Skip to content

Commit d895e9e

Browse files
committed
Auto merge of rust-lang#15477 - Veykril:import-alias-symbols, r=Veykril
feat: Record import aliases in symbol index Fixes rust-lang/rust-analyzer#7938
2 parents 44cf174 + eb6244c commit d895e9e

File tree

10 files changed

+360
-18
lines changed

10 files changed

+360
-18
lines changed

crates/hir-def/src/item_scope.rs

+70-4
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ use syntax::ast;
1616

1717
use crate::{
1818
db::DefDatabase, per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType, ConstId,
19-
ExternCrateId, HasModule, ImplId, LocalModuleId, MacroId, ModuleDefId, ModuleId, TraitId,
20-
UseId,
19+
ExternCrateId, HasModule, ImplId, LocalModuleId, Lookup, MacroId, ModuleDefId, ModuleId,
20+
TraitId, UseId,
2121
};
2222

2323
#[derive(Debug, Default)]
@@ -55,7 +55,7 @@ pub enum ImportOrDef {
5555
ExternCrate(ExternCrateId),
5656
Def(ModuleDefId),
5757
}
58-
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
58+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
5959
pub struct ImportId {
6060
pub import: UseId,
6161
pub idx: Idx<ast::UseTree>,
@@ -142,11 +142,77 @@ impl ItemScope {
142142
.chain(self.values.keys())
143143
.chain(self.macros.keys())
144144
.chain(self.unresolved.iter())
145-
.sorted()
146145
.unique()
146+
.sorted()
147147
.map(move |name| (name, self.get(name)))
148148
}
149149

150+
pub fn imports(&self) -> impl Iterator<Item = ImportId> + '_ {
151+
self.use_imports_types
152+
.keys()
153+
.copied()
154+
.filter_map(ImportOrExternCrate::into_import)
155+
.chain(self.use_imports_values.keys().copied())
156+
.chain(self.use_imports_macros.keys().copied())
157+
.unique()
158+
.sorted()
159+
}
160+
161+
pub fn fully_resolve_import(&self, db: &dyn DefDatabase, mut import: ImportId) -> PerNs {
162+
let mut res = PerNs::none();
163+
164+
let mut def_map;
165+
let mut scope = self;
166+
while let Some(&m) = scope.use_imports_macros.get(&import) {
167+
match m {
168+
ImportOrDef::Import(i) => {
169+
let module_id = i.import.lookup(db).container;
170+
def_map = module_id.def_map(db);
171+
scope = &def_map[module_id.local_id].scope;
172+
import = i;
173+
}
174+
ImportOrDef::Def(ModuleDefId::MacroId(def)) => {
175+
res.macros = Some((def, Visibility::Public, None));
176+
break;
177+
}
178+
_ => break,
179+
}
180+
}
181+
let mut scope = self;
182+
while let Some(&m) = scope.use_imports_types.get(&ImportOrExternCrate::Import(import)) {
183+
match m {
184+
ImportOrDef::Import(i) => {
185+
let module_id = i.import.lookup(db).container;
186+
def_map = module_id.def_map(db);
187+
scope = &def_map[module_id.local_id].scope;
188+
import = i;
189+
}
190+
ImportOrDef::Def(def) => {
191+
res.types = Some((def, Visibility::Public, None));
192+
break;
193+
}
194+
_ => break,
195+
}
196+
}
197+
let mut scope = self;
198+
while let Some(&m) = scope.use_imports_values.get(&import) {
199+
match m {
200+
ImportOrDef::Import(i) => {
201+
let module_id = i.import.lookup(db).container;
202+
def_map = module_id.def_map(db);
203+
scope = &def_map[module_id.local_id].scope;
204+
import = i;
205+
}
206+
ImportOrDef::Def(def) => {
207+
res.values = Some((def, Visibility::Public, None));
208+
break;
209+
}
210+
_ => break,
211+
}
212+
}
213+
res
214+
}
215+
150216
pub fn declarations(&self) -> impl Iterator<Item = ModuleDefId> + '_ {
151217
self.declarations.iter().copied()
152218
}

crates/hir-def/src/item_tree.rs

