diff options
Diffstat (limited to 'crates')
-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 | ||||
-rw-r--r-- | crates/rust-analyzer/Cargo.toml | 2 | ||||
-rw-r--r-- | crates/rust-analyzer/src/bin/args.rs | 2 | ||||
-rw-r--r-- | crates/rust-analyzer/src/cli.rs | 12 | ||||
-rw-r--r-- | crates/rust-analyzer/src/cli/ssr.rs | 2 | ||||
-rw-r--r-- | crates/ssr/Cargo.toml (renamed from crates/ra_ssr/Cargo.toml) | 11 | ||||
-rw-r--r-- | crates/ssr/src/errors.rs (renamed from crates/ra_ssr/src/errors.rs) | 0 | ||||
-rw-r--r-- | crates/ssr/src/lib.rs (renamed from crates/ra_ssr/src/lib.rs) | 52 | ||||
-rw-r--r-- | crates/ssr/src/matching.rs (renamed from crates/ra_ssr/src/matching.rs) | 0 | ||||
-rw-r--r-- | crates/ssr/src/nester.rs (renamed from crates/ra_ssr/src/nester.rs) | 0 | ||||
-rw-r--r-- | crates/ssr/src/parsing.rs (renamed from crates/ra_ssr/src/parsing.rs) | 0 | ||||
-rw-r--r-- | crates/ssr/src/replacing.rs (renamed from crates/ra_ssr/src/replacing.rs) | 0 | ||||
-rw-r--r-- | crates/ssr/src/resolving.rs (renamed from crates/ra_ssr/src/resolving.rs) | 0 | ||||
-rw-r--r-- | crates/ssr/src/search.rs (renamed from crates/ra_ssr/src/search.rs) | 0 | ||||
-rw-r--r-- | crates/ssr/src/tests.rs (renamed from crates/ra_ssr/src/tests.rs) | 0 |
17 files changed, 79 insertions, 94 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 | } | ||
diff --git a/crates/rust-analyzer/Cargo.toml b/crates/rust-analyzer/Cargo.toml index da8c09c09..749cf648c 100644 --- a/crates/rust-analyzer/Cargo.toml +++ b/crates/rust-analyzer/Cargo.toml | |||
@@ -48,7 +48,7 @@ toolchain = { path = "../toolchain" } | |||
48 | # This should only be used in CLI | 48 | # This should only be used in CLI |
49 | base_db = { path = "../base_db" } | 49 | base_db = { path = "../base_db" } |
50 | ide_db = { path = "../ide_db" } | 50 | ide_db = { path = "../ide_db" } |
51 | ra_ssr = { path = "../ra_ssr" } | 51 | ssr = { path = "../ssr" } |
52 | hir = { path = "../hir" } | 52 | hir = { path = "../hir" } |
53 | hir_def = { path = "../hir_def" } | 53 | hir_def = { path = "../hir_def" } |
54 | hir_ty = { path = "../hir_ty" } | 54 | hir_ty = { path = "../hir_ty" } |
diff --git a/crates/rust-analyzer/src/bin/args.rs b/crates/rust-analyzer/src/bin/args.rs index d3081e88b..0bc92431a 100644 --- a/crates/rust-analyzer/src/bin/args.rs +++ b/crates/rust-analyzer/src/bin/args.rs | |||
@@ -7,8 +7,8 @@ use std::{env, fmt::Write, path::PathBuf}; | |||
7 | 7 | ||
8 | use anyhow::{bail, Result}; | 8 | use anyhow::{bail, Result}; |
9 | use pico_args::Arguments; | 9 | use pico_args::Arguments; |
10 | use ra_ssr::{SsrPattern, SsrRule}; | ||
11 | use rust_analyzer::cli::{AnalysisStatsCmd, BenchCmd, BenchWhat, Position, Verbosity}; | 10 | use rust_analyzer::cli::{AnalysisStatsCmd, BenchCmd, BenchWhat, Position, Verbosity}; |
11 | use ssr::{SsrPattern, SsrRule}; | ||
12 | use vfs::AbsPathBuf; | 12 | use vfs::AbsPathBuf; |
13 | 13 | ||
14 | pub(crate) struct Args { | 14 | pub(crate) struct Args { |
diff --git a/crates/rust-analyzer/src/cli.rs b/crates/rust-analyzer/src/cli.rs index 420abaccb..b237a94d1 100644 --- a/crates/rust-analyzer/src/cli.rs +++ b/crates/rust-analyzer/src/cli.rs | |||
@@ -13,11 +13,13 @@ use anyhow::Result; | |||
13 | use ra_ide::Analysis; | 13 | use ra_ide::Analysis; |
14 | use syntax::{AstNode, SourceFile}; | 14 | use syntax::{AstNode, SourceFile}; |
15 | 15 | ||
16 | pub use analysis_bench::{BenchCmd, BenchWhat, Position}; | 16 | pub use self::{ |
17 | pub use analysis_stats::AnalysisStatsCmd; | 17 | analysis_bench::{BenchCmd, BenchWhat, Position}, |
18 | pub use diagnostics::diagnostics; | 18 | analysis_stats::AnalysisStatsCmd, |
19 | pub use load_cargo::load_cargo; | 19 | diagnostics::diagnostics, |
20 | pub use ssr::{apply_ssr_rules, search_for_patterns}; | 20 | load_cargo::load_cargo, |
21 | ssr::{apply_ssr_rules, search_for_patterns}, | ||
22 | }; | ||
21 | 23 | ||
22 | #[derive(Clone, Copy)] | 24 | #[derive(Clone, Copy)] |
23 | pub enum Verbosity { | 25 | pub enum Verbosity { |
diff --git a/crates/rust-analyzer/src/cli/ssr.rs b/crates/rust-analyzer/src/cli/ssr.rs index 1357a93e1..c11e10943 100644 --- a/crates/rust-analyzer/src/cli/ssr.rs +++ b/crates/rust-analyzer/src/cli/ssr.rs | |||
@@ -1,7 +1,7 @@ | |||
1 | //! Applies structured search replace rules from the command line. | 1 | //! Applies structured search replace rules from the command line. |
2 | 2 | ||
3 | use crate::cli::{load_cargo::load_cargo, Result}; | 3 | use crate::cli::{load_cargo::load_cargo, Result}; |
4 | use ra_ssr::{MatchFinder, SsrPattern, SsrRule}; | 4 | use ssr::{MatchFinder, SsrPattern, SsrRule}; |
5 | 5 | ||
6 | pub fn apply_ssr_rules(rules: Vec<SsrRule>) -> Result<()> { | 6 | pub fn apply_ssr_rules(rules: Vec<SsrRule>) -> Result<()> { |
7 | use base_db::SourceDatabaseExt; | 7 | use base_db::SourceDatabaseExt; |
diff --git a/crates/ra_ssr/Cargo.toml b/crates/ssr/Cargo.toml index 4d22a8a98..cd05eeecc 100644 --- a/crates/ra_ssr/Cargo.toml +++ b/crates/ssr/Cargo.toml | |||
@@ -1,22 +1,23 @@ | |||
1 | [package] | 1 | [package] |
2 | edition = "2018" | 2 | name = "ssr" |
3 | name = "ra_ssr" | ||
4 | version = "0.1.0" | 3 | version = "0.1.0" |
5 | authors = ["rust-analyzer developers"] | ||
6 | license = "MIT OR Apache-2.0" | ||
7 | description = "Structural search and replace of Rust code" | 4 | description = "Structural search and replace of Rust code" |
5 | license = "MIT OR Apache-2.0" | ||
8 | repository = "https://github.com/rust-analyzer/rust-analyzer" | 6 | repository = "https://github.com/rust-analyzer/rust-analyzer" |
7 | authors = ["rust-analyzer developers"] | ||
8 | edition = "2018" | ||
9 | 9 | ||
10 | [lib] | 10 | [lib] |
11 | doctest = false | 11 | doctest = false |
12 | 12 | ||
13 | [dependencies] | 13 | [dependencies] |
14 | rustc-hash = "1.1.0" | ||
15 | |||
14 | text_edit = { path = "../text_edit" } | 16 | text_edit = { path = "../text_edit" } |
15 | syntax = { path = "../syntax" } | 17 | syntax = { path = "../syntax" } |
16 | base_db = { path = "../base_db" } | 18 | base_db = { path = "../base_db" } |
17 | ide_db = { path = "../ide_db" } | 19 | ide_db = { path = "../ide_db" } |
18 | hir = { path = "../hir" } | 20 | hir = { path = "../hir" } |
19 | rustc-hash = "1.1.0" | ||
20 | test_utils = { path = "../test_utils" } | 21 | test_utils = { path = "../test_utils" } |
21 | 22 | ||
22 | [dev-dependencies] | 23 | [dev-dependencies] |
diff --git a/crates/ra_ssr/src/errors.rs b/crates/ssr/src/errors.rs index c02bacae6..c02bacae6 100644 --- a/crates/ra_ssr/src/errors.rs +++ b/crates/ssr/src/errors.rs | |||
diff --git a/crates/ra_ssr/src/lib.rs b/crates/ssr/src/lib.rs index b4e35107e..292bd5b9a 100644 --- a/crates/ra_ssr/src/lib.rs +++ b/crates/ssr/src/lib.rs | |||
@@ -3,6 +3,58 @@ | |||
3 | //! Allows searching the AST for code that matches one or more patterns and then replacing that code | 3 | //! Allows searching the AST for code that matches one or more patterns and then replacing that code |
4 | //! based on a template. | 4 | //! based on a template. |
5 | 5 | ||
6 | // Feature: Structural Search and Replace | ||
7 | // | ||
8 | // Search and replace with named wildcards that will match any expression, type, path, pattern or item. | ||
9 | // The syntax for a structural search replace command is `<search_pattern> ==>> <replace_pattern>`. | ||
10 | // A `$<name>` placeholder in the search pattern will match any AST node and `$<name>` will reference it in the replacement. | ||
11 | // Within a macro call, a placeholder will match up until whatever token follows the placeholder. | ||
12 | // | ||
13 | // All paths in both the search pattern and the replacement template must resolve in the context | ||
14 | // in which this command is invoked. Paths in the search pattern will then match the code if they | ||
15 | // resolve to the same item, even if they're written differently. For example if we invoke the | ||
16 | // command in the module `foo` with a pattern of `Bar`, then code in the parent module that refers | ||
17 | // to `foo::Bar` will match. | ||
18 | // | ||
19 | // Paths in the replacement template will be rendered appropriately for the context in which the | ||
20 | // replacement occurs. For example if our replacement template is `foo::Bar` and we match some | ||
21 | // code in the `foo` module, we'll insert just `Bar`. | ||
22 | // | ||
23 | // Inherent method calls should generally be written in UFCS form. e.g. `foo::Bar::baz($s, $a)` will | ||
24 | // match `$s.baz($a)`, provided the method call `baz` resolves to the method `foo::Bar::baz`. | ||
25 | // | ||
26 | // The scope of the search / replace will be restricted to the current selection if any, otherwise | ||
27 | // it will apply to the whole workspace. | ||
28 | // | ||
29 | // Placeholders may be given constraints by writing them as `${<name>:<constraint1>:<constraint2>...}`. | ||
30 | // | ||
31 | // Supported constraints: | ||
32 | // | ||
33 | // |=== | ||
34 | // | Constraint | Restricts placeholder | ||
35 | // | ||
36 | // | kind(literal) | Is a literal (e.g. `42` or `"forty two"`) | ||
37 | // | not(a) | Negates the constraint `a` | ||
38 | // |=== | ||
39 | // | ||
40 | // Available via the command `rust-analyzer.ssr`. | ||
41 | // | ||
42 | // ```rust | ||
43 | // // Using structural search replace command [foo($a, $b) ==>> ($a).foo($b)] | ||
44 | // | ||
45 | // // BEFORE | ||
46 | // String::from(foo(y + 5, z)) | ||
47 | // | ||
48 | // // AFTER | ||
49 | // String::from((y + 5).foo(z)) | ||
50 | // ``` | ||
51 | // | ||
52 | // |=== | ||
53 | // | Editor | Action Name | ||
54 | // | ||
55 | // | VS Code | **Rust Analyzer: Structural Search Replace** | ||
56 | // |=== | ||
57 | |||
6 | mod matching; | 58 | mod matching; |
7 | mod nester; | 59 | mod nester; |
8 | mod parsing; | 60 | mod parsing; |
diff --git a/crates/ra_ssr/src/matching.rs b/crates/ssr/src/matching.rs index ffc7202ae..ffc7202ae 100644 --- a/crates/ra_ssr/src/matching.rs +++ b/crates/ssr/src/matching.rs | |||
diff --git a/crates/ra_ssr/src/nester.rs b/crates/ssr/src/nester.rs index 6ac355dfc..6ac355dfc 100644 --- a/crates/ra_ssr/src/nester.rs +++ b/crates/ssr/src/nester.rs | |||
diff --git a/crates/ra_ssr/src/parsing.rs b/crates/ssr/src/parsing.rs index 9570e96e3..9570e96e3 100644 --- a/crates/ra_ssr/src/parsing.rs +++ b/crates/ssr/src/parsing.rs | |||
diff --git a/crates/ra_ssr/src/replacing.rs b/crates/ssr/src/replacing.rs index 8f8fe6149..8f8fe6149 100644 --- a/crates/ra_ssr/src/replacing.rs +++ b/crates/ssr/src/replacing.rs | |||
diff --git a/crates/ra_ssr/src/resolving.rs b/crates/ssr/src/resolving.rs index 020fd7994..020fd7994 100644 --- a/crates/ra_ssr/src/resolving.rs +++ b/crates/ssr/src/resolving.rs | |||
diff --git a/crates/ra_ssr/src/search.rs b/crates/ssr/src/search.rs index 8509cfa4d..8509cfa4d 100644 --- a/crates/ra_ssr/src/search.rs +++ b/crates/ssr/src/search.rs | |||
diff --git a/crates/ra_ssr/src/tests.rs b/crates/ssr/src/tests.rs index 0d0a00090..0d0a00090 100644 --- a/crates/ra_ssr/src/tests.rs +++ b/crates/ssr/src/tests.rs | |||