Repository: scalameta/scalameta
Pull request #4035 (2024-11-17 08:27:31)

ScannerTokens: drop region line after match


Patch:
diff --git a/scalameta/parsers/shared/src/main/scala/scala/meta/internal/parsers/ScannerTokens.scala b/scalameta/parsers/shared/src/main/scala/scala/meta/internal/parsers/ScannerTokens.scala
index 6414a422a..6732d3e22 100644
--- a/scalameta/parsers/shared/src/main/scala/scala/meta/internal/parsers/ScannerTokens.scala
+++ b/scalameta/parsers/shared/src/main/scala/scala/meta/internal/parsers/ScannerTokens.scala
@@ -740,7 +740,7 @@ final class ScannerTokens(val tokens: Tokens)(implicit dialect: Dialect) {
               if (nextIndent > r.indent) null
               else if (next.is[KwFinally]) OutdentInfo(r, rs, noOutdent(rs))
               else if (nextIndent < r.indent || rc.arrow.ne(prev) && (!next.is[KwCase]) ||
-                getNextToken(nextPos).isClassOrObject) OutdentInfo(r, rs)
+                getNextToken(nextPos).isClassOrObject) OutdentInfo(r, dropRegionLine(nextIndent, rs))
               else null
             case (r: RegionIndent) :: (rs @ RegionTry :: xs) =>
               if (nextIndent < r.indent || nextIndent == r.indent && next.isAny[KwCatch, KwFinally]) {
@@ -887,11 +887,10 @@ final class ScannerTokens(val tokens: Tokens)(implicit dialect: Dialect) {
               case (r: RegionControl) :: rs
                   if !r.isControlKeyword(prev) && r.isNotTerminatingTokenIfOptional(next) =>
                 r match {
-                  case rc: RegionControlMaybeCond if prev.is[RightParen] =>
+                  case r: RegionControlMaybeCond if prev.is[RightParen] =>
                     if (next.is[Dot]) None
-                    else rc.asBody() match {
-                      case Some(body) => getIfCanProduceLF(body :: rs, nextIndent)
-                          .orElse(onlyWithoutLF())
+                    else r.asBody() match {
+                      case Some(x) => getIfCanProduceLF(x :: rs, nextIndent).orElse(onlyWithoutLF())
                       case None => iter(rs)
                     }
                   case _ => iter(rs)
@@ -990,6 +989,13 @@ object ScannerTokens {
     case _ => regions
   }
 
+  @tailrec
+  private def dropRegionLine(indent: Int, regions: List[SepRegion]): List[SepRegion] =
+    regions match {
+      case (r: RegionLine) :: rs if r.indent >= indent => dropRegionLine(indent, rs)
+      case _ => regions
+    }
+
   private def findIndent(sepRegions: List[SepRegion]): Int = sepRegions.find(_.indent >= 0)
     .fold(0)(_.indent)
 


Test patch:
diff --git a/tests/shared/src/test/scala/scala/meta/tests/parsers/dotty/SignificantIndentationSuite.scala b/tests/shared/src/test/scala/scala/meta/tests/parsers/dotty/SignificantIndentationSuite.scala
index d45d3cd5b..f761b1a26 100644
--- a/tests/shared/src/test/scala/scala/meta/tests/parsers/dotty/SignificantIndentationSuite.scala
+++ b/tests/shared/src/test/scala/scala/meta/tests/parsers/dotty/SignificantIndentationSuite.scala
@@ -3092,4 +3092,41 @@ class SignificantIndentationSuite extends BaseDottySuite {
     runTestAssert[Stat](code, layout)(tree)
   }
 
+  test("case at same indent as line containing match, then template") {
+    val code = """|object Definitions:
+                  |  def foo = bar
+                  |    .baz match
+                  |    case none => false
+                  |
+                  |  class Qux:
+                  |    self =>
+                  |  end Qux
+                  |""".stripMargin
+    val layout = """|object Definitions {
+                    |  def foo = bar.baz match {
+                    |    case none => false
+                    |  }
+                    |  class Qux { self => }
+                    |  end Qux
+                    |}
+                    |""".stripMargin
+    val tree = Defn.Object(
+      Nil,
+      "Definitions",
+      tpl(
+        Defn.Def(
+          Nil,
+          "foo",
+          Nil,
+          Nil,
+          None,
+          Term.Match(Term.Select("bar", "baz"), List(Case(Pat.Var("none"), None, lit(false))), Nil)
+        ),
+        Defn.Class(Nil, pname("Qux"), Nil, ctor, tpl(Nil, tplBody("self"))),
+        Term.EndMarker("Qux")
+      )
+    )
+    runTestAssert[Stat](code, layout)(tree)
+  }
+
 }