+13
Original file line numberDiff line numberDiff line change
@@ -773,6 +773,19 @@ impl Use {
773773
lower::lower_use_tree(db, &hygiene, ast_use_tree).expect("failed to lower use tree");
774774
source_map[index].clone()
775775
}
776+
/// Maps a `UseTree` contained in this import back to its AST node.
777+
pub fn use_tree_source_map(
778+
&self,
779+
db: &dyn DefDatabase,
780+
file_id: HirFileId,
781+
) -> Arena<ast::UseTree> {
782+
// Re-lower the AST item and get the source map.
783+
// Note: The AST unwraps are fine, since if they fail we should have never obtained `index`.
784+
let ast = InFile::new(file_id, self.ast_id).to_node(db.upcast());
785+
let ast_use_tree = ast.use_tree().expect("missing `use_tree`");
786+
let hygiene = Hygiene::new(db.upcast(), file_id);
787+
lower::lower_use_tree(db, &hygiene, ast_use_tree).expect("failed to lower use tree").1
788+
}
776789
}
777790

778791
#[derive(Clone, Copy, Debug, Eq, PartialEq)]

crates/hir-def/src/item_tree/lower.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -780,7 +780,7 @@ impl UseTreeLowering<'_> {
780780
}
781781
}
782782

783-
pub(super) fn lower_use_tree(
783+
pub(crate) fn lower_use_tree(
784784
db: &dyn DefDatabase,
785785
hygiene: &Hygiene,
786786
tree: ast::UseTree,

crates/hir-def/src/per_ns.rs

+7
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,13 @@ use crate::{
99
MacroId, ModuleDefId,
1010
};
1111

12+
#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)]
13+
pub enum Namespace {
14+
Types,
15+
Values,
16+
Macros,
17+
}
18+
1219
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1320
pub struct PerNs {
1421
pub types: Option<(ModuleDefId, Visibility, Option<ImportOrExternCrate>)>,

crates/hir-def/src/src.rs

+17-2
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ use la_arena::ArenaMap;
55
use syntax::ast;
66

77
use crate::{
8-
db::DefDatabase, item_tree::ItemTreeNode, AssocItemLoc, ItemLoc, Macro2Loc, MacroRulesLoc,
9-
ProcMacroLoc,
8+
db::DefDatabase, item_tree::ItemTreeNode, AssocItemLoc, ItemLoc, Lookup, Macro2Loc,
9+
MacroRulesLoc, ProcMacroLoc, UseId,
1010
};
1111

1212
pub trait HasSource {
@@ -83,3 +83,18 @@ pub trait HasChildSource<ChildId> {
8383
type Value;
8484
fn child_source(&self, db: &dyn DefDatabase) -> InFile<ArenaMap<ChildId, Self::Value>>;
8585
}
86+
87+
impl HasChildSource<la_arena::Idx<ast::UseTree>> for UseId {
88+
type Value = ast::UseTree;
89+
fn child_source(
90+
&self,
91+
db: &dyn DefDatabase,
92+
) -> InFile<ArenaMap<la_arena::Idx<ast::UseTree>, Self::Value>> {
93+
let loc = &self.lookup(db);
94+
let use_ = &loc.id.item_tree(db)[loc.id.value];
95+
InFile::new(
96+
loc.id.file_id(),
97+
use_.use_tree_source_map(db, loc.id.file_id()).into_iter().collect(),
98+
)
99+
}
100+
}

crates/hir/src/attrs.rs

+1-7
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use hir_def::{
44
attr::{AttrsWithOwner, Documentation},
55
item_scope::ItemInNs,
66
path::{ModPath, Path},
7+
per_ns::Namespace,
78
resolver::{HasResolver, Resolver, TypeNs},
89
AssocItemId, AttrDefId, GenericParamId, ModuleDefId,
910
};
@@ -28,13 +29,6 @@ pub trait HasAttrs {
2829
) -> Option<DocLinkDef>;
2930
}
3031

31-
#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)]
32-
pub enum Namespace {
33-
Types,
34-
Values,
35-
Macros,
36-
}
37-
3832
/// Subset of `ide_db::Definition` that doc links can resolve to.
3933
pub enum DocLinkDef {
4034
ModuleDef(ModuleDef),

crates/hir/src/lib.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ use triomphe::Arc;
8888
use crate::db::{DefDatabase, HirDatabase};
8989

9090
pub use crate::{
91-
attrs::{DocLinkDef, HasAttrs, Namespace},
91+
attrs::{DocLinkDef, HasAttrs},
9292
diagnostics::{
9393
AnyDiagnostic, BreakOutsideOfLoop, CaseType, ExpectedFunction, InactiveCode,
9494
IncoherentImpl, IncorrectCase, InvalidDeriveTarget, MacroDefError, MacroError,
@@ -122,6 +122,7 @@ pub use {
122122
lang_item::LangItem,
123123
nameres::{DefMap, ModuleSource},
124124
path::{ModPath, PathKind},
125+
per_ns::Namespace,
125126
type_ref::{Mutability, TypeRef},
126127
visibility::Visibility,
127128
// FIXME: This is here since some queries take it as input that are used

crates/hir/src/symbols.rs

+38-2
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22
33
use base_db::FileRange;
44
use hir_def::{
5-
src::HasSource, AdtId, AssocItemId, DefWithBodyId, HasModule, ImplId, Lookup, MacroId,
6-
ModuleDefId, ModuleId, TraitId,
5+
item_scope::ItemInNs,
6+
src::{HasChildSource, HasSource},
7+
AdtId, AssocItemId, DefWithBodyId, HasModule, ImplId, Lookup, MacroId, ModuleDefId, ModuleId,
8+
TraitId,
79
};
810
use hir_expand::{HirFileId, InFile};
911
use hir_ty::db::HirDatabase;
@@ -167,6 +169,40 @@ impl<'a> SymbolCollector<'a> {
167169
self.collect_from_impl(impl_id);
168170
}
169171

172+
// Record renamed imports.
173+
// In case it imports multiple items under different namespaces we just pick one arbitrarily
174+
// for now.
175+
for id in scope.imports() {
176+
let loc = id.import.lookup(self.db.upcast());
177+
loc.id.item_tree(self.db.upcast());
178+
let source = id.import.child_source(self.db.upcast());
179+
let Some(use_tree_src) = source.value.get(id.idx) else { continue };
180+
let Some(rename) = use_tree_src.rename() else { continue };
181+
let Some(name) = rename.name() else { continue };
182+
183+
let res = scope.fully_resolve_import(self.db.upcast(), id);
184+
res.iter_items().for_each(|(item, _)| {
185+
let def = match item {
186+
ItemInNs::Types(def) | ItemInNs::Values(def) => def,
187+
ItemInNs::Macros(def) => ModuleDefId::from(def),
188+
}
189+
.into();
190+
let dec_loc = DeclarationLocation {
191+
hir_file_id: source.file_id,
192+
ptr: SyntaxNodePtr::new(use_tree_src.syntax()),
193+
name_ptr: SyntaxNodePtr::new(name.syntax()),
194+
};
195+
196+
self.symbols.push(FileSymbol {
197+
name: name.text().into(),
198+
def,
199+
container_name: self.current_container_name.clone(),
200+
loc: dec_loc,
201+
is_alias: false,
202+
});
203+
});
204+
}
205+
170206
for const_id in scope.unnamed_consts() {
171207
self.collect_from_body(const_id);
172208
}

crates/ide-db/src/symbol_index.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -419,9 +419,16 @@ const CONST_WITH_INNER: () = {
419419
420420
mod b_mod;
421421
422+
423+
use define_struct as really_define_struct;
424+
use Macro as ItemLikeMacro;
425+
use Macro as Trait; // overlay namespaces
422426
//- /b_mod.rs
423427
struct StructInModB;
424-
"#,
428+
use super::Macro as SuperItemLikeMacro;
429+
use crate::b_mod::StructInModB as ThisStruct;
430+
use crate::Trait as IsThisJustATrait;
431+
"#,
425432
);
426433

427434
let symbols: Vec<_> = Crate::from(db.test_crate())

0 commit comments

Comments
 (0)