mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-02 22:54:58 +00:00
internal: Expand the derive attribute into a pseudo expansion
This commit is contained in:
parent
1fe3b2edd6
commit
7b89d5ede2
17 changed files with 178 additions and 155 deletions
|
@ -116,11 +116,11 @@ impl ChildBySource for ItemScope {
|
|||
self.derive_macro_invocs().filter(|(id, _)| id.file_id == file_id).for_each(
|
||||
|(ast_id, calls)| {
|
||||
let adt = ast_id.to_node(db.upcast());
|
||||
calls.for_each(|(attr_id, calls)| {
|
||||
calls.for_each(|(attr_id, call_id, calls)| {
|
||||
if let Some(Either::Left(attr)) =
|
||||
adt.doc_comments_and_attrs().nth(attr_id.ast_index as usize)
|
||||
{
|
||||
res[keys::DERIVE_MACRO_CALL].insert(attr, (attr_id, calls.into()));
|
||||
res[keys::DERIVE_MACRO_CALL].insert(attr, (attr_id, call_id, calls.into()));
|
||||
}
|
||||
});
|
||||
},
|
||||
|
|
|
@ -66,8 +66,10 @@ pub struct ItemScope {
|
|||
attr_macros: FxHashMap<AstId<ast::Item>, MacroCallId>,
|
||||
/// The derive macro invocations in this scope, keyed by the owner item over the actual derive attributes
|
||||
/// paired with the derive macro invocations for the specific attribute.
|
||||
derive_macros:
|
||||
FxHashMap<AstId<ast::Adt>, SmallVec<[(AttrId, SmallVec<[Option<MacroCallId>; 1]>); 1]>>,
|
||||
derive_macros: FxHashMap<
|
||||
AstId<ast::Adt>,
|
||||
SmallVec<[(AttrId, MacroCallId, SmallVec<[Option<MacroCallId>; 1]>); 1]>,
|
||||
>,
|
||||
}
|
||||
|
||||
pub(crate) static BUILTIN_SCOPE: Lazy<FxHashMap<Name, PerNs>> = Lazy::new(|| {
|
||||
|
@ -210,7 +212,7 @@ impl ItemScope {
|
|||
idx: usize,
|
||||
) {
|
||||
if let Some(derives) = self.derive_macros.get_mut(&adt) {
|
||||
if let Some((_, invocs)) = derives.iter_mut().find(|&&mut (id, _)| id == attr_id) {
|
||||
if let Some((.., invocs)) = derives.iter_mut().find(|&&mut (id, ..)| id == attr_id) {
|
||||
invocs[idx] = Some(call);
|
||||
}
|
||||
}
|
||||
|
@ -223,19 +225,23 @@ impl ItemScope {
|
|||
&mut self,
|
||||
adt: AstId<ast::Adt>,
|
||||
attr_id: AttrId,
|
||||
call_id: MacroCallId,
|
||||
len: usize,
|
||||
) {
|
||||
self.derive_macros.entry(adt).or_default().push((attr_id, smallvec![None; len]));
|
||||
self.derive_macros.entry(adt).or_default().push((attr_id, call_id, smallvec![None; len]));
|
||||
}
|
||||
|
||||
pub(crate) fn derive_macro_invocs(
|
||||
&self,
|
||||
) -> impl Iterator<
|
||||
Item = (AstId<ast::Adt>, impl Iterator<Item = (AttrId, &[Option<MacroCallId>])>),
|
||||
Item = (
|
||||
AstId<ast::Adt>,
|
||||
impl Iterator<Item = (AttrId, MacroCallId, &[Option<MacroCallId>])>,
|
||||
),
|
||||
> + '_ {
|
||||
self.derive_macros
|
||||
.iter()
|
||||
.map(|(k, v)| (*k, v.iter().map(|(attr_id, invocs)| (*attr_id, &**invocs))))
|
||||
self.derive_macros.iter().map(|(k, v)| {
|
||||
(*k, v.iter().map(|&(attr_id, call_id, ref invocs)| (attr_id, call_id, &**invocs)))
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn unnamed_trait_vis(&self, tr: TraitId) -> Option<Visibility> {
|
||||
|
|
|
@ -34,7 +34,8 @@ pub const CONST_PARAM: Key<ast::ConstParam, ConstParamId> = Key::new();
|
|||
|
||||
pub const MACRO: Key<ast::Macro, MacroDefId> = Key::new();
|
||||
pub const ATTR_MACRO_CALL: Key<ast::Item, MacroCallId> = Key::new();
|
||||
pub const DERIVE_MACRO_CALL: Key<ast::Attr, (AttrId, Box<[Option<MacroCallId>]>)> = Key::new();
|
||||
pub const DERIVE_MACRO_CALL: Key<ast::Attr, (AttrId, MacroCallId, Box<[Option<MacroCallId>]>)> =
|
||||
Key::new();
|
||||
|
||||
/// XXX: AST Nodes and SyntaxNodes have identity equality semantics: nodes are
|
||||
/// equal if they point to exactly the same object.
|
||||
|
|
|
@ -690,9 +690,9 @@ impl AsMacroCall for InFile<&ast::MacroCall> {
|
|||
};
|
||||
|
||||
macro_call_as_call_id(
|
||||
db,
|
||||
&AstIdWithPath::new(ast_id.file_id, ast_id.value, path),
|
||||
expands_to,
|
||||
db,
|
||||
krate,
|
||||
resolver,
|
||||
error_sink,
|
||||
|
@ -714,9 +714,9 @@ impl<T: ast::AstNode> AstIdWithPath<T> {
|
|||
}
|
||||
|
||||
fn macro_call_as_call_id(
|
||||
db: &dyn db::DefDatabase,
|
||||
call: &AstIdWithPath<ast::MacroCall>,
|
||||
expand_to: ExpandTo,
|
||||
db: &dyn db::DefDatabase,
|
||||
krate: CrateId,
|
||||
resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
|
||||
error_sink: &mut dyn FnMut(ExpandError),
|
||||
|
@ -739,10 +739,10 @@ fn macro_call_as_call_id(
|
|||
}
|
||||
|
||||
fn derive_macro_as_call_id(
|
||||
db: &dyn db::DefDatabase,
|
||||
item_attr: &AstIdWithPath<ast::Adt>,
|
||||
derive_attr: AttrId,
|
||||
derive_pos: u32,
|
||||
db: &dyn db::DefDatabase,
|
||||
krate: CrateId,
|
||||
resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
|
||||
) -> Result<MacroCallId, UnresolvedMacro> {
|
||||
|
@ -761,11 +761,12 @@ fn derive_macro_as_call_id(
|
|||
}
|
||||
|
||||
fn attr_macro_as_call_id(
|
||||
db: &dyn db::DefDatabase,
|
||||
item_attr: &AstIdWithPath<ast::Item>,
|
||||
macro_attr: &Attr,
|
||||
db: &dyn db::DefDatabase,
|
||||
krate: CrateId,
|
||||
def: MacroDefId,
|
||||
is_derive: bool,
|
||||
) -> MacroCallId {
|
||||
let mut arg = match macro_attr.input.as_deref() {
|
||||
Some(attr::AttrInput::TokenTree(tt, map)) => (tt.clone(), map.clone()),
|
||||
|
@ -782,6 +783,7 @@ fn attr_macro_as_call_id(
|
|||
ast_id: item_attr.ast_id,
|
||||
attr_args: Arc::new(arg),
|
||||
invoc_attr_index: macro_attr.id.ast_index,
|
||||
is_derive,
|
||||
},
|
||||
);
|
||||
res
|
||||
|
|
|
@ -54,7 +54,7 @@ impl DefMap {
|
|||
None => return Err(UnresolvedMacro { path: ast_id.path.clone() }),
|
||||
};
|
||||
|
||||
Ok(ResolvedAttr::Macro(attr_macro_as_call_id(&ast_id, attr, db, self.krate, def)))
|
||||
Ok(ResolvedAttr::Macro(attr_macro_as_call_id(db, &ast_id, attr, self.krate, def, false)))
|
||||
}
|
||||
|
||||
pub(crate) fn is_builtin_or_registered_attr(&self, path: &ModPath) -> bool {
|
||||
|
|
|
@ -1055,9 +1055,9 @@ impl DefCollector<'_> {
|
|||
match &directive.kind {
|
||||
MacroDirectiveKind::FnLike { ast_id, expand_to } => {
|
||||
let call_id = macro_call_as_call_id(
|
||||
self.db,
|
||||
ast_id,
|
||||
*expand_to,
|
||||
self.db,
|
||||
self.def_map.krate,
|
||||
&resolver,
|
||||
&mut |_err| (),
|
||||
|
@ -1070,10 +1070,10 @@ impl DefCollector<'_> {
|
|||
}
|
||||
MacroDirectiveKind::Derive { ast_id, derive_attr, derive_pos } => {
|
||||
let call_id = derive_macro_as_call_id(
|
||||
self.db,
|
||||
ast_id,
|
||||
*derive_attr,
|
||||
*derive_pos as u32,
|
||||
self.db,
|
||||
self.def_map.krate,
|
||||
&resolver,
|
||||
);
|
||||
|
@ -1170,9 +1170,17 @@ impl DefCollector<'_> {
|
|||
len = idx;
|
||||
}
|
||||
|
||||
let call_id = attr_macro_as_call_id(
|
||||
self.db,
|
||||
file_ast_id,
|
||||
attr,
|
||||
self.def_map.krate,
|
||||
def,
|
||||
true,
|
||||
);
|
||||
self.def_map.modules[directive.module_id]
|
||||
.scope
|
||||
.init_derive_attribute(ast_id, attr.id, len + 1);
|
||||
.init_derive_attribute(ast_id, attr.id, call_id, len + 1);
|
||||
}
|
||||
None => {
|
||||
let diag = DefDiagnostic::malformed_derive(
|
||||
|
@ -1192,8 +1200,14 @@ impl DefCollector<'_> {
|
|||
}
|
||||
|
||||
// Not resolved to a derive helper or the derive attribute, so try to treat as a normal attribute.
|
||||
let call_id =
|
||||
attr_macro_as_call_id(file_ast_id, attr, self.db, self.def_map.krate, def);
|
||||
let call_id = attr_macro_as_call_id(
|
||||
self.db,
|
||||
file_ast_id,
|
||||
attr,
|
||||
self.def_map.krate,
|
||||
def,
|
||||
false,
|
||||
);
|
||||
let loc: MacroCallLoc = self.db.lookup_intern_macro_call(call_id);
|
||||
|
||||
// Skip #[test]/#[bench] expansion, which would merely result in more memory usage
|
||||
|
@ -1310,9 +1324,9 @@ impl DefCollector<'_> {
|
|||
match &directive.kind {
|
||||
MacroDirectiveKind::FnLike { ast_id, expand_to } => {
|
||||
let macro_call_as_call_id = macro_call_as_call_id(
|
||||
self.db,
|
||||
ast_id,
|
||||
*expand_to,
|
||||
self.db,
|
||||
self.def_map.krate,
|
||||
|path| {
|
||||
let resolved_res = self.def_map.resolve_path_fp_with_macro(
|
||||
|
@ -1959,9 +1973,9 @@ impl ModCollector<'_, '_> {
|
|||
// Case 1: try to resolve in legacy scope and expand macro_rules
|
||||
let mut error = None;
|
||||
match macro_call_as_call_id(
|
||||
self.def_collector.db,
|
||||
&ast_id,
|
||||
mac.expand_to,
|
||||
self.def_collector.db,
|
||||
self.def_collector.def_map.krate,
|
||||
|path| {
|
||||
path.as_ident().and_then(|name| {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue