From 174773e07bf7992b714b6f46af5837f9b592dd5a Mon Sep 17 00:00:00 2001 From: Albert Meltzer <7529386+kitbellew@users.noreply.github.com> Date: Sat, 18 Jul 2020 22:38:46 -0700 Subject: [PATCH 1/4] Newlines: import symbols from companion object --- .../scala/org/scalafmt/config/Newlines.scala | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/scalafmt-core/shared/src/main/scala/org/scalafmt/config/Newlines.scala b/scalafmt-core/shared/src/main/scala/org/scalafmt/config/Newlines.scala index b879cd377d..87a3029c42 100644 --- a/scalafmt-core/shared/src/main/scala/org/scalafmt/config/Newlines.scala +++ b/scalafmt-core/shared/src/main/scala/org/scalafmt/config/Newlines.scala @@ -1,6 +1,6 @@ package org.scalafmt.config -import org.scalafmt.config.Newlines.AfterInfix +import org.scalafmt.config.Newlines._ import metaconfig._ import metaconfig.generic.Surface @@ -140,14 +140,14 @@ import metaconfig.generic.Surface * and would likely overflow even after a break */ case class Newlines( - source: Newlines.SourceHints = Newlines.classic, + source: SourceHints = Newlines.classic, neverInResultType: Boolean = false, neverBeforeJsNative: Boolean = false, sometimesBeforeColonInMethodReturnType: Boolean = true, penalizeSingleSelectMultiArgList: Boolean = true, alwaysBeforeCurlyBraceLambdaParams: Boolean = false, topLevelStatementsMinBreaks: Int = 1, - topLevelStatements: Seq[Newlines.BeforeAfter] = Seq.empty, + topLevelStatements: Seq[BeforeAfter] = Seq.empty, @annotation.DeprecatedName( "alwaysBeforeTopLevelStatements", "Use newlines.topLevelStatements instead", @@ -155,15 +155,15 @@ case class Newlines( ) alwaysBeforeTopLevelStatements: Boolean = false, afterCurlyLambda: NewlineCurlyLambda = NewlineCurlyLambda.never, - implicitParamListModifierForce: Seq[Newlines.BeforeAfter] = Seq.empty, - implicitParamListModifierPrefer: Option[Newlines.BeforeAfter] = None, + implicitParamListModifierForce: Seq[BeforeAfter] = Seq.empty, + implicitParamListModifierPrefer: Option[BeforeAfter] = None, alwaysBeforeElseAfterCurlyIf: Boolean = false, alwaysBeforeMultilineDef: Boolean = true, afterInfix: Option[AfterInfix] = None, afterInfixBreakOnNested: Boolean = false, afterInfixMaxCountPerExprForSome: Int = 10, afterInfixMaxCountPerFile: Int = 500, - avoidForSimpleOverflow: Seq[Newlines.AvoidForSimpleOverflow] = Seq.empty, + avoidForSimpleOverflow: Seq[AvoidForSimpleOverflow] = Seq.empty, avoidAfterYield: Boolean = true ) { if ( @@ -177,14 +177,14 @@ case class Newlines( } val reader: ConfDecoder[Newlines] = generic.deriveDecoder(this).noTypos - if (source != Newlines.classic) Newlines.warnSourceIsExperimental + if (source != Newlines.classic) warnSourceIsExperimental @inline - def sourceIs(hint: Newlines.SourceHints): Boolean = + def sourceIs(hint: SourceHints): Boolean = hint eq source @inline - def sourceIn(hints: Newlines.SourceHints*): Boolean = + def sourceIn(hints: SourceHints*): Boolean = hints.contains(source) val sourceIgnored: Boolean = @@ -210,12 +210,12 @@ case class Newlines( } lazy val forceBeforeImplicitParamListModifier: Boolean = - implicitParamListModifierForce.contains(Newlines.before) + implicitParamListModifierForce.contains(before) lazy val forceAfterImplicitParamListModifier: Boolean = - implicitParamListModifierForce.contains(Newlines.after) + implicitParamListModifierForce.contains(after) private def preferBeforeImplicitParamListModifier: Boolean = - implicitParamListModifierPrefer.contains(Newlines.before) + implicitParamListModifierPrefer.contains(before) lazy val notPreferAfterImplicitParamListModifier: Boolean = implicitParamListModifierForce.nonEmpty || preferBeforeImplicitParamListModifier @@ -226,15 +226,15 @@ case class Newlines( !forceBeforeImplicitParamListModifier lazy val forceBlankBeforeMultilineTopLevelStmt: Boolean = - topLevelStatements.contains(Newlines.before) || + topLevelStatements.contains(before) || alwaysBeforeTopLevelStatements lazy val forceBlankAfterMultilineTopLevelStmt: Boolean = - topLevelStatements.contains(Newlines.after) + topLevelStatements.contains(after) lazy val avoidForSimpleOverflowPunct: Boolean = - avoidForSimpleOverflow.contains(Newlines.AvoidForSimpleOverflow.punct) + avoidForSimpleOverflow.contains(AvoidForSimpleOverflow.punct) lazy val avoidForSimpleOverflowTooLong: Boolean = - avoidForSimpleOverflow.contains(Newlines.AvoidForSimpleOverflow.tooLong) + avoidForSimpleOverflow.contains(AvoidForSimpleOverflow.tooLong) } object Newlines { From 979b4c96f0ba31215142d90604aec4b3fb15902a Mon Sep 17 00:00:00 2001 From: Albert Meltzer <7529386+kitbellew@users.noreply.github.com> Date: Sun, 19 Jul 2020 08:32:47 -0700 Subject: [PATCH 2/4] Newlines: move AfterCurlyLambdaParams as nested --- .../scala/org/scalafmt/config/Newlines.scala | 23 ++++++++----------- .../org/scalafmt/config/ScalafmtConfig.scala | 3 ++- .../org/scalafmt/internal/FormatOps.scala | 16 ++++--------- .../scala/org/scalafmt/internal/Router.scala | 10 +++----- 4 files changed, 20 insertions(+), 32 deletions(-) diff --git a/scalafmt-core/shared/src/main/scala/org/scalafmt/config/Newlines.scala b/scalafmt-core/shared/src/main/scala/org/scalafmt/config/Newlines.scala index 87a3029c42..8edad59d12 100644 --- a/scalafmt-core/shared/src/main/scala/org/scalafmt/config/Newlines.scala +++ b/scalafmt-core/shared/src/main/scala/org/scalafmt/config/Newlines.scala @@ -154,7 +154,7 @@ case class Newlines( "2.5.0" ) alwaysBeforeTopLevelStatements: Boolean = false, - afterCurlyLambda: NewlineCurlyLambda = NewlineCurlyLambda.never, + afterCurlyLambda: AfterCurlyLambdaParams = AfterCurlyLambdaParams.never, implicitParamListModifierForce: Seq[BeforeAfter] = Seq.empty, implicitParamListModifierPrefer: Option[BeforeAfter] = None, alwaysBeforeElseAfterCurlyIf: Boolean = false, @@ -284,17 +284,14 @@ object Newlines { ReaderUtil.oneOf[AvoidForSimpleOverflow](punct, tooLong) } -} - -sealed abstract class NewlineCurlyLambda - -object NewlineCurlyLambda { - - case object preserve extends NewlineCurlyLambda - case object always extends NewlineCurlyLambda - case object never extends NewlineCurlyLambda - case object squash extends NewlineCurlyLambda + sealed abstract class AfterCurlyLambdaParams + object AfterCurlyLambdaParams { + case object preserve extends AfterCurlyLambdaParams + case object always extends AfterCurlyLambdaParams + case object never extends AfterCurlyLambdaParams + case object squash extends AfterCurlyLambdaParams + implicit val codec: ConfCodec[AfterCurlyLambdaParams] = + ReaderUtil.oneOf[AfterCurlyLambdaParams](preserve, always, never, squash) + } - implicit val newlineCurlyLambdaReader: ConfCodec[NewlineCurlyLambda] = - ReaderUtil.oneOf[NewlineCurlyLambda](preserve, always, never, squash) } diff --git a/scalafmt-core/shared/src/main/scala/org/scalafmt/config/ScalafmtConfig.scala b/scalafmt-core/shared/src/main/scala/org/scalafmt/config/ScalafmtConfig.scala index e7200c8fd1..f90db01944 100644 --- a/scalafmt-core/shared/src/main/scala/org/scalafmt/config/ScalafmtConfig.scala +++ b/scalafmt-core/shared/src/main/scala/org/scalafmt/config/ScalafmtConfig.scala @@ -160,12 +160,13 @@ case class ScalafmtConfig( xmlLiterals: XmlLiterals = XmlLiterals(), edition: Edition = Edition.Latest ) { + import Newlines._ val allErrors = new mutable.ArrayBuffer[String] locally { import ValidationOps._ implicit val errors = new mutable.ArrayBuffer[String] if (newlines.sourceIgnored) { - addIf(newlines.afterCurlyLambda == NewlineCurlyLambda.preserve) + addIf(newlines.afterCurlyLambda == AfterCurlyLambdaParams.preserve) addIf(optIn.configStyleArguments && align.openParenCallSite) addIf(optIn.configStyleArguments && align.openParenDefnSite) } diff --git a/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/FormatOps.scala b/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/FormatOps.scala index 1de69922c2..4c6a52f390 100644 --- a/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/FormatOps.scala +++ b/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/FormatOps.scala @@ -4,13 +4,7 @@ import java.{util => ju} import org.scalafmt.CompatCollections.JavaConverters._ import org.scalafmt.Error.UnexpectedTree -import org.scalafmt.config.{ - BinPack, - Comments, - NewlineCurlyLambda, - Newlines, - ScalafmtConfig -} +import org.scalafmt.config.{BinPack, Comments, Newlines, ScalafmtConfig} import org.scalafmt.internal.Length.Num import org.scalafmt.internal.Policy.NoPolicy import org.scalafmt.util._ @@ -1221,16 +1215,16 @@ class FormatOps( newlines: Int )(implicit style: ScalafmtConfig): (Boolean, NewlineT) = style.newlines.afterCurlyLambda match { - case NewlineCurlyLambda.squash => (true, Newline) - case NewlineCurlyLambda.never => + case Newlines.AfterCurlyLambdaParams.squash => (true, Newline) + case Newlines.AfterCurlyLambdaParams.never => val space = style.newlines.source match { case Newlines.fold => true case Newlines.unfold => false case _ => newlines == 0 } (space, Newline) - case NewlineCurlyLambda.always => (false, Newline2x) - case NewlineCurlyLambda.preserve => + case Newlines.AfterCurlyLambdaParams.always => (false, Newline2x) + case Newlines.AfterCurlyLambdaParams.preserve => (newlines == 0, if (newlines >= 2) Newline2x else Newline) } 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 91bf2e029e..a6028bca55 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 @@ -1,12 +1,7 @@ package org.scalafmt.internal import org.scalafmt.Error.UnexpectedTree -import org.scalafmt.config.{ - ImportSelectors, - NewlineCurlyLambda, - Newlines, - ScalafmtConfig -} +import org.scalafmt.config.{ImportSelectors, Newlines, ScalafmtConfig} import org.scalafmt.internal.ExpiresOn.{After, Before} import org.scalafmt.internal.Length.{Num, StateColumn} import org.scalafmt.internal.Policy.NoPolicy @@ -373,7 +368,8 @@ class Router(formatOps: FormatOps) { leftOwner.is[Template] || leftOwner.parent.exists(_.is[Template]) def noSquash = - style.newlines.afterCurlyLambda != NewlineCurlyLambda.squash + style.newlines.afterCurlyLambda ne + Newlines.AfterCurlyLambdaParams.squash isCurlyLambda && (style.newlines.source match { case Newlines.fold => false From e7738441b24fc95ac29707e958198c961807b5f7 Mon Sep 17 00:00:00 2001 From: Albert Meltzer <7529386+kitbellew@users.noreply.github.com> Date: Sun, 19 Jul 2020 08:24:50 -0700 Subject: [PATCH 3/4] FormatOps: afterCurlyLambda=preserve for [un]fold --- .../src/main/scala/org/scalafmt/internal/FormatOps.scala | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/FormatOps.scala b/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/FormatOps.scala index 4c6a52f390..65d9edbf7e 100644 --- a/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/FormatOps.scala +++ b/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/FormatOps.scala @@ -1225,7 +1225,12 @@ class FormatOps( (space, Newline) case Newlines.AfterCurlyLambdaParams.always => (false, Newline2x) case Newlines.AfterCurlyLambdaParams.preserve => - (newlines == 0, if (newlines >= 2) Newline2x else Newline) + val space = style.newlines.source match { + case Newlines.fold => true + case Newlines.unfold => false + case _ => newlines == 0 + } + (space, if (newlines >= 2) Newline2x else Newline) } def getNoSplit( From 431df4dea3c5d16b18ff1beba0609d840f3f353f Mon Sep 17 00:00:00 2001 From: Albert Meltzer <7529386+kitbellew@users.noreply.github.com> Date: Sun, 19 Jul 2020 08:23:33 -0700 Subject: [PATCH 4/4] Documentation: improve newlines.afterCurlyLambda --- docs/configuration.md | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/docs/configuration.md b/docs/configuration.md index 0507a15b4f..0c70b3d4a4 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -886,13 +886,20 @@ else { ### `newlines.afterCurlyLambda` +This parameter controls handling of newlines after the arrow following the +parameters of a curly brace lambda or partial function, and whether a space +can be used for one-line formatting of the entire function body (if allowed +but the body doesn't fit, a break is always forced). + ```scala mdoc:defaults newlines.afterCurlyLambda ``` ```scala mdoc:scalafmt -newlines.afterCurlyLambda = never +newlines.afterCurlyLambda = squash --- +// remove all blank lines if any +// one-line formatting is allowed something.map { x => @@ -904,8 +911,11 @@ something.map { x => f(x) } ``` ```scala mdoc:scalafmt -newlines.afterCurlyLambda = always +newlines.afterCurlyLambda = never --- +// remove all blank lines if any +// one-line formatting depends on newlines.source: +// yes for fold; no for unfold; otherwise, only if there was no break something.map { x => @@ -919,6 +929,9 @@ something.map { x => f(x) } ```scala mdoc:scalafmt newlines.afterCurlyLambda = preserve --- +// if blank lines are present, keep only one +// one-line formatting depends on newlines.source: +// yes for fold; no for unfold; otherwise, only if there was no break something.map { x => @@ -930,8 +943,10 @@ something.map { x => f(x) } ``` ```scala mdoc:scalafmt -newlines.afterCurlyLambda = squash +newlines.afterCurlyLambda = always --- +// ensure a single blank line +// one-line formatting is not allowed something.map { x =>