From 84aebb73b13e006de94ee644651db06a671a94f1 Mon Sep 17 00:00:00 2001 From: Albert Meltzer <7529386+kitbellew@users.noreply.github.com> Date: Sat, 9 Mar 2024 01:53:36 -0800 Subject: [PATCH 1/2] Add test with incorrect leading-infix handling --- .../meta/tests/parsers/dotty/InfixSuite.scala | 98 +++++++++++++++++++ 1 file changed, 98 insertions(+) diff --git a/tests/shared/src/test/scala/scala/meta/tests/parsers/dotty/InfixSuite.scala b/tests/shared/src/test/scala/scala/meta/tests/parsers/dotty/InfixSuite.scala index 3dac9c0880..44436a8c77 100644 --- a/tests/shared/src/test/scala/scala/meta/tests/parsers/dotty/InfixSuite.scala +++ b/tests/shared/src/test/scala/scala/meta/tests/parsers/dotty/InfixSuite.scala @@ -653,4 +653,102 @@ class InfixSuite extends BaseDottySuite { runTestAssert[Stat](code, Some(layout))(tree) } + test("scalafmt #3825 1") { + val code = + """|object a: + | foo + | .map: i => + | i + 1 + | *> bar + |""".stripMargin + val layout = + """|object a { + | foo.map { + | i => i + 1 *> bar + | } + |} + |""".stripMargin + val tree = Defn.Object( + Nil, + tname("a"), + tpl( + Term.Apply( + Term.Select(tname("foo"), tname("map")), + blk( + Term.Function( + List(tparam("i")), + Term.ApplyInfix( + tname("i"), + tname("+"), + Nil, + List(Term.ApplyInfix(int(1), tname("*>"), Nil, List(tname("bar")))) + ) + ) + ) :: Nil + ) + ) + ) + runTestAssert[Stat](code, layout)(tree) + } + + test("scalafmt #3825 2") { + val code = + """|object a: + | object b: + | foo + | .map: i => + | i + 1 + | + 2 + | + 3 + | *> bar + | baz + | qux + |""".stripMargin + val layout = + """|object a { + | object b { + | foo.map { + | i => i + 1 + 2 + 3 *> bar + | } + | baz + | } + | qux + |} + |""".stripMargin + val tree = Defn.Object( + Nil, + tname("a"), + tpl( + Defn.Object( + Nil, + tname("b"), + tpl( + Term.Apply( + Term.Select(tname("foo"), tname("map")), + blk( + Term.Function( + List(tparam("i")), + Term.ApplyInfix( + Term.ApplyInfix( + Term.ApplyInfix(tname("i"), tname("+"), Nil, List(int(1))), + tname("+"), + Nil, + List(int(2)) + ), + tname("+"), + Nil, + List(Term.ApplyInfix(int(3), tname("*>"), Nil, List(tname("bar")))) + ) + ) + ) :: Nil + ), + tname("baz") + ) + ), + tname("qux") + ) + ) + runTestAssert[Stat](code, layout)(tree) + } + } From 231e2cfd795684cf6ce354f1bdb81ed903f96861 Mon Sep 17 00:00:00 2001 From: Albert Meltzer <7529386+kitbellew@users.noreply.github.com> Date: Sat, 9 Mar 2024 09:15:53 -0800 Subject: [PATCH 2/2] ScannerTokens: add RegionLine if indented further --- .../meta/internal/parsers/ScannerTokens.scala | 14 +++- .../meta/tests/parsers/dotty/InfixSuite.scala | 65 ++++++++++--------- 2 files changed, 47 insertions(+), 32 deletions(-) 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 e60e5c1b5e..ff1e5797b7 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 @@ -911,6 +911,16 @@ final class ScannerTokens(val tokens: Tokens)(implicit dialect: Dialect) { if (prevToken.is[Indentation]) _ => None else getOutdentIfNeeded(_).fold(getIndentIfNeeded, x => Some(Right(x))) + def maybeWithLF(regions: List[SepRegion]) = { + val res = getIfCanProduceLF(regions, nextIndent) + if (res.isEmpty) sepRegionsOrig match { + case (ri: SepRegionIndented) :: _ if ri.indent < nextIndent => + Some(Left(RegionLine(nextIndent) :: sepRegionsOrig)) + case _ => res + } + else res + } + @tailrec def iter(regions: List[SepRegion]): Option[Either[List[SepRegion], TokenRef]] = { val res = regionsToRes(regions).orElse { @@ -927,12 +937,12 @@ final class ScannerTokens(val tokens: Tokens)(implicit dialect: Dialect) { if (next.is[Dot]) None else rc.asBody() match { - case Some(body) => getIfCanProduceLF(body :: rs, nextIndent) + case Some(body) => maybeWithLF(body :: rs) case None => iter(rs) } case _ => iter(rs) } - case rs => getIfCanProduceLF(rs, nextIndent) + case rs => maybeWithLF(rs) } else res } diff --git a/tests/shared/src/test/scala/scala/meta/tests/parsers/dotty/InfixSuite.scala b/tests/shared/src/test/scala/scala/meta/tests/parsers/dotty/InfixSuite.scala index 44436a8c77..2622e3a564 100644 --- a/tests/shared/src/test/scala/scala/meta/tests/parsers/dotty/InfixSuite.scala +++ b/tests/shared/src/test/scala/scala/meta/tests/parsers/dotty/InfixSuite.scala @@ -664,27 +664,27 @@ class InfixSuite extends BaseDottySuite { val layout = """|object a { | foo.map { - | i => i + 1 *> bar - | } + | i => i + 1 + | } *> bar |} |""".stripMargin val tree = Defn.Object( Nil, tname("a"), tpl( - Term.Apply( - Term.Select(tname("foo"), tname("map")), - blk( - Term.Function( - List(tparam("i")), - Term.ApplyInfix( - tname("i"), - tname("+"), - Nil, - List(Term.ApplyInfix(int(1), tname("*>"), Nil, List(tname("bar")))) + Term.ApplyInfix( + Term.Apply( + Term.Select(tname("foo"), tname("map")), + blk( + Term.Function( + List(tparam("i")), + Term.ApplyInfix(tname("i"), tname("+"), Nil, List(int(1))) ) - ) - ) :: Nil + ) :: Nil + ), + tname("*>"), + Nil, + List(tname("bar")) ) ) ) @@ -708,8 +708,8 @@ class InfixSuite extends BaseDottySuite { """|object a { | object b { | foo.map { - | i => i + 1 + 2 + 3 *> bar - | } + | i => i + 1 + 2 + 3 + | } *> bar | baz | } | qux @@ -723,24 +723,29 @@ class InfixSuite extends BaseDottySuite { Nil, tname("b"), tpl( - Term.Apply( - Term.Select(tname("foo"), tname("map")), - blk( - Term.Function( - List(tparam("i")), - Term.ApplyInfix( + Term.ApplyInfix( + Term.Apply( + Term.Select(tname("foo"), tname("map")), + blk( + Term.Function( + List(tparam("i")), Term.ApplyInfix( - Term.ApplyInfix(tname("i"), tname("+"), Nil, List(int(1))), + Term.ApplyInfix( + Term.ApplyInfix(tname("i"), tname("+"), Nil, List(int(1))), + tname("+"), + Nil, + List(int(2)) + ), tname("+"), Nil, - List(int(2)) - ), - tname("+"), - Nil, - List(Term.ApplyInfix(int(3), tname("*>"), Nil, List(tname("bar")))) + List(int(3)) + ) ) - ) - ) :: Nil + ) :: Nil + ), + tname("*>"), + Nil, + List(tname("bar")) ), tname("baz") )