aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2018-10-08 15:33:13 +0100
committerAleksey Kladov <[email protected]>2018-10-08 15:36:38 +0100
commita05e09e9c514878148ddf26aa76d6b9183583d0f (patch)
treef9d1d3baaa8aead60d356f0e60ca8f5e0fdcd308
parentb642e6c6451b21d9b3fc719472a1802ea70a83d8 (diff)
Attach comments smartly
-rw-r--r--crates/ra_editor/src/extend_selection.rs16
-rw-r--r--crates/ra_syntax/src/parser_impl/event.rs93
-rw-r--r--crates/ra_syntax/tests/data/parser/err/0025_nope.txt6
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0033_label_break.txt6
4 files changed, 97 insertions, 24 deletions
diff --git a/crates/ra_editor/src/extend_selection.rs b/crates/ra_editor/src/extend_selection.rs
index 6977900e6..e12346cb6 100644
--- a/crates/ra_editor/src/extend_selection.rs
+++ b/crates/ra_editor/src/extend_selection.rs
@@ -154,6 +154,22 @@ impl S {
154 } 154 }
155 155
156 #[test] 156 #[test]
157 fn test_extend_selection_doc_comments() {
158 do_check(
159 r#"
160struct A;
161
162/// bla
163/// bla
164struct B {
165 <|>
166}
167 "#,
168 &["\n \n", "{\n \n}", "/// bla\n/// bla\nstruct B {\n \n}"]
169 )
170 }
171
172 #[test]
157 fn test_extend_selection_comments() { 173 fn test_extend_selection_comments() {
158 do_check( 174 do_check(
159 r#" 175 r#"
diff --git a/crates/ra_syntax/src/parser_impl/event.rs b/crates/ra_syntax/src/parser_impl/event.rs
index 4e6e25cfb..95e5ce4cc 100644
--- a/crates/ra_syntax/src/parser_impl/event.rs
+++ b/crates/ra_syntax/src/parser_impl/event.rs
@@ -12,7 +12,7 @@ use {
12 TextUnit, TextRange, SmolStr, 12 TextUnit, TextRange, SmolStr,
13 lexer::Token, 13 lexer::Token,
14 parser_impl::Sink, 14 parser_impl::Sink,
15 SyntaxKind::{self, TOMBSTONE}, 15 SyntaxKind::{self, *},
16}; 16};
17 17
18 18
@@ -104,7 +104,6 @@ impl<'a, S: Sink> EventProcessor<'a, S> {
104 fn tombstone() -> Event { 104 fn tombstone() -> Event {
105 Event::Start { kind: TOMBSTONE, forward_parent: None } 105 Event::Start { kind: TOMBSTONE, forward_parent: None }
106 } 106 }
107 let mut depth = 0;
108 let mut forward_parents = Vec::new(); 107 let mut forward_parents = Vec::new();
109 108
110 for i in 0..self.events.len() { 109 for i in 0..self.events.len() {
@@ -131,25 +130,14 @@ impl<'a, S: Sink> EventProcessor<'a, S> {
131 }; 130 };
132 } 131 }
133 for kind in forward_parents.drain(..).rev() { 132 for kind in forward_parents.drain(..).rev() {
134 if depth > 0 { 133 self.start(kind);
135 self.eat_ws();
136 }
137 depth += 1;
138 self.sink.start_internal(kind);
139 } 134 }
140 } 135 }
141 Event::Finish => { 136 Event::Finish => {
142 depth -= 1; 137 let last = i == self.events.len() - 1;
143 if depth == 0 { 138 self.finish(last);
144 self.eat_ws(); 139 },
145 } 140 Event::Token { kind, n_raw_tokens } => {
146
147 self.sink.finish_internal();
148 }
149 Event::Token {
150 kind,
151 n_raw_tokens,
152 } => {
153 self.eat_ws(); 141 self.eat_ws();
154 let n_raw_tokens = n_raw_tokens as usize; 142 let n_raw_tokens = n_raw_tokens as usize;
155 let len = self.tokens[self.token_pos..self.token_pos + n_raw_tokens] 143 let len = self.tokens[self.token_pos..self.token_pos + n_raw_tokens]
@@ -164,6 +152,43 @@ impl<'a, S: Sink> EventProcessor<'a, S> {
164 self.sink 152 self.sink
165 } 153 }
166 154
155 fn start(&mut self, kind: SyntaxKind) {
156 if kind == ROOT {
157 self.sink.start_internal(kind);
158 return;
159 }
160 let n_trivias = self.tokens[self.token_pos..]
161 .iter()
162 .take_while(|it| it.kind.is_trivia())
163 .count();
164 let leading_trivias = &self.tokens[self.token_pos..self.token_pos + n_trivias];
165 let mut trivia_end = self.text_pos + leading_trivias
166 .iter()
167 .map(|it| it.len)
168 .sum::<TextUnit>();
169
170 let n_attached_trivias = {
171 let leading_trivias = leading_trivias.iter().rev()
172 .map(|it| {
173 let next_end = trivia_end - it.len;
174 let range = TextRange::from_to(next_end, trivia_end);
175 trivia_end = next_end;
176 (it.kind, &self.text[range])
177 });
178 n_attached_trivias(kind, leading_trivias)
179 };
180 self.eat_n_trivias(n_trivias - n_attached_trivias);
181 self.sink.start_internal(kind);
182 self.eat_n_trivias(n_attached_trivias);
183 }
184
185 fn finish(&mut self, last: bool) {
186 if last {
187 self.eat_ws()
188 }
189 self.sink.finish_internal();
190 }
191
167 fn eat_ws(&mut self) { 192 fn eat_ws(&mut self) {
168 while let Some(&token) = self.tokens.get(self.token_pos) { 193 while let Some(&token) = self.tokens.get(self.token_pos) {
169 if !token.kind.is_trivia() { 194 if !token.kind.is_trivia() {
@@ -173,6 +198,14 @@ impl<'a, S: Sink> EventProcessor<'a, S> {
173 } 198 }
174 } 199 }
175 200
201 fn eat_n_trivias(&mut self, n: usize) {
202 for _ in 0..n {
203 let token = self.tokens[self.token_pos];
204 assert!(token.kind.is_trivia());
205 self.leaf(token.kind, token.len, 1);
206 }
207 }
208
176 fn leaf(&mut self, kind: SyntaxKind, len: TextUnit, n_tokens: usize) { 209 fn leaf(&mut self, kind: SyntaxKind, len: TextUnit, n_tokens: usize) {
177 let range = TextRange::offset_len(self.text_pos, len); 210 let range = TextRange::offset_len(self.text_pos, len);
178 let text: SmolStr = self.text[range].into(); 211 let text: SmolStr = self.text[range].into();
@@ -181,3 +214,27 @@ impl<'a, S: Sink> EventProcessor<'a, S> {
181 self.sink.leaf(kind, text); 214 self.sink.leaf(kind, text);
182 } 215 }
183} 216}
217
218fn n_attached_trivias<'a>(kind: SyntaxKind, trivias: impl Iterator<Item=(SyntaxKind, &'a str)>) -> usize {
219 match kind {
220 STRUCT_DEF | ENUM_DEF | FN_DEF | TRAIT_DEF | MODULE => {
221 let mut res = 0;
222 for (i, (kind, text)) in trivias.enumerate() {
223 match kind {
224 WHITESPACE => {
225 if text.contains("\n\n") {
226 break;
227 }
228 }
229 COMMENT => {
230 res = i + 1;
231 }
232 _ => (),
233 }
234 }
235 res
236 }
237 _ => 0,
238 }
239
240}
diff --git a/crates/ra_syntax/tests/data/parser/err/0025_nope.txt b/crates/ra_syntax/tests/data/parser/err/0025_nope.txt
index c30b8585f..6879c8d0a 100644
--- a/crates/ra_syntax/tests/data/parser/err/0025_nope.txt
+++ b/crates/ra_syntax/tests/data/parser/err/0025_nope.txt
@@ -137,9 +137,9 @@ ROOT@[0; 575)
137 BLOCK@[306; 459) 137 BLOCK@[306; 459)
138 L_CURLY@[306; 307) 138 L_CURLY@[306; 307)
139 WHITESPACE@[307; 316) 139 WHITESPACE@[307; 316)
140 COMMENT@[316; 329) 140 ENUM_DEF@[316; 453)
141 WHITESPACE@[329; 338) 141 COMMENT@[316; 329)
142 ENUM_DEF@[338; 453) 142 WHITESPACE@[329; 338)
143 ENUM_KW@[338; 342) 143 ENUM_KW@[338; 342)
144 WHITESPACE@[342; 343) 144 WHITESPACE@[342; 343)
145 NAME@[343; 348) 145 NAME@[343; 348)
diff --git a/crates/ra_syntax/tests/data/parser/ok/0033_label_break.txt b/crates/ra_syntax/tests/data/parser/ok/0033_label_break.txt
index 6abb9234c..201eca644 100644
--- a/crates/ra_syntax/tests/data/parser/ok/0033_label_break.txt
+++ b/crates/ra_syntax/tests/data/parser/ok/0033_label_break.txt
@@ -1,7 +1,7 @@
1ROOT@[0; 506) 1ROOT@[0; 506)
2 COMMENT@[0; 33) 2 FN_DEF@[0; 505)
3 WHITESPACE@[33; 34) 3 COMMENT@[0; 33)
4 FN_DEF@[34; 505) 4 WHITESPACE@[33; 34)
5 FN_KW@[34; 36) 5 FN_KW@[34; 36)
6 WHITESPACE@[36; 37) 6 WHITESPACE@[36; 37)
7 NAME@[37; 41) 7 NAME@[37; 41)