Skip to content

Commit 2266578

Browse files
committed
Add diagnostic for equal with missing trailing or leading space
1 parent 7e099ed commit 2266578

File tree

6 files changed

+66
-11
lines changed

6 files changed

+66
-11
lines changed

Sources/SwiftParser/Lexer/Cursor.swift

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1967,7 +1967,23 @@ extension Lexer.Cursor {
19671967
if self.input.baseAddress! - tokStart.input.baseAddress! == 1 {
19681968
switch tokStart.peek() {
19691969
case UInt8(ascii: "="):
1970-
return Lexer.Result(.equal)
1970+
if leftBound != rightBound {
1971+
var errorPos = tokStart
1972+
1973+
if rightBound {
1974+
_ = errorPos.advance()
1975+
}
1976+
1977+
return Lexer.Result(
1978+
.equal,
1979+
error: LexingDiagnostic(
1980+
.equalMustHaveConsistentWhitespaceOnBothSides,
1981+
position: errorPos
1982+
)
1983+
)
1984+
} else {
1985+
return Lexer.Result(.equal)
1986+
}
19711987
case UInt8(ascii: "&"):
19721988
if leftBound == rightBound || leftBound {
19731989
break

Sources/SwiftParserDiagnostics/LexerDiagnosticMessages.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ public extension TokenError {
3939
/// Please order the cases in this enum alphabetically by case name.
4040
public enum StaticTokenError: String, DiagnosticMessage {
4141
case editorPlaceholder = "editor placeholder in source file"
42+
case equalMustHaveConsistentWhitespaceOnBothSides = "'=' must have consistent whitespace on both sides"
4243
case expectedBinaryExponentInHexFloatLiteral = "hexadecimal floating point literal must end with an exponent"
4344
case expectedClosingBraceInUnicodeEscape = #"expected '}' in \u{...} escape sequence"#
4445
case expectedDigitInFloatLiteral = "expected a digit in floating point exponent"
@@ -134,6 +135,7 @@ public extension SwiftSyntax.TokenDiagnostic {
134135

135136
switch self.kind {
136137
case .editorPlaceholder: return StaticTokenError.editorPlaceholder
138+
case .equalMustHaveConsistentWhitespaceOnBothSides: return StaticTokenError.equalMustHaveConsistentWhitespaceOnBothSides
137139
case .expectedBinaryExponentInHexFloatLiteral: return StaticTokenError.expectedBinaryExponentInHexFloatLiteral
138140
case .expectedClosingBraceInUnicodeEscape: return StaticTokenError.expectedClosingBraceInUnicodeEscape
139141
case .expectedDigitInFloatLiteral: return StaticTokenError.expectedDigitInFloatLiteral

Sources/SwiftParserDiagnostics/ParseDiagnosticsGenerator.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -771,6 +771,24 @@ public class ParseDiagnosticsGenerator: SyntaxAnyVisitor {
771771
if shouldSkip(node) {
772772
return .skipChildren
773773
}
774+
775+
if node.equal.hasError && node.equal.presence == .present {
776+
addDiagnostic(
777+
node.equal,
778+
StaticTokenError.equalMustHaveConsistentWhitespaceOnBothSides,
779+
fixIts: [
780+
FixIt(
781+
message: .insertWhitespace,
782+
changes: [
783+
FixIt.Changes(changes: [.replaceLeadingTrivia(token: node.equal, newTrivia: .spaces(1))]),
784+
FixIt.Changes(changes: [.replaceTrailingTrivia(token: node.equal, newTrivia: .spaces(1))]),
785+
]
786+
)
787+
],
788+
handledNodes: [node.equal.id]
789+
)
790+
}
791+
774792
if node.equal.presence == .missing {
775793
exchangeTokens(
776794
unexpected: node.unexpectedBeforeEqual,

Sources/SwiftParserDiagnostics/ParserDiagnosticMessages.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,9 @@ extension FixItMessage where Self == StaticParserFixIt {
498498
public static var insertNewline: Self {
499499
.init("insert newline")
500500
}
501+
public static var insertWhitespace: Self {
502+
.init("insert whitespace")
503+
}
501504
public static var joinIdentifiers: Self {
502505
.init("join the identifiers together")
503506
}

Sources/SwiftSyntax/TokenDiagnostic.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ public struct TokenDiagnostic: Hashable {
2323
// Please order these alphabetically
2424

2525
case editorPlaceholder
26+
case equalMustHaveConsistentWhitespaceOnBothSides
2627
case expectedBinaryExponentInHexFloatLiteral
2728
case expectedClosingBraceInUnicodeEscape
2829
case expectedDigitInFloatLiteral
@@ -96,6 +97,7 @@ public struct TokenDiagnostic: Hashable {
9697
public var severity: Severity {
9798
switch kind {
9899
case .editorPlaceholder: return .error
100+
case .equalMustHaveConsistentWhitespaceOnBothSides: return .error
99101
case .expectedBinaryExponentInHexFloatLiteral: return .error
100102
case .expectedClosingBraceInUnicodeEscape: return .error
101103
case .expectedDigitInFloatLiteral: return .error

Tests/SwiftParserTest/translated/RecoveryTests.swift

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1962,14 +1962,21 @@ final class RecoveryTests: XCTestCase {
19621962
"""
19631963
// <rdar://problem/22387625> QoI: Common errors: 'let x= 5' and 'let x =5' could use Fix-its
19641964
func r22387625() {
1965-
let _= 5
1966-
let _ =5
1965+
let _1️⃣= 5
1966+
let _ =2️⃣5
19671967
}
19681968
""",
19691969
diagnostics: [
1970-
// TODO: Old parser expected error on line 3: '=' must have consistent whitespace on both sides, Fix-It replacements: 8 - 8 = ' '
1971-
// TODO: Old parser expected error on line 4: '=' must have consistent whitespace on both sides, Fix-It replacements: 10 - 10 = ' '
1972-
]
1970+
DiagnosticSpec(locationMarker: "1️⃣", message: "'=' must have consistent whitespace on both sides"),
1971+
DiagnosticSpec(locationMarker: "2️⃣", message: "'=' must have consistent whitespace on both sides"),
1972+
],
1973+
fixedSource: """
1974+
// <rdar://problem/22387625> QoI: Common errors: 'let x= 5' and 'let x =5' could use Fix-its
1975+
func r22387625() {
1976+
let _ = 5
1977+
let _ = 5
1978+
}
1979+
"""
19731980
)
19741981
}
19751982

@@ -1978,14 +1985,21 @@ final class RecoveryTests: XCTestCase {
19781985
"""
19791986
// https://github.com/apple/swift/issues/45723
19801987
do {
1981-
let _: Int= 5
1982-
let _: Array<Int>= []
1988+
let _: Int1️⃣= 5
1989+
let _: Array<Int>2️⃣= []
19831990
}
19841991
""",
19851992
diagnostics: [
1986-
// TODO: Old parser expected error on line 3: '=' must have consistent whitespace on both sides, Fix-It replacements: 13 - 13 = ' '
1987-
// TODO: Old parser expected error on line 4: '=' must have consistent whitespace on both sides, Fix-It replacements: 20 - 20 = ' '
1988-
]
1993+
DiagnosticSpec(locationMarker: "1️⃣", message: "'=' must have consistent whitespace on both sides"),
1994+
DiagnosticSpec(locationMarker: "2️⃣", message: "'=' must have consistent whitespace on both sides"),
1995+
],
1996+
fixedSource: """
1997+
// https://github.com/apple/swift/issues/45723
1998+
do {
1999+
let _: Int = 5
2000+
let _: Array<Int> = []
2001+
}
2002+
"""
19892003
)
19902004
}
19912005

0 commit comments

Comments
 (0)