From 5c8cb56506646637e45a646657baf12fa9a8f49a Mon Sep 17 00:00:00 2001 From: gfreezy Date: Wed, 16 Jan 2019 21:39:01 +0800 Subject: move rename to a new mod --- crates/ra_ide_api/src/hover.rs | 3 +- crates/ra_ide_api/src/imp.rs | 95 +------------- crates/ra_ide_api/src/lib.rs | 3 +- crates/ra_ide_api/src/rename.rs | 136 +++++++++++++++++++++ crates/ra_ide_api/tests/test/main.rs | 20 ++- .../tests/test/snapshots/test__rename_mod.snap | 36 ++++++ .../test/snapshots/test__rename_mod_in_dir.snap | 36 ++++++ 7 files changed, 231 insertions(+), 98 deletions(-) create mode 100644 crates/ra_ide_api/src/rename.rs create mode 100644 crates/ra_ide_api/tests/test/snapshots/test__rename_mod.snap create mode 100644 crates/ra_ide_api/tests/test/snapshots/test__rename_mod_in_dir.snap (limited to 'crates/ra_ide_api') diff --git a/crates/ra_ide_api/src/hover.rs b/crates/ra_ide_api/src/hover.rs index d91151c15..4d4bfbc4d 100644 --- a/crates/ra_ide_api/src/hover.rs +++ b/crates/ra_ide_api/src/hover.rs @@ -1,7 +1,6 @@ use ra_db::{SyntaxDatabase}; use ra_syntax::{ - AstNode, SyntaxNode, TreeArc, - ast::self, + AstNode, SyntaxNode, TreeArc, ast, algo::{find_covering_node, find_node_at_offset, find_leaf_at_offset, visit::{visitor, Visitor}}, }; diff --git a/crates/ra_ide_api/src/imp.rs b/crates/ra_ide_api/src/imp.rs index 3f0de8b5b..b52a3f4d5 100644 --- a/crates/ra_ide_api/src/imp.rs +++ b/crates/ra_ide_api/src/imp.rs @@ -1,10 +1,7 @@ use std::sync::Arc; use hir::{ - self, Problem, source_binder::{ - self, - module_from_declaration - }, ModuleSource, + self, Problem, source_binder }; use ra_db::{ FilesDatabase, SourceRoot, SourceRootId, SyntaxDatabase, @@ -22,6 +19,7 @@ use crate::{ CrateId, db, Diagnostic, FileId, FilePosition, FileRange, FileSystemEdit, Query, RootChange, SourceChange, SourceFileEdit, symbol_index::{FileSymbol, LibrarySymbolsQuery}, + rename::rename }; impl db::RootDatabase { @@ -234,94 +232,11 @@ impl db::RootDatabase { .collect() } -<<<<<<< HEAD - pub(crate) fn rename(&self, position: FilePosition, new_name: &str) -> Vec { - self.find_all_refs(position) - .iter() - .map(|(file_id, text_range)| SourceFileEdit { - file_id: *file_id, -======= - pub(crate) fn rename( - &self, - position: FilePosition, - new_name: &str, - ) -> Cancelable> { - let mut source_file_edits = Vec::new(); - let mut file_system_edits = Vec::new(); - - let source_file = self.source_file(position.file_id); - let syntax = source_file.syntax(); - // We are rename a mod - if let (Some(ast_module), Some(name)) = ( - find_node_at_offset::(syntax, position.offset), - find_node_at_offset::(syntax, position.offset), - ) { - if let Some(module) = module_from_declaration(self, position.file_id, &ast_module)? { - let (file_id, module_source) = module.definition_source(self)?; - match module_source { - ModuleSource::SourceFile(..) => { - let move_file = FileSystemEdit::MoveFile { - src: file_id, - dst_source_root: self.file_source_root(position.file_id), - dst_path: self - .file_relative_path(file_id) - .with_file_name(new_name) - .with_extension("rs"), - }; - file_system_edits.push(move_file); - } - ModuleSource::Module(..) => {} - } - } - - let edit = SourceFileEdit { - file_id: position.file_id, ->>>>>>> rename mod - edit: { - let mut builder = ra_text_edit::TextEditBuilder::default(); - builder.replace(name.syntax().range(), new_name.into()); - builder.finish() - }, -<<<<<<< HEAD - }) - .collect::>() + pub(crate) fn rename(&self, position: FilePosition, new_name: &str) -> Option { + rename(self, position, new_name) } - pub(crate) fn index_resolve(&self, name_ref: &ast::NameRef) -> Vec { -======= - }; - source_file_edits.push(edit); - } - // rename references - else { - let edit = self - .find_all_refs(position)? - .iter() - .map(|(file_id, text_range)| SourceFileEdit { - file_id: *file_id, - edit: { - let mut builder = ra_text_edit::TextEditBuilder::default(); - builder.replace(*text_range, new_name.into()); - builder.finish() - }, - }) - .collect::>(); - if edit.is_empty() { - return Ok(None); - } - source_file_edits = edit; - } - - return Ok(Some(SourceChange { - label: "rename".to_string(), - source_file_edits, - file_system_edits, - cursor_position: None, - })); - } - - pub(crate) fn index_resolve(&self, name_ref: &ast::NameRef) -> Cancelable> { ->>>>>>> rename mod + pub(crate) fn index_resolve(&self, name_ref: &ast::NameRef) -> Vec { let name = name_ref.text(); let mut query = Query::new(name.to_string()); query.exact(); diff --git a/crates/ra_ide_api/src/lib.rs b/crates/ra_ide_api/src/lib.rs index 7b47d7b6d..1845bf443 100644 --- a/crates/ra_ide_api/src/lib.rs +++ b/crates/ra_ide_api/src/lib.rs @@ -23,6 +23,7 @@ mod hover; mod call_info; mod syntax_highlighting; mod parent_module; +mod rename; use std::{fmt, sync::Arc}; @@ -464,7 +465,7 @@ impl Analysis { &self, position: FilePosition, new_name: &str, - ) -> Cancelable> { + ) -> Cancelable> { self.with_db(|db| db.rename(position, new_name)) } diff --git a/crates/ra_ide_api/src/rename.rs b/crates/ra_ide_api/src/rename.rs new file mode 100644 index 000000000..9f8a00ae7 --- /dev/null +++ b/crates/ra_ide_api/src/rename.rs @@ -0,0 +1,136 @@ +use relative_path::RelativePathBuf; + +use hir::{ + self, ModuleSource, source_binder::module_from_declaration, +}; +use ra_syntax::{ + algo::find_node_at_offset, + ast, + AstNode, + SyntaxNode +}; + +use crate::{ + db::RootDatabase, + FilePosition, + FileSystemEdit, + SourceChange, + SourceFileEdit, +}; +use ra_db::{FilesDatabase, SyntaxDatabase}; +use relative_path::RelativePath; + +pub(crate) fn rename( + db: &RootDatabase, + position: FilePosition, + new_name: &str, +) -> Option { + let source_file = db.source_file(position.file_id); + let syntax = source_file.syntax(); + + if let Some((ast_name, ast_module)) = find_name_and_module_at_offset(syntax, position) { + rename_mod(db, ast_name, ast_module, position, new_name) + } else { + rename_reference(db, position, new_name) + } +} + +fn find_name_and_module_at_offset( + syntax: &SyntaxNode, + position: FilePosition, +) -> Option<(&ast::Name, &ast::Module)> { + let ast_name = find_node_at_offset::(syntax, position.offset); + let ast_name_parent = ast_name + .and_then(|n| n.syntax().parent()) + .and_then(|p| ast::Module::cast(p)); + + if let (Some(ast_module), Some(name)) = (ast_name_parent, ast_name) { + return Some((name, ast_module)); + } + None +} + +fn rename_mod( + db: &RootDatabase, + ast_name: &ast::Name, + ast_module: &ast::Module, + position: FilePosition, + new_name: &str, +) -> Option { + let mut source_file_edits = Vec::new(); + let mut file_system_edits = Vec::new(); + + if let Some(module) = module_from_declaration(db, position.file_id, &ast_module) { + let (file_id, module_source) = module.definition_source(db); + match module_source { + ModuleSource::SourceFile(..) => { + let mod_path: RelativePathBuf = db.file_relative_path(file_id); + // mod is defined in path/to/dir/mod.rs + let dst_path = if mod_path.file_stem() == Some("mod") { + mod_path + .parent() + .and_then(|p| p.parent()) + .or_else(|| Some(RelativePath::new(""))) + .map(|p| p.join(new_name).join("mod.rs")) + } else { + Some(mod_path.with_file_name(new_name).with_extension("rs")) + }; + if let Some(path) = dst_path { + let move_file = FileSystemEdit::MoveFile { + src: file_id, + dst_source_root: db.file_source_root(position.file_id), + dst_path: path, + }; + file_system_edits.push(move_file); + } + } + ModuleSource::Module(..) => {} + } + } + + let edit = SourceFileEdit { + file_id: position.file_id, + edit: { + let mut builder = ra_text_edit::TextEditBuilder::default(); + builder.replace(ast_name.syntax().range(), new_name.into()); + builder.finish() + }, + }; + source_file_edits.push(edit); + + return Some(SourceChange { + label: "rename".to_string(), + source_file_edits, + file_system_edits, + cursor_position: None, + }); +} + +fn rename_reference( + db: &RootDatabase, + position: FilePosition, + new_name: &str, +) -> Option { + let edit = db + .find_all_refs(position) + .iter() + .map(|(file_id, text_range)| SourceFileEdit { + file_id: *file_id, + edit: { + let mut builder = ra_text_edit::TextEditBuilder::default(); + builder.replace(*text_range, new_name.into()); + builder.finish() + }, + }) + .collect::>(); + if edit.is_empty() { + return None; + } + + return Some(SourceChange { + label: "rename".to_string(), + source_file_edits: edit, + file_system_edits: Vec::new(), + cursor_position: None, + }); +} diff --git a/crates/ra_ide_api/tests/test/main.rs b/crates/ra_ide_api/tests/test/main.rs index 4aa13b0e7..2077a89ce 100644 --- a/crates/ra_ide_api/tests/test/main.rs +++ b/crates/ra_ide_api/tests/test/main.rs @@ -7,8 +7,6 @@ use ra_syntax::TextRange; use test_utils::assert_eq_text; use insta::assert_debug_snapshot_matches; -mod runnables; - #[test] fn test_unresolved_module_diagnostic() { let (analysis, file_id) = single_file("mod foo;"); @@ -182,10 +180,22 @@ fn test_rename_mod() { ); let new_name = "foo2"; let source_change = analysis.rename(position, new_name).unwrap(); - assert_eq_dbg( - r#"Some(SourceChange { label: "rename", source_file_edits: [SourceFileEdit { file_id: FileId(1), edit: TextEdit { atoms: [AtomTextEdit { delete: [4; 7), insert: "foo2" }] } }], file_system_edits: [MoveFile { src: FileId(2), dst_source_root: SourceRootId(0), dst_path: "bar/foo2.rs" }], cursor_position: None })"#, - &source_change, + assert_debug_snapshot_matches!("rename_mod", &source_change); +} + +#[test] +fn test_rename_mod_in_dir() { + let (analysis, position) = analysis_and_position( + " + //- /lib.rs + mod fo<|>o; + //- /foo/mod.rs + // emtpy + ", ); + let new_name = "foo2"; + let source_change = analysis.rename(position, new_name).unwrap(); + assert_debug_snapshot_matches!("rename_mod_in_dir", &source_change); } fn test_rename(text: &str, new_name: &str, expected: &str) { diff --git a/crates/ra_ide_api/tests/test/snapshots/test__rename_mod.snap b/crates/ra_ide_api/tests/test/snapshots/test__rename_mod.snap new file mode 100644 index 000000000..54f622b95 --- /dev/null +++ b/crates/ra_ide_api/tests/test/snapshots/test__rename_mod.snap @@ -0,0 +1,36 @@ +Created: 2019-01-16T14:12:39.379431+00:00 +Creator: insta@0.1.4 +Source: crates/ra_ide_api/tests/test/main.rs + +Some( + SourceChange { + label: "rename", + source_file_edits: [ + SourceFileEdit { + file_id: FileId( + 1 + ), + edit: TextEdit { + atoms: [ + AtomTextEdit { + delete: [4; 7), + insert: "foo2" + } + ] + } + } + ], + file_system_edits: [ + MoveFile { + src: FileId( + 2 + ), + dst_source_root: SourceRootId( + 0 + ), + dst_path: "bar/foo2.rs" + } + ], + cursor_position: None + } +) diff --git a/crates/ra_ide_api/tests/test/snapshots/test__rename_mod_in_dir.snap b/crates/ra_ide_api/tests/test/snapshots/test__rename_mod_in_dir.snap new file mode 100644 index 000000000..aac30e89f --- /dev/null +++ b/crates/ra_ide_api/tests/test/snapshots/test__rename_mod_in_dir.snap @@ -0,0 +1,36 @@ +Created: 2019-01-16T14:12:39.379358+00:00 +Creator: insta@0.1.4 +Source: crates/ra_ide_api/tests/test/main.rs + +Some( + SourceChange { + label: "rename", + source_file_edits: [ + SourceFileEdit { + file_id: FileId( + 1 + ), + edit: TextEdit { + atoms: [ + AtomTextEdit { + delete: [4; 7), + insert: "foo2" + } + ] + } + } + ], + file_system_edits: [ + MoveFile { + src: FileId( + 2 + ), + dst_source_root: SourceRootId( + 0 + ), + dst_path: "foo2/mod.rs" + } + ], + cursor_position: None + } +) -- cgit v1.2.3