Unnamed repository; edit this file 'description' to name the repository.
-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 699231fd37..7c11fb9d13 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 957a5cf2e2..3e1922750b 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 f8efc80223..e4702c113b 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 da9c13740b..14890364d0 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 6047f770d4..3770103cda 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 364405f56a..121e5a0a24 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 583e26c136..512fe7e042 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 43d957412b..ca7874c368 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 ad1ce453ec..f699f999ba 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 1a00e29384..87ad5844c6 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,
+ },
],
),
]