aboutsummaryrefslogtreecommitdiff
path: root/crates/syntax
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2021-01-04 11:14:40 +0000
committerGitHub <[email protected]>2021-01-04 11:14:40 +0000
commitac123ac9e41c14296154ba42bb432e03dffa8b24 (patch)
tree8d6138e0af5f7349a7f00c8cce4a89196b64cd95 /crates/syntax
parent5b86ff3e91838e58397ec39502d85056e46fcfcb (diff)
parentb87699d97ac34f95dc09d166d07fc1220b460821 (diff)
Merge #6587
6587: SSR: Support statement matching and replacing r=davidlattimore a=MarijnS95 For #3186 Hi! This is a smaller initial patchset that came up while working on support for statement lists (and my first time working on RA :grin:). It has me stuck on trailing semicolons for which I hope to receive some feedback. Matching (and replacing) `let` bindings with a trailing semicolon works fine, but trying to omit these (to make patterns more ergonomic) turns out more complex than expected. The "optional trailing semicolon solution" implemented in this PR is ugly because `Matcher::attempt_match_token` should only consume a trailing `;` when parsing `let` bindings to prevent other code from breaking. That at the same time has a nasty side-effect of `;` ending up in the matched code: any replacements on that should include the trailing semicolon as well even if it was not in the pattern. A better example is in the tests: https://github.com/rust-analyzer/rust-analyzer/blob/3ae1649c24a689473b874c331f5f176e5839978e/crates/ssr/src/tests.rs#L178-L184 The end result to achieve is (I guess) allowing replacement of let bindings without trailing semicolon like `let x = $a ==>> let x = 1` (but including them on both sides is still fine), and should make replacement in a macro call (where `foo!(let a = 2;)` for a `$x:stmt` is invalid syntax) possible as well. That should allow to enable/fix these tests: https://github.com/rust-analyzer/rust-analyzer/blob/3ae1649c24a689473b874c331f5f176e5839978e/crates/ssr/src/tests.rs#L201-L214 A possible MVP of this PR might be to drop this optional `;' handling entirely and only allow an SSR pattern/template with semicolons on either side. Co-authored-by: Marijn Suijten <[email protected]>
Diffstat (limited to 'crates/syntax')
-rw-r--r--crates/syntax/src/lib.rs7
-rw-r--r--crates/syntax/src/tests.rs9
-rw-r--r--crates/syntax/test_data/parser/fragments/stmt/err/0000_attr.rast1
-rw-r--r--crates/syntax/test_data/parser/fragments/stmt/err/0000_attr.rs1
-rw-r--r--crates/syntax/test_data/parser/fragments/stmt/err/0000_multiple_stmts.rast1
-rw-r--r--crates/syntax/test_data/parser/fragments/stmt/err/0000_multiple_stmts.rs1
-rw-r--r--crates/syntax/test_data/parser/fragments/stmt/err/0000_open_parenthesis.rast1
-rw-r--r--crates/syntax/test_data/parser/fragments/stmt/err/0000_open_parenthesis.rs1
-rw-r--r--crates/syntax/test_data/parser/fragments/stmt/err/0000_semicolon.rast1
-rw-r--r--crates/syntax/test_data/parser/fragments/stmt/err/0000_semicolon.rs1
-rw-r--r--crates/syntax/test_data/parser/fragments/stmt/err/0000_unterminated_expr.rast1
-rw-r--r--crates/syntax/test_data/parser/fragments/stmt/err/0000_unterminated_expr.rs1
-rw-r--r--crates/syntax/test_data/parser/fragments/stmt/ok/0000_expr.rast9
-rw-r--r--crates/syntax/test_data/parser/fragments/stmt/ok/0000_expr.rs1
-rw-r--r--crates/syntax/test_data/parser/fragments/stmt/ok/0000_expr_block.rast69
-rw-r--r--crates/syntax/test_data/parser/fragments/stmt/ok/0000_expr_block.rs5
-rw-r--r--crates/syntax/test_data/parser/fragments/stmt/ok/0000_fn_call.rast11
-rw-r--r--crates/syntax/test_data/parser/fragments/stmt/ok/0000_fn_call.rs1
-rw-r--r--crates/syntax/test_data/parser/fragments/stmt/ok/0000_let_stmt.rast12
-rw-r--r--crates/syntax/test_data/parser/fragments/stmt/ok/0000_let_stmt.rs1
-rw-r--r--crates/syntax/test_data/parser/fragments/stmt/ok/0000_macro_let_stmt.rast21
-rw-r--r--crates/syntax/test_data/parser/fragments/stmt/ok/0000_macro_let_stmt.rs1
-rw-r--r--crates/syntax/test_data/parser/fragments/stmt/ok/0000_macro_unterminated_let_stmt.rast21
-rw-r--r--crates/syntax/test_data/parser/fragments/stmt/ok/0000_macro_unterminated_let_stmt.rs1
-rw-r--r--crates/syntax/test_data/parser/fragments/stmt/ok/0000_struct_item.rast22
-rw-r--r--crates/syntax/test_data/parser/fragments/stmt/ok/0000_struct_item.rs3
-rw-r--r--crates/syntax/test_data/parser/fragments/stmt/ok/0000_unterminated_fn_call.rast10
-rw-r--r--crates/syntax/test_data/parser/fragments/stmt/ok/0000_unterminated_fn_call.rs1
-rw-r--r--crates/syntax/test_data/parser/fragments/stmt/ok/0000_unterminated_let_stmt.rast11
-rw-r--r--crates/syntax/test_data/parser/fragments/stmt/ok/0000_unterminated_let_stmt.rs1
30 files changed, 227 insertions, 0 deletions
diff --git a/crates/syntax/src/lib.rs b/crates/syntax/src/lib.rs
index 4d272f367..da151e328 100644
--- a/crates/syntax/src/lib.rs
+++ b/crates/syntax/src/lib.rs
@@ -212,6 +212,13 @@ impl ast::Attr {
212 } 212 }
213} 213}
214 214
215impl ast::Stmt {
216 /// Returns `text`, parsed as statement, but only if it has no errors.
217 pub fn parse(text: &str) -> Result<Self, ()> {
218 parsing::parse_text_fragment(text, parser::FragmentKind::StatementOptionalSemi)
219 }
220}
221
215/// Matches a `SyntaxNode` against an `ast` type. 222/// Matches a `SyntaxNode` against an `ast` type.
216/// 223///
217/// # Example: 224/// # Example:
diff --git a/crates/syntax/src/tests.rs b/crates/syntax/src/tests.rs
index 8c217dfe0..9d3433c9d 100644
--- a/crates/syntax/src/tests.rs
+++ b/crates/syntax/src/tests.rs
@@ -103,6 +103,15 @@ fn type_parser_tests() {
103} 103}
104 104
105#[test] 105#[test]
106fn stmt_parser_tests() {
107 fragment_parser_dir_test(
108 &["parser/fragments/stmt/ok"],
109 &["parser/fragments/stmt/err"],
110 crate::ast::Stmt::parse,
111 );
112}
113
114#[test]
106fn parser_fuzz_tests() { 115fn parser_fuzz_tests() {
107 for (_, text) in collect_rust_files(&test_data_dir(), &["parser/fuzz-failures"]) { 116 for (_, text) in collect_rust_files(&test_data_dir(), &["parser/fuzz-failures"]) {
108 fuzz::check_parser(&text) 117 fuzz::check_parser(&text)
diff --git a/crates/syntax/test_data/parser/fragments/stmt/err/0000_attr.rast b/crates/syntax/test_data/parser/fragments/stmt/err/0000_attr.rast
new file mode 100644
index 000000000..5df7507e2
--- /dev/null
+++ b/crates/syntax/test_data/parser/fragments/stmt/err/0000_attr.rast
@@ -0,0 +1 @@
ERROR
diff --git a/crates/syntax/test_data/parser/fragments/stmt/err/0000_attr.rs b/crates/syntax/test_data/parser/fragments/stmt/err/0000_attr.rs
new file mode 100644
index 000000000..988df0705
--- /dev/null
+++ b/crates/syntax/test_data/parser/fragments/stmt/err/0000_attr.rs
@@ -0,0 +1 @@
#[foo]
diff --git a/crates/syntax/test_data/parser/fragments/stmt/err/0000_multiple_stmts.rast b/crates/syntax/test_data/parser/fragments/stmt/err/0000_multiple_stmts.rast
new file mode 100644
index 000000000..5df7507e2
--- /dev/null
+++ b/crates/syntax/test_data/parser/fragments/stmt/err/0000_multiple_stmts.rast
@@ -0,0 +1 @@
ERROR
diff --git a/crates/syntax/test_data/parser/fragments/stmt/err/0000_multiple_stmts.rs b/crates/syntax/test_data/parser/fragments/stmt/err/0000_multiple_stmts.rs
new file mode 100644
index 000000000..7e3b2fd49
--- /dev/null
+++ b/crates/syntax/test_data/parser/fragments/stmt/err/0000_multiple_stmts.rs
@@ -0,0 +1 @@
a(); b(); c()
diff --git a/crates/syntax/test_data/parser/fragments/stmt/err/0000_open_parenthesis.rast b/crates/syntax/test_data/parser/fragments/stmt/err/0000_open_parenthesis.rast
new file mode 100644
index 000000000..5df7507e2
--- /dev/null
+++ b/crates/syntax/test_data/parser/fragments/stmt/err/0000_open_parenthesis.rast
@@ -0,0 +1 @@
ERROR
diff --git a/crates/syntax/test_data/parser/fragments/stmt/err/0000_open_parenthesis.rs b/crates/syntax/test_data/parser/fragments/stmt/err/0000_open_parenthesis.rs
new file mode 100644
index 000000000..2d06f3766
--- /dev/null
+++ b/crates/syntax/test_data/parser/fragments/stmt/err/0000_open_parenthesis.rs
@@ -0,0 +1 @@
(
diff --git a/crates/syntax/test_data/parser/fragments/stmt/err/0000_semicolon.rast b/crates/syntax/test_data/parser/fragments/stmt/err/0000_semicolon.rast
new file mode 100644
index 000000000..5df7507e2
--- /dev/null
+++ b/crates/syntax/test_data/parser/fragments/stmt/err/0000_semicolon.rast
@@ -0,0 +1 @@
ERROR
diff --git a/crates/syntax/test_data/parser/fragments/stmt/err/0000_semicolon.rs b/crates/syntax/test_data/parser/fragments/stmt/err/0000_semicolon.rs
new file mode 100644
index 000000000..092bc2b04
--- /dev/null
+++ b/crates/syntax/test_data/parser/fragments/stmt/err/0000_semicolon.rs
@@ -0,0 +1 @@
;
diff --git a/crates/syntax/test_data/parser/fragments/stmt/err/0000_unterminated_expr.rast b/crates/syntax/test_data/parser/fragments/stmt/err/0000_unterminated_expr.rast
new file mode 100644
index 000000000..5df7507e2
--- /dev/null
+++ b/crates/syntax/test_data/parser/fragments/stmt/err/0000_unterminated_expr.rast
@@ -0,0 +1 @@
ERROR
diff --git a/crates/syntax/test_data/parser/fragments/stmt/err/0000_unterminated_expr.rs b/crates/syntax/test_data/parser/fragments/stmt/err/0000_unterminated_expr.rs
new file mode 100644
index 000000000..ca49acb07
--- /dev/null
+++ b/crates/syntax/test_data/parser/fragments/stmt/err/0000_unterminated_expr.rs
@@ -0,0 +1 @@
1 +
diff --git a/crates/syntax/test_data/parser/fragments/stmt/ok/0000_expr.rast b/crates/syntax/test_data/parser/fragments/stmt/ok/0000_expr.rast
new file mode 100644
index 000000000..274fdf16d
--- /dev/null
+++ b/crates/syntax/test_data/parser/fragments/stmt/ok/0000_expr.rast
@@ -0,0 +1,9 @@
1[email protected]
2 [email protected]
3 [email protected]
4 [email protected] "1"
5 [email protected] " "
6 [email protected] "+"
7 [email protected] " "
8 [email protected]
9 [email protected] "1"
diff --git a/crates/syntax/test_data/parser/fragments/stmt/ok/0000_expr.rs b/crates/syntax/test_data/parser/fragments/stmt/ok/0000_expr.rs
new file mode 100644
index 000000000..8d2f0971e
--- /dev/null
+++ b/crates/syntax/test_data/parser/fragments/stmt/ok/0000_expr.rs
@@ -0,0 +1 @@
1 + 1
diff --git a/crates/syntax/test_data/parser/fragments/stmt/ok/0000_expr_block.rast b/crates/syntax/test_data/parser/fragments/stmt/ok/0000_expr_block.rast
new file mode 100644
index 000000000..6c946091f
--- /dev/null
+++ b/crates/syntax/test_data/parser/fragments/stmt/ok/0000_expr_block.rast
@@ -0,0 +1,69 @@
1[email protected]
2 [email protected]
3 [email protected] "{"
4 [email protected] "\n "
5 [email protected]
6 [email protected] "let"
7 [email protected] " "
8 [email protected]
9 [email protected]
10 [email protected] "x"
11 [email protected] " "
12 [email protected] "="
13 [email protected] " "
14 [email protected]
15 [email protected]
16 [email protected]
17 [email protected]
18 [email protected]
19 [email protected] "foo"
20 [email protected]
21 [email protected] "("
22 [email protected] ")"
23 [email protected] ";"
24 [email protected] "\n "
25 [email protected]
26 [email protected] "let"
27 [email protected] " "
28 [email protected]
29 [email protected]
30 [email protected] "y"
31 [email protected] " "
32 [email protected] "="
33 [email protected] " "
34 [email protected]
35 [email protected]
36 [email protected]
37 [email protected]
38 [email protected]
39 [email protected] "bar"
40 [email protected]
41 [email protected] "("
42 [email protected] ")"
43 [email protected] ";"
44 [email protected] "\n "
45 [email protected]
46 [email protected]
47 [email protected]
48 [email protected]
49 [email protected]
50 [email protected] "Ok"
51 [email protected]
52 [email protected] "("
53 [email protected]
54 [email protected]
55 [email protected]
56 [email protected]
57 [email protected]
58 [email protected] "x"
59 [email protected] " "
60 [email protected] "+"
61 [email protected] " "
62 [email protected]
63 [email protected]
64 [email protected]
65 [email protected]
66 [email protected] "y"
67 [email protected] ")"
68 [email protected] "\n"
69 [email protected] "}"
diff --git a/crates/syntax/test_data/parser/fragments/stmt/ok/0000_expr_block.rs b/crates/syntax/test_data/parser/fragments/stmt/ok/0000_expr_block.rs
new file mode 100644
index 000000000..ffa5c1e66
--- /dev/null
+++ b/crates/syntax/test_data/parser/fragments/stmt/ok/0000_expr_block.rs
@@ -0,0 +1,5 @@
1{
2 let x = foo();
3 let y = bar();
4 Ok(x + y)
5}
diff --git a/crates/syntax/test_data/parser/fragments/stmt/ok/0000_fn_call.rast b/crates/syntax/test_data/parser/fragments/stmt/ok/0000_fn_call.rast
new file mode 100644
index 000000000..8c186da93
--- /dev/null
+++ b/crates/syntax/test_data/parser/fragments/stmt/ok/0000_fn_call.rast
@@ -0,0 +1,11 @@
1[email protected]
2 [email protected]
3 [email protected]
4 [email protected]
5 [email protected]
6 [email protected]
7 [email protected] "foo"
8 [email protected]
9 [email protected] "("
10 [email protected] ")"
11 [email protected] ";"
diff --git a/crates/syntax/test_data/parser/fragments/stmt/ok/0000_fn_call.rs b/crates/syntax/test_data/parser/fragments/stmt/ok/0000_fn_call.rs
new file mode 100644
index 000000000..a280f9a5c
--- /dev/null
+++ b/crates/syntax/test_data/parser/fragments/stmt/ok/0000_fn_call.rs
@@ -0,0 +1 @@
foo();
diff --git a/crates/syntax/test_data/parser/fragments/stmt/ok/0000_let_stmt.rast b/crates/syntax/test_data/parser/fragments/stmt/ok/0000_let_stmt.rast
new file mode 100644
index 000000000..8ab38da21
--- /dev/null
+++ b/crates/syntax/test_data/parser/fragments/stmt/ok/0000_let_stmt.rast
@@ -0,0 +1,12 @@
1[email protected]
2 [email protected] "let"
3 [email protected] " "
4 [email protected]
5 [email protected]
6 [email protected] "x"
7 [email protected] " "
8 [email protected] "="
9 [email protected] " "
10 [email protected]
11 [email protected] "10"
12 [email protected] ";"
diff --git a/crates/syntax/test_data/parser/fragments/stmt/ok/0000_let_stmt.rs b/crates/syntax/test_data/parser/fragments/stmt/ok/0000_let_stmt.rs
new file mode 100644
index 000000000..de8a7f1fc
--- /dev/null
+++ b/crates/syntax/test_data/parser/fragments/stmt/ok/0000_let_stmt.rs
@@ -0,0 +1 @@
let x = 10;
diff --git a/crates/syntax/test_data/parser/fragments/stmt/ok/0000_macro_let_stmt.rast b/crates/syntax/test_data/parser/fragments/stmt/ok/0000_macro_let_stmt.rast
new file mode 100644
index 000000000..81d6df29a
--- /dev/null
+++ b/crates/syntax/test_data/parser/fragments/stmt/ok/0000_macro_let_stmt.rast
@@ -0,0 +1,21 @@
1[email protected]
2 [email protected]
3 [email protected]
4 [email protected]
5 [email protected]
6 [email protected] "m1"
7 [email protected] "!"
8 [email protected]
9 [email protected] "{"
10 [email protected] " "
11 [email protected] "let"
12 [email protected] " "
13 [email protected] "a"
14 [email protected] " "
15 [email protected] "="
16 [email protected] " "
17 [email protected] "0"
18 [email protected] ";"
19 [email protected] " "
20 [email protected] "}"
21 [email protected] ";"
diff --git a/crates/syntax/test_data/parser/fragments/stmt/ok/0000_macro_let_stmt.rs b/crates/syntax/test_data/parser/fragments/stmt/ok/0000_macro_let_stmt.rs
new file mode 100644
index 000000000..075f30159
--- /dev/null
+++ b/crates/syntax/test_data/parser/fragments/stmt/ok/0000_macro_let_stmt.rs
@@ -0,0 +1 @@
m1!{ let a = 0; };
diff --git a/crates/syntax/test_data/parser/fragments/stmt/ok/0000_macro_unterminated_let_stmt.rast b/crates/syntax/test_data/parser/fragments/stmt/ok/0000_macro_unterminated_let_stmt.rast
new file mode 100644
index 000000000..81d6df29a
--- /dev/null
+++ b/crates/syntax/test_data/parser/fragments/stmt/ok/0000_macro_unterminated_let_stmt.rast
@@ -0,0 +1,21 @@
1[email protected]
2 [email protected]
3 [email protected]
4 [email protected]
5 [email protected]
6 [email protected] "m1"
7 [email protected] "!"
8 [email protected]
9 [email protected] "{"
10 [email protected] " "
11 [email protected] "let"
12 [email protected] " "
13 [email protected] "a"
14 [email protected] " "
15 [email protected] "="
16 [email protected] " "
17 [email protected] "0"
18 [email protected] ";"
19 [email protected] " "
20 [email protected] "}"
21 [email protected] ";"
diff --git a/crates/syntax/test_data/parser/fragments/stmt/ok/0000_macro_unterminated_let_stmt.rs b/crates/syntax/test_data/parser/fragments/stmt/ok/0000_macro_unterminated_let_stmt.rs
new file mode 100644
index 000000000..075f30159
--- /dev/null
+++ b/crates/syntax/test_data/parser/fragments/stmt/ok/0000_macro_unterminated_let_stmt.rs
@@ -0,0 +1 @@
m1!{ let a = 0; };
diff --git a/crates/syntax/test_data/parser/fragments/stmt/ok/0000_struct_item.rast b/crates/syntax/test_data/parser/fragments/stmt/ok/0000_struct_item.rast
new file mode 100644
index 000000000..64c5d2969
--- /dev/null
+++ b/crates/syntax/test_data/parser/fragments/stmt/ok/0000_struct_item.rast
@@ -0,0 +1,22 @@
1[email protected]
2 [email protected] "struct"
3 [email protected] " "
4 [email protected]
5 [email protected] "Foo"
6 [email protected] " "
7 [email protected]
8 [email protected] "{"
9 [email protected] "\n "
10 [email protected]
11 [email protected]
12 [email protected] "bar"
13 [email protected] ":"
14 [email protected] " "
15 [email protected]
16 [email protected]
17 [email protected]
18 [email protected]
19 [email protected] "u32"
20 [email protected] ","
21 [email protected] "\n"
22 [email protected] "}"
diff --git a/crates/syntax/test_data/parser/fragments/stmt/ok/0000_struct_item.rs b/crates/syntax/test_data/parser/fragments/stmt/ok/0000_struct_item.rs
new file mode 100644
index 000000000..e5473e3ac
--- /dev/null
+++ b/crates/syntax/test_data/parser/fragments/stmt/ok/0000_struct_item.rs
@@ -0,0 +1,3 @@
1struct Foo {
2 bar: u32,
3}
diff --git a/crates/syntax/test_data/parser/fragments/stmt/ok/0000_unterminated_fn_call.rast b/crates/syntax/test_data/parser/fragments/stmt/ok/0000_unterminated_fn_call.rast
new file mode 100644
index 000000000..9089906bc
--- /dev/null
+++ b/crates/syntax/test_data/parser/fragments/stmt/ok/0000_unterminated_fn_call.rast
@@ -0,0 +1,10 @@
1[email protected]
2 [email protected]
3 [email protected]
4 [email protected]
5 [email protected]
6 [email protected]
7 [email protected] "foo"
8 [email protected]
9 [email protected] "("
10 [email protected] ")"
diff --git a/crates/syntax/test_data/parser/fragments/stmt/ok/0000_unterminated_fn_call.rs b/crates/syntax/test_data/parser/fragments/stmt/ok/0000_unterminated_fn_call.rs
new file mode 100644
index 000000000..eb28ef440
--- /dev/null
+++ b/crates/syntax/test_data/parser/fragments/stmt/ok/0000_unterminated_fn_call.rs
@@ -0,0 +1 @@
foo()
diff --git a/crates/syntax/test_data/parser/fragments/stmt/ok/0000_unterminated_let_stmt.rast b/crates/syntax/test_data/parser/fragments/stmt/ok/0000_unterminated_let_stmt.rast
new file mode 100644
index 000000000..37663671f
--- /dev/null
+++ b/crates/syntax/test_data/parser/fragments/stmt/ok/0000_unterminated_let_stmt.rast
@@ -0,0 +1,11 @@
1[email protected]
2 [email protected] "let"
3 [email protected] " "
4 [email protected]
5 [email protected]
6 [email protected] "x"
7 [email protected] " "
8 [email protected] "="
9 [email protected] " "
10 [email protected]
11 [email protected] "10"
diff --git a/crates/syntax/test_data/parser/fragments/stmt/ok/0000_unterminated_let_stmt.rs b/crates/syntax/test_data/parser/fragments/stmt/ok/0000_unterminated_let_stmt.rs
new file mode 100644
index 000000000..78364b2a9
--- /dev/null
+++ b/crates/syntax/test_data/parser/fragments/stmt/ok/0000_unterminated_let_stmt.rs
@@ -0,0 +1 @@
let x = 10