]> git.lizzy.rs Git - rust.git/commitdiff
use extern prelude in Resolver
authorAleksey Kladov <aleksey.kladov@gmail.com>
Mon, 11 Feb 2019 12:39:26 +0000 (15:39 +0300)
committerAleksey Kladov <aleksey.kladov@gmail.com>
Mon, 11 Feb 2019 12:41:39 +0000 (15:41 +0300)
This fixes two bugs:

- completion for paths works again
- we handle extern prelude shadowing more correctly

crates/ra_hir/src/nameres.rs
crates/ra_hir/src/nameres/tests.rs
crates/ra_hir/src/resolve.rs
crates/ra_ide_api/src/completion/complete_path.rs
crates/ra_ide_api/src/completion/snapshots/completion_item__completes_use_paths_across_crates.snap [new file with mode: 0644]

index 94f7db0241df8674fc23d1db0229162e45f89baa..4b80972353a4ab66d851592c93b84c1c47f56ee3 100644 (file)
@@ -434,6 +434,14 @@ pub(crate) fn resolve_path(
         self.resolve_path_fp(db, original_module, path).0
     }
 
+    pub(crate) fn resolve_name_in_module(&self, module: Module, name: &Name) -> PerNs<ModuleDef> {
+        let from_scope = self[module.module_id].items.get(name).map_or(PerNs::none(), |it| it.def);
+        let from_extern_prelude =
+            self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it));
+
+        from_scope.combine(from_extern_prelude)
+    }
+
     // Returns Yes if we are sure that additions to `ItemMap` wouldn't change
     // the result.
     fn resolve_path_fp(
@@ -451,19 +459,7 @@ fn resolve_path_fp(
                     Some((_, segment)) => segment,
                     None => return (PerNs::none(), ReachedFixedPoint::Yes),
                 };
-                // Resolve in:
-                //  - current module / scope
-                //  - extern prelude
-                match self[original_module.module_id].items.get(&segment.name) {
-                    Some(res) if !res.def.is_none() => res.def,
-                    _ => {
-                        if let Some(def) = self.extern_prelude.get(&segment.name) {
-                            PerNs::types(*def)
-                        } else {
-                            return (PerNs::none(), ReachedFixedPoint::No);
-                        }
-                    }
-                }
+                self.resolve_name_in_module(original_module, &segment.name)
             }
             PathKind::Super => {
                 if let Some(p) = original_module.parent(db) {
index 9b621fbc27ead15849aa0149a67545c93b7089e6..f1a1f5b76904e72e27695a803095261373b9cc3f 100644 (file)
@@ -536,6 +536,38 @@ fn reexport_across_crates() {
     );
 }
 
+#[test]
+fn values_dont_shadow_extern_crates() {
+    let mut db = MockDatabase::with_files(
+        "
+        //- /main.rs
+        fn foo() {}
+        use foo::Bar;
+
+        //- /foo/lib.rs
+        pub struct Bar;
+        ",
+    );
+    db.set_crate_graph_from_fixture(crate_graph! {
+        "main": ("/main.rs", ["foo"]),
+        "foo": ("/foo/lib.rs", []),
+    });
+    let main_id = db.file_id_of("/main.rs");
+
+    let module = crate::source_binder::module_from_file_id(&db, main_id).unwrap();
+    let krate = module.krate(&db).unwrap();
+    let item_map = db.item_map(krate);
+
+    check_module_item_map(
+        &item_map,
+        module.module_id,
+        "
+        Bar: t v
+        foo: v
+        ",
+    );
+}
+
 fn check_item_map_is_not_recomputed(initial: &str, file_change: &str) {
     let (mut db, pos) = MockDatabase::with_position(initial);
     let module = crate::source_binder::module_from_file_id(&db, pos.file_id).unwrap();
index 3d7ec5683d2760698d395018dd687a82623e137c..e8abac5bc95cdef22cf7185714aa909bc53671d3 100644 (file)
@@ -149,10 +149,7 @@ fn resolve_name(&self, name: &Name) -> PerNs<Resolution> {
                 if let Some(KnownName::SelfParam) = name.as_known_name() {
                     PerNs::types(Resolution::Def(m.module.into()))
                 } else {
-                    match m.item_map[m.module.module_id].get(name) {
-                        Some(res) => res.def.map(Resolution::Def),
-                        None => PerNs::none(),
-                    }
+                    m.item_map.resolve_name_in_module(m.module, name).map(Resolution::Def)
                 }
             }
             Scope::GenericParams(gp) => match gp.find_by_name(name) {
@@ -177,7 +174,7 @@ fn resolve_name(&self, name: &Name) -> PerNs<Resolution> {
         }
     }
 
-    fn collect_names(&self, f: &mut FnMut(Name, PerNs<Resolution>)) {
+    fn collect_names(&self, f: &mut dyn FnMut(Name, PerNs<Resolution>)) {
         match self {
             Scope::ModuleScope(m) => {
                 // TODO: should we provide `self` here?
index c47a14e9f7d1e0928c9b136dadd40b954799ef2c..39aefdb13c92c7a9145f20b74ac693fd0520a96f 100644 (file)
@@ -186,4 +186,20 @@ fn foo() { let _ = E::<|> }
             ",
         );
     }
+
+    #[test]
+    fn completes_use_paths_across_crates() {
+        check_reference_completion(
+            "completes_use_paths_across_crates",
+            "
+            //- /main.rs
+            use foo::<|>;
+
+            //- /foo/lib.rs
+            pub mod bar {
+                pub struct S;
+            }
+            ",
+        );
+    }
 }
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 (file)
index 0000000..4b40fcf
--- /dev/null
@@ -0,0 +1,22 @@
+---
+created: "2019-02-11T11:53:02.410665254Z"
+creator: insta@0.6.1
+source: crates/ra_ide_api/src/completion/completion_item.rs
+expression: kind_completions
+---
+[
+    CompletionItem {
+        completion_kind: Reference,
+        label: "bar",
+        kind: Some(
+            Module
+        ),
+        detail: None,
+        documentation: None,
+        lookup: None,
+        insert_text: None,
+        insert_text_format: PlainText,
+        source_range: [9; 9),
+        text_edit: None
+    }
+]