Skip to content

Commit f3a6ce1

Browse files
authored
Merge pull request #63906 from bnbarham/add-nested-expansion
[Refactor] Allow expanding nested macros
2 parents a9e5075 + bb7760b commit f3a6ce1

File tree

19 files changed

+241
-144
lines changed

19 files changed

+241
-144
lines changed

include/swift/AST/Decl.h

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -892,8 +892,8 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated<Decl> {
892892

893893
/// Retrieve the discriminator for the given custom attribute that names
894894
/// an attached macro.
895-
unsigned getAttachedMacroDiscriminator(
896-
MacroRole role, const CustomAttr *attr) const;
895+
unsigned getAttachedMacroDiscriminator(DeclBaseName macroName, MacroRole role,
896+
const CustomAttr *attr) const;
897897

898898
/// Returns the innermost enclosing decl with an availability annotation.
899899
const Decl *getInnermostDeclWithAvailability() const;
@@ -8323,24 +8323,23 @@ class PostfixOperatorDecl : public OperatorDecl {
83238323
/// is used for parser recovery, e.g. when parsing a floating
83248324
/// attribute list.
83258325
class MissingDecl: public Decl {
8326-
MissingDecl(DeclContext *DC) : Decl(DeclKind::Missing, DC) {
8326+
/// The location that the decl would be if it wasn't missing.
8327+
SourceLoc Loc;
8328+
8329+
MissingDecl(DeclContext *DC, SourceLoc loc)
8330+
: Decl(DeclKind::Missing, DC), Loc(loc) {
83278331
setImplicit();
83288332
}
83298333

83308334
friend class Decl;
8331-
SourceLoc getLocFromSource() const {
8332-
return SourceLoc();
8333-
}
8335+
SourceLoc getLocFromSource() const { return Loc; }
83348336

83358337
public:
8336-
static MissingDecl *
8337-
create(ASTContext &ctx, DeclContext *DC) {
8338-
return new (ctx) MissingDecl(DC);
8338+
static MissingDecl *create(ASTContext &ctx, DeclContext *DC, SourceLoc loc) {
8339+
return new (ctx) MissingDecl(DC, loc);
83398340
}
83408341

8341-
SourceRange getSourceRange() const {
8342-
return SourceRange();
8343-
}
8342+
SourceRange getSourceRange() const { return SourceRange(Loc); }
83448343

83458344
static bool classof(const Decl *D) {
83468345
return D->getKind() == DeclKind::Missing;

include/swift/Refactoring/Refactoring.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ enum class RefactoringKind : int8_t {
3333
};
3434

3535
struct RangeConfig {
36-
unsigned BufferId;
36+
unsigned BufferID;
3737
unsigned Line;
3838
unsigned Column;
3939
unsigned Length;

lib/AST/ASTMangler.cpp

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3812,13 +3812,14 @@ void ASTMangler::appendMacroExpansionContext(
38123812

38133813
outerExpansionLoc = decl->getLoc();
38143814
outerExpansionDC = decl->getDeclContext();
3815-
discriminator = decl->getAttachedMacroDiscriminator(role, attr);
38163815

38173816
if (auto *macroDecl = decl->getResolvedMacro(attr))
38183817
baseName = macroDecl->getBaseName();
38193818
else
38203819
baseName = ctx.getIdentifier("__unknown_macro__");
38213820

3821+
discriminator = decl->getAttachedMacroDiscriminator(baseName, role, attr);
3822+
38223823
break;
38233824
}
38243825

@@ -3898,24 +3899,30 @@ std::string ASTMangler::mangleAttachedMacroExpansion(
38983899
beginMangling();
38993900

39003901
const Decl *attachedTo = decl;
3901-
if (role == MacroRole::MemberAttribute) {
3902-
appendContextOf(cast<ValueDecl>(decl));
3903-
attachedTo = decl->getDeclContext()->getAsDecl();
3904-
} else if (auto valueDecl = dyn_cast<ValueDecl>(decl)) {
3905-
appendAnyDecl(valueDecl);
3902+
if (auto valueDecl = dyn_cast<ValueDecl>(decl)) {
3903+
if (role != MacroRole::MemberAttribute) {
3904+
appendAnyDecl(valueDecl);
3905+
} else {
3906+
// Appending the member would result in a cycle since `VarDecl` appends
3907+
// its type, which would then loop back around to getting the attributes
3908+
// again. We'll instead add a discriminator for each member.
3909+
appendContextOf(valueDecl);
3910+
attachedTo = decl->getDeclContext()->getAsDecl();
3911+
}
39063912
} else {
39073913
appendContext(decl->getDeclContext(), "");
39083914
}
39093915

3910-
StringRef macroName;
3911-
if (auto *macroDecl = attachedTo->getResolvedMacro(attr))
3912-
macroName = macroDecl->getName().getBaseName().userFacingName();
3913-
else
3914-
macroName = "__unknown_macro__";
3916+
DeclBaseName macroName;
3917+
if (auto *macroDecl = attachedTo->getResolvedMacro(attr)) {
3918+
macroName = macroDecl->getName().getBaseName();
3919+
} else {
3920+
macroName = decl->getASTContext().getIdentifier("__unknown_macro__");
3921+
}
39153922

39163923
appendMacroExpansionOperator(
3917-
macroName, role,
3918-
decl->getAttachedMacroDiscriminator(role, attr));
3924+
macroName.userFacingName(), role,
3925+
decl->getAttachedMacroDiscriminator(macroName, role, attr));
39193926
return finalize();
39203927
}
39213928

lib/AST/Decl.cpp

Lines changed: 19 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -441,39 +441,34 @@ MacroDecl *Decl::getResolvedMacro(CustomAttr *customAttr) const {
441441
return dyn_cast_or_null<MacroDecl>(declRef.getDecl());
442442
}
443443

444-
unsigned Decl::getAttachedMacroDiscriminator(
445-
MacroRole role, const CustomAttr *attr
446-
) const {
444+
unsigned Decl::getAttachedMacroDiscriminator(DeclBaseName macroName,
445+
MacroRole role,
446+
const CustomAttr *attr) const {
447447
assert(isAttachedMacro(role) && "Not an attached macro role");
448448

449-
// Member-attribute macros are written on the enclosing declaration,
450-
// but apply to the member itself. Adjust the owning declaration accordingly.
451-
const Decl *owningDecl = this;
452-
if (role == MacroRole::MemberAttribute) {
453-
owningDecl = getDeclContext()->getAsDecl();
454-
}
455-
456-
llvm::SmallDenseMap<Identifier, unsigned> nextDiscriminator;
457-
Optional<unsigned> foundDiscriminator;
449+
if (role != MacroRole::MemberAttribute) {
450+
llvm::SmallDenseMap<Identifier, unsigned> nextDiscriminator;
451+
Optional<unsigned> foundDiscriminator;
458452

459-
owningDecl->forEachAttachedMacro(
460-
role,
461-
[&](CustomAttr *foundAttr, MacroDecl *foundMacro) {
462-
unsigned discriminator =
463-
nextDiscriminator[foundMacro->getBaseIdentifier()]++;
464-
if (attr == foundAttr)
465-
foundDiscriminator = discriminator;
466-
});
453+
forEachAttachedMacro(
454+
role, [&](CustomAttr *foundAttr, MacroDecl *foundMacro) {
455+
unsigned discriminator =
456+
nextDiscriminator[foundMacro->getBaseIdentifier()]++;
457+
if (attr == foundAttr)
458+
foundDiscriminator = discriminator;
459+
});
467460

468-
if (foundDiscriminator)
469-
return *foundDiscriminator;
461+
if (foundDiscriminator)
462+
return *foundDiscriminator;
463+
}
470464

471465
// If that failed, conjure up a discriminator.
466+
// FIXME: Better discriminator for member attributes - add the member name?
472467
ASTContext &ctx = getASTContext();
473-
assert(ctx.Diags.hadAnyError());
468+
assert(role == MacroRole::MemberAttribute || ctx.Diags.hadAnyError());
474469
return ctx.getNextMacroDiscriminator(
475470
MacroDiscriminatorContext::getParentOf(getLoc(), getDeclContext()),
476-
DeclBaseName());
471+
macroName);
477472
}
478473

479474
const Decl *Decl::getInnermostDeclWithAvailability() const {

lib/AST/Module.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -646,7 +646,9 @@ SourceFile *ModuleDecl::getSourceFileContainingLocation(SourceLoc loc) {
646646

647647
auto foundSourceFile = *found;
648648
auto foundRange = sourceMgr.getRangeForBuffer(*foundSourceFile->getBufferID());
649-
if (!foundRange.contains(adjustedLoc) && adjustedLoc != foundRange.getStart())
649+
// Positions inside an empty file or at EOF should still be considered within
650+
// this file.
651+
if (!foundRange.contains(adjustedLoc) && adjustedLoc != foundRange.getEnd())
650652
return nullptr;
651653

652654
// Update the last source file.

lib/IDE/SourceEntityWalker.cpp

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -684,11 +684,13 @@ bool SemaAnnotator::handleCustomAttributes(Decl *D) {
684684
}
685685
}
686686

687-
// FIXME: This should be getSemanticAttrs if we want to walk macro
688-
// expansions. We've just already typechecked and this list is mutable so...
689-
for (auto *customAttr : D->getAttrs().getAttributes<CustomAttr, true>()) {
690-
if (!shouldWalkMacroArgumentsAndExpansion().second &&
691-
D->getModuleContext()->isInGeneratedBuffer(customAttr->getLocation()))
687+
ModuleDecl *MD = D->getModuleContext();
688+
for (auto *customAttr :
689+
D->getSemanticAttrs().getAttributes<CustomAttr, true>()) {
690+
SourceFile *SF =
691+
MD->getSourceFileContainingLocation(customAttr->getLocation());
692+
ASTNode expansion = SF ? SF->getMacroExpansion() : nullptr;
693+
if (!shouldWalkMacroArgumentsAndExpansion().second && expansion)
692694
continue;
693695

694696
if (auto *Repr = customAttr->getTypeRepr()) {
@@ -700,10 +702,12 @@ bool SemaAnnotator::handleCustomAttributes(Decl *D) {
700702
if (auto macroDecl = D->getResolvedMacro(mutableAttr)) {
701703
Type macroRefType = macroDecl->getDeclaredInterfaceType();
702704
if (!passReference(
703-
macroDecl, macroRefType, DeclNameLoc(Repr->getStartLoc()),
704-
ReferenceMetaData(SemaReferenceKind::DeclRef, None,
705-
/*isImplicit=*/false,
706-
std::make_pair(customAttr, D))))
705+
macroDecl, macroRefType, DeclNameLoc(Repr->getStartLoc()),
706+
ReferenceMetaData(
707+
SemaReferenceKind::DeclRef, None,
708+
/*isImplicit=*/false,
709+
std::make_pair(customAttr,
710+
expansion ? expansion.get<Decl *>() : D))))
707711
return false;
708712
} else if (!Repr->walk(*this)) {
709713
return false;
@@ -865,9 +869,23 @@ bool SemaAnnotator::passCallArgNames(Expr *Fn, ArgumentList *ArgList) {
865869
}
866870

867871
bool SemaAnnotator::shouldIgnore(Decl *D) {
872+
if (!D->isImplicit())
873+
return false;
874+
868875
// TODO: There should really be a separate field controlling whether
869876
// constructors are visited or not
870-
return D->isImplicit() && !isa<ConstructorDecl>(D);
877+
if (isa<ConstructorDecl>(D))
878+
return false;
879+
880+
// Walk into missing decls to visit their attributes if they were generated
881+
// by a member attribute expansion. Note that we would have already skipped
882+
// this decl if we were ignoring expansions, so no need to check that.
883+
if (auto *missing = dyn_cast<MissingDecl>(D)) {
884+
if (D->isInGeneratedBuffer())
885+
return false;
886+
}
887+
888+
return true;
871889
}
872890

873891
bool SourceEntityWalker::walk(SourceFile &SrcFile) {

lib/Parse/ParseDecl.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7132,7 +7132,8 @@ void Parser::parseExpandedAttributeList(SmallVectorImpl<ASTNode> &items) {
71327132

71337133
// Create a `MissingDecl` as a placeholder for the declaration the
71347134
// macro will attach the attribute list to.
7135-
MissingDecl *missing = MissingDecl::create(Context, CurDeclContext);
7135+
MissingDecl *missing =
7136+
MissingDecl::create(Context, CurDeclContext, Tok.getLoc());
71367137
missing->getAttrs() = attributes;
71377138

71387139
items.push_back(ASTNode(missing));

lib/Refactoring/Refactoring.cpp

Lines changed: 6 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -730,27 +730,12 @@ RenameRangeCollector::indexSymbolToRenameLoc(const index::IndexSymbol &symbol,
730730
isFunctionLike, isNonProtocolType};
731731
}
732732

733-
ArrayRef<SourceFile*>
734-
collectSourceFiles(ModuleDecl *MD, SmallVectorImpl<SourceFile *> &Scratch) {
735-
for (auto Unit : MD->getFiles()) {
736-
if (auto SF = dyn_cast<SourceFile>(Unit)) {
737-
Scratch.push_back(SF);
738-
}
739-
}
740-
return llvm::makeArrayRef(Scratch);
741-
}
742-
743-
/// Get the source file that contains the given range and belongs to the module.
733+
/// Get the source file that corresponds to the given buffer.
744734
SourceFile *getContainingFile(ModuleDecl *M, RangeConfig Range) {
745-
SmallVector<SourceFile*, 4> Files;
746-
for (auto File : collectSourceFiles(M, Files)) {
747-
if (File->getBufferID()) {
748-
if (File->getBufferID().value() == Range.BufferId) {
749-
return File;
750-
}
751-
}
752-
}
753-
return nullptr;
735+
auto &SM = M->getASTContext().SourceMgr;
736+
// TODO: We should add an ID -> SourceFile mapping.
737+
return M->getSourceFileContainingLocation(
738+
SM.getRangeForBuffer(Range.BufferID).getStart());
754739
}
755740

756741
class RefactoringAction {
@@ -8804,7 +8789,7 @@ getDescriptiveRefactoringKindName(RefactoringKind Kind) {
88048789
}
88058790

88068791
SourceLoc swift::ide::RangeConfig::getStart(SourceManager &SM) {
8807-
return SM.getLocForLineCol(BufferId, Line, Column);
8792+
return SM.getLocForLineCol(BufferID, Line, Column);
88088793
}
88098794

88108795
SourceLoc swift::ide::RangeConfig::getEnd(SourceManager &SM) {

test/SourceKit/Macros/macro_basic.swift

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,14 +137,25 @@ struct S4 { }
137137
// ATTACHED_EXPAND: source.edit.kind.active:
138138
// ATTACHED_EXPAND-NEXT: 23:3-23:3 (@__swiftmacro_9MacroUser1SV13myTypeWrapperfMA_.swift) "@accessViaStorage "
139139
// ATTACHED_EXPAND-NEXT: source.edit.kind.active:
140-
// ATTACHED_EXPAND-NEXT: 24:3-24:3 (@__swiftmacro_9MacroUser1SV13myTypeWrapperfMA_.swift) "@accessViaStorage "
140+
// ATTACHED_EXPAND-NEXT: 24:3-24:3 (@__swiftmacro_9MacroUser1SV13myTypeWrapperfMA0_.swift) "@accessViaStorage "
141141
// ATTACHED_EXPAND-NEXT: source.edit.kind.active:
142142
// ATTACHED_EXPAND-NEXT: 22:11-22:11 (@__swiftmacro_9MacroUser1SV13myTypeWrapperfMm_.swift) "
143143
// ATTACHED_EXPAND-NEXT: private var _storage = _Storage()
144144
// ATTACHED_EXPAND-NEXT: "
145145
// ATTACHED_EXPAND-NEXT: source.edit.kind.active:
146146
// ATTACHED_EXPAND-NEXT: 21:1-21:15 ""
147147

148+
//##-- Refactoring expanding the attribute expanded by @myTypeWrapper
149+
// RUN: %sourcekitd-test -req=refactoring.expand.macro -pos=1:2 @__swiftmacro_9MacroUser1SV13myTypeWrapperfMA_.swift -primary-file %s -- ${COMPILER_ARGS[@]} | %FileCheck -check-prefix=NESTED_ATTACHED_EXPAND %s
150+
// NESTED_ATTACHED_EXPAND: source.edit.kind.active:
151+
// NESTED_ATTACHED_EXPAND-NEXT: Macros/macro_basic.swift 23:13-23:13 (@__swiftmacro_9MacroUser1SV1xSivp16accessViaStoragefMa_.swift) "{
152+
// NESTED_ATTACHED_EXPAND-NEXT: get { _storage.x }
153+
// NESTED_ATTACHED_EXPAND-EMPTY:
154+
// NESTED_ATTACHED_EXPAND-NEXT: set { _storage.x = newValue }
155+
// NESTED_ATTACHED_EXPAND-NEXT: }"
156+
// NESTED_ATTACHED_EXPAND-NEXT: source.edit.kind.active:
157+
// NESTED_ATTACHED_EXPAND-NEXT: 1:1-1:18 ""
158+
148159
//##-- Refactoring expanding the first accessor macro
149160
// RUN: %sourcekitd-test -req=refactoring.expand.macro -pos=30:4 %s -- ${COMPILER_ARGS[@]} | %FileCheck -check-prefix=ACCESSOR1_EXPAND %s
150161
// ACCESSOR1_EXPAND: source.edit.kind.active:

tools/SourceKit/include/SourceKit/Core/LangSupport.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -637,6 +637,10 @@ enum class SemanticRefactoringKind {
637637

638638
struct SemanticRefactoringInfo {
639639
SemanticRefactoringKind Kind;
640+
// The name of the source file to start the refactoring in. Empty if it is
641+
// the primary file (in which case the primary file from the AST is used).
642+
// This must match the buffer identifier stored in the source manager.
643+
StringRef SourceFile;
640644
unsigned Line;
641645
unsigned Column;
642646
unsigned Length;
@@ -1045,7 +1049,7 @@ class LangSupport {
10451049
SourceKitCancellationToken CancellationToken,
10461050
CategorizedRenameRangesReceiver Receiver) = 0;
10471051

1048-
virtual void semanticRefactoring(StringRef Filename,
1052+
virtual void semanticRefactoring(StringRef PrimaryFile,
10491053
SemanticRefactoringInfo Info,
10501054
ArrayRef<const char *> Args,
10511055
SourceKitCancellationToken CancellationToken,

0 commit comments

Comments
 (0)