aboutsummaryrefslogtreecommitdiff
path: root/crates/ssr/src
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/ssr/src
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/ssr/src')
-rw-r--r--crates/ssr/src/parsing.rs1
-rw-r--r--crates/ssr/src/tests.rs44
2 files changed, 45 insertions, 0 deletions
diff --git a/crates/ssr/src/parsing.rs b/crates/ssr/src/parsing.rs
index f3b084baf..289affe90 100644
--- a/crates/ssr/src/parsing.rs
+++ b/crates/ssr/src/parsing.rs
@@ -78,6 +78,7 @@ impl ParsedRule {
78 builder.try_add(ast::Item::parse(&raw_pattern), raw_template.map(ast::Item::parse)); 78 builder.try_add(ast::Item::parse(&raw_pattern), raw_template.map(ast::Item::parse));
79 builder.try_add(ast::Path::parse(&raw_pattern), raw_template.map(ast::Path::parse)); 79 builder.try_add(ast::Path::parse(&raw_pattern), raw_template.map(ast::Path::parse));
80 builder.try_add(ast::Pat::parse(&raw_pattern), raw_template.map(ast::Pat::parse)); 80 builder.try_add(ast::Pat::parse(&raw_pattern), raw_template.map(ast::Pat::parse));
81 builder.try_add(ast::Stmt::parse(&raw_pattern), raw_template.map(ast::Stmt::parse));
81 builder.build() 82 builder.build()
82 } 83 }
83} 84}
diff --git a/crates/ssr/src/tests.rs b/crates/ssr/src/tests.rs
index 63131f6ca..c4149a849 100644
--- a/crates/ssr/src/tests.rs
+++ b/crates/ssr/src/tests.rs
@@ -160,6 +160,50 @@ fn assert_match_failure_reason(pattern: &str, code: &str, snippet: &str, expecte
160} 160}
161 161
162#[test] 162#[test]
163fn ssr_let_stmt_in_macro_match() {
164 assert_matches(
165 "let a = 0",
166 r#"
167 macro_rules! m1 { ($a:stmt) => {$a}; }
168 fn f() {m1!{ let a = 0 };}"#,
169 // FIXME: Whitespace is not part of the matched block
170 &["leta=0"],
171 );
172}
173
174#[test]
175fn ssr_let_stmt_in_fn_match() {
176 assert_matches("let $a = 10;", "fn main() { let x = 10; x }", &["let x = 10;"]);
177 assert_matches("let $a = $b;", "fn main() { let x = 10; x }", &["let x = 10;"]);
178}
179
180#[test]
181fn ssr_block_expr_match() {
182 assert_matches("{ let $a = $b; }", "fn main() { let x = 10; }", &["{ let x = 10; }"]);
183 assert_matches("{ let $a = $b; $c }", "fn main() { let x = 10; x }", &["{ let x = 10; x }"]);
184}
185
186#[test]
187fn ssr_let_stmt_replace() {
188 // Pattern and template with trailing semicolon
189 assert_ssr_transform(
190 "let $a = $b; ==>> let $a = 11;",
191 "fn main() { let x = 10; x }",
192 expect![["fn main() { let x = 11; x }"]],
193 );
194}
195
196#[test]
197fn ssr_let_stmt_replace_expr() {
198 // Trailing semicolon should be dropped from the new expression
199 assert_ssr_transform(
200 "let $a = $b; ==>> $b",
201 "fn main() { let x = 10; }",
202 expect![["fn main() { 10 }"]],
203 );
204}
205
206#[test]
163fn ssr_function_to_method() { 207fn ssr_function_to_method() {
164 assert_ssr_transform( 208 assert_ssr_transform(
165 "my_function($a, $b) ==>> ($a).my_method($b)", 209 "my_function($a, $b) ==>> ($a).my_method($b)",