summaryrefslogtreecommitdiffstats
path: root/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/ssr.rs
diff options
context:
space:
mode:
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.rs86
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(())
+ }
+}