Rename ra_ssr -> ssr

This commit is contained in:
Aleksey Kladov 2020-08-13 16:45:10 +02:00
parent bb5c189b7d
commit ae3abd6e57
18 changed files with 95 additions and 110 deletions

32
Cargo.lock generated
View file

@ -1135,28 +1135,14 @@ dependencies = [
"oorandom", "oorandom",
"profile", "profile",
"ra_assists", "ra_assists",
"ra_ssr",
"rustc-hash", "rustc-hash",
"ssr",
"stdx", "stdx",
"syntax", "syntax",
"test_utils", "test_utils",
"text_edit", "text_edit",
] ]
[[package]]
name = "ra_ssr"
version = "0.1.0"
dependencies = [
"base_db",
"expect",
"hir",
"ide_db",
"rustc-hash",
"syntax",
"test_utils",
"text_edit",
]
[[package]] [[package]]
name = "rayon" name = "rayon"
version = "1.3.1" version = "1.3.1"
@ -1254,11 +1240,11 @@ dependencies = [
"profile", "profile",
"project_model", "project_model",
"ra_ide", "ra_ide",
"ra_ssr",
"rayon", "rayon",
"rustc-hash", "rustc-hash",
"serde", "serde",
"serde_json", "serde_json",
"ssr",
"stdx", "stdx",
"syntax", "syntax",
"test_utils", "test_utils",
@ -1456,6 +1442,20 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "ssr"
version = "0.1.0"
dependencies = [
"base_db",
"expect",
"hir",
"ide_db",
"rustc-hash",
"syntax",
"test_utils",
"text_edit",
]
[[package]] [[package]]
name = "stdx" name = "stdx"
version = "0.1.0" version = "0.1.0"

View file

@ -29,7 +29,7 @@ cfg = { path = "../cfg" }
profile = { path = "../profile" } profile = { path = "../profile" }
test_utils = { path = "../test_utils" } test_utils = { path = "../test_utils" }
ra_assists = { path = "../ra_assists" } ra_assists = { path = "../ra_assists" }
ra_ssr = { path = "../ra_ssr" } ssr = { path = "../ssr" }
# ra_ide should depend only on the top-level `hir` package. if you need # ra_ide should depend only on the top-level `hir` package. if you need
# something from some `hir_xxx` subpackage, reexport the API via `hir`. # something from some `hir_xxx` subpackage, reexport the API via `hir`.

View file

@ -39,7 +39,6 @@ macro_rules! eprintln {
mod parent_module; mod parent_module;
mod references; mod references;
mod runnables; mod runnables;
mod ssr;
mod status; mod status;
mod syntax_highlighting; mod syntax_highlighting;
mod syntax_tree; mod syntax_tree;
@ -95,7 +94,7 @@ macro_rules! eprintln {
RootDatabase, RootDatabase,
}; };
pub use ra_assists::{Assist, AssistConfig, AssistId, AssistKind, ResolvedAssist}; pub use ra_assists::{Assist, AssistConfig, AssistId, AssistKind, ResolvedAssist};
pub use ra_ssr::SsrError; pub use ssr::SsrError;
pub use text_edit::{Indel, TextEdit}; pub use text_edit::{Indel, TextEdit};
pub type Cancelable<T> = Result<T, Canceled>; pub type Cancelable<T> = Result<T, Canceled>;
@ -515,20 +514,23 @@ pub fn structural_search_replace(
&self, &self,
query: &str, query: &str,
parse_only: bool, parse_only: bool,
position: FilePosition, resolve_context: FilePosition,
selections: Vec<FileRange>, selections: Vec<FileRange>,
) -> Cancelable<Result<SourceChange, SsrError>> { ) -> Cancelable<Result<SourceChange, SsrError>> {
self.with_db(|db| { self.with_db(|db| {
let edits = ssr::parse_search_replace(query, parse_only, db, position, selections)?; let rule: ssr::SsrRule = query.parse()?;
let mut match_finder = ssr::MatchFinder::in_context(db, resolve_context, selections);
match_finder.add_rule(rule)?;
let edits = if parse_only { Vec::new() } else { match_finder.edits() };
Ok(SourceChange::from(edits)) Ok(SourceChange::from(edits))
}) })
} }
/// Performs an operation on that may be Canceled. /// Performs an operation on that may be Canceled.
fn with_db<F: FnOnce(&RootDatabase) -> T + std::panic::UnwindSafe, T>( fn with_db<F, T>(&self, f: F) -> Cancelable<T>
&self, where
f: F, F: FnOnce(&RootDatabase) -> T + std::panic::UnwindSafe,
) -> Cancelable<T> { {
self.db.catch_canceled(f) self.db.catch_canceled(f)
} }
} }

View file

@ -1,72 +0,0 @@
use base_db::{FilePosition, FileRange};
use ide_db::RootDatabase;
use crate::SourceFileEdit;
use ra_ssr::{MatchFinder, SsrError, SsrRule};
// Feature: Structural Search and Replace
//
// Search and replace with named wildcards that will match any expression, type, path, pattern or item.
// The syntax for a structural search replace command is `<search_pattern> ==>> <replace_pattern>`.
// A `$<name>` placeholder in the search pattern will match any AST node and `$<name>` will reference it in the replacement.
// Within a macro call, a placeholder will match up until whatever token follows the placeholder.
//
// All paths in both the search pattern and the replacement template must resolve in the context
// in which this command is invoked. Paths in the search pattern will then match the code if they
// resolve to the same item, even if they're written differently. For example if we invoke the
// command in the module `foo` with a pattern of `Bar`, then code in the parent module that refers
// to `foo::Bar` will match.
//
// Paths in the replacement template will be rendered appropriately for the context in which the
// replacement occurs. For example if our replacement template is `foo::Bar` and we match some
// code in the `foo` module, we'll insert just `Bar`.
//
// Inherent method calls should generally be written in UFCS form. e.g. `foo::Bar::baz($s, $a)` will
// match `$s.baz($a)`, provided the method call `baz` resolves to the method `foo::Bar::baz`.
//
// The scope of the search / replace will be restricted to the current selection if any, otherwise
// it will apply to the whole workspace.
//
// Placeholders may be given constraints by writing them as `${<name>:<constraint1>:<constraint2>...}`.
//
// Supported constraints:
//
// |===
// | Constraint | Restricts placeholder
//
// | kind(literal) | Is a literal (e.g. `42` or `"forty two"`)
// | not(a) | Negates the constraint `a`
// |===
//
// Available via the command `rust-analyzer.ssr`.
//
// ```rust
// // Using structural search replace command [foo($a, $b) ==>> ($a).foo($b)]
//
// // BEFORE
// String::from(foo(y + 5, z))
//
// // AFTER
// String::from((y + 5).foo(z))
// ```
//
// |===
// | Editor | Action Name
//
// | VS Code | **Rust Analyzer: Structural Search Replace**
// |===
pub fn parse_search_replace(
rule: &str,
parse_only: bool,
db: &RootDatabase,
resolve_context: FilePosition,
selections: Vec<FileRange>,
) -> Result<Vec<SourceFileEdit>, SsrError> {
let rule: SsrRule = rule.parse()?;
let mut match_finder = MatchFinder::in_context(db, resolve_context, selections);
match_finder.add_rule(rule)?;
if parse_only {
return Ok(Vec::new());
}
Ok(match_finder.edits())
}

View file

@ -48,7 +48,7 @@ toolchain = { path = "../toolchain" }
# This should only be used in CLI # This should only be used in CLI
base_db = { path = "../base_db" } base_db = { path = "../base_db" }
ide_db = { path = "../ide_db" } ide_db = { path = "../ide_db" }
ra_ssr = { path = "../ra_ssr" } ssr = { path = "../ssr" }
hir = { path = "../hir" } hir = { path = "../hir" }
hir_def = { path = "../hir_def" } hir_def = { path = "../hir_def" }
hir_ty = { path = "../hir_ty" } hir_ty = { path = "../hir_ty" }

View file

