Skip to content

Commit b99b25c

Browse files
authored
Merge pull request #19572 from github/redsun82/rust-macro
Rust: turn off macro expansion in code to be expanded by attribute macros
2 parents a519eab + a749cf9 commit b99b25c

File tree

10 files changed

+506
-243
lines changed

10 files changed

+506
-243
lines changed

rust/ast-generator/templates/extractor.mustache

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
use super::base::Translator;
44
use super::mappings::TextValue;
5-
use crate::emit_detached;
5+
use crate::{pre_emit,post_emit};
66
use crate::generated;
77
use crate::trap::{Label, TrapId};
88
use ra_ap_syntax::ast::{
@@ -22,18 +22,20 @@ impl Translator<'_> {
2222
{{#enums}}
2323

2424
pub(crate) fn emit_{{snake_case_name}}(&mut self, node: &ast::{{ast_name}}) -> Option<Label<generated::{{name}}>> {
25+
pre_emit!({{name}}, self, node);
2526
let label = match node {
2627
{{#variants}}
2728
ast::{{ast_name}}::{{variant_ast_name}}(inner) => self.emit_{{snake_case_name}}(inner).map(Into::into),
2829
{{/variants}}
2930
}?;
30-
emit_detached!({{name}}, self, node, label);
31+
post_emit!({{name}}, self, node, label);
3132
Some(label)
3233
}
3334
{{/enums}}
3435
{{#nodes}}
3536

3637
pub(crate) fn emit_{{snake_case_name}}(&mut self, node: &ast::{{ast_name}}) -> Option<Label<generated::{{name}}>> {
38+
pre_emit!({{name}}, self, node);
3739
if self.should_be_excluded(node) { return None; }
3840
{{#has_attrs}}
3941
if self.should_be_excluded_attrs(node) { return None; }
@@ -59,7 +61,7 @@ impl Translator<'_> {
5961
{{/fields}}
6062
});
6163
self.emit_location(label, node);
62-
emit_detached!({{name}}, self, node, label);
64+
post_emit!({{name}}, self, node, label);
6365
self.emit_tokens(node, label.into(), node.syntax().children_with_tokens());
6466
Some(label)
6567
}

rust/extractor/src/translate/base.rs

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use ra_ap_hir::{
1111
};
1212
use ra_ap_hir_def::ModuleId;
1313
use ra_ap_hir_def::type_ref::Mutability;
14-
use ra_ap_hir_expand::{ExpandResult, ExpandTo};
14+
use ra_ap_hir_expand::{ExpandResult, ExpandTo, InFile};
1515
use ra_ap_ide_db::RootDatabase;
1616
use ra_ap_ide_db::line_index::{LineCol, LineIndex};
1717
use ra_ap_parser::SyntaxKind;
@@ -23,7 +23,15 @@ use ra_ap_syntax::{
2323
};
2424

2525
#[macro_export]
26-
macro_rules! emit_detached {
26+
macro_rules! pre_emit {
27+
(Item, $self:ident, $node:ident) => {
28+
$self.setup_item_expansion($node);
29+
};
30+
($($_:tt)*) => {};
31+
}
32+
33+
#[macro_export]
34+
macro_rules! post_emit {
2735
(MacroCall, $self:ident, $node:ident, $label:ident) => {
2836
$self.extract_macro_call_expanded($node, $label);
2937
};
@@ -106,8 +114,9 @@ pub struct Translator<'a> {
106114
line_index: LineIndex,
107115
file_id: Option<EditionedFileId>,
108116
pub semantics: Option<&'a Semantics<'a, RootDatabase>>,
109-
resolve_paths: ResolvePaths,
117+
resolve_paths: bool,
110118
source_kind: SourceKind,
119+
macro_context_depth: usize,
111120
}
112121

113122
const UNKNOWN_LOCATION: (LineCol, LineCol) =
@@ -130,8 +139,9 @@ impl<'a> Translator<'a> {
130139
line_index,
131140
file_id: semantic_info.map(|i| i.file_id),
132141
semantics: semantic_info.map(|i| i.semantics),
133-
resolve_paths,
142+
resolve_paths: resolve_paths == ResolvePaths::Yes,
134143
source_kind,
144+
macro_context_depth: 0,
135145
}
136146
}
137147
fn location(&self, range: TextRange) -> Option<(LineCol, LineCol)> {
@@ -337,6 +347,11 @@ impl<'a> Translator<'a> {
337347
mcall: &ast::MacroCall,
338348
label: Label<generated::MacroCall>,
339349
) {
350+
if self.macro_context_depth > 0 {
351+
// we are in an attribute macro, don't emit anything: we would be failing to expand any
352+
// way as from version 0.0.274 rust-analyser only expands in the context of an expansion
353+
return;
354+
}
340355
if let Some(expanded) = self
341356
.semantics
342357
.as_ref()
@@ -537,7 +552,7 @@ impl<'a> Translator<'a> {
537552
item: &T,
538553
label: Label<generated::Addressable>,
539554
) {
540-
if self.resolve_paths == ResolvePaths::No {
555+
if !self.resolve_paths {
541556
return;
542557
}
543558
(|| {
@@ -560,7 +575,7 @@ impl<'a> Translator<'a> {
560575
item: &ast::Variant,
561576
label: Label<generated::Variant>,
562577
) {
563-
if self.resolve_paths == ResolvePaths::No {
578+
if !self.resolve_paths {
564579
return;
565580
}
566581
(|| {
@@ -583,7 +598,7 @@ impl<'a> Translator<'a> {
583598
item: &impl PathAst,
584599
label: Label<generated::Resolvable>,
585600
) {
586-
if self.resolve_paths == ResolvePaths::No {
601+
if !self.resolve_paths {
587602
return;
588603
}
589604
(|| {
@@ -606,7 +621,7 @@ impl<'a> Translator<'a> {
606621
item: &ast::MethodCallExpr,
607622
label: Label<generated::MethodCallExpr>,
608623
) {
609-
if self.resolve_paths == ResolvePaths::No {
624+
if !self.resolve_paths {
610625
return;
611626
}
612627
(|| {
@@ -708,13 +723,33 @@ impl<'a> Translator<'a> {
708723
}
709724
}
710725

726+
pub(crate) fn setup_item_expansion(&mut self, node: &ast::Item) {
727+
if self.semantics.is_some_and(|s| {
728+
let file = s.hir_file_for(node.syntax());
729+
let node = InFile::new(file, node);
730+
s.is_attr_macro_call(node)
731+
}) {
732+
self.macro_context_depth += 1;
733+
}
734+
}
735+
711736
pub(crate) fn emit_item_expansion(&mut self, node: &ast::Item, label: Label<generated::Item>) {
712737
// TODO: remove this after fixing exponential expansion on libraries like funty-2.0.0
713738
if self.source_kind == SourceKind::Library {
714739
return;
715740
}
716741
(|| {
717742
let semantics = self.semantics?;
743+
let file = semantics.hir_file_for(node.syntax());
744+
let infile_node = InFile::new(file, node);
745+
if !semantics.is_attr_macro_call(infile_node) {
746+
return None;
747+
}
748+
self.macro_context_depth -= 1;
749+
if self.macro_context_depth > 0 {
750+
// only expand the outermost attribute macro
751+
return None;
752+
}
718753
let ExpandResult {
719754
value: expanded, ..
720755
} = semantics.expand_attr_macro(node)?;

0 commit comments

Comments
 (0)