diff --git a/Sources/SwiftParser/Availability.swift b/Sources/SwiftParser/Availability.swift index a6d6be4ebe1..c329bfc2fd4 100644 --- a/Sources/SwiftParser/Availability.swift +++ b/Sources/SwiftParser/Availability.swift @@ -218,6 +218,13 @@ extension Parser { (unexpectedBeforePlatform, platform) = self.expect(.identifier) } + let unexpectedComparison: RawUnexpectedNodesSyntax? + if let greaterThanOrEqualTo = self.consumeIfContextualPunctuator(">=") { + unexpectedComparison = RawUnexpectedNodesSyntax([greaterThanOrEqualTo], arena: self.arena) + } else { + unexpectedComparison = nil + } + let version: RawVersionTupleSyntax? if self.at(.integerLiteral, .floatingLiteral) { version = self.parseVersionTuple() @@ -228,6 +235,7 @@ extension Parser { return RawAvailabilityVersionRestrictionSyntax( unexpectedBeforePlatform, platform: platform, + unexpectedComparison, version: version, arena: self.arena ) diff --git a/Sources/SwiftParserDiagnostics/ParseDiagnosticsGenerator.swift b/Sources/SwiftParserDiagnostics/ParseDiagnosticsGenerator.swift index 21f0e7ef28b..51b2fe1a966 100644 --- a/Sources/SwiftParserDiagnostics/ParseDiagnosticsGenerator.swift +++ b/Sources/SwiftParserDiagnostics/ParseDiagnosticsGenerator.swift @@ -440,6 +440,25 @@ public class ParseDiagnosticsGenerator: SyntaxAnyVisitor { return .visitChildren } + public override func visit(_ node: AvailabilityVersionRestrictionSyntax) -> SyntaxVisitorContinueKind { + if shouldSkip(node) { + return .skipChildren + } + if let unexpected = node.unexpectedBetweenPlatformAndVersion, + unexpected.onlyToken(where: { $0.tokenKind == .binaryOperator(">=") }) != nil + { + addDiagnostic( + unexpected, + .versionComparisonNotNeeded, + fixIts: [ + FixIt(message: RemoveNodesFixIt(unexpected), changes: .makeMissing(unexpected)) + ], + handledNodes: [unexpected.id] + ) + } + return .visitChildren + } + public override func visit(_ node: ConditionElementSyntax) -> SyntaxVisitorContinueKind { if shouldSkip(node) { return .skipChildren diff --git a/Sources/SwiftParserDiagnostics/ParserDiagnosticMessages.swift b/Sources/SwiftParserDiagnostics/ParserDiagnosticMessages.swift index d0907ca85da..9d8b7feb2f6 100644 --- a/Sources/SwiftParserDiagnostics/ParserDiagnosticMessages.swift +++ b/Sources/SwiftParserDiagnostics/ParserDiagnosticMessages.swift @@ -212,6 +212,9 @@ extension DiagnosticMessage where Self == StaticParserError { public static var unexpectedSemicolon: Self { .init("unexpected ';' separator") } + public static var versionComparisonNotNeeded: Self { + .init("version comparison not needed") + } } // MARK: - Diagnostics (please sort alphabetically) diff --git a/Tests/SwiftParserTest/translated/AvailabilityQueryTests.swift b/Tests/SwiftParserTest/translated/AvailabilityQueryTests.swift index f41f167346c..b7fc3aae8e2 100644 --- a/Tests/SwiftParserTest/translated/AvailabilityQueryTests.swift +++ b/Tests/SwiftParserTest/translated/AvailabilityQueryTests.swift @@ -407,9 +407,12 @@ final class AvailabilityQueryTests: XCTestCase { } """, diagnostics: [ - // TODO: (good first issue) Old parser expected error on line 1: version comparison not needed, Fix-It replacements: 19 - 22 = '' - DiagnosticSpec(message: "unexpected code '>= 10.51, *' in availability condition") - ] + DiagnosticSpec(message: "version comparison not needed", fixIts: ["remove '>='"]) + ], + fixedSource: """ + if #available(OSX 10.51, *) { + } + """ ) } diff --git a/Tests/SwiftParserTest/translated/AvailabilityQueryUnavailabilityTests.swift b/Tests/SwiftParserTest/translated/AvailabilityQueryUnavailabilityTests.swift index 8cfe667e8c8..00421bd65fb 100644 --- a/Tests/SwiftParserTest/translated/AvailabilityQueryUnavailabilityTests.swift +++ b/Tests/SwiftParserTest/translated/AvailabilityQueryUnavailabilityTests.swift @@ -365,8 +365,7 @@ final class AvailabilityQueryUnavailabilityTests: XCTestCase { } """, diagnostics: [ - // TODO: (good first issue) Old parser expected error on line 2: version comparison not needed, Fix-It replacements: 21 - 24 = '' - DiagnosticSpec(message: "unexpected code '>= 10.51' in availability condition") + DiagnosticSpec(message: "version comparison not needed", fixIts: ["remove '>='"]) ] ) }