aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock32
-rw-r--r--crates/ra_ide/Cargo.toml2
-rw-r--r--crates/ra_ide/src/lib.rs18
-rw-r--r--crates/ra_ide/src/ssr.rs72
-rw-r--r--crates/rust-analyzer/Cargo.toml2
-rw-r--r--crates/rust-analyzer/src/bin/args.rs2
-rw-r--r--crates/rust-analyzer/src/cli.rs12
-rw-r--r--crates/rust-analyzer/src/cli/ssr.rs2
-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
18 files changed, 95 insertions, 110 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 8704e4386..4d8b74839 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1135,8 +1135,8 @@ dependencies = [
1135 "oorandom", 1135 "oorandom",
1136 "profile", 1136 "profile",
1137 "ra_assists", 1137 "ra_assists",
1138 "ra_ssr",
1139 "rustc-hash", 1138 "rustc-hash",
1139 "ssr",
1140 "stdx", 1140 "stdx",
1141 "syntax", 1141 "syntax",
1142 "test_utils", 1142 "test_utils",
@@ -1144,20 +1144,6 @@ dependencies = [
1144] 1144]
1145 1145
1146[[package]] 1146[[package]]
1147name = "ra_ssr"
1148version = "0.1.0"
1149dependencies = [
1150 "base_db",
1151 "expect",
1152 "hir",
1153 "ide_db",
1154 "rustc-hash",
1155 "syntax",
1156 "test_utils",
1157 "text_edit",
1158]
1159
1160[[package]]
1161name = "rayon" 1147name = "rayon"
1162version = "1.3.1" 1148version = "1.3.1"
1163source = "registry+https://github.com/rust-lang/crates.io-index" 1149source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1254,11 +1240,11 @@ dependencies = [
1254 "profile", 1240 "profile",
1255 "project_model", 1241 "project_model",
1256 "ra_ide", 1242 "ra_ide",
1257 "ra_ssr",
1258 "rayon", 1243 "rayon",
1259 "rustc-hash", 1244 "rustc-hash",
1260 "serde", 1245 "serde",
1261 "serde_json", 1246 "serde_json",
1247 "ssr",
1262 "stdx", 1248 "stdx",
1263 "syntax", 1249 "syntax",
1264 "test_utils", 1250 "test_utils",
@@ -1457,6 +1443,20 @@ dependencies = [
1457] 1443]
1458 1444
1459[[package]] 1445[[package]]
1446name = "ssr"
1447version = "0.1.0"
1448dependencies = [
1449 "base_db",
1450 "expect",
1451 "hir",
1452 "ide_db",
1453 "rustc-hash",
1454 "syntax",
1455 "test_utils",
1456 "text_edit",
1457]
1458
1459[[package]]
1460name = "stdx" 1460name = "stdx"
1461version = "0.1.0" 1461version = "0.1.0"
1462 1462
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" }
29profile = { path = "../profile" } 29profile = { path = "../profile" }
30test_utils = { path = "../test_utils" } 30test_utils = { path = "../test_utils" }
31ra_assists = { path = "../ra_assists" } 31ra_assists = { path = "../ra_assists" }
32ra_ssr = { path = "../ra_ssr" } 32ssr = { 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;
39mod parent_module; 39mod parent_module;
40mod references; 40mod references;
41mod runnables; 41mod runnables;
42mod ssr;
43mod status; 42mod status;
44mod syntax_highlighting; 43mod syntax_highlighting;
45mod syntax_tree; 44mod syntax_tree;
@@ -95,7 +94,7 @@ pub use ide_db::{
95 RootDatabase, 94 RootDatabase,
96}; 95};
97pub use ra_assists::{Assist, AssistConfig, AssistId, AssistKind, ResolvedAssist}; 96pub use ra_assists::{Assist, AssistConfig, AssistId, AssistKind, ResolvedAssist};
98pub use ra_ssr::SsrError; 97pub use ssr::SsrError;
99pub use text_edit::{Indel, TextEdit}; 98pub use text_edit::{Indel, TextEdit};
100 99
101pub type Cancelable<T> = Result<T, Canceled>; 100pub 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 @@
1use base_db::{FilePosition, FileRange};
2use ide_db::RootDatabase;
3
4use crate::SourceFileEdit;
5use 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// |===
58pub 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
49base_db = { path = "../base_db" } 49base_db = { path = "../base_db" }
50ide_db = { path = "../ide_db" } 50ide_db = { path = "../ide_db" }
51ra_ssr = { path = "../ra_ssr" } 51ssr = { path = "../ssr" }
52hir = { path = "../hir" } 52hir = { path = "../hir" }
53hir_def = { path = "../hir_def" } 53hir_def = { path = "../hir_def" }
54hir_ty = { path = "../hir_ty" } 54hir_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
8use anyhow::{bail, Result}; 8use anyhow::{bail, Result};
9use pico_args::Arguments; 9use pico_args::Arguments;
10use ra_ssr::{SsrPattern, SsrRule};
11use rust_analyzer::cli::{AnalysisStatsCmd, BenchCmd, BenchWhat, Position, Verbosity}; 10use rust_analyzer::cli::{AnalysisStatsCmd, BenchCmd, BenchWhat, Position, Verbosity};
11use ssr::{SsrPattern, SsrRule};
12use vfs::AbsPathBuf; 12use vfs::AbsPathBuf;
13 13
14pub(crate) struct Args { 14pub(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;
13use ra_ide::Analysis; 13use ra_ide::Analysis;
14use syntax::{AstNode, SourceFile}; 14use syntax::{AstNode, SourceFile};
15 15
16pub use analysis_bench::{BenchCmd, BenchWhat, Position}; 16pub use self::{
17pub use analysis_stats::AnalysisStatsCmd; 17 analysis_bench::{BenchCmd, BenchWhat, Position},
18pub use diagnostics::diagnostics; 18 analysis_stats::AnalysisStatsCmd,
19pub use load_cargo::load_cargo; 19 diagnostics::diagnostics,
20pub 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)]
23pub enum Verbosity { 25pub 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
3use crate::cli::{load_cargo::load_cargo, Result}; 3use crate::cli::{load_cargo::load_cargo, Result};
4use ra_ssr::{MatchFinder, SsrPattern, SsrRule}; 4use ssr::{MatchFinder, SsrPattern, SsrRule};
5 5
6pub fn apply_ssr_rules(rules: Vec<SsrRule>) -> Result<()> { 6pub 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]
2edition = "2018" 2name = "ssr"
3name = "ra_ssr"
4version = "0.1.0" 3version = "0.1.0"
5authors = ["rust-analyzer developers"]
6license = "MIT OR Apache-2.0"
7description = "Structural search and replace of Rust code" 4description = "Structural search and replace of Rust code"
5license = "MIT OR Apache-2.0"
8repository = "https://github.com/rust-analyzer/rust-analyzer" 6repository = "https://github.com/rust-analyzer/rust-analyzer"
7authors = ["rust-analyzer developers"]
8edition = "2018"
9 9
10[lib] 10[lib]
11doctest = false 11doctest = false
12 12
13[dependencies] 13[dependencies]
14rustc-hash = "1.1.0"
15
14text_edit = { path = "../text_edit" } 16text_edit = { path = "../text_edit" }
15syntax = { path = "../syntax" } 17syntax = { path = "../syntax" }
16base_db = { path = "../base_db" } 18base_db = { path = "../base_db" }
17ide_db = { path = "../ide_db" } 19ide_db = { path = "../ide_db" }
18hir = { path = "../hir" } 20hir = { path = "../hir" }
19rustc-hash = "1.1.0"
20test_utils = { path = "../test_utils" } 21test_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
6mod matching; 58mod matching;
7mod nester; 59mod nester;
8mod parsing; 60mod 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