diff options
-rw-r--r-- | crates/ra_hir/src/nameres.rs | 22 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/tests.rs | 32 | ||||
-rw-r--r-- | crates/ra_hir/src/resolve.rs | 7 | ||||
-rw-r--r-- | crates/ra_ide_api/src/completion/complete_path.rs | 16 | ||||
-rw-r--r-- | crates/ra_ide_api/src/completion/snapshots/completion_item__completes_use_paths_across_crates.snap | 22 |
5 files changed, 81 insertions, 18 deletions
diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs index 94f7db024..4b8097235 100644 --- a/crates/ra_hir/src/nameres.rs +++ b/crates/ra_hir/src/nameres.rs | |||
@@ -434,6 +434,14 @@ impl ItemMap { | |||
434 | self.resolve_path_fp(db, original_module, path).0 | 434 | self.resolve_path_fp(db, original_module, path).0 |
435 | } | 435 | } |
436 | 436 | ||
437 | pub(crate) fn resolve_name_in_module(&self, module: Module, name: &Name) -> PerNs<ModuleDef> { | ||
438 | let from_scope = self[module.module_id].items.get(name).map_or(PerNs::none(), |it| it.def); | ||
439 | let from_extern_prelude = | ||
440 | self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it)); | ||
441 | |||
442 | from_scope.combine(from_extern_prelude) | ||
443 | } | ||
444 | |||
437 | // Returns Yes if we are sure that additions to `ItemMap` wouldn't change | 445 | // Returns Yes if we are sure that additions to `ItemMap` wouldn't change |
438 | // the result. | 446 | // the result. |
439 | fn resolve_path_fp( | 447 | fn resolve_path_fp( |
@@ -451,19 +459,7 @@ impl ItemMap { | |||
451 | Some((_, segment)) => segment, | 459 | Some((_, segment)) => segment, |
452 | None => return (PerNs::none(), ReachedFixedPoint::Yes), | 460 | None => return (PerNs::none(), ReachedFixedPoint::Yes), |
453 | }; | 461 | }; |
454 | // Resolve in: | 462 | self.resolve_name_in_module(original_module, &segment.name) |
455 | // - current module / scope | ||
456 | // - extern prelude | ||
457 | match self[original_module.module_id].items.get(&segment.name) { | ||
458 | Some(res) if !res.def.is_none() => res.def, | ||
459 | _ => { | ||
460 | if let Some(def) = self.extern_prelude.get(&segment.name) { | ||
461 | PerNs::types(*def) | ||
462 | } else { | ||
463 | return (PerNs::none(), ReachedFixedPoint::No); | ||
464 | } | ||
465 | } | ||
466 | } | ||
467 | } | 463 | } |
468 | PathKind::Super => { | 464 | PathKind::Super => { |
469 | if let Some(p) = original_module.parent(db) { | 465 | if let Some(p) = original_module.parent(db) { |
diff --git a/crates/ra_hir/src/nameres/tests.rs b/crates/ra_hir/src/nameres/tests.rs index 9b621fbc2..f1a1f5b76 100644 --- a/crates/ra_hir/src/nameres/tests.rs +++ b/crates/ra_hir/src/nameres/tests.rs | |||
@@ -536,6 +536,38 @@ fn reexport_across_crates() { | |||
536 | ); | 536 | ); |
537 | } | 537 | } |
538 | 538 | ||
539 | #[test] | ||
540 | fn values_dont_shadow_extern_crates() { | ||
541 | let mut db = MockDatabase::with_files( | ||
542 | " | ||
543 | //- /main.rs | ||
544 | fn foo() {} | ||
545 | use foo::Bar; | ||
546 | |||
547 | //- /foo/lib.rs | ||
548 | pub struct Bar; | ||
549 | ", | ||
550 | ); | ||
551 | db.set_crate_graph_from_fixture(crate_graph! { | ||
552 | "main": ("/main.rs", ["foo"]), | ||
553 | "foo": ("/foo/lib.rs", []), | ||
554 | }); | ||
555 | let main_id = db.file_id_of("/main.rs"); | ||
556 | |||
557 | let module = crate::source_binder::module_from_file_id(&db, main_id).unwrap(); | ||
558 | let krate = module.krate(&db).unwrap(); | ||
559 | let item_map = db.item_map(krate); | ||
560 | |||
561 | check_module_item_map( | ||
562 | &item_map, | ||
563 | module.module_id, | ||
564 | " | ||
565 | Bar: t v | ||
566 | foo: v | ||
567 | ", | ||
568 | ); | ||
569 | } | ||
570 | |||
539 | fn check_item_map_is_not_recomputed(initial: &str, file_change: &str) { | 571 | fn check_item_map_is_not_recomputed(initial: &str, file_change: &str) { |
540 | let (mut db, pos) = MockDatabase::with_position(initial); | 572 | let (mut db, pos) = MockDatabase::with_position(initial); |
541 | let module = crate::source_binder::module_from_file_id(&db, pos.file_id).unwrap(); | 573 | let module = crate::source_binder::module_from_file_id(&db, pos.file_id).unwrap(); |
diff --git a/crates/ra_hir/src/resolve.rs b/crates/ra_hir/src/resolve.rs index 3d7ec5683..e8abac5bc 100644 --- a/crates/ra_hir/src/resolve.rs +++ b/crates/ra_hir/src/resolve.rs | |||
@@ -149,10 +149,7 @@ impl Scope { | |||
149 | if let Some(KnownName::SelfParam) = name.as_known_name() { | 149 | if let Some(KnownName::SelfParam) = name.as_known_name() { |
150 | PerNs::types(Resolution::Def(m.module.into())) | 150 | PerNs::types(Resolution::Def(m.module.into())) |
151 | } else { | 151 | } else { |
152 | match m.item_map[m.module.module_id].get(name) { | 152 | m.item_map.resolve_name_in_module(m.module, name).map(Resolution::Def) |
153 | Some(res) => res.def.map(Resolution::Def), | ||
154 | None => PerNs::none(), | ||
155 | } | ||
156 | } | 153 | } |
157 | } | 154 | } |
158 | Scope::GenericParams(gp) => match gp.find_by_name(name) { | 155 | Scope::GenericParams(gp) => match gp.find_by_name(name) { |
@@ -177,7 +174,7 @@ impl Scope { | |||
177 | } | 174 | } |
178 | } | 175 | } |
179 | 176 | ||
180 | fn collect_names(&self, f: &mut FnMut(Name, PerNs<Resolution>)) { | 177 | fn collect_names(&self, f: &mut dyn FnMut(Name, PerNs<Resolution>)) { |
181 | match self { | 178 | match self { |
182 | Scope::ModuleScope(m) => { | 179 | Scope::ModuleScope(m) => { |
183 | // TODO: should we provide `self` here? | 180 | // TODO: should we provide `self` here? |
diff --git a/crates/ra_ide_api/src/completion/complete_path.rs b/crates/ra_ide_api/src/completion/complete_path.rs index c47a14e9f..39aefdb13 100644 --- a/crates/ra_ide_api/src/completion/complete_path.rs +++ b/crates/ra_ide_api/src/completion/complete_path.rs | |||
@@ -186,4 +186,20 @@ mod tests { | |||
186 | ", | 186 | ", |
187 | ); | 187 | ); |
188 | } | 188 | } |
189 | |||
190 | #[test] | ||
191 | fn completes_use_paths_across_crates() { | ||
192 | check_reference_completion( | ||
193 | "completes_use_paths_across_crates", | ||
194 | " | ||
195 | //- /main.rs | ||
196 | use foo::<|>; | ||
197 | |||
198 | //- /foo/lib.rs | ||
199 | pub mod bar { | ||
200 | pub struct S; | ||
201 | } | ||
202 | ", | ||
203 | ); | ||
204 | } | ||
189 | } | 205 | } |
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__completes_use_paths_across_crates.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__completes_use_paths_across_crates.snap new file mode 100644 index 000000000..4b40fcf27 --- /dev/null +++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__completes_use_paths_across_crates.snap | |||
@@ -0,0 +1,22 @@ | |||
1 | --- | ||
2 | created: "2019-02-11T11:53:02.410665254Z" | ||
3 | creator: [email protected] | ||
4 | source: crates/ra_ide_api/src/completion/completion_item.rs | ||
5 | expression: kind_completions | ||
6 | --- | ||
7 | [ | ||
8 | CompletionItem { | ||
9 | completion_kind: Reference, | ||
10 | label: "bar", | ||
11 | kind: Some( | ||
12 | Module | ||
13 | ), | ||
14 | detail: None, | ||
15 | documentation: None, | ||
16 | lookup: None, | ||
17 | insert_text: None, | ||
18 | insert_text_format: PlainText, | ||
19 | source_range: [9; 9), | ||
20 | text_edit: None | ||
21 | } | ||
22 | ] | ||