Skip to content

Commit 33e4b33

Browse files
authored
Merge pull request #1445 from kimdv/kimdv/add-diagnostic-for-comparison-in-default-value
2 parents 74c544e + 0643ff3 commit 33e4b33

File tree

10 files changed

+62
-29
lines changed

10 files changed

+62
-29
lines changed

Sources/SwiftParser/Declarations.swift

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ extension Parser {
192192
lastElement.unexpectedBeforeDecl,
193193
decl: lastElement.decl,
194194
lastElement.unexpectedBetweenDeclAndSemicolon,
195-
semicolon: parser.missingToken(.semicolon, text: nil),
195+
semicolon: parser.missingToken(.semicolon),
196196
lastElement.unexpectedAfterSemicolon,
197197
arena: parser.arena
198198
)
@@ -835,7 +835,7 @@ extension Parser {
835835
lastItem.unexpectedBeforeDecl,
836836
decl: lastItem.decl,
837837
lastItem.unexpectedBetweenDeclAndSemicolon,
838-
semicolon: self.missingToken(.semicolon, text: nil),
838+
semicolon: self.missingToken(.semicolon),
839839
lastItem.unexpectedAfterSemicolon,
840840
arena: self.arena
841841
)
@@ -1229,7 +1229,7 @@ extension Parser {
12291229
}
12301230

