diff options
author | David Lattimore <[email protected]> | 2020-06-18 22:43:19 +0100 |
---|---|---|
committer | David Lattimore <[email protected]> | 2020-06-21 13:28:17 +0100 |
commit | bc99e95d7d954701c36142881302bb70e791bec1 (patch) | |
tree | e2cf8c7c18c0b3b6a1f0936db8195f709bc03a5c /crates | |
parent | 902a9c6da7939abec74bb4e4be9d1d16dfb15daa (diff) |
Implement APIs for parsing expressions, types, paths, patterns and items
Diffstat (limited to 'crates')
29 files changed, 222 insertions, 1 deletions
diff --git a/crates/ra_syntax/src/lib.rs b/crates/ra_syntax/src/lib.rs index a33a35cc1..9b7664576 100644 --- a/crates/ra_syntax/src/lib.rs +++ b/crates/ra_syntax/src/lib.rs | |||
@@ -168,6 +168,41 @@ impl SourceFile { | |||
168 | } | 168 | } |
169 | } | 169 | } |
170 | 170 | ||
171 | impl ast::Path { | ||
172 | /// Returns `text`, parsed as a path, but only if it has no errors. | ||
173 | pub fn parse(text: &str) -> Result<Self, ()> { | ||
174 | parsing::parse_text_fragment(text, ra_parser::FragmentKind::Path) | ||
175 | } | ||
176 | } | ||
177 | |||
178 | impl ast::Pat { | ||
179 | /// Returns `text`, parsed as a pattern, but only if it has no errors. | ||
180 | pub fn parse(text: &str) -> Result<Self, ()> { | ||
181 | parsing::parse_text_fragment(text, ra_parser::FragmentKind::Pattern) | ||
182 | } | ||
183 | } | ||
184 | |||
185 | impl ast::Expr { | ||
186 | /// Returns `text`, parsed as an expression, but only if it has no errors. | ||
187 | pub fn parse(text: &str) -> Result<Self, ()> { | ||
188 | parsing::parse_text_fragment(text, ra_parser::FragmentKind::Expr) | ||
189 | } | ||
190 | } | ||
191 | |||
192 | impl ast::ModuleItem { | ||
193 | /// Returns `text`, parsed as an item, but only if it has no errors. | ||
194 | pub fn parse(text: &str) -> Result<Self, ()> { | ||
195 | parsing::parse_text_fragment(text, ra_parser::FragmentKind::Item) | ||
196 | } | ||
197 | } | ||
198 | |||
199 | impl ast::TypeRef { | ||
200 | /// Returns `text`, parsed as an type reference, but only if it has no errors. | ||
201 | pub fn parse(text: &str) -> Result<Self, ()> { | ||
202 | parsing::parse_text_fragment(text, ra_parser::FragmentKind::Type) | ||
203 | } | ||
204 | } | ||
205 | |||
171 | /// Matches a `SyntaxNode` against an `ast` type. | 206 | /// Matches a `SyntaxNode` against an `ast` type. |
172 | /// | 207 | /// |
173 | /// # Example: | 208 | /// # Example: |
diff --git a/crates/ra_syntax/src/parsing.rs b/crates/ra_syntax/src/parsing.rs index e5eb80850..0ed3c20ef 100644 --- a/crates/ra_syntax/src/parsing.rs +++ b/crates/ra_syntax/src/parsing.rs | |||
@@ -6,13 +6,14 @@ mod text_token_source; | |||
6 | mod text_tree_sink; | 6 | mod text_tree_sink; |
7 | mod reparsing; | 7 | mod reparsing; |
8 | 8 | ||
9 | use crate::{syntax_node::GreenNode, SyntaxError}; | 9 | use crate::{syntax_node::GreenNode, AstNode, SyntaxError, SyntaxNode}; |
10 | use text_token_source::TextTokenSource; | 10 | use text_token_source::TextTokenSource; |
11 | use text_tree_sink::TextTreeSink; | 11 | use text_tree_sink::TextTreeSink; |
12 | 12 | ||
13 | pub use lexer::*; | 13 | pub use lexer::*; |
14 | 14 | ||
15 | pub(crate) use self::reparsing::incremental_reparse; | 15 | pub(crate) use self::reparsing::incremental_reparse; |
16 | use ra_parser::SyntaxKind; | ||
16 | 17 | ||
17 | pub(crate) fn parse_text(text: &str) -> (GreenNode, Vec<SyntaxError>) { | 18 | pub(crate) fn parse_text(text: &str) -> (GreenNode, Vec<SyntaxError>) { |
18 | let (tokens, lexer_errors) = tokenize(&text); | 19 | let (tokens, lexer_errors) = tokenize(&text); |
@@ -27,3 +28,32 @@ pub(crate) fn parse_text(text: &str) -> (GreenNode, Vec<SyntaxError>) { | |||
27 | 28 | ||
28 | (tree, parser_errors) | 29 | (tree, parser_errors) |
29 | } | 30 | } |
31 | |||
32 | /// Returns `text` parsed as a `T` provided there are no parse errors. | ||
33 | pub(crate) fn parse_text_fragment<T: AstNode>( | ||
34 | text: &str, | ||
35 | fragment_kind: ra_parser::FragmentKind, | ||
36 | ) -> Result<T, ()> { | ||
37 | let (tokens, lexer_errors) = tokenize(&text); | ||
38 | if !lexer_errors.is_empty() { | ||
39 | return Err(()); | ||
40 | } | ||
41 | |||
42 | let mut token_source = TextTokenSource::new(text, &tokens); | ||
43 | let mut tree_sink = TextTreeSink::new(text, &tokens); | ||
44 | |||
45 | // TextTreeSink assumes that there's at least some root node to which it can attach errors and | ||
46 | // tokens. We arbitrarily give it a SourceFile. | ||
47 | use ra_parser::TreeSink; | ||
48 | tree_sink.start_node(SyntaxKind::SOURCE_FILE); | ||
49 | ra_parser::parse_fragment(&mut token_source, &mut tree_sink, fragment_kind); | ||
50 | tree_sink.finish_node(); | ||
51 | |||
52 | let (tree, parser_errors) = tree_sink.finish(); | ||
53 | use ra_parser::TokenSource; | ||
54 | if !parser_errors.is_empty() || token_source.current().kind != SyntaxKind::EOF { | ||
55 | return Err(()); | ||
56 | } | ||
57 | |||
58 | SyntaxNode::new_root(tree).first_child().and_then(T::cast).ok_or(()) | ||
59 | } | ||
diff --git a/crates/ra_syntax/src/tests.rs b/crates/ra_syntax/src/tests.rs index aee57db62..959967b79 100644 --- a/crates/ra_syntax/src/tests.rs +++ b/crates/ra_syntax/src/tests.rs | |||
@@ -55,6 +55,51 @@ fn parser_tests() { | |||
55 | } | 55 | } |
56 | 56 | ||
57 | #[test] | 57 | #[test] |
58 | fn expr_parser_tests() { | ||
59 | fragment_parser_dir_test( | ||
60 | &["parser/fragments/expr/ok"], | ||
61 | &["parser/fragments/expr/err"], | ||
62 | crate::ast::Expr::parse, | ||
63 | ); | ||
64 | } | ||
65 | |||
66 | #[test] | ||
67 | fn path_parser_tests() { | ||
68 | fragment_parser_dir_test( | ||
69 | &["parser/fragments/path/ok"], | ||
70 | &["parser/fragments/path/err"], | ||
71 | crate::ast::Path::parse, | ||
72 | ); | ||
73 | } | ||
74 | |||
75 | #[test] | ||
76 | fn pattern_parser_tests() { | ||
77 | fragment_parser_dir_test( | ||
78 | &["parser/fragments/pattern/ok"], | ||
79 | &["parser/fragments/pattern/err"], | ||
80 | crate::ast::Pat::parse, | ||
81 | ); | ||
82 | } | ||
83 | |||
84 | #[test] | ||
85 | fn item_parser_tests() { | ||
86 | fragment_parser_dir_test( | ||
87 | &["parser/fragments/item/ok"], | ||
88 | &["parser/fragments/item/err"], | ||
89 | crate::ast::ModuleItem::parse, | ||
90 | ); | ||
91 | } | ||
92 | |||
93 | #[test] | ||
94 | fn type_parser_tests() { | ||
95 | fragment_parser_dir_test( | ||
96 | &["parser/fragments/type/ok"], | ||
97 | &["parser/fragments/type/err"], | ||
98 | crate::ast::TypeRef::parse, | ||
99 | ); | ||
100 | } | ||
101 | |||
102 | #[test] | ||
58 | fn parser_fuzz_tests() { | 103 | fn parser_fuzz_tests() { |
59 | for (_, text) in collect_rust_files(&test_data_dir(), &["parser/fuzz-failures"]) { | 104 | for (_, text) in collect_rust_files(&test_data_dir(), &["parser/fuzz-failures"]) { |
60 | fuzz::check_parser(&text) | 105 | fuzz::check_parser(&text) |
@@ -134,3 +179,24 @@ fn dump_tokens_and_errors(tokens: &[Token], errors: &[SyntaxError], text: &str) | |||
134 | } | 179 | } |
135 | acc | 180 | acc |
136 | } | 181 | } |
182 | |||
183 | fn fragment_parser_dir_test<T, F>(ok_paths: &[&str], err_paths: &[&str], f: F) | ||
184 | where | ||
185 | T: crate::AstNode, | ||
186 | F: Fn(&str) -> Result<T, ()>, | ||
187 | { | ||
188 | dir_tests(&test_data_dir(), ok_paths, "rast", |text, path| { | ||
189 | if let Ok(node) = f(text) { | ||
190 | format!("{:#?}", crate::ast::AstNode::syntax(&node)) | ||
191 | } else { | ||
192 | panic!("Failed to parse '{:?}'", path); | ||
193 | } | ||
194 | }); | ||
195 | dir_tests(&test_data_dir(), err_paths, "rast", |text, path| { | ||
196 | if let Ok(_) = f(text) { | ||
197 | panic!("'{:?}' successfully parsed when it should have errored", path); | ||
198 | } else { | ||
199 | "ERROR\n".to_owned() | ||
200 | } | ||
201 | }); | ||
202 | } | ||
diff --git a/crates/ra_syntax/test_data/parser/fragments/expr/err/0000_truncated_add.rast b/crates/ra_syntax/test_data/parser/fragments/expr/err/0000_truncated_add.rast new file mode 100644 index 000000000..5df7507e2 --- /dev/null +++ b/crates/ra_syntax/test_data/parser/fragments/expr/err/0000_truncated_add.rast | |||
@@ -0,0 +1 @@ | |||
ERROR | |||
diff --git a/crates/ra_syntax/test_data/parser/fragments/expr/err/0000_truncated_add.rs b/crates/ra_syntax/test_data/parser/fragments/expr/err/0000_truncated_add.rs new file mode 100644 index 000000000..ca49acb07 --- /dev/null +++ b/crates/ra_syntax/test_data/parser/fragments/expr/err/0000_truncated_add.rs | |||
@@ -0,0 +1 @@ | |||
1 + | |||
diff --git a/crates/ra_syntax/test_data/parser/fragments/expr/ok/0000_add.rast b/crates/ra_syntax/test_data/parser/fragments/expr/ok/0000_add.rast new file mode 100644 index 000000000..fa78a02a6 --- /dev/null +++ b/crates/ra_syntax/test_data/parser/fragments/expr/ok/0000_add.rast | |||
@@ -0,0 +1,8 @@ | |||
1 | [email protected] | ||
2 | [email protected] | ||
3 | [email protected] "1" | ||
4 | [email protected] " " | ||
5 | [email protected] "+" | ||
6 | [email protected] " " | ||
7 | [email protected] | ||
8 | [email protected] "2" | ||
diff --git a/crates/ra_syntax/test_data/parser/fragments/expr/ok/0000_add.rs b/crates/ra_syntax/test_data/parser/fragments/expr/ok/0000_add.rs new file mode 100644 index 000000000..e0ef58402 --- /dev/null +++ b/crates/ra_syntax/test_data/parser/fragments/expr/ok/0000_add.rs | |||
@@ -0,0 +1 @@ | |||
1 + 2 | |||
diff --git a/crates/ra_syntax/test_data/parser/fragments/item/err/0000_extra_keyword.rast b/crates/ra_syntax/test_data/parser/fragments/item/err/0000_extra_keyword.rast new file mode 100644 index 000000000..5df7507e2 --- /dev/null +++ b/crates/ra_syntax/test_data/parser/fragments/item/err/0000_extra_keyword.rast | |||
@@ -0,0 +1 @@ | |||
ERROR | |||
diff --git a/crates/ra_syntax/test_data/parser/fragments/item/err/0000_extra_keyword.rs b/crates/ra_syntax/test_data/parser/fragments/item/err/0000_extra_keyword.rs new file mode 100644 index 000000000..dc32389bb --- /dev/null +++ b/crates/ra_syntax/test_data/parser/fragments/item/err/0000_extra_keyword.rs | |||
@@ -0,0 +1 @@ | |||
fn fn foo() {} | |||
diff --git a/crates/ra_syntax/test_data/parser/fragments/item/ok/0000_fn.rast b/crates/ra_syntax/test_data/parser/fragments/item/ok/0000_fn.rast new file mode 100644 index 000000000..f1e78f388 --- /dev/null +++ b/crates/ra_syntax/test_data/parser/fragments/item/ok/0000_fn.rast | |||
@@ -0,0 +1,12 @@ | |||
1 | [email protected] | ||
2 | [email protected] "fn" | ||
3 | [email protected] " " | ||
4 | [email protected] | ||
5 | [email protected] "foo" | ||
6 | [email protected] | ||
7 | [email protected] "(" | ||
8 | [email protected] ")" | ||
9 | [email protected] " " | ||
10 | [email protected] | ||
11 | [email protected] "{" | ||
12 | [email protected] "}" | ||
diff --git a/crates/ra_syntax/test_data/parser/fragments/item/ok/0000_fn.rs b/crates/ra_syntax/test_data/parser/fragments/item/ok/0000_fn.rs new file mode 100644 index 000000000..8f3b7ef11 --- /dev/null +++ b/crates/ra_syntax/test_data/parser/fragments/item/ok/0000_fn.rs | |||
@@ -0,0 +1 @@ | |||
fn foo() {} | |||
diff --git a/crates/ra_syntax/test_data/parser/fragments/path/err/0000_reserved_word.rast b/crates/ra_syntax/test_data/parser/fragments/path/err/0000_reserved_word.rast new file mode 100644 index 000000000..5df7507e2 --- /dev/null +++ b/crates/ra_syntax/test_data/parser/fragments/path/err/0000_reserved_word.rast | |||
@@ -0,0 +1 @@ | |||
ERROR | |||
diff --git a/crates/ra_syntax/test_data/parser/fragments/path/err/0000_reserved_word.rs b/crates/ra_syntax/test_data/parser/fragments/path/err/0000_reserved_word.rs new file mode 100644 index 000000000..2046de049 --- /dev/null +++ b/crates/ra_syntax/test_data/parser/fragments/path/err/0000_reserved_word.rs | |||
@@ -0,0 +1 @@ | |||
struct | |||
diff --git a/crates/ra_syntax/test_data/parser/fragments/path/err/0001_expression.rast b/crates/ra_syntax/test_data/parser/fragments/path/err/0001_expression.rast new file mode 100644 index 000000000..5df7507e2 --- /dev/null +++ b/crates/ra_syntax/test_data/parser/fragments/path/err/0001_expression.rast | |||
@@ -0,0 +1 @@ | |||
ERROR | |||
diff --git a/crates/ra_syntax/test_data/parser/fragments/path/err/0001_expression.rs b/crates/ra_syntax/test_data/parser/fragments/path/err/0001_expression.rs new file mode 100644 index 000000000..745e8d376 --- /dev/null +++ b/crates/ra_syntax/test_data/parser/fragments/path/err/0001_expression.rs | |||
@@ -0,0 +1 @@ | |||
a + b | |||
diff --git a/crates/ra_syntax/test_data/parser/fragments/path/ok/0000_single_ident.rast b/crates/ra_syntax/test_data/parser/fragments/path/ok/0000_single_ident.rast new file mode 100644 index 000000000..0c5d4360f --- /dev/null +++ b/crates/ra_syntax/test_data/parser/fragments/path/ok/0000_single_ident.rast | |||
@@ -0,0 +1,4 @@ | |||
1 | [email protected] | ||
2 | [email protected] | ||
3 | [email protected] | ||
4 | [email protected] "foo" | ||
diff --git a/crates/ra_syntax/test_data/parser/fragments/path/ok/0000_single_ident.rs b/crates/ra_syntax/test_data/parser/fragments/path/ok/0000_single_ident.rs new file mode 100644 index 000000000..257cc5642 --- /dev/null +++ b/crates/ra_syntax/test_data/parser/fragments/path/ok/0000_single_ident.rs | |||
@@ -0,0 +1 @@ | |||
foo | |||
diff --git a/crates/ra_syntax/test_data/parser/fragments/path/ok/0001_multipart.rast b/crates/ra_syntax/test_data/parser/fragments/path/ok/0001_multipart.rast new file mode 100644 index 000000000..4a2b45e6a --- /dev/null +++ b/crates/ra_syntax/test_data/parser/fragments/path/ok/0001_multipart.rast | |||
@@ -0,0 +1,14 @@ | |||
1 | [email protected] | ||
2 | [email protected] | ||
3 | [email protected] | ||
4 | [email protected] | ||
5 | [email protected] | ||
6 | [email protected] "foo" | ||
7 | [email protected] "::" | ||
8 | [email protected] | ||
9 | [email protected] | ||
10 | [email protected] "bar" | ||
11 | [email protected] "::" | ||
12 | [email protected] | ||
13 | [email protected] | ||
14 | [email protected] "baz" | ||
diff --git a/crates/ra_syntax/test_data/parser/fragments/path/ok/0001_multipart.rs b/crates/ra_syntax/test_data/parser/fragments/path/ok/0001_multipart.rs new file mode 100644 index 000000000..81e0b21cd --- /dev/null +++ b/crates/ra_syntax/test_data/parser/fragments/path/ok/0001_multipart.rs | |||
@@ -0,0 +1 @@ | |||
foo::bar::baz | |||
diff --git a/crates/ra_syntax/test_data/parser/fragments/pattern/err/0000_reserved_word.rast b/crates/ra_syntax/test_data/parser/fragments/pattern/err/0000_reserved_word.rast new file mode 100644 index 000000000..5df7507e2 --- /dev/null +++ b/crates/ra_syntax/test_data/parser/fragments/pattern/err/0000_reserved_word.rast | |||
@@ -0,0 +1 @@ | |||
ERROR | |||
diff --git a/crates/ra_syntax/test_data/parser/fragments/pattern/err/0000_reserved_word.rs b/crates/ra_syntax/test_data/parser/fragments/pattern/err/0000_reserved_word.rs new file mode 100644 index 000000000..ae26fc455 --- /dev/null +++ b/crates/ra_syntax/test_data/parser/fragments/pattern/err/0000_reserved_word.rs | |||
@@ -0,0 +1 @@ | |||
fn | |||
diff --git a/crates/ra_syntax/test_data/parser/fragments/pattern/err/0001_missing_paren.rast b/crates/ra_syntax/test_data/parser/fragments/pattern/err/0001_missing_paren.rast new file mode 100644 index 000000000..5df7507e2 --- /dev/null +++ b/crates/ra_syntax/test_data/parser/fragments/pattern/err/0001_missing_paren.rast | |||
@@ -0,0 +1 @@ | |||
ERROR | |||
diff --git a/crates/ra_syntax/test_data/parser/fragments/pattern/err/0001_missing_paren.rs b/crates/ra_syntax/test_data/parser/fragments/pattern/err/0001_missing_paren.rs new file mode 100644 index 000000000..61a391d08 --- /dev/null +++ b/crates/ra_syntax/test_data/parser/fragments/pattern/err/0001_missing_paren.rs | |||
@@ -0,0 +1 @@ | |||
Some(x | |||
diff --git a/crates/ra_syntax/test_data/parser/fragments/pattern/ok/0000_enum.rast b/crates/ra_syntax/test_data/parser/fragments/pattern/ok/0000_enum.rast new file mode 100644 index 000000000..15eb7f9c6 --- /dev/null +++ b/crates/ra_syntax/test_data/parser/fragments/pattern/ok/0000_enum.rast | |||
@@ -0,0 +1,10 @@ | |||
1 | [email protected] | ||
2 | [email protected] | ||
3 | [email protected] | ||
4 | [email protected] | ||
5 | [email protected] "Some" | ||
6 | [email protected] "(" | ||
7 | [email protected] | ||
8 | [email protected] | ||
9 | [email protected] "x" | ||
10 | [email protected] ")" | ||
diff --git a/crates/ra_syntax/test_data/parser/fragments/pattern/ok/0000_enum.rs b/crates/ra_syntax/test_data/parser/fragments/pattern/ok/0000_enum.rs new file mode 100644 index 000000000..87114dd78 --- /dev/null +++ b/crates/ra_syntax/test_data/parser/fragments/pattern/ok/0000_enum.rs | |||
@@ -0,0 +1 @@ | |||
Some(x) | |||
diff --git a/crates/ra_syntax/test_data/parser/fragments/type/err/0000_missing_close.rast b/crates/ra_syntax/test_data/parser/fragments/type/err/0000_missing_close.rast new file mode 100644 index 000000000..5df7507e2 --- /dev/null +++ b/crates/ra_syntax/test_data/parser/fragments/type/err/0000_missing_close.rast | |||
@@ -0,0 +1 @@ | |||
ERROR | |||
diff --git a/crates/ra_syntax/test_data/parser/fragments/type/err/0000_missing_close.rs b/crates/ra_syntax/test_data/parser/fragments/type/err/0000_missing_close.rs new file mode 100644 index 000000000..caa4d7c09 --- /dev/null +++ b/crates/ra_syntax/test_data/parser/fragments/type/err/0000_missing_close.rs | |||
@@ -0,0 +1 @@ | |||
Result<Foo, Bar | |||
diff --git a/crates/ra_syntax/test_data/parser/fragments/type/ok/0000_result.rast b/crates/ra_syntax/test_data/parser/fragments/type/ok/0000_result.rast new file mode 100644 index 000000000..8831cfa6c --- /dev/null +++ b/crates/ra_syntax/test_data/parser/fragments/type/ok/0000_result.rast | |||
@@ -0,0 +1,22 @@ | |||
1 | [email protected] | ||
2 | [email protected] | ||
3 | [email protected] | ||
4 | [email protected] | ||
5 | [email protected] "Result" | ||
6 | [email protected] | ||
7 | [email protected] "<" | ||
8 | [email protected] | ||
9 | [email protected] | ||
10 | [email protected] | ||
11 | [email protected] | ||
12 | [email protected] | ||
13 | [email protected] "Foo" | ||
14 | [email protected] "," | ||
15 | [email protected] " " | ||
16 | [email protected] | ||
17 | [email protected] | ||
18 | [email protected] | ||
19 | [email protected] | ||
20 | [email protected] | ||
21 | [email protected] "Bar" | ||
22 | [email protected] ">" | ||
diff --git a/crates/ra_syntax/test_data/parser/fragments/type/ok/0000_result.rs b/crates/ra_syntax/test_data/parser/fragments/type/ok/0000_result.rs new file mode 100644 index 000000000..b50b3bb3b --- /dev/null +++ b/crates/ra_syntax/test_data/parser/fragments/type/ok/0000_result.rs | |||
@@ -0,0 +1 @@ | |||
Result<Foo, Bar> | |||