New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
StructuralSearchReplace: next steps #3186
Comments
The most important feature here is documentation! |
What kinds of things are you thinking about for the second item? |
White space differences should not matter for natching |
Made an initial change for the whitespace, but there's two points I'm not certain about:
|
Actually I think for my second question it's fine to throw out all whitespace tokens. I can't actually think of any situations where it would be a problem. |
Note that there's an |
Yeah, the line that checks for Pattern_White_Space is in the rustc_lexer
crate, which we share with the compiler
…On Sat, 22 Feb 2020 at 23:18, Florian Diebold ***@***.***> wrote:
Note that there's an is_trivia method on SyntaxKind, you don't need to
implement this yourself. E.g. some_token.kind().is_trivia().
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#3186>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AANB3M2QY4CRZWSFQLYQ6D3REGQDNANCNFSM4KWONEZA>
.
|
Cool, thanks. |
@adamrk sorry, I missed that you started to work on it and created a PR for the second step. |
3285: Handle trivia in Structural Search and Replace r=matklad a=adamrk Addresses the second point of #3186. Structural search and replace will now match code that has varies from the pattern in whitespace or comments. One issue is that it's not clear where comments in the matched code should go in the replacement. With this change they're just tacked on at the end, which can cause some unexpected moving of comments (see the last test example). Co-authored-by: adamrk <ark.email@gmail.com>
my mistake @mikhail-m1 - didn't realize you were working on it either. |
Example of semanticly equivalent transformations -- trailing comma: // replace_children(self, $what:expr, $where:expr) ==>> self.replace_children($what, $where)
return replace_children(
self,
single_node(old.syntax().clone()),
iter::once(segment.syntax().clone().into()),
); |
I've actually been using ssr and it works surprisingly well. One thing I've found is that typing ssr in comment and then copy-pasting it is the most productive workflow. I think we should probably make this the workflow. Specifcally, I imaging something like this:
|
next steps:
|
@RReverser no, we currently run on pre-expansion code. Although we should probably run post-expansion eventually. A minimal test-case would be useful! |
Hmm, my problem is exactly that it doesn't seem to match pre-expansion code. I've tried something as simple as:
and it didn't match anything. |
See also this nice blog post about how semantic code searches are handled in IntelliJ: https://habr.com/en/company/JetBrains/blog/451754/ I think for rust-analyzer we might be able to come up with something even more efficient (salsa allows us to lift the "single file index" constraint), but that is very much unexplored territory. |
Reasoning discussed at rust-lang#3186
BTW, it might be nice to be able to apply SSR by running |
4919: Remove :expr from placeholders r=matklad a=davidlattimore Reasoning discussed at #3186 (comment) Co-authored-by: David Lattimore <dml@google.com>
Forgot to reference this issue, but #5120 added support for SSR from the rust-analyzer command line |
I figred that it migbe be useful to support statements in SSR: let $var = foo();
$var.bar();
==>>
foo().bar(); |
I've added path resolution to SSR rules, the main user-visible changes are:
Regarding supporting statements, I agree, that would be good to support. It'll probably require some refactoring since currently we only match whole AST nodes, not sequences of nodes. Also, the example you gave would also require allowing a placeholder to be repeated, then checking the equivalence of each occurrence. I just started looking at making an SSR assist, but I'm slightly unsure of how it should work if there's an SSR rule, but it fails validation. How should the error be presented? It looks like the assist API just does edits, but doesn't offer any scope for interaction or error reporting. Is that correct? |
You could report an error for all invalid ssr comments instead of waiting for the assist to be invoked. |
That sounds like it would work. Another thing that I've been thinking it would be good to support is a way to scope the rule. Sometimes you just want to automate a repetitive edit to the current file, or even within the current function. One way I was considering was by extending the placeholder constraint syntax. So A completely different option would be to just have different commands - e.g. "Structural Search Replace - current file". That's perhaps more discoverable, but less scalable (adding new scopes would be a pain). A third option would be building a more sophisticated UI for doing SSR - one that could have drop downs, checkboxes etc. I know comparatively little about extending vscode, so I'm not sure how plausible that would be. |
I think a bit more natural option could be "search within selection" which is how regular Find & Replace already limits itself in VSCode. Then user can easily select a single function, or couple of them, or whole module, etc. |
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 <marijn@traverseresearch.nl>
7874: add apply ssr assist r=JoshMcguigan a=JoshMcguigan This PR adds an `Apply SSR` assist which was briefly mentioned in #3186. It allows writing an ssr rule as a comment, and then applying that SSR via an assist. This workflow is much nicer than the default available via `coc-rust-analyzer` when iterating to find the proper replacement. As currently implemented, this requires the ssr rule is written as a single line in the comment, and it doesn't require any kind of prefix. Anything which properly parses as a ssr rule will enable the assist. The benefit of requiring the ssr rule be on a single line is it allows for a workflow where the user has several rules written one after the other, possibly to be triggered in order, without having to try to parse multiple lines of text and determine where one rule ends and the next begins. The benefit of not requiring a prefix is less typing 😆 - plus, I think the chance of something accidentally parsing as an ssr rule is minimal. I think a reasonable extension of this would be to allow either any ssr rule that fits on a single line, or any comment block which in its entirety makes up a single ssr rule (parsing a comment block containing multiple ssr rules and running them all would break the use case that currently works where a user writes multiple ssr rules then runs them each one by one in arbitrary order). I've marked this as a draft because for some reason I am strugging to make the unit tests pass. It does work when I compile rust-analyzer and test it in my editor though, so I'm not sure what is going on. Co-authored-by: Josh Mcguigan <joshmcg88@gmail.com>
Tried SSR today. One limitation seems to be the power of the matcher, e.g. |
Another thing that would make SSR a lot more approachable would be incremental search and replace, ie
Also syntax highlighting in the SSR query+replacement would be nice Some of this is more about the ide plugin side, but the server needs to have the capabilities. Is everything necessary for this available from the server already? |
#3099 implemented initial version of SSR.
This issue collects things we need to do to make this really production-read
$expr
@mikhail-m1 any other things I've missed?
The text was updated successfully, but these errors were encountered: