about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-08-18 09:47:39 +0000
committerbors <bors@rust-lang.org>2023-08-18 09:47:39 +0000
commitd895e9effaf320a6cc6477cfb1237f5bedee4a3f (patch)
tree4fe8d77dd8a5f8bee16862369c0975762977bb69
parent44cf1745a8d044c00fbe100d14b403a6c029528d (diff)
parenteb6244c5f91884a612c2fd16a2a5439237129f64 (diff)
downloadrust-d895e9effaf320a6cc6477cfb1237f5bedee4a3f.tar.gz
rust-d895e9effaf320a6cc6477cfb1237f5bedee4a3f.zip
Auto merge of #15477 - Veykril:import-alias-symbols, r=Veykril
feat: Record import aliases in symbol index

Fixes https://github.com/rust-lang/rust-analyzer/issues/7938
-rw-r--r--crates/hir-def/src/item_scope.rs74
-rw-r--r--crates/hir-def/src/item_tree.rs13
-rw-r--r--crates/hir-def/src/item_tree/lower.rs2
-rw-r--r--crates/hir-def/src/per_ns.rs7
-rw-r--r--crates/hir-def/src/src.rs19
-rw-r--r--crates/hir/src/attrs.rs8
-rw-r--r--crates/hir/src/lib.rs3
-rw-r--r--crates/hir/src/symbols.rs40
-rw-r--r--crates/ide-db/src/symbol_index.rs9
-rw-r--r--crates/ide-db/src/test_data/test_symbol_index_collection.txt203
10 files changed, 360 insertions, 18 deletions
diff --git a/crates/hir-def/src/item_scope.rs b/crates/hir-def/src/item_scope.rs
index 699231fd378..7c11fb9d136 100644
--- a/crates/hir-def/src/item_scope.rs
+++ b/crates/hir-def/src/item_scope.rs
@@ -16,8 +16,8 @@ use syntax::ast;
 
 use crate::{
     db::DefDatabase, per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType, ConstId,
-    ExternCrateId, HasModule, ImplId, LocalModuleId, MacroId, ModuleDefId, ModuleId, TraitId,
-    UseId,
+    ExternCrateId, HasModule, ImplId, LocalModuleId, Lookup, MacroId, ModuleDefId, ModuleId,
+    TraitId, UseId,
 };
 
 #[derive(Debug, Default)]
@@ -55,7 +55,7 @@ pub enum ImportOrDef {
     ExternCrate(ExternCrateId),
     Def(ModuleDefId),
 }
-#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
 pub struct ImportId {
     pub import: UseId,
     pub idx: Idx<ast::UseTree>,
@@ -142,11 +142,77 @@ impl ItemScope {
             .chain(self.values.keys())
             .chain(self.macros.keys())
             .chain(self.unresolved.iter())
-            .sorted()
             .unique()
+            .sorted()
             .map(move |name| (name, self.get(name)))
     }
 
+    pub fn imports(&self) -> impl Iterator<Item = ImportId> + '_ {
+        self.use_imports_types
+            .keys()
+            .copied()
+            .filter_map(ImportOrExternCrate::into_import)
+            .chain(self.use_imports_values.keys().copied())
+            .chain(self.use_imports_macros.keys().copied())
+            .unique()
+            .sorted()
+    }
+
+    pub fn fully_resolve_import(&self, db: &dyn DefDatabase, mut import: ImportId) -> PerNs {
+        let mut res = PerNs::none();
+
+        let mut def_map;
+        let mut scope = self;
+        while let Some(&m) = scope.use_imports_macros.get(&import) {
+            match m {
+                ImportOrDef::Import(i) => {
+                    let module_id = i.import.lookup(db).container;
+                    def_map = module_id.def_map(db);
+                    scope = &def_map[module_id.local_id].scope;
+                    import = i;
+                }
+                ImportOrDef::Def(ModuleDefId::MacroId(def)) => {
+                    res.macros = Some((def, Visibility::Public, None));
+                    break;
+                }
+                _ => break,
+            }
+        }
+        let mut scope = self;
+        while let Some(&m) = scope.use_imports_types.get(&ImportOrExternCrate::Import(import)) {
+            match m {
+                ImportOrDef::Import(i) => {
+                    let module_id = i.import.lookup(db).container;
+                    def_map = module_id.def_map(db);
+                    scope = &def_map[module_id.local_id].scope;
+                    import = i;
+                }
+                ImportOrDef::Def(def) => {
+                    res.types = Some((def, Visibility::Public, None));
+                    break;
+                }
+                _ => break,
+            }
+        }
+        let mut scope = self;
+        while let Some(&m) = scope.use_imports_values.get(&import) {
+            match m {
+                ImportOrDef::Import(i) => {
+                    let module_id = i.import.lookup(db).container;
+                    def_map = module_id.def_map(db);
+                    scope = &def_map[module_id.local_id].scope;
+                    import = i;
+                }
+                ImportOrDef::Def(def) => {
+                    res.values = Some((def, Visibility::Public, None));
+                    break;
+                }
+                _ => break,
+            }
+        }
+        res
+    }
+
     pub fn declarations(&self) -> impl Iterator<Item = ModuleDefId> + '_ {
         self.declarations.iter().copied()
     }
