Merge #1059
1059: Typed ids r=matklad a=matklad just some type-safety and refactorings. closes https://github.com/rust-analyzer/rust-analyzer/issues/1054 bors r+ Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
This commit is contained in:
commit
a82755e241
@ -13,7 +13,7 @@ use crate::{
|
||||
adt::{EnumVariantId, StructFieldId, VariantDef},
|
||||
generics::GenericParams,
|
||||
docs::{Documentation, Docs, docs_from_ast},
|
||||
ids::{FunctionId, StructId, EnumId, AstItemDef, ConstId, StaticId, TraitId, TypeId},
|
||||
ids::{FunctionId, StructId, EnumId, AstItemDef, ConstId, StaticId, TraitId, TypeAliasId},
|
||||
impl_block::ImplBlock,
|
||||
resolve::Resolver,
|
||||
diagnostics::DiagnosticSink,
|
||||
@ -672,7 +672,7 @@ impl Docs for Trait {
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct TypeAlias {
|
||||
pub(crate) id: TypeId,
|
||||
pub(crate) id: TypeAliasId,
|
||||
}
|
||||
|
||||
impl TypeAlias {
|
||||
|
@ -1,18 +1,18 @@
|
||||
use ra_db::FileId;
|
||||
use ra_syntax::{ast, TreeArc, AstNode};
|
||||
use ra_syntax::{ast, TreeArc};
|
||||
|
||||
use crate::{
|
||||
Module, ModuleSource, Name,
|
||||
Module, ModuleSource, Name, AstId,
|
||||
nameres::{CrateModuleId, ImportId},
|
||||
HirDatabase, DefDatabase,
|
||||
HirFileId, SourceItemId,
|
||||
HirFileId,
|
||||
};
|
||||
|
||||
impl ModuleSource {
|
||||
pub(crate) fn new(
|
||||
db: &impl DefDatabase,
|
||||
file_id: Option<FileId>,
|
||||
decl_id: Option<SourceItemId>,
|
||||
decl_id: Option<AstId<ast::Module>>,
|
||||
) -> ModuleSource {
|
||||
match (file_id, decl_id) {
|
||||
(Some(file_id), _) => {
|
||||
@ -20,8 +20,7 @@ impl ModuleSource {
|
||||
ModuleSource::SourceFile(source_file)
|
||||
}
|
||||
(None, Some(item_id)) => {
|
||||
let module = db.file_item(item_id);
|
||||
let module = ast::Module::cast(&*module).unwrap();
|
||||
let module = item_id.to_node(db);
|
||||
assert!(module.item_list().is_some(), "expected inline module");
|
||||
ModuleSource::Module(module.to_owned())
|
||||
}
|
||||
@ -55,7 +54,7 @@ impl Module {
|
||||
let decl_id = def_map[self.module_id].declaration;
|
||||
let file_id = def_map[self.module_id].definition;
|
||||
let module_source = ModuleSource::new(db, file_id, decl_id);
|
||||
let file_id = file_id.map(HirFileId::from).unwrap_or_else(|| decl_id.unwrap().file_id);
|
||||
let file_id = file_id.map(HirFileId::from).unwrap_or_else(|| decl_id.unwrap().file_id());
|
||||
(file_id, module_source)
|
||||
}
|
||||
|
||||
@ -65,9 +64,8 @@ impl Module {
|
||||
) -> Option<(HirFileId, TreeArc<ast::Module>)> {
|
||||
let def_map = db.crate_def_map(self.krate);
|
||||
let decl = def_map[self.module_id].declaration?;
|
||||
let syntax_node = db.file_item(decl);
|
||||
let ast = ast::Module::cast(&syntax_node).unwrap().to_owned();
|
||||
Some((decl.file_id, ast))
|
||||
let ast = decl.to_node(db);
|
||||
Some((decl.file_id(), ast))
|
||||
}
|
||||
|
||||
pub(crate) fn import_source_impl(
|
||||
|
@ -4,7 +4,7 @@ use ra_syntax::{SyntaxNode, TreeArc, SourceFile};
|
||||
use ra_db::{SourceDatabase, salsa};
|
||||
|
||||
use crate::{
|
||||
HirFileId, MacroDefId, SourceFileItems, SourceItemId, Crate, Module, HirInterner,
|
||||
HirFileId, MacroDefId, AstIdMap, ErasedFileAstId, Crate, Module, HirInterner,
|
||||
Function, FnSignature, ExprScopes, TypeAlias,
|
||||
Struct, Enum, StructField,
|
||||
Const, ConstSignature, Static,
|
||||
@ -22,7 +22,7 @@ pub trait DefDatabase: SourceDatabase + AsRef<HirInterner> {
|
||||
#[salsa::invoke(crate::ids::macro_def_query)]
|
||||
fn macro_def(&self, macro_id: MacroDefId) -> Option<Arc<mbe::MacroRules>>;
|
||||
|
||||
#[salsa::invoke(HirFileId::hir_parse)]
|
||||
#[salsa::invoke(HirFileId::hir_parse_query)]
|
||||
fn hir_parse(&self, file_id: HirFileId) -> TreeArc<SourceFile>;
|
||||
|
||||
#[salsa::invoke(crate::adt::StructData::struct_data_query)]
|
||||
@ -34,11 +34,11 @@ pub trait DefDatabase: SourceDatabase + AsRef<HirInterner> {
|
||||
#[salsa::invoke(crate::traits::TraitData::trait_data_query)]
|
||||
fn trait_data(&self, t: Trait) -> Arc<TraitData>;
|
||||
|
||||
#[salsa::invoke(crate::source_id::SourceFileItems::file_items_query)]
|
||||
fn file_items(&self, file_id: HirFileId) -> Arc<SourceFileItems>;
|
||||
#[salsa::invoke(crate::source_id::AstIdMap::ast_id_map_query)]
|
||||
fn ast_id_map(&self, file_id: HirFileId) -> Arc<AstIdMap>;
|
||||
|
||||
#[salsa::invoke(crate::source_id::SourceFileItems::file_item_query)]
|
||||
fn file_item(&self, source_item_id: SourceItemId) -> TreeArc<SyntaxNode>;
|
||||
#[salsa::invoke(crate::source_id::AstIdMap::file_item_query)]
|
||||
fn ast_id_to_node(&self, file_id: HirFileId, ast_id: ErasedFileAstId) -> TreeArc<SyntaxNode>;
|
||||
|
||||
#[salsa::invoke(RawItems::raw_items_query)]
|
||||
fn raw_items(&self, file_id: HirFileId) -> Arc<RawItems>;
|
||||
|
@ -1,5 +1,4 @@
|
||||
use std::{
|
||||
marker::PhantomData,
|
||||
hash::{Hash, Hasher},
|
||||
sync::Arc,
|
||||
};
|
||||
@ -10,7 +9,7 @@ use ra_arena::{RawId, ArenaId, impl_arena_id};
|
||||
use mbe::MacroRules;
|
||||
|
||||
use crate::{
|
||||
Module, DefDatabase, SourceItemId, SourceFileItemId,
|
||||
Module, DefDatabase, AstId, FileAstId,
|
||||
};
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
@ -22,7 +21,7 @@ pub struct HirInterner {
|
||||
consts: LocationInterner<ItemLoc<ast::ConstDef>, ConstId>,
|
||||
statics: LocationInterner<ItemLoc<ast::StaticDef>, StaticId>,
|
||||
traits: LocationInterner<ItemLoc<ast::TraitDef>, TraitId>,
|
||||
types: LocationInterner<ItemLoc<ast::TypeAliasDef>, TypeId>,
|
||||
types: LocationInterner<ItemLoc<ast::TypeAliasDef>, TypeAliasId>,
|
||||
}
|
||||
|
||||
impl HirInterner {
|
||||
@ -68,7 +67,7 @@ impl HirFileId {
|
||||
HirFileIdRepr::File(file_id) => file_id,
|
||||
HirFileIdRepr::Macro(macro_call_id) => {
|
||||
let loc = macro_call_id.loc(db);
|
||||
loc.source_item_id.file_id.original_file(db)
|
||||
loc.ast_id.file_id().original_file(db)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -83,7 +82,10 @@ impl HirFileId {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn hir_parse(db: &impl DefDatabase, file_id: HirFileId) -> TreeArc<SourceFile> {
|
||||
pub(crate) fn hir_parse_query(
|
||||
db: &impl DefDatabase,
|
||||
file_id: HirFileId,
|
||||
) -> TreeArc<SourceFile> {
|
||||
match file_id.0 {
|
||||
HirFileIdRepr::File(file_id) => db.parse(file_id),
|
||||
HirFileIdRepr::Macro(macro_call_id) => {
|
||||
@ -96,8 +98,7 @@ impl HirFileId {
|
||||
|
||||
fn parse_macro(db: &impl DefDatabase, macro_call_id: MacroCallId) -> Option<TreeArc<SourceFile>> {
|
||||
let loc = macro_call_id.loc(db);
|
||||
let syntax = db.file_item(loc.source_item_id);
|
||||
let macro_call = ast::MacroCall::cast(&syntax).unwrap();
|
||||
let macro_call = loc.ast_id.to_node(db);
|
||||
let (macro_arg, _) = macro_call.token_tree().and_then(mbe::ast_to_token_tree)?;
|
||||
|
||||
let macro_rules = db.macro_def(loc.def)?;
|
||||
@ -124,15 +125,10 @@ impl From<MacroCallId> for HirFileId {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub enum MacroDefId {
|
||||
MacroByExample { source_item_id: SourceItemId },
|
||||
}
|
||||
pub struct MacroDefId(pub(crate) AstId<ast::MacroCall>);
|
||||
|
||||
pub(crate) fn macro_def_query(db: &impl DefDatabase, id: MacroDefId) -> Option<Arc<MacroRules>> {
|
||||
let syntax_node = match id {
|
||||
MacroDefId::MacroByExample { source_item_id } => db.file_item(source_item_id),
|
||||
};
|
||||
let macro_call = ast::MacroCall::cast(&syntax_node).unwrap();
|
||||
let macro_call = id.0.to_node(db);
|
||||
let arg = macro_call.token_tree()?;
|
||||
let (tt, _) = mbe::ast_to_token_tree(arg)?;
|
||||
let rules = MacroRules::parse(&tt).ok()?;
|
||||
@ -148,7 +144,7 @@ impl_arena_id!(MacroCallId);
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct MacroCallLoc {
|
||||
pub(crate) def: MacroDefId,
|
||||
pub(crate) source_item_id: SourceItemId,
|
||||
pub(crate) ast_id: AstId<ast::MacroCall>,
|
||||
}
|
||||
|
||||
impl MacroCallId {
|
||||
@ -158,7 +154,6 @@ impl MacroCallId {
|
||||
}
|
||||
|
||||
impl MacroCallLoc {
|
||||
#[allow(unused)]
|
||||
pub(crate) fn id(&self, db: &impl AsRef<HirInterner>) -> MacroCallId {
|
||||
db.as_ref().macros.loc2id(&self)
|
||||
}
|
||||
@ -167,26 +162,25 @@ impl MacroCallLoc {
|
||||
#[derive(Debug)]
|
||||
pub struct ItemLoc<N: AstNode> {
|
||||
pub(crate) module: Module,
|
||||
raw: SourceItemId,
|
||||
_ty: PhantomData<N>,
|
||||
ast_id: AstId<N>,
|
||||
}
|
||||
|
||||
impl<N: AstNode> PartialEq for ItemLoc<N> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.module == other.module && self.raw == other.raw
|
||||
self.module == other.module && self.ast_id == other.ast_id
|
||||
}
|
||||
}
|
||||
impl<N: AstNode> Eq for ItemLoc<N> {}
|
||||
impl<N: AstNode> Hash for ItemLoc<N> {
|
||||
fn hash<H: Hasher>(&self, hasher: &mut H) {
|
||||
self.module.hash(hasher);
|
||||
self.raw.hash(hasher);
|
||||
self.ast_id.hash(hasher);
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: AstNode> Clone for ItemLoc<N> {
|
||||
fn clone(&self) -> ItemLoc<N> {
|
||||
ItemLoc { module: self.module, raw: self.raw, _ty: PhantomData }
|
||||
ItemLoc { module: self.module, ast_id: self.ast_id }
|
||||
}
|
||||
}
|
||||
|
||||
@ -213,26 +207,19 @@ impl<'a, DB: DefDatabase> LocationCtx<&'a DB> {
|
||||
pub(crate) trait AstItemDef<N: AstNode>: ArenaId + Clone {
|
||||
fn interner(interner: &HirInterner) -> &LocationInterner<ItemLoc<N>, Self>;
|
||||
fn from_ast(ctx: LocationCtx<&impl DefDatabase>, ast: &N) -> Self {
|
||||
let items = ctx.db.file_items(ctx.file_id);
|
||||
let item_id = items.id_of(ctx.file_id, ast.syntax());
|
||||
Self::from_source_item_id_unchecked(ctx, item_id)
|
||||
let items = ctx.db.ast_id_map(ctx.file_id);
|
||||
let item_id = items.ast_id(ast);
|
||||
Self::from_ast_id(ctx, item_id)
|
||||
}
|
||||
fn from_source_item_id_unchecked(
|
||||
ctx: LocationCtx<&impl DefDatabase>,
|
||||
item_id: SourceFileItemId,
|
||||
) -> Self {
|
||||
let raw = SourceItemId { file_id: ctx.file_id, item_id };
|
||||
let loc = ItemLoc { module: ctx.module, raw, _ty: PhantomData };
|
||||
|
||||
fn from_ast_id(ctx: LocationCtx<&impl DefDatabase>, ast_id: FileAstId<N>) -> Self {
|
||||
let loc = ItemLoc { module: ctx.module, ast_id: ast_id.with_file_id(ctx.file_id) };
|
||||
Self::interner(ctx.db.as_ref()).loc2id(&loc)
|
||||
}
|
||||
fn source(self, db: &impl DefDatabase) -> (HirFileId, TreeArc<N>) {
|
||||
let int = Self::interner(db.as_ref());
|
||||
let loc = int.id2loc(self);
|
||||
let syntax = db.file_item(loc.raw);
|
||||
let ast =
|
||||
N::cast(&syntax).unwrap_or_else(|| panic!("invalid ItemLoc: {:?}", loc.raw)).to_owned();
|
||||
(loc.raw.file_id, ast)
|
||||
let ast = loc.ast_id.to_node(db);
|
||||
(loc.ast_id.file_id(), ast)
|
||||
}
|
||||
fn module(self, db: &impl DefDatabase) -> Module {
|
||||
let int = Self::interner(db.as_ref());
|
||||
@ -242,7 +229,7 @@ pub(crate) trait AstItemDef<N: AstNode>: ArenaId + Clone {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct FunctionId(RawId);
|
||||
pub(crate) struct FunctionId(RawId);
|
||||
impl_arena_id!(FunctionId);
|
||||
impl AstItemDef<ast::FnDef> for FunctionId {
|
||||
fn interner(interner: &HirInterner) -> &LocationInterner<ItemLoc<ast::FnDef>, Self> {
|
||||
@ -251,7 +238,7 @@ impl AstItemDef<ast::FnDef> for FunctionId {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct StructId(RawId);
|
||||
pub(crate) struct StructId(RawId);
|
||||
impl_arena_id!(StructId);
|
||||
impl AstItemDef<ast::StructDef> for StructId {
|
||||
fn interner(interner: &HirInterner) -> &LocationInterner<ItemLoc<ast::StructDef>, Self> {
|
||||
@ -260,7 +247,7 @@ impl AstItemDef<ast::StructDef> for StructId {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct EnumId(RawId);
|
||||
pub(crate) struct EnumId(RawId);
|
||||
impl_arena_id!(EnumId);
|
||||
impl AstItemDef<ast::EnumDef> for EnumId {
|
||||
fn interner(interner: &HirInterner) -> &LocationInterner<ItemLoc<ast::EnumDef>, Self> {
|
||||
@ -269,7 +256,7 @@ impl AstItemDef<ast::EnumDef> for EnumId {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct ConstId(RawId);
|
||||
pub(crate) struct ConstId(RawId);
|
||||
impl_arena_id!(ConstId);
|
||||
impl AstItemDef<ast::ConstDef> for ConstId {
|
||||
fn interner(interner: &HirInterner) -> &LocationInterner<ItemLoc<ast::ConstDef>, Self> {
|
||||
@ -278,7 +265,7 @@ impl AstItemDef<ast::ConstDef> for ConstId {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct StaticId(RawId);
|
||||
pub(crate) struct StaticId(RawId);
|
||||
impl_arena_id!(StaticId);
|
||||
impl AstItemDef<ast::StaticDef> for StaticId {
|
||||
fn interner(interner: &HirInterner) -> &LocationInterner<ItemLoc<ast::StaticDef>, Self> {
|
||||
@ -287,7 +274,7 @@ impl AstItemDef<ast::StaticDef> for StaticId {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct TraitId(RawId);
|
||||
pub(crate) struct TraitId(RawId);
|
||||
impl_arena_id!(TraitId);
|
||||
impl AstItemDef<ast::TraitDef> for TraitId {
|
||||
fn interner(interner: &HirInterner) -> &LocationInterner<ItemLoc<ast::TraitDef>, Self> {
|
||||
@ -296,9 +283,9 @@ impl AstItemDef<ast::TraitDef> for TraitId {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct TypeId(RawId);
|
||||
impl_arena_id!(TypeId);
|
||||
impl AstItemDef<ast::TypeAliasDef> for TypeId {
|
||||
pub(crate) struct TypeAliasId(RawId);
|
||||
impl_arena_id!(TypeAliasId);
|
||||
impl AstItemDef<ast::TypeAliasDef> for TypeAliasId {
|
||||
fn interner(interner: &HirInterner) -> &LocationInterner<ItemLoc<ast::TypeAliasDef>, Self> {
|
||||
&interner.types
|
||||
}
|
||||
|
@ -48,13 +48,13 @@ mod marks;
|
||||
use crate::{
|
||||
db::{HirDatabase, DefDatabase},
|
||||
name::{AsName, KnownName},
|
||||
source_id::SourceFileItemId,
|
||||
source_id::{FileAstId, AstId},
|
||||
};
|
||||
|
||||
pub use self::{
|
||||
path::{Path, PathKind},
|
||||
name::Name,
|
||||
source_id::{SourceFileItems, SourceItemId},
|
||||
source_id::{AstIdMap, ErasedFileAstId},
|
||||
ids::{HirFileId, MacroDefId, MacroCallId, MacroCallLoc, HirInterner},
|
||||
nameres::{PerNs, Namespace},
|
||||
ty::{Ty, ApplicationTy, TypeCtor, Substs, display::HirDisplay},
|
||||
|
@ -59,13 +59,15 @@ use rustc_hash::FxHashMap;
|
||||
use ra_arena::{Arena, RawId, impl_arena_id};
|
||||
use ra_db::{FileId, Edition};
|
||||
use test_utils::tested_by;
|
||||
use ra_syntax::ast;
|
||||
|
||||
use crate::{
|
||||
ModuleDef, Name, Crate, Module, SourceItemId,
|
||||
ModuleDef, Name, Crate, Module,
|
||||
DefDatabase, Path, PathKind, HirFileId, Trait,
|
||||
ids::MacroDefId,
|
||||
diagnostics::DiagnosticSink,
|
||||
nameres::diagnostics::DefDiagnostic,
|
||||
AstId,
|
||||
};
|
||||
|
||||
pub(crate) use self::raw::{RawItems, ImportId, ImportSourceMap};
|
||||
@ -106,7 +108,7 @@ pub(crate) struct ModuleData {
|
||||
pub(crate) children: FxHashMap<Name, CrateModuleId>,
|
||||
pub(crate) scope: ModuleScope,
|
||||
/// None for root
|
||||
pub(crate) declaration: Option<SourceItemId>,
|
||||
pub(crate) declaration: Option<AstId<ast::Module>>,
|
||||
/// None for inline modules.
|
||||
///
|
||||
/// Note that non-inline modules, by definition, live inside non-macro file.
|
||||
@ -225,7 +227,7 @@ impl CrateDefMap {
|
||||
pub(crate) fn find_module_by_source(
|
||||
&self,
|
||||
file_id: HirFileId,
|
||||
decl_id: Option<SourceItemId>,
|
||||
decl_id: Option<AstId<ast::Module>>,
|
||||
) -> Option<CrateModuleId> {
|
||||
let (module_id, _module_data) = self.modules.iter().find(|(_module_id, module_data)| {
|
||||
if decl_id.is_some() {
|
||||
@ -429,10 +431,10 @@ impl CrateDefMap {
|
||||
|
||||
mod diagnostics {
|
||||
use relative_path::RelativePathBuf;
|
||||
use ra_syntax::{AstPtr, AstNode, ast};
|
||||
use ra_syntax::{AstPtr, ast};
|
||||
|
||||
use crate::{
|
||||
SourceItemId, DefDatabase,
|
||||
AstId, DefDatabase,
|
||||
nameres::CrateModuleId,
|
||||
diagnostics::{DiagnosticSink, UnresolvedModule},
|
||||
};
|
||||
@ -441,7 +443,7 @@ mod diagnostics {
|
||||
pub(super) enum DefDiagnostic {
|
||||
UnresolvedModule {
|
||||
module: CrateModuleId,
|
||||
declaration: SourceItemId,
|
||||
declaration: AstId<ast::Module>,
|
||||
candidate: RelativePathBuf,
|
||||
},
|
||||
}
|
||||
@ -458,10 +460,9 @@ mod diagnostics {
|
||||
if *module != target_module {
|
||||
return;
|
||||
}
|
||||
let syntax = db.file_item(*declaration);
|
||||
let decl = ast::Module::cast(&syntax).unwrap();
|
||||
let decl = declaration.to_node(db);
|
||||
sink.push(UnresolvedModule {
|
||||
file: declaration.file_id,
|
||||
file: declaration.file_id(),
|
||||
decl: AstPtr::new(&decl),
|
||||
candidate: candidate.clone(),
|
||||
})
|
||||
@ -469,5 +470,4 @@ mod diagnostics {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -3,10 +3,11 @@ use rustc_hash::FxHashMap;
|
||||
use relative_path::RelativePathBuf;
|
||||
use test_utils::tested_by;
|
||||
use ra_db::FileId;
|
||||
use ra_syntax::ast;
|
||||
|
||||
use crate::{
|
||||
Function, Module, Struct, Enum, Const, Static, Trait, TypeAlias,
|
||||
DefDatabase, HirFileId, Name, Path, SourceItemId,
|
||||
DefDatabase, HirFileId, Name, Path,
|
||||
KnownName,
|
||||
nameres::{
|
||||
Resolution, PerNs, ModuleDef, ReachedFixedPoint, ResolveMode,
|
||||
@ -15,6 +16,7 @@ use crate::{
|
||||
raw,
|
||||
},
|
||||
ids::{AstItemDef, LocationCtx, MacroCallLoc, MacroCallId, MacroDefId},
|
||||
AstId,
|
||||
};
|
||||
|
||||
pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> CrateDefMap {
|
||||
@ -51,7 +53,7 @@ struct DefCollector<DB> {
|
||||
def_map: CrateDefMap,
|
||||
glob_imports: FxHashMap<CrateModuleId, Vec<(CrateModuleId, raw::ImportId)>>,
|
||||
unresolved_imports: Vec<(CrateModuleId, raw::ImportId, raw::ImportData)>,
|
||||
unexpanded_macros: Vec<(CrateModuleId, SourceItemId, Path)>,
|
||||
unexpanded_macros: Vec<(CrateModuleId, AstId<ast::MacroCall>, Path)>,
|
||||
global_macro_scope: FxHashMap<Name, MacroDefId>,
|
||||
}
|
||||
|
||||
@ -293,7 +295,7 @@ where
|
||||
let mut macros = std::mem::replace(&mut self.unexpanded_macros, Vec::new());
|
||||
let mut resolved = Vec::new();
|
||||
let mut res = ReachedFixedPoint::Yes;
|
||||
macros.retain(|(module_id, source_item_id, path)| {
|
||||
macros.retain(|(module_id, ast_id, path)| {
|
||||
if path.segments.len() != 2 {
|
||||
return true;
|
||||
}
|
||||
@ -309,8 +311,7 @@ where
|
||||
res = ReachedFixedPoint::No;
|
||||
let def_map = self.db.crate_def_map(krate);
|
||||
if let Some(macro_id) = def_map.public_macros.get(&path.segments[1].name).cloned() {
|
||||
let call_id =
|
||||
MacroCallLoc { def: macro_id, source_item_id: *source_item_id }.id(self.db);
|
||||
let call_id = MacroCallLoc { def: macro_id, ast_id: *ast_id }.id(self.db);
|
||||
resolved.push((*module_id, call_id));
|
||||
}
|
||||
false
|
||||
@ -364,12 +365,9 @@ where
|
||||
fn collect_module(&mut self, module: &raw::ModuleData) {
|
||||
match module {
|
||||
// inline module, just recurse
|
||||
raw::ModuleData::Definition { name, items, source_item_id } => {
|
||||
let module_id = self.push_child_module(
|
||||
name.clone(),
|
||||
source_item_id.with_file_id(self.file_id),
|
||||
None,
|
||||
);
|
||||
raw::ModuleData::Definition { name, items, ast_id } => {
|
||||
let module_id =
|
||||
self.push_child_module(name.clone(), ast_id.with_file_id(self.file_id), None);
|
||||
ModCollector {
|
||||
def_collector: &mut *self.def_collector,
|
||||
module_id,
|
||||
@ -379,13 +377,12 @@ where
|
||||
.collect(&*items);
|
||||
}
|
||||
// out of line module, resovle, parse and recurse
|
||||
raw::ModuleData::Declaration { name, source_item_id } => {
|
||||
let source_item_id = source_item_id.with_file_id(self.file_id);
|
||||
raw::ModuleData::Declaration { name, ast_id } => {
|
||||
let ast_id = ast_id.with_file_id(self.file_id);
|
||||
let is_root = self.def_collector.def_map.modules[self.module_id].parent.is_none();
|
||||
match resolve_submodule(self.def_collector.db, self.file_id, name, is_root) {
|
||||
Ok(file_id) => {
|
||||
let module_id =
|
||||
self.push_child_module(name.clone(), source_item_id, Some(file_id));
|
||||
let module_id = self.push_child_module(name.clone(), ast_id, Some(file_id));
|
||||
let raw_items = self.def_collector.db.raw_items(file_id.into());
|
||||
ModCollector {
|
||||
def_collector: &mut *self.def_collector,
|
||||
@ -398,7 +395,7 @@ where
|
||||
Err(candidate) => self.def_collector.def_map.diagnostics.push(
|
||||
DefDiagnostic::UnresolvedModule {
|
||||
module: self.module_id,
|
||||
declaration: source_item_id,
|
||||
declaration: ast_id,
|
||||
candidate,
|
||||
},
|
||||
),
|
||||
@ -410,7 +407,7 @@ where
|
||||
fn push_child_module(
|
||||
&mut self,
|
||||
name: Name,
|
||||
declaration: SourceItemId,
|
||||
declaration: AstId<ast::Module>,
|
||||
definition: Option<FileId>,
|
||||
) -> CrateModuleId {
|
||||
let modules = &mut self.def_collector.def_map.modules;
|
||||
@ -432,23 +429,24 @@ where
|
||||
fn define_def(&mut self, def: &raw::DefData) {
|
||||
let module = Module { krate: self.def_collector.def_map.krate, module_id: self.module_id };
|
||||
let ctx = LocationCtx::new(self.def_collector.db, module, self.file_id.into());
|
||||
macro_rules! id {
|
||||
() => {
|
||||
AstItemDef::from_source_item_id_unchecked(ctx, def.source_item_id)
|
||||
|
||||
macro_rules! def {
|
||||
($kind:ident, $ast_id:ident) => {
|
||||
$kind { id: AstItemDef::from_ast_id(ctx, $ast_id) }.into()
|
||||
};
|
||||
}
|
||||
let name = def.name.clone();
|
||||
let def: PerNs<ModuleDef> = match def.kind {
|
||||
raw::DefKind::Function => PerNs::values(Function { id: id!() }.into()),
|
||||
raw::DefKind::Struct => {
|
||||
let s = Struct { id: id!() }.into();
|
||||
raw::DefKind::Function(ast_id) => PerNs::values(def!(Function, ast_id)),
|
||||
raw::DefKind::Struct(ast_id) => {
|
||||
let s = def!(Struct, ast_id);
|
||||
PerNs::both(s, s)
|
||||
}
|
||||
raw::DefKind::Enum => PerNs::types(Enum { id: id!() }.into()),
|
||||
raw::DefKind::Const => PerNs::values(Const { id: id!() }.into()),
|
||||
raw::DefKind::Static => PerNs::values(Static { id: id!() }.into()),
|
||||
raw::DefKind::Trait => PerNs::types(Trait { id: id!() }.into()),
|
||||
raw::DefKind::TypeAlias => PerNs::types(TypeAlias { id: id!() }.into()),
|
||||
raw::DefKind::Enum(ast_id) => PerNs::types(def!(Enum, ast_id)),
|
||||
raw::DefKind::Const(ast_id) => PerNs::values(def!(Const, ast_id)),
|
||||
raw::DefKind::Static(ast_id) => PerNs::values(def!(Static, ast_id)),
|
||||
raw::DefKind::Trait(ast_id) => PerNs::types(def!(Trait, ast_id)),
|
||||
raw::DefKind::TypeAlias(ast_id) => PerNs::types(def!(TypeAlias, ast_id)),
|
||||
};
|
||||
let resolution = Resolution { def, import: None };
|
||||
self.def_collector.update(self.module_id, None, &[(name, resolution)])
|
||||
@ -458,34 +456,27 @@ where
|
||||
// Case 1: macro rules, define a macro in crate-global mutable scope
|
||||
if is_macro_rules(&mac.path) {
|
||||
if let Some(name) = &mac.name {
|
||||
let macro_id = MacroDefId::MacroByExample {
|
||||
source_item_id: mac.source_item_id.with_file_id(self.file_id),
|
||||
};
|
||||
let macro_id = MacroDefId(mac.ast_id.with_file_id(self.file_id));
|
||||
self.def_collector.define_macro(name.clone(), macro_id, mac.export)
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
let source_item_id = SourceItemId { file_id: self.file_id, item_id: mac.source_item_id };
|
||||
let ast_id = mac.ast_id.with_file_id(self.file_id);
|
||||
|
||||
// Case 2: try to expand macro_rules from this crate, triggering
|
||||
// recursive item collection.
|
||||
if let Some(¯o_id) =
|
||||
mac.path.as_ident().and_then(|name| self.def_collector.global_macro_scope.get(name))
|
||||
{
|
||||
let macro_call_id =
|
||||
MacroCallLoc { def: macro_id, source_item_id }.id(self.def_collector.db);
|
||||
let macro_call_id = MacroCallLoc { def: macro_id, ast_id }.id(self.def_collector.db);
|
||||
|
||||
self.def_collector.collect_macro_expansion(self.module_id, macro_call_id);
|
||||
return;
|
||||
}
|
||||
|
||||
// Case 3: path to a macro from another crate, expand during name resolution
|
||||
self.def_collector.unexpanded_macros.push((
|
||||
self.module_id,
|
||||
source_item_id,
|
||||
mac.path.clone(),
|
||||
))
|
||||
self.def_collector.unexpanded_macros.push((self.module_id, ast_id, mac.path.clone()))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,7 @@ use ra_syntax::{
|
||||
|
||||
use crate::{
|
||||
DefDatabase, Name, AsName, Path, HirFileId, ModuleSource,
|
||||
SourceFileItemId, SourceFileItems,
|
||||
AstIdMap, FileAstId,
|
||||
};
|
||||
|
||||
/// `RawItems` is a set of top-level items in a file (except for impls).
|
||||
@ -60,7 +60,7 @@ impl RawItems {
|
||||
) -> (Arc<RawItems>, Arc<ImportSourceMap>) {
|
||||
let mut collector = RawItemsCollector {
|
||||
raw_items: RawItems::default(),
|
||||
source_file_items: db.file_items(file_id.into()),
|
||||
source_ast_id_map: db.ast_id_map(file_id.into()),
|
||||
source_map: ImportSourceMap::default(),
|
||||
};
|
||||
let source_file = db.hir_parse(file_id);
|
||||
@ -115,8 +115,8 @@ impl_arena_id!(Module);
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub(super) enum ModuleData {
|
||||
Declaration { name: Name, source_item_id: SourceFileItemId },
|
||||
Definition { name: Name, source_item_id: SourceFileItemId, items: Vec<RawItem> },
|
||||
Declaration { name: Name, ast_id: FileAstId<ast::Module> },
|
||||
Definition { name: Name, ast_id: FileAstId<ast::Module>, items: Vec<RawItem> },
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
@ -138,20 +138,19 @@ impl_arena_id!(Def);
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub(super) struct DefData {
|
||||
pub(super) source_item_id: SourceFileItemId,
|
||||
pub(super) name: Name,
|
||||
pub(super) kind: DefKind,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||
pub(super) enum DefKind {
|
||||
Function,
|
||||
Struct,
|
||||
Enum,
|
||||
Const,
|
||||
Static,
|
||||
Trait,
|
||||
TypeAlias,
|
||||
Function(FileAstId<ast::FnDef>),
|
||||
Struct(FileAstId<ast::StructDef>),
|
||||
Enum(FileAstId<ast::EnumDef>),
|
||||
Const(FileAstId<ast::ConstDef>),
|
||||
Static(FileAstId<ast::StaticDef>),
|
||||
Trait(FileAstId<ast::TraitDef>),
|
||||
TypeAlias(FileAstId<ast::TypeAliasDef>),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
@ -160,7 +159,7 @@ impl_arena_id!(Macro);
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub(super) struct MacroData {
|
||||
pub(super) source_item_id: SourceFileItemId,
|
||||
pub(super) ast_id: FileAstId<ast::MacroCall>,
|
||||
pub(super) path: Path,
|
||||
pub(super) name: Option<Name>,
|
||||
pub(super) export: bool,
|
||||
@ -168,7 +167,7 @@ pub(super) struct MacroData {
|
||||
|
||||
struct RawItemsCollector {
|
||||
raw_items: RawItems,
|
||||
source_file_items: Arc<SourceFileItems>,
|
||||
source_ast_id_map: Arc<AstIdMap>,
|
||||
source_map: ImportSourceMap,
|
||||
}
|
||||
|
||||
@ -200,18 +199,31 @@ impl RawItemsCollector {
|
||||
// impls don't participate in name resolution
|
||||
return;
|
||||
}
|
||||
ast::ModuleItemKind::StructDef(it) => (DefKind::Struct, it.name()),
|
||||
ast::ModuleItemKind::EnumDef(it) => (DefKind::Enum, it.name()),
|
||||
ast::ModuleItemKind::FnDef(it) => (DefKind::Function, it.name()),
|
||||
ast::ModuleItemKind::TraitDef(it) => (DefKind::Trait, it.name()),
|
||||
ast::ModuleItemKind::TypeAliasDef(it) => (DefKind::TypeAlias, it.name()),
|
||||
ast::ModuleItemKind::ConstDef(it) => (DefKind::Const, it.name()),
|
||||
ast::ModuleItemKind::StaticDef(it) => (DefKind::Static, it.name()),
|
||||
ast::ModuleItemKind::StructDef(it) => {
|
||||
(DefKind::Struct(self.source_ast_id_map.ast_id(it)), it.name())
|
||||
}
|
||||
ast::ModuleItemKind::EnumDef(it) => {
|
||||
(DefKind::Enum(self.source_ast_id_map.ast_id(it)), it.name())
|
||||
}
|
||||
ast::ModuleItemKind::FnDef(it) => {
|
||||
(DefKind::Function(self.source_ast_id_map.ast_id(it)), it.name())
|
||||
}
|
||||
ast::ModuleItemKind::TraitDef(it) => {
|
||||
(DefKind::Trait(self.source_ast_id_map.ast_id(it)), it.name())
|
||||
}
|
||||
ast::ModuleItemKind::TypeAliasDef(it) => {
|
||||
(DefKind::TypeAlias(self.source_ast_id_map.ast_id(it)), it.name())
|
||||
}
|
||||
ast::ModuleItemKind::ConstDef(it) => {
|
||||
(DefKind::Const(self.source_ast_id_map.ast_id(it)), it.name())
|
||||
}
|
||||
ast::ModuleItemKind::StaticDef(it) => {
|
||||
(DefKind::Static(self.source_ast_id_map.ast_id(it)), it.name())
|
||||
}
|
||||
};
|
||||
if let Some(name) = name {
|
||||
let name = name.as_name();
|
||||
let source_item_id = self.source_file_items.id_of_unchecked(item.syntax());
|
||||
let def = self.raw_items.defs.alloc(DefData { name, kind, source_item_id });
|
||||
let def = self.raw_items.defs.alloc(DefData { name, kind });
|
||||
self.push_item(current_module, RawItem::Def(def))
|
||||
}
|
||||
}
|
||||
@ -221,10 +233,9 @@ impl RawItemsCollector {
|
||||
Some(it) => it.as_name(),
|
||||
None => return,
|
||||
};
|
||||
let source_item_id = self.source_file_items.id_of_unchecked(module.syntax());
|
||||
let ast_id = self.source_ast_id_map.ast_id(module);
|
||||
if module.has_semi() {
|
||||
let item =
|
||||
self.raw_items.modules.alloc(ModuleData::Declaration { name, source_item_id });
|
||||
let item = self.raw_items.modules.alloc(ModuleData::Declaration { name, ast_id });
|
||||
self.push_item(current_module, RawItem::Module(item));
|
||||
return;
|
||||
}
|
||||
@ -232,7 +243,7 @@ impl RawItemsCollector {
|
||||
if let Some(item_list) = module.item_list() {
|
||||
let item = self.raw_items.modules.alloc(ModuleData::Definition {
|
||||
name,
|
||||
source_item_id,
|
||||
ast_id,
|
||||
items: Vec::new(),
|
||||
});
|
||||
self.process_module(Some(item), item_list);
|
||||
@ -286,9 +297,9 @@ impl RawItemsCollector {
|
||||
};
|
||||
|
||||
let name = m.name().map(|it| it.as_name());
|
||||
let source_item_id = self.source_file_items.id_of_unchecked(m.syntax());
|
||||
let ast_id = self.source_ast_id_map.ast_id(m);
|
||||
let export = m.has_atom_attr("macro_export");
|
||||
let m = self.raw_items.macros.alloc(MacroData { source_item_id, path, name, export });
|
||||
let m = self.raw_items.macros.alloc(MacroData { ast_id, path, name, export });
|
||||
self.push_item(current_module, RawItem::Macro(m));
|
||||
}
|
||||
|
||||
|
@ -13,10 +13,10 @@ use ra_syntax::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
HirDatabase, Function, Struct, Enum, SourceItemId,
|
||||
HirDatabase, Function, Struct, Enum,
|
||||
AsName, Module, HirFileId, Crate, Trait, Resolver,
|
||||
ids::LocationCtx,
|
||||
expr
|
||||
expr, AstId
|
||||
};
|
||||
|
||||
/// Locates the module by `FileId`. Picks topmost module in the file.
|
||||
@ -54,8 +54,8 @@ fn module_from_inline(
|
||||
) -> Option<Module> {
|
||||
assert!(!module.has_semi());
|
||||
let file_id = file_id.into();
|
||||
let file_items = db.file_items(file_id);
|
||||
let item_id = file_items.id_of(file_id, module.syntax()).with_file_id(file_id);
|
||||
let ast_id_map = db.ast_id_map(file_id);
|
||||
let item_id = ast_id_map.ast_id(module).with_file_id(file_id);
|
||||
module_from_source(db, file_id, Some(item_id))
|
||||
}
|
||||
|
||||
@ -75,7 +75,7 @@ pub fn module_from_child_node(
|
||||
fn module_from_source(
|
||||
db: &impl HirDatabase,
|
||||
file_id: HirFileId,
|
||||
decl_id: Option<SourceItemId>,
|
||||
decl_id: Option<AstId<ast::Module>>,
|
||||
) -> Option<Module> {
|
||||
let source_root_id = db.file_source_root(file_id.as_original_file());
|
||||
db.source_root_crates(source_root_id).iter().map(|&crate_id| Crate { crate_id }).find_map(
|
||||
|
@ -1,59 +1,122 @@
|
||||
use std::sync::Arc;
|
||||
use std::{marker::PhantomData, sync::Arc, hash::{Hash, Hasher}};
|
||||
|
||||
use ra_arena::{Arena, RawId, impl_arena_id};
|
||||
use ra_syntax::{SyntaxNodePtr, TreeArc, SyntaxNode, SourceFile, AstNode, ast};
|
||||
|
||||
use crate::{HirFileId, DefDatabase};
|
||||
|
||||
/// 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)]
|
||||
pub(crate) struct SourceFileItemId(RawId);
|
||||
impl_arena_id!(SourceFileItemId);
|
||||
/// `AstId` points to an AST node in any file.
|
||||
///
|
||||
/// It is stable across reparses, and can be used as salsa key/value.
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct AstId<N: AstNode> {
|
||||
file_id: HirFileId,
|
||||
file_ast_id: FileAstId<N>,
|
||||
}
|
||||
|
||||
impl SourceFileItemId {
|
||||
pub(crate) fn with_file_id(self, file_id: HirFileId) -> SourceItemId {
|
||||
SourceItemId { file_id, item_id: self }
|
||||
impl<N: AstNode> Clone for AstId<N> {
|
||||
fn clone(&self) -> AstId<N> {
|
||||
*self
|
||||
}
|
||||
}
|
||||
impl<N: AstNode> Copy for AstId<N> {}
|
||||
|
||||
impl<N: AstNode> PartialEq for AstId<N> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
(self.file_id, self.file_ast_id) == (other.file_id, other.file_ast_id)
|
||||
}
|
||||
}
|
||||
impl<N: AstNode> Eq for AstId<N> {}
|
||||
impl<N: AstNode> Hash for AstId<N> {
|
||||
fn hash<H: Hasher>(&self, hasher: &mut H) {
|
||||
(self.file_id, self.file_ast_id).hash(hasher);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct SourceItemId {
|
||||
pub(crate) file_id: HirFileId,
|
||||
pub(crate) item_id: SourceFileItemId,
|
||||
impl<N: AstNode> AstId<N> {
|
||||
pub(crate) fn file_id(&self) -> HirFileId {
|
||||
self.file_id
|
||||
}
|
||||
|
||||
pub(crate) fn to_node(&self, db: &impl DefDatabase) -> TreeArc<N> {
|
||||
let syntax_node = db.ast_id_to_node(self.file_id, self.file_ast_id.raw);
|
||||
N::cast(&syntax_node).unwrap().to_owned()
|
||||
}
|
||||
}
|
||||
|
||||
/// Maps items' `SyntaxNode`s to `SourceFileItemId`s and back.
|
||||
/// `AstId` points to an AST node in a specific file.
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct FileAstId<N: AstNode> {
|
||||
raw: ErasedFileAstId,
|
||||
_ty: PhantomData<N>,
|
||||
}
|
||||
|
||||
impl<N: AstNode> Clone for FileAstId<N> {
|
||||
fn clone(&self) -> FileAstId<N> {
|
||||
*self
|
||||
}
|
||||
}
|
||||
impl<N: AstNode> Copy for FileAstId<N> {}
|
||||
|
||||
impl<N: AstNode> PartialEq for FileAstId<N> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.raw == other.raw
|
||||
}
|
||||
}
|
||||
impl<N: AstNode> Eq for FileAstId<N> {}
|
||||
impl<N: AstNode> Hash for FileAstId<N> {
|
||||
fn hash<H: Hasher>(&self, hasher: &mut H) {
|
||||
self.raw.hash(hasher);
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: AstNode> FileAstId<N> {
|
||||
pub(crate) fn with_file_id(self, file_id: HirFileId) -> AstId<N> {
|
||||
AstId { file_id, file_ast_id: self }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct ErasedFileAstId(RawId);
|
||||
impl_arena_id!(ErasedFileAstId);
|
||||
|
||||
/// Maps items' `SyntaxNode`s to `ErasedFileAstId`s and back.
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct SourceFileItems {
|
||||
file_id: HirFileId,
|
||||
arena: Arena<SourceFileItemId, SyntaxNodePtr>,
|
||||
pub struct AstIdMap {
|
||||
arena: Arena<ErasedFileAstId, SyntaxNodePtr>,
|
||||
}
|
||||
|
||||
impl SourceFileItems {
|
||||
pub(crate) fn file_items_query(
|
||||
db: &impl DefDatabase,
|
||||
file_id: HirFileId,
|
||||
) -> Arc<SourceFileItems> {
|
||||
impl AstIdMap {
|
||||
pub(crate) fn ast_id_map_query(db: &impl DefDatabase, file_id: HirFileId) -> Arc<AstIdMap> {
|
||||
let source_file = db.hir_parse(file_id);
|
||||
Arc::new(SourceFileItems::from_source_file(&source_file, file_id))
|
||||
Arc::new(AstIdMap::from_source_file(&source_file))
|
||||
}
|
||||
|
||||
pub(crate) fn file_item_query(
|
||||
db: &impl DefDatabase,
|
||||
source_item_id: SourceItemId,
|
||||
file_id: HirFileId,
|
||||
ast_id: ErasedFileAstId,
|
||||
) -> TreeArc<SyntaxNode> {
|
||||
let source_file = db.hir_parse(source_item_id.file_id);
|
||||
db.file_items(source_item_id.file_id)[source_item_id.item_id]
|
||||
.to_node(&source_file)
|
||||
.to_owned()
|
||||
let source_file = db.hir_parse(file_id);
|
||||
db.ast_id_map(file_id).arena[ast_id].to_node(&source_file).to_owned()
|
||||
}
|
||||
|
||||
pub(crate) fn from_source_file(
|
||||
source_file: &SourceFile,
|
||||
file_id: HirFileId,
|
||||
) -> SourceFileItems {
|
||||
let mut res = SourceFileItems { file_id, arena: Arena::default() };
|
||||
pub(crate) fn ast_id<N: AstNode>(&self, item: &N) -> FileAstId<N> {
|
||||
let ptr = SyntaxNodePtr::new(item.syntax());
|
||||
let raw = match self.arena.iter().find(|(_id, i)| **i == ptr) {
|
||||
Some((it, _)) => it,
|
||||
None => panic!(
|
||||
"Can't find {:?} in AstIdMap:\n{:?}",
|
||||
item.syntax(),
|
||||
self.arena.iter().map(|(_id, i)| i).collect::<Vec<_>>(),
|
||||
),
|
||||
};
|
||||
|
||||
FileAstId { raw, _ty: PhantomData }
|
||||
}
|
||||
|
||||
fn from_source_file(source_file: &SourceFile) -> AstIdMap {
|
||||
let mut res = AstIdMap { arena: Arena::default() };
|
||||
// By walking the tree in bread-first order we make sure that parents
|
||||
// get lower ids then children. That is, adding a new child does not
|
||||
// change parent's id. This means that, say, adding a new function to a
|
||||
@ -68,35 +131,9 @@ impl SourceFileItems {
|
||||
res
|
||||
}
|
||||
|
||||
fn alloc(&mut self, item: &SyntaxNode) -> SourceFileItemId {
|
||||
fn alloc(&mut self, item: &SyntaxNode) -> ErasedFileAstId {
|
||||
self.arena.alloc(SyntaxNodePtr::new(item))
|
||||
}
|
||||
pub(crate) fn id_of(&self, file_id: HirFileId, item: &SyntaxNode) -> SourceFileItemId {
|
||||
assert_eq!(
|
||||
self.file_id, file_id,
|
||||
"SourceFileItems: wrong file, expected {:?}, got {:?}",
|
||||
self.file_id, file_id
|
||||
);
|
||||
self.id_of_unchecked(item)
|
||||
}
|
||||
pub(crate) fn id_of_unchecked(&self, item: &SyntaxNode) -> SourceFileItemId {
|
||||
let ptr = SyntaxNodePtr::new(item);
|
||||
if let Some((id, _)) = self.arena.iter().find(|(_id, i)| **i == ptr) {
|
||||
return id;
|
||||
}
|
||||
panic!(
|
||||
"Can't find {:?} in SourceFileItems:\n{:?}",
|
||||
item,
|
||||
self.arena.iter().map(|(_id, i)| i).collect::<Vec<_>>(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Index<SourceFileItemId> for SourceFileItems {
|
||||
type Output = SyntaxNodePtr;
|
||||
fn index(&self, idx: SourceFileItemId) -> &SyntaxNodePtr {
|
||||
&self.arena[idx]
|
||||
}
|
||||
}
|
||||
|
||||
/// Walks the subtree in bfs order, calling `f` for each node.
|
||||
|
@ -220,8 +220,8 @@ impl RootDatabase {
|
||||
self.query(ra_db::ParseQuery).sweep(sweep);
|
||||
|
||||
self.query(hir::db::HirParseQuery).sweep(sweep);
|
||||
self.query(hir::db::FileItemsQuery).sweep(sweep);
|
||||
self.query(hir::db::FileItemQuery).sweep(sweep);
|
||||
self.query(hir::db::AstIdMapQuery).sweep(sweep);
|
||||
self.query(hir::db::AstIdToNodeQuery).sweep(sweep);
|
||||
|
||||
self.query(hir::db::RawItemsWithSourceMapQuery).sweep(sweep);
|
||||
self.query(hir::db::BodyWithSourceMapQuery).sweep(sweep);
|
||||
|
Loading…
x
Reference in New Issue
Block a user