diff options
-rw-r--r-- | crates/libanalysis/src/lib.rs | 6 | ||||
-rw-r--r-- | crates/libeditor/src/code_actions.rs | 18 | ||||
-rw-r--r-- | crates/libeditor/src/completion.rs | 31 | ||||
-rw-r--r-- | crates/libeditor/src/lib.rs | 21 | ||||
-rw-r--r-- | crates/libeditor/tests/test.rs | 22 | ||||
-rw-r--r-- | crates/libsyntax2/src/grammar/items/mod.rs | 7 | ||||
-rw-r--r-- | crates/libsyntax2/src/lib.rs | 4 | ||||
-rw-r--r-- | crates/libsyntax2/src/parser_api.rs | 4 | ||||
-rw-r--r-- | crates/libsyntax2/tests/data/parser/err/0007_stray_curly_in_file.txt | 6 | ||||
-rw-r--r-- | crates/libsyntax2/tests/data/parser/err/0015_curly_in_params.txt | 2 | ||||
-rw-r--r-- | crates/libsyntax2/tests/data/parser/err/0017_incomplete_binexpr.rs | 4 | ||||
-rw-r--r-- | crates/libsyntax2/tests/data/parser/err/0017_incomplete_binexpr.txt | 47 | ||||
-rw-r--r-- | crates/libsyntax2/tests/test/main.rs | 1 |
13 files changed, 144 insertions, 29 deletions
diff --git a/crates/libanalysis/src/lib.rs b/crates/libanalysis/src/lib.rs index c84ab6077..a3f721cc8 100644 --- a/crates/libanalysis/src/lib.rs +++ b/crates/libanalysis/src/lib.rs | |||
@@ -32,7 +32,7 @@ use libsyntax2::{ | |||
32 | ast::{self, AstNode, NameOwner}, | 32 | ast::{self, AstNode, NameOwner}, |
33 | SyntaxKind::*, | 33 | SyntaxKind::*, |
34 | }; | 34 | }; |
35 | use libeditor::{LineIndex, FileSymbol, find_node}; | 35 | use libeditor::{LineIndex, FileSymbol, find_node_at_offset}; |
36 | 36 | ||
37 | use self::{ | 37 | use self::{ |
38 | symbol_index::FileSymbols, | 38 | symbol_index::FileSymbols, |
@@ -183,10 +183,10 @@ impl World { | |||
183 | ) -> Result<Vec<(FileId, FileSymbol)>> { | 183 | ) -> Result<Vec<(FileId, FileSymbol)>> { |
184 | let file = self.file_syntax(id)?; | 184 | let file = self.file_syntax(id)?; |
185 | let syntax = file.syntax(); | 185 | let syntax = file.syntax(); |
186 | if let Some(name_ref) = find_node::<ast::NameRef>(syntax, offset) { | 186 | if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(syntax, offset) { |
187 | return Ok(self.index_resolve(name_ref)); | 187 | return Ok(self.index_resolve(name_ref)); |
188 | } | 188 | } |
189 | if let Some(name) = find_node::<ast::Name>(syntax, offset) { | 189 | if let Some(name) = find_node_at_offset::<ast::Name>(syntax, offset) { |
190 | if let Some(module) = name.syntax().parent().and_then(ast::Module::cast) { | 190 | if let Some(module) = name.syntax().parent().and_then(ast::Module::cast) { |
191 | if module.has_semi() { | 191 | if module.has_semi() { |
192 | let file_ids = self.resolve_module(id, module); | 192 | let file_ids = self.resolve_module(id, module); |
diff --git a/crates/libeditor/src/code_actions.rs b/crates/libeditor/src/code_actions.rs index b3305be2a..f53a8f9c6 100644 --- a/crates/libeditor/src/code_actions.rs +++ b/crates/libeditor/src/code_actions.rs | |||
@@ -3,7 +3,7 @@ use std::{ | |||
3 | }; | 3 | }; |
4 | 4 | ||
5 | use libsyntax2::{ | 5 | use libsyntax2::{ |
6 | File, | 6 | File, TextUnit, |
7 | ast::{self, AstNode, AttrsOwner, TypeParamsOwner, NameOwner}, | 7 | ast::{self, AstNode, AttrsOwner, TypeParamsOwner, NameOwner}, |
8 | SyntaxKind::COMMA, | 8 | SyntaxKind::COMMA, |
9 | SyntaxNodeRef, | 9 | SyntaxNodeRef, |
@@ -13,7 +13,7 @@ use libsyntax2::{ | |||
13 | }, | 13 | }, |
14 | }; | 14 | }; |
15 | 15 | ||
16 | use {TextUnit, EditBuilder, Edit}; | 16 | use {EditBuilder, Edit, find_node_at_offset}; |
17 | 17 | ||
18 | #[derive(Debug)] | 18 | #[derive(Debug)] |
19 | pub struct ActionResult { | 19 | pub struct ActionResult { |
@@ -39,7 +39,7 @@ pub fn flip_comma<'a>(file: &'a File, offset: TextUnit) -> Option<impl FnOnce() | |||
39 | } | 39 | } |
40 | 40 | ||
41 | pub fn add_derive<'a>(file: &'a File, offset: TextUnit) -> Option<impl FnOnce() -> ActionResult + 'a> { | 41 | pub fn add_derive<'a>(file: &'a File, offset: TextUnit) -> Option<impl FnOnce() -> ActionResult + 'a> { |
42 | let nominal = find_node::<ast::NominalDef>(file.syntax(), offset)?; | 42 | let nominal = find_node_at_offset::<ast::NominalDef>(file.syntax(), offset)?; |
43 | Some(move || { | 43 | Some(move || { |
44 | let derive_attr = nominal | 44 | let derive_attr = nominal |
45 | .attrs() | 45 | .attrs() |
@@ -66,7 +66,7 @@ pub fn add_derive<'a>(file: &'a File, offset: TextUnit) -> Option<impl FnOnce() | |||
66 | } | 66 | } |
67 | 67 | ||
68 | pub fn add_impl<'a>(file: &'a File, offset: TextUnit) -> Option<impl FnOnce() -> ActionResult + 'a> { | 68 | pub fn add_impl<'a>(file: &'a File, offset: TextUnit) -> Option<impl FnOnce() -> ActionResult + 'a> { |
69 | let nominal = find_node::<ast::NominalDef>(file.syntax(), offset)?; | 69 | let nominal = find_node_at_offset::<ast::NominalDef>(file.syntax(), offset)?; |
70 | let name = nominal.name()?; | 70 | let name = nominal.name()?; |
71 | 71 | ||
72 | Some(move || { | 72 | Some(move || { |
@@ -105,16 +105,6 @@ fn non_trivia_sibling(node: SyntaxNodeRef, direction: Direction) -> Option<Synta | |||
105 | .find(|node| !node.kind().is_trivia()) | 105 | .find(|node| !node.kind().is_trivia()) |
106 | } | 106 | } |
107 | 107 | ||
108 | pub fn find_node<'a, N: AstNode<'a>>(syntax: SyntaxNodeRef<'a>, offset: TextUnit) -> Option<N> { | ||
109 | let leaves = find_leaf_at_offset(syntax, offset); | ||
110 | let leaf = leaves.clone() | ||
111 | .find(|leaf| !leaf.kind().is_trivia()) | ||
112 | .or_else(|| leaves.right_biased())?; | ||
113 | ancestors(leaf) | ||
114 | .filter_map(N::cast) | ||
115 | .next() | ||
116 | } | ||
117 | |||
118 | fn comma_list(buf: &mut String, bra: &str, ket: &str, items: impl Iterator<Item=impl fmt::Display>) { | 108 | fn comma_list(buf: &mut String, bra: &str, ket: &str, items: impl Iterator<Item=impl fmt::Display>) { |
119 | buf.push_str(bra); | 109 | buf.push_str(bra); |
120 | let mut first = true; | 110 | let mut first = true; |
diff --git a/crates/libeditor/src/completion.rs b/crates/libeditor/src/completion.rs new file mode 100644 index 000000000..cf61ec784 --- /dev/null +++ b/crates/libeditor/src/completion.rs | |||
@@ -0,0 +1,31 @@ | |||
1 | use libsyntax2::{ | ||
2 | File, TextUnit, | ||
3 | ast, | ||
4 | algo::find_leaf_at_offset, | ||
5 | }; | ||
6 | |||
7 | use { | ||
8 | AtomEdit, find_node_at_offset, | ||
9 | }; | ||
10 | |||
11 | #[derive(Debug)] | ||
12 | pub struct CompletionItem { | ||
13 | name: String, | ||
14 | } | ||
15 | |||
16 | pub fn scope_completion(file: &File, offset: TextUnit) -> Option<Vec<CompletionItem>> { | ||
17 | // Insert a fake ident to get a valid parse tree | ||
18 | let file = { | ||
19 | let edit = AtomEdit::insert(offset, "intellijRulezz".to_string()); | ||
20 | // Don't bother with completion if incremental reparse fails | ||
21 | file.incremental_reparse(&edit)? | ||
22 | }; | ||
23 | let name_ref = find_node_at_offset::<ast::NameRef>(file.syntax(), offset)?; | ||
24 | Some(complete(name_ref)) | ||
25 | } | ||
26 | |||
27 | fn complete(name_ref: ast::NameRef) -> Vec<CompletionItem> { | ||
28 | vec![CompletionItem { | ||
29 | name: "foo".to_string() | ||
30 | }] | ||
31 | } | ||
diff --git a/crates/libeditor/src/lib.rs b/crates/libeditor/src/lib.rs index 55302265f..60489f7e3 100644 --- a/crates/libeditor/src/lib.rs +++ b/crates/libeditor/src/lib.rs | |||
@@ -8,11 +8,12 @@ mod line_index; | |||
8 | mod edit; | 8 | mod edit; |
9 | mod code_actions; | 9 | mod code_actions; |
10 | mod typing; | 10 | mod typing; |
11 | mod completion; | ||
11 | 12 | ||
12 | use libsyntax2::{ | 13 | use libsyntax2::{ |
13 | File, TextUnit, TextRange, | 14 | File, TextUnit, TextRange, SyntaxNodeRef, |
14 | ast::{AstNode, NameOwner}, | 15 | ast::{AstNode, NameOwner}, |
15 | algo::{walk, find_leaf_at_offset}, | 16 | algo::{walk, find_leaf_at_offset, ancestors}, |
16 | SyntaxKind::{self, *}, | 17 | SyntaxKind::{self, *}, |
17 | }; | 18 | }; |
18 | pub use libsyntax2::AtomEdit; | 19 | pub use libsyntax2::AtomEdit; |
@@ -22,10 +23,11 @@ pub use self::{ | |||
22 | symbols::{StructureNode, file_structure, FileSymbol, file_symbols}, | 23 | symbols::{StructureNode, file_structure, FileSymbol, file_symbols}, |
23 | edit::{EditBuilder, Edit}, | 24 | edit::{EditBuilder, Edit}, |
24 | code_actions::{ | 25 | code_actions::{ |
25 | ActionResult, find_node, | 26 | ActionResult, |
26 | flip_comma, add_derive, add_impl, | 27 | flip_comma, add_derive, add_impl, |
27 | }, | 28 | }, |
28 | typing::join_lines, | 29 | typing::join_lines, |
30 | completion::scope_completion, | ||
29 | }; | 31 | }; |
30 | 32 | ||
31 | #[derive(Debug)] | 33 | #[derive(Debug)] |
@@ -138,3 +140,16 @@ pub fn runnables(file: &File) -> Vec<Runnable> { | |||
138 | }) | 140 | }) |
139 | .collect() | 141 | .collect() |
140 | } | 142 | } |
143 | |||
144 | pub fn find_node_at_offset<'a, N: AstNode<'a>>( | ||
145 | syntax: SyntaxNodeRef<'a>, | ||
146 | offset: TextUnit, | ||
147 | ) -> Option<N> { | ||
148 | let leaves = find_leaf_at_offset(syntax, offset); | ||
149 | let leaf = leaves.clone() | ||
150 | .find(|leaf| !leaf.kind().is_trivia()) | ||
151 | .or_else(|| leaves.right_biased())?; | ||
152 | ancestors(leaf) | ||
153 | .filter_map(N::cast) | ||
154 | .next() | ||
155 | } | ||
diff --git a/crates/libeditor/tests/test.rs b/crates/libeditor/tests/test.rs index c8882c94d..9d59f4cdf 100644 --- a/crates/libeditor/tests/test.rs +++ b/crates/libeditor/tests/test.rs | |||
@@ -9,7 +9,7 @@ use libeditor::{ | |||
9 | ActionResult, | 9 | ActionResult, |
10 | highlight, runnables, extend_selection, file_structure, | 10 | highlight, runnables, extend_selection, file_structure, |
11 | flip_comma, add_derive, add_impl, matching_brace, | 11 | flip_comma, add_derive, add_impl, matching_brace, |
12 | join_lines, | 12 | join_lines, scope_completion, |
13 | }; | 13 | }; |
14 | 14 | ||
15 | #[test] | 15 | #[test] |
@@ -244,6 +244,26 @@ struct Foo { f: u32 } | |||
244 | "); | 244 | "); |
245 | } | 245 | } |
246 | 246 | ||
247 | // #[test] | ||
248 | // fn test_completion() { | ||
249 | // fn do_check(code: &str, expected_completions: &str) { | ||
250 | // let (off, code) = extract_offset(&code); | ||
251 | // let file = file(&code); | ||
252 | // let completions = scope_completion(&file, off).unwrap(); | ||
253 | // assert_eq_dbg(expected_completions, &completions); | ||
254 | // } | ||
255 | |||
256 | // do_check(r" | ||
257 | // fn foo(foo: i32) { | ||
258 | // let bar = 92; | ||
259 | // 1 + <|> | ||
260 | // } | ||
261 | // ", r#" | ||
262 | // CompletionItem { name: "bar" }, | ||
263 | // CompletionItem { name: "foo" }, | ||
264 | // "#); | ||
265 | // } | ||
266 | |||
247 | fn file(text: &str) -> File { | 267 | fn file(text: &str) -> File { |
248 | File::parse(text) | 268 | File::parse(text) |
249 | } | 269 | } |
diff --git a/crates/libsyntax2/src/grammar/items/mod.rs b/crates/libsyntax2/src/grammar/items/mod.rs index 32d0778c4..a285892df 100644 --- a/crates/libsyntax2/src/grammar/items/mod.rs +++ b/crates/libsyntax2/src/grammar/items/mod.rs | |||
@@ -43,7 +43,12 @@ pub(super) fn item_or_macro(p: &mut Parser, stop_on_r_curly: bool, flavor: ItemF | |||
43 | m.abandon(p); | 43 | m.abandon(p); |
44 | if p.at(L_CURLY) { | 44 | if p.at(L_CURLY) { |
45 | error_block(p, "expected an item"); | 45 | error_block(p, "expected an item"); |
46 | } else if !p.at(EOF) && !(stop_on_r_curly && p.at(R_CURLY)) { | 46 | } else if p.at(R_CURLY) && !stop_on_r_curly { |
47 | let e = p.start(); | ||
48 | p.error("unmatched `}`"); | ||
49 | p.bump(); | ||
50 | e.complete(p, ERROR); | ||
51 | } else if !p.at(EOF) && !p.at(R_CURLY) { | ||
47 | p.err_and_bump("expected an item"); | 52 | p.err_and_bump("expected an item"); |
48 | } else { | 53 | } else { |
49 | p.error("expected an item"); | 54 | p.error("expected an item"); |
diff --git a/crates/libsyntax2/src/lib.rs b/crates/libsyntax2/src/lib.rs index 9ba9970c9..93057dd6a 100644 --- a/crates/libsyntax2/src/lib.rs +++ b/crates/libsyntax2/src/lib.rs | |||
@@ -127,12 +127,12 @@ fn validate_block_structure(root: SyntaxNodeRef) { | |||
127 | assert_eq!( | 127 | assert_eq!( |
128 | node.parent(), | 128 | node.parent(), |
129 | pair.parent(), | 129 | pair.parent(), |
130 | "unpaired curleys:\n{}", | 130 | "\nunpaired curleys:\n{}", |
131 | utils::dump_tree(root), | 131 | utils::dump_tree(root), |
132 | ); | 132 | ); |
133 | assert!( | 133 | assert!( |
134 | node.next_sibling().is_none() && pair.prev_sibling().is_none(), | 134 | node.next_sibling().is_none() && pair.prev_sibling().is_none(), |
135 | "floating curlys at {:?}\nfile:\n{}\nerror:\n{}\n", | 135 | "\nfloating curlys at {:?}\nfile:\n{}\nerror:\n{}\n", |
136 | node, | 136 | node, |
137 | root.text(), | 137 | root.text(), |
138 | node.text(), | 138 | node.text(), |
diff --git a/crates/libsyntax2/src/parser_api.rs b/crates/libsyntax2/src/parser_api.rs index bb34fe973..0a3b29b70 100644 --- a/crates/libsyntax2/src/parser_api.rs +++ b/crates/libsyntax2/src/parser_api.rs | |||
@@ -141,7 +141,9 @@ impl<'t> Parser<'t> { | |||
141 | pub(crate) fn err_and_bump(&mut self, message: &str) { | 141 | pub(crate) fn err_and_bump(&mut self, message: &str) { |
142 | let m = self.start(); | 142 | let m = self.start(); |
143 | self.error(message); | 143 | self.error(message); |
144 | self.bump(); | 144 | if !self.at(SyntaxKind::L_CURLY) && !self.at(SyntaxKind::R_CURLY) { |
145 | self.bump(); | ||
146 | } | ||
145 | m.complete(self, ERROR); | 147 | m.complete(self, ERROR); |
146 | } | 148 | } |
147 | } | 149 | } |
diff --git a/crates/libsyntax2/tests/data/parser/err/0007_stray_curly_in_file.txt b/crates/libsyntax2/tests/data/parser/err/0007_stray_curly_in_file.txt index 81e82f7e2..802c69b31 100644 --- a/crates/libsyntax2/tests/data/parser/err/0007_stray_curly_in_file.txt +++ b/crates/libsyntax2/tests/data/parser/err/0007_stray_curly_in_file.txt | |||
@@ -1,7 +1,7 @@ | |||
1 | ROOT@[0; 31) | 1 | ROOT@[0; 31) |
2 | ERROR@[0; 1) | 2 | ERROR@[0; 1) |
3 | R_CURLY@[0; 1) | 3 | R_CURLY@[0; 1) |
4 | err: `expected an item` | 4 | err: `unmatched `}`` |
5 | WHITESPACE@[1; 3) | 5 | WHITESPACE@[1; 3) |
6 | STRUCT_DEF@[3; 12) | 6 | STRUCT_DEF@[3; 12) |
7 | STRUCT_KW@[3; 9) | 7 | STRUCT_KW@[3; 9) |
@@ -10,7 +10,7 @@ ROOT@[0; 31) | |||
10 | IDENT@[10; 11) "S" | 10 | IDENT@[10; 11) "S" |
11 | SEMI@[11; 12) | 11 | SEMI@[11; 12) |
12 | WHITESPACE@[12; 14) | 12 | WHITESPACE@[12; 14) |
13 | err: `expected an item` | 13 | err: `unmatched `}`` |
14 | ERROR@[14; 15) | 14 | ERROR@[14; 15) |
15 | R_CURLY@[14; 15) | 15 | R_CURLY@[14; 15) |
16 | WHITESPACE@[15; 17) | 16 | WHITESPACE@[15; 17) |
@@ -26,7 +26,7 @@ ROOT@[0; 31) | |||
26 | L_CURLY@[25; 26) | 26 | L_CURLY@[25; 26) |
27 | R_CURLY@[26; 27) | 27 | R_CURLY@[26; 27) |
28 | WHITESPACE@[27; 29) | 28 | WHITESPACE@[27; 29) |
29 | err: `expected an item` | 29 | err: `unmatched `}`` |
30 | ERROR@[29; 30) | 30 | ERROR@[29; 30) |
31 | R_CURLY@[29; 30) | 31 | R_CURLY@[29; 30) |
32 | WHITESPACE@[30; 31) | 32 | WHITESPACE@[30; 31) |
diff --git a/crates/libsyntax2/tests/data/parser/err/0015_curly_in_params.txt b/crates/libsyntax2/tests/data/parser/err/0015_curly_in_params.txt index dbc19abea..5f736a978 100644 --- a/crates/libsyntax2/tests/data/parser/err/0015_curly_in_params.txt +++ b/crates/libsyntax2/tests/data/parser/err/0015_curly_in_params.txt | |||
@@ -9,7 +9,7 @@ ROOT@[0; 14) | |||
9 | err: `expected value parameter` | 9 | err: `expected value parameter` |
10 | err: `expected R_PAREN` | 10 | err: `expected R_PAREN` |
11 | err: `expected a block` | 11 | err: `expected a block` |
12 | err: `expected an item` | 12 | err: `unmatched `}`` |
13 | ERROR@[7; 8) | 13 | ERROR@[7; 8) |
14 | R_CURLY@[7; 8) | 14 | R_CURLY@[7; 8) |
15 | err: `expected an item` | 15 | err: `expected an item` |
diff --git a/crates/libsyntax2/tests/data/parser/err/0017_incomplete_binexpr.rs b/crates/libsyntax2/tests/data/parser/err/0017_incomplete_binexpr.rs new file mode 100644 index 000000000..17bd49777 --- /dev/null +++ b/crates/libsyntax2/tests/data/parser/err/0017_incomplete_binexpr.rs | |||
@@ -0,0 +1,4 @@ | |||
1 | fn foo(foo: i32) { | ||
2 | let bar = 92; | ||
3 | 1 + | ||
4 | } | ||
diff --git a/crates/libsyntax2/tests/data/parser/err/0017_incomplete_binexpr.txt b/crates/libsyntax2/tests/data/parser/err/0017_incomplete_binexpr.txt new file mode 100644 index 000000000..db9a2f175 --- /dev/null +++ b/crates/libsyntax2/tests/data/parser/err/0017_incomplete_binexpr.txt | |||
@@ -0,0 +1,47 @@ | |||
1 | ROOT@[0; 47) | ||
2 | FN_DEF@[0; 46) | ||
3 | FN_KW@[0; 2) | ||
4 | WHITESPACE@[2; 3) | ||
5 | NAME@[3; 6) | ||
6 | IDENT@[3; 6) "foo" | ||
7 | PARAM_LIST@[6; 16) | ||
8 | L_PAREN@[6; 7) | ||
9 | PARAM@[7; 15) | ||
10 | BIND_PAT@[7; 10) | ||
11 | NAME@[7; 10) | ||
12 | IDENT@[7; 10) "foo" | ||
13 | COLON@[10; 11) | ||
14 | WHITESPACE@[11; 12) | ||
15 | PATH_TYPE@[12; 15) | ||
16 | PATH@[12; 15) | ||
17 | PATH_SEGMENT@[12; 15) | ||
18 | NAME_REF@[12; 15) | ||
19 | IDENT@[12; 15) "i32" | ||
20 | R_PAREN@[15; 16) | ||
21 | WHITESPACE@[16; 17) | ||
22 | BLOCK@[17; 46) | ||
23 | L_CURLY@[17; 18) | ||
24 | WHITESPACE@[18; 23) | ||
25 | LET_STMT@[23; 36) | ||
26 | LET_KW@[23; 26) | ||
27 | WHITESPACE@[26; 27) | ||
28 | BIND_PAT@[27; 30) | ||
29 | NAME@[27; 30) | ||
30 | IDENT@[27; 30) "bar" | ||
31 | WHITESPACE@[30; 31) | ||
32 | EQ@[31; 32) | ||
33 | WHITESPACE@[32; 33) | ||
34 | LITERAL@[33; 35) | ||
35 | INT_NUMBER@[33; 35) "92" | ||
36 | SEMI@[35; 36) | ||
37 | WHITESPACE@[36; 41) | ||
38 | BIN_EXPR@[41; 45) | ||
39 | LITERAL@[41; 42) | ||
40 | INT_NUMBER@[41; 42) "1" | ||
41 | WHITESPACE@[42; 43) | ||
42 | PLUS@[43; 44) | ||
43 | WHITESPACE@[44; 45) | ||
44 | err: `expected expression` | ||
45 | ERROR@[45; 45) | ||
46 | R_CURLY@[45; 46) | ||
47 | WHITESPACE@[46; 47) | ||
diff --git a/crates/libsyntax2/tests/test/main.rs b/crates/libsyntax2/tests/test/main.rs index 596f32216..9958c7ece 100644 --- a/crates/libsyntax2/tests/test/main.rs +++ b/crates/libsyntax2/tests/test/main.rs | |||
@@ -26,6 +26,7 @@ fn lexer_tests() { | |||
26 | #[test] | 26 | #[test] |
27 | fn parser_tests() { | 27 | fn parser_tests() { |
28 | dir_tests(&["parser/inline", "parser/ok", "parser/err"], |text| { | 28 | dir_tests(&["parser/inline", "parser/ok", "parser/err"], |text| { |
29 | eprintln!("\n{}\n", text); | ||
29 | let file = File::parse(text); | 30 | let file = File::parse(text); |
30 | dump_tree(file.syntax()) | 31 | dump_tree(file.syntax()) |
31 | }) | 32 | }) |