aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_syntax/src/reparsing.rs
diff options
context:
space:
mode:
authorJeremy A. Kolb <[email protected]>2018-10-15 22:44:23 +0100
committerJeremy A. Kolb <[email protected]>2018-10-16 14:41:10 +0100
commit61f3a438d3a729a6be941bca1ff4c6a97a33f221 (patch)
tree6551967cc8c6e921b66071453ad7888a9121d326 /crates/ra_syntax/src/reparsing.rs
parent39cb6c6d3f78b193f5873c3492e530bbd24d5dd2 (diff)
Cargo Format
Run `cargo fmt` and ignore generated files
Diffstat (limited to 'crates/ra_syntax/src/reparsing.rs')
-rw-r--r--crates/ra_syntax/src/reparsing.rs247
1 files changed, 152 insertions, 95 deletions
diff --git a/crates/ra_syntax/src/reparsing.rs b/crates/ra_syntax/src/reparsing.rs
index 16272fe88..a0014e016 100644
--- a/crates/ra_syntax/src/reparsing.rs
+++ b/crates/ra_syntax/src/reparsing.rs
@@ -1,14 +1,11 @@
1use crate::algo; 1use crate::algo;
2use crate::grammar; 2use crate::grammar;
3use crate::lexer::{tokenize, Token}; 3use crate::lexer::{tokenize, Token};
4use crate::yellow::{self, GreenNode, SyntaxNodeRef, SyntaxError};
5use crate::parser_impl;
6use crate::parser_api::Parser; 4use crate::parser_api::Parser;
7use crate::{ 5use crate::parser_impl;
8 TextUnit, TextRange,
9 SyntaxKind::*,
10};
11use crate::text_utils::replace_range; 6use crate::text_utils::replace_range;
7use crate::yellow::{self, GreenNode, SyntaxError, SyntaxNodeRef};
8use crate::{SyntaxKind::*, TextRange, TextUnit};
12 9
13#[derive(Debug, Clone)] 10#[derive(Debug, Clone)]
14pub struct AtomEdit { 11pub struct AtomEdit {
@@ -18,7 +15,10 @@ pub struct AtomEdit {
18 15
19impl AtomEdit { 16impl AtomEdit {
20 pub fn replace(range: TextRange, replace_with: String) -> AtomEdit { 17 pub fn replace(range: TextRange, replace_with: String) -> AtomEdit {
21 AtomEdit { delete: range, insert: replace_with } 18 AtomEdit {
19 delete: range,
20 insert: replace_with,
21 }
22 } 22 }
23 23
24 pub fn delete(range: TextRange) -> AtomEdit { 24 pub fn delete(range: TextRange) -> AtomEdit {
@@ -48,12 +48,7 @@ fn reparse_leaf<'node>(
48) -> Option<(SyntaxNodeRef<'node>, GreenNode, Vec<SyntaxError>)> { 48) -> Option<(SyntaxNodeRef<'node>, GreenNode, Vec<SyntaxError>)> {
49 let node = algo::find_covering_node(node, edit.delete); 49 let node = algo::find_covering_node(node, edit.delete);
50 match node.kind() { 50 match node.kind() {
51 | WHITESPACE 51 WHITESPACE | COMMENT | DOC_COMMENT | IDENT | STRING | RAW_STRING => {
52 | COMMENT
53 | DOC_COMMENT
54 | IDENT
55 | STRING
56 | RAW_STRING => {
57 let text = get_text_after_edit(node, &edit); 52 let text = get_text_after_edit(node, &edit);
58 let tokens = tokenize(&text); 53 let tokens = tokenize(&text);
59 let token = match tokens[..] { 54 let token = match tokens[..] {
@@ -84,10 +79,7 @@ fn reparse_block<'node>(
84 return None; 79 return None;
85 } 80 }
86 let (green, new_errors) = 81 let (green, new_errors) =
87 parser_impl::parse_with( 82 parser_impl::parse_with(yellow::GreenBuilder::new(), &text, &tokens, reparser);
88 yellow::GreenBuilder::new(),
89 &text, &tokens, reparser,
90 );
91 Some((node, green, new_errors)) 83 Some((node, green, new_errors))
92} 84}
93 85
@@ -101,9 +93,7 @@ fn get_text_after_edit(node: SyntaxNodeRef, edit: &AtomEdit) -> String {
101 93
102fn is_contextual_kw(text: &str) -> bool { 94fn is_contextual_kw(text: &str) -> bool {
103 match text { 95 match text {
104 | "auto" 96 "auto" | "default" | "union" => true,
105 | "default"
106 | "union" => true,
107 _ => false, 97 _ => false,
108 } 98 }
109} 99}
@@ -113,7 +103,8 @@ fn find_reparsable_node<'node>(
113 range: TextRange, 103 range: TextRange,
114) -> Option<(SyntaxNodeRef<'node>, fn(&mut Parser))> { 104) -> Option<(SyntaxNodeRef<'node>, fn(&mut Parser))> {
115 let node = algo::find_covering_node(node, range); 105 let node = algo::find_covering_node(node, range);
116 return node.ancestors() 106 return node
107 .ancestors()
117 .filter_map(|node| reparser(node).map(|r| (node, r))) 108 .filter_map(|node| reparser(node).map(|r| (node, r)))
118 .next(); 109 .next();
119 110
@@ -145,17 +136,20 @@ fn find_reparsable_node<'node>(
145fn is_balanced(tokens: &[Token]) -> bool { 136fn is_balanced(tokens: &[Token]) -> bool {
146 if tokens.len() == 0 137 if tokens.len() == 0
147 || tokens.first().unwrap().kind != L_CURLY 138 || tokens.first().unwrap().kind != L_CURLY
148 || tokens.last().unwrap().kind != R_CURLY { 139 || tokens.last().unwrap().kind != R_CURLY
140 {
149 return false; 141 return false;
150 } 142 }
151 let mut balance = 0usize; 143 let mut balance = 0usize;
152 for t in tokens.iter() { 144 for t in tokens.iter() {
153 match t.kind { 145 match t.kind {
154 L_CURLY => balance += 1, 146 L_CURLY => balance += 1,
155 R_CURLY => balance = match balance.checked_sub(1) { 147 R_CURLY => {
156 Some(b) => b, 148 balance = match balance.checked_sub(1) {
157 None => return false, 149 Some(b) => b,
158 }, 150 None => return false,
151 }
152 }
159 _ => (), 153 _ => (),
160 } 154 }
161 } 155 }
@@ -191,24 +185,14 @@ fn merge_errors(
191#[cfg(test)] 185#[cfg(test)]
192mod tests { 186mod tests {
193 use super::{ 187 use super::{
194 super::{ 188 super::{test_utils::extract_range, text_utils::replace_range, utils::dump_tree, File},
195 File, 189 reparse_block, reparse_leaf, AtomEdit, GreenNode, SyntaxError, SyntaxNodeRef,
196 test_utils::extract_range,
197 text_utils::replace_range,
198 utils::dump_tree,
199 },
200 reparse_leaf, reparse_block, AtomEdit, GreenNode, SyntaxError, SyntaxNodeRef,
201 }; 190 };
202 191
203 fn do_check<F>( 192 fn do_check<F>(before: &str, replace_with: &str, reparser: F)
204 before: &str, 193 where
205 replace_with: &str, 194 for<'a> F: Fn(SyntaxNodeRef<'a>, &AtomEdit)
206 reparser: F, 195 -> Option<(SyntaxNodeRef<'a>, GreenNode, Vec<SyntaxError>)>,
207 ) where
208 for<'a> F: Fn(
209 SyntaxNodeRef<'a>,
210 &AtomEdit,
211 ) -> Option<(SyntaxNodeRef<'a>, GreenNode, Vec<SyntaxError>)>
212 { 196 {
213 let (range, before) = extract_range(before); 197 let (range, before) = extract_range(before);
214 let after = replace_range(before.clone(), range, replace_with); 198 let after = replace_range(before.clone(), range, replace_with);
@@ -216,7 +200,10 @@ mod tests {
216 let fully_reparsed = File::parse(&after); 200 let fully_reparsed = File::parse(&after);
217 let incrementally_reparsed = { 201 let incrementally_reparsed = {
218 let f = File::parse(&before); 202 let f = File::parse(&before);
219 let edit = AtomEdit { delete: range, insert: replace_with.to_string() }; 203 let edit = AtomEdit {
204 delete: range,
205 insert: replace_with.to_string(),
206 };
220 let (node, green, new_errors) = 207 let (node, green, new_errors) =
221 reparser(f.syntax(), &edit).expect("cannot incrementally reparse"); 208 reparser(f.syntax(), &edit).expect("cannot incrementally reparse");
222 let green_root = node.replace_with(green); 209 let green_root = node.replace_with(green);
@@ -232,113 +219,183 @@ mod tests {
232 219
233 #[test] 220 #[test]
234 fn reparse_block_tests() { 221 fn reparse_block_tests() {
235 let do_check = |before, replace_to| 222 let do_check = |before, replace_to| do_check(before, replace_to, reparse_block);
236 do_check(before, replace_to, reparse_block);
237 223
238 do_check(r" 224 do_check(
225 r"
239fn foo() { 226fn foo() {
240 let x = foo + <|>bar<|> 227 let x = foo + <|>bar<|>
241} 228}
242", "baz"); 229",
243 do_check(r" 230 "baz",
231 );
232 do_check(
233 r"
244fn foo() { 234fn foo() {
245 let x = foo<|> + bar<|> 235 let x = foo<|> + bar<|>
246} 236}
247", "baz"); 237",
248 do_check(r" 238 "baz",
239 );
240 do_check(
241 r"
249struct Foo { 242struct Foo {
250 f: foo<|><|> 243 f: foo<|><|>
251} 244}
252", ",\n g: (),"); 245",
253 do_check(r" 246 ",\n g: (),",
247 );
248 do_check(
249 r"
254fn foo { 250fn foo {
255 let; 251 let;
256 1 + 1; 252 1 + 1;
257 <|>92<|>; 253 <|>92<|>;
258} 254}
259", "62"); 255",
260 do_check(r" 256 "62",
257 );
258 do_check(
259 r"
261mod foo { 260mod foo {
262 fn <|><|> 261 fn <|><|>
263} 262}
264", "bar"); 263",
265 do_check(r" 264 "bar",
265 );
266 do_check(
267 r"
266trait Foo { 268trait Foo {
267 type <|>Foo<|>; 269 type <|>Foo<|>;
268} 270}
269", "Output"); 271",
270 do_check(r" 272 "Output",
273 );
274 do_check(
275 r"
271impl IntoIterator<Item=i32> for Foo { 276impl IntoIterator<Item=i32> for Foo {
272 f<|><|> 277 f<|><|>
273} 278}
274", "n next("); 279",
275 do_check(r" 280 "n next(",
281 );
282 do_check(
283 r"
276use a::b::{foo,<|>,bar<|>}; 284use a::b::{foo,<|>,bar<|>};
277 ", "baz"); 285 ",
278 do_check(r" 286 "baz",
287 );
288 do_check(
289 r"
279pub enum A { 290pub enum A {
280 Foo<|><|> 291 Foo<|><|>
281} 292}
282", "\nBar;\n"); 293",
283 do_check(r" 294 "\nBar;\n",
295 );
296 do_check(
297 r"
284foo!{a, b<|><|> d} 298foo!{a, b<|><|> d}
285", ", c[3]"); 299",
286 do_check(r" 300 ", c[3]",
301 );
302 do_check(
303 r"
287fn foo() { 304fn foo() {
288 vec![<|><|>] 305 vec![<|><|>]
289} 306}
290", "123"); 307",
291 do_check(r" 308 "123",
309 );
310 do_check(
311 r"
292extern { 312extern {
293 fn<|>;<|> 313 fn<|>;<|>
294} 314}
295", " exit(code: c_int)"); 315",
316 " exit(code: c_int)",
317 );
296 } 318 }
297 319
298 #[test] 320 #[test]
299 fn reparse_leaf_tests() { 321 fn reparse_leaf_tests() {
300 let do_check = |before, replace_to| 322 let do_check = |before, replace_to| do_check(before, replace_to, reparse_leaf);
301 do_check(before, replace_to, reparse_leaf);
302 323
303 do_check(r"<|><|> 324 do_check(
325 r"<|><|>
304fn foo() -> i32 { 1 } 326fn foo() -> i32 { 1 }
305", "\n\n\n \n"); 327",
306 do_check(r" 328 "\n\n\n \n",
329 );
330 do_check(
331 r"
307fn foo() -> <|><|> {} 332fn foo() -> <|><|> {}
308", " \n"); 333",
309 do_check(r" 334 " \n",
335 );
336 do_check(
337 r"
310fn <|>foo<|>() -> i32 { 1 } 338fn <|>foo<|>() -> i32 { 1 }
311", "bar"); 339",
312 do_check(r" 340 "bar",
341 );
342 do_check(
343 r"
313fn foo<|><|>foo() { } 344fn foo<|><|>foo() { }
314", "bar"); 345",
315 do_check(r" 346 "bar",
347 );
348 do_check(
349 r"
316fn foo /* <|><|> */ () {} 350fn foo /* <|><|> */ () {}
317", "some comment"); 351",
318 do_check(r" 352 "some comment",
353 );
354 do_check(
355 r"
319fn baz <|><|> () {} 356fn baz <|><|> () {}
320", " \t\t\n\n"); 357",
321 do_check(r" 358 " \t\t\n\n",
359 );
360 do_check(
361 r"
322fn baz <|><|> () {} 362fn baz <|><|> () {}
323", " \t\t\n\n"); 363",
324 do_check(r" 364 " \t\t\n\n",
365 );
366 do_check(
367 r"
325/// foo <|><|>omment 368/// foo <|><|>omment
326mod { } 369mod { }
327", "c"); 370",
328 do_check(r#" 371 "c",
372 );
373 do_check(
374 r#"
329fn -> &str { "Hello<|><|>" } 375fn -> &str { "Hello<|><|>" }
330"#, ", world"); 376"#,
331 do_check(r#" 377 ", world",
378 );
379 do_check(
380 r#"
332fn -> &str { // "Hello<|><|>" 381fn -> &str { // "Hello<|><|>"
333"#, ", world"); 382"#,
334 do_check(r##" 383 ", world",
384 );
385 do_check(
386 r##"
335fn -> &str { r#"Hello<|><|>"# 387fn -> &str { r#"Hello<|><|>"#
336"##, ", world"); 388"##,
337 do_check(r" 389 ", world",
390 );
391 do_check(
392 r"
338#[derive(<|>Copy<|>)] 393#[derive(<|>Copy<|>)]
339enum Foo { 394enum Foo {
340 395
341} 396}
342", "Clone"); 397",
398 "Clone",
399 );
343 } 400 }
344} 401}