Repository: scalameta/scalameta
Pull request #2570 (2022-02-03 17:28:28)

Fix issues with using atPos with tree position
`Tree.pos` gives us the position in the file, while `atPos` needs to figure out the token index, so we can't just use start and end from Position. Instead we can jsut copy the origin of the original Tree.

The implicit conversions from Int are a bit at fault here, but when I tried to touch them everything blew up, so I'd rather escape with my life.

Fixes https://github.com/scalameta/scalameta/issues/2567


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 945ce7b50..75b539a39 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
@@ -918,9 +918,10 @@ class ScalametaParser(input: Input)(implicit dialect: Dialect) { parser =>
   implicit def modsToPos(mods: List[Mod]): Pos = mods.headOption
   def auto = AutoPos
 
-  def atPos[T <: Tree](pos: Position)(body: => T): T = {
-    atPos(pos.start, pos.end)(body)
+  def atPos[T <: Tree](tree: Tree)(body: => T): T = {
+    body.withOrigin(tree.origin)
   }
+
   def atPos[T <: Tree](token: Token)(body: => T): T = {
     atPos(token.startTokenPos, token.endTokenPos)(body)
   }
@@ -2674,13 +2675,13 @@ class ScalametaParser(input: Input)(implicit dialect: Dialect) { parser =>
                 case Term.Select(kwUsing @ Term.Name(soft.KwUsing.name), name) =>
                   Some(
                     atPos(tree, tree)(
-                      Term.Param(List(atPos(kwUsing.pos)(Mod.Using())), name, None, None)
+                      Term.Param(List(atPos(kwUsing)(Mod.Using())), name, None, None)
                     )
                   )
                 case Term.Ascribe(Term.Select(kwUsing @ Term.Name(soft.KwUsing.name), name), tpt) =>
                   Some(
                     atPos(tree, tree)(
-                      Term.Param(List(atPos(kwUsing.pos)(Mod.Using())), name, Some(tpt), None)
+                      Term.Param(List(atPos(kwUsing)(Mod.Using())), name, Some(tpt), None)
                     )
                   )
                 case Term.Ascribe(eta @ Term.Eta(kwUsing @ Term.Name(soft.KwUsing.name)), tpt) =>


Test patch:
diff --git a/tests/shared/src/test/scala/scala/meta/tests/parsers/dotty/MinorDottySuite.scala b/tests/shared/src/test/scala/scala/meta/tests/parsers/dotty/MinorDottySuite.scala
index f63f55c3d..49c7ff14c 100644
--- a/tests/shared/src/test/scala/scala/meta/tests/parsers/dotty/MinorDottySuite.scala
+++ b/tests/shared/src/test/scala/scala/meta/tests/parsers/dotty/MinorDottySuite.scala
@@ -1224,29 +1224,76 @@ class MinorDottySuite extends BaseDottySuite {
   }
 
   test("issue-2567") {
-    runTestAssert[Stat](
-      """|List(1,2,3).map { using i: Int => i }
+    runTestAssert[Source](
+      """|import _root_com.olegych.scastie.api.runtime._
+         |
+         |object Playground extends ScastieApp {
+         |  List(1,2,3).map { (using i: Int) => i }
+         |}
          |""".stripMargin,
       assertLayout = Some(
-        """|List(1, 2, 3).map {
-           |  (using i: Int) => i
+        """|import _root_com.olegych.scastie.api.runtime.*
+           |object Playground extends ScastieApp {
+           |  List(1, 2, 3).map {
+           |    (using i: Int) => i
+           |  }
            |}
            |""".stripMargin
       )
     )(
-      Term.Apply(
-        Term.Select(
-          Term.Apply(Term.Name("List"), List(Lit.Int(1), Lit.Int(2), Lit.Int(3))),
-          Term.Name("map")
-        ),
+      Source(
         List(
-          Term.Block(
+          Import(
             List(
-              Term.Function(
-                List(Term.Param(List(Mod.Using()), Term.Name("i"), Some(Type.Name("Int")), None)),
-                Term.Name("i")
+              Importer(
+                Term.Select(
+                  Term.Select(
+                    Term.Select(
+                      Term.Select(Term.Name("_root_com"), Term.Name("olegych")),
+                      Term.Name("scastie")
+                    ),
+                    Term.Name("api")
+                  ),
+                  Term.Name("runtime")
+                ),
+                List(Importee.Wildcard())
               )
             )
+          ),
+          Defn.Object(
+            Nil,
+            Term.Name("Playground"),
+            Template(
+              Nil,
+              List(Init(Type.Name("ScastieApp"), Name(""), Nil)),
+              Self(Name(""), None),
+              List(
+                Term.Apply(
+                  Term.Select(
+                    Term.Apply(Term.Name("List"), List(Lit.Int(1), Lit.Int(2), Lit.Int(3))),
+                    Term.Name("map")
+                  ),
+                  List(
+                    Term.Block(
+                      List(
+                        Term.Function(
+                          List(
+                            Term.Param(
+                              List(Mod.Using()),
+                              Term.Name("i"),
+                              Some(Type.Name("Int")),
+                              None
+                            )
+                          ),
+                          Term.Name("i")
+                        )
+                      )
+                    )
+                  )
+                )
+              ),
+              Nil
+            )
           )
         )
       )