mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-02 06:41:48 +00:00
assign DefIds when lowering
This commit is contained in:
parent
118e11e50b
commit
59f830d3e8
4 changed files with 99 additions and 107 deletions
|
@ -1,9 +1,9 @@
|
||||||
use ra_db::{SourceRootId, LocationIntener, FileId};
|
use ra_db::{SourceRootId, LocationIntener, FileId};
|
||||||
use ra_syntax::{TreeArc, SyntaxKind, SyntaxNode, SourceFile, AstNode, ast};
|
use ra_syntax::{TreeArc, SyntaxNode, SourceFile, AstNode, ast};
|
||||||
use ra_arena::{Arena, RawId, impl_arena_id};
|
use ra_arena::{Arena, RawId, impl_arena_id};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
HirDatabase, PerNs, Def, Function, Struct, Enum, EnumVariant, ImplBlock, Crate,
|
HirDatabase, Def, Function, Struct, Enum, EnumVariant, ImplBlock, Crate,
|
||||||
Module, Trait, Type, Static, Const,
|
Module, Trait, Type, Static, Const,
|
||||||
module_tree::ModuleId,
|
module_tree::ModuleId,
|
||||||
};
|
};
|
||||||
|
@ -238,23 +238,6 @@ impl DefLoc {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DefKind {
|
|
||||||
pub(crate) fn for_syntax_kind(kind: SyntaxKind) -> PerNs<DefKind> {
|
|
||||||
match kind {
|
|
||||||
SyntaxKind::FN_DEF => PerNs::values(DefKind::Function),
|
|
||||||
SyntaxKind::MODULE => PerNs::types(DefKind::Module),
|
|
||||||
SyntaxKind::STRUCT_DEF => PerNs::both(DefKind::Struct, DefKind::StructCtor),
|
|
||||||
SyntaxKind::ENUM_DEF => PerNs::types(DefKind::Enum),
|
|
||||||
// These define items, but don't have their own DefKinds yet:
|
|
||||||
SyntaxKind::TRAIT_DEF => PerNs::types(DefKind::Trait),
|
|
||||||
SyntaxKind::TYPE_DEF => PerNs::types(DefKind::Type),
|
|
||||||
SyntaxKind::CONST_DEF => PerNs::values(DefKind::Const),
|
|
||||||
SyntaxKind::STATIC_DEF => PerNs::values(DefKind::Static),
|
|
||||||
_ => PerNs::none(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Identifier of item within a specific file. This is stable over reparses, so
|
/// Identifier of item within a specific file. This is stable over reparses, so
|
||||||
/// it's OK to use it as a salsa key/value.
|
/// it's OK to use it as a salsa key/value.
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
|
|
@ -21,7 +21,6 @@ use crate::nameres::lower::*;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use rustc_hash::{FxHashMap, FxHashSet};
|
use rustc_hash::{FxHashMap, FxHashSet};
|
||||||
use ra_syntax::SyntaxKind::*;
|
|
||||||
use ra_db::SourceRootId;
|
use ra_db::SourceRootId;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -235,27 +234,12 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Populate explicitly declared items, except modules
|
// Populate explicitly declared items, except modules
|
||||||
for item in input.items.iter() {
|
for (name, &def_id) in input.declarations.iter() {
|
||||||
if item.kind == MODULE {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// depending on the item kind, the location can define something in
|
|
||||||
// the values namespace, the types namespace, or both
|
|
||||||
let kind = DefKind::for_syntax_kind(item.kind);
|
|
||||||
let def_id = kind.map(|k| {
|
|
||||||
let def_loc = DefLoc {
|
|
||||||
kind: k,
|
|
||||||
source_root_id: self.source_root,
|
|
||||||
module_id,
|
|
||||||
source_item_id: item.id,
|
|
||||||
};
|
|
||||||
def_loc.id(self.db)
|
|
||||||
});
|
|
||||||
let resolution = Resolution {
|
let resolution = Resolution {
|
||||||
def_id,
|
def_id,
|
||||||
import: None,
|
import: None,
|
||||||
};
|
};
|
||||||
module_items.items.insert(item.name.clone(), resolution);
|
module_items.items.insert(name.clone(), resolution);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Populate modules
|
// Populate modules
|
||||||
|
|
|
@ -2,52 +2,18 @@ use std::sync::Arc;
|
||||||
|
|
||||||
use ra_syntax::{
|
use ra_syntax::{
|
||||||
SyntaxKind, AstNode, SourceFile, TreeArc, AstPtr,
|
SyntaxKind, AstNode, SourceFile, TreeArc, AstPtr,
|
||||||
ast::{self, ModuleItemOwner},
|
ast::{self, ModuleItemOwner, NameOwner},
|
||||||
};
|
};
|
||||||
use ra_db::SourceRootId;
|
use ra_db::SourceRootId;
|
||||||
use ra_arena::{Arena, RawId, impl_arena_id, map::ArenaMap};
|
use ra_arena::{Arena, RawId, impl_arena_id, map::ArenaMap};
|
||||||
|
use rustc_hash::FxHashMap;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
SourceItemId, Path, ModuleSource, HirDatabase, Name, SourceFileItems,
|
SourceItemId, Path, ModuleSource, HirDatabase, Name, SourceFileItems,
|
||||||
HirFileId, MacroCallLoc, AsName,
|
HirFileId, MacroCallLoc, AsName, PerNs, DefId, DefKind, DefLoc,
|
||||||
module_tree::ModuleId
|
module_tree::ModuleId
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
|
||||||
pub(super) enum Vis {
|
|
||||||
// Priv,
|
|
||||||
Other,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
|
||||||
pub(crate) struct ModuleItem {
|
|
||||||
pub(crate) id: SourceItemId,
|
|
||||||
pub(crate) name: Name,
|
|
||||||
pub(super) kind: SyntaxKind,
|
|
||||||
pub(super) vis: Vis,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ModuleItem {
|
|
||||||
fn new(
|
|
||||||
file_id: HirFileId,
|
|
||||||
file_items: &SourceFileItems,
|
|
||||||
item: &impl ast::NameOwner,
|
|
||||||
) -> Option<ModuleItem> {
|
|
||||||
let name = item.name()?.as_name();
|
|
||||||
let kind = item.syntax().kind();
|
|
||||||
let vis = Vis::Other;
|
|
||||||
let item_id = Some(file_items.id_of_unchecked(item.syntax()));
|
|
||||||
let id = SourceItemId { file_id, item_id };
|
|
||||||
let res = ModuleItem {
|
|
||||||
id,
|
|
||||||
name,
|
|
||||||
kind,
|
|
||||||
vis,
|
|
||||||
};
|
|
||||||
Some(res)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub struct ImportId(RawId);
|
pub struct ImportId(RawId);
|
||||||
impl_arena_id!(ImportId);
|
impl_arena_id!(ImportId);
|
||||||
|
@ -66,7 +32,7 @@ pub(super) struct ImportData {
|
||||||
/// can avoid redoing name resolution.
|
/// can avoid redoing name resolution.
|
||||||
#[derive(Debug, Default, PartialEq, Eq)]
|
#[derive(Debug, Default, PartialEq, Eq)]
|
||||||
pub struct LoweredModule {
|
pub struct LoweredModule {
|
||||||
pub(crate) items: Vec<ModuleItem>,
|
pub(crate) declarations: FxHashMap<Name, PerNs<DefId>>,
|
||||||
pub(super) imports: Arena<ImportId, ImportData>,
|
pub(super) imports: Arena<ImportId, ImportData>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,7 +123,15 @@ impl LoweredModule {
|
||||||
for item in items {
|
for item in items {
|
||||||
match item {
|
match item {
|
||||||
ast::ItemOrMacro::Item(it) => {
|
ast::ItemOrMacro::Item(it) => {
|
||||||
self.add_item(source_map, file_id, &file_items, it);
|
self.add_def_id(
|
||||||
|
source_map,
|
||||||
|
db,
|
||||||
|
source_root_id,
|
||||||
|
module_id,
|
||||||
|
file_id,
|
||||||
|
&file_items,
|
||||||
|
it,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
ast::ItemOrMacro::Macro(macro_call) => {
|
ast::ItemOrMacro::Macro(macro_call) => {
|
||||||
let item_id = file_items.id_of_unchecked(macro_call.syntax());
|
let item_id = file_items.id_of_unchecked(macro_call.syntax());
|
||||||
|
@ -174,54 +148,60 @@ impl LoweredModule {
|
||||||
let file_items = db.file_items(file_id);
|
let file_items = db.file_items(file_id);
|
||||||
//FIXME: expand recursively
|
//FIXME: expand recursively
|
||||||
for item in db.hir_source_file(file_id).items() {
|
for item in db.hir_source_file(file_id).items() {
|
||||||
self.add_item(source_map, file_id, &file_items, item);
|
self.add_def_id(
|
||||||
|
source_map,
|
||||||
|
db,
|
||||||
|
source_root_id,
|
||||||
|
module_id,
|
||||||
|
file_id,
|
||||||
|
&file_items,
|
||||||
|
item,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_item(
|
fn add_def_id(
|
||||||
&mut self,
|
&mut self,
|
||||||
source_map: &mut ImportSourceMap,
|
source_map: &mut ImportSourceMap,
|
||||||
|
db: &impl HirDatabase,
|
||||||
|
source_root_id: SourceRootId,
|
||||||
|
module_id: ModuleId,
|
||||||
file_id: HirFileId,
|
file_id: HirFileId,
|
||||||
file_items: &SourceFileItems,
|
file_items: &SourceFileItems,
|
||||||
item: &ast::ModuleItem,
|
item: &ast::ModuleItem,
|
||||||
) -> Option<()> {
|
) {
|
||||||
match item.kind() {
|
let name = match item.kind() {
|
||||||
ast::ModuleItemKind::StructDef(it) => {
|
ast::ModuleItemKind::StructDef(it) => it.name(),
|
||||||
self.items.push(ModuleItem::new(file_id, file_items, it)?)
|
ast::ModuleItemKind::EnumDef(it) => it.name(),
|
||||||
}
|
ast::ModuleItemKind::FnDef(it) => it.name(),
|
||||||
ast::ModuleItemKind::EnumDef(it) => {
|
ast::ModuleItemKind::TraitDef(it) => it.name(),
|
||||||
self.items.push(ModuleItem::new(file_id, file_items, it)?)
|
ast::ModuleItemKind::TypeDef(it) => it.name(),
|
||||||
}
|
|
||||||
ast::ModuleItemKind::FnDef(it) => {
|
|
||||||
self.items.push(ModuleItem::new(file_id, file_items, it)?)
|
|
||||||
}
|
|
||||||
ast::ModuleItemKind::TraitDef(it) => {
|
|
||||||
self.items.push(ModuleItem::new(file_id, file_items, it)?)
|
|
||||||
}
|
|
||||||
ast::ModuleItemKind::TypeDef(it) => {
|
|
||||||
self.items.push(ModuleItem::new(file_id, file_items, it)?)
|
|
||||||
}
|
|
||||||
ast::ModuleItemKind::ImplBlock(_) => {
|
ast::ModuleItemKind::ImplBlock(_) => {
|
||||||
// impls don't define items
|
// impls don't define items
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ast::ModuleItemKind::UseItem(it) => {
|
||||||
|
self.add_use_item(source_map, it);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
ast::ModuleItemKind::UseItem(it) => self.add_use_item(source_map, it),
|
|
||||||
ast::ModuleItemKind::ExternCrateItem(_) => {
|
ast::ModuleItemKind::ExternCrateItem(_) => {
|
||||||
// TODO
|
// TODO
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
ast::ModuleItemKind::ConstDef(it) => {
|
ast::ModuleItemKind::ConstDef(it) => it.name(),
|
||||||
self.items.push(ModuleItem::new(file_id, file_items, it)?)
|
ast::ModuleItemKind::StaticDef(it) => it.name(),
|
||||||
|
ast::ModuleItemKind::Module(_) => {
|
||||||
|
// modules are handled separately direclty by nameres
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
ast::ModuleItemKind::StaticDef(it) => {
|
};
|
||||||
self.items.push(ModuleItem::new(file_id, file_items, it)?)
|
if let Some(name) = name {
|
||||||
|
let def_id = assign_def_id(db, source_root_id, module_id, file_id, file_items, item);
|
||||||
|
self.declarations.insert(name.as_name(), def_id);
|
||||||
}
|
}
|
||||||
ast::ModuleItemKind::Module(it) => {
|
|
||||||
self.items.push(ModuleItem::new(file_id, file_items, it)?)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Some(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_use_item(&mut self, source_map: &mut ImportSourceMap, item: &ast::UseItem) {
|
fn add_use_item(&mut self, source_map: &mut ImportSourceMap, item: &ast::UseItem) {
|
||||||
|
@ -236,3 +216,47 @@ impl LoweredModule {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn assign_def_id(
|
||||||
|
db: &impl HirDatabase,
|
||||||
|
source_root_id: SourceRootId,
|
||||||
|
module_id: ModuleId,
|
||||||
|
file_id: HirFileId,
|
||||||
|
file_items: &SourceFileItems,
|
||||||
|
item: &ast::ModuleItem,
|
||||||
|
) -> PerNs<DefId> {
|
||||||
|
// depending on the item kind, the location can define something in
|
||||||
|
// the values namespace, the types namespace, or both
|
||||||
|
let kind = DefKind::for_syntax_kind(item.syntax().kind());
|
||||||
|
let def_id = kind.map(|k| {
|
||||||
|
let item_id = file_items.id_of_unchecked(item.syntax());
|
||||||
|
let def_loc = DefLoc {
|
||||||
|
kind: k,
|
||||||
|
source_root_id,
|
||||||
|
module_id,
|
||||||
|
source_item_id: SourceItemId {
|
||||||
|
file_id,
|
||||||
|
item_id: Some(item_id),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
def_loc.id(db)
|
||||||
|
});
|
||||||
|
def_id
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DefKind {
|
||||||
|
fn for_syntax_kind(kind: SyntaxKind) -> PerNs<DefKind> {
|
||||||
|
match kind {
|
||||||
|
SyntaxKind::FN_DEF => PerNs::values(DefKind::Function),
|
||||||
|
SyntaxKind::MODULE => PerNs::types(DefKind::Module),
|
||||||
|
SyntaxKind::STRUCT_DEF => PerNs::both(DefKind::Struct, DefKind::StructCtor),
|
||||||
|
SyntaxKind::ENUM_DEF => PerNs::types(DefKind::Enum),
|
||||||
|
// These define items, but don't have their own DefKinds yet:
|
||||||
|
SyntaxKind::TRAIT_DEF => PerNs::types(DefKind::Trait),
|
||||||
|
SyntaxKind::TYPE_DEF => PerNs::types(DefKind::Type),
|
||||||
|
SyntaxKind::CONST_DEF => PerNs::values(DefKind::Const),
|
||||||
|
SyntaxKind::STATIC_DEF => PerNs::values(DefKind::Static),
|
||||||
|
_ => PerNs::none(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -146,9 +146,10 @@ pub fn macro_symbols(db: &impl HirDatabase, file_id: FileId) -> Vec<(SmolStr, Te
|
||||||
let mut res = Vec::new();
|
let mut res = Vec::new();
|
||||||
|
|
||||||
for macro_call_id in items
|
for macro_call_id in items
|
||||||
.items
|
.declarations
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|it| it.id.file_id.as_macro_call_id())
|
.filter_map(|(_, it)| it.take_types())
|
||||||
|
.filter_map(|it| it.loc(db).source_item_id.file_id.as_macro_call_id())
|
||||||
{
|
{
|
||||||
if let Some(exp) = db.expand_macro_invocation(macro_call_id) {
|
if let Some(exp) = db.expand_macro_invocation(macro_call_id) {
|
||||||
let loc = macro_call_id.loc(db);
|
let loc = macro_call_id.loc(db);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue