Skip to content

Commit 3ec17e0

Browse files
authored
Merge pull request #2453 from DougGregor/deinit-subscript-decl-ref-fixes
Only parse subscript and deinit as declaration references within macro role attributes
2 parents eee52cb + a3f1e2a commit 3ec17e0

File tree

8 files changed

+232
-21
lines changed

8 files changed

+232
-21
lines changed

CodeGeneration/Sources/SyntaxSupport/KeywordSpec.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ public enum Keyword: CaseIterable {
185185
case discard
186186
case forward
187187
case `func`
188+
case freestanding
188189
case get
189190
case `guard`
190191
case higherThan
@@ -508,6 +509,8 @@ public enum Keyword: CaseIterable {
508509
return KeywordSpec("forward")
509510
case .func:
510511
return KeywordSpec("func", isLexerClassified: true)
512+
case .freestanding:
513+
return KeywordSpec("freestanding")
511514
case .get:
512515
return KeywordSpec("get")
513516
case .guard:

Sources/SwiftParser/Attributes.swift

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ extension Parser {
6060
case derivative
6161
case differentiable
6262
case exclusivity
63+
case freestanding
6364
case inline
6465
case objc
6566
case Sendable
@@ -96,6 +97,7 @@ extension Parser {
9697
case TokenSpec(.derivative): self = .derivative
9798
case TokenSpec(.differentiable): self = .differentiable
9899
case TokenSpec(.exclusivity): self = .exclusivity
100+
case TokenSpec(.freestanding): self = .freestanding
99101
case TokenSpec(.inline): self = .inline
100102
case TokenSpec(.objc): self = .objc
101103
case TokenSpec(.Sendable): self = .Sendable
@@ -136,6 +138,7 @@ extension Parser {
136138
case .derivative: return .keyword(.derivative)
137139
case .differentiable: return .keyword(.differentiable)
138140
case .exclusivity: return .keyword(.exclusivity)
141+
case .freestanding: return .keyword(.freestanding)
139142
case .inline: return .keyword(.inline)
140143
case .objc: return .keyword(.objc)
141144
case .Sendable: return .keyword(.Sendable)
@@ -322,9 +325,9 @@ extension Parser {
322325
return parseAttribute(argumentMode: .optional) { parser in
323326
return .unavailableFromAsyncArguments(parser.parseUnavailableFromAsyncAttributeArguments())
324327
}
325-
case .attached:
328+
case .attached, .freestanding:
326329
return parseAttribute(argumentMode: .customAttribute) { parser in
327-
let arguments = parser.parseAttachedArguments()
330+
let arguments = parser.parseMacroRoleArguments()
328331
return .argumentList(RawLabeledExprListSyntax(elements: arguments, arena: parser.arena))
329332
}
330333
case .rethrows:
@@ -356,7 +359,7 @@ extension Parser {
356359
}
357360

358361
extension Parser {
359-
mutating func parseAttachedArguments() -> [RawLabeledExprSyntax] {
362+
mutating func parseMacroRoleArguments() -> [RawLabeledExprSyntax] {
360363
let (unexpectedBeforeRole, role) = self.expect(.identifier, TokenSpec(.extension, remapping: .identifier), default: .identifier)
361364
let roleTrailingComma = self.consume(if: .comma)
362365
let roleElement = RawLabeledExprSyntax(
@@ -373,7 +376,7 @@ extension Parser {
373376
trailingComma: roleTrailingComma,
374377
arena: self.arena
375378
)
376-
let additionalArgs = self.parseArgumentListElements(pattern: .none)
379+
let additionalArgs = self.parseArgumentListElements(pattern: .none, flavor: .attributeArguments)
377380
return [roleElement] + additionalArgs
378381
}
379382
}

Sources/SwiftParser/Expressions.swift

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,10 @@ extension Parser {
7878
///
7979
/// We don't allow allow newlines here.
8080
case poundIfDirective
81+
82+
/// Parsing an attribute's arguments, which can contain declaration
83+
/// references like `subscript` or `deinit`.
84+
case attributeArguments
8185
}
8286

8387
enum PatternContext {
@@ -725,7 +729,7 @@ extension Parser {
725729

726730
// If there is an expr-call-suffix, parse it and form a call.
727731
if let lparen = self.consume(if: TokenSpec(.leftParen, allowAtStartOfLine: false)) {
728-
let args = self.parseArgumentListElements(pattern: pattern)
732+
let args = self.parseArgumentListElements(pattern: pattern, flavor: flavor.callArgumentFlavor)
729733
let (unexpectedBeforeRParen, rparen) = self.expect(.rightParen)
730734

731735
// If we can parse trailing closures, do so.
@@ -1135,9 +1139,9 @@ extension Parser {
11351139
return RawExprSyntax(RawPatternExprSyntax(pattern: pattern, arena: self.arena))
11361140
}
11371141

1138-
return RawExprSyntax(self.parseIdentifierExpression())
1142+
return RawExprSyntax(self.parseIdentifierExpression(flavor: flavor))
11391143
case (.Self, _)?: // Self
1140-
return RawExprSyntax(self.parseIdentifierExpression())
1144+
return RawExprSyntax(self.parseIdentifierExpression(flavor: flavor))
11411145
case (.Any, _)?: // Any
11421146
let anyType = RawTypeSyntax(self.parseAnyType())
11431147
return RawExprSyntax(RawTypeExprSyntax(type: anyType, arena: self.arena))
@@ -1237,8 +1241,14 @@ extension Parser {
12371241

12381242
extension Parser {
12391243
/// Parse an identifier as an expression.
1240-
mutating func parseIdentifierExpression() -> RawExprSyntax {
1241-
let declName = self.parseDeclReferenceExpr(.compoundNames)
1244+
mutating func parseIdentifierExpression(flavor: ExprFlavor) -> RawExprSyntax {
1245+
var options: DeclNameOptions = .compoundNames
1246+
switch flavor {
1247+
case .basic, .poundIfDirective, .stmtCondition: break
1248+
case .attributeArguments: options.insert(.keywordsUsingSpecialNames)
1249+
}
1250+
1251+
let declName = self.parseDeclReferenceExpr(options)
12421252
guard self.withLookahead({ $0.canParseAsGenericArgumentList() }) else {
12431253
return RawExprSyntax(declName)
12441254
}
@@ -1689,7 +1699,7 @@ extension Parser {
16891699
name = nil
16901700
unexpectedBeforeEqual = nil
16911701
equal = nil
1692-
expression = RawExprSyntax(self.parseIdentifierExpression())
1702+
expression = RawExprSyntax(self.parseIdentifierExpression(flavor: .basic))
16931703
}
16941704

16951705
keepGoing = self.consume(if: .comma)
@@ -1833,7 +1843,7 @@ extension Parser {
18331843
///
18341844
/// This is currently the same as parsing a tuple expression. In the future,
18351845
/// this will be a dedicated argument list type.
1836-
mutating func parseArgumentListElements(pattern: PatternContext) -> [RawLabeledExprSyntax] {
1846+
mutating func parseArgumentListElements(pattern: PatternContext, flavor: ExprFlavor = .basic) -> [RawLabeledExprSyntax] {
18371847
if let remainingTokens = remainingTokensIfMaximumNestingLevelReached() {
18381848
return [
18391849
RawLabeledExprSyntax(
@@ -1878,7 +1888,7 @@ extension Parser {
18781888
if self.at(.binaryOperator) && self.peek(isAt: .comma, .rightParen, .rightSquare) {
18791889
expr = RawExprSyntax(self.parseDeclReferenceExpr(.operators))
18801890
} else {
1881-
expr = self.parseExpression(flavor: .basic, pattern: pattern)
1891+
expr = self.parseExpression(flavor: flavor, pattern: pattern)
18821892
}
18831893
keepGoing = self.consume(if: .comma)
18841894
result.append(
@@ -2548,3 +2558,14 @@ extension SyntaxKind {
25482558
}
25492559
}
25502560
}
2561+
2562+
private extension Parser.ExprFlavor {
2563+
/// The expression flavor used for the argument of a call that occurs
2564+
/// within a particularly-flavored expression.
2565+
var callArgumentFlavor: Parser.ExprFlavor {
2566+
switch self {
2567+
case .basic, .poundIfDirective, .stmtCondition: return .basic
2568+
case .attributeArguments: return .attributeArguments
2569+
}
2570+
}
2571+
}

Sources/SwiftParser/Names.swift

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,12 +66,14 @@ extension Parser {
6666
mutating func parseDeclReferenceExpr(_ flags: DeclNameOptions = []) -> RawDeclReferenceExprSyntax {
6767
// Consume the base name.
6868
let base: RawTokenSyntax
69-
if let identOrSelf = self.consume(if: .identifier, .keyword(.self), .keyword(.Self)) ?? self.consume(if: .keyword(.`init`)) ?? self.consume(
70-
if: .keyword(.`deinit`)
71-
) ?? self.consume(if: .keyword(.`subscript`)) {
69+
if let identOrSelf = self.consume(if: .identifier, .keyword(.self), .keyword(.Self)) ?? self.consume(if: .keyword(.`init`)) {
7270
base = identOrSelf
7371
} else if flags.contains(.operators), let (_, _) = self.at(anyIn: Operator.self) {
7472
base = self.consumeAnyToken(remapping: .binaryOperator)
73+
} else if flags.contains(.keywordsUsingSpecialNames),
74+
let special = self.consume(if: .keyword(.`deinit`), .keyword(.`subscript`))
75+
{
76+
base = special
7577
} else if flags.contains(.keywords) && self.currentToken.isLexerClassifiedKeyword {
7678
base = self.consumeAnyToken(remapping: .identifier)
7779
} else {

Sources/SwiftParser/TokenPrecedence.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,7 @@ enum TokenPrecedence: Comparable {
282282
.backDeployed,
283283
.derivative,
284284
.exclusivity,
285+
.freestanding,
285286
.inline,
286287
.objc,
287288
.transpose:

Sources/SwiftSyntax/generated/Keyword.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ public enum Keyword: UInt8, Hashable, Sendable {
127127
case discard
128128
case forward
129129
case `func`
130+
case freestanding
130131
case get
131132
case `guard`
132133
case higherThan
@@ -647,6 +648,8 @@ public enum Keyword: UInt8, Hashable, Sendable {
647648
self = .availability
648649
case "backDeployed":
649650
self = .backDeployed
651+
case "freestanding":
652+
self = .freestanding
650653
case "noDerivative":
651654
self = .noDerivative
652655
case "transferring":
@@ -909,6 +912,7 @@ public enum Keyword: UInt8, Hashable, Sendable {
909912
"discard",
910913
"forward",
911914
"func",
915+
"freestanding",
912916
"get",
913917
"guard",
914918
"higherThan",

0 commit comments

Comments
 (0)