diff --git a/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/Router.scala b/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/Router.scala index 2a494e3cab..78d753f65a 100644 --- a/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/Router.scala +++ b/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/Router.scala @@ -2096,12 +2096,13 @@ class Router(formatOps: FormatOps) { } val arrow = arrowFt.left val postArrowFt = nextNonCommentSameLine(arrowFt) + val postArrow = postArrowFt.left val ownerEnd = getLastOpt(owner) val expire = ownerEnd.fold(postArrowFt)(nextNonCommentSameLine).left val bodyBlock = isCaseBodyABlock(arrowFt, owner) - def defaultPolicy = decideNewlinesOnlyAfterToken(postArrowFt.left) - val policy = + def defaultPolicy = decideNewlinesOnlyAfterToken(postArrow) + val postArrowPolicy = if (bodyBlock || isAttachedCommentThenBreak(arrowFt)) NoPolicy else if (isCaseBodyEnclosedAsBlock(postArrowFt, owner)) { val postParenFt = nextNonCommentSameLineAfter(postArrowFt) @@ -2135,12 +2136,23 @@ class Router(formatOps: FormatOps) { Indent(arrowIndent, arrow, After), ) val mod = ModExt(Space, indents) - val slbSplitOpt = (ownerEnd match { + val slbExpireOpt = ownerEnd match { case None => Some(postArrowFt) case Some(x) => prevNotTrailingComment(x).toOption - }).map(x => Split(mod, 0).withSingleLine(x.left, killOnFail = true)) - val splits = Split(mod, 0, policy = policy) :: Nil - slbSplitOpt.fold(splits)(_ :: splits) + } + val policy = slbExpireOpt.fold(postArrowPolicy) { slbExpireFt => + val slbExpire = slbExpireFt.left + val onArrowPolicy = Policy.End == arrow ==> + Policy.after(postArrow, "CASESLB>ARROW") { case Decision(_, ss) => + ss.flatMap { s => + val nonSlbSplit = s.andPolicy(postArrowPolicy) + if (s.isNL) Seq(nonSlbSplit) + else Seq(s.withSingleLine(slbExpire, extend = true), nonSlbSplit) + } + } + Policy.RelayOnSplit((s, _) => s.isNL)(onArrowPolicy, postArrowPolicy) + } + Seq(Split(mod, 0, policy = policy)) case FormatToken(_, cond: T.KwIf, _) if rightOwner.is[Case] => if (style.newlines.keepBreak(newlines)) Seq(Split(Newline, 0)) diff --git a/scalafmt-tests/src/test/resources/newlines/source_classic.stat b/scalafmt-tests/src/test/resources/newlines/source_classic.stat index 5baa06140b..c42246d8b4 100644 --- a/scalafmt-tests/src/test/resources/newlines/source_classic.stat +++ b/scalafmt-tests/src/test/resources/newlines/source_classic.stat @@ -3752,7 +3752,7 @@ object a { case None => Command.invalid } } -<<< ONLY complex match case triggering SLB precedence rule +<<< complex match case triggering SLB precedence rule object a { val breakpoints = (breaks.map { case Break(point) => diff --git a/scalafmt-tests/src/test/resources/newlines/source_fold.stat b/scalafmt-tests/src/test/resources/newlines/source_fold.stat index 0db6e902fc..f1d0a4976a 100644 --- a/scalafmt-tests/src/test/resources/newlines/source_fold.stat +++ b/scalafmt-tests/src/test/resources/newlines/source_fold.stat @@ -3437,7 +3437,7 @@ object a { case None => Command.invalid } } -<<< ONLY complex match case triggering SLB precedence rule +<<< complex match case triggering SLB precedence rule object a { val breakpoints = (breaks.map { case Break(point) => diff --git a/scalafmt-tests/src/test/resources/newlines/source_keep.stat b/scalafmt-tests/src/test/resources/newlines/source_keep.stat index d798944958..bd3ffb418d 100644 --- a/scalafmt-tests/src/test/resources/newlines/source_keep.stat +++ b/scalafmt-tests/src/test/resources/newlines/source_keep.stat @@ -3556,7 +3556,7 @@ object a { case None => Command.invalid } } -<<< ONLY complex match case triggering SLB precedence rule +<<< complex match case triggering SLB precedence rule object a { val breakpoints = (breaks.map { case Break(point) => diff --git a/scalafmt-tests/src/test/resources/newlines/source_unfold.stat b/scalafmt-tests/src/test/resources/newlines/source_unfold.stat index 87dc8bbcba..fbd3f8b25f 100644 --- a/scalafmt-tests/src/test/resources/newlines/source_unfold.stat +++ b/scalafmt-tests/src/test/resources/newlines/source_unfold.stat @@ -3701,7 +3701,7 @@ object a { Command.invalid } } -<<< ONLY complex match case triggering SLB precedence rule +<<< complex match case triggering SLB precedence rule object a { val breakpoints = (breaks.map { case Break(point) => @@ -3713,17 +3713,18 @@ object a { }).mkString("\n\n") } >>> -BestFirstSearch:289 Failed to format -UNABLE TO FORMAT, -tok #17/52: =>∙s: RightArrow [69..71) [LF] Interpolation.Id(s) [82..83) -policies: - NA:[Router:2096]>71d - (NB:[Router:229]@280d & NA:[Router:300]>71d) - SLB:[Router:2063]@281!d - NB:[Router:229]@300d -splits (before policy): - Newline:[Router:517](cost=0, indents=[], NoPolicy) -splits (after policy): +object a { + val breakpoints = + ( + breaks.map { case Break(point) => + s"""|send "stop at $MainObject$$:$point\\r" + |sleep $CommandWait + |expect "breakpoint $MainObject$$:$point" + |expect -re $$ + """.stripMargin + } + ).mkString("\n\n") +} <<< #2137 pubSubMessage match { case message: IngestionMessage => (