mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-27 20:42:04 +00:00
Handle attribute macros in descend_into_macros
This commit is contained in:
parent
13da28cc2b
commit
8d87f9b298
6 changed files with 86 additions and 22 deletions
|
@ -362,25 +362,57 @@ impl<'db> SemanticsImpl<'db> {
|
||||||
|
|
||||||
let token = successors(Some(InFile::new(sa.file_id, token)), |token| {
|
let token = successors(Some(InFile::new(sa.file_id, token)), |token| {
|
||||||
self.db.unwind_if_cancelled();
|
self.db.unwind_if_cancelled();
|
||||||
let macro_call = token.value.ancestors().find_map(ast::MacroCall::cast)?;
|
|
||||||
let tt = macro_call.token_tree()?;
|
|
||||||
if !tt.syntax().text_range().contains_range(token.value.text_range()) {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
let file_id = sa.expand(self.db, token.with_value(¯o_call))?;
|
|
||||||
let token = self
|
|
||||||
.expansion_info_cache
|
|
||||||
.borrow_mut()
|
|
||||||
.entry(file_id)
|
|
||||||
.or_insert_with(|| file_id.expansion_info(self.db.upcast()))
|
|
||||||
.as_ref()?
|
|
||||||
.map_token_down(token.as_ref())?;
|
|
||||||
|
|
||||||
if let Some(parent) = token.value.parent() {
|
for node in token.value.ancestors() {
|
||||||
self.cache(find_root(&parent), token.file_id);
|
match_ast! {
|
||||||
|
match node {
|
||||||
|
ast::MacroCall(macro_call) => {
|
||||||
|
let tt = macro_call.token_tree()?;
|
||||||
|
if !tt.syntax().text_range().contains_range(token.value.text_range()) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let file_id = sa.expand(self.db, token.with_value(¯o_call))?;
|
||||||
|
let token = self
|
||||||
|
.expansion_info_cache
|
||||||
|
.borrow_mut()
|
||||||
|
.entry(file_id)
|
||||||
|
.or_insert_with(|| file_id.expansion_info(self.db.upcast()))
|
||||||
|
.as_ref()?
|
||||||
|
.map_token_down(token.as_ref())?;
|
||||||
|
|
||||||
|
if let Some(parent) = token.value.parent() {
|
||||||
|
self.cache(find_root(&parent), token.file_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Some(token);
|
||||||
|
},
|
||||||
|
ast::Item(item) => {
|
||||||
|
match self.with_ctx(|ctx| ctx.item_to_macro_call(token.with_value(item))) {
|
||||||
|
Some(call_id) => {
|
||||||
|
let file_id = call_id.as_file();
|
||||||
|
let token = self
|
||||||
|
.expansion_info_cache
|
||||||
|
.borrow_mut()
|
||||||
|
.entry(file_id)
|
||||||
|
.or_insert_with(|| file_id.expansion_info(self.db.upcast()))
|
||||||
|
.as_ref()?
|
||||||
|
.map_token_down(token.as_ref())?;
|
||||||
|
|
||||||
|
if let Some(parent) = token.value.parent() {
|
||||||
|
self.cache(find_root(&parent), token.file_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Some(token);
|
||||||
|
}
|
||||||
|
None => {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(token)
|
None
|
||||||
})
|
})
|
||||||
.last()
|
.last()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
|
@ -10,7 +10,7 @@ use hir_def::{
|
||||||
ImplId, LifetimeParamId, ModuleId, StaticId, StructId, TraitId, TypeAliasId, TypeParamId,
|
ImplId, LifetimeParamId, ModuleId, StaticId, StructId, TraitId, TypeAliasId, TypeParamId,
|
||||||
UnionId, VariantId,
|
UnionId, VariantId,
|
||||||
};
|
};
|
||||||
use hir_expand::{name::AsName, AstId, MacroDefKind};
|
use hir_expand::{name::AsName, AstId, MacroCallId, MacroDefKind};
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use stdx::impl_from;
|
use stdx::impl_from;
|
||||||
|
@ -145,16 +145,25 @@ impl SourceToDefCtx<'_, '_> {
|
||||||
Some((container, label_id))
|
Some((container, label_id))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(super) fn item_to_macro_call(&mut self, src: InFile<ast::Item>) -> Option<MacroCallId> {
|
||||||
|
let map = self.dyn_map(src.as_ref())?;
|
||||||
|
map[keys::ATTR_MACRO].get(&src).copied()
|
||||||
|
}
|
||||||
|
|
||||||
fn to_def<Ast: AstNode + 'static, ID: Copy + 'static>(
|
fn to_def<Ast: AstNode + 'static, ID: Copy + 'static>(
|
||||||
&mut self,
|
&mut self,
|
||||||
src: InFile<Ast>,
|
src: InFile<Ast>,
|
||||||
key: Key<Ast, ID>,
|
key: Key<Ast, ID>,
|
||||||
) -> Option<ID> {
|
) -> Option<ID> {
|
||||||
let container = self.find_container(src.as_ref().map(|it| it.syntax()))?;
|
self.dyn_map(src.as_ref())?[key].get(&src).copied()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dyn_map<Ast: AstNode + 'static>(&mut self, src: InFile<&Ast>) -> Option<&DynMap> {
|
||||||
|
let container = self.find_container(src.map(|it| it.syntax()))?;
|
||||||
let db = self.db;
|
let db = self.db;
|
||||||
let dyn_map =
|
let dyn_map =
|
||||||
&*self.cache.entry(container).or_insert_with(|| container.child_by_source(db));
|
&*self.cache.entry(container).or_insert_with(|| container.child_by_source(db));
|
||||||
dyn_map[key].get(&src).copied()
|
Some(dyn_map)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn type_param_to_def(&mut self, src: InFile<ast::TypeParam>) -> Option<TypeParamId> {
|
pub(super) fn type_param_to_def(&mut self, src: InFile<ast::TypeParam>) -> Option<TypeParamId> {
|
||||||
|
|
|
@ -85,6 +85,10 @@ impl ChildBySource for ItemScope {
|
||||||
res[keys::CONST].insert(src, konst);
|
res[keys::CONST].insert(src, konst);
|
||||||
});
|
});
|
||||||
self.impls().for_each(|imp| add_impl(db, res, imp));
|
self.impls().for_each(|imp| add_impl(db, res, imp));
|
||||||
|
self.attr_macro_invocs().for_each(|(ast_id, call_id)| {
|
||||||
|
let item = ast_id.with_value(ast_id.to_node(db.upcast()));
|
||||||
|
res[keys::ATTR_MACRO].insert(item, call_id);
|
||||||
|
});
|
||||||
|
|
||||||
fn add_module_def(db: &dyn DefDatabase, map: &mut DynMap, item: ModuleDefId) {
|
fn add_module_def(db: &dyn DefDatabase, map: &mut DynMap, item: ModuleDefId) {
|
||||||
match item {
|
match item {
|
||||||
|
|
|
@ -4,11 +4,11 @@
|
||||||
use std::collections::hash_map::Entry;
|
use std::collections::hash_map::Entry;
|
||||||
|
|
||||||
use base_db::CrateId;
|
use base_db::CrateId;
|
||||||
use hir_expand::name::Name;
|
use hir_expand::{name::Name, AstId, MacroCallId, MacroDefKind};
|
||||||
use hir_expand::MacroDefKind;
|
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use rustc_hash::{FxHashMap, FxHashSet};
|
use rustc_hash::{FxHashMap, FxHashSet};
|
||||||
use stdx::format_to;
|
use stdx::format_to;
|
||||||
|
use syntax::ast;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
db::DefDatabase, per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType, ConstId, ImplId,
|
db::DefDatabase, per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType, ConstId, ImplId,
|
||||||
|
@ -53,6 +53,7 @@ pub struct ItemScope {
|
||||||
// FIXME: Macro shadowing in one module is not properly handled. Non-item place macros will
|
// FIXME: Macro shadowing in one module is not properly handled. Non-item place macros will
|
||||||
// be all resolved to the last one defined if shadowing happens.
|
// be all resolved to the last one defined if shadowing happens.
|
||||||
legacy_macros: FxHashMap<Name, MacroDefId>,
|
legacy_macros: FxHashMap<Name, MacroDefId>,
|
||||||
|
attr_macros: FxHashMap<AstId<ast::Item>, MacroCallId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) static BUILTIN_SCOPE: Lazy<FxHashMap<Name, PerNs>> = Lazy::new(|| {
|
pub(crate) static BUILTIN_SCOPE: Lazy<FxHashMap<Name, PerNs>> = Lazy::new(|| {
|
||||||
|
@ -169,6 +170,16 @@ impl ItemScope {
|
||||||
self.legacy_macros.insert(name, mac);
|
self.legacy_macros.insert(name, mac);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn add_attr_macro_invoc(&mut self, item: AstId<ast::Item>, call: MacroCallId) {
|
||||||
|
self.attr_macros.insert(item, call);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn attr_macro_invocs(
|
||||||
|
&self,
|
||||||
|
) -> impl Iterator<Item = (AstId<ast::Item>, MacroCallId)> + '_ {
|
||||||
|
self.attr_macros.iter().map(|(k, v)| (*k, *v))
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn unnamed_trait_vis(&self, tr: TraitId) -> Option<Visibility> {
|
pub(crate) fn unnamed_trait_vis(&self, tr: TraitId) -> Option<Visibility> {
|
||||||
self.unnamed_trait_imports.get(&tr).copied()
|
self.unnamed_trait_imports.get(&tr).copied()
|
||||||
}
|
}
|
||||||
|
@ -307,6 +318,7 @@ impl ItemScope {
|
||||||
unnamed_consts,
|
unnamed_consts,
|
||||||
unnamed_trait_imports,
|
unnamed_trait_imports,
|
||||||
legacy_macros,
|
legacy_macros,
|
||||||
|
attr_macros,
|
||||||
} = self;
|
} = self;
|
||||||
types.shrink_to_fit();
|
types.shrink_to_fit();
|
||||||
values.shrink_to_fit();
|
values.shrink_to_fit();
|
||||||
|
@ -317,6 +329,7 @@ impl ItemScope {
|
||||||
unnamed_consts.shrink_to_fit();
|
unnamed_consts.shrink_to_fit();
|
||||||
unnamed_trait_imports.shrink_to_fit();
|
unnamed_trait_imports.shrink_to_fit();
|
||||||
legacy_macros.shrink_to_fit();
|
legacy_macros.shrink_to_fit();
|
||||||
|
attr_macros.shrink_to_fit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
use hir_expand::{InFile, MacroDefId};
|
use hir_expand::{InFile, MacroCallId, MacroDefId};
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
use syntax::{ast, AstNode, AstPtr};
|
use syntax::{ast, AstNode, AstPtr};
|
||||||
|
|
||||||
|
@ -32,6 +32,7 @@ pub const LIFETIME_PARAM: Key<ast::LifetimeParam, LifetimeParamId> = Key::new();
|
||||||
pub const CONST_PARAM: Key<ast::ConstParam, ConstParamId> = Key::new();
|
pub const CONST_PARAM: Key<ast::ConstParam, ConstParamId> = Key::new();
|
||||||
|
|
||||||
pub const MACRO: Key<ast::MacroCall, MacroDefId> = Key::new();
|
pub const MACRO: Key<ast::MacroCall, MacroDefId> = Key::new();
|
||||||
|
pub const ATTR_MACRO: Key<ast::Item, MacroCallId> = Key::new();
|
||||||
|
|
||||||
/// XXX: AST Nodes and SyntaxNodes have identity equality semantics: nodes are
|
/// XXX: AST Nodes and SyntaxNodes have identity equality semantics: nodes are
|
||||||
/// equal if they point to exactly the same object.
|
/// equal if they point to exactly the same object.
|
||||||
|
|
|
@ -1112,6 +1112,11 @@ impl DefCollector<'_> {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.def_map.modules[directive.module_id]
|
||||||
|
.scope
|
||||||
|
.add_attr_macro_invoc(ast_id.ast_id, call_id);
|
||||||
|
|
||||||
resolved.push((directive.module_id, call_id, directive.depth));
|
resolved.push((directive.module_id, call_id, directive.depth));
|
||||||
res = ReachedFixedPoint::No;
|
res = ReachedFixedPoint::No;
|
||||||
return false;
|
return false;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue