Skip to content

Commit d2fab1a

Browse files
committed
Re-implement syntax fixups
1 parent 7a8c4c0 commit d2fab1a

File tree

5 files changed

+380
-241
lines changed

5 files changed

+380
-241
lines changed

crates/hir-expand/src/db.rs

+68-35
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use base_db::{
99
use either::Either;
1010
use limit::Limit;
1111
use mbe::{syntax_node_to_token_tree, ValueResult};
12+
use rustc_hash::FxHashSet;
1213
use syntax::{
1314
ast::{self, HasAttrs, HasDocComments},
1415
AstNode, Parse, SyntaxError, SyntaxNode, SyntaxToken, T,
@@ -20,6 +21,7 @@ use crate::{
2021
attrs::RawAttrs,
2122
builtin_attr_macro::pseudo_derive_attr_expansion,
2223
builtin_fn_macro::EagerExpander,
24+
fixup::{self, SyntaxFixupUndoInfo},
2325
hygiene::{self, SyntaxContextData, Transparency},
2426
span::{RealSpanMap, SpanMap, SpanMapRef},
2527
tt, AstId, BuiltinAttrExpander, BuiltinDeriveExpander, BuiltinFnLikeExpander, EagerCallInfo,
@@ -135,7 +137,7 @@ pub trait ExpandDatabase: SourceDatabase {
135137
fn macro_arg(
136138
&self,
137139
id: MacroCallId,
138-
) -> ValueResult<Option<Arc<tt::Subtree>>, Arc<Box<[SyntaxError]>>>;
140+
) -> ValueResult<Option<(Arc<tt::Subtree>, SyntaxFixupUndoInfo)>, Arc<Box<[SyntaxError]>>>;
139141
/// Fetches the expander for this macro.
140142
#[salsa::transparent]
141143
fn macro_expander(&self, id: MacroDefId) -> TokenExpander;
@@ -189,15 +191,33 @@ pub fn expand_speculative(
189191
) -> Option<(SyntaxNode, SyntaxToken)> {
190192
let loc = db.lookup_intern_macro_call(actual_macro_call);
191193

192-
// Build the subtree and token mapping for the speculative args
193-
let _censor = censor_for_macro_input(&loc, speculative_args);
194194
let span_map = RealSpanMap::absolute(SpanAnchor::DUMMY.file_id);
195195
let span_map = SpanMapRef::RealSpanMap(&span_map);
196-
let mut tt = mbe::syntax_node_to_token_tree(
197-
speculative_args,
198-
// we don't leak these spans into any query so its fine to make them absolute
199-
span_map,
200-
);
196+
197+
// Build the subtree and token mapping for the speculative args
198+
let (mut tt, undo_info) = match loc.kind {
199+
MacroCallKind::FnLike { .. } => {
200+
(mbe::syntax_node_to_token_tree(speculative_args, span_map), SyntaxFixupUndoInfo::NONE)
201+
}
202+
MacroCallKind::Derive { .. } | MacroCallKind::Attr { .. } => {
203+
let censor = censor_for_macro_input(&loc, speculative_args);
204+
let mut fixups = fixup::fixup_syntax(span_map, speculative_args);
205+
fixups.append.retain(|it, _| match it {
206+
syntax::NodeOrToken::Node(it) => !censor.contains(it),
207+
syntax::NodeOrToken::Token(_) => true,
208+
});
209+
fixups.remove.extend(censor);
210+
(
211+
mbe::syntax_node_to_token_tree_modified(
212+
speculative_args,
213+
span_map,
214+
fixups.append,
215+
fixups.remove,
216+
),
217+
fixups.undo_info,
218+
)
219+
}
220+
};
201221

202222
let attr_arg = match loc.kind {
203223
MacroCallKind::Attr { invoc_attr_index, .. } => {
@@ -227,7 +247,7 @@ pub fn expand_speculative(
227247

228248
// Do the actual expansion, we need to directly expand the proc macro due to the attribute args
229249
// Otherwise the expand query will fetch the non speculative attribute args and pass those instead.
230-
let speculative_expansion = match loc.def.kind {
250+
let mut speculative_expansion = match loc.def.kind {
231251
MacroDefKind::ProcMacro(expander, ..) => {
232252
tt.delimiter = tt::Delimiter::UNSPECIFIED;
233253
let call_site = loc.span(db);
@@ -261,6 +281,7 @@ pub fn expand_speculative(
261281
};
262282

263283
let expand_to = macro_expand_to(db, actual_macro_call);
284+
fixup::reverse_fixups(&mut speculative_expansion.value, &undo_info);
264285
let (node, rev_tmap) = token_tree_to_syntax_node(&speculative_expansion.value, expand_to);
265286

266287
let syntax_node = node.syntax_node();
@@ -347,7 +368,9 @@ fn parse_with_map(db: &dyn ExpandDatabase, file_id: HirFileId) -> (Parse<SyntaxN
347368
fn macro_arg(
348369
db: &dyn ExpandDatabase,
349370
id: MacroCallId,
350-
) -> ValueResult<Option<Arc<tt::Subtree>>, Arc<Box<[SyntaxError]>>> {
371+
// FIXME: consider the following by putting fixup info into eager call info args
372+
// ) -> ValueResult<Option<Arc<(tt::Subtree, SyntaxFixupUndoInfo)>>, Arc<Box<[SyntaxError]>>> {
373+
) -> ValueResult<Option<(Arc<tt::Subtree>, SyntaxFixupUndoInfo)>, Arc<Box<[SyntaxError]>>> {
351374
let mismatched_delimiters = |arg: &SyntaxNode| {
352375
let first = arg.first_child_or_token().map_or(T![.], |it| it.kind());
353376
let last = arg.last_child_or_token().map_or(T![.], |it| it.kind());
@@ -375,7 +398,7 @@ fn macro_arg(
375398
.then(|| loc.eager.as_deref())
376399
.flatten()
377400
{
378-
ValueResult::ok(Some(arg.clone()))
401+
ValueResult::ok(Some((arg.clone(), SyntaxFixupUndoInfo::NONE)))
379402
} else {
380403
let (parse, map) = parse_with_map(db, loc.kind.file_id());
381404
let root = parse.syntax_node();
@@ -404,22 +427,27 @@ fn macro_arg(
404427
}
405428
MacroCallKind::Attr { ast_id, .. } => ast_id.to_ptr(db).to_node(&root).syntax().clone(),
406429
};
407-
let censor = censor_for_macro_input(&loc, &syntax);
408-
let mut tt = match loc.kind {
430+
let (mut tt, undo_info) = match loc.kind {
409431
MacroCallKind::FnLike { .. } => {
410-
mbe::syntax_node_to_token_tree_censored(&syntax, map.as_ref(), censor)
432+
(mbe::syntax_node_to_token_tree(&syntax, map.as_ref()), SyntaxFixupUndoInfo::NONE)
411433
}
412434
MacroCallKind::Derive { .. } | MacroCallKind::Attr { .. } => {
413-
// let mut fixups = crate::fixup::fixup_syntax(&syntax);
414-
// fixups.replace.extend(censor.into_iter().map(|node| (node.into(), Vec::new())));
415-
// let (mut tt, tmap, _) = mbe::syntax_node_to_token_tree_with_modifications(
416-
// &node,
417-
// fixups.token_map,
418-
// fixups.next_id,
419-
// fixups.replace,
420-
// fixups.append,
421-
// );
422-
mbe::syntax_node_to_token_tree_censored(&syntax, map.as_ref(), censor)
435+
let censor = censor_for_macro_input(&loc, &syntax);
436+
let mut fixups = fixup::fixup_syntax(map.as_ref(), &syntax);
437+
fixups.append.retain(|it, _| match it {
438+
syntax::NodeOrToken::Node(it) => !censor.contains(it),
439+
syntax::NodeOrToken::Token(_) => true,
440+
});
441+
fixups.remove.extend(censor);
442+
(
443+
mbe::syntax_node_to_token_tree_modified(
444+
&syntax,
445+
map,
446+
fixups.append,
447+
fixups.remove,
448+
),
449+
fixups.undo_info,
450+
)
423451
}
424452
};
425453

@@ -430,15 +458,15 @@ fn macro_arg(
430458

431459
if matches!(loc.def.kind, MacroDefKind::BuiltInEager(..)) {
432460
match parse.errors() {
433-
[] => ValueResult::ok(Some(Arc::new(tt))),
461+
[] => ValueResult::ok(Some((Arc::new(tt), undo_info))),
434462
errors => ValueResult::new(
435-
Some(Arc::new(tt)),
463+
Some((Arc::new(tt), undo_info)),
436464
// Box::<[_]>::from(res.errors()), not stable yet
437465
Arc::new(errors.to_vec().into_boxed_slice()),
438466
),
439467
}
440468
} else {
441-
ValueResult::ok(Some(Arc::new(tt)))
469+
ValueResult::ok(Some((Arc::new(tt), undo_info)))
442470
}
443471
}
444472
}
@@ -447,7 +475,7 @@ fn macro_arg(
447475
/// Certain macro calls expect some nodes in the input to be preprocessed away, namely:
448476
/// - derives expect all `#[derive(..)]` invocations up to the currently invoked one to be stripped
449477
/// - attributes expect the invoking attribute to be stripped
450-
fn censor_for_macro_input(loc: &MacroCallLoc, node: &SyntaxNode) -> Vec<SyntaxNode> {
478+
fn censor_for_macro_input(loc: &MacroCallLoc, node: &SyntaxNode) -> FxHashSet<SyntaxNode> {
451479
// FIXME: handle `cfg_attr`
452480
(|| {
453481
let censor = match loc.kind {
@@ -574,13 +602,13 @@ fn macro_expand(
574602
let MacroCallKind::Derive { ast_id, .. } = loc.kind else { unreachable!() };
575603
let node = ast_id.to_ptr(db).to_node(&root);
576604

577-
// FIXME: we might need to remove the spans from the input to the derive macro here
605+
// FIXME: Use censoring
578606
let _censor = censor_for_macro_input(&loc, node.syntax());
579607
expander.expand(db, macro_call_id, &node, map.as_ref())
580608
}
581609
_ => {
582610
let ValueResult { value, err } = db.macro_arg(macro_call_id);
583-
let Some(macro_arg) = value else {
611+
let Some((macro_arg, undo_info)) = value else {
584612
return ExpandResult {
585613
value: Arc::new(tt::Subtree {
586614
delimiter: tt::Delimiter::UNSPECIFIED,
@@ -608,7 +636,7 @@ fn macro_expand(
608636
// As such we just return the input subtree here.
609637
MacroDefKind::BuiltInEager(..) if loc.eager.is_none() => {
610638
return ExpandResult {
611-
value: Arc::new(arg.clone()),
639+
value: macro_arg.clone(),
612640
err: err.map(|err| {
613641
let mut buf = String::new();
614642
for err in &**err {
@@ -624,7 +652,11 @@ fn macro_expand(
624652
MacroDefKind::BuiltInEager(it, _) => {
625653
it.expand(db, macro_call_id, &arg).map_err(Into::into)
626654
}
627-
MacroDefKind::BuiltInAttr(it, _) => it.expand(db, macro_call_id, &arg),
655+
MacroDefKind::BuiltInAttr(it, _) => {
656+
let mut res = it.expand(db, macro_call_id, &arg);
657+
fixup::reverse_fixups(&mut res.value, &undo_info);
658+
res
659+
}
628660
_ => unreachable!(),
629661
}
630662
}
@@ -647,9 +679,8 @@ fn macro_expand(
647679
}
648680

649681
fn expand_proc_macro(db: &dyn ExpandDatabase, id: MacroCallId) -> ExpandResult<Arc<tt::Subtree>> {
650-
// FIXME: Syntax fix ups
651682
let loc = db.lookup_intern_macro_call(id);
652-
let Some(macro_arg) = db.macro_arg(id).value else {
683+
let Some((macro_arg, undo_info)) = db.macro_arg(id).value else {
653684
return ExpandResult {
654685
value: Arc::new(tt::Subtree {
655686
delimiter: tt::Delimiter::UNSPECIFIED,
@@ -672,7 +703,7 @@ fn expand_proc_macro(db: &dyn ExpandDatabase, id: MacroCallId) -> ExpandResult<A
672703
};
673704

674705
let call_site = loc.span(db);
675-
let ExpandResult { value: tt, err } = expander.expand(
706+
let ExpandResult { value: mut tt, err } = expander.expand(
676707
db,
677708
loc.def.krate,
678709
loc.krate,
@@ -690,6 +721,8 @@ fn expand_proc_macro(db: &dyn ExpandDatabase, id: MacroCallId) -> ExpandResult<A
690721
return value;
691722
}
692723

724+
fixup::reverse_fixups(&mut tt, &undo_info);
725+
693726
ExpandResult { value: Arc::new(tt), err }
694727
}
695728

0 commit comments

Comments
 (0)