diff --git a/crates/hir-def/src/item_tree.rs b/crates/hir-def/src/item_tree.rs
index 957a5cf2e2b..3e1922750b9 100644
--- a/crates/hir-def/src/item_tree.rs
+++ b/crates/hir-def/src/item_tree.rs
@@ -773,6 +773,19 @@ impl Use {
             lower::lower_use_tree(db, &hygiene, ast_use_tree).expect("failed to lower use tree");
         source_map[index].clone()
     }
+    /// Maps a `UseTree` contained in this import back to its AST node.
+    pub fn use_tree_source_map(
+        &self,
+        db: &dyn DefDatabase,
+        file_id: HirFileId,
+    ) -> Arena<ast::UseTree> {
+        // Re-lower the AST item and get the source map.
+        // Note: The AST unwraps are fine, since if they fail we should have never obtained `index`.
+        let ast = InFile::new(file_id, self.ast_id).to_node(db.upcast());
+        let ast_use_tree = ast.use_tree().expect("missing `use_tree`");
+        let hygiene = Hygiene::new(db.upcast(), file_id);
+        lower::lower_use_tree(db, &hygiene, ast_use_tree).expect("failed to lower use tree").1
+    }
 }
 
 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
diff --git a/crates/hir-def/src/item_tree/lower.rs b/crates/hir-def/src/item_tree/lower.rs
index f8efc802234..e4702c113b8 100644
--- a/crates/hir-def/src/item_tree/lower.rs
+++ b/crates/hir-def/src/item_tree/lower.rs
@@ -780,7 +780,7 @@ impl UseTreeLowering<'_> {
     }
 }
 
