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

View File

@@ -11,7 +11,7 @@ use ra_ap_hir::{
}; };
use ra_ap_hir_def::ModuleId; use ra_ap_hir_def::ModuleId;
use ra_ap_hir_def::type_ref::Mutability; 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::RootDatabase;
use ra_ap_ide_db::line_index::{LineCol, LineIndex}; use ra_ap_ide_db::line_index::{LineCol, LineIndex};
use ra_ap_parser::SyntaxKind; use ra_ap_parser::SyntaxKind;
@@ -23,7 +23,15 @@ use ra_ap_syntax::{
}; };
#[macro_export] #[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) => { (MacroCall, $self:ident, $node:ident, $label:ident) => {
$self.extract_macro_call_expanded($node, $label); $self.extract_macro_call_expanded($node, $label);
}; };
@@ -101,7 +109,8 @@ pub struct Translator<'a> {
line_index: LineIndex, line_index: LineIndex,
file_id: Option<EditionedFileId>, file_id: Option<EditionedFileId>,
pub semantics: Option<&'a Semantics<'a, RootDatabase>>, pub semantics: Option<&'a Semantics<'a, RootDatabase>>,
resolve_paths: ResolvePaths, resolve_paths: bool,
macro_context_depth: usize,
} }
const UNKNOWN_LOCATION: (LineCol, LineCol) = const UNKNOWN_LOCATION: (LineCol, LineCol) =
@@ -123,7 +132,8 @@ impl<'a> Translator<'a> {
line_index, line_index,
file_id: semantic_info.map(|i| i.file_id), file_id: semantic_info.map(|i| i.file_id),
semantics: semantic_info.map(|i| i.semantics), 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)> { fn location(&self, range: TextRange) -> Option<(LineCol, LineCol)> {
@@ -321,6 +331,11 @@ impl<'a> Translator<'a> {
mcall: &ast::MacroCall, mcall: &ast::MacroCall,
label: Label<generated::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 if let Some(expanded) = self
.semantics .semantics
.as_ref() .as_ref()
@@ -521,7 +536,7 @@ impl<'a> Translator<'a> {
item: &T, item: &T,
label: Label<generated::Addressable>, label: Label<generated::Addressable>,
) { ) {
if self.resolve_paths == ResolvePaths::No { if !self.resolve_paths {
return; return;
} }
(|| { (|| {
@@ -544,7 +559,7 @@ impl<'a> Translator<'a> {
item: &ast::Variant, item: &ast::Variant,
label: Label<generated::Variant>, label: Label<generated::Variant>,
) { ) {
if self.resolve_paths == ResolvePaths::No { if !self.resolve_paths {
return; return;
} }
(|| { (|| {
@@ -567,7 +582,7 @@ impl<'a> Translator<'a> {
item: &impl PathAst, item: &impl PathAst,
label: Label<generated::Resolvable>, label: Label<generated::Resolvable>,
) { ) {
if self.resolve_paths == ResolvePaths::No { if !self.resolve_paths {
return; return;
} }
(|| { (|| {
@@ -590,7 +605,7 @@ impl<'a> Translator<'a> {
item: &ast::MethodCallExpr, item: &ast::MethodCallExpr,
label: Label<generated::MethodCallExpr>, label: Label<generated::MethodCallExpr>,
) { ) {
if self.resolve_paths == ResolvePaths::No { if !self.resolve_paths {
return; 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>) { pub(crate) fn emit_item_expansion(&mut self, node: &ast::Item, label: Label<generated::Item>) {
(|| { (|| {
let semantics = self.semantics?; 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 { let ExpandResult {
value: expanded, .. value: expanded, ..
} = semantics.expand_attr_macro(node)?; } = semantics.expand_attr_macro(node)?;

File diff suppressed because it is too large Load Diff