aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgfreezy <[email protected]>2019-01-16 13:39:01 +0000
committerAleksey Kladov <[email protected]>2019-01-19 12:36:58 +0000
commit5c8cb56506646637e45a646657baf12fa9a8f49a (patch)
tree132edba357d82b4f011ea580c7e73e36c7cde02b
parentbc0f79f74ad0ab4f663b94772ccbfabed1de625e (diff)
move rename to a new mod
-rw-r--r--crates/ra_hir/src/source_binder.rs9
-rw-r--r--crates/ra_ide_api/src/hover.rs3
-rw-r--r--crates/ra_ide_api/src/imp.rs95
-rw-r--r--crates/ra_ide_api/src/lib.rs3
-rw-r--r--crates/ra_ide_api/src/rename.rs136
-rw-r--r--crates/ra_ide_api/tests/test/main.rs20
-rw-r--r--crates/ra_ide_api/tests/test/snapshots/test__rename_mod.snap36
-rw-r--r--crates/ra_ide_api/tests/test/snapshots/test__rename_mod_in_dir.snap36
8 files changed, 233 insertions, 105 deletions
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index 7ab8eeae2..be82d804a 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_binder.rs
@@ -35,14 +35,9 @@ pub fn module_from_declaration(
35 let parent_module = module_from_file_id(db, file_id); 35 let parent_module = module_from_file_id(db, file_id);
36 let child_name = decl.name(); 36 let child_name = decl.name();
37 match (parent_module, child_name) { 37 match (parent_module, child_name) {
38 (Some(parent_module), Some(child_name)) => { 38 (Some(parent_module), Some(child_name)) => parent_module.child(db, &child_name.as_name()),
39 if let Some(child) = parent_module.child(db, &child_name.as_name()) { 39 _ => None,
40 return Some(child);
41 }
42 }
43 _ => (),
44 } 40 }
45 None
46} 41}
47 42
48/// Locates the module by position in the source code. 43/// Locates the module by position in the source code.
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 @@
1use ra_db::{SyntaxDatabase}; 1use ra_db::{SyntaxDatabase};
2use ra_syntax::{ 2use ra_syntax::{
3 AstNode, SyntaxNode, TreeArc, 3 AstNode, SyntaxNode, TreeArc, ast,
4 ast::self,
5 algo::{find_covering_node, find_node_at_offset, find_leaf_at_offset, visit::{visitor, Visitor}}, 4 algo::{find_covering_node, find_node_at_offset, find_leaf_at_offset, visit::{visitor, Visitor}},
6}; 5};
7 6
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 @@
1use std::sync::Arc; 1use std::sync::Arc;
2 2
3use hir::{ 3use hir::{
4 self, Problem, source_binder::{ 4 self, Problem, source_binder
5 self,
6 module_from_declaration
7 }, ModuleSource,
8}; 5};
9use ra_db::{ 6use ra_db::{
10 FilesDatabase, SourceRoot, SourceRootId, SyntaxDatabase, 7 FilesDatabase, SourceRoot, SourceRootId, SyntaxDatabase,
@@ -22,6 +19,7 @@ use crate::{
22 CrateId, db, Diagnostic, FileId, FilePosition, FileRange, FileSystemEdit, 19 CrateId, db, Diagnostic, FileId, FilePosition, FileRange, FileSystemEdit,
23 Query, RootChange, SourceChange, SourceFileEdit, 20 Query, RootChange, SourceChange, SourceFileEdit,
24 symbol_index::{FileSymbol, LibrarySymbolsQuery}, 21 symbol_index::{FileSymbol, LibrarySymbolsQuery},
22 rename::rename
25}; 23};
26 24
27impl db::RootDatabase { 25impl db::RootDatabase {
@@ -234,94 +232,11 @@ impl db::RootDatabase {
234 .collect() 232 .collect()
235 } 233 }
236 234
237<<<<<<< HEAD 235 pub(crate) fn rename(&self, position: FilePosition, new_name: &str) -> Option<SourceChange> {
238 pub(crate) fn rename(&self, position: FilePosition, new_name: &str) -> Vec<SourceFileEdit> { 236 rename(self, position, new_name)
239 self.find_all_refs(position)
240 .iter()
241 .map(|(file_id, text_range)| SourceFileEdit {
242 file_id: *file_id,
243=======
244 pub(crate) fn rename(
245 &self,
246 position: FilePosition,
247 new_name: &str,
248 ) -> Cancelable<Option<SourceChange>> {
249 let mut source_file_edits = Vec::new();
250 let mut file_system_edits = Vec::new();
251
252 let source_file = self.source_file(position.file_id);
253 let syntax = source_file.syntax();
254 // We are rename a mod
255 if let (Some(ast_module), Some(name)) = (
256 find_node_at_offset::<ast::Module>(syntax, position.offset),
257 find_node_at_offset::<ast::Name>(syntax, position.offset),
258 ) {
259 if let Some(module) = module_from_declaration(self, position.file_id, &ast_module)? {
260 let (file_id, module_source) = module.definition_source(self)?;
261 match module_source {
262 ModuleSource::SourceFile(..) => {
263 let move_file = FileSystemEdit::MoveFile {
264 src: file_id,
265 dst_source_root: self.file_source_root(position.file_id),
266 dst_path: self
267 .file_relative_path(file_id)
268 .with_file_name(new_name)
269 .with_extension("rs"),
270 };
271 file_system_edits.push(move_file);
272 }
273 ModuleSource::Module(..) => {}
274 }
275 }
276
277 let edit = SourceFileEdit {
278 file_id: position.file_id,
279>>>>>>> rename mod
280 edit: {
281 let mut builder = ra_text_edit::TextEditBuilder::default();
282 builder.replace(name.syntax().range(), new_name.into());
283 builder.finish()
284 },
285<<<<<<< HEAD
286 })
287 .collect::<Vec<_>>()
288 } 237 }
289 pub(crate) fn index_resolve(&self, name_ref: &ast::NameRef) -> Vec<FileSymbol> {
290=======
291 };
292 source_file_edits.push(edit);
293 }
294 // rename references
295 else {
296 let edit = self
297 .find_all_refs(position)?
298 .iter()
299 .map(|(file_id, text_range)| SourceFileEdit {
300 file_id: *file_id,
301 edit: {
302 let mut builder = ra_text_edit::TextEditBuilder::default();
303 builder.replace(*text_range, new_name.into());
304 builder.finish()
305 },
306 })
307 .collect::<Vec<_>>();
308 if edit.is_empty() {
309 return Ok(None);
310 }
311 238
312 source_file_edits = edit; 239 pub(crate) fn index_resolve(&self, name_ref: &ast::NameRef) -> Vec<FileSymbol> {
313 }
314
315 return Ok(Some(SourceChange {
316 label: "rename".to_string(),
317 source_file_edits,
318 file_system_edits,
319 cursor_position: None,
320 }));
321 }
322
323 pub(crate) fn index_resolve(&self, name_ref: &ast::NameRef) -> Cancelable<Vec<FileSymbol>> {
324>>>>>>> rename mod
325 let name = name_ref.text(); 240 let name = name_ref.text();
326 let mut query = Query::new(name.to_string()); 241 let mut query = Query::new(name.to_string());
327 query.exact(); 242 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;
23mod call_info; 23mod call_info;
24mod syntax_highlighting; 24mod syntax_highlighting;
25mod parent_module; 25mod parent_module;
26mod rename;
26 27
27use std::{fmt, sync::Arc}; 28use std::{fmt, sync::Arc};
28 29
@@ -464,7 +465,7 @@ impl Analysis {
464 &self, 465 &self,
465 position: FilePosition, 466 position: FilePosition,
466 new_name: &str, 467 new_name: &str,
467 ) -> Cancelable<Vec<SourceFileEdit>> { 468 ) -> Cancelable<Option<SourceChange>> {
468 self.with_db(|db| db.rename(position, new_name)) 469 self.with_db(|db| db.rename(position, new_name))
469 } 470 }
470 471
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 @@
1use relative_path::RelativePathBuf;
2
3use hir::{
4 self, ModuleSource, source_binder::module_from_declaration,
5};
6use ra_syntax::{
7 algo::find_node_at_offset,
8 ast,
9 AstNode,
10 SyntaxNode
11};
12
13use crate::{
14 db::RootDatabase,
15 FilePosition,
16 FileSystemEdit,
17 SourceChange,
18 SourceFileEdit,
19};
20use ra_db::{FilesDatabase, SyntaxDatabase};
21use relative_path::RelativePath;
22
23pub(crate) fn rename(
24 db: &RootDatabase,
25 position: FilePosition,
26 new_name: &str,
27) -> Option<SourceChange> {
28 let source_file = db.source_file(position.file_id);
29 let syntax = source_file.syntax();
30
31 if let Some((ast_name, ast_module)) = find_name_and_module_at_offset(syntax, position) {
32 rename_mod(db, ast_name, ast_module, position, new_name)
33 } else {
34 rename_reference(db, position, new_name)
35 }
36}
37
38fn find_name_and_module_at_offset(
39 syntax: &SyntaxNode,
40 position: FilePosition,
41) -> Option<(&ast::Name, &ast::Module)> {
42 let ast_name = find_node_at_offset::<ast::Name>(syntax, position.offset);
43 let ast_name_parent = ast_name
44 .and_then(|n| n.syntax().parent())
45 .and_then(|p| ast::Module::cast(p));
46
47 if let (Some(ast_module), Some(name)) = (ast_name_parent, ast_name) {
48 return Some((name, ast_module));
49 }
50 None
51}
52
53fn rename_mod(
54 db: &RootDatabase,
55 ast_name: &ast::Name,
56 ast_module: &ast::Module,
57 position: FilePosition,
58 new_name: &str,
59) -> Option<SourceChange> {
60 let mut source_file_edits = Vec::new();
61 let mut file_system_edits = Vec::new();
62
63 if let Some(module) = module_from_declaration(db, position.file_id, &ast_module) {
64 let (file_id, module_source) = module.definition_source(db);
65 match module_source {
66 ModuleSource::SourceFile(..) => {
67 let mod_path: RelativePathBuf = db.file_relative_path(file_id);
68 // mod is defined in path/to/dir/mod.rs
69 let dst_path = if mod_path.file_stem() == Some("mod") {
70 mod_path
71 .parent()
72 .and_then(|p| p.parent())
73 .or_else(|| Some(RelativePath::new("")))
74 .map(|p| p.join(new_name).join("mod.rs"))
75 } else {
76 Some(mod_path.with_file_name(new_name).with_extension("rs"))
77 };
78 if let Some(path) = dst_path {
79 let move_file = FileSystemEdit::MoveFile {
80 src: file_id,
81 dst_source_root: db.file_source_root(position.file_id),
82 dst_path: path,
83 };
84 file_system_edits.push(move_file);
85 }
86 }
87 ModuleSource::Module(..) => {}
88 }
89 }
90
91 let edit = SourceFileEdit {
92 file_id: position.file_id,
93 edit: {
94 let mut builder = ra_text_edit::TextEditBuilder::default();
95 builder.replace(ast_name.syntax().range(), new_name.into());
96 builder.finish()
97 },
98 };
99 source_file_edits.push(edit);
100
101 return Some(SourceChange {
102 label: "rename".to_string(),
103 source_file_edits,
104 file_system_edits,
105 cursor_position: None,
106 });
107}
108
109fn rename_reference(
110 db: &RootDatabase,
111 position: FilePosition,
112 new_name: &str,
113) -> Option<SourceChange> {
114 let edit = db
115 .find_all_refs(position)
116 .iter()
117 .map(|(file_id, text_range)| SourceFileEdit {
118 file_id: *file_id,
119 edit: {
120 let mut builder = ra_text_edit::TextEditBuilder::default();
121 builder.replace(*text_range, new_name.into());
122 builder.finish()
123 },
124 })
125 .collect::<Vec<_>>();
126 if edit.is_empty() {
127 return None;
128 }
129
130 return Some(SourceChange {
131 label: "rename".to_string(),
132 source_file_edits: edit,
133 file_system_edits: Vec::new(),
134 cursor_position: None,
135 });
136}
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;
7use test_utils::assert_eq_text; 7use test_utils::assert_eq_text;
8use insta::assert_debug_snapshot_matches; 8use insta::assert_debug_snapshot_matches;
9 9
10mod runnables;
11
12#[test] 10#[test]
13fn test_unresolved_module_diagnostic() { 11fn test_unresolved_module_diagnostic() {
14 let (analysis, file_id) = single_file("mod foo;"); 12 let (analysis, file_id) = single_file("mod foo;");
@@ -182,10 +180,22 @@ fn test_rename_mod() {
182 ); 180 );
183 let new_name = "foo2"; 181 let new_name = "foo2";
184 let source_change = analysis.rename(position, new_name).unwrap(); 182 let source_change = analysis.rename(position, new_name).unwrap();
185 assert_eq_dbg( 183 assert_debug_snapshot_matches!("rename_mod", &source_change);
186 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 })"#, 184}
187 &source_change, 185
186#[test]
187fn test_rename_mod_in_dir() {
188 let (analysis, position) = analysis_and_position(
189 "
190 //- /lib.rs
191 mod fo<|>o;
192 //- /foo/mod.rs
193 // emtpy
194 ",
188 ); 195 );
196 let new_name = "foo2";
197 let source_change = analysis.rename(position, new_name).unwrap();
198 assert_debug_snapshot_matches!("rename_mod_in_dir", &source_change);
189} 199}
190 200
191fn test_rename(text: &str, new_name: &str, expected: &str) { 201fn 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 @@
1Created: 2019-01-16T14:12:39.379431+00:00
2Creator: [email protected]
3Source: crates/ra_ide_api/tests/test/main.rs
4
5Some(
6 SourceChange {
7 label: "rename",
8 source_file_edits: [
9 SourceFileEdit {
10 file_id: FileId(
11 1
12 ),
13 edit: TextEdit {
14 atoms: [
15 AtomTextEdit {
16 delete: [4; 7),
17 insert: "foo2"
18 }
19 ]
20 }
21 }
22 ],
23 file_system_edits: [
24 MoveFile {
25 src: FileId(
26 2
27 ),
28 dst_source_root: SourceRootId(
29 0
30 ),
31 dst_path: "bar/foo2.rs"
32 }
33 ],
34 cursor_position: None
35 }
36)
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 @@
1Created: 2019-01-16T14:12:39.379358+00:00
2Creator: [email protected]
3Source: crates/ra_ide_api/tests/test/main.rs
4
5Some(
6 SourceChange {
7 label: "rename",
8 source_file_edits: [
9 SourceFileEdit {
10 file_id: FileId(
11 1
12 ),
13 edit: TextEdit {
14 atoms: [
15 AtomTextEdit {
16 delete: [4; 7),
17 insert: "foo2"
18 }
19 ]
20 }
21 }
22 ],
23 file_system_edits: [
24 MoveFile {
25 src: FileId(
26 2
27 ),
28 dst_source_root: SourceRootId(
29 0
30 ),
31 dst_path: "foo2/mod.rs"
32 }
33 ],
34 cursor_position: None
35 }
36)