diff options
Diffstat (limited to 'crates/ra_ide')
-rw-r--r-- | crates/ra_ide/Cargo.toml | 2 | ||||
-rw-r--r-- | crates/ra_ide/src/lib.rs | 18 | ||||
-rw-r--r-- | crates/ra_ide/src/ssr.rs | 72 |
3 files changed, 11 insertions, 81 deletions
diff --git a/crates/ra_ide/Cargo.toml b/crates/ra_ide/Cargo.toml index e25aad6cf..8519e9cca 100644 --- a/crates/ra_ide/Cargo.toml +++ b/crates/ra_ide/Cargo.toml | |||
@@ -29,7 +29,7 @@ cfg = { path = "../cfg" } | |||
29 | profile = { path = "../profile" } | 29 | profile = { path = "../profile" } |
30 | test_utils = { path = "../test_utils" } | 30 | test_utils = { path = "../test_utils" } |
31 | ra_assists = { path = "../ra_assists" } | 31 | ra_assists = { path = "../ra_assists" } |
32 | ra_ssr = { path = "../ra_ssr" } | 32 | ssr = { path = "../ssr" } |
33 | 33 | ||
34 | # ra_ide should depend only on the top-level `hir` package. if you need | 34 | # ra_ide should depend only on the top-level `hir` package. if you need |
35 | # something from some `hir_xxx` subpackage, reexport the API via `hir`. | 35 | # something from some `hir_xxx` subpackage, reexport the API via `hir`. |
diff --git a/crates/ra_ide/src/lib.rs b/crates/ra_ide/src/lib.rs index 66a234fff..bbc9e4b8a 100644 --- a/crates/ra_ide/src/lib.rs +++ b/crates/ra_ide/src/lib.rs | |||
@@ -39,7 +39,6 @@ mod matching_brace; | |||
39 | mod parent_module; | 39 | mod parent_module; |
40 | mod references; | 40 | mod references; |
41 | mod runnables; | 41 | mod runnables; |
42 | mod ssr; | ||
43 | mod status; | 42 | mod status; |
44 | mod syntax_highlighting; | 43 | mod syntax_highlighting; |
45 | mod syntax_tree; | 44 | mod syntax_tree; |
@@ -95,7 +94,7 @@ pub use ide_db::{ | |||
95 | RootDatabase, | 94 | RootDatabase, |
96 | }; | 95 | }; |
97 | pub use ra_assists::{Assist, AssistConfig, AssistId, AssistKind, ResolvedAssist}; | 96 | pub use ra_assists::{Assist, AssistConfig, AssistId, AssistKind, ResolvedAssist}; |
98 | pub use ra_ssr::SsrError; | 97 | pub use ssr::SsrError; |
99 | pub use text_edit::{Indel, TextEdit}; | 98 | pub use text_edit::{Indel, TextEdit}; |
100 | 99 | ||
101 | pub type Cancelable<T> = Result<T, Canceled>; | 100 | pub type Cancelable<T> = Result<T, Canceled>; |
@@ -515,20 +514,23 @@ impl Analysis { | |||
515 | &self, | 514 | &self, |
516 | query: &str, | 515 | query: &str, |
517 | parse_only: bool, | 516 | parse_only: bool, |
518 | position: FilePosition, | 517 | resolve_context: FilePosition, |
519 | selections: Vec<FileRange>, | 518 | selections: Vec<FileRange>, |
520 | ) -> Cancelable<Result<SourceChange, SsrError>> { | 519 | ) -> Cancelable<Result<SourceChange, SsrError>> { |
521 | self.with_db(|db| { | 520 | self.with_db(|db| { |
522 | let edits = ssr::parse_search_replace(query, parse_only, db, position, selections)?; | 521 | let rule: ssr::SsrRule = query.parse()?; |
522 | let mut match_finder = ssr::MatchFinder::in_context(db, resolve_context, selections); | ||
523 | match_finder.add_rule(rule)?; | ||
524 | let edits = if parse_only { Vec::new() } else { match_finder.edits() }; | ||
523 | Ok(SourceChange::from(edits)) | 525 | Ok(SourceChange::from(edits)) |
524 | }) | 526 | }) |
525 | } | 527 | } |
526 | 528 | ||
527 | /// Performs an operation on that may be Canceled. | 529 | /// Performs an operation on that may be Canceled. |
528 | fn with_db<F: FnOnce(&RootDatabase) -> T + std::panic::UnwindSafe, T>( | 530 | fn with_db<F, T>(&self, f: F) -> Cancelable<T> |
529 | &self, | 531 | where |
530 | f: F, | 532 | F: FnOnce(&RootDatabase) -> T + std::panic::UnwindSafe, |
531 | ) -> Cancelable<T> { | 533 | { |
532 | self.db.catch_canceled(f) | 534 | self.db.catch_canceled(f) |
533 | } | 535 | } |
534 | } | 536 | } |
diff --git a/crates/ra_ide/src/ssr.rs b/crates/ra_ide/src/ssr.rs deleted file mode 100644 index a8a704192..000000000 --- a/crates/ra_ide/src/ssr.rs +++ /dev/null | |||
@@ -1,72 +0,0 @@ | |||
1 | use base_db::{FilePosition, FileRange}; | ||
2 | use ide_db::RootDatabase; | ||
3 | |||
4 | use crate::SourceFileEdit; | ||
5 | use ra_ssr::{MatchFinder, SsrError, SsrRule}; | ||
6 | |||
7 | // Feature: Structural Search and Replace | ||
8 | // | ||
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>`. | ||
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. | ||
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 | // Inherent method calls should generally be written in UFCS form. e.g. `foo::Bar::baz($s, $a)` will | ||
25 | // match `$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 | // | ||
41 | // Available via the command `rust-analyzer.ssr`. | ||
42 | // | ||
43 | // ```rust | ||
44 | // // Using structural search replace command [foo($a, $b) ==>> ($a).foo($b)] | ||
45 | // | ||
46 | // // BEFORE | ||
47 | // String::from(foo(y + 5, z)) | ||
48 | // | ||
49 | // // AFTER | ||
50 | // String::from((y + 5).foo(z)) | ||
51 | // ``` | ||
52 | // | ||
53 | // |=== | ||
54 | // | Editor | Action Name | ||
55 | // | ||
56 | // | VS Code | **Rust Analyzer: Structural Search Replace** | ||
57 | // |=== | ||
58 | pub fn parse_search_replace( | ||
59 | rule: &str, | ||
60 | parse_only: bool, | ||
61 | db: &RootDatabase, | ||
62 | resolve_context: FilePosition, | ||
63 | selections: Vec<FileRange>, | ||
64 | ) -> Result<Vec<SourceFileEdit>, SsrError> { | ||
65 | let rule: SsrRule = rule.parse()?; | ||
66 | let mut match_finder = MatchFinder::in_context(db, resolve_context, selections); | ||
67 | match_finder.add_rule(rule)?; | ||
68 | if parse_only { | ||
69 | return Ok(Vec::new()); | ||
70 | } | ||
71 | Ok(match_finder.edits()) | ||
72 | } | ||