Repository: scalameta/scalameta (scala)

Issue:
Type apply after block fails to parse
The following snippet is valid in Scala 3:

```Scala
def fn[A](a: A) = ???
{
  [B] => (c: B) => fn[B](c)
}[Int](0)
```

Scalameta parser fails to parse it with:
```
`;` expected but `[` found
```

Pull request:
Follow-on to #3728. Fixes #3731.

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 d557e89517..ca9296d276 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
@@ -2127,16 +2127,20 @@ class ScalametaParser(input: Input)(implicit dialect: Dialect) {
           newLineOptWhenFollowedBy[Dot]
           simpleExprRest(clause, canApply = false, startPos = startPos)
         } else simpleExprRest(selector(t, startPos), canApply = true, startPos = startPos)
-      case _: LeftBracket => t match {
+      case _: LeftBracket =>
+        @tailrec
+        def isOk(tree: Tree): Boolean = tree match {
           case _: Quasi | _: Term.Name | _: Term.Select | _: Term.Apply | _: Term.ApplyInfix |
               _: Term.ApplyUnary | _: Term.New | _: Term.Placeholder | _: Term.ApplyUsing |
-              _: Term.Interpolate | _: Term.SplicedMacroExpr =>
-            var app: Term = t
-            while (token.is[LeftBracket]) app = addPos(Term.ApplyType(app, exprTypeArgs()))
-
-            simpleExprRest(app, canApply = true, startPos = startPos)
-          case _ => addPos(t)
+              _: Term.Interpolate | _: Term.SplicedMacroExpr | _: Term.PolyFunction => true
+          case Term.Block(t :: Nil) => isOk(t)
+          case _ => false
         }
+        if (isOk(t)) {
+          var app: Term = t
+          while (token.is[LeftBracket]) app = addPos(Term.ApplyType(app, exprTypeArgs()))
+          simpleExprRest(app, canApply = true, startPos = startPos)
+        } else addPos(t)
       case tok @ (_: LeftParen | _: LeftBrace) if canApply =>
         def argClause = if (tok.is[LeftBrace]) getArgClauseOnBrace() else getArgClauseOnParen()
         val arguments = addPos(Term.Apply(t, argClause))


Test patch:
diff --git a/tests/jvm/src/test/scala/scala/meta/tests/semanticdb/MetacScalaLibrary.scala b/tests/jvm/src/test/scala/scala/meta/tests/semanticdb/MetacScalaLibrary.scala
index 57ff095492..86fc1d1b6b 100644
--- a/tests/jvm/src/test/scala/scala/meta/tests/semanticdb/MetacScalaLibrary.scala
+++ b/tests/jvm/src/test/scala/scala/meta/tests/semanticdb/MetacScalaLibrary.scala
@@ -13,9 +13,14 @@ import java.net.URLClassLoader
 import java.nio.file.Files
 import java.nio.file.Paths
 
+import scala.concurrent.duration
+
 import munit.FunSuite
 
 class MetacScalaLibrary extends FunSuite {
+
+  override val munitTimeout = new duration.FiniteDuration(3, duration.MINUTES)
+
   test("compile scala-library".tag(Slow).tag(SkipWindows)) {
     val exit = MetacScalaLibrary.process(Array())
     require(exit == 0, "failed to compile scala-library")
diff --git a/tests/shared/src/test/scala/scala/meta/tests/parsers/dotty/MacroSuite.scala b/tests/shared/src/test/scala/scala/meta/tests/parsers/dotty/MacroSuite.scala
index c887c093d9..18332be959 100644
--- a/tests/shared/src/test/scala/scala/meta/tests/parsers/dotty/MacroSuite.scala
+++ b/tests/shared/src/test/scala/scala/meta/tests/parsers/dotty/MacroSuite.scala
@@ -315,12 +315,63 @@ class MacroSuite extends BaseDottySuite {
     runTestAssert[Stat](code)(tree)
   }
 
-  test("#6483-metals") {
+  test("#6483-metals splice") {
     val code = "${ fn }[Int](0)"
+    val codeInParens = "( ${ fn } )[Int](0)"
+    val tree = Term
+      .Apply(Term.ApplyType(Term.SplicedMacroExpr(blk(tname("fn"))), List(pname("Int"))), List(lit(0)))
+    runTestAssert[Stat](code)(tree)
+    runTestAssert[Stat](codeInParens, code)(tree)
+  }
+
+  test("#6483-metals splice in braces") {
+    val code = """|{
+                  |  ${ fn }
+                  |}[Int](0)""".stripMargin
+    val tree = Term.Apply(
+      Term.ApplyType(blk(Term.SplicedMacroExpr(blk(tname("fn")))), List(pname("Int"))),
+      List(lit(0))
+    )
+    runTestAssert[Stat](code)(tree)
+  }
+
+  test("#6483-metals poly in parens") {
+    val code = "([B] => (c: B) => fn[B](c))[Int](0)"
     val tree = Term.Apply(
-      Term.ApplyType(Term.SplicedMacroExpr(blk(tname("fn"))), List(Type.Name("Int"))),
+      Term.ApplyType(
+        Term.PolyFunction(
+          List(pparam("B")),
+          Term.Function(
+            List(tparam("c", "B")),
+            Term.Apply(Term.ApplyType(tname("fn"), List(pname("B"))), List(tname("c")))
+          )
+        ),
+        List(pname("Int"))
+      ),
       List(lit(0))
     )
     runTestAssert[Stat](code)(tree)
   }
+
+  test("#6483-metals poly in braces") {
+    val code = """|{
+                  |  [B] => (c: B) => fn[B](c)
+                  |}[Int](0)
+                  |""".stripMargin
+    val tree = Term.Apply(
+      Term.ApplyType(
+        blk(Term.PolyFunction(
+          List(pparam("B")),
+          Term.Function(
+            List(tparam("c", "B")),
+            Term.Apply(Term.ApplyType(tname("fn"), List(pname("B"))), List(tname("c")))
+          )
+        )),
+        List(pname("Int"))
+      ),
+      List(lit(0))
+    )
+    runTestAssert[Stat](code)(tree)
+  }
+
 }