diff options
Diffstat (limited to 'src/tools/rust-analyzer/crates/rust-analyzer/src/cli/ssr.rs')
-rw-r--r-- | src/tools/rust-analyzer/crates/rust-analyzer/src/cli/ssr.rs | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/ssr.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/ssr.rs new file mode 100644 index 000000000..e8291782b --- /dev/null +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/ssr.rs @@ -0,0 +1,86 @@ +//! Applies structured search replace rules from the command line. + +use ide_ssr::MatchFinder; +use project_model::CargoConfig; + +use crate::cli::{ + flags, + load_cargo::{load_workspace_at, LoadCargoConfig}, + Result, +}; + +impl flags::Ssr { + pub fn run(self) -> Result<()> { + use ide_db::base_db::SourceDatabaseExt; + let cargo_config = CargoConfig::default(); + let load_cargo_config = LoadCargoConfig { + load_out_dirs_from_check: true, + with_proc_macro: true, + prefill_caches: false, + }; + let (host, vfs, _proc_macro) = load_workspace_at( + &std::env::current_dir()?, + &cargo_config, + &load_cargo_config, + &|_| {}, + )?; + let db = host.raw_database(); + let mut match_finder = MatchFinder::at_first_file(db)?; + for rule in self.rule { + match_finder.add_rule(rule)?; + } + let edits = match_finder.edits(); + for (file_id, edit) in edits { + if let Some(path) = vfs.file_path(file_id).as_path() { + let mut contents = db.file_text(file_id).to_string(); + edit.apply(&mut contents); + std::fs::write(path, contents)?; + } + } + Ok(()) + } +} + +impl flags::Search { + /// Searches for `patterns`, printing debug information for any nodes whose text exactly matches + /// `debug_snippet`. This is intended for debugging and probably isn't in it's current form useful + /// for much else. + pub fn run(self) -> Result<()> { + use ide_db::base_db::SourceDatabaseExt; + use ide_db::symbol_index::SymbolsDatabase; + let cargo_config = CargoConfig::default(); + let load_cargo_config = LoadCargoConfig { + load_out_dirs_from_check: true, + with_proc_macro: true, + prefill_caches: false, + }; + let (host, _vfs, _proc_macro) = load_workspace_at( + &std::env::current_dir()?, + &cargo_config, + &load_cargo_config, + &|_| {}, + )?; + let db = host.raw_database(); + let mut match_finder = MatchFinder::at_first_file(db)?; + for pattern in self.pattern { + match_finder.add_search_pattern(pattern)?; + } + if let Some(debug_snippet) = &self.debug { + for &root in db.local_roots().iter() { + let sr = db.source_root(root); + for file_id in sr.iter() { + for debug_info in match_finder.debug_where_text_equal(file_id, debug_snippet) { + println!("{:#?}", debug_info); + } + } + } + } else { + for m in match_finder.matches().flattened().matches { + // We could possibly at some point do something more useful than just printing + // the matched text. For now though, that's the easiest thing to do. + println!("{}", m.matched_text()); + } + } + Ok(()) + } +} |