Add refactoring support for accessor macros

This commit is contained in:
Doug Gregor
2023-02-10 23:21:06 -08:00
parent 96380624db
commit a75b64e034
7 changed files with 95 additions and 11 deletions

View File

@@ -3825,6 +3825,26 @@ public:
bool isCached() const { return true; } bool isCached() const { return true; }
}; };
/// Expand all accessor macros attached to the given declaration.
///
/// Produces the set of macro expansion buffer IDs.
class ExpandAccessorMacros
: public SimpleRequest<ExpandAccessorMacros,
ArrayRef<unsigned>(AbstractStorageDecl *),
RequestFlags::Cached> {
public:
using SimpleRequest::SimpleRequest;
private:
friend SimpleRequest;
ArrayRef<unsigned> evaluate(
Evaluator &evaluator, AbstractStorageDecl *storage) const;
public:
bool isCached() const { return true; }
};
/// Expand all member attribute macros attached to the given /// Expand all member attribute macros attached to the given
/// declaration. /// declaration.
/// ///

View File

@@ -434,6 +434,9 @@ SWIFT_REQUEST(TypeChecker, ExpandMacroExpansionDeclRequest,
SWIFT_REQUEST(TypeChecker, ExpandMemberAttributeMacros, SWIFT_REQUEST(TypeChecker, ExpandMemberAttributeMacros,
ArrayRef<unsigned>(Decl *), ArrayRef<unsigned>(Decl *),
Cached, NoLocationInfo) Cached, NoLocationInfo)
SWIFT_REQUEST(TypeChecker, ExpandAccessorMacros,
ArrayRef<unsigned>(AbstractStorageDecl *),
Cached, NoLocationInfo)
SWIFT_REQUEST(TypeChecker, ExpandSynthesizedMemberMacroRequest, SWIFT_REQUEST(TypeChecker, ExpandSynthesizedMemberMacroRequest,
ArrayRef<unsigned>(Decl *), ArrayRef<unsigned>(Decl *),
Cached, NoLocationInfo) Cached, NoLocationInfo)

View File

@@ -8491,7 +8491,11 @@ getMacroExpansionBuffers(MacroDecl *macro, const CustomAttr *attr, Decl *decl) {
ASTContext &ctx = macro->getASTContext(); ASTContext &ctx = macro->getASTContext();
llvm::SmallVector<unsigned, 2> allBufferIDs; llvm::SmallVector<unsigned, 2> allBufferIDs;
if (roles.contains(MacroRole::Accessor)) { if (roles.contains(MacroRole::Accessor)) {
// FIXME: Need to requestify. 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 (roles.contains(MacroRole::MemberAttribute)) {
@@ -8607,9 +8611,10 @@ bool RefactoringActionExpandMacro::performChange() {
auto originalSourceRange = generatedInfo->originalSourceRange; auto originalSourceRange = generatedInfo->originalSourceRange;
// For member macros, adjust the source range from before-the-close-brace SmallString<64> scratchBuffer;
// to after-the-open-brace.
if (generatedInfo->kind == GeneratedSourceInfo::MemberMacroExpansion) { if (generatedInfo->kind == GeneratedSourceInfo::MemberMacroExpansion) {
// For member macros, adjust the source range from before-the-close-brace
// to after-the-open-brace.
ASTNode node = ASTNode::getFromOpaqueValue(generatedInfo->astNode); ASTNode node = ASTNode::getFromOpaqueValue(generatedInfo->astNode);
auto decl = node.dyn_cast<Decl *>(); auto decl = node.dyn_cast<Decl *>();
if (!decl) if (!decl)
@@ -8626,6 +8631,13 @@ bool RefactoringActionExpandMacro::performChange() {
auto afterLeftBraceLoc = Lexer::getLocForEndOfToken(SM, leftBraceLoc); auto afterLeftBraceLoc = Lexer::getLocForEndOfToken(SM, leftBraceLoc);
originalSourceRange = CharSourceRange(afterLeftBraceLoc, 0); originalSourceRange = CharSourceRange(afterLeftBraceLoc, 0);
} else if (generatedInfo->kind ==
GeneratedSourceInfo::AccessorMacroExpansion) {
// For accessor macros, wrap curly braces around the buffer contents.
scratchBuffer += "{\n";
scratchBuffer += rewrittenBuffer;
scratchBuffer += "\n}";
rewrittenBuffer = scratchBuffer;
} }
EditConsumer.accept(SM, originalSourceRange, rewrittenBuffer); EditConsumer.accept(SM, originalSourceRange, rewrittenBuffer);

View File

@@ -990,8 +990,14 @@ evaluateAttachedMacro(MacroDecl *macro, Decl *attachedTo, CustomAttr *attr,
Lexer::getCharSourceRangeFromSourceRange(sourceMgr, *initRange); Lexer::getCharSourceRangeFromSourceRange(sourceMgr, *initRange);
} else { } else {
// The accessors go at the end. // The accessors go at the end.
SourceLoc endLoc = storage->getEndLoc();
if (auto var = dyn_cast<VarDecl>(storage)) {
if (auto pattern = var->getParentPattern())
endLoc = pattern->getEndLoc();
}
generatedOriginalSourceRange = CharSourceRange( generatedOriginalSourceRange = CharSourceRange(
Lexer::getLocForEndOfToken(sourceMgr, storage->getEndLoc()), 0); Lexer::getLocForEndOfToken(sourceMgr, endLoc), 0);
} }
break; break;
@@ -1064,7 +1070,7 @@ evaluateAttachedMacro(MacroDecl *macro, Decl *attachedTo, CustomAttr *attr,
return macroSourceFile; return macroSourceFile;
} }
void swift::expandAccessors( Optional<unsigned> swift::expandAccessors(
AbstractStorageDecl *storage, CustomAttr *attr, MacroDecl *macro AbstractStorageDecl *storage, CustomAttr *attr, MacroDecl *macro
) { ) {
// Evaluate the macro. // Evaluate the macro.
@@ -1072,7 +1078,7 @@ void swift::expandAccessors(
/*passParentContext*/false, /*passParentContext*/false,
MacroRole::Accessor); MacroRole::Accessor);
if (!macroSourceFile) if (!macroSourceFile)
return; return None;
PrettyStackTraceDecl debugStack( PrettyStackTraceDecl debugStack(
"type checking expanded declaration macro", storage); "type checking expanded declaration macro", storage);
@@ -1098,6 +1104,22 @@ void swift::expandAccessors(
} }
} }
} }
return macroSourceFile->getBufferID();
}
ArrayRef<unsigned> ExpandAccessorMacros::evaluate(
Evaluator &evaluator, AbstractStorageDecl *storage
) const {
llvm::SmallVector<unsigned, 1> bufferIDs;
storage->forEachAttachedMacro(MacroRole::Accessor,
[&](CustomAttr *customAttr, MacroDecl *macro) {
if (auto bufferID = expandAccessors(
storage, customAttr, macro))
bufferIDs.push_back(*bufferID);
});
return storage->getASTContext().AllocateCopy(bufferIDs);
} }
Optional<unsigned> Optional<unsigned>

