[Refactoring] Move ExpandMacro and InlineMacro to their own file

This commit is contained in:
Alex Hoppen
2023-09-11 17:01:48 -07:00
parent 10b9daf2b5
commit c05c573a04
3 changed files with 205 additions and 186 deletions

View File

@@ -4933,192 +4933,6 @@ bool RefactoringActionAddAsyncWrapper::performChange() {
return false;
}
/// Retrieve the macro expansion buffer for the given macro expansion
/// expression.
static llvm::Optional<unsigned>
getMacroExpansionBuffer(SourceManager &sourceMgr,
MacroExpansionExpr *expansion) {
return evaluateOrDefault(
expansion->getDeclContext()->getASTContext().evaluator,
ExpandMacroExpansionExprRequest{expansion}, {});
}
/// Retrieve the macro expansion buffer for the given macro expansion
/// declaration.
static llvm::Optional<unsigned>
getMacroExpansionBuffer(SourceManager &sourceMgr,
MacroExpansionDecl *expansion) {
return evaluateOrDefault(expansion->getASTContext().evaluator,
ExpandMacroExpansionDeclRequest{expansion}, {});
}
/// Retrieve the macro expansion buffers for the given attached macro reference.
static llvm::SmallVector<unsigned, 2>
getMacroExpansionBuffers(MacroDecl *macro, const CustomAttr *attr, Decl *decl) {
auto roles = macro->getMacroRoles() & getAttachedMacroRoles();
if (!roles)
return { };
ASTContext &ctx = macro->getASTContext();
llvm::SmallVector<unsigned, 2> allBufferIDs;
if (roles.contains(MacroRole::Accessor)) {
if (auto storage = dyn_cast<AbstractStorageDecl>(decl)) {
auto bufferIDs = evaluateOrDefault(
ctx.evaluator, ExpandAccessorMacros{storage}, { });
allBufferIDs.append(bufferIDs.begin(), bufferIDs.end());
}
}
if (roles.contains(MacroRole::MemberAttribute)) {
if (auto idc = dyn_cast<IterableDeclContext>(decl)) {
for (auto memberDecl : idc->getAllMembers()) {
auto bufferIDs = evaluateOrDefault(
ctx.evaluator, ExpandMemberAttributeMacros{memberDecl}, { });
allBufferIDs.append(bufferIDs.begin(), bufferIDs.end());
}
}
}
if (roles.contains(MacroRole::Member)) {
auto bufferIDs = evaluateOrDefault(
ctx.evaluator, ExpandSynthesizedMemberMacroRequest{decl}, { });
allBufferIDs.append(bufferIDs.begin(), bufferIDs.end());
}
if (roles.contains(MacroRole::Peer)) {
auto bufferIDs = evaluateOrDefault(
ctx.evaluator, ExpandPeerMacroRequest{decl}, { });
allBufferIDs.append(bufferIDs.begin(), bufferIDs.end());
}
if (roles.contains(MacroRole::Conformance) ||
roles.contains(MacroRole::Extension)) {
if (auto nominal = dyn_cast<NominalTypeDecl>(decl)) {
auto bufferIDs = evaluateOrDefault(
ctx.evaluator, ExpandExtensionMacros{nominal}, { });
allBufferIDs.append(bufferIDs.begin(), bufferIDs.end());
}
}
// Drop any buffers that come from other macros. We could eliminate this
// step by adding more fine-grained requests above, which only expand for a
// single custom attribute.
SourceManager &sourceMgr = ctx.SourceMgr;
auto removedAt = std::remove_if(
allBufferIDs.begin(), allBufferIDs.end(),
[&](unsigned bufferID) {
auto generatedInfo = sourceMgr.getGeneratedSourceInfo(bufferID);
if (!generatedInfo)
return true;
return generatedInfo->attachedMacroCustomAttr != attr;
});
allBufferIDs.erase(removedAt, allBufferIDs.end());
return allBufferIDs;
}
/// Given a resolved cursor, determine whether it is for a macro expansion and
/// return the list of macro expansion buffer IDs that are associated with the
/// macro reference here.
static llvm::SmallVector<unsigned, 2>
getMacroExpansionBuffers(SourceManager &sourceMgr, ResolvedCursorInfoPtr Info) {
auto *refInfo = dyn_cast<ResolvedValueRefCursorInfo>(Info);
if (!refInfo || !refInfo->isRef())
return {};
auto *macro = dyn_cast_or_null<MacroDecl>(refInfo->getValueD());
if (!macro)
return {};
// Attached macros
if (auto customAttrRef = refInfo->getCustomAttrRef()) {
auto macro = cast<MacroDecl>(refInfo->getValueD());
return getMacroExpansionBuffers(macro, customAttrRef->first,
customAttrRef->second);
}
// FIXME: A resolved cursor should contain a slice up to its reference.
// We shouldn't need to find it again.
ContextFinder Finder(*Info->getSourceFile(), Info->getLoc(), [&](ASTNode N) {
if (auto *expr =
dyn_cast_or_null<MacroExpansionExpr>(N.dyn_cast<Expr *>())) {
return expr->getStartLoc() == Info->getLoc() ||
expr->getMacroNameLoc().getBaseNameLoc() == Info->getLoc();
} else if (auto *decl =
dyn_cast_or_null<MacroExpansionDecl>(N.dyn_cast<Decl *>())) {
return decl->getStartLoc() == Info->getLoc() ||
decl->getMacroNameLoc().getBaseNameLoc() == Info->getLoc();
}
return false;
});
Finder.resolve();
if (!Finder.getContexts().empty()) {
llvm::Optional<unsigned> bufferID;
if (auto *target = dyn_cast_or_null<MacroExpansionExpr>(
Finder.getContexts()[0].dyn_cast<Expr *>())) {
bufferID = getMacroExpansionBuffer(sourceMgr, target);
} else if (auto *target = dyn_cast_or_null<MacroExpansionDecl>(
Finder.getContexts()[0].dyn_cast<Decl *>())) {
bufferID = getMacroExpansionBuffer(sourceMgr, target);
}
if (bufferID)
return {*bufferID};
}
return {};
}
static bool expandMacro(SourceManager &SM, ResolvedCursorInfoPtr cursorInfo,
SourceEditConsumer &editConsumer, bool adjustExpansion) {
auto bufferIDs = getMacroExpansionBuffers(SM, cursorInfo);
if (bufferIDs.empty())
return true;
SourceFile *containingSF = cursorInfo->getSourceFile();
if (!containingSF)
return true;
// Send all of the rewritten buffer snippets.
for (auto bufferID: bufferIDs) {
editConsumer.acceptMacroExpansionBuffer(SM, bufferID, containingSF,
adjustExpansion, /*includeBufferName=*/true);
}
// For an attached macro, remove the custom attribute; it's been fully
// subsumed by its expansions.
if (auto attrRef =
cast<ResolvedValueRefCursorInfo>(cursorInfo)->getCustomAttrRef()) {
const CustomAttr *attachedMacroAttr = attrRef->first;
SourceRange range = attachedMacroAttr->getRangeWithAt();
auto charRange = Lexer::getCharSourceRangeFromSourceRange(SM, range);
editConsumer.remove(SM, charRange);
}
return false;
}
bool RefactoringActionExpandMacro::isApplicable(ResolvedCursorInfoPtr Info,
DiagnosticEngine &Diag) {
// Never list in available refactorings. Only allow requesting directly.
return false;
}
bool RefactoringActionExpandMacro::performChange() {
return expandMacro(SM, CursorInfo, EditConsumer, /*adjustExpansion=*/false);
}
bool RefactoringActionInlineMacro::isApplicable(ResolvedCursorInfoPtr Info,
DiagnosticEngine &Diag) {
return !getMacroExpansionBuffers(Diag.SourceMgr, Info).empty();
}
bool RefactoringActionInlineMacro::performChange() {
return expandMacro(SM, CursorInfo, EditConsumer, /*adjustExpansion=*/true);
}
StringRef swift::ide::
getDescriptiveRefactoringKindName(RefactoringKind Kind) {
switch(Kind) {