Record import aliases in symbol index
This commit is contained in:
parent
637f496a81
commit
eb6244c5f9
@ -16,8 +16,8 @@
|
||||
|
||||
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 @@ pub fn entries(&self) -> impl Iterator<Item = (&Name, PerNs)> + '_ {
|
||||
.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()
|
||||
}
|
||||
|
@ -773,6 +773,19 @@ pub fn use_tree_to_ast(
|
||||
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)]
|
||||
|
@ -780,7 +780,7 @@ fn use_tree(&mut self, kind: UseTreeKind, ast: ast::UseTree) -> UseTree {
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn lower_use_tree(
|
||||
pub(crate) fn lower_use_tree(
|
||||
db: &dyn DefDatabase,
|
||||
hygiene: &Hygiene,
|
||||
tree: ast::UseTree,
|
||||
|
@ -9,6 +9,13 @@
|
||||
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>)>,
|
||||
|
@ -5,8 +5,8 @@
|
||||
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(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
attr::{AttrsWithOwner, Documentation},
|
||||
item_scope::ItemInNs,
|
||||
path::{ModPath, Path},
|
||||
per_ns::Namespace,
|
||||
resolver::{HasResolver, Resolver, TypeNs},
|
||||
AssocItemId, AttrDefId, GenericParamId, ModuleDefId,
|
||||
};
|
||||
@ -28,13 +29,6 @@ fn resolve_doc_path(
|
||||
) -> 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),
|
||||
|
@ -88,7 +88,7 @@
|
||||
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 @@
|
||||
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
|
||||
|
@ -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 @@ fn collect_from_module(&mut self, module_id: ModuleId) {
|
||||
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);
|
||||
}
|
||||
|
@ -419,9 +419,16 @@ mod a_mod {
|
||||
|
||||
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())
|
||||
|
@ -118,6 +118,35 @@
|
||||
container_name: None,
|
||||
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(
|
||||
@ -352,6 +381,35 @@
|
||||
container_name: None,
|
||||
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(
|
||||
@ -551,6 +609,35 @@
|
||||
container_name: None,
|
||||
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(
|
||||
@ -631,6 +718,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(
|
||||
@ -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,
|
||||
},
|
||||
],
|
||||
),
|
||||
]
|
||||
|
Loading…
Reference in New Issue
Block a user