View File

@@ -49,7 +49,7 @@ bool expandFreestandingDeclarationMacro(
/// Expand the accessors for the given storage declaration based on the /// Expand the accessors for the given storage declaration based on the
/// custom attribute that references the given macro. /// custom attribute that references the given macro.
void expandAccessors( Optional<unsigned> expandAccessors(
AbstractStorageDecl *storage, CustomAttr *attr, MacroDecl *macro AbstractStorageDecl *storage, CustomAttr *attr, MacroDecl *macro
); );

View File

@@ -3414,10 +3414,7 @@ StorageImplInfoRequest::evaluate(Evaluator &evaluator,
} }
// Expand any attached accessor macros. // Expand any attached accessor macros.
storage->forEachAttachedMacro(MacroRole::Accessor, (void)evaluateOrDefault(evaluator, ExpandAccessorMacros{storage}, { });
[&](CustomAttr *customAttr, MacroDecl *macro) {
expandAccessors(storage, customAttr, macro);
});
bool hasWillSet = storage->getParsedAccessor(AccessorKind::WillSet); bool hasWillSet = storage->getParsedAccessor(AccessorKind::WillSet);
bool hasDidSet = storage->getParsedAccessor(AccessorKind::DidSet); bool hasDidSet = storage->getParsedAccessor(AccessorKind::DidSet);

View File

@@ -24,6 +24,16 @@ struct S {
var y: Int var y: Int
} }
struct S2 {
private var _storage = _Storage()
@accessViaStorage
var x: Int
@accessViaStorage
var y: Int = 17
}
// FIXME: Swift parser is not enabled on Linux CI yet. // FIXME: Swift parser is not enabled on Linux CI yet.
// REQUIRES: OS=macosx // REQUIRES: OS=macosx
@@ -92,3 +102,23 @@ struct S {
// ATTACHED_EXPAND: 22:11-22:11 "private var _storage = _Storage()" // ATTACHED_EXPAND: 22:11-22:11 "private var _storage = _Storage()"
// ATTACHED_EXPAND: source.edit.kind.active: // ATTACHED_EXPAND: source.edit.kind.active:
// ATTACHED_EXPAND: 21:1-21:15 "" // ATTACHED_EXPAND: 21:1-21:15 ""
//##-- Refactoring expanding the first accessor macro
// RUN: %sourcekitd-test -req=refactoring.expand.macro -pos=30:4 %s -- ${COMPILER_ARGS[@]} | %FileCheck -check-prefix=ACCESSOR1_EXPAND %s
// ACCESSOR1_EXPAND: source.edit.kind.active:
// ACCESSOR1_EXPAND: 31:13-31:13 "{
// ACCESSOR1_EXPAND: get { _storage.x }
// ACCESSOR1_EXPAND: set { _storage.x = newValue }
// ACCESSOR1_EXPAND: }"
// ACCESSOR1_EXPAND: source.edit.kind.active:
// ACCESSOR1_EXPAND: 30:3-30:20 ""
//##-- Refactoring expanding the first accessor macro
// RUN: %sourcekitd-test -req=refactoring.expand.macro -pos=33:13 %s -- ${COMPILER_ARGS[@]} | %FileCheck -check-prefix=ACCESSOR2_EXPAND %s
// ACCESSOR2_EXPAND: source.edit.kind.active:
// ACCESSOR2_EXPAND: 34:14-34:18 "{
// ACCESSOR2_EXPAND: get { _storage.y }
// ACCESSOR2_EXPAND: set { _storage.y = newValue }
// ACCESSOR2_EXPAND: }"
// ACCESSOR2_EXPAND: source.edit.kind.active:
// ACCESSOR2_EXPAND: 33:3-33:20 ""