Rust: skip macro expansion in unexpanded attribute macro AST

This commit is contained in:
Paolo Tranquilli
2025-05-16 16:15:03 +02:00
parent 32cece3a43
commit abf21ba767
3 changed files with 383 additions and 179 deletions

View File

@@ -2,7 +2,7 @@
use super::base::Translator;
use super::mappings::TextValue;
use crate::emit_detached;
use crate::{pre_emit,post_emit};
use crate::generated;
use crate::trap::{Label, TrapId};
use ra_ap_syntax::ast::{
@@ -22,18 +22,20 @@ impl Translator<'_> {
{{#enums}}
pub(crate) fn emit_{{snake_case_name}}(&mut self, node: &ast::{{ast_name}}) -> Option<Label<generated::{{name}}>> {
pre_emit!({{name}}, self, node);
let label = match node {
{{#variants}}
ast::{{ast_name}}::{{variant_ast_name}}(inner) => self.emit_{{snake_case_name}}(inner).map(Into::into),
{{/variants}}
}?;
emit_detached!({{name}}, self, node, label);
post_emit!({{name}}, self, node, label);
Some(label)
}
{{/enums}}
{{#nodes}}
pub(crate) fn emit_{{snake_case_name}}(&mut self, node: &ast::{{ast_name}}) -> Option<Label<generated::{{name}}>> {
pre_emit!({{name}}, self, node);
{{#has_attrs}}
if self.should_be_excluded(node) { return None; }
{{/has_attrs}}
@@ -58,7 +60,7 @@ impl Translator<'_> {
{{/fields}}
});
self.emit_location(label, node);
emit_detached!({{name}}, self, node, label);
post_emit!({{name}}, self, node, label);
self.emit_tokens(node, label.into(), node.syntax().children_with_tokens());
Some(label)
}

View File

@@ -11,7 +11,7 @@ use ra_ap_hir::{
};
use ra_ap_hir_def::ModuleId;
use ra_ap_hir_def::type_ref::Mutability;
use ra_ap_hir_expand::{ExpandResult, ExpandTo};
use ra_ap_hir_expand::{ExpandResult, ExpandTo, InFile};
use ra_ap_ide_db::RootDatabase;
use ra_ap_ide_db::line_index::{LineCol, LineIndex};
use ra_ap_parser::SyntaxKind;
@@ -23,7 +23,15 @@ use ra_ap_syntax::{
};
#[macro_export]
macro_rules! emit_detached {
macro_rules! pre_emit {
(Item, $self:ident, $node:ident) => {
$self.setup_item_expansion($node);
};
($($_:tt)*) => {};
}
#[macro_export]
macro_rules! post_emit {
(MacroCall, $self:ident, $node:ident, $label:ident) => {
$self.extract_macro_call_expanded($node, $label);
};
@@ -101,7 +109,8 @@ pub struct Translator<'a> {
line_index: LineIndex,
file_id: Option<EditionedFileId>,
pub semantics: Option<&'a Semantics<'a, RootDatabase>>,
resolve_paths: ResolvePaths,
resolve_paths: bool,
macro_context_depth: usize,
}
const UNKNOWN_LOCATION: (LineCol, LineCol) =
@@ -123,7 +132,8 @@ impl<'a> Translator<'a> {
line_index,
file_id: semantic_info.map(|i| i.file_id),
semantics: semantic_info.map(|i| i.semantics),
resolve_paths,
resolve_paths: resolve_paths == ResolvePaths::Yes,
macro_context_depth: 0,
}
}
fn location(&self, range: TextRange) -> Option<(LineCol, LineCol)> {
@@ -321,6 +331,11 @@ impl<'a> Translator<'a> {
mcall: &ast::MacroCall,
label: Label<generated::MacroCall>,
) {
if self.macro_context_depth > 0 {
// we are in an attribute macro, don't emit anything: we would be failing to expand any
// way as rust-analyser now only expands in the context of an expansion
return;
}
if let Some(expanded) = self
.semantics
.as_ref()
@@ -521,7 +536,7 @@ impl<'a> Translator<'a> {
item: &T,
label: Label<generated::Addressable>,
) {
if self.resolve_paths == ResolvePaths::No {
if !self.resolve_paths {
return;
}
(|| {
@@ -544,7 +559,7 @@ impl<'a> Translator<'a> {
item: &ast::Variant,
label: Label<generated::Variant>,
) {
if self.resolve_paths == ResolvePaths::No {
if !self.resolve_paths {
return;
}
(|| {
@@ -567,7 +582,7 @@ impl<'a> Translator<'a> {
item: &impl PathAst,
label: Label<generated::Resolvable>,
) {
if self.resolve_paths == ResolvePaths::No {
if !self.resolve_paths {
return;
}
(|| {
@@ -590,7 +605,7 @@ impl<'a> Translator<'a> {
item: &ast::MethodCallExpr,
label: Label<generated::MethodCallExpr>,
) {
if self.resolve_paths == ResolvePaths::No {
if !self.resolve_paths {
return;
}
(|| {
@@ -653,9 +668,29 @@ impl<'a> Translator<'a> {
}
}
pub(crate) fn setup_item_expansion(&mut self, node: &ast::Item) {
if self.semantics.is_some_and(|s| {
let file = s.hir_file_for(node.syntax());
let node = InFile::new(file, node);
s.is_attr_macro_call(node)
}) {
self.macro_context_depth += 1;
}
}
pub(crate) fn emit_item_expansion(&mut self, node: &ast::Item, label: Label<generated::Item>) {
(|| {
let semantics = self.semantics?;
let file = semantics.hir_file_for(node.syntax());
let infile_node = InFile::new(file, node);
if !semantics.is_attr_macro_call(infile_node) {
return None;
}
self.macro_context_depth -= 1;
if self.macro_context_depth > 0 {
// only expand the outermost attribute macro
return None;
}
let ExpandResult {
value: expanded, ..
} = semantics.expand_attr_macro(node)?;

File diff suppressed because it is too large Load Diff