@ -7,8 +7,8 @@
use anyhow::{bail, Result}; use anyhow::{bail, Result};
use pico_args::Arguments; use pico_args::Arguments;
use ra_ssr::{SsrPattern, SsrRule};
use rust_analyzer::cli::{AnalysisStatsCmd, BenchCmd, BenchWhat, Position, Verbosity}; use rust_analyzer::cli::{AnalysisStatsCmd, BenchCmd, BenchWhat, Position, Verbosity};
use ssr::{SsrPattern, SsrRule};
use vfs::AbsPathBuf; use vfs::AbsPathBuf;
pub(crate) struct Args { pub(crate) struct Args {

View file

@ -13,11 +13,13 @@
use ra_ide::Analysis; use ra_ide::Analysis;
use syntax::{AstNode, SourceFile}; use syntax::{AstNode, SourceFile};
pub use analysis_bench::{BenchCmd, BenchWhat, Position}; pub use self::{
pub use analysis_stats::AnalysisStatsCmd; analysis_bench::{BenchCmd, BenchWhat, Position},
pub use diagnostics::diagnostics; analysis_stats::AnalysisStatsCmd,
pub use load_cargo::load_cargo; diagnostics::diagnostics,
pub use ssr::{apply_ssr_rules, search_for_patterns}; load_cargo::load_cargo,
ssr::{apply_ssr_rules, search_for_patterns},
};
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub enum Verbosity { pub enum Verbosity {

View file

@ -1,7 +1,7 @@
//! Applies structured search replace rules from the command line. //! Applies structured search replace rules from the command line.
use crate::cli::{load_cargo::load_cargo, Result}; use crate::cli::{load_cargo::load_cargo, Result};
use ra_ssr::{MatchFinder, SsrPattern, SsrRule}; use ssr::{MatchFinder, SsrPattern, SsrRule};
pub fn apply_ssr_rules(rules: Vec<SsrRule>) -> Result<()> { pub fn apply_ssr_rules(rules: Vec<SsrRule>) -> Result<()> {
use base_db::SourceDatabaseExt; use base_db::SourceDatabaseExt;

View file

@ -1,22 +1,23 @@
[package] [package]
edition = "2018" name = "ssr"
name = "ra_ssr"
version = "0.1.0" version = "0.1.0"
authors = ["rust-analyzer developers"]
license = "MIT OR Apache-2.0"
description = "Structural search and replace of Rust code" description = "Structural search and replace of Rust code"
license = "MIT OR Apache-2.0"
repository = "https://github.com/rust-analyzer/rust-analyzer" repository = "https://github.com/rust-analyzer/rust-analyzer"
authors = ["rust-analyzer developers"]
edition = "2018"
[lib] [lib]
doctest = false doctest = false
[dependencies] [dependencies]
rustc-hash = "1.1.0"
text_edit = { path = "../text_edit" } text_edit = { path = "../text_edit" }
syntax = { path = "../syntax" } syntax = { path = "../syntax" }
base_db = { path = "../base_db" } base_db = { path = "../base_db" }
ide_db = { path = "../ide_db" } ide_db = { path = "../ide_db" }
hir = { path = "../hir" } hir = { path = "../hir" }
rustc-hash = "1.1.0"
test_utils = { path = "../test_utils" } test_utils = { path = "../test_utils" }
[dev-dependencies] [dev-dependencies]

View file

@ -3,6 +3,58 @@
//! Allows searching the AST for code that matches one or more patterns and then replacing that code //! Allows searching the AST for code that matches one or more patterns and then replacing that code
//! based on a template. //! based on a template.
// Feature: Structural Search and Replace
//
// Search and replace with named wildcards that will match any expression, type, path, pattern or item.
// The syntax for a structural search replace command is `<search_pattern> ==>> <replace_pattern>`.
// A `$<name>` placeholder in the search pattern will match any AST node and `$<name>` will reference it in the replacement.
// Within a macro call, a placeholder will match up until whatever token follows the placeholder.
//
// All paths in both the search pattern and the replacement template must resolve in the context
// in which this command is invoked. Paths in the search pattern will then match the code if they
// resolve to the same item, even if they're written differently. For example if we invoke the
// command in the module `foo` with a pattern of `Bar`, then code in the parent module that refers
// to `foo::Bar` will match.
//
// Paths in the replacement template will be rendered appropriately for the context in which the
// replacement occurs. For example if our replacement template is `foo::Bar` and we match some
// code in the `foo` module, we'll insert just `Bar`.
//
// Inherent method calls should generally be written in UFCS form. e.g. `foo::Bar::baz($s, $a)` will
// match `$s.baz($a)`, provided the method call `baz` resolves to the method `foo::Bar::baz`.
//
// The scope of the search / replace will be restricted to the current selection if any, otherwise
// it will apply to the whole workspace.
//
// Placeholders may be given constraints by writing them as `${<name>:<constraint1>:<constraint2>...}`.
//
// Supported constraints:
//
// |===
// | Constraint | Restricts placeholder
//
// | kind(literal) | Is a literal (e.g. `42` or `"forty two"`)
// | not(a) | Negates the constraint `a`
// |===
//
// Available via the command `rust-analyzer.ssr`.
//
// ```rust
// // Using structural search replace command [foo($a, $b) ==>> ($a).foo($b)]
//
// // BEFORE
// String::from(foo(y + 5, z))
//
// // AFTER
// String::from((y + 5).foo(z))
// ```
//
// |===
// | Editor | Action Name
//
// | VS Code | **Rust Analyzer: Structural Search Replace**
// |===
mod matching; mod matching;
mod nester; mod nester;
mod parsing; mod parsing;