12311231
let defaultArgument: RawInitializerClauseSyntax?
1232-
if self.at(.equal) {
1232+
if self.at(.equal) || self.atContextualPunctuator("==") {
12331233
defaultArgument = self.parseDefaultArgument()
12341234
} else {
12351235
defaultArgument = nil
@@ -1575,7 +1575,7 @@ extension Parser {
15751575
typeAnnotationUnwrapped.unexpectedBetweenColonAndType,
15761576
arena: self.arena
15771577
),
1578-
equal: missingToken(.equal, text: nil),
1578+
equal: missingToken(.equal),
15791579
value: initExpr,
15801580
arena: self.arena
15811581
)
@@ -1742,7 +1742,7 @@ extension Parser {
17421742
let lbrace: RawTokenSyntax
17431743
if self.at(anyIn: AccessorKind.self) != nil {
17441744
unexpectedBeforeLBrace = nil
1745-
lbrace = missingToken(.leftBrace, text: nil)
1745+
lbrace = missingToken(.leftBrace)
17461746
} else {
17471747
(unexpectedBeforeLBrace, lbrace) = self.expect(.leftBrace)
17481748
}
@@ -1831,7 +1831,7 @@ extension Parser {
18311831
let equal: RawTokenSyntax
18321832
if let colon = self.consume(if: .colon) {
18331833
unexpectedBeforeEqual = RawUnexpectedNodesSyntax(elements: [RawSyntax(colon)], arena: self.arena)
1834-
equal = missingToken(.equal, text: nil)
1834+
equal = missingToken(.equal)
18351835
} else {
18361836
(unexpectedBeforeEqual, equal) = self.expect(.equal)
18371837
}
@@ -1895,7 +1895,7 @@ extension Parser {
18951895
} else {
18961896
unexpectedBeforeName = nil
18971897
}
1898-
name = missingToken(.binaryOperator, text: nil)
1898+
name = missingToken(.binaryOperator)
18991899
}
19001900

19011901
// Eat any subsequent tokens that are not separated to the operator by trivia.

Sources/SwiftParser/Expressions.swift

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1671,7 +1671,18 @@ extension Parser {
16711671
extension Parser {
16721672
@_spi(RawSyntax)
16731673
public mutating func parseDefaultArgument() -> RawInitializerClauseSyntax {
1674-
let (unexpectedBeforeEq, eq) = self.expect(.equal)
1674+
let unexpectedBeforeEq: RawUnexpectedNodesSyntax?
1675+
let eq: RawTokenSyntax
1676+
if let comparison = self.consumeIfContextualPunctuator("==") {
1677+
unexpectedBeforeEq = RawUnexpectedNodesSyntax(
1678+
elements: [RawSyntax(comparison)],
1679+
arena: self.arena
1680+
)
1681+
eq = missingToken(.equal)
1682+
} else {
1683+
(unexpectedBeforeEq, eq) = self.expect(.equal)
1684+
}
1685+
16751686
let expr = self.parseExpression()
16761687
return RawInitializerClauseSyntax(
16771688
unexpectedBeforeEq,
@@ -2314,7 +2325,7 @@ extension Parser {
23142325
RawCaseItemSyntax(
23152326
pattern: RawPatternSyntax(
23162327
RawIdentifierPatternSyntax(
2317-
identifier: missingToken(.identifier, text: nil),
2328+
identifier: missingToken(.identifier),
23182329
arena: self.arena
23192330
)
23202331
),
@@ -2325,7 +2336,7 @@ extension Parser {
23252336
],
23262337
arena: self.arena
23272338
),
2328-
colon: missingToken(.colon, text: nil),
2339+
colon: missingToken(.colon),
23292340
arena: self.arena
23302341
)
23312342
),

Sources/SwiftParser/Names.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ extension Parser {
2828
if let dollarIdent = self.consume(if: .dollarIdentifier) {
2929
return (
3030
RawUnexpectedNodesSyntax(elements: [RawSyntax(dollarIdent)], arena: self.arena),
31-
self.missingToken(.identifier, text: nil)
31+
self.missingToken(.identifier)
3232
)
3333
} else {
3434
if let wildcardToken = self.consume(if: .wildcard) {

Sources/SwiftParser/Parser.swift

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -439,7 +439,7 @@ extension Parser {
439439
if let number = self.consume(if: .integerLiteral, .floatingLiteral, .dollarIdentifier) {
440440
return (
441441
RawUnexpectedNodesSyntax(elements: [RawSyntax(number)], arena: self.arena),
442-
self.missingToken(.identifier, text: nil)
442+
self.missingToken(.identifier)
443443
)
444444
} else if keywordRecovery,
445445
(self.currentToken.isLexerClassifiedKeyword || self.currentToken.rawTokenKind == .wildcard),
@@ -448,7 +448,7 @@ extension Parser {
448448
let keyword = self.consumeAnyToken()
449449
return (
450450
RawUnexpectedNodesSyntax(elements: [RawSyntax(keyword)], arena: self.arena),
451-
self.missingToken(.identifier, text: nil)
451+
self.missingToken(.identifier)
452452
)
453453
}
454454
return (
@@ -505,21 +505,21 @@ extension Parser {
505505
var lookahead = self.lookahead()
506506
guard let recoveryHandle = lookahead.canRecoverTo(.rightBrace) else {
507507
// We can't recover to '}'. Synthesize it.
508-
return (nil, self.missingToken(.rightBrace, text: nil))
508+
return (nil, self.missingToken(.rightBrace))
509509
}
510510

511511
// We can recover to a '}'. Decide whether we want to eat it based on its indentation.
512512
let rightBraceTrivia = self.arena.parseTrivia(source: lookahead.currentToken.leadingTriviaText, position: .leading)
513513
switch (indentation(introducer.leadingTriviaPieces), indentation(rightBraceTrivia)) {
514514
// Catch cases where the brace has known indentation that is less than that of `introducer`, in which case we don't want to consume it.
515515
case (.spaces(let introducerSpaces), .spaces(let rightBraceSpaces)) where rightBraceSpaces < introducerSpaces:
516-
return (nil, self.missingToken(.rightBrace, text: nil))
516+
return (nil, self.missingToken(.rightBrace))
517517
case (.tabs(let introducerTabs), .tabs(let rightBraceTabs)) where rightBraceTabs < introducerTabs:
518-
return (nil, self.missingToken(.rightBrace, text: nil))
518+
return (nil, self.missingToken(.rightBrace))
519519
case (.spaces, .tabs(0)):
520-
return (nil, self.missingToken(.rightBrace, text: nil))
520+
return (nil, self.missingToken(.rightBrace))
521521
case (.tabs, .spaces(0)):
522-
return (nil, self.missingToken(.rightBrace, text: nil))
522+
return (nil, self.missingToken(.rightBrace))
523523
default:
524524
return self.eat(recoveryHandle)
525525
}

Sources/SwiftParser/Patterns.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ extension Parser {
141141
return RawPatternSyntax(
142142
RawIdentifierPatternSyntax(
143143
RawUnexpectedNodesSyntax([keyword], arena: self.arena),
144-
identifier: missingToken(.identifier, text: nil),
144+
identifier: missingToken(.identifier),
145145
arena: self.arena
146146
)
147147
)
@@ -178,7 +178,7 @@ extension Parser {
178178
// Recovery if the user forgot to add ':'
179179
let result = self.parseResultType()
180180
type = RawTypeAnnotationSyntax(
181-
colon: self.missingToken(.colon, text: nil),
181+
colon: self.missingToken(.colon),
182182
type: result,
183183
arena: self.arena
184184
)

Sources/SwiftParser/TokenConsumer.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -224,15 +224,15 @@ extension TokenConsumer {
224224
if let (_, handle) = self.at(anyIn: IdentifierTokens.self) {
225225
return self.eat(handle)
226226
}
227-
return missingToken(.identifier, text: nil)
227+
return missingToken(.identifier)
228228
}
229229

230230
@inline(__always)
231231
mutating func expectIdentifierOrRethrowsWithoutRecovery() -> Token {
232232
if let (_, handle) = self.at(anyIn: IdentifierOrRethrowsTokens.self) {
233233
return self.eat(handle)
234234
}
235-
return missingToken(.identifier, text: nil)
235+
return missingToken(.identifier)
236236
}
237237

238238
var canHaveParameterSpecifier: Bool {

Sources/SwiftParser/TopLevel.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ extension Parser {
7272
lastItem.unexpectedBeforeItem,
7373
item: .init(lastItem.item)!,
7474
lastItem.unexpectedBetweenItemAndSemicolon,
75-
semicolon: self.missingToken(.semicolon, text: nil),
75+
semicolon: self.missingToken(.semicolon),
7676
lastItem.unexpectedAfterSemicolon,
7777
arena: self.arena
7878
)
@@ -236,7 +236,7 @@ extension Parser {
236236
lastElement.unexpectedBeforeItem,
237237
item: .init(lastElement.item)!,
238238
lastElement.unexpectedBetweenItemAndSemicolon,
239-
semicolon: parser.missingToken(.semicolon, text: nil),
239+
semicolon: parser.missingToken(.semicolon),
240240
lastElement.unexpectedAfterSemicolon,
241241
arena: parser.arena
242242
)

Sources/SwiftParserDiagnostics/ParseDiagnosticsGenerator.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -776,6 +776,23 @@ public class ParseDiagnosticsGenerator: SyntaxAnyVisitor {
776776
if shouldSkip(node) {
777777
return .skipChildren
778778
}
779+
780+
if let unexpected = node.unexpectedBeforeEqual,
781+
unexpected.first?.as(TokenSyntax.self)?.tokenKind == .binaryOperator("==")
782+
{
783+
addDiagnostic(
784+
unexpected,
785+
.expectedAssignmentInsteadOfComparisonOperator,
786+
fixIts: [
787+
FixIt(
788+
message: ReplaceTokensFixIt(replaceTokens: [.binaryOperator("==")], replacement: node.equal),
789+
changes: [.makeMissing(unexpected), .makePresent(node.equal, leadingTrivia: [])]
790+
)
791+
],
792+
handledNodes: [unexpected.id, node.equal.id]
793+
)
794+
}
795+
779796
if node.equal.presence == .missing {
780797
exchangeTokens(
781798
unexpected: node.unexpectedBeforeEqual,

Sources/SwiftParserDiagnostics/ParserDiagnosticMessages.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,9 @@ extension DiagnosticMessage where Self == StaticParserError {
128128
public static var expectedExpressionAfterTry: Self {
129129
.init("expected expression after 'try'")
130130
}
131+
public static var expectedAssignmentInsteadOfComparisonOperator: Self {
132+
.init("expected '=' instead of '==' to assign default value for parameter")
133+
}
131134
public static var expectedLeftBraceOrIfAfterElse: Self {
132135
.init("expected '{' or 'if' after 'else'")
133136
}

Tests/SwiftParserTest/translated/RecoveryTests.swift

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2139,16 +2139,18 @@ final class RecoveryTests: XCTestCase {
21392139
}
21402140

21412141
func testRecovery176() {
2142+
// rdar://problem/22478168
2143+
// https://github.com/apple/swift/issues/53396
21422144
assertParse(
21432145
"""
2144-
// rdar://problem/22478168
2145-
// https://github.com/apple/swift/issues/53396
21462146
func f_53396(a: Int 1️⃣== 0) {}
21472147
""",
21482148
diagnostics: [
2149-
// TODO: Old parser expected error on line 3: expected '=' instead of '==' to assign default value for parameter, Fix-It replacements: 21 - 23 = '='
2150-
DiagnosticSpec(message: "unexpected code '== 0' in parameter clause")
2151-
]
2149+
DiagnosticSpec(message: "expected '=' instead of '==' to assign default value for parameter", fixIts: ["replace '==' with '='"])
2150+
],
2151+
fixedSource: """
2152+
func f_53396(a: Int = 0) {}
2153+
"""
21522154
)
21532155
}
21542156

0 commit comments

Comments
 (0)