Skip to content

Add missing comma diagnostic if it's inside an array or dictionary #2257

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 6, 2023

Conversation

kimdv
Copy link
Contributor

@kimdv kimdv commented Oct 3, 2023

Fixes #2255

@kimdv kimdv requested review from ahoppen and bnbarham as code owners October 3, 2023 19:12
@kimdv
Copy link
Contributor Author

kimdv commented Oct 3, 2023

It also says there is an error in

    assertParse(
      "[() try await(MyError) -> Void]()",
      experimentalFeatures: .typedThrows
    )

Not sure if that is true or not

@kimdv kimdv self-assigned this Oct 3, 2023
@ahoppen
Copy link
Member

ahoppen commented Oct 4, 2023

I’m a little worried about the fact that this duplicates the logic of whether we should continue parsing, once for deciding whether to synthesize a comma and then whether to break a loop. We should decide whether to continue parsing another element based on whether we parsed/synthesized a comma.

Something like

Diff

diff --git a/Sources/SwiftParser/Expressions.swift b/Sources/SwiftParser/Expressions.swift
index 0eef0bdd..2b43aebe 100644
--- a/Sources/SwiftParser/Expressions.swift
+++ b/Sources/SwiftParser/Expressions.swift
@@ -1497,33 +1497,36 @@ extension Parser {
     var elements = [RawSyntax]()
     do {
       var collectionProgress = LoopProgressCondition()
-      COLLECTION_LOOP: while self.hasProgressed(&collectionProgress) {
+      var keepGoing: RawTokenSyntax?
+      COLLECTION_LOOP: repeat {
         elementKind = self.parseCollectionElement(elementKind)
 
-        var hasElementKindError: Bool {
+        /// Whether expression of an array element or the value of a dictionary
+        /// element is missing. If this is the case, we shouldn't recover from
+        /// a missing comma since most likely the closing `]` is missing.
+        var elementIsMissingExpression: Bool {
           switch elementKind! {
-          case .dictionary(let key, _, let colon, let value):
-            return key.hasError || colon.hasError || value.hasError
+          case .dictionary(_, _, _, let value):
+            return value.is(RawMissingExprSyntax.self)
           case .array(let rawExprSyntax):
-            return rawExprSyntax.hasError
+            return rawExprSyntax.is(RawMissingExprSyntax.self)
           }
         }
 
         // Parse the ',' if exists.
-        let comma: Token?
         if let token = self.consume(if: .comma) {
-          comma = token
-        } else if !self.atStartOfLine, !self.at(.rightSquare, .endOfFile), !hasElementKindError {
-          comma = missingToken(.comma)
+          keepGoing = token
+        } else if !self.at(.rightSquare, .endOfFile) && !self.atStartOfLine && !elementIsMissingExpression && !self.atStartOfDeclaration() && !self.atStartOfStatement(preferExpr: false) {
+          keepGoing = missingToken(.comma)
         } else {
-          comma = nil
+          keepGoing = nil
         }
 
         switch elementKind! {
         case .array(let el):
           let element = RawArrayElementSyntax(
             expression: el,
-            trailingComma: comma,
+            trailingComma: keepGoing,
             arena: self.arena
           )
           if element.isEmpty {
@@ -1537,7 +1540,7 @@ extension Parser {
             unexpectedBeforeColon,
             colon: colon,
             value: value,
-            trailingComma: comma,
+            trailingComma: keepGoing,
             arena: self.arena
           )
           if element.isEmpty {
@@ -1546,29 +1549,7 @@ extension Parser {
             elements.append(RawSyntax(element))
           }
         }
-
-        // If we saw a comma, that's a strong indicator we have more elements
-        // to process. If that's not the case, we have to do some legwork to
-        // determine if we should bail out.
-        guard comma == nil || self.at(.rightSquare, .endOfFile) else {
-          continue
-        }
-
-        // If we found EOF or the closing square bracket, bailout.
-        if self.at(.rightSquare, .endOfFile) {
-          break
-        }
-
-        // If the next token is at the beginning of a new line and can never start
-        // an element, break.
-        if self.atStartOfLine
-          && (self.at(.rightBrace, .poundEndif)
-            || self.atStartOfDeclaration()
-            || self.atStartOfStatement(preferExpr: false))
-        {
-          break
-        }
-      }
+      } while keepGoing != nil && self.hasProgressed(&collectionProgress)
     }
 
     let (unexpectedBeforeRSquare, rsquare) = self.expect(.rightSquare)

@ahoppen
Copy link
Member

ahoppen commented Oct 4, 2023

It also says there is an error in

    assertParse(
      "[() try await(MyError) -> Void]()",
      experimentalFeatures: .typedThrows
    )

Not sure if that is true or not

Yes, that expression absolutely has an error.

@kimdv kimdv force-pushed the task/add-missing-comma branch from 1c89f84 to 9a2da83 Compare October 5, 2023 17:58
@kimdv
Copy link
Contributor Author

kimdv commented Oct 5, 2023

I’m a little worried about the fact that this duplicates the logic of whether we should continue parsing, once for deciding whether to synthesize a comma and then whether to break a loop. We should decide whether to continue parsing another element based on whether we parsed/synthesized a comma.

Something like

Diff

Thanks!
I think you can take a look again

Copy link
Member

@ahoppen ahoppen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool. LGTM.

@ahoppen
Copy link
Member

ahoppen commented Oct 5, 2023

@swift-ci Please test

@ahoppen
Copy link
Member

ahoppen commented Oct 5, 2023

@swift-ci Please test Windows

@kimdv kimdv merged commit 7a643a7 into swiftlang:main Oct 6, 2023
@kimdv kimdv deleted the task/add-missing-comma branch October 6, 2023 05:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

SwiftParser accepts array literals where elements aren’t separated by commas
2 participants