-pub(super) fn lower_use_tree(
+pub(crate) fn lower_use_tree(
     db: &dyn DefDatabase,
     hygiene: &Hygiene,
     tree: ast::UseTree,
diff --git a/crates/hir-def/src/per_ns.rs b/crates/hir-def/src/per_ns.rs
index da9c13740b3..14890364d0b 100644
--- a/crates/hir-def/src/per_ns.rs
+++ b/crates/hir-def/src/per_ns.rs
@@ -9,6 +9,13 @@ use crate::{
     MacroId, ModuleDefId,
 };
 
+#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)]
+pub enum Namespace {
+    Types,
+    Values,
+    Macros,
+}
+
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
 pub struct PerNs {
     pub types: Option<(ModuleDefId, Visibility, Option<ImportOrExternCrate>)>,
diff --git a/crates/hir-def/src/src.rs b/crates/hir-def/src/src.rs
index 6047f770d4d..3770103cda5 100644
--- a/crates/hir-def/src/src.rs
+++ b/crates/hir-def/src/src.rs
@@ -5,8 +5,8 @@ use la_arena::ArenaMap;
 use syntax::ast;
 
 use crate::{
-    db::DefDatabase, item_tree::ItemTreeNode, AssocItemLoc, ItemLoc, Macro2Loc, MacroRulesLoc,
-    ProcMacroLoc,
+    db::DefDatabase, item_tree::ItemTreeNode, AssocItemLoc, ItemLoc, Lookup, Macro2Loc,
+    MacroRulesLoc, ProcMacroLoc, UseId,
 };
 
 pub trait HasSource {
@@ -83,3 +83,18 @@ pub trait HasChildSource<ChildId> {
     type Value;
     fn child_source(&self, db: &dyn DefDatabase) -> InFile<ArenaMap<ChildId, Self::Value>>;
 }
+
+impl HasChildSource<la_arena::Idx<ast::UseTree>> for UseId {
+    type Value = ast::UseTree;
+    fn child_source(
+        &self,
+        db: &dyn DefDatabase,
+    ) -> InFile<ArenaMap<la_arena::Idx<ast::UseTree>, Self::Value>> {
+        let loc = &self.lookup(db);
+        let use_ = &loc.id.item_tree(db)[loc.id.value];
+        InFile::new(
+            loc.id.file_id(),
+            use_.use_tree_source_map(db, loc.id.file_id()).into_iter().collect(),
+        )
+    }
+}
diff --git a/crates/hir/src/attrs.rs b/crates/hir/src/attrs.rs
index 364405f56a8..121e5a0a249 100644
--- a/crates/hir/src/attrs.rs
+++ b/crates/hir/src/attrs.rs
@@ -4,6 +4,7 @@ use hir_def::{
     attr::{AttrsWithOwner, Documentation},
     item_scope::ItemInNs,
     path::{ModPath, Path},
+    per_ns::Namespace,
     resolver::{HasResolver, Resolver, TypeNs},
     AssocItemId, AttrDefId, GenericParamId, ModuleDefId,
 };
@@ -28,13 +29,6 @@ pub trait HasAttrs {
     ) -> Option<DocLinkDef>;
 }
 
-#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)]
-pub enum Namespace {
-    Types,
-    Values,
-    Macros,
-}
-
 /// Subset of `ide_db::Definition` that doc links can resolve to.
 pub enum DocLinkDef {
     ModuleDef(ModuleDef),
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 583e26c136c..512fe7e0428 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -88,7 +88,7 @@ use triomphe::Arc;
 use crate::db::{DefDatabase, HirDatabase};
 
 pub use crate::{
-    attrs::{DocLinkDef, HasAttrs, Namespace},
+    attrs::{DocLinkDef, HasAttrs},
     diagnostics::{
         AnyDiagnostic, BreakOutsideOfLoop, CaseType, ExpectedFunction, InactiveCode,
         IncoherentImpl, IncorrectCase, InvalidDeriveTarget, MacroDefError, MacroError,
@@ -122,6 +122,7 @@ pub use {
         lang_item::LangItem,
         nameres::{DefMap, ModuleSource},
         path::{ModPath, PathKind},
+        per_ns::Namespace,
         type_ref::{Mutability, TypeRef},
         visibility::Visibility,
         // FIXME: This is here since some queries take it as input that are used
diff --git a/crates/hir/src/symbols.rs b/crates/hir/src/symbols.rs
index 43d957412bc..ca7874c3683 100644
--- a/crates/hir/src/symbols.rs
+++ b/crates/hir/src/symbols.rs
@@ -2,8 +2,10 @@
 
 use base_db::FileRange;
 use hir_def::{
-    src::HasSource, AdtId, AssocItemId, DefWithBodyId, HasModule, ImplId, Lookup, MacroId,
-    ModuleDefId, ModuleId, TraitId,
+    item_scope::ItemInNs,
+    src::{HasChildSource, HasSource},
+    AdtId, AssocItemId, DefWithBodyId, HasModule, ImplId, Lookup, MacroId, ModuleDefId, ModuleId,
+    TraitId,
 };
 use hir_expand::{HirFileId, InFile};
 use hir_ty::db::HirDatabase;
@@ -167,6 +169,40 @@ impl<'a> SymbolCollector<'a> {
             self.collect_from_impl(impl_id);
         }
 
+        // Record renamed imports.
+        // In case it imports multiple items under different namespaces we just pick one arbitrarily
+        // for now.
+        for id in scope.imports() {
+            let loc = id.import.lookup(self.db.upcast());
+            loc.id.item_tree(self.db.upcast());
+            let source = id.import.child_source(self.db.upcast());
+            let Some(use_tree_src) = source.value.get(id.idx) else { continue };
+            let Some(rename) = use_tree_src.rename() else { continue };
+            let Some(name) = rename.name() else { continue };
+
+            let res = scope.fully_resolve_import(self.db.upcast(), id);
+            res.iter_items().for_each(|(item, _)| {
+                let def = match item {
+                    ItemInNs::Types(def) | ItemInNs::Values(def) => def,
+                    ItemInNs::Macros(def) => ModuleDefId::from(def),
+                }
+                .into();
+                let dec_loc = DeclarationLocation {
+                    hir_file_id: source.file_id,
+                    ptr: SyntaxNodePtr::new(use_tree_src.syntax()),
+                    name_ptr: SyntaxNodePtr::new(name.syntax()),
+                };
+
+                self.symbols.push(FileSymbol {
+                    name: name.text().into(),
+                    def,
+                    container_name: self.current_container_name.clone(),
+                    loc: dec_loc,
+                    is_alias: false,
+                });
+            });
+        }
+
         for const_id in scope.unnamed_consts() {
             self.collect_from_body(const_id);
         }
diff --git a/crates/ide-db/src/symbol_index.rs b/crates/ide-db/src/symbol_index.rs
index ad1ce453eca..f699f999baf 100644
--- a/crates/ide-db/src/symbol_index.rs
+++ b/crates/ide-db/src/symbol_index.rs
@@ -419,9 +419,16 @@ const CONST_WITH_INNER: () = {
 
 mod b_mod;
 
+
+use define_struct as really_define_struct;
+use Macro as ItemLikeMacro;
+use Macro as Trait; // overlay namespaces
 //- /b_mod.rs
 struct StructInModB;
-        "#,
+use super::Macro as SuperItemLikeMacro;
+use crate::b_mod::StructInModB as ThisStruct;
+use crate::Trait as IsThisJustATrait;
+"#,
         );
 
         let symbols: Vec<_> = Crate::from(db.test_crate())
diff --git a/crates/ide-db/src/test_data/test_symbol_index_collection.txt b/crates/ide-db/src/test_data/test_symbol_index_collection.txt
index 1a00e29384e..87ad5844c64 100644
--- a/crates/ide-db/src/test_data/test_symbol_index_collection.txt
+++ b/crates/ide-db/src/test_data/test_symbol_index_collection.txt
@@ -119,6 +119,35 @@
                 is_alias: false,
             },
             FileSymbol {
+                name: "ItemLikeMacro",
+                def: Macro(
+                    Macro {
+                        id: Macro2Id(
+                            Macro2Id(
+                                0,
+                            ),
+                        ),
+                    },
+                ),
+                loc: DeclarationLocation {
+                    hir_file_id: FileId(
+                        FileId(
+                            0,
+                        ),
+                    ),
+                    ptr: SyntaxNodePtr {
+                        kind: USE_TREE,
+                        range: 654..676,
+                    },
+                    name_ptr: SyntaxNodePtr {
+                        kind: NAME,
+                        range: 663..676,
+                    },
+                },
+                container_name: None,
+                is_alias: false,
+            },
+            FileSymbol {
                 name: "Macro",
                 def: Macro(
                     Macro {
@@ -353,6 +382,35 @@
                 is_alias: false,
             },
             FileSymbol {
+                name: "Trait",
+                def: Macro(
+                    Macro {
+                        id: Macro2Id(
+                            Macro2Id(
+                                0,
+                            ),
+                        ),
+                    },
+                ),
+                loc: DeclarationLocation {
+                    hir_file_id: FileId(
+                        FileId(
+                            0,
+                        ),
+                    ),
+                    ptr: SyntaxNodePtr {
+                        kind: USE_TREE,
+                        range: 682..696,
+                    },
+                    name_ptr: SyntaxNodePtr {
+                        kind: NAME,
+                        range: 691..696,
+                    },
+                },
+                container_name: None,
+                is_alias: false,
+            },
+            FileSymbol {
                 name: "Union",
                 def: Adt(
                     Union(
@@ -552,6 +610,35 @@
                 is_alias: false,
             },
             FileSymbol {
+                name: "really_define_struct",
+                def: Macro(
+                    Macro {
+                        id: MacroRulesId(
+                            MacroRulesId(
+                                1,
+                            ),
+                        ),
+                    },
+                ),
+                loc: DeclarationLocation {
+                    hir_file_id: FileId(
+                        FileId(
+                            0,
+                        ),
+                    ),
+                    ptr: SyntaxNodePtr {
+                        kind: USE_TREE,
+                        range: 611..648,
+                    },
+                    name_ptr: SyntaxNodePtr {
+                        kind: NAME,
+                        range: 628..648,
+                    },
+                },
+                container_name: None,
+                is_alias: false,
+            },
+            FileSymbol {
                 name: "trait_fn",
                 def: Function(
                     Function {
@@ -632,6 +719,35 @@
         },
         [
             FileSymbol {
+                name: "IsThisJustATrait",
+                def: Macro(
+                    Macro {
+                        id: Macro2Id(
+                            Macro2Id(
+                                0,
+                            ),
+                        ),
+                    },
+                ),
+                loc: DeclarationLocation {
+                    hir_file_id: FileId(
+                        FileId(
+                            1,
+                        ),
+                    ),
+                    ptr: SyntaxNodePtr {
+                        kind: USE_TREE,
+                        range: 111..143,
+                    },
+                    name_ptr: SyntaxNodePtr {
+                        kind: NAME,
+                        range: 127..143,
+                    },
+                },
+                container_name: None,
+                is_alias: false,
+            },
+            FileSymbol {
                 name: "StructInModB",
                 def: Adt(
                     Struct(
@@ -660,6 +776,93 @@
                 container_name: None,
                 is_alias: false,
             },
+            FileSymbol {
+                name: "SuperItemLikeMacro",
+                def: Macro(
+                    Macro {
+                        id: Macro2Id(
+                            Macro2Id(
+                                0,
+                            ),
+                        ),
+                    },
+                ),
+                loc: DeclarationLocation {
+                    hir_file_id: FileId(
+                        FileId(
+                            1,
+                        ),
+                    ),
+                    ptr: SyntaxNodePtr {
+                        kind: USE_TREE,
+                        range: 25..59,
+                    },
+                    name_ptr: SyntaxNodePtr {
+                        kind: NAME,
+                        range: 41..59,
+                    },
+                },
+                container_name: None,
+                is_alias: false,
+            },
+            FileSymbol {
+                name: "ThisStruct",
+                def: Adt(
+                    Struct(
+                        Struct {
+                            id: StructId(
+                                3,
+                            ),
+                        },
+                    ),
+                ),
+                loc: DeclarationLocation {
+                    hir_file_id: FileId(
+                        FileId(
+                            1,
+                        ),
+                    ),
+                    ptr: SyntaxNodePtr {
+                        kind: USE_TREE,
+                        range: 65..105,
+                    },
+                    name_ptr: SyntaxNodePtr {
+                        kind: NAME,
+                        range: 95..105,
+                    },
+                },
+                container_name: None,
+                is_alias: false,
+            },
+            FileSymbol {
+                name: "ThisStruct",
+                def: Adt(
+                    Struct(
+                        Struct {
+                            id: StructId(
+                                3,
+                            ),
+                        },
+                    ),
+                ),
+                loc: DeclarationLocation {
+                    hir_file_id: FileId(
+                        FileId(
+                            1,
+                        ),
+                    ),
+                    ptr: SyntaxNodePtr {
+                        kind: USE_TREE,
+                        range: 65..105,
+                    },
+                    name_ptr: SyntaxNodePtr {
+                        kind: NAME,
+                        range: 95..105,
+                    },
+                },
+                container_name: None,
+                is_alias: false,
+            },
         ],
     ),
 ]