From 93a91ae9defed0b4e5148b4af6feb90dc75289c0 Mon Sep 17 00:00:00 2001 From: David Lattimore Date: Sat, 27 Jun 2020 17:31:50 +1000 Subject: Add a simple SSR subcommand to the rust-analyzer command line binary --- Cargo.lock | 2 ++ crates/rust-analyzer/Cargo.toml | 2 ++ crates/rust-analyzer/src/bin/args.rs | 31 +++++++++++++++++++++++++++++++ crates/rust-analyzer/src/bin/main.rs | 3 +++ crates/rust-analyzer/src/cli.rs | 2 ++ crates/rust-analyzer/src/cli/ssr.rs | 33 +++++++++++++++++++++++++++++++++ 6 files changed, 73 insertions(+) create mode 100644 crates/rust-analyzer/src/cli/ssr.rs diff --git a/Cargo.lock b/Cargo.lock index b19d697f5..cf0479f0b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -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", diff --git a/crates/rust-analyzer/Cargo.toml b/crates/rust-analyzer/Cargo.toml index 53621fb44..97d9bf5d4 100644 --- a/crates/rust-analyzer/Cargo.toml +++ b/crates/rust-analyzer/Cargo.toml @@ -34,8 +34,10 @@ stdx = { path = "../stdx" } lsp-server = "0.3.3" flycheck = { path = "../flycheck" } ra_ide = { path = "../ra_ide" } +ra_ide_db = { path = "../ra_ide_db" } ra_prof = { path = "../ra_prof" } ra_project_model = { path = "../ra_project_model" } +ra_ssr = { path = "../ra_ssr" } ra_syntax = { path = "../ra_syntax" } ra_text_edit = { path = "../ra_text_edit" } vfs = { path = "../vfs" } diff --git a/crates/rust-analyzer/src/bin/args.rs b/crates/rust-analyzer/src/bin/args.rs index 8e3ca9343..3f0bb3865 100644 --- a/crates/rust-analyzer/src/bin/args.rs +++ b/crates/rust-analyzer/src/bin/args.rs @@ -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, + }, ProcMacro, RunServer, Version, @@ -270,6 +274,32 @@ ARGS: 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: + 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 @@ SUBCOMMANDS: diagnostics proc-macro parse + ssr symbols" ) } diff --git a/crates/rust-analyzer/src/bin/main.rs b/crates/rust-analyzer/src/bin/main.rs index 45204d1a3..16882fc13 100644 --- a/crates/rust-analyzer/src/bin/main.rs +++ b/crates/rust-analyzer/src/bin/main.rs @@ -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(()) diff --git a/crates/rust-analyzer/src/cli.rs b/crates/rust-analyzer/src/cli.rs index c5faec83a..13e3d75be 100644 --- a/crates/rust-analyzer/src/cli.rs +++ b/crates/rust-analyzer/src/cli.rs @@ -5,6 +5,7 @@ mod analysis_stats; mod analysis_bench; mod diagnostics; mod progress_report; +mod ssr; use std::io::Read; @@ -17,6 +18,7 @@ pub use analysis_bench::{analysis_bench, BenchWhat, Position}; 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 { diff --git a/crates/rust-analyzer/src/cli/ssr.rs b/crates/rust-analyzer/src/cli/ssr.rs new file mode 100644 index 000000000..a5265ac15 --- /dev/null +++ b/crates/rust-analyzer/src/cli/ssr.rs @@ -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) -> 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(()) +} -- cgit v1.2.3