mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Merge pull request #84972 from rintaro/accessor-disambiguation-rdar140943107
[ASTPrinter/Parse] Disambiguate accessor block in .swiftinterface
This commit is contained in:
@@ -2716,6 +2716,32 @@ void PrintAST::printAccessors(const AbstractStorageDecl *ASD) {
|
||||
}
|
||||
}
|
||||
|
||||
Printer << " {";
|
||||
|
||||
// For var decls, if it has an initializer, the parser only expects observing
|
||||
// accessors. But sometimes for example in '.swiftinterface', we want to print
|
||||
// both the initializer and the accessors. So when we print the initializer
|
||||
// *and* the accessor block not starting with willSet/didSet, print an
|
||||
// attribute as a disambiguation marker.
|
||||
bool needsDisambiguationAttr = false;
|
||||
if (auto *VD = dyn_cast<VarDecl>(ASD)) {
|
||||
if (auto *PBD = VD->getParentPatternBinding()) {
|
||||
AccessorDecl *firstAccessor = *accessorsToPrint.begin();
|
||||
if (!firstAccessor->isObservingAccessor()) {
|
||||
const auto i = PBD->getPatternEntryIndexForVarDecl(VD);
|
||||
if (Options.PrintExprs) {
|
||||
needsDisambiguationAttr |= bool(PBD->getInit(i));
|
||||
} else if (Options.VarInitializers) {
|
||||
needsDisambiguationAttr |= bool(PBD->hasInitStringRepresentation(i) &&
|
||||
VD->isInitExposedToClients());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (needsDisambiguationAttr) {
|
||||
Printer << " @_accessorBlock";
|
||||
}
|
||||
|
||||
// If we're not printing the accessor bodies and none of the accessors have
|
||||
// attributes then we can print in a shorter, compact form.
|
||||
bool PrintCompactAccessors =
|
||||
@@ -2724,9 +2750,6 @@ void PrintAST::printAccessors(const AbstractStorageDecl *ASD) {
|
||||
[](AccessorDecl *accessor) {
|
||||
return accessor->getAttrs().isEmpty();
|
||||
});
|
||||
|
||||
Printer << " {";
|
||||
|
||||
if (!PrintCompactAccessors)
|
||||
Printer.printNewline();
|
||||
|
||||
|
||||
@@ -367,6 +367,11 @@ extension ASTGenVisitor {
|
||||
break
|
||||
|
||||
case .none:
|
||||
// '@_accessorBlock' is a parser only disambiguation marker, ignore.
|
||||
if attrName == "_accessorBlock" {
|
||||
return
|
||||
}
|
||||
|
||||
// Fall back to CustomAttr.
|
||||
break
|
||||
}
|
||||
|
||||
@@ -8167,6 +8167,14 @@ ParserStatus Parser::parseGetSet(ParseDeclOptions Flags, ParameterList *Indices,
|
||||
bool IsFirstAccessor = true;
|
||||
bool hasEffectfulGet = false;
|
||||
accessors.LBLoc = consumeToken(tok::l_brace);
|
||||
|
||||
// Skip accessor-block disambiguation attribute if exist.
|
||||
if (Tok.is(tok::at_sign) &&
|
||||
peekToken().isContextualKeyword("_accessorBlock")) {
|
||||
consumeToken(tok::at_sign);
|
||||
consumeToken();
|
||||
}
|
||||
|
||||
while (!Tok.isAny(tok::r_brace, tok::eof)) {
|
||||
// Parse introducer if possible.
|
||||
DeclAttributes Attributes;
|
||||
|
||||
@@ -1127,6 +1127,10 @@ bool Parser::isStartOfGetSetAccessor() {
|
||||
// Eat the "{".
|
||||
consumeToken(tok::l_brace);
|
||||
|
||||
// '@_accessorBlock' is a builtin disambiguation marker.
|
||||
if (peekToken().isContextualKeyword("_accessorBlock"))
|
||||
return true;
|
||||
|
||||
// Eat attributes, if present.
|
||||
while (consumeIf(tok::at_sign)) {
|
||||
if (!consumeIf(tok::identifier))
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
// RUN: %empty-directory(%t)
|
||||
// RUN: %target-swift-frontend -emit-module -o %t/Test.swiftmodule -emit-module-interface-path %t/Test.swiftinterface -module-name Test %s
|
||||
// RUN: %target-swift-typecheck-module-from-interface(%t/Test.swiftinterface) -module-name Test
|
||||
|
||||
// RUN: %FileCheck %s --check-prefix INTERFACE --input-file %t/Test.swiftinterface
|
||||
|
||||
@frozen public struct Struct {
|
||||
public var values: [Int] = .init() {
|
||||
willSet {}
|
||||
}
|
||||
}
|
||||
// INTERFACE: @frozen public struct Struct {
|
||||
// INTERFACE-LABEL: @_hasStorage public var values: [Swift.Int] = .init() { @_accessorBlock
|
||||
// INTERFACE-NEXT: @_transparent get
|
||||
// INTERFACE-NEXT: set
|
||||
// INTERFACE-NEXT: }
|
||||
// INTERFACE: }
|
||||
Reference in New Issue
Block a user