From 10f2867b213a46aa42da4c42de2e5ec4b18d5e0e Mon Sep 17 00:00:00 2001 From: Albert Meltzer <7529386+kitbellew@users.noreply.github.com> Date: Sat, 1 Oct 2022 09:47:16 -0700 Subject: [PATCH 1/2] Add indent.relativeToLhsLastLine config parameter --- docs/configuration.md | 41 +++ .../scala/org/scalafmt/config/Indents.scala | 10 + .../resources/newlines/source_classic.stat | 82 ++++++ .../test/resources/newlines/source_fold.stat | 82 ++++++ .../test/resources/newlines/source_keep.stat | 82 ++++++ .../resources/newlines/source_unfold.stat | 86 ++++++ .../test/resources/scala3/OptionalBraces.stat | 22 ++ .../resources/scala3/OptionalBraces_fold.stat | 21 ++ .../resources/scala3/OptionalBraces_keep.stat | 22 ++ .../scala3/OptionalBraces_unfold.stat | 23 ++ .../test/resources/test/IndentOperator.stat | 274 +++++++++++++++++ .../test/IndentOperatorFormatInfix.stat | 276 ++++++++++++++++++ 12 files changed, 1021 insertions(+) diff --git a/docs/configuration.md b/docs/configuration.md index eaf57111e9..c809fc8600 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -548,6 +548,47 @@ def fooDef } ``` +#### `indent.relativeToLhsLastLine` + +When the left-hand side of an infix or `match` expression is itself broken over +several lines, with the last line indented relative to the first line, this flag +determines whether the indent is relative to the first or the last line. + +This parameter takes a list of values including: + +- `match`: applies to match expressions +- `infix`: applies to infix expressions + +```scala mdoc:defaults +indent.relativeToLhsLastLine +``` + +```scala mdoc:scalafmt +indent.relativeToLhsLastLine = [] +--- +foo // c1 + .bar match { + case baz => qux + } +foo // c1 + .bar infix { + case baz => qux + } +``` + +```scala mdoc:scalafmt +indent.relativeToLhsLastLine = [match, infix] +--- +foo // c1 + .bar match { + case baz => qux +} +foo // c1 + .bar infix { + case baz => qux +} +``` + ### `indentOperator` Normally, the first eligible break _inside_ a chain of infix operators is diff --git a/scalafmt-core/shared/src/main/scala/org/scalafmt/config/Indents.scala b/scalafmt-core/shared/src/main/scala/org/scalafmt/config/Indents.scala index 621b5aba88..453461a973 100644 --- a/scalafmt-core/shared/src/main/scala/org/scalafmt/config/Indents.scala +++ b/scalafmt-core/shared/src/main/scala/org/scalafmt/config/Indents.scala @@ -31,6 +31,7 @@ case class Indents( matchSite: Option[Int] = None, private[config] val ctorSite: Option[Int] = None, extraBeforeOpenParenDefnSite: Int = 0, + relativeToLhsLastLine: Seq[Indents.RelativeToLhs] = Nil, @annotation.ExtraName("deriveSite") extendSite: Int = 4, withSiteRelativeToExtends: Int = 0, @@ -50,4 +51,13 @@ object Indents { generic.deriveSurface implicit lazy val codec: ConfCodecEx[Indents] = generic.deriveCodecEx(Indents()).noTypos + + sealed abstract class RelativeToLhs + object RelativeToLhs { + case object `match` extends RelativeToLhs + case object `infix` extends RelativeToLhs + + implicit val reader: ConfCodecEx[RelativeToLhs] = ReaderUtil + .oneOf[RelativeToLhs](`match`, `infix`) + } } diff --git a/scalafmt-tests/src/test/resources/newlines/source_classic.stat b/scalafmt-tests/src/test/resources/newlines/source_classic.stat index 57756cd579..817271a576 100644 --- a/scalafmt-tests/src/test/resources/newlines/source_classic.stat +++ b/scalafmt-tests/src/test/resources/newlines/source_classic.stat @@ -6005,3 +6005,85 @@ class Foo() { false } } +<<< #3327 match +indent.relativeToLhsLastLine = [match] +=== +object A { + private def get(ds: Any): IO[Long] = + IO.delay { + ds // c1 + .headOption /* c1 */ match /* c2 */ { + case Some(Row(value: Long)) => value + case _ => 0 + } + } +} +>>> +object A { + private def get(ds: Any): IO[Long] = + IO.delay { + ds // c1 + .headOption /* c1 */ match /* c2 */ { + case Some(Row(value: Long)) => + value + case _ => 0 + } + } +} +<<< #3327 infix +indent.relativeToLhsLastLine = [infix] +=== +object A { + private def get(ds: Any): IO[Long] = + IO.delay { + ds // c1 + .headOption /* c1 */ infix /* c2 */ { + case Some(Row(value: Long)) => value + case _ => 0 + } + } +} +>>> +object A { + private def get(ds: Any): IO[Long] = + IO.delay { + ds // c1 + .headOption /* c1 */ infix /* c2 */ { + case Some(Row(value: Long)) => + value + case _ => 0 + } + } +} +<<< #3327 infix 2 +indent.relativeToLhsLastLine = [infix] +=== +object A { + private def get(ds: Any): IO[Long] = + IO.delay { + ds // c1 + .headOption /* c1 */ infix /* c2 */ { + case Some(Row(value: Long)) => value + case _ => 0 + } /* c3 */ infix /* c4 */ { + case Some(Row(value: Long)) => value + case _ => 0 + } + } +} +>>> +object A { + private def get(ds: Any): IO[Long] = + IO.delay { + ds // c1 + .headOption /* c1 */ infix /* c2 */ { + case Some(Row(value: Long)) => + value + case _ => 0 + } /* c3 */ infix /* c4 */ { + case Some(Row(value: Long)) => + value + case _ => 0 + } + } +} diff --git a/scalafmt-tests/src/test/resources/newlines/source_fold.stat b/scalafmt-tests/src/test/resources/newlines/source_fold.stat index 3aa24336bc..66c114fc5f 100644 --- a/scalafmt-tests/src/test/resources/newlines/source_fold.stat +++ b/scalafmt-tests/src/test/resources/newlines/source_fold.stat @@ -5714,3 +5714,85 @@ class Foo() { false } } +<<< #3327 match +indent.relativeToLhsLastLine = [match] +=== +object A { + private def get(ds: Any): IO[Long] = + IO.delay { + ds // c1 + .headOption /* c1 */ match /* c2 */ { + case Some(Row(value: Long)) => value + case _ => 0 + } + } +} +>>> +object A { + private def get(ds: Any): IO[Long] = + IO.delay { + ds // c1 + .headOption /* c1 */ match /* c2 */ { + case Some(Row(value: Long)) => + value + case _ => 0 + } + } +} +<<< #3327 infix +indent.relativeToLhsLastLine = [infix] +=== +object A { + private def get(ds: Any): IO[Long] = + IO.delay { + ds // c1 + .headOption /* c1 */ infix /* c2 */ { + case Some(Row(value: Long)) => value + case _ => 0 + } + } +} +>>> +object A { + private def get(ds: Any): IO[Long] = + IO.delay { + ds // c1 + .headOption /* c1 */ infix /* c2 */ { + case Some(Row(value: Long)) => + value + case _ => 0 + } + } +} +<<< #3327 infix 2 +indent.relativeToLhsLastLine = [infix] +=== +object A { + private def get(ds: Any): IO[Long] = + IO.delay { + ds // c1 + .headOption /* c1 */ infix /* c2 */ { + case Some(Row(value: Long)) => value + case _ => 0 + } /* c3 */ infix /* c4 */ { + case Some(Row(value: Long)) => value + case _ => 0 + } + } +} +>>> +object A { + private def get(ds: Any): IO[Long] = + IO.delay { + ds // c1 + .headOption /* c1 */ infix /* c2 */ { + case Some(Row(value: Long)) => + value + case _ => 0 + } /* c3 */ infix /* c4 */ { + case Some(Row(value: Long)) => + value + case _ => 0 + } + } +} diff --git a/scalafmt-tests/src/test/resources/newlines/source_keep.stat b/scalafmt-tests/src/test/resources/newlines/source_keep.stat index a19785ec35..8aec16f550 100644 --- a/scalafmt-tests/src/test/resources/newlines/source_keep.stat +++ b/scalafmt-tests/src/test/resources/newlines/source_keep.stat @@ -6011,3 +6011,85 @@ class Foo() { false } } +<<< #3327 match +indent.relativeToLhsLastLine = [match] +=== +object A { + private def get(ds: Any): IO[Long] = + IO.delay { + ds // c1 + .headOption /* c1 */ match /* c2 */ { + case Some(Row(value: Long)) => value + case _ => 0 + } + } +} +>>> +object A { + private def get(ds: Any): IO[Long] = + IO.delay { + ds // c1 + .headOption /* c1 */ match /* c2 */ { + case Some(Row(value: Long)) => + value + case _ => 0 + } + } +} +<<< #3327 infix +indent.relativeToLhsLastLine = [infix] +=== +object A { + private def get(ds: Any): IO[Long] = + IO.delay { + ds // c1 + .headOption /* c1 */ infix /* c2 */ { + case Some(Row(value: Long)) => value + case _ => 0 + } + } +} +>>> +object A { + private def get(ds: Any): IO[Long] = + IO.delay { + ds // c1 + .headOption /* c1 */ infix /* c2 */ { + case Some(Row(value: Long)) => + value + case _ => 0 + } + } +} +<<< #3327 infix 2 +indent.relativeToLhsLastLine = [infix] +=== +object A { + private def get(ds: Any): IO[Long] = + IO.delay { + ds // c1 + .headOption /* c1 */ infix /* c2 */ { + case Some(Row(value: Long)) => value + case _ => 0 + } /* c3 */ infix /* c4 */ { + case Some(Row(value: Long)) => value + case _ => 0 + } + } +} +>>> +object A { + private def get(ds: Any): IO[Long] = + IO.delay { + ds // c1 + .headOption /* c1 */ infix /* c2 */ { + case Some(Row(value: Long)) => + value + case _ => 0 + } /* c3 */ infix /* c4 */ { + case Some(Row(value: Long)) => + value + case _ => 0 + } + } +} diff --git a/scalafmt-tests/src/test/resources/newlines/source_unfold.stat b/scalafmt-tests/src/test/resources/newlines/source_unfold.stat index 6971540c83..8a316235b6 100644 --- a/scalafmt-tests/src/test/resources/newlines/source_unfold.stat +++ b/scalafmt-tests/src/test/resources/newlines/source_unfold.stat @@ -6163,3 +6163,89 @@ class Foo() { false } } +<<< #3327 match +indent.relativeToLhsLastLine = [match] +=== +object A { + private def get(ds: Any): IO[Long] = + IO.delay { + ds // c1 + .headOption /* c1 */ match /* c2 */ { + case Some(Row(value: Long)) => value + case _ => 0 + } + } +} +>>> +object A { + private def get(ds: Any): IO[Long] = + IO.delay { + ds // c1 + .headOption /* c1 */ match /* c2 */ { + case Some(Row(value: Long)) => + value + case _ => + 0 + } + } +} +<<< #3327 infix +indent.relativeToLhsLastLine = [infix] +=== +object A { + private def get(ds: Any): IO[Long] = + IO.delay { + ds // c1 + .headOption /* c1 */ infix /* c2 */ { + case Some(Row(value: Long)) => value + case _ => 0 + } + } +} +>>> +object A { + private def get(ds: Any): IO[Long] = + IO.delay { + ds // c1 + .headOption /* c1 */ infix /* c2 */ { + case Some(Row(value: Long)) => + value + case _ => + 0 + } + } +} +<<< #3327 infix 2 +indent.relativeToLhsLastLine = [infix] +=== +object A { + private def get(ds: Any): IO[Long] = + IO.delay { + ds // c1 + .headOption /* c1 */ infix /* c2 */ { + case Some(Row(value: Long)) => value + case _ => 0 + } /* c3 */ infix /* c4 */ { + case Some(Row(value: Long)) => value + case _ => 0 + } + } +} +>>> +object A { + private def get(ds: Any): IO[Long] = + IO.delay { + ds // c1 + .headOption /* c1 */ infix /* c2 */ { + case Some(Row(value: Long)) => + value + case _ => + 0 + } /* c3 */ infix /* c4 */ { + case Some(Row(value: Long)) => + value + case _ => + 0 + } + } +} diff --git a/scalafmt-tests/src/test/resources/scala3/OptionalBraces.stat b/scalafmt-tests/src/test/resources/scala3/OptionalBraces.stat index 9258992b30..2c132f21d1 100644 --- a/scalafmt-tests/src/test/resources/scala3/OptionalBraces.stat +++ b/scalafmt-tests/src/test/resources/scala3/OptionalBraces.stat @@ -3564,3 +3564,25 @@ type Inner[A] = A match type Inner[A] = A match case Seq[x] => x case _ => A +<<< #3327 match +indent.relativeToLhsLastLine = [match] +=== +object A { + private def get(ds: Any): IO[Long] = + IO.delay { + ds // c1 + .headOption match + case Some(Row(value: Long)) => value + case _ => 0 + } +} +>>> +object A { + private def get(ds: Any): IO[Long] = + IO.delay { + ds // c1 + .headOption match + case Some(Row(value: Long)) => value + case _ => 0 + } +} diff --git a/scalafmt-tests/src/test/resources/scala3/OptionalBraces_fold.stat b/scalafmt-tests/src/test/resources/scala3/OptionalBraces_fold.stat index a05869d4b0..f552a77392 100644 --- a/scalafmt-tests/src/test/resources/scala3/OptionalBraces_fold.stat +++ b/scalafmt-tests/src/test/resources/scala3/OptionalBraces_fold.stat @@ -3390,3 +3390,24 @@ type Inner[A] = A match type Inner[A] = A match case Seq[x] => x case _ => A +<<< #3327 match +indent.relativeToLhsLastLine = [match] +=== +object A { + private def get(ds: Any): IO[Long] = + IO.delay { + ds // c1 + .headOption match + case Some(Row(value: Long)) => value + case _ => 0 + } +} +>>> +object A { + private def get(ds: Any): IO[Long] = IO.delay { + ds // c1 + .headOption match + case Some(Row(value: Long)) => value + case _ => 0 + } +} diff --git a/scalafmt-tests/src/test/resources/scala3/OptionalBraces_keep.stat b/scalafmt-tests/src/test/resources/scala3/OptionalBraces_keep.stat index 6c086d0872..f830809b89 100644 --- a/scalafmt-tests/src/test/resources/scala3/OptionalBraces_keep.stat +++ b/scalafmt-tests/src/test/resources/scala3/OptionalBraces_keep.stat @@ -3546,3 +3546,25 @@ type Inner[A] = A match type Inner[A] = A match case Seq[x] => x case _ => A +<<< #3327 match +indent.relativeToLhsLastLine = [match] +=== +object A { + private def get(ds: Any): IO[Long] = + IO.delay { + ds // c1 + .headOption match + case Some(Row(value: Long)) => value + case _ => 0 + } +} +>>> +object A { + private def get(ds: Any): IO[Long] = + IO.delay { + ds // c1 + .headOption match + case Some(Row(value: Long)) => value + case _ => 0 + } +} diff --git a/scalafmt-tests/src/test/resources/scala3/OptionalBraces_unfold.stat b/scalafmt-tests/src/test/resources/scala3/OptionalBraces_unfold.stat index 0a409b3949..6cfb36bb39 100644 --- a/scalafmt-tests/src/test/resources/scala3/OptionalBraces_unfold.stat +++ b/scalafmt-tests/src/test/resources/scala3/OptionalBraces_unfold.stat @@ -3674,3 +3674,26 @@ type Inner[A] = x case _ => A +<<< #3327 match +indent.relativeToLhsLastLine = [match] +=== +object A { + private def get(ds: Any): IO[Long] = + IO.delay { + ds // c1 + .headOption match + case Some(Row(value: Long)) => value + case _ => 0 + } +} +>>> +object A { + private def get(ds: Any): IO[Long] = IO.delay { + ds // c1 + .headOption match + case Some(Row(value: Long)) => + value + case _ => + 0 + } +} diff --git a/scalafmt-tests/src/test/resources/test/IndentOperator.stat b/scalafmt-tests/src/test/resources/test/IndentOperator.stat index 58f63b1f4c..e4eafef825 100644 --- a/scalafmt-tests/src/test/resources/test/IndentOperator.stat +++ b/scalafmt-tests/src/test/resources/test/IndentOperator.stat @@ -3731,3 +3731,277 @@ object a { b ) } +<<< #3327 relativeToLhsLastLine +runner.dialect = scala3 +indentOperator.exemptScope = aloneEnclosed +indent.relativeToLhsLastLine = [infix] +=== +object a { + if ( + a /* c1 */ // c2 + .foo && /* c1 */ // c2 + b /* c1 */ // c2 + .foo && /* c1 */ // c2 + c /* c1 */ // c2 + .foo + ) { + a /* c1 */ // c2 + .foo && /* c1 */ // c2 + b /* c1 */ // c2 + .foo && /* c1 */ // c2 + c /* c1 */ // c2 + .foo + } else if ( + a /* c1 */ // c2 + .foo /* c1 */ // c2 + && /* c1 */ // c2 + b /* c1 */ // c2 + .foo /* c1 */ // c2 + && c /* c1 */ // c2 + .foo + ) + a /* c1 */ // c2 + .foo && /* c1 */ // c2 + b /* c1 */ // c2 + .foo /* c1 */ // c2 + && c /* c1 */ // c2 + .foo +} +>>> +object a { + if ( + a /* c1 */ // c2 + .foo && /* c1 */ // c2 + b /* c1 */ // c2 + .foo && /* c1 */ // c2 + c /* c1 */ // c2 + .foo + ) { + a /* c1 */ // c2 + .foo && /* c1 */ // c2 + b /* c1 */ // c2 + .foo && /* c1 */ // c2 + c /* c1 */ // c2 + .foo + } else if ( + a /* c1 */ // c2 + .foo /* c1 */ // c2 + && /* c1 */ // c2 + b /* c1 */ // c2 + .foo /* c1 */ // c2 + && c /* c1 */ // c2 + .foo + ) + a /* c1 */ // c2 + .foo && /* c1 */ // c2 + b /* c1 */ // c2 + .foo /* c1 */ // c2 + && c /* c1 */ // c2 + .foo +} +<<< #3327 !relativeToLhsLastLine +runner.dialect = scala3 +indentOperator.exemptScope = aloneEnclosed +=== +object a { + if ( + a /* c1 */ // c2 + .foo && /* c1 */ // c2 + b /* c1 */ // c2 + .foo && /* c1 */ // c2 + c /* c1 */ // c2 + .foo + ) { + a /* c1 */ // c2 + .foo && /* c1 */ // c2 + b /* c1 */ // c2 + .foo && /* c1 */ // c2 + c /* c1 */ // c2 + .foo + } else if ( + a /* c1 */ // c2 + .foo /* c1 */ // c2 + && /* c1 */ // c2 + b /* c1 */ // c2 + .foo /* c1 */ // c2 + && c /* c1 */ // c2 + .foo + ) + a /* c1 */ // c2 + .foo && /* c1 */ // c2 + b /* c1 */ // c2 + .foo /* c1 */ // c2 + && c /* c1 */ // c2 + .foo +} +>>> +object a { + if ( + a /* c1 */ // c2 + .foo && /* c1 */ // c2 + b /* c1 */ // c2 + .foo && /* c1 */ // c2 + c /* c1 */ // c2 + .foo + ) { + a /* c1 */ // c2 + .foo && /* c1 */ // c2 + b /* c1 */ // c2 + .foo && /* c1 */ // c2 + c /* c1 */ // c2 + .foo + } else if ( + a /* c1 */ // c2 + .foo /* c1 */ // c2 + && /* c1 */ // c2 + b /* c1 */ // c2 + .foo /* c1 */ // c2 + && c /* c1 */ // c2 + .foo + ) + a /* c1 */ // c2 + .foo && /* c1 */ // c2 + b /* c1 */ // c2 + .foo /* c1 */ // c2 + && c /* c1 */ // c2 + .foo +} +<<< #3327 match +indent.relativeToLhsLastLine = [match] +=== +object A { + private def get(ds: Any): IO[Long] = + IO.delay { + ds // c1 + .headOption /* c1 */ match /* c2 */ { + case Some(Row(value: Long)) => value + case _ => 0 + } + } +} +>>> +object A { + private def get(ds: Any): IO[Long] = + IO.delay { + ds // c1 + .headOption /* c1 */ match /* c2 */ { + case Some(Row(value: Long)) => + value + case _ => 0 + } + } +} +<<< #3327 infix 1 `infix` +indent.relativeToLhsLastLine = [infix] +=== +object A { + private def get(ds: Any): IO[Long] = + IO.delay { + ds // c1 + .headOption /* c1 */ infix /* c2 */ { + case Some(Row(value: Long)) => value + case _ => 0 + } + } +} +>>> +object A { + private def get(ds: Any): IO[Long] = + IO.delay { + ds // c1 + .headOption /* c1 */ infix /* c2 */ { + case Some(Row(value: Long)) => + value + case _ => 0 + } + } +} +<<< #3327 infix 1 `&&` +indent.relativeToLhsLastLine = [infix] +=== +object A { + private def get(ds: Any): IO[Long] = + IO.delay { + ds // c1 + .headOption /* c1 */ && /* c2 */ { + case Some(Row(value: Long)) => value + case _ => 0 + } + } +} +>>> +object A { + private def get(ds: Any): IO[Long] = + IO.delay { + ds // c1 + .headOption /* c1 */ && /* c2 */ { + case Some(Row(value: Long)) => + value + case _ => 0 + } + } +} +<<< #3327 infix 2 `infix` +indent.relativeToLhsLastLine = [infix] +=== +object A { + private def get(ds: Any): IO[Long] = + IO.delay { + ds // c1 + .headOption /* c1 */ infix /* c2 */ { + case Some(Row(value: Long)) => value + case _ => 0 + } /* c3 */ infix /* c4 */ { + case Some(Row(value: Long)) => value + case _ => 0 + } + } +} +>>> +object A { + private def get(ds: Any): IO[Long] = + IO.delay { + ds // c1 + .headOption /* c1 */ infix /* c2 */ { + case Some(Row(value: Long)) => + value + case _ => 0 + } /* c3 */ infix /* c4 */ { + case Some(Row(value: Long)) => + value + case _ => 0 + } + } +} +<<< #3327 infix 2 `&&` +indent.relativeToLhsLastLine = [infix] +=== +object A { + private def get(ds: Any): IO[Long] = + IO.delay { + ds // c1 + .headOption /* c1 */ && /* c2 */ { + case Some(Row(value: Long)) => value + case _ => 0 + } /* c3 */ && /* c4 */ { + case Some(Row(value: Long)) => value + case _ => 0 + } + } +} +>>> +object A { + private def get(ds: Any): IO[Long] = + IO.delay { + ds // c1 + .headOption /* c1 */ && /* c2 */ { + case Some(Row(value: Long)) => + value + case _ => 0 + } /* c3 */ && /* c4 */ { + case Some(Row(value: Long)) => + value + case _ => 0 + } + } +} diff --git a/scalafmt-tests/src/test/resources/test/IndentOperatorFormatInfix.stat b/scalafmt-tests/src/test/resources/test/IndentOperatorFormatInfix.stat index fbcbc077a4..7a3e93b737 100644 --- a/scalafmt-tests/src/test/resources/test/IndentOperatorFormatInfix.stat +++ b/scalafmt-tests/src/test/resources/test/IndentOperatorFormatInfix.stat @@ -2908,3 +2908,279 @@ object a { b } } +<<< #3327 relativeToLhsLastLine +runner.dialect = scala3 +indentOperator.exemptScope = aloneEnclosed +indent.relativeToLhsLastLine = [infix] +=== +object a { + if ( + a /* c1 */ // c2 + .foo && /* c1 */ // c2 + b /* c1 */ // c2 + .foo && /* c1 */ // c2 + c /* c1 */ // c2 + .foo + ) { + a /* c1 */ // c2 + .foo && /* c1 */ // c2 + b /* c1 */ // c2 + .foo && /* c1 */ // c2 + c /* c1 */ // c2 + .foo + } else if ( + a /* c1 */ // c2 + .foo /* c1 */ // c2 + && /* c1 */ // c2 + b /* c1 */ // c2 + .foo /* c1 */ // c2 + && c /* c1 */ // c2 + .foo + ) + a /* c1 */ // c2 + .foo && /* c1 */ // c2 + b /* c1 */ // c2 + .foo /* c1 */ && // c2 + c /* c1 */ // c2 + .foo +} +>>> +object a { + if ( + a /* c1 */ // c2 + .foo && /* c1 */ // c2 + b /* c1 */ // c2 + .foo && /* c1 */ // c2 + c /* c1 */ // c2 + .foo + ) { + a /* c1 */ // c2 + .foo && /* c1 */ // c2 + b /* c1 */ // c2 + .foo && /* c1 */ // c2 + c /* c1 */ // c2 + .foo + } else if ( + a /* c1 */ // c2 + .foo /* c1 */ // c2 + && /* c1 */ // c2 + b /* c1 */ // c2 + .foo /* c1 */ // c2 + && + c /* c1 */ // c2 + .foo + ) + a /* c1 */ // c2 + .foo && /* c1 */ // c2 + b /* c1 */ // c2 + .foo /* c1 */ && // c2 + c /* c1 */ // c2 + .foo +} +<<< #3327 !relativeToLhsLastLine +runner.dialect = scala3 +indentOperator.exemptScope = aloneEnclosed +=== +object a { + if ( + a /* c1 */ // c2 + .foo && /* c1 */ // c2 + b /* c1 */ // c2 + .foo && /* c1 */ // c2 + c /* c1 */ // c2 + .foo + ) { + a /* c1 */ // c2 + .foo && /* c1 */ // c2 + b /* c1 */ // c2 + .foo && /* c1 */ // c2 + c /* c1 */ // c2 + .foo + } else if ( + a /* c1 */ // c2 + .foo /* c1 */ // c2 + && /* c1 */ // c2 + b /* c1 */ // c2 + .foo /* c1 */ // c2 + && c /* c1 */ // c2 + .foo + ) + a /* c1 */ // c2 + .foo && /* c1 */ // c2 + b /* c1 */ // c2 + .foo /* c1 */ && // c2 + c /* c1 */ // c2 + .foo +} +>>> +object a { + if ( + a /* c1 */ // c2 + .foo && /* c1 */ // c2 + b /* c1 */ // c2 + .foo && /* c1 */ // c2 + c /* c1 */ // c2 + .foo + ) { + a /* c1 */ // c2 + .foo && /* c1 */ // c2 + b /* c1 */ // c2 + .foo && /* c1 */ // c2 + c /* c1 */ // c2 + .foo + } else if ( + a /* c1 */ // c2 + .foo /* c1 */ // c2 + && /* c1 */ // c2 + b /* c1 */ // c2 + .foo /* c1 */ // c2 + && + c /* c1 */ // c2 + .foo + ) + a /* c1 */ // c2 + .foo && /* c1 */ // c2 + b /* c1 */ // c2 + .foo /* c1 */ && // c2 + c /* c1 */ // c2 + .foo +} +<<< #3327 match +indent.relativeToLhsLastLine = [match] +=== +object A { + private def get(ds: Any): IO[Long] = + IO.delay { + ds // c1 + .headOption /* c1 */ match /* c2 */ { + case Some(Row(value: Long)) => value + case _ => 0 + } + } +} +>>> +object A { + private def get(ds: Any): IO[Long] = + IO.delay { + ds // c1 + .headOption /* c1 */ match /* c2 */ { + case Some(Row(value: Long)) => + value + case _ => 0 + } + } +} +<<< #3327 infix 1 `infix` +indent.relativeToLhsLastLine = [infix] +=== +object A { + private def get(ds: Any): IO[Long] = + IO.delay { + ds // c1 + .headOption /* c1 */ infix /* c2 */ { + case Some(Row(value: Long)) => value + case _ => 0 + } + } +} +>>> +object A { + private def get(ds: Any): IO[Long] = + IO.delay { + ds // c1 + .headOption /* c1 */ infix /* c2 */ { + case Some(Row(value: Long)) => + value + case _ => 0 + } + } +} +<<< #3327 infix 1 `&&` +indent.relativeToLhsLastLine = [infix] +=== +object A { + private def get(ds: Any): IO[Long] = + IO.delay { + ds // c1 + .headOption /* c1 */ && /* c2 */ { + case Some(Row(value: Long)) => value + case _ => 0 + } + } +} +>>> +object A { + private def get(ds: Any): IO[Long] = + IO.delay { + ds // c1 + .headOption /* c1 */ && /* c2 */ { + case Some(Row(value: Long)) => + value + case _ => 0 + } + } +} +<<< #3327 infix 2 `infix` +indent.relativeToLhsLastLine = [infix] +=== +object A { + private def get(ds: Any): IO[Long] = + IO.delay { + ds // c1 + .headOption /* c1 */ infix /* c2 */ { + case Some(Row(value: Long)) => value + case _ => 0 + } /* c3 */ infix /* c4 */ { + case Some(Row(value: Long)) => value + case _ => 0 + } + } +} +>>> +object A { + private def get(ds: Any): IO[Long] = + IO.delay { + ds // c1 + .headOption /* c1 */ infix /* c2 */ { + case Some(Row(value: Long)) => + value + case _ => 0 + } /* c3 */ infix /* c4 */ { + case Some(Row(value: Long)) => + value + case _ => 0 + } + } +} +<<< #3327 infix 2 `&&` +indent.relativeToLhsLastLine = [infix] +=== +object A { + private def get(ds: Any): IO[Long] = + IO.delay { + ds // c1 + .headOption /* c1 */ && /* c2 */ { + case Some(Row(value: Long)) => value + case _ => 0 + } /* c3 */ && /* c4 */ { + case Some(Row(value: Long)) => value + case _ => 0 + } + } +} +>>> +object A { + private def get(ds: Any): IO[Long] = + IO.delay { + ds // c1 + .headOption /* c1 */ && /* c2 */ { + case Some(Row(value: Long)) => + value + case _ => 0 + } /* c3 */ && /* c4 */ { + case Some(Row(value: Long)) => + value + case _ => 0 + } + } +} From 338f65ef748937aabd4a71479327867dfca771dd Mon Sep 17 00:00:00 2001 From: Albert Meltzer <7529386+kitbellew@users.noreply.github.com> Date: Mon, 3 Oct 2022 15:34:01 +0200 Subject: [PATCH 2/2] State: extend indent if relativeToLhsLastLine --- .../scala/org/scalafmt/internal/ModExt.scala | 3 + .../scala/org/scalafmt/internal/Split.scala | 2 +- .../scala/org/scalafmt/internal/State.scala | 75 +++++++++++++++++-- .../resources/newlines/source_classic.stat | 32 ++++---- .../test/resources/newlines/source_fold.stat | 35 +++++---- .../test/resources/newlines/source_keep.stat | 32 ++++---- .../resources/newlines/source_unfold.stat | 46 +++++++----- .../test/resources/scala3/OptionalBraces.stat | 4 +- .../resources/scala3/OptionalBraces_fold.stat | 4 +- .../resources/scala3/OptionalBraces_keep.stat | 4 +- .../scala3/OptionalBraces_unfold.stat | 8 +- .../test/resources/test/IndentOperator.stat | 56 +++++++------- .../test/IndentOperatorFormatInfix.stat | 62 ++++++++------- 13 files changed, 220 insertions(+), 143 deletions(-) diff --git a/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/ModExt.scala b/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/ModExt.scala index 3e9557f8a8..0da8ba2e4b 100644 --- a/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/ModExt.scala +++ b/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/ModExt.scala @@ -14,6 +14,9 @@ case class ModExt( ) { lazy val indentation = indents.mkString("[", ", ", "]") + @inline + def isNL: Boolean = mod.isNewline + def withIndent(length: => Length, expire: => Token, when: ExpiresOn): ModExt = length match { case Length.Num(0, _) => this diff --git a/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/Split.scala b/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/Split.scala index 8d4150cbaf..bc60d96cc5 100644 --- a/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/Split.scala +++ b/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/Split.scala @@ -58,7 +58,7 @@ case class Split( def indentation: String = modExt.indentation @inline - def isNL: Boolean = modExt.mod.isNewline + def isNL: Boolean = modExt.isNL @inline def length: Int = modExt.mod.length diff --git a/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/State.scala b/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/State.scala index 0280cfa7f8..4a11667e32 100644 --- a/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/State.scala +++ b/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/State.scala @@ -4,9 +4,9 @@ import java.util.regex.Pattern import scala.annotation.tailrec import scala.meta.tokens.Token +import scala.meta.{Term, Tree} -import org.scalafmt.config.Comments -import org.scalafmt.config.ScalafmtConfig +import org.scalafmt.config.{Comments, Indents, ScalafmtConfig} import org.scalafmt.util.TreeOps._ /** A partial formatting solution up to splits.length number of tokens. @@ -43,20 +43,26 @@ final case class State( if (right.is[Token.EOF]) (initialNextSplit, 0, Seq.empty) else { val offset = column - indentation - def getUnexpired(indents: Seq[ActualIndent]): Seq[ActualIndent] = - indents.filter(_.notExpiredBy(tok)) - def getPushes(modExt: ModExt): Seq[ActualIndent] = - getUnexpired(modExt.getActualIndents(offset)) + def getUnexpired(modExt: ModExt, indents: Seq[ActualIndent] = Nil) = { + val extendedEnd = getRelativeToLhsLastLineEnd(modExt.isNL) + (modExt.getActualIndents(offset) ++ indents).flatMap { x => + if (x.notExpiredBy(tok)) Some(x) + else + extendedEnd + .map(y => x.copy(expireEnd = y, expiresAt = ExpiresOn.After)) + } + } + val initialModExt = initialNextSplit.modExt val indents = initialModExt.indents - val nextPushes = getPushes(initialModExt) ++ getUnexpired(pushes) + val nextPushes = getUnexpired(initialModExt, pushes) val nextIndent = Indent.getIndent(nextPushes) initialNextSplit.modExt.mod match { case m: NewlineT if !tok.left.is[Token.Comment] && m.alt.isDefined && nextIndent >= m.alt.get.mod.length + column => val alt = m.alt.get - val altPushes = getPushes(alt) + val altPushes = getUnexpired(alt) val altIndent = Indent.getIndent(altPushes) val split = initialNextSplit.withMod(alt.withIndents(indents)) (split, nextIndent + altIndent, nextPushes ++ altPushes) @@ -255,6 +261,59 @@ final case class State( } } + private def getRelativeToLhsLastLineEnd(isNL: Boolean)(implicit + style: ScalafmtConfig, + tokens: FormatTokens + ): Option[Int] = { + val allowed = style.indent.relativeToLhsLastLine + + def treeEnd(x: Tree) = tokens.getLast(x).left.end + def indentEnd(ft: FormatToken, isNL: Boolean)(onComment: => Option[Int]) = { + val leftOwner = ft.meta.leftOwner + ft.left match { + case _: Token.KwMatch + if leftOwner.is[Term.Match] && + allowed.contains(Indents.RelativeToLhs.`match`) => + Some(treeEnd(leftOwner)) + case _: Token.Ident if !isNL => + leftOwner.parent match { + case Some(p: Term.ApplyInfix) + if p.op.eq(leftOwner) && + allowed.contains(Indents.RelativeToLhs.`infix`) => + Some(treeEnd(p)) + case _ => None + } + case _: Token.Comment if !isNL => onComment + case _ => None + } + } + + val tok = tokens(depth) + val right = tok.right + if (allowed.isEmpty) None + else if (right.is[Token.Comment]) Some(right.end) + else + indentEnd(tok, isNL) { + val earlierState = prev.prevNonCommentSameLine + indentEnd(tokens(earlierState.depth), earlierState.split.isNL)(None) + }.orElse { + val delay = !isNL && (right match { + case _: Token.KwMatch => + tok.meta.rightOwner.is[Term.Match] && + allowed.contains(Indents.RelativeToLhs.`match`) + case _: Token.Ident => + tok.meta.rightOwner.parent.exists(_.is[Term.ApplyInfix]) && + allowed.contains(Indents.RelativeToLhs.`infix`) + case _ => false + }) + if (delay) Some(right.end) else None + } + } + + @tailrec + private def prevNonCommentSameLine(implicit tokens: FormatTokens): State = + if (split.isNL || !tokens(depth).left.is[Token.Comment]) this + else prev.prevNonCommentSameLine } object State { diff --git a/scalafmt-tests/src/test/resources/newlines/source_classic.stat b/scalafmt-tests/src/test/resources/newlines/source_classic.stat index 817271a576..5f2f0987e0 100644 --- a/scalafmt-tests/src/test/resources/newlines/source_classic.stat +++ b/scalafmt-tests/src/test/resources/newlines/source_classic.stat @@ -6024,10 +6024,10 @@ object A { IO.delay { ds // c1 .headOption /* c1 */ match /* c2 */ { - case Some(Row(value: Long)) => - value - case _ => 0 - } + case Some(Row(value: Long)) => + value + case _ => 0 + } } } <<< #3327 infix @@ -6049,10 +6049,10 @@ object A { IO.delay { ds // c1 .headOption /* c1 */ infix /* c2 */ { - case Some(Row(value: Long)) => - value - case _ => 0 - } + case Some(Row(value: Long)) => + value + case _ => 0 + } } } <<< #3327 infix 2 @@ -6077,13 +6077,13 @@ object A { IO.delay { ds // c1 .headOption /* c1 */ infix /* c2 */ { - case Some(Row(value: Long)) => - value - case _ => 0 - } /* c3 */ infix /* c4 */ { - case Some(Row(value: Long)) => - value - case _ => 0 - } + case Some(Row(value: Long)) => + value + case _ => 0 + } /* c3 */ infix /* c4 */ { + case Some(Row(value: Long)) => + value + case _ => 0 + } } } diff --git a/scalafmt-tests/src/test/resources/newlines/source_fold.stat b/scalafmt-tests/src/test/resources/newlines/source_fold.stat index 66c114fc5f..25a3164e87 100644 --- a/scalafmt-tests/src/test/resources/newlines/source_fold.stat +++ b/scalafmt-tests/src/test/resources/newlines/source_fold.stat @@ -5733,10 +5733,10 @@ object A { IO.delay { ds // c1 .headOption /* c1 */ match /* c2 */ { - case Some(Row(value: Long)) => - value - case _ => 0 - } + case Some(Row(value: Long)) => + value + case _ => 0 + } } } <<< #3327 infix @@ -5758,10 +5758,11 @@ object A { IO.delay { ds // c1 .headOption /* c1 */ infix /* c2 */ { - case Some(Row(value: Long)) => - value - case _ => 0 - } + case Some( + Row(value: Long) + ) => value + case _ => 0 + } } } <<< #3327 infix 2 @@ -5786,13 +5787,15 @@ object A { IO.delay { ds // c1 .headOption /* c1 */ infix /* c2 */ { - case Some(Row(value: Long)) => - value - case _ => 0 - } /* c3 */ infix /* c4 */ { - case Some(Row(value: Long)) => - value - case _ => 0 - } + case Some( + Row(value: Long) + ) => value + case _ => 0 + } /* c3 */ infix /* c4 */ { + case Some( + Row(value: Long) + ) => value + case _ => 0 + } } } diff --git a/scalafmt-tests/src/test/resources/newlines/source_keep.stat b/scalafmt-tests/src/test/resources/newlines/source_keep.stat index 8aec16f550..78c1ba9b85 100644 --- a/scalafmt-tests/src/test/resources/newlines/source_keep.stat +++ b/scalafmt-tests/src/test/resources/newlines/source_keep.stat @@ -6030,10 +6030,10 @@ object A { IO.delay { ds // c1 .headOption /* c1 */ match /* c2 */ { - case Some(Row(value: Long)) => - value - case _ => 0 - } + case Some(Row(value: Long)) => + value + case _ => 0 + } } } <<< #3327 infix @@ -6055,10 +6055,10 @@ object A { IO.delay { ds // c1 .headOption /* c1 */ infix /* c2 */ { - case Some(Row(value: Long)) => - value - case _ => 0 - } + case Some(Row(value: Long)) => + value + case _ => 0 + } } } <<< #3327 infix 2 @@ -6083,13 +6083,13 @@ object A { IO.delay { ds // c1 .headOption /* c1 */ infix /* c2 */ { - case Some(Row(value: Long)) => - value - case _ => 0 - } /* c3 */ infix /* c4 */ { - case Some(Row(value: Long)) => - value - case _ => 0 - } + case Some(Row(value: Long)) => + value + case _ => 0 + } /* c3 */ infix /* c4 */ { + case Some(Row(value: Long)) => + value + case _ => 0 + } } } diff --git a/scalafmt-tests/src/test/resources/newlines/source_unfold.stat b/scalafmt-tests/src/test/resources/newlines/source_unfold.stat index 8a316235b6..420c8b322c 100644 --- a/scalafmt-tests/src/test/resources/newlines/source_unfold.stat +++ b/scalafmt-tests/src/test/resources/newlines/source_unfold.stat @@ -6182,11 +6182,11 @@ object A { IO.delay { ds // c1 .headOption /* c1 */ match /* c2 */ { - case Some(Row(value: Long)) => - value - case _ => - 0 - } + case Some(Row(value: Long)) => + value + case _ => + 0 + } } } <<< #3327 infix @@ -6208,11 +6208,13 @@ object A { IO.delay { ds // c1 .headOption /* c1 */ infix /* c2 */ { - case Some(Row(value: Long)) => - value - case _ => - 0 - } + case Some( + Row(value: Long) + ) => + value + case _ => + 0 + } } } <<< #3327 infix 2 @@ -6237,15 +6239,19 @@ object A { IO.delay { ds // c1 .headOption /* c1 */ infix /* c2 */ { - case Some(Row(value: Long)) => - value - case _ => - 0 - } /* c3 */ infix /* c4 */ { - case Some(Row(value: Long)) => - value - case _ => - 0 - } + case Some( + Row(value: Long) + ) => + value + case _ => + 0 + } /* c3 */ infix /* c4 */ { + case Some( + Row(value: Long) + ) => + value + case _ => + 0 + } } } diff --git a/scalafmt-tests/src/test/resources/scala3/OptionalBraces.stat b/scalafmt-tests/src/test/resources/scala3/OptionalBraces.stat index 2c132f21d1..9fffb640ae 100644 --- a/scalafmt-tests/src/test/resources/scala3/OptionalBraces.stat +++ b/scalafmt-tests/src/test/resources/scala3/OptionalBraces.stat @@ -3582,7 +3582,7 @@ object A { IO.delay { ds // c1 .headOption match - case Some(Row(value: Long)) => value - case _ => 0 + case Some(Row(value: Long)) => value + case _ => 0 } } diff --git a/scalafmt-tests/src/test/resources/scala3/OptionalBraces_fold.stat b/scalafmt-tests/src/test/resources/scala3/OptionalBraces_fold.stat index f552a77392..73535344d6 100644 --- a/scalafmt-tests/src/test/resources/scala3/OptionalBraces_fold.stat +++ b/scalafmt-tests/src/test/resources/scala3/OptionalBraces_fold.stat @@ -3407,7 +3407,7 @@ object A { private def get(ds: Any): IO[Long] = IO.delay { ds // c1 .headOption match - case Some(Row(value: Long)) => value - case _ => 0 + case Some(Row(value: Long)) => value + case _ => 0 } } diff --git a/scalafmt-tests/src/test/resources/scala3/OptionalBraces_keep.stat b/scalafmt-tests/src/test/resources/scala3/OptionalBraces_keep.stat index f830809b89..58d120536e 100644 --- a/scalafmt-tests/src/test/resources/scala3/OptionalBraces_keep.stat +++ b/scalafmt-tests/src/test/resources/scala3/OptionalBraces_keep.stat @@ -3564,7 +3564,7 @@ object A { IO.delay { ds // c1 .headOption match - case Some(Row(value: Long)) => value - case _ => 0 + case Some(Row(value: Long)) => value + case _ => 0 } } diff --git a/scalafmt-tests/src/test/resources/scala3/OptionalBraces_unfold.stat b/scalafmt-tests/src/test/resources/scala3/OptionalBraces_unfold.stat index 6cfb36bb39..ac66004587 100644 --- a/scalafmt-tests/src/test/resources/scala3/OptionalBraces_unfold.stat +++ b/scalafmt-tests/src/test/resources/scala3/OptionalBraces_unfold.stat @@ -3691,9 +3691,9 @@ object A { private def get(ds: Any): IO[Long] = IO.delay { ds // c1 .headOption match - case Some(Row(value: Long)) => - value - case _ => - 0 + case Some(Row(value: Long)) => + value + case _ => + 0 } } diff --git a/scalafmt-tests/src/test/resources/test/IndentOperator.stat b/scalafmt-tests/src/test/resources/test/IndentOperator.stat index e4eafef825..0ffe9e9036 100644 --- a/scalafmt-tests/src/test/resources/test/IndentOperator.stat +++ b/scalafmt-tests/src/test/resources/test/IndentOperator.stat @@ -3885,10 +3885,10 @@ object A { IO.delay { ds // c1 .headOption /* c1 */ match /* c2 */ { - case Some(Row(value: Long)) => - value - case _ => 0 - } + case Some(Row(value: Long)) => + value + case _ => 0 + } } } <<< #3327 infix 1 `infix` @@ -3910,10 +3910,10 @@ object A { IO.delay { ds // c1 .headOption /* c1 */ infix /* c2 */ { - case Some(Row(value: Long)) => - value - case _ => 0 - } + case Some(Row(value: Long)) => + value + case _ => 0 + } } } <<< #3327 infix 1 `&&` @@ -3935,10 +3935,10 @@ object A { IO.delay { ds // c1 .headOption /* c1 */ && /* c2 */ { - case Some(Row(value: Long)) => - value - case _ => 0 - } + case Some(Row(value: Long)) => + value + case _ => 0 + } } } <<< #3327 infix 2 `infix` @@ -3963,14 +3963,14 @@ object A { IO.delay { ds // c1 .headOption /* c1 */ infix /* c2 */ { - case Some(Row(value: Long)) => - value - case _ => 0 - } /* c3 */ infix /* c4 */ { - case Some(Row(value: Long)) => - value - case _ => 0 - } + case Some(Row(value: Long)) => + value + case _ => 0 + } /* c3 */ infix /* c4 */ { + case Some(Row(value: Long)) => + value + case _ => 0 + } } } <<< #3327 infix 2 `&&` @@ -3995,13 +3995,13 @@ object A { IO.delay { ds // c1 .headOption /* c1 */ && /* c2 */ { - case Some(Row(value: Long)) => - value - case _ => 0 - } /* c3 */ && /* c4 */ { - case Some(Row(value: Long)) => - value - case _ => 0 - } + case Some(Row(value: Long)) => + value + case _ => 0 + } /* c3 */ && /* c4 */ { + case Some(Row(value: Long)) => + value + case _ => 0 + } } } diff --git a/scalafmt-tests/src/test/resources/test/IndentOperatorFormatInfix.stat b/scalafmt-tests/src/test/resources/test/IndentOperatorFormatInfix.stat index 7a3e93b737..1d66444212 100644 --- a/scalafmt-tests/src/test/resources/test/IndentOperatorFormatInfix.stat +++ b/scalafmt-tests/src/test/resources/test/IndentOperatorFormatInfix.stat @@ -3064,10 +3064,10 @@ object A { IO.delay { ds // c1 .headOption /* c1 */ match /* c2 */ { - case Some(Row(value: Long)) => - value - case _ => 0 - } + case Some(Row(value: Long)) => + value + case _ => 0 + } } } <<< #3327 infix 1 `infix` @@ -3089,10 +3089,12 @@ object A { IO.delay { ds // c1 .headOption /* c1 */ infix /* c2 */ { - case Some(Row(value: Long)) => - value - case _ => 0 - } + case Some( + Row(value: Long) + ) => + value + case _ => 0 + } } } <<< #3327 infix 1 `&&` @@ -3114,10 +3116,10 @@ object A { IO.delay { ds // c1 .headOption /* c1 */ && /* c2 */ { - case Some(Row(value: Long)) => - value - case _ => 0 - } + case Some(Row(value: Long)) => + value + case _ => 0 + } } } <<< #3327 infix 2 `infix` @@ -3142,14 +3144,18 @@ object A { IO.delay { ds // c1 .headOption /* c1 */ infix /* c2 */ { - case Some(Row(value: Long)) => - value - case _ => 0 - } /* c3 */ infix /* c4 */ { - case Some(Row(value: Long)) => - value - case _ => 0 - } + case Some( + Row(value: Long) + ) => + value + case _ => 0 + } /* c3 */ infix /* c4 */ { + case Some( + Row(value: Long) + ) => + value + case _ => 0 + } } } <<< #3327 infix 2 `&&` @@ -3174,13 +3180,13 @@ object A { IO.delay { ds // c1 .headOption /* c1 */ && /* c2 */ { - case Some(Row(value: Long)) => - value - case _ => 0 - } /* c3 */ && /* c4 */ { - case Some(Row(value: Long)) => - value - case _ => 0 - } + case Some(Row(value: Long)) => + value + case _ => 0 + } /* c3 */ && /* c4 */ { + case Some(Row(value: Long)) => + value + case _ => 0 + } } }