//! 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, SsrPattern, 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(()) } /// 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 search_for_patterns(patterns: Vec, debug_snippet: Option) -> 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 pattern in patterns { match_finder.add_search_pattern(pattern); } for &root in db.local_roots().iter() { let sr = db.source_root(root); for file_id in sr.iter() { if let Some(debug_snippet) = &debug_snippet { for debug_info in match_finder.debug_where_text_equal(file_id, debug_snippet) { println!("{:#?}", debug_info); } } else { let matches = match_finder.find_matches_in_file(file_id); if !matches.matches.is_empty() { let matches = matches.flattened().matches; if let Some(path) = vfs.file_path(file_id).as_path() { println!("{} matches in '{}'", matches.len(), path.to_string_lossy()); } // 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. for m in matches { println!("{}", m.matched_text()); } } } } } Ok(()) }