aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide/src/ssr.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide/src/ssr.rs')
-rw-r--r--crates/ra_ide/src/ssr.rs53
1 files changed, 37 insertions, 16 deletions
diff --git a/crates/ra_ide/src/ssr.rs b/crates/ra_ide/src/ssr.rs
index 6cb96608b..4348b43be 100644
--- a/crates/ra_ide/src/ssr.rs
+++ b/crates/ra_ide/src/ssr.rs
@@ -1,15 +1,43 @@
1use ra_db::SourceDatabaseExt; 1use ra_db::{FilePosition, FileRange};
2use ra_ide_db::{symbol_index::SymbolsDatabase, RootDatabase}; 2use ra_ide_db::RootDatabase;
3 3
4use crate::SourceFileEdit; 4use crate::SourceFileEdit;
5use ra_ssr::{MatchFinder, SsrError, SsrRule}; 5use ra_ssr::{MatchFinder, SsrError, SsrRule};
6 6
7// Feature: Structural Seach and Replace 7// Feature: Structural Search and Replace
8// 8//
9// Search and replace with named wildcards that will match any expression, type, path, pattern or item. 9// Search and replace with named wildcards that will match any expression, type, path, pattern or item.
10// The syntax for a structural search replace command is `<search_pattern> ==>> <replace_pattern>`. 10// The syntax for a structural search replace command is `<search_pattern> ==>> <replace_pattern>`.
11// A `$<name>` placeholder in the search pattern will match any AST node and `$<name>` will reference it in the replacement. 11// A `$<name>` placeholder in the search pattern will match any AST node and `$<name>` will reference it in the replacement.
12// Within a macro call, a placeholder will match up until whatever token follows the placeholder. 12// Within a macro call, a placeholder will match up until whatever token follows the placeholder.
13//
14// All paths in both the search pattern and the replacement template must resolve in the context
15// in which this command is invoked. Paths in the search pattern will then match the code if they
16// resolve to the same item, even if they're written differently. For example if we invoke the
17// command in the module `foo` with a pattern of `Bar`, then code in the parent module that refers
18// to `foo::Bar` will match.
19//
20// Paths in the replacement template will be rendered appropriately for the context in which the
21// replacement occurs. For example if our replacement template is `foo::Bar` and we match some
22// code in the `foo` module, we'll insert just `Bar`.
23//
24// Method calls should generally be written in UFCS form. e.g. `foo::Bar::baz($s, $a)` will match
25// `$s.baz($a)`, provided the method call `baz` resolves to the method `foo::Bar::baz`.
26//
27// The scope of the search / replace will be restricted to the current selection if any, otherwise
28// it will apply to the whole workspace.
29//
30// Placeholders may be given constraints by writing them as `${<name>:<constraint1>:<constraint2>...}`.
31//
32// Supported constraints:
33//
34// |===
35// | Constraint | Restricts placeholder
36//
37// | kind(literal) | Is a literal (e.g. `42` or `"forty two"`)
38// | not(a) | Negates the constraint `a`
39// |===
40//
13// Available via the command `rust-analyzer.ssr`. 41// Available via the command `rust-analyzer.ssr`.
14// 42//
15// ```rust 43// ```rust
@@ -31,21 +59,14 @@ pub fn parse_search_replace(
31 rule: &str, 59 rule: &str,
32 parse_only: bool, 60 parse_only: bool,
33 db: &RootDatabase, 61 db: &RootDatabase,
62 resolve_context: FilePosition,
63 selections: Vec<FileRange>,
34) -> Result<Vec<SourceFileEdit>, SsrError> { 64) -> Result<Vec<SourceFileEdit>, SsrError> {
35 let mut edits = vec![];
36 let rule: SsrRule = rule.parse()?; 65 let rule: SsrRule = rule.parse()?;
66 let mut match_finder = MatchFinder::in_context(db, resolve_context, selections);
67 match_finder.add_rule(rule)?;
37 if parse_only { 68 if parse_only {
38 return Ok(edits); 69 return Ok(Vec::new());
39 }
40 let mut match_finder = MatchFinder::new(db);
41 match_finder.add_rule(rule);
42 for &root in db.local_roots().iter() {
43 let sr = db.source_root(root);
44 for file_id in sr.iter() {
45 if let Some(edit) = match_finder.edits_for_file(file_id) {
46 edits.push(SourceFileEdit { file_id, edit });
47 }
48 }
49 } 70 }
50 Ok(edits) 71 Ok(match_finder.edits())
51} 72}