strongy-typed ids for macros

This commit is contained in:
Aleksey Kladov 2019-03-26 18:03:17 +03:00
parent fb8b354dcc
commit 071a19537d
4 changed files with 19 additions and 33 deletions

View File

@ -10,7 +10,7 @@ use ra_arena::{RawId, ArenaId, impl_arena_id};
use mbe::MacroRules; use mbe::MacroRules;
use crate::{ use crate::{
Module, DefDatabase, SourceItemId, SourceFileItemId, Module, DefDatabase, SourceItemId, SourceFileItemId, AstId,
}; };
#[derive(Debug, Default)] #[derive(Debug, Default)]
@ -68,7 +68,7 @@ impl HirFileId {
HirFileIdRepr::File(file_id) => file_id, HirFileIdRepr::File(file_id) => file_id,
HirFileIdRepr::Macro(macro_call_id) => { HirFileIdRepr::Macro(macro_call_id) => {
let loc = macro_call_id.loc(db); let loc = macro_call_id.loc(db);
loc.source_item_id.file_id.original_file(db) loc.ast_id.file_id().original_file(db)
} }
} }
} }
@ -96,8 +96,7 @@ impl HirFileId {
fn parse_macro(db: &impl DefDatabase, macro_call_id: MacroCallId) -> Option<TreeArc<SourceFile>> { fn parse_macro(db: &impl DefDatabase, macro_call_id: MacroCallId) -> Option<TreeArc<SourceFile>> {
let loc = macro_call_id.loc(db); let loc = macro_call_id.loc(db);
let syntax = db.file_item(loc.source_item_id); let macro_call = loc.ast_id.to_node(db);
let macro_call = ast::MacroCall::cast(&syntax).unwrap();
let (macro_arg, _) = macro_call.token_tree().and_then(mbe::ast_to_token_tree)?; let (macro_arg, _) = macro_call.token_tree().and_then(mbe::ast_to_token_tree)?;
let macro_rules = db.macro_def(loc.def)?; let macro_rules = db.macro_def(loc.def)?;
@ -124,15 +123,10 @@ impl From<MacroCallId> for HirFileId {
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum MacroDefId { pub struct MacroDefId(pub(crate) AstId<ast::MacroCall>);
MacroByExample { source_item_id: SourceItemId },
}
pub(crate) fn macro_def_query(db: &impl DefDatabase, id: MacroDefId) -> Option<Arc<MacroRules>> { pub(crate) fn macro_def_query(db: &impl DefDatabase, id: MacroDefId) -> Option<Arc<MacroRules>> {
let syntax_node = match id { let macro_call = id.0.to_node(db);
MacroDefId::MacroByExample { source_item_id } => db.file_item(source_item_id),
};
let macro_call = ast::MacroCall::cast(&syntax_node).unwrap();
let arg = macro_call.token_tree()?; let arg = macro_call.token_tree()?;
let (tt, _) = mbe::ast_to_token_tree(arg)?; let (tt, _) = mbe::ast_to_token_tree(arg)?;
let rules = MacroRules::parse(&tt).ok()?; let rules = MacroRules::parse(&tt).ok()?;
@ -148,7 +142,7 @@ impl_arena_id!(MacroCallId);
#[derive(Debug, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct MacroCallLoc { pub struct MacroCallLoc {
pub(crate) def: MacroDefId, pub(crate) def: MacroDefId,
pub(crate) source_item_id: SourceItemId, pub(crate) ast_id: AstId<ast::MacroCall>,
} }
impl MacroCallId { impl MacroCallId {

View File

@ -7,7 +7,7 @@ use ra_syntax::ast;
use crate::{ use crate::{
Function, Module, Struct, Enum, Const, Static, Trait, TypeAlias, Function, Module, Struct, Enum, Const, Static, Trait, TypeAlias,
DefDatabase, HirFileId, Name, Path, SourceItemId, DefDatabase, HirFileId, Name, Path,
KnownName, KnownName,
nameres::{ nameres::{
Resolution, PerNs, ModuleDef, ReachedFixedPoint, ResolveMode, Resolution, PerNs, ModuleDef, ReachedFixedPoint, ResolveMode,
@ -53,7 +53,7 @@ struct DefCollector<DB> {
def_map: CrateDefMap, def_map: CrateDefMap,
glob_imports: FxHashMap<CrateModuleId, Vec<(CrateModuleId, raw::ImportId)>>, glob_imports: FxHashMap<CrateModuleId, Vec<(CrateModuleId, raw::ImportId)>>,
unresolved_imports: Vec<(CrateModuleId, raw::ImportId, raw::ImportData)>, 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>, global_macro_scope: FxHashMap<Name, MacroDefId>,
} }
@ -295,7 +295,7 @@ where
let mut macros = std::mem::replace(&mut self.unexpanded_macros, Vec::new()); let mut macros = std::mem::replace(&mut self.unexpanded_macros, Vec::new());
let mut resolved = Vec::new(); let mut resolved = Vec::new();
let mut res = ReachedFixedPoint::Yes; 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 { if path.segments.len() != 2 {
return true; return true;
} }
@ -311,8 +311,7 @@ where
res = ReachedFixedPoint::No; res = ReachedFixedPoint::No;
let def_map = self.db.crate_def_map(krate); let def_map = self.db.crate_def_map(krate);
if let Some(macro_id) = def_map.public_macros.get(&path.segments[1].name).cloned() { if let Some(macro_id) = def_map.public_macros.get(&path.segments[1].name).cloned() {
let call_id = let call_id = MacroCallLoc { def: macro_id, ast_id: *ast_id }.id(self.db);
MacroCallLoc { def: macro_id, source_item_id: *source_item_id }.id(self.db);
resolved.push((*module_id, call_id)); resolved.push((*module_id, call_id));
} }
false false
@ -456,34 +455,27 @@ where
// Case 1: macro rules, define a macro in crate-global mutable scope // Case 1: macro rules, define a macro in crate-global mutable scope
if is_macro_rules(&mac.path) { if is_macro_rules(&mac.path) {
if let Some(name) = &mac.name { if let Some(name) = &mac.name {
let macro_id = MacroDefId::MacroByExample { let macro_id = MacroDefId(mac.ast_id.with_file_id(self.file_id));
source_item_id: mac.source_item_id.with_file_id(self.file_id),
};
self.def_collector.define_macro(name.clone(), macro_id, mac.export) self.def_collector.define_macro(name.clone(), macro_id, mac.export)
} }
return; 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 // Case 2: try to expand macro_rules from this crate, triggering
// recursive item collection. // recursive item collection.
if let Some(&macro_id) = if let Some(&macro_id) =
mac.path.as_ident().and_then(|name| self.def_collector.global_macro_scope.get(name)) mac.path.as_ident().and_then(|name| self.def_collector.global_macro_scope.get(name))
{ {
let macro_call_id = let macro_call_id = MacroCallLoc { def: macro_id, ast_id }.id(self.def_collector.db);
MacroCallLoc { def: macro_id, source_item_id }.id(self.def_collector.db);
self.def_collector.collect_macro_expansion(self.module_id, macro_call_id); self.def_collector.collect_macro_expansion(self.module_id, macro_call_id);
return; return;
} }
// Case 3: path to a macro from another crate, expand during name resolution // Case 3: path to a macro from another crate, expand during name resolution
self.def_collector.unexpanded_macros.push(( self.def_collector.unexpanded_macros.push((self.module_id, ast_id, mac.path.clone()))
self.module_id,
source_item_id,
mac.path.clone(),
))
} }
} }

View File

@ -160,7 +160,7 @@ impl_arena_id!(Macro);
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
pub(super) struct MacroData { pub(super) struct MacroData {
pub(super) source_item_id: SourceFileItemId, pub(super) ast_id: FileAstId<ast::MacroCall>,
pub(super) path: Path, pub(super) path: Path,
pub(super) name: Option<Name>, pub(super) name: Option<Name>,
pub(super) export: bool, pub(super) export: bool,
@ -285,9 +285,9 @@ impl RawItemsCollector {
}; };
let name = m.name().map(|it| it.as_name()); 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_file_items.ast_id(m);
let export = m.has_atom_attr("macro_export"); 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)); self.push_item(current_module, RawItem::Macro(m));
} }

View File

@ -5,7 +5,7 @@ use ra_syntax::{SyntaxNodePtr, TreeArc, SyntaxNode, SourceFile, AstNode, ast};
use crate::{HirFileId, DefDatabase}; use crate::{HirFileId, DefDatabase};
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq, Hash)]
pub(crate) struct AstId<N: AstNode> { pub(crate) struct AstId<N: AstNode> {
file_id: HirFileId, file_id: HirFileId,
file_ast_id: FileAstId<N>, file_ast_id: FileAstId<N>,
@ -30,7 +30,7 @@ impl<N: AstNode> AstId<N> {
} }
} }
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq, Hash)]
pub(crate) struct FileAstId<N: AstNode> { pub(crate) struct FileAstId<N: AstNode> {
raw: SourceFileItemId, raw: SourceFileItemId,
_ty: PhantomData<N>, _ty: PhantomData<N>,