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:
bors[bot] 2020-06-29 23:33:34 +00:00 committed by GitHub
commit 2bd7171399
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 73 additions and 0 deletions

2
Cargo.lock generated
View File

@ -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",

View File

@ -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" }

View File

@ -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"
)
}

View File

@ -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(())

View File

@ -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 {

View 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(())
}