@@ -8470,21 +8470,91 @@ bool RefactoringActionAddAsyncWrapper::performChange() {
8470
8470
return false ;
8471
8471
}
8472
8472
8473
- static MacroExpansionExpr *
8474
- findMacroExpansionTargetExpr (const ResolvedCursorInfo &Info) {
8473
+ // / Retrieve the macro expansion buffer for the given macro expansion
8474
+ // / expression.
8475
+ static Optional<unsigned > getMacroExpansionBuffer (
8476
+ SourceManager &sourceMgr, MacroExpansionExpr *expansion) {
8477
+ if (auto rewritten = expansion->getRewritten ()) {
8478
+ return sourceMgr.findBufferContainingLoc (rewritten->getStartLoc ());
8479
+ }
8480
+
8481
+ return None;
8482
+ }
8483
+
8484
+ // / Retrieve the macro expansion buffers for the given attached macro reference.
8485
+ static llvm::SmallVector<unsigned , 2 >
8486
+ getMacroExpansionBuffers (MacroDecl *macro, const CustomAttr *attr, Decl *decl) {
8487
+ auto roles = macro->getMacroRoles () & getAttachedMacroRoles ();
8488
+ if (!roles)
8489
+ return { };
8490
+
8491
+ ASTContext &ctx = macro->getASTContext ();
8492
+ llvm::SmallVector<unsigned , 2 > allBufferIDs;
8493
+ if (roles.contains (MacroRole::Accessor)) {
8494
+ // FIXME: Need to requestify.
8495
+ }
8496
+
8497
+ if (roles.contains (MacroRole::MemberAttribute)) {
8498
+ if (auto idc = dyn_cast<IterableDeclContext>(decl)) {
8499
+ for (auto memberDecl : idc->getAllMembers ()) {
8500
+ auto bufferIDs = evaluateOrDefault (
8501
+ ctx.evaluator , ExpandMemberAttributeMacros{memberDecl}, { });
8502
+ allBufferIDs.append (bufferIDs.begin (), bufferIDs.end ());
8503
+ }
8504
+ }
8505
+ }
8475
8506
8507
+ if (roles.contains (MacroRole::Member)) {
8508
+ auto bufferIDs = evaluateOrDefault (
8509
+ ctx.evaluator , ExpandSynthesizedMemberMacroRequest{decl}, { });
8510
+ allBufferIDs.append (bufferIDs.begin (), bufferIDs.end ());
8511
+ }
8512
+
8513
+ // Drop any buffers that come from other macros. We could eliminate this
8514
+ // step by adding more fine-grained requests above, which only expand for a
8515
+ // single custom attribute.
8516
+ SourceManager &sourceMgr = ctx.SourceMgr ;
8517
+ auto removedAt = std::remove_if (
8518
+ allBufferIDs.begin (), allBufferIDs.end (),
8519
+ [&](unsigned bufferID) {
8520
+ auto generatedInfo = sourceMgr.getGeneratedSourceInfo (bufferID);
8521
+ if (!generatedInfo)
8522
+ return true ;
8523
+
8524
+ return generatedInfo->attachedMacroCustomAttr != attr;
8525
+ });
8526
+ allBufferIDs.erase (removedAt, allBufferIDs.end ());
8527
+ return allBufferIDs;
8528
+ }
8529
+
8530
+ // / Given a resolved cursor, determine whether it is for a macro expansion and
8531
+ // / return the list of macro expansion buffer IDs that are associated with the
8532
+ // / macro reference here.
8533
+ static llvm::SmallVector<unsigned , 2 >
8534
+ getMacroExpansionBuffers (
8535
+ SourceManager &sourceMgr, const ResolvedCursorInfo &Info
8536
+ ) {
8476
8537
// Handle '#' position in '#macroName(...)'.
8477
8538
if (auto exprInfo = dyn_cast<ResolvedExprStartCursorInfo>(&Info)) {
8478
8539
if (auto target =
8479
- dyn_cast_or_null<MacroExpansionExpr>(exprInfo->getTrailingExpr ()))
8480
- if (target->getRewritten ())
8481
- return target;
8482
- return nullptr ;
8540
+ dyn_cast_or_null<MacroExpansionExpr>(exprInfo->getTrailingExpr ())) {
8541
+ if (auto bufferID = getMacroExpansionBuffer (sourceMgr, target))
8542
+ return { *bufferID };
8543
+ }
8544
+
8545
+ return { };
8483
8546
}
8484
8547
8485
- // Handle 'macroName' position in '#macroName(...)'.
8486
8548
if (auto refInfo = dyn_cast<ResolvedValueRefCursorInfo>(&Info)) {
8487
8549
if (refInfo->isRef () && isa_and_nonnull<MacroDecl>(refInfo->getValueD ())) {
8550
+ // Handle 'macroName' position in '@macroName(...)'.
8551
+ if (auto customAttrRef = refInfo->getCustomAttrRef ()) {
8552
+ auto macro = cast<MacroDecl>(refInfo->getValueD ());
8553
+ return getMacroExpansionBuffers (
8554
+ macro, customAttrRef->first , customAttrRef->second );
8555
+ }
8556
+
8557
+ // Handle 'macroName' position in '#macroName(...)'.
8488
8558
ContextFinder Finder (
8489
8559
*Info.getSourceFile (), Info.getLoc (), [&](ASTNode N) {
8490
8560
auto *expr =
@@ -8496,33 +8566,82 @@ findMacroExpansionTargetExpr(const ResolvedCursorInfo &Info) {
8496
8566
if (!Finder.getContexts ().empty ()) {
8497
8567
auto *target =
8498
8568
dyn_cast<MacroExpansionExpr>(Finder.getContexts ()[0 ].get <Expr *>());
8499
- if (target->getRewritten ())
8500
- return target;
8569
+ if (target) {
8570
+ if (auto bufferID = getMacroExpansionBuffer (sourceMgr, target))
8571
+ return { *bufferID };
8572
+ }
8501
8573
}
8502
8574
}
8503
- return nullptr ;
8575
+
8576
+ return { };
8504
8577
}
8505
8578
8506
8579
// TODO: handle MacroExpansionDecl.
8507
- return nullptr ;
8580
+ return { } ;
8508
8581
}
8509
8582
8510
8583
bool RefactoringActionExpandMacro::isApplicable (const ResolvedCursorInfo &Info,
8511
8584
DiagnosticEngine &Diag) {
8512
- return findMacroExpansionTargetExpr ( Info) != nullptr ;
8585
+ return ! getMacroExpansionBuffers (Diag. SourceMgr , Info). empty () ;
8513
8586
}
8514
8587
8515
8588
bool RefactoringActionExpandMacro::performChange () {
8516
- auto target = findMacroExpansionTargetExpr ( CursorInfo);
8517
- if (!target )
8589
+ auto bufferIDs = getMacroExpansionBuffers (SM, CursorInfo);
8590
+ if (bufferIDs. empty () )
8518
8591
return true ;
8519
8592
8520
- auto exprRange =
8521
- Lexer::getCharSourceRangeFromSourceRange (SM, target->getSourceRange ());
8522
- auto rewrittenRange = Lexer::getCharSourceRangeFromSourceRange (
8523
- SM, target->getRewritten ()->getSourceRange ());
8524
- auto rewrittenBuffer = SM.extractText (rewrittenRange);
8525
- EditConsumer.accept (SM, exprRange, rewrittenBuffer);
8593
+ // Send all of the rewritten buffer snippets.
8594
+ CustomAttr *attachedMacroAttr = nullptr ;
8595
+ for (auto bufferID: bufferIDs) {
8596
+ auto generatedInfo = SM.getGeneratedSourceInfo (bufferID);
8597
+ if (!generatedInfo || generatedInfo->originalSourceRange .isInvalid ())
8598
+ continue ;
8599
+
8600
+ auto rewrittenBuffer = SM.extractText (generatedInfo->generatedSourceRange );
8601
+
8602
+ // If there's no change, drop the edit entirely.
8603
+ if (generatedInfo->originalSourceRange .getStart () ==
8604
+ generatedInfo->originalSourceRange .getEnd () &&
8605
+ rewrittenBuffer.empty ())
8606
+ continue ;
8607
+
8608
+ auto originalSourceRange = generatedInfo->originalSourceRange ;
8609
+
8610
+ // For member macros, adjust the source range from before-the-close-brace
8611
+ // to after-the-open-brace.
8612
+ if (generatedInfo->kind == GeneratedSourceInfo::MemberMacroExpansion) {
8613
+ ASTNode node = ASTNode::getFromOpaqueValue (generatedInfo->astNode );
8614
+ auto decl = node.dyn_cast <Decl *>();
8615
+ if (!decl)
8616
+ continue ;
8617
+
8618
+ SourceLoc leftBraceLoc;
8619
+ if (auto nominal = dyn_cast<NominalTypeDecl>(decl)) {
8620
+ leftBraceLoc = nominal->getBraces ().Start ;
8621
+ } else if (auto ext = dyn_cast<ExtensionDecl>(decl)) {
8622
+ leftBraceLoc = ext->getBraces ().Start ;
8623
+ }
8624
+ if (leftBraceLoc.isInvalid ())
8625
+ continue ;
8626
+
8627
+ auto afterLeftBraceLoc = Lexer::getLocForEndOfToken (SM, leftBraceLoc);
8628
+ originalSourceRange = CharSourceRange (afterLeftBraceLoc, 0 );
8629
+ }
8630
+
8631
+ EditConsumer.accept (SM, originalSourceRange, rewrittenBuffer);
8632
+
8633
+ if (generatedInfo->attachedMacroCustomAttr && !attachedMacroAttr)
8634
+ attachedMacroAttr = generatedInfo->attachedMacroCustomAttr ;
8635
+ }
8636
+
8637
+ // For an attached macro, remove the custom attribute; it's been fully
8638
+ // subsumed by its expansions.
8639
+ if (attachedMacroAttr) {
8640
+ SourceRange range = attachedMacroAttr->getRangeWithAt ();
8641
+ auto charRange = Lexer::getCharSourceRangeFromSourceRange (SM, range);
8642
+ EditConsumer.accept (SM, charRange, StringRef ());
8643
+ }
8644
+
8526
8645
return false ;
8527
8646
}
8528
8647
0 commit comments