diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/hir_def/src/find_path.rs | 63 | ||||
-rw-r--r-- | crates/hir_expand/src/eager.rs | 18 | ||||
-rw-r--r-- | crates/ide/src/expand_macro.rs | 23 | ||||
-rw-r--r-- | crates/ide_assists/src/handlers/auto_import.rs | 33 |
4 files changed, 109 insertions, 28 deletions
diff --git a/crates/hir_def/src/find_path.rs b/crates/hir_def/src/find_path.rs index 2c4bbe585..dc3f2908f 100644 --- a/crates/hir_def/src/find_path.rs +++ b/crates/hir_def/src/find_path.rs | |||
@@ -119,8 +119,7 @@ fn find_path_inner( | |||
119 | 119 | ||
120 | // - if the item is the crate root, return `crate` | 120 | // - if the item is the crate root, return `crate` |
121 | let root = def_map.crate_root(db); | 121 | let root = def_map.crate_root(db); |
122 | if item == ItemInNs::Types(ModuleDefId::ModuleId(root)) && def_map.block_id().is_none() { | 122 | if item == ItemInNs::Types(ModuleDefId::ModuleId(root)) { |
123 | // FIXME: the `block_id()` check should be unnecessary, but affects the result | ||
124 | return Some(ModPath::from_segments(PathKind::Crate, Vec::new())); | 123 | return Some(ModPath::from_segments(PathKind::Crate, Vec::new())); |
125 | } | 124 | } |
126 | 125 | ||
@@ -131,7 +130,7 @@ fn find_path_inner( | |||
131 | } | 130 | } |
132 | 131 | ||
133 | // - if the item is the crate root of a dependency crate, return the name from the extern prelude | 132 | // - if the item is the crate root of a dependency crate, return the name from the extern prelude |
134 | for (name, def_id) in def_map.extern_prelude() { | 133 | for (name, def_id) in root.def_map(db).extern_prelude() { |
135 | if item == ItemInNs::Types(*def_id) { | 134 | if item == ItemInNs::Types(*def_id) { |
136 | let name = scope_name.unwrap_or_else(|| name.clone()); | 135 | let name = scope_name.unwrap_or_else(|| name.clone()); |
137 | return Some(ModPath::from_segments(PathKind::Plain, vec![name])); | 136 | return Some(ModPath::from_segments(PathKind::Plain, vec![name])); |
@@ -298,6 +297,7 @@ fn find_local_import_locations( | |||
298 | let data = &def_map[from.local_id]; | 297 | let data = &def_map[from.local_id]; |
299 | let mut worklist = | 298 | let mut worklist = |
300 | data.children.values().map(|child| def_map.module_id(*child)).collect::<Vec<_>>(); | 299 | data.children.values().map(|child| def_map.module_id(*child)).collect::<Vec<_>>(); |
300 | // FIXME: do we need to traverse out of block expressions here? | ||
301 | for ancestor in iter::successors(from.containing_module(db), |m| m.containing_module(db)) { | 301 | for ancestor in iter::successors(from.containing_module(db), |m| m.containing_module(db)) { |
302 | worklist.push(ancestor); | 302 | worklist.push(ancestor); |
303 | } | 303 | } |
@@ -947,10 +947,11 @@ fn main() { | |||
947 | $0 | 947 | $0 |
948 | } | 948 | } |
949 | "#, | 949 | "#, |
950 | // FIXME: these could use fewer/better prefixes | ||
950 | "module::CompleteMe", | 951 | "module::CompleteMe", |
951 | "module::CompleteMe", | ||
952 | "crate::module::CompleteMe", | 952 | "crate::module::CompleteMe", |
953 | "self::module::CompleteMe", | 953 | "crate::module::CompleteMe", |
954 | "crate::module::CompleteMe", | ||
954 | ) | 955 | ) |
955 | } | 956 | } |
956 | 957 | ||
@@ -978,6 +979,28 @@ mod bar { | |||
978 | } | 979 | } |
979 | 980 | ||
980 | #[test] | 981 | #[test] |
982 | fn from_inside_module_with_inner_items() { | ||
983 | check_found_path( | ||
984 | r#" | ||
985 | mod baz { | ||
986 | pub struct Foo {} | ||
987 | } | ||
988 | |||
989 | mod bar { | ||
990 | fn bar() { | ||
991 | fn inner() {} | ||
992 | $0 | ||
993 | } | ||
994 | } | ||
995 | "#, | ||
996 | "crate::baz::Foo", | ||
997 | "crate::baz::Foo", | ||
998 | "crate::baz::Foo", | ||
999 | "crate::baz::Foo", | ||
1000 | ) | ||
1001 | } | ||
1002 | |||
1003 | #[test] | ||
981 | fn recursive_pub_mod_reexport() { | 1004 | fn recursive_pub_mod_reexport() { |
982 | cov_mark::check!(recursive_imports); | 1005 | cov_mark::check!(recursive_imports); |
983 | check_found_path( | 1006 | check_found_path( |
@@ -1004,4 +1027,34 @@ pub mod name { | |||
1004 | "self::name::AsName", | 1027 | "self::name::AsName", |
1005 | ); | 1028 | ); |
1006 | } | 1029 | } |
1030 | |||
1031 | #[test] | ||
1032 | fn extern_crate() { | ||
1033 | check_found_path( | ||
1034 | r#" | ||
1035 | //- /main.rs crate:main deps:dep | ||
1036 | $0 | ||
1037 | //- /dep.rs crate:dep | ||
1038 | "#, | ||
1039 | "dep", | ||
1040 | "dep", | ||
1041 | "dep", | ||
1042 | "dep", | ||
1043 | ); | ||
1044 | |||
1045 | check_found_path( | ||
1046 | r#" | ||
1047 | //- /main.rs crate:main deps:dep | ||
1048 | fn f() { | ||
1049 | fn inner() {} | ||
1050 | $0 | ||
1051 | } | ||
1052 | //- /dep.rs crate:dep | ||
1053 | "#, | ||
1054 | "dep", | ||
1055 | "dep", | ||
1056 | "dep", | ||
1057 | "dep", | ||
1058 | ); | ||
1059 | } | ||
1007 | } | 1060 | } |
diff --git a/crates/hir_expand/src/eager.rs b/crates/hir_expand/src/eager.rs index a5ac32d3c..f12132f84 100644 --- a/crates/hir_expand/src/eager.rs +++ b/crates/hir_expand/src/eager.rs | |||
@@ -29,7 +29,7 @@ use base_db::CrateId; | |||
29 | use mbe::ExpandResult; | 29 | use mbe::ExpandResult; |
30 | use parser::FragmentKind; | 30 | use parser::FragmentKind; |
31 | use std::sync::Arc; | 31 | use std::sync::Arc; |
32 | use syntax::{algo::SyntaxRewriter, SyntaxNode}; | 32 | use syntax::{ted, SyntaxNode}; |
33 | 33 | ||
34 | #[derive(Debug)] | 34 | #[derive(Debug)] |
35 | pub struct ErrorEmitted { | 35 | pub struct ErrorEmitted { |
@@ -192,10 +192,10 @@ fn eager_macro_recur( | |||
192 | macro_resolver: &dyn Fn(ast::Path) -> Option<MacroDefId>, | 192 | macro_resolver: &dyn Fn(ast::Path) -> Option<MacroDefId>, |
193 | mut diagnostic_sink: &mut dyn FnMut(mbe::ExpandError), | 193 | mut diagnostic_sink: &mut dyn FnMut(mbe::ExpandError), |
194 | ) -> Result<SyntaxNode, ErrorEmitted> { | 194 | ) -> Result<SyntaxNode, ErrorEmitted> { |
195 | let original = curr.value.clone(); | 195 | let original = curr.value.clone().clone_for_update(); |
196 | 196 | ||
197 | let children = curr.value.descendants().filter_map(ast::MacroCall::cast); | 197 | let children = original.descendants().filter_map(ast::MacroCall::cast); |
198 | let mut rewriter = SyntaxRewriter::default(); | 198 | let mut replacements = Vec::new(); |
199 | 199 | ||
200 | // Collect replacement | 200 | // Collect replacement |
201 | for child in children { | 201 | for child in children { |
@@ -214,6 +214,7 @@ fn eager_macro_recur( | |||
214 | .into(); | 214 | .into(); |
215 | db.parse_or_expand(id.as_file()) | 215 | db.parse_or_expand(id.as_file()) |
216 | .expect("successful macro expansion should be parseable") | 216 | .expect("successful macro expansion should be parseable") |
217 | .clone_for_update() | ||
217 | } | 218 | } |
218 | MacroDefKind::Declarative(_) | 219 | MacroDefKind::Declarative(_) |
219 | | MacroDefKind::BuiltIn(..) | 220 | | MacroDefKind::BuiltIn(..) |
@@ -227,15 +228,14 @@ fn eager_macro_recur( | |||
227 | } | 228 | } |
228 | }; | 229 | }; |
229 | 230 | ||
230 | // check if the whole original sytnax is replaced | 231 | // check if the whole original syntax is replaced |
231 | // Note that SyntaxRewriter cannot replace the root node itself | ||
232 | if child.syntax() == &original { | 232 | if child.syntax() == &original { |
233 | return Ok(insert); | 233 | return Ok(insert); |
234 | } | 234 | } |
235 | 235 | ||
236 | rewriter.replace(child.syntax(), &insert); | 236 | replacements.push((child, insert)); |
237 | } | 237 | } |
238 | 238 | ||
239 | let res = rewriter.rewrite(&original); | 239 | replacements.into_iter().rev().for_each(|(old, new)| ted::replace(old.syntax(), new)); |
240 | Ok(res) | 240 | Ok(original) |
241 | } | 241 | } |
diff --git a/crates/ide/src/expand_macro.rs b/crates/ide/src/expand_macro.rs index be0ee03bf..eebae5ebe 100644 --- a/crates/ide/src/expand_macro.rs +++ b/crates/ide/src/expand_macro.rs | |||
@@ -3,9 +3,7 @@ use std::iter; | |||
3 | use hir::Semantics; | 3 | use hir::Semantics; |
4 | use ide_db::RootDatabase; | 4 | use ide_db::RootDatabase; |
5 | use syntax::{ | 5 | use syntax::{ |
6 | algo::{find_node_at_offset, SyntaxRewriter}, | 6 | algo::find_node_at_offset, ast, ted, AstNode, NodeOrToken, SyntaxKind, SyntaxKind::*, |
7 | ast, AstNode, NodeOrToken, SyntaxKind, | ||
8 | SyntaxKind::*, | ||
9 | SyntaxNode, WalkEvent, T, | 7 | SyntaxNode, WalkEvent, T, |
10 | }; | 8 | }; |
11 | 9 | ||
@@ -46,26 +44,23 @@ fn expand_macro_recur( | |||
46 | sema: &Semantics<RootDatabase>, | 44 | sema: &Semantics<RootDatabase>, |
47 | macro_call: &ast::MacroCall, | 45 | macro_call: &ast::MacroCall, |
48 | ) -> Option<SyntaxNode> { | 46 | ) -> Option<SyntaxNode> { |
49 | let mut expanded = sema.expand(macro_call)?; | 47 | let expanded = sema.expand(macro_call)?.clone_for_update(); |
50 | 48 | ||
51 | let children = expanded.descendants().filter_map(ast::MacroCall::cast); | 49 | let children = expanded.descendants().filter_map(ast::MacroCall::cast); |
52 | let mut rewriter = SyntaxRewriter::default(); | 50 | let mut replacements = Vec::new(); |
53 | 51 | ||
54 | for child in children.into_iter() { | 52 | for child in children { |
55 | if let Some(new_node) = expand_macro_recur(sema, &child) { | 53 | if let Some(new_node) = expand_macro_recur(sema, &child) { |
56 | // Replace the whole node if it is root | 54 | // check if the whole original syntax is replaced |
57 | // `replace_descendants` will not replace the parent node | ||
58 | // but `SyntaxNode::descendants include itself | ||
59 | if expanded == *child.syntax() { | 55 | if expanded == *child.syntax() { |
60 | expanded = new_node; | 56 | return Some(new_node); |
61 | } else { | ||
62 | rewriter.replace(child.syntax(), &new_node) | ||
63 | } | 57 | } |
58 | replacements.push((child, new_node)); | ||
64 | } | 59 | } |
65 | } | 60 | } |
66 | 61 | ||
67 | let res = rewriter.rewrite(&expanded); | 62 | replacements.into_iter().rev().for_each(|(old, new)| ted::replace(old.syntax(), new)); |
68 | Some(res) | 63 | Some(expanded) |
69 | } | 64 | } |
70 | 65 | ||
71 | // FIXME: It would also be cool to share logic here and in the mbe tests, | 66 | // FIXME: It would also be cool to share logic here and in the mbe tests, |
diff --git a/crates/ide_assists/src/handlers/auto_import.rs b/crates/ide_assists/src/handlers/auto_import.rs index 5ccd7f7a2..49aa70f74 100644 --- a/crates/ide_assists/src/handlers/auto_import.rs +++ b/crates/ide_assists/src/handlers/auto_import.rs | |||
@@ -934,4 +934,37 @@ fn main() { | |||
934 | ", | 934 | ", |
935 | ); | 935 | ); |
936 | } | 936 | } |
937 | |||
938 | #[test] | ||
939 | fn inner_items() { | ||
940 | check_assist( | ||
941 | auto_import, | ||
942 | r#" | ||
943 | mod baz { | ||
944 | pub struct Foo {} | ||
945 | } | ||
946 | |||
947 | mod bar { | ||
948 | fn bar() { | ||
949 | Foo$0; | ||
950 | println!("Hallo"); | ||
951 | } | ||
952 | } | ||
953 | "#, | ||
954 | r#" | ||
955 | mod baz { | ||
956 | pub struct Foo {} | ||
957 | } | ||
958 | |||
959 | mod bar { | ||
960 | use crate::baz::Foo; | ||
961 | |||
962 | fn bar() { | ||
963 | Foo; | ||
964 | println!("Hallo"); | ||
965 | } | ||
966 | } | ||
967 | "#, | ||
968 | ); | ||
969 | } | ||
937 | } | 970 | } |