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 <dml@google.com>
This commit is contained in:
commit
2bd7171399
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -1464,10 +1464,12 @@ dependencies = [
|
||||
"ra_hir_def",
|
||||
"ra_hir_ty",
|
||||
"ra_ide",
|
||||
"ra_ide_db",
|
||||
"ra_mbe",
|
||||
"ra_proc_macro_srv",
|
||||
"ra_prof",
|
||||
"ra_project_model",
|
||||
"ra_ssr",
|
||||
"ra_syntax",
|
||||
"ra_text_edit",
|
||||
"ra_toolchain",
|
||||
|
@ -45,6 +45,8 @@ ra_toolchain = { path = "../ra_toolchain" }
|
||||
|
||||
# This should only be used in CLI
|
||||
ra_db = { path = "../ra_db" }
|
||||
ra_ide_db = { path = "../ra_ide_db" }
|
||||
ra_ssr = { path = "../ra_ssr" }
|
||||
hir = { path = "../ra_hir", package = "ra_hir" }
|
||||
hir_def = { path = "../ra_hir_def", package = "ra_hir_def" }
|
||||
hir_ty = { path = "../ra_hir_ty", package = "ra_hir_ty" }
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
use anyhow::{bail, Result};
|
||||
use pico_args::Arguments;
|
||||
use ra_ssr::SsrRule;
|
||||
use rust_analyzer::cli::{BenchWhat, Position, Verbosity};
|
||||
|
||||
use std::{fmt::Write, path::PathBuf};
|
||||
@ -45,6 +46,9 @@ pub(crate) enum Command {
|
||||
/// this would include the parser test files.
|
||||
all: bool,
|
||||
},
|
||||
Ssr {
|
||||
rules: Vec<SsrRule>,
|
||||
},
|
||||
ProcMacro,
|
||||
RunServer,
|
||||
Version,
|
||||
@ -270,6 +274,32 @@ pub(crate) fn parse() -> Result<Result<Args, HelpPrinted>> {
|
||||
Command::Diagnostics { path, load_output_dirs, with_proc_macro, all }
|
||||
}
|
||||
"proc-macro" => Command::ProcMacro,
|
||||
"ssr" => {
|
||||
if matches.contains(["-h", "--help"]) {
|
||||
eprintln!(
|
||||
"\
|
||||
rust-analyzer ssr
|
||||
|
||||
USAGE:
|
||||
rust-analyzer ssr [FLAGS] [RULE...]
|
||||
|
||||
EXAMPLE:
|
||||
rust-analyzer ssr '$a.foo($b) ==> bar($a, $b)'
|
||||
|
||||
FLAGS:
|
||||
-h, --help Prints help information
|
||||
|
||||
ARGS:
|
||||
<RULE> A structured search replace rule"
|
||||
);
|
||||
return Ok(Err(HelpPrinted));
|
||||
}
|
||||
let mut rules = Vec::new();
|
||||
while let Some(rule) = matches.free_from_str()? {
|
||||
rules.push(rule);
|
||||
}
|
||||
Command::Ssr { rules }
|
||||
}
|
||||
_ => {
|
||||
print_subcommands();
|
||||
return Ok(Err(HelpPrinted));
|
||||
@ -297,6 +327,7 @@ fn print_subcommands() {
|
||||
diagnostics
|
||||
proc-macro
|
||||
parse
|
||||
ssr
|
||||
symbols"
|
||||
)
|
||||
}
|
||||
|
@ -60,6 +60,9 @@ fn main() -> Result<()> {
|
||||
args::Command::Diagnostics { path, load_output_dirs, with_proc_macro, all } => {
|
||||
cli::diagnostics(path.as_ref(), load_output_dirs, with_proc_macro, all)?
|
||||
}
|
||||
args::Command::Ssr { rules } => {
|
||||
cli::apply_ssr_rules(rules)?;
|
||||
}
|
||||
args::Command::Version => println!("rust-analyzer {}", env!("REV")),
|
||||
}
|
||||
Ok(())
|
||||
|
@ -5,6 +5,7 @@
|
||||
mod analysis_bench;
|
||||
mod diagnostics;
|
||||
mod progress_report;
|
||||
mod ssr;
|
||||
|
||||
use std::io::Read;
|
||||
|
||||
@ -17,6 +18,7 @@
|
||||
pub use analysis_stats::analysis_stats;
|
||||
pub use diagnostics::diagnostics;
|
||||
pub use load_cargo::load_cargo;
|
||||
pub use ssr::apply_ssr_rules;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum Verbosity {
|
||||
|
33
crates/rust-analyzer/src/cli/ssr.rs
Normal file
33
crates/rust-analyzer/src/cli/ssr.rs
Normal file
@ -0,0 +1,33 @@
|
||||
//! Applies structured search replace rules from the command line.
|
||||
|
||||
use crate::cli::{load_cargo::load_cargo, Result};
|
||||
use ra_ide::SourceFileEdit;
|
||||
use ra_ssr::{MatchFinder, SsrRule};
|
||||
|
||||
pub fn apply_ssr_rules(rules: Vec<SsrRule>) -> Result<()> {
|
||||
use ra_db::SourceDatabaseExt;
|
||||
use ra_ide_db::symbol_index::SymbolsDatabase;
|
||||
let (host, vfs) = load_cargo(&std::env::current_dir()?, true, true)?;
|
||||
let db = host.raw_database();
|
||||
let mut match_finder = MatchFinder::new(db);
|
||||
for rule in rules {
|
||||
match_finder.add_rule(rule);
|
||||
}
|
||||
let mut edits = Vec::new();
|
||||
for &root in db.local_roots().iter() {
|
||||
let sr = db.source_root(root);
|
||||
for file_id in sr.iter() {
|
||||
if let Some(edit) = match_finder.edits_for_file(file_id) {
|
||||
edits.push(SourceFileEdit { file_id, edit });
|
||||
}
|
||||
}
|
||||
}
|
||||
for edit in edits {
|
||||
if let Some(path) = vfs.file_path(edit.file_id).as_path() {
|
||||
let mut contents = db.file_text(edit.file_id).to_string();
|
||||
edit.edit.apply(&mut contents);
|
||||
std::fs::write(path, contents)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
Loading…
Reference in New Issue
Block a user