Skip to content

Commit 2bd7171

Browse files
Merge #5120
5120: Add a simple SSR subcommand to the rust-analyzer command line binary r=davidlattimore a=davidlattimore Is adding the dependency on ra_ide_db OK? It's needed for the call to `db.local_roots()` Co-authored-by: David Lattimore <[email protected]>
2 parents 8035b0a + 867f295 commit 2bd7171

File tree

6 files changed

+73
-0
lines changed

6 files changed

+73
-0
lines changed

Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/rust-analyzer/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ ra_toolchain = { path = "../ra_toolchain" }
4545

4646
# This should only be used in CLI
4747
ra_db = { path = "../ra_db" }
48+
ra_ide_db = { path = "../ra_ide_db" }
49+
ra_ssr = { path = "../ra_ssr" }
4850
hir = { path = "../ra_hir", package = "ra_hir" }
4951
hir_def = { path = "../ra_hir_def", package = "ra_hir_def" }
5052
hir_ty = { path = "../ra_hir_ty", package = "ra_hir_ty" }

crates/rust-analyzer/src/bin/args.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
66
use anyhow::{bail, Result};
77
use pico_args::Arguments;
8+
use ra_ssr::SsrRule;
89
use rust_analyzer::cli::{BenchWhat, Position, Verbosity};
910

1011
use std::{fmt::Write, path::PathBuf};
@@ -45,6 +46,9 @@ pub(crate) enum Command {
4546
/// this would include the parser test files.
4647
all: bool,
4748
},
49+
Ssr {
50+
rules: Vec<SsrRule>,
51+
},
4852
ProcMacro,
4953
RunServer,
5054
Version,
@@ -270,6 +274,32 @@ ARGS:
270274
Command::Diagnostics { path, load_output_dirs, with_proc_macro, all }
271275
}
272276
"proc-macro" => Command::ProcMacro,
277+
"ssr" => {
278+
if matches.contains(["-h", "--help"]) {
279+
eprintln!(
280+
"\
281+
rust-analyzer ssr
282+
283+
USAGE:
284+
rust-analyzer ssr [FLAGS] [RULE...]
285+
286+
EXAMPLE:
287+
rust-analyzer ssr '$a.foo($b) ==> bar($a, $b)'
288+
289+
FLAGS:
290+
-h, --help Prints help information
291+
292+
ARGS:
293+
<RULE> A structured search replace rule"
294+
);
295+
return Ok(Err(HelpPrinted));
296+
}
297+
let mut rules = Vec::new();
298+
while let Some(rule) = matches.free_from_str()? {
299+
rules.push(rule);
300+
}
301+
Command::Ssr { rules }
302+
}
273303
_ => {
274304
print_subcommands();
275305
return Ok(Err(HelpPrinted));
@@ -297,6 +327,7 @@ SUBCOMMANDS:
297327
diagnostics
298328
proc-macro
299329
parse
330+
ssr
300331
symbols"
301332
)
302333
}

crates/rust-analyzer/src/bin/main.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ fn main() -> Result<()> {
6060
args::Command::Diagnostics { path, load_output_dirs, with_proc_macro, all } => {
6161
cli::diagnostics(path.as_ref(), load_output_dirs, with_proc_macro, all)?
6262
}
63+
args::Command::Ssr { rules } => {
64+
cli::apply_ssr_rules(rules)?;
65+
}
6366
args::Command::Version => println!("rust-analyzer {}", env!("REV")),
6467
}
6568
Ok(())

crates/rust-analyzer/src/cli.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ mod analysis_stats;
55
mod analysis_bench;
66
mod diagnostics;
77
mod progress_report;
8+
mod ssr;
89

910
use std::io::Read;
1011

@@ -17,6 +18,7 @@ pub use analysis_bench::{analysis_bench, BenchWhat, Position};
1718
pub use analysis_stats::analysis_stats;
1819
pub use diagnostics::diagnostics;
1920
pub use load_cargo::load_cargo;
21+
pub use ssr::apply_ssr_rules;
2022

2123
#[derive(Clone, Copy)]
2224
pub enum Verbosity {
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
//! Applies structured search replace rules from the command line.
2+
3+
use crate::cli::{load_cargo::load_cargo, Result};
4+
use ra_ide::SourceFileEdit;
5+
use ra_ssr::{MatchFinder, SsrRule};
6+
7+
pub fn apply_ssr_rules(rules: Vec<SsrRule>) -> Result<()> {
8+
use ra_db::SourceDatabaseExt;
9+
use ra_ide_db::symbol_index::SymbolsDatabase;
10+
let (host, vfs) = load_cargo(&std::env::current_dir()?, true, true)?;
11+
let db = host.raw_database();
12+
let mut match_finder = MatchFinder::new(db);
13+
for rule in rules {
14+
match_finder.add_rule(rule);
15+
}
16+
let mut edits = Vec::new();
17+
for &root in db.local_roots().iter() {
18+
let sr = db.source_root(root);
19+
for file_id in sr.iter() {
20+
if let Some(edit) = match_finder.edits_for_file(file_id) {
21+
edits.push(SourceFileEdit { file_id, edit });
22+
}
23+
}
24+
}
25+
for edit in edits {
26+
if let Some(path) = vfs.file_path(edit.file_id).as_path() {
27+
let mut contents = db.file_text(edit.file_id).to_string();
28+
edit.edit.apply(&mut contents);
29+
std::fs::write(path, contents)?;
30+
}
31+
}
32+
Ok(())
33+
}

0 commit comments

Comments
 (0)