Skip to content

Commit cc8fc77

Browse files
authored
Merge pull request #1180 from ahoppen/ahoppen/assert-token-choices
Assert that tokens in the syntax tree match `token_choices` and `text_choices`
2 parents df441cf + 1cde192 commit cc8fc77

28 files changed

+500
-59
lines changed

CodeGeneration/Sources/SyntaxSupport/KeywordSpec.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ public let KEYWORDS: [KeywordSpec] = [
130130
KeywordSpec("fileprivate", isLexerClassified: true, requiresTrailingSpace: true),
131131
KeywordSpec("final"),
132132
KeywordSpec("for", isLexerClassified: true, requiresTrailingSpace: true),
133+
KeywordSpec("forward"),
133134
KeywordSpec("func", isLexerClassified: true, requiresTrailingSpace: true),
134135
KeywordSpec("get"),
135136
KeywordSpec("guard", isLexerClassified: true, requiresTrailingSpace: true),
@@ -151,6 +152,7 @@ public let KEYWORDS: [KeywordSpec] = [
151152
KeywordSpec("left"),
152153
KeywordSpec("let", isLexerClassified: true, requiresTrailingSpace: true),
153154
KeywordSpec("line"),
155+
KeywordSpec("linear"),
154156
KeywordSpec("lowerThan"),
155157
KeywordSpec("macro"),
156158
KeywordSpec("message"),
@@ -163,6 +165,7 @@ public let KEYWORDS: [KeywordSpec] = [
163165
KeywordSpec("noasync"),
164166
KeywordSpec("noDerivative"),
165167
KeywordSpec("noescape"),
168+
KeywordSpec("none"),
166169
KeywordSpec("nonisolated"),
167170
KeywordSpec("nonmutating"),
168171
KeywordSpec("objc"),
@@ -187,6 +190,7 @@ public let KEYWORDS: [KeywordSpec] = [
187190
KeywordSpec("rethrows", isLexerClassified: true, requiresTrailingSpace: true),
188191
KeywordSpec("return", isLexerClassified: true, requiresTrailingSpace: true),
189192
KeywordSpec("reverse"),
193+
KeywordSpec("right"),
190194
KeywordSpec("safe"),
191195
KeywordSpec("self", isLexerClassified: true),
192196
KeywordSpec("Self", isLexerClassified: true),

CodeGeneration/Sources/SyntaxSupport/gyb_generated/AttributeNodes.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ public let ATTRIBUTE_NODES: [Node] = [
103103
kind: "Syntax",
104104
children: [
105105
Child(name: "Label",
106-
kind: .token(choices: [.token(tokenKind: "IdentifierToken")]),
106+
kind: .token(choices: [.keyword(text: "availability")]),
107107
description: "The label of the argument"),
108108
Child(name: "Colon",
109109
kind: .token(choices: [.token(tokenKind: "ColonToken")]),
@@ -123,7 +123,7 @@ public let ATTRIBUTE_NODES: [Node] = [
123123
],
124124
children: [
125125
Child(name: "Label",
126-
kind: .token(choices: [.token(tokenKind: "IdentifierToken")]),
126+
kind: .token(choices: [.token(tokenKind: "IdentifierToken"), .keyword(text: "available"), .keyword(text: "exported"), .keyword(text: "kind"), .keyword(text: "spi"), .keyword(text: "spiModule")]),
127127
description: "The label of the argument"),
128128
Child(name: "Colon",
129129
kind: .token(choices: [.token(tokenKind: "ColonToken")]),
@@ -146,7 +146,7 @@ public let ATTRIBUTE_NODES: [Node] = [
146146
],
147147
children: [
148148
Child(name: "Label",
149-
kind: .token(choices: [.token(tokenKind: "IdentifierToken")]),
149+
kind: .token(choices: [.keyword(text: "target")]),
150150
description: "The label of the argument"),
151151
Child(name: "Colon",
152152
kind: .token(choices: [.token(tokenKind: "ColonToken")]),
@@ -165,7 +165,7 @@ public let ATTRIBUTE_NODES: [Node] = [
165165
kind: "Syntax",
166166
children: [
167167
Child(name: "DeclBaseName",
168-
kind: .token(choices: [.token(tokenKind: "IdentifierToken"), .token(tokenKind: "PrefixOperatorToken")]),
168+
kind: .token(choices: [.token(tokenKind: "IdentifierToken"), .token(tokenKind: "PrefixOperatorToken"), .keyword(text: "init")]),
169169
description: "The base name of the protocol's requirement."),
170170
Child(name: "DeclNameArguments",
171171
kind: .node(kind: "DeclNameArguments"),
@@ -396,7 +396,7 @@ public let ATTRIBUTE_NODES: [Node] = [
396396
kind: "Syntax",
397397
children: [
398398
Child(name: "ConventionLabel",
399-
kind: .token(choices: [.keyword(text: "block"), .keyword(text: "c"), .keyword(text: "objc_method"), .keyword(text: "thin"), .keyword(text: "thick")]),
399+
kind: .token(choices: [.token(tokenKind: "IdentifierToken")]),
400400
description: "The convention label."),
401401
Child(name: "Comma",
402402
kind: .token(choices: [.token(tokenKind: "CommaToken")]),
@@ -418,7 +418,7 @@ public let ATTRIBUTE_NODES: [Node] = [
418418
kind: "Syntax",
419419
children: [
420420
Child(name: "WitnessMethodLabel",
421-
kind: .token(choices: [.token(tokenKind: "IdentifierToken")])),
421+
kind: .token(choices: [.keyword(text: "witness_method")])),
422422
Child(name: "Colon",
423423
kind: .token(choices: [.token(tokenKind: "ColonToken")])),
424424
Child(name: "ProtocolName",

CodeGeneration/Sources/SyntaxSupport/gyb_generated/AvailabilityNodes.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public let AVAILABILITY_NODES: [Node] = [
4545
kind: "Syntax",
4646
children: [
4747
Child(name: "Label",
48-
kind: .token(choices: [.token(tokenKind: "IdentifierToken")]),
48+
kind: .token(choices: [.keyword(text: "message"), .keyword(text: "renamed"), .keyword(text: "introduced"), .keyword(text: "obsoleted"), .keyword(text: "deprecated")]),
4949
description: "The label of the argument"),
5050
Child(name: "Colon",
5151
kind: .token(choices: [.token(tokenKind: "ColonToken")]),

CodeGeneration/Sources/SyntaxSupport/gyb_generated/DeclNodes.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ public let DECL_NODES: [Node] = [
216216
Child(name: "LeftParen",
217217
kind: .token(choices: [.token(tokenKind: "LeftParenToken")])),
218218
Child(name: "Detail",
219-
kind: .token(choices: [.token(tokenKind: "IdentifierToken")])),
219+
kind: .token(choices: [.token(tokenKind: "IdentifierToken"), .keyword(text: "set")])),
220220
Child(name: "RightParen",
221221
kind: .token(choices: [.token(tokenKind: "RightParenToken")]))
222222
]),
@@ -226,7 +226,7 @@ public let DECL_NODES: [Node] = [
226226
kind: "Syntax",
227227
children: [
228228
Child(name: "Name",
229-
kind: .token(choices: [.keyword(text: "class"), .keyword(text: "convenience"), .keyword(text: "dynamic"), .keyword(text: "final"), .keyword(text: "infix"), .keyword(text: "lazy"), .keyword(text: "optional"), .keyword(text: "override"), .keyword(text: "postfix"), .keyword(text: "prefix"), .keyword(text: "required"), .keyword(text: "static"), .keyword(text: "unowned"), .keyword(text: "weak"), .keyword(text: "private"), .keyword(text: "fileprivate"), .keyword(text: "internal"), .keyword(text: "public"), .keyword(text: "open"), .keyword(text: "mutating"), .keyword(text: "nonmutating"), .keyword(text: "indirect"), .keyword(text: "__consuming"), .keyword(text: "actor"), .keyword(text: "async"), .keyword(text: "distributed"), .keyword(text: "isolated"), .keyword(text: "nonisolated"), .keyword(text: "_const"), .keyword(text: "_local")]),
229+
kind: .token(choices: [.keyword(text: "class"), .keyword(text: "convenience"), .keyword(text: "dynamic"), .keyword(text: "final"), .keyword(text: "infix"), .keyword(text: "lazy"), .keyword(text: "optional"), .keyword(text: "override"), .keyword(text: "postfix"), .keyword(text: "prefix"), .keyword(text: "required"), .keyword(text: "static"), .keyword(text: "unowned"), .keyword(text: "weak"), .keyword(text: "private"), .keyword(text: "fileprivate"), .keyword(text: "internal"), .keyword(text: "public"), .keyword(text: "open"), .keyword(text: "mutating"), .keyword(text: "nonmutating"), .keyword(text: "indirect"), .keyword(text: "__consuming"), .keyword(text: "actor"), .keyword(text: "async"), .keyword(text: "distributed"), .keyword(text: "isolated"), .keyword(text: "nonisolated"), .keyword(text: "_const"), .keyword(text: "_local"), .keyword(text: "package")]),
230230
classification: "Attribute"),
231231
Child(name: "Detail",
232232
kind: .node(kind: "DeclModifierDetail"),
@@ -934,7 +934,7 @@ public let DECL_NODES: [Node] = [
934934
Child(name: "LeadingComma",
935935
kind: .token(choices: [.token(tokenKind: "CommaToken")])),
936936
Child(name: "Name",
937-
kind: .token(choices: [.token(tokenKind: "IdentifierToken")]))
937+
kind: .node(kind: "Token"))
938938
]),
939939

940940
Node(name: "OperatorPrecedenceAndTypes",

CodeGeneration/Sources/SyntaxSupport/gyb_generated/ExprNodes.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -737,11 +737,11 @@ public let EXPR_NODES: [Node] = [
737737
kind: .token(choices: [.token(tokenKind: "RawStringDelimiterToken")]),
738738
isOptional: true),
739739
Child(name: "OpenQuote",
740-
kind: .token(choices: [.token(tokenKind: "StringQuoteToken"), .token(tokenKind: "MultilineStringQuoteToken")])),
740+
kind: .token(choices: [.token(tokenKind: "StringQuoteToken"), .token(tokenKind: "MultilineStringQuoteToken"), .token(tokenKind: "SingleQuoteToken")])),
741741
Child(name: "Segments",
742742
kind: .collection(kind: "StringLiteralSegments", collectionElementName: "Segment")),
743743
Child(name: "CloseQuote",
744-
kind: .token(choices: [.token(tokenKind: "StringQuoteToken"), .token(tokenKind: "MultilineStringQuoteToken")])),
744+
kind: .token(choices: [.token(tokenKind: "StringQuoteToken"), .token(tokenKind: "MultilineStringQuoteToken"), .token(tokenKind: "SingleQuoteToken")])),
745745
Child(name: "CloseDelimiter",
746746
kind: .token(choices: [.token(tokenKind: "RawStringDelimiterToken")]),
747747
isOptional: true)

CodeGeneration/Sources/SyntaxSupport/gyb_generated/GenericNodes.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ public let GENERIC_NODES: [Node] = [
7171
Child(name: "Colon",
7272
kind: .token(choices: [.token(tokenKind: "ColonToken")])),
7373
Child(name: "LayoutConstraint",
74-
kind: .token(choices: [.token(tokenKind: "IdentifierToken")])),
74+
kind: .token(choices: [.keyword(text: "_Trivial"), .keyword(text: "_TrivialAtMost"), .keyword(text: "_UnknownLayout"), .keyword(text: "_RefCountedObject"), .keyword(text: "_NativeRefCountedObject"), .keyword(text: "_Class"), .keyword(text: "_NativeClass")])),
7575
Child(name: "LeftParen",
7676
kind: .token(choices: [.token(tokenKind: "LeftParenToken")]),
7777
isOptional: true),

CodeGeneration/Sources/SyntaxSupport/gyb_generated/TypeNodes.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public let TYPE_NODES: [Node] = [
1818
kind: "Type",
1919
children: [
2020
Child(name: "Name",
21-
kind: .token(choices: [.token(tokenKind: "IdentifierToken"), .token(tokenKind: "KeywordToken")]),
21+
kind: .token(choices: [.token(tokenKind: "IdentifierToken"), .token(tokenKind: "KeywordToken"), .token(tokenKind: "WildcardToken")]),
2222
classification: "TypeIdentifier"),
2323
Child(name: "GenericArgumentClause",
2424
kind: .node(kind: "GenericArgumentClause"),
@@ -245,7 +245,7 @@ public let TYPE_NODES: [Node] = [
245245
],
246246
children: [
247247
Child(name: "Specifier",
248-
kind: .token(choices: [.keyword(text: "inout"), .keyword(text: "__shared"), .keyword(text: "__owned")]),
248+
kind: .token(choices: [.keyword(text: "inout"), .keyword(text: "__shared"), .keyword(text: "__owned"), .keyword(text: "isolated"), .keyword(text: "_const")]),
249249
isOptional: true),
250250
Child(name: "Attributes",
251251
kind: .collection(kind: "AttributeList", collectionElementName: "Attribute"),

Sources/SwiftParser/Attributes.swift

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -418,7 +418,7 @@ extension Parser {
418418
}
419419

420420
mutating func parseDifferentiabilityParameters() -> RawDifferentiabilityParamsClauseSyntax {
421-
let (unexpectedBeforeWrt, wrt) = self.expectIdentifier(keywordRecovery: true)
421+
let (unexpectedBeforeWrt, wrt) = self.expect(.keyword(.wrt))
422422
let (unexpectedBeforeColon, colon) = self.expect(.colon)
423423

424424
guard let leftParen = self.consume(if: .leftParen) else {
@@ -879,31 +879,35 @@ extension Parser {
879879
)
880880
)
881881
} else {
882-
let label = self.consumeAnyToken()
882+
let (unexpectedBeforeLabel, label) = self.expect(.identifier)
883883
let unexpectedBeforeComma: RawUnexpectedNodesSyntax?
884884
let comma: RawTokenSyntax?
885+
let unexpectedBeforeCTypeLabel: RawUnexpectedNodesSyntax?
885886
let cTypeLabel: RawTokenSyntax?
886887
let unexpectedBeforeColon: RawUnexpectedNodesSyntax?
887888
let colon: RawTokenSyntax?
888889
let cTypeString: RawStringLiteralExprSyntax?
889890
if self.at(.comma) {
890891
(unexpectedBeforeComma, comma) = self.expect(.comma)
891-
cTypeLabel = self.consumeAnyToken()
892+
(unexpectedBeforeCTypeLabel, cTypeLabel) = self.expect(.keyword(.cType))
892893
(unexpectedBeforeColon, colon) = self.expect(.colon)
893894
cTypeString = self.parseStringLiteral()
894895
} else {
895896
unexpectedBeforeComma = nil
896897
comma = nil
898+
unexpectedBeforeCTypeLabel = nil
897899
cTypeLabel = nil
898900
unexpectedBeforeColon = nil
899901
colon = nil
900902
cTypeString = nil
901903
}
902904
return .conventionArguments(
903905
RawConventionAttributeArgumentsSyntax(
906+
unexpectedBeforeLabel,
904907
conventionLabel: label,
905908
unexpectedBeforeComma,
906909
comma: comma,
910+
unexpectedBeforeCTypeLabel,
907911
cTypeLabel: cTypeLabel,
908912
unexpectedBeforeColon,
909913
colon: colon,
@@ -917,7 +921,7 @@ extension Parser {
917921

918922
extension Parser {
919923
mutating func parseBackDeployArguments() -> RawBackDeployAttributeSpecListSyntax {
920-
let (unexpectedBeforeLabel, label) = self.expect(.keyword(.before), remapping: .identifier)
924+
let (unexpectedBeforeLabel, label) = self.expect(.keyword(.before))
921925
let (unexpectedBeforeColon, colon) = self.expect(.colon)
922926
var elements: [RawAvailabilityVersionRestrictionListEntrySyntax] = []
923927
var keepGoing: RawTokenSyntax? = nil
@@ -974,7 +978,7 @@ extension Parser {
974978

975979
extension Parser {
976980
mutating func parseOriginallyDefinedInArguments() -> RawOriginallyDefinedInArgumentsSyntax {
977-
let (unexpectedBeforeModuleLabel, moduleLabel) = self.expect(.keyword(.module), remapping: .identifier)
981+
let (unexpectedBeforeModuleLabel, moduleLabel) = self.expect(.keyword(.module))
978982
let (unexpectedBeforeColon, colon) = self.expect(.colon)
979983
let moduleName = self.parseStringLiteral()
980984
let (unexpectedBeforeComma, comma) = self.expect(.comma)
@@ -1009,7 +1013,7 @@ extension Parser {
10091013

10101014
extension Parser {
10111015
mutating func parseUnderscorePrivateAttributeArguments() -> RawUnderscorePrivateAttributeArgumentsSyntax {
1012-
let (unexpectedBeforeLabel, label) = self.expect(.keyword(.sourceFile), remapping: .identifier)
1016+
let (unexpectedBeforeLabel, label) = self.expect(.keyword(.sourceFile))
10131017
let (unexpectedBeforeColon, colon) = self.expect(.colon)
10141018
let filename = self.parseStringLiteral()
10151019
return RawUnderscorePrivateAttributeArgumentsSyntax(
@@ -1025,7 +1029,7 @@ extension Parser {
10251029

10261030
extension Parser {
10271031
mutating func parseDynamicReplacementArguments() -> RawDynamicReplacementArgumentsSyntax {
1028-
let (unexpectedBeforeLabel, label) = self.expect(.keyword(.for), remapping: .identifier)
1032+
let (unexpectedBeforeLabel, label) = self.expect(.keyword(.for))
10291033
let (unexpectedBeforeColon, colon) = self.expect(.colon)
10301034
let base: RawTokenSyntax
10311035
let args: RawDeclNameArgumentsSyntax?
@@ -1051,7 +1055,7 @@ extension Parser {
10511055

10521056
extension Parser {
10531057
mutating func parseUnavailableFromAsyncArguments() -> RawUnavailableFromAsyncArgumentsSyntax {
1054-
let (unexpectedBeforeLabel, label) = self.expect(.keyword(.message), remapping: .identifier)
1058+
let (unexpectedBeforeLabel, label) = self.expect(.keyword(.message))
10551059
let (unexpectedBeforeColon, colon) = self.expect(.colon)
10561060
let message = self.parseStringLiteral()
10571061
return RawUnavailableFromAsyncArgumentsSyntax(

Sources/SwiftParser/Declarations.swift

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -695,7 +695,7 @@ extension Parser {
695695
requirement = .sameTypeRequirement(
696696
RawSameTypeRequirementSyntax(
697697
leftTypeIdentifier: firstType,
698-
equalityToken: RawTokenSyntax(missing: .equal, arena: self.arena),
698+
equalityToken: RawTokenSyntax(missing: .binaryOperator, text: "==", arena: self.arena),
699699
rightTypeIdentifier: RawTypeSyntax(RawMissingTypeSyntax(arena: self.arena)),
700700
arena: self.arena
701701
)
@@ -981,7 +981,7 @@ extension Parser {
981981
let failable: RawTokenSyntax?
982982
if let parsedFailable = self.consume(ifAny: [.exclamationMark, .postfixQuestionMark, .infixQuestionMark]) {
983983
failable = parsedFailable
984-
} else if let parsedFailable = self.consumeIfContextualPunctuator("!") {
984+
} else if let parsedFailable = self.consumeIfContextualPunctuator("!", remapping: .exclamationMark) {
985985
failable = parsedFailable
986986
} else {
987987
failable = nil
@@ -1563,8 +1563,10 @@ extension Parser {
15631563
// get and set.
15641564
let modifier: RawDeclModifierSyntax?
15651565
if hasModifier {
1566+
let (unexpectedBeforeName, name) = self.expectAny([.keyword(.mutating), .keyword(.nonmutating), .keyword(.__consuming)], default: .keyword(.mutating))
15661567
modifier = RawDeclModifierSyntax(
1567-
name: self.consumeAnyToken(),
1568+
unexpectedBeforeName,
1569+
name: name,
15681570
detail: nil,
15691571
arena: self.arena
15701572
)
@@ -1980,7 +1982,10 @@ extension Parser {
19801982
case (.associativity, let handle)?:
19811983
let associativity = self.eat(handle)
19821984
let (unexpectedBeforeColon, colon) = self.expect(.colon)
1983-
let (unexpectedBeforeValue, value) = self.expectIdentifier()
1985+
var (unexpectedBeforeValue, value) = self.expectAny([.keyword(.left), .keyword(.right), .keyword(.none)], default: .keyword(.none))
1986+
if value.isMissing, let identifier = self.consume(if: .identifier) {
1987+
unexpectedBeforeValue = RawUnexpectedNodesSyntax(combining: unexpectedBeforeValue, identifier, arena: self.arena)
1988+
}
19841989
elements.append(
19851990
.precedenceGroupAssociativity(
19861991
RawPrecedenceGroupAssociativitySyntax(

Sources/SwiftParser/Directives.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -152,12 +152,12 @@ extension Parser {
152152
let (unexpectedBeforeLParen, lparen) = self.expect(.leftParen)
153153
let args: RawPoundSourceLocationArgsSyntax?
154154
if !self.at(.rightParen) {
155-
let (unexpectedBeforeFile, file) = self.expectIdentifier()
155+
let (unexpectedBeforeFile, file) = self.expect(.keyword(.file))
156156
let (unexpectedBeforeFileColon, fileColon) = self.expect(.colon)
157157
let fileName = self.parseStringLiteral()
158158
let (unexpectedBeforeComma, comma) = self.expect(.comma)
159159

160-
let (unexpectedBeforeLine, line) = self.expectIdentifier()
160+
let (unexpectedBeforeLine, line) = self.expect(.keyword(.line))
161161
let (unexpectedBeforeLineColon, lineColon) = self.expect(.colon)
162162
let lineNumber = self.expectWithoutRecovery(.integerLiteral)
163163

Sources/SwiftParser/RawTokenKindSubset.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,18 @@ enum OperatorLike: RawTokenKindSubset {
467467
default: return nil
468468
}
469469
}
470+
471+
var remappedKind: RawTokenKind? {
472+
switch self {
473+
case .operator(_): return nil
474+
case .exclamationMark: return .postfixOperator
475+
case .infixQuestionMark: return .binaryOperator
476+
case .postfixQuestionMark: return .postfixOperator
477+
case .equal: return .binaryOperator
478+
case .arrow: return .binaryOperator
479+
case .regexLiteral: return .binaryOperator
480+
}
481+
}
470482
}
471483

472484
enum PoundDeclarationStart: RawTokenKindSubset {

Sources/SwiftParser/TokenConsumer.swift

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,9 +162,13 @@ extension TokenConsumer {
162162

163163
/// Consumes and returns the current token is an operator with the given `name`.
164164
@_spi(RawSyntax)
165-
public mutating func consumeIfContextualPunctuator(_ name: SyntaxText) -> Token? {
165+
public mutating func consumeIfContextualPunctuator(_ name: SyntaxText, remapping: RawTokenKind? = nil) -> Token? {
166166
if self.atContextualPunctuator(name) {
167-
return self.consumeAnyToken()
167+
if let remapping = remapping {
168+
return self.consumeAnyToken(remapping: remapping)
169+
} else {
170+
return self.consumeAnyToken()
171+
}
168172
}
169173
return nil
170174
}

Sources/SwiftParser/Types.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -548,7 +548,7 @@ extension Parser {
548548
}
549549
// Parse the type annotation.
550550
let type = self.parseType(misplacedSpecifiers: misplacedSpecifiers)
551-
let ellipsis = self.currentToken.isEllipsis ? self.consumeAnyToken() : nil
551+
let ellipsis = self.consumeIfContextualPunctuator("...", remapping: .ellipsis)
552552
var trailingComma = self.consume(if: .comma)
553553
if trailingComma == nil && self.withLookahead({ $0.canParseType() }) {
554554
// If the next token does not close the tuple, it is very likely the user forgot the comma.

0 commit comments

Comments
 (0)