Repository: scalameta/scalameta
Pull request #2507 (2021-11-15 16:38:18)

Don't allow indentation on `=>` in enums
Fixes https://github.com/scalameta/scalameta/issues/2505

PReviously, we would try to undo the indentation, but isntead we can just not introduce indentation on `=>` inside enums.


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 180b02efe..ac37cdcae 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
@@ -310,12 +310,23 @@ class ScalametaParser(input: Input)(implicit dialect: Dialect) { parser =>
       }
     }
 
+    /**
+     * Deals with different rules for indentation after self type arrow.
+     */
     def undoIndent(): Unit = {
-      sepRegions = sepRegions match {
+      sepRegions match {
         case region :: others if region.isIndented && curr.token.is[Indentation.Indent] =>
           next()
-          others
-        case regions => regions
+          sepRegions = sepRegions match {
+            // deal with  region added by `case` in enum after self type
+            case RegionArrow :: _ => others
+            // if no region was added
+            case `region` :: _ => others
+            // keep any added region in `next()`
+            case head :: _ => head :: others
+            case _ => sepRegions
+          }
+        case _ =>
       }
     }
 
@@ -3115,8 +3126,7 @@ class ScalametaParser(input: Input)(implicit dialect: Dialect) { parser =>
       case LeftBracket() =>
         t match {
           case _: Quasi | _: Term.Name | _: Term.Select | _: Term.Apply | _: Term.ApplyInfix |
-              _: Term.ApplyUnary | _: Term.New | _: Term.Placeholder | _: Term.ApplyUsing |
-              _: Term.Interpolate =>
+              _: Term.ApplyUnary | _: Term.New | _: Term.Placeholder | _: Term.ApplyUsing =>
             var app: Term = t
             while (token.is[LeftBracket]) app = atPos(t, auto)(Term.ApplyType(app, exprTypeArgs()))
 


Test patch:
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 7fb705e45..bfd758e73 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
@@ -811,13 +811,6 @@ class TermSuite extends ParseSuite {
     ) = term("""f"\\u$oct%04x"""")
   }
 
-  test("typed-interpolation") {
-    val Term.ApplyType(
-      Term.Interpolate(Term.Name("c"), List(Lit.String("something")), Nil),
-      List(Type.Name("String"))
-    ) = term("""c"something"[String]""")
-  }
-
   test("block-arg") {
     val res = term("new Foo({str => str.length})")
     val termList = q"List($res)"
diff --git a/tests/shared/src/test/scala/scala/meta/tests/parsers/dotty/EnumSuite.scala b/tests/shared/src/test/scala/scala/meta/tests/parsers/dotty/EnumSuite.scala
index 7bcf29b07..ca61d946a 100644
--- a/tests/shared/src/test/scala/scala/meta/tests/parsers/dotty/EnumSuite.scala
+++ b/tests/shared/src/test/scala/scala/meta/tests/parsers/dotty/EnumSuite.scala
@@ -603,6 +603,51 @@ class EnumSuite extends BaseDottySuite {
     )
   }
 
+  test("enum-arrow-toplevel") {
+    val code =
+      """|enum T2Enum:
+         |  case Hmm
+         |  val a = () =>  
+         |    fx()
+         |    gx()
+    """.stripMargin
+    val expected =
+      """|enum T2Enum {
+         |  case Hmm
+         |  val a = () => {
+         |    fx()
+         |    gx()
+         |  }
+         |}
+         |""".stripMargin
+    runTestAssert[Stat](code, assertLayout = Some(expected))(
+      Defn.Enum(
+        Nil,
+        Type.Name("T2Enum"),
+        Nil,
+        Ctor.Primary(Nil, Name(""), Nil),
+        Template(
+          Nil,
+          Nil,
+          Self(Name(""), None),
+          List(
+            Defn.EnumCase(Nil, Term.Name("Hmm"), Nil, Ctor.Primary(Nil, Name(""), Nil), Nil),
+            Defn.Val(
+              Nil,
+              List(Pat.Var(Term.Name("a"))),
+              None,
+              Term.Function(
+                Nil,
+                Term.Block(List(Term.Apply(Term.Name("fx"), Nil), Term.Apply(Term.Name("gx"), Nil)))
+              )
+            )
+          ),
+          Nil
+        )
+      )
+    )
+  }
+
   private def enumWithCase(name: String, enumCase: Stat) = Defn.Enum(
     Nil,
     Type.Name(name),
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 c57c03a18..d46f88249 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
@@ -2240,4 +2240,74 @@ class SignificantIndentationSuite extends BaseDottySuite {
     )
   }
 
+  test("i2505") {
+    runTestAssert[Source](
+      """|trait T2 { self: T =>
+         |  enum T2Enum:
+         |    case EnumCase
+         |  
+         |  extension (n: Int) def negate: Int = -n
+         |}""".stripMargin,
+      assertLayout = Some(
+        """|trait T2 { self: T =>
+           |  enum T2Enum { case EnumCase }
+           |  extension (n: Int) def negate: Int = -n
+           |}
+           |""".stripMargin
+      )
+    )(
+      Source(
+        List(
+          Defn.Trait(
+            Nil,
+            Type.Name("T2"),
+            Nil,
+            Ctor.Primary(Nil, Name(""), Nil),
+            Template(
+              Nil,
+              Nil,
+              Self(Term.Name("self"), Some(Type.Name("T"))),
+              List(
+                Defn.Enum(
+                  Nil,
+                  Type.Name("T2Enum"),
+                  Nil,
+                  Ctor.Primary(Nil, Name(""), Nil),
+                  Template(
+                    Nil,
+                    Nil,
+                    Self(Name(""), None),
+                    List(
+                      Defn.EnumCase(
+                        Nil,
+                        Term.Name("EnumCase"),
+                        Nil,
+                        Ctor.Primary(Nil, Name(""), Nil),
+                        Nil
+                      )
+                    ),
+                    Nil
+                  )
+                ),
+                Defn.ExtensionGroup(
+                  Nil,
+                  List(List(Term.Param(Nil, Term.Name("n"), Some(Type.Name("Int")), None))),
+                  Defn.Def(
+                    Nil,
+                    Term.Name("negate"),
+                    Nil,
+                    Nil,
+                    Some(Type.Name("Int")),
+                    Term.ApplyUnary(Term.Name("-"), Term.Name("n"))
+                  )
+                )
+              ),
+              Nil
+            )
+          )
+        )
+      )
+    )
+
+  }
 }