Repository: scalameta/scalameta
Pull request #2680 (2022-03-16 15:42:39)

ScalametaParser: recognize Pat.Tuple as infix rhs


Patch:
diff --git a/scalameta/parsers/shared/src/main/scala/scala/meta/internal/parsers/ScalametaParser.scala b/scalameta/parsers/shared/src/main/scala/scala/meta/internal/parsers/ScalametaParser.scala
index 540d7fac9..bd59210e9 100644
--- a/scalameta/parsers/shared/src/main/scala/scala/meta/internal/parsers/ScalametaParser.scala
+++ b/scalameta/parsers/shared/src/main/scala/scala/meta/internal/parsers/ScalametaParser.scala
@@ -2521,7 +2521,7 @@ class ScalametaParser(input: Input)(implicit dialect: Dialect) { parser =>
             if (token.is[LeftBracket])
               syntaxError("infix patterns cannot have type arguments", at = token)
             ctx.push(ctx.UnfinishedInfix(lhs1, op))
-            val rhs1 = simplePattern(badPattern3)
+            val rhs1 = simplePattern(badPattern3, isRhs = true)
             loop(rhs1)
           case None =>
             lhs1
@@ -2556,7 +2556,7 @@ class ScalametaParser(input: Input)(implicit dialect: Dialect) { parser =>
     def simplePattern(): Pat =
       // simple diagnostics for this entry point
       simplePattern(token => syntaxError("illegal start of simple pattern", at = token))
-    def simplePattern(onError: Token => Nothing): Pat =
+    def simplePattern(onError: Token => Nothing, isRhs: Boolean = false): Pat =
       autoPos(token match {
         case _: Ident | _: KwThis | _: Unquote =>
           val isBackquoted = parser.isBackquoted
@@ -2611,7 +2611,13 @@ class ScalametaParser(input: Input)(implicit dialect: Dialect) { parser =>
           xmlPat()
         case _: LeftParen =>
           val patterns = inParensOnOpen(if (token.is[RightParen]) Nil else noSeq.patterns())
-          makeTuple(checkNoTripleDots(patterns), Lit.Unit(), Pat.Tuple.apply)
+          patterns match {
+            case (t: Pat.Tuple) :: Nil
+                if isRhs && t.endTokenPos != in.prevTokenPos && t.args.lengthCompare(1) != 0 =>
+              Pat.Tuple(t :: Nil)
+            case _ =>
+              makeTuple(checkNoTripleDots(patterns), Lit.Unit(), Pat.Tuple.apply)
+          }
         case _: MacroQuote =>
           QuotedPatternContext.within {
             Pat.Macro(macroQuote())


Test patch:
diff --git a/tests/shared/src/test/scala/scala/meta/tests/parsers/PatSuite.scala b/tests/shared/src/test/scala/scala/meta/tests/parsers/PatSuite.scala
index 899689cb1..d4d27bdd1 100644
--- a/tests/shared/src/test/scala/scala/meta/tests/parsers/PatSuite.scala
+++ b/tests/shared/src/test/scala/scala/meta/tests/parsers/PatSuite.scala
@@ -210,4 +210,36 @@ class PatSuite extends ParseSuite {
       pat("<a>{ns @ _*}</a>")
   }
 
+  test("(A, B, C)") {
+    assertPat("(A, B, C)") {
+      Pat.Tuple(List(Term.Name("A"), Term.Name("B"), Term.Name("C")))
+    }
+  }
+
+  test("((A, B, C))") {
+    assertPat("((A, B, C))") {
+      Pat.Tuple(List(Term.Name("A"), Term.Name("B"), Term.Name("C")))
+    }
+  }
+
+  test("(A, B, C) :: ((A, B, C))") {
+    assertPat("(A, B, C) :: ((A, B, C))") {
+      Pat.ExtractInfix(
+        Pat.Tuple(List(Term.Name("A"), Term.Name("B"), Term.Name("C"))),
+        Term.Name("::"),
+        List(Pat.Tuple(List(Term.Name("A"), Term.Name("B"), Term.Name("C"))))
+      )
+    }
+  }
+
+  test("((A, B, C)) :: ((A, B, C))") {
+    assertPat("((A, B, C)) :: ((A, B, C))") {
+      Pat.ExtractInfix(
+        Pat.Tuple(List(Term.Name("A"), Term.Name("B"), Term.Name("C"))),
+        Term.Name("::"),
+        List(Pat.Tuple(List(Term.Name("A"), Term.Name("B"), Term.Name("C"))))
+      )
+    }
+  }
+
 }
diff --git a/tests/shared/src/test/scala/scala/meta/tests/parsers/TermSuite.scala b/tests/shared/src/test/scala/scala/meta/tests/parsers/TermSuite.scala
index dfb5d8c70..414993c96 100644
--- a/tests/shared/src/test/scala/scala/meta/tests/parsers/TermSuite.scala
+++ b/tests/shared/src/test/scala/scala/meta/tests/parsers/TermSuite.scala
@@ -1293,4 +1293,38 @@ class TermSuite extends ParseSuite {
     )
   }
 
+  test("(a, b, c)") {
+    assertTerm("(a, b, c)") {
+      Term.Tuple(List(Term.Name("a"), Term.Name("b"), Term.Name("c")))
+    }
+  }
+
+  test("((a, b, c))") {
+    assertTerm("((a, b, c))") {
+      Term.Tuple(List(Term.Name("a"), Term.Name("b"), Term.Name("c")))
+    }
+  }
+
+  test("(a, b, c) :: ((a, b, c))") {
+    assertTerm("(a, b, c) :: ((a, b, c))") {
+      Term.ApplyInfix(
+        Term.Tuple(List(Term.Name("a"), Term.Name("b"), Term.Name("c"))),
+        Term.Name("::"),
+        Nil,
+        List(Term.Tuple(List(Term.Name("a"), Term.Name("b"), Term.Name("c"))))
+      )
+    }
+  }
+
+  test("((a, b, c)) :: ((a, b, c))") {
+    assertTerm("((a, b, c)) :: ((a, b, c))") {
+      Term.ApplyInfix(
+        Term.Tuple(List(Term.Name("a"), Term.Name("b"), Term.Name("c"))),
+        Term.Name("::"),
+        Nil,
+        List(Term.Tuple(List(Term.Name("a"), Term.Name("b"), Term.Name("c"))))
+      )
+    }
+  }
+
 }