mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-26 04:53:34 +00:00
Rename ra_ssr -> ssr
This commit is contained in:
parent
bb5c189b7d
commit
ae3abd6e57
18 changed files with 95 additions and 110 deletions
32
Cargo.lock
generated
32
Cargo.lock
generated
|
@ -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"
|
||||||
|
|
|
@ -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`.
|
||||||
|
|
|
@ -39,7 +39,6 @@ mod matching_brace;
|
||||||
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 @@ pub use ide_db::{
|
||||||
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 @@ impl Analysis {
|
||||||
&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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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())
|
|
||||||
}
|
|
|
@ -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" }
|
||||||
|
|
|
@ -7,8 +7,8 @@ use std::{env, fmt::Write, path::PathBuf};
|
||||||
|
|
||||||
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 {
|
||||||
|
|
|
@ -13,11 +13,13 @@ use anyhow::Result;
|
||||||
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 {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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]
|
|
@ -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;
|
Loading…
Reference in a new issue