assign DefIds when lowering

This commit is contained in:
Aleksey Kladov 2019-01-23 19:49:11 +03:00
parent 118e11e50b
commit 59f830d3e8
4 changed files with 99 additions and 107 deletions

View file

@ -1,9 +1,9 @@
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 crate::{
HirDatabase, PerNs, Def, Function, Struct, Enum, EnumVariant, ImplBlock, Crate,
HirDatabase, Def, Function, Struct, Enum, EnumVariant, ImplBlock, Crate,
Module, Trait, Type, Static, Const,
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
/// it's OK to use it as a salsa key/value.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]

View file

@ -21,7 +21,6 @@ use crate::nameres::lower::*;
use std::sync::Arc;
use rustc_hash::{FxHashMap, FxHashSet};
use ra_syntax::SyntaxKind::*;
use ra_db::SourceRootId;
use crate::{
@ -235,27 +234,12 @@ where
}
}
// Populate explicitly declared items, except modules
for item in input.items.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)
});
for (name, &def_id) in input.declarations.iter() {
let resolution = Resolution {
def_id,
import: None,
};
module_items.items.insert(item.name.clone(), resolution);
module_items.items.insert(name.clone(), resolution);
}
// Populate modules

View file

@ -2,52 +2,18 @@ use std::sync::Arc;
use ra_syntax::{
SyntaxKind, AstNode, SourceFile, TreeArc, AstPtr,
ast::{self, ModuleItemOwner},
ast::{self, ModuleItemOwner, NameOwner},
};
use ra_db::SourceRootId;
use ra_arena::{Arena, RawId, impl_arena_id, map::ArenaMap};
use rustc_hash::FxHashMap;
use crate::{
SourceItemId, Path, ModuleSource, HirDatabase, Name, SourceFileItems,
HirFileId, MacroCallLoc, AsName,
HirFileId, MacroCallLoc, AsName, PerNs, DefId, DefKind, DefLoc,
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)]
pub struct ImportId(RawId);
impl_arena_id!(ImportId);
@ -66,7 +32,7 @@ pub(super) struct ImportData {
/// can avoid redoing name resolution.
#[derive(Debug, Default, PartialEq, Eq)]
pub struct LoweredModule {
pub(crate) items: Vec<ModuleItem>,
pub(crate) declarations: FxHashMap<Name, PerNs<DefId>>,
pub(super) imports: Arena<ImportId, ImportData>,
}
@ -157,7 +123,15 @@ impl LoweredModule {
for item in items {
match item {
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) => {
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);
//FIXME: expand recursively
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,
source_map: &mut ImportSourceMap,
db: &impl HirDatabase,
source_root_id: SourceRootId,
module_id: ModuleId,
file_id: HirFileId,
file_items: &SourceFileItems,
item: &ast::ModuleItem,
) -> Option<()> {
match item.kind() {
ast::ModuleItemKind::StructDef(it) => {
self.items.push(ModuleItem::new(file_id, file_items, it)?)
}
ast::ModuleItemKind::EnumDef(it) => {
self.items.push(ModuleItem::new(file_id, file_items, it)?)
}
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)?)
}
) {
let name = match item.kind() {
ast::ModuleItemKind::StructDef(it) => it.name(),
ast::ModuleItemKind::EnumDef(it) => it.name(),
ast::ModuleItemKind::FnDef(it) => it.name(),
ast::ModuleItemKind::TraitDef(it) => it.name(),
ast::ModuleItemKind::TypeDef(it) => it.name(),
ast::ModuleItemKind::ImplBlock(_) => {
// 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(_) => {
// TODO
return;
}
ast::ModuleItemKind::ConstDef(it) => {
self.items.push(ModuleItem::new(file_id, file_items, it)?)
}
ast::ModuleItemKind::StaticDef(it) => {
self.items.push(ModuleItem::new(file_id, file_items, it)?)
}
ast::ModuleItemKind::Module(it) => {
self.items.push(ModuleItem::new(file_id, file_items, it)?)
ast::ModuleItemKind::ConstDef(it) => it.name(),
ast::ModuleItemKind::StaticDef(it) => it.name(),
ast::ModuleItemKind::Module(_) => {
// modules are handled separately direclty by nameres
return;
}
};
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);
}
Some(())
}
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(),
}
}
}

View file

@ -146,9 +146,10 @@ pub fn macro_symbols(db: &impl HirDatabase, file_id: FileId) -> Vec<(SmolStr, Te
let mut res = Vec::new();
for macro_call_id in items
.items
.declarations
.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) {
let loc = macro_call_id.loc(db);