From 192d7afc4bf6458b1c7fbf5893b0469aa321f078 Mon Sep 17 00:00:00 2001 From: TTOzzi Date: Thu, 18 May 2023 22:52:28 +0900 Subject: [PATCH 1/6] Fix diagnostic of ternary operator missing only colon --- Sources/SwiftParser/Expressions.swift | 6 ++---- .../translated/InvalidIfExprTests.swift | 11 +++++++++++ 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/Sources/SwiftParser/Expressions.swift b/Sources/SwiftParser/Expressions.swift index e9332141879..d978c6c3a0d 100644 --- a/Sources/SwiftParser/Expressions.swift +++ b/Sources/SwiftParser/Expressions.swift @@ -318,10 +318,8 @@ extension Parser { ) let rhs: RawExprSyntax? - if colon.isMissing { - // If the colon is missing there's not much more structure we can - // expect out of this expression sequence. Emit a missing expression - // to end the parsing here. + if colon.isMissing, + currentToken.rawTokenKind != currentToken.cursor.previousTokenKind { rhs = RawExprSyntax(RawMissingExprSyntax(arena: self.arena)) } else { rhs = nil diff --git a/Tests/SwiftParserTest/translated/InvalidIfExprTests.swift b/Tests/SwiftParserTest/translated/InvalidIfExprTests.swift index bc9acf35685..cb721900ab7 100644 --- a/Tests/SwiftParserTest/translated/InvalidIfExprTests.swift +++ b/Tests/SwiftParserTest/translated/InvalidIfExprTests.swift @@ -69,4 +69,15 @@ final class InvalidIfExprTests: XCTestCase { ) } + func testInvalidIfExpr5() { + assertParse( + """ + foo ? 1 1️⃣2 + """, + diagnostics: [ + DiagnosticSpec(message: "expected ':' after '? ...' in ternary expression", fixIts: ["insert ':'"]) + ], + fixedSource: "foo ? 1 : 2" + ) + } } From b769363d1b8f5c61805ef9a93ea28bb8e0b929f1 Mon Sep 17 00:00:00 2001 From: TTOzzi Date: Thu, 18 May 2023 22:59:34 +0900 Subject: [PATCH 2/6] Modify tokenKind comparison logic to use "at" function --- Sources/SwiftParser/Expressions.swift | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Sources/SwiftParser/Expressions.swift b/Sources/SwiftParser/Expressions.swift index d978c6c3a0d..0dab54d6a87 100644 --- a/Sources/SwiftParser/Expressions.swift +++ b/Sources/SwiftParser/Expressions.swift @@ -318,9 +318,13 @@ extension Parser { ) let rhs: RawExprSyntax? - if colon.isMissing, - currentToken.rawTokenKind != currentToken.cursor.previousTokenKind { - rhs = RawExprSyntax(RawMissingExprSyntax(arena: self.arena)) + if colon.isMissing { + if let previousTokenKind = currentToken.cursor.previousTokenKind, + self.at(TokenSpec(previousTokenKind)) { + rhs = nil + } else { + rhs = RawExprSyntax(RawMissingExprSyntax(arena: self.arena)) + } } else { rhs = nil } From 24f4274daf0ece95bc938632d48f8f2496c73734 Mon Sep 17 00:00:00 2001 From: TTOzzi Date: Thu, 18 May 2023 23:01:13 +0900 Subject: [PATCH 3/6] Formatting --- Sources/SwiftParser/Expressions.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Sources/SwiftParser/Expressions.swift b/Sources/SwiftParser/Expressions.swift index 0dab54d6a87..d60741fbe02 100644 --- a/Sources/SwiftParser/Expressions.swift +++ b/Sources/SwiftParser/Expressions.swift @@ -320,7 +320,8 @@ extension Parser { let rhs: RawExprSyntax? if colon.isMissing { if let previousTokenKind = currentToken.cursor.previousTokenKind, - self.at(TokenSpec(previousTokenKind)) { + self.at(TokenSpec(previousTokenKind)) + { rhs = nil } else { rhs = RawExprSyntax(RawMissingExprSyntax(arena: self.arena)) From 91843786f3570a5b75cdfcd9526c28b0b35e258c Mon Sep 17 00:00:00 2001 From: TTOzzi Date: Sat, 20 May 2023 14:24:47 +0900 Subject: [PATCH 4/6] Remove check logic for expressions after a colon from ternary operators --- Sources/SwiftParser/Expressions.swift | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/Sources/SwiftParser/Expressions.swift b/Sources/SwiftParser/Expressions.swift index d60741fbe02..4a11add9f8f 100644 --- a/Sources/SwiftParser/Expressions.swift +++ b/Sources/SwiftParser/Expressions.swift @@ -317,19 +317,7 @@ extension Parser { arena: self.arena ) - let rhs: RawExprSyntax? - if colon.isMissing { - if let previousTokenKind = currentToken.cursor.previousTokenKind, - self.at(TokenSpec(previousTokenKind)) - { - rhs = nil - } else { - rhs = RawExprSyntax(RawMissingExprSyntax(arena: self.arena)) - } - } else { - rhs = nil - } - return (RawExprSyntax(op), rhs) + return (RawExprSyntax(op), nil) case (.equal, let handle)?: switch pattern { From f302ac97372d0f439e1f0475e84779700ba03b10 Mon Sep 17 00:00:00 2001 From: TTOzzi Date: Sat, 20 May 2023 14:25:40 +0900 Subject: [PATCH 5/6] Added test case for missing both colon and rhs expression in ternary operator --- .../translated/InvalidIfExprTests.swift | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Tests/SwiftParserTest/translated/InvalidIfExprTests.swift b/Tests/SwiftParserTest/translated/InvalidIfExprTests.swift index cb721900ab7..bf86a6e1b6f 100644 --- a/Tests/SwiftParserTest/translated/InvalidIfExprTests.swift +++ b/Tests/SwiftParserTest/translated/InvalidIfExprTests.swift @@ -80,4 +80,16 @@ final class InvalidIfExprTests: XCTestCase { fixedSource: "foo ? 1 : 2" ) } + + func testInvalidIfExpr6() { + assertParse( + """ + foo ? 1 1️⃣ + """, + diagnostics: [ + DiagnosticSpec(message: "expected ':' and expression after '? ...' in ternary expression", fixIts: ["insert ':' and expression"]) + ], + fixedSource: "foo ? 1 : <#expression#>" + ) + } } From 9bf8ff2a7775adc6b7b244ea95e2cab06d7ac758 Mon Sep 17 00:00:00 2001 From: TTOzzi Date: Sun, 21 May 2023 00:08:26 +0900 Subject: [PATCH 6/6] Add logic to check if the next token starts on a new line when there is no colon --- Sources/SwiftParser/Expressions.swift | 8 +++++++- .../translated/InvalidIfExprTests.swift | 16 ++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/Sources/SwiftParser/Expressions.swift b/Sources/SwiftParser/Expressions.swift index 4a11add9f8f..b4205e88327 100644 --- a/Sources/SwiftParser/Expressions.swift +++ b/Sources/SwiftParser/Expressions.swift @@ -317,7 +317,13 @@ extension Parser { arena: self.arena ) - return (RawExprSyntax(op), nil) + let rhs: RawExprSyntax? + if colon.isMissing, currentToken.isAtStartOfLine { + rhs = RawExprSyntax(RawMissingExprSyntax(arena: self.arena)) + } else { + rhs = nil + } + return (RawExprSyntax(op), rhs) case (.equal, let handle)?: switch pattern { diff --git a/Tests/SwiftParserTest/translated/InvalidIfExprTests.swift b/Tests/SwiftParserTest/translated/InvalidIfExprTests.swift index bf86a6e1b6f..80cc943f4ec 100644 --- a/Tests/SwiftParserTest/translated/InvalidIfExprTests.swift +++ b/Tests/SwiftParserTest/translated/InvalidIfExprTests.swift @@ -92,4 +92,20 @@ final class InvalidIfExprTests: XCTestCase { fixedSource: "foo ? 1 : <#expression#>" ) } + + func testInvalidIfExpr7() { + assertParse( + """ + condition ? 1 1️⃣ + someOtherVariable + """, + diagnostics: [ + DiagnosticSpec(message: "expected ':' and expression after '? ...' in ternary expression", fixIts: ["insert ':' and expression"]) + ], + fixedSource: """ + condition ? 1 : <#expression#> + someOtherVariable + """ + ) + } }