Skip to content

Commit ea628d7

Browse files
committed
Fix wrong diagnostic for generics
1 parent 6134c24 commit ea628d7

File tree

3 files changed

+53
-3
lines changed

3 files changed

+53
-3
lines changed

Sources/SwiftParser/Declarations.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -465,7 +465,7 @@ extension Parser {
465465
}
466466

467467
precondition(self.currentToken.starts(with: "<"))
468-
let langle = self.consumeAnyToken(remapping: .leftAngle)
468+
let langle = self.consumeStartingCharacterOfCurrentToken(as: .leftAngle)
469469
var elements = [RawGenericParameterSyntax]()
470470
do {
471471
var keepGoing: RawTokenSyntax? = nil
@@ -477,7 +477,7 @@ extension Parser {
477477
var each = self.consume(if: .keyword(.each))
478478

479479
let (unexpectedBetweenEachAndName, name) = self.expectIdentifier(allowSelfOrCapitalSelfAsIdentifier: true)
480-
if attributes == nil && each == nil && unexpectedBetweenEachAndName == nil && name.isMissing && elements.isEmpty {
480+
if attributes == nil && each == nil && unexpectedBetweenEachAndName == nil && name.isMissing && elements.isEmpty && !self.currentToken.starts(with: ">") {
481481
break
482482
}
483483

Sources/SwiftParser/Parser.swift

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -557,6 +557,37 @@ extension Parser {
557557
)
558558
return tok
559559
}
560+
561+
/// Consumes a single token and advances the current token by 1.
562+
mutating func consumeStartingCharacterOfCurrentToken(
563+
as tokenKind: RawTokenKind
564+
) -> RawTokenSyntax {
565+
let current = self.currentToken
566+
567+
let endIndex = current.textRange.lowerBound.advanced(by: 1)
568+
var tokenDiagnostic = current.diagnostic
569+
if let error = tokenDiagnostic, error.byteOffset > current.leadingTriviaByteLength + 1 {
570+
// The lexer error isn't in the prefix. Drop it.
571+
tokenDiagnostic = nil
572+
}
573+
574+
let tok = RawTokenSyntax(
575+
kind: tokenKind,
576+
wholeText: SyntaxText(rebasing: current.wholeText[..<endIndex]),
577+
textRange: current.textRange.lowerBound..<endIndex,
578+
presence: .present,
579+
tokenDiagnostic: tokenDiagnostic,
580+
arena: self.arena
581+
)
582+
583+
self.adjustNestingLevel(for: tokenKind)
584+
585+
self.currentToken = self.lexemes.resetForSplit(
586+
splitToken: self.currentToken,
587+
consumedPrefix: self.currentToken.leadingTriviaByteLength + 1
588+
)
589+
return tok
590+
}
560591
}
561592

562593
extension SyntaxText {

Tests/SwiftParserTest/translated/RecoveryTests.swift

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1031,7 +1031,7 @@ final class RecoveryTests: XCTestCase {
10311031
assertParse(
10321032
"""
10331033
// Note: Don't move braces to a different line here.
1034-
struct ErrorGenericParameterList4< 1️⃣
1034+
struct ErrorGenericParameterList4<1️⃣
10351035
{
10361036
}
10371037
""",
@@ -2245,4 +2245,23 @@ final class RecoveryTests: XCTestCase {
22452245
)
22462246
}
22472247

2248+
// https://github.com/apple/swift-syntax/issues/1483
2249+
func testRecovery183() {
2250+
// Can be parsed and produces no diagnostics.
2251+
assertParse(
2252+
"func f<1️⃣ >() {}",
2253+
diagnostics: [
2254+
DiagnosticSpec(message: "expected generic parameter in generic parameter clause")
2255+
]
2256+
)
2257+
2258+
// Can be parsed. Printing the node or asking for the diagnostics leads to a crash.
2259+
assertParse(
2260+
"func f<1️⃣>() {}",
2261+
diagnostics: [
2262+
DiagnosticSpec(message: "expected generic parameter in generic parameter clause")
2263+
]
2264+
)
2265+
}
2266+
22482267
}

0 commit comments

Comments
 (0)