diff --git a/docs/configuration.md b/docs/configuration.md index cc4221c56c..361a725ed8 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -216,9 +216,9 @@ top-level. neverBeforeJsNative = true sometimesBeforeColonInMethodReturnType = false } - runner.optimizer { - forceConfigStyleMinSpan = 500 - forceConfigStyleMinArgCount = 5 + runner.optimizer.callSite { + minSpan = 500 + minCount = 5 } ``` @@ -2822,7 +2822,7 @@ object a { ### Forcing config style When `newlines.configStyleXxxSite.forceIfOptimized` is enabled and -[call-site clause optimization](#route-search-optimizations-call-site-clause) +[route search optimization](#route-search-optimizations-arg-or-param-clause) is applicable to a clause, the formatter will force config-style formatting. By default, takes the same value as @@ -2831,8 +2831,7 @@ By default, takes the same value as ```scala mdoc:scalafmt newlines.configStyleCallSite.forceIfOptimized = true newlines.configStyleDefnSite.forceIfOptimized = false -runner.optimizer.forceConfigStyleMinSpan = 5 -runner.optimizer.forceConfigStyleMinArgCount = 2 +runner.optimizer.callSite { minSpan = 5, minCount = 2 } maxColumn = 60 --- object a { @@ -5357,24 +5356,25 @@ and this optimization is enabled when: runner.optimizer.dequeueOnNewStatements ``` -#### Route search optimizations: call-site clause +#### Route search optimizations: arg or param clause Similar to statements above, we might create a new priority queue when we -encounter a long-enough call-site clause. +encounter a long-enough call-site argument or defn-site parameter clause. ```scala mdoc:defaults -runner.optimizer.forceConfigStyleMinSpan -runner.optimizer.forceConfigStyleMinArgCount +runner.optimizer.callSite +runner.optimizer.defnSite ``` This optimization is enabled when all these criteria are satisfied: -- `runner.optimizer.forceConfigStyleMinSpan`: +- `xxxSite.minSpan`: must be non-negative, and the character distance between the matching parentheses, excluding any whitespace, must exceed this value (prior to v3.8.1, this parameter was called `forceConfigStyleOnOffset`) -- `runner.optimizer.forceConfigStyleMinArgCount`: +- `xxxSite.minCount`: must be positive and may not exceed the number of arguments + (prior to v3.8.2, this parameter was called `forceConfigStyleMinCount`) > These parameters cannot be [overridden within a file](#for-code-block) diff --git a/scalafmt-core/shared/src/main/scala/org/scalafmt/config/ScalafmtOptimizer.scala b/scalafmt-core/shared/src/main/scala/org/scalafmt/config/ScalafmtOptimizer.scala index 963cb3ab28..b52d4c0de2 100644 --- a/scalafmt-core/shared/src/main/scala/org/scalafmt/config/ScalafmtOptimizer.scala +++ b/scalafmt-core/shared/src/main/scala/org/scalafmt/config/ScalafmtOptimizer.scala @@ -51,18 +51,32 @@ case class ScalafmtOptimizer( disableOptimizationsInsideSensitiveAreas: Boolean = true, pruneSlowStates: Boolean = true, recurseOnBlocks: Boolean = true, - @annotation.ExtraName("forceConfigStyleOnOffset") - forceConfigStyleMinSpan: Int = 150, - forceConfigStyleMinArgCount: Int = 2, + @annotation.ExtraName("forceConfigStyleOnOffset") @annotation.DeprecatedName( + "forceConfigStyleMinSpan", + "Use `callSite.minSpan` instead", + "3.8.2", + ) + private val forceConfigStyleMinSpan: Int = 150, + @annotation.DeprecatedName( + "forceConfigStyleMinArgCount", + "Use `callSite.minCount` instead", + "3.8.2", + ) + private val forceConfigStyleMinArgCount: Int = 2, + private val callSite: Option[ClauseElement] = None, + private val defnSite: ClauseElement = ClauseElement.default, ) { - def getCallSite: ClauseElement = ClauseElement( + def getCallSite: ClauseElement = callSite.getOrElse(ClauseElement( minSpan = forceConfigStyleMinSpan, minCount = forceConfigStyleMinArgCount, - ) + )) + def getDefnSite: ClauseElement = defnSite - private[config] def conservative: ScalafmtOptimizer = + private[config] def conservative: ScalafmtOptimizer = { // The tests were not written in this style - copy(forceConfigStyleMinSpan = 500, forceConfigStyleMinArgCount = 5) + val cfg = ClauseElement(minSpan = 500, minCount = 5) + copy(callSite = Some(cfg), defnSite = cfg) + } } @@ -89,4 +103,12 @@ object ScalafmtOptimizer { val isEnabled: Boolean = minSpan >= 0 && minCount > 0 } + private[config] object ClauseElement { + val default = ClauseElement() + implicit val surface: generic.Surface[ClauseElement] = generic + .deriveSurface[ClauseElement] + implicit val codec: ConfCodecEx[ClauseElement] = generic + .deriveCodecEx(default).noTypos + } + } 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 6717f27b16..52a972f798 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 @@ -1033,12 +1033,13 @@ class FormatOps( def getForceConfigStyle: (Set[Int], Set[Int]) = { val callSite = initStyle.runner.optimizer.getCallSite - if (callSite.isEnabled) { + val defnSite = initStyle.runner.optimizer.getDefnSite + if (callSite.isEnabled || defnSite.isEnabled) { val clearQueues = Set.newBuilder[Int] val forces = Set.newBuilder[Int] def process(clause: Member.SyntaxValuesClause, ftOpen: FormatToken)( cfg: ScalafmtOptimizer.ClauseElement, - ): Unit = matchingOpt(ftOpen.left).foreach { close => + ): Unit = if (cfg.isEnabled) matchingOpt(ftOpen.left).foreach { close => val values = clause.values if ( values.lengthCompare(cfg.minCount) >= 0 && @@ -1052,10 +1053,13 @@ class FormatOps( case ft @ FormatToken(_: T.LeftParen, _, m) => m.leftOwner match { case t: Term.ArgClause if !t.parent.exists(_.is[Term.ApplyInfix]) => process(t, ft)(callSite) + case t: Term.ParamClause => process(t, ft)(defnSite) case _ => } case ft @ FormatToken(_: T.LeftBracket, _, m) => m.leftOwner match { case t: Type.ArgClause => process(t, ft)(callSite) + case t: Type.ParamClause => process(t, ft)(defnSite) + case t: Type.FuncParamClause => process(t, ft)(defnSite) case _ => } case _ => diff --git a/scalafmt-tests/src/test/resources/newlines/source_classic.stat b/scalafmt-tests/src/test/resources/newlines/source_classic.stat index 18d4edd641..a8ac545e22 100644 --- a/scalafmt-tests/src/test/resources/newlines/source_classic.stat +++ b/scalafmt-tests/src/test/resources/newlines/source_classic.stat @@ -7608,7 +7608,7 @@ newlines.configStyleCallSite.prefer = true danglingParentheses.callSite = true binPack.unsafeCallSite = always maxColumn = 30 -runner.optimizer.forceConfigStyleMinSpan = 20 +runner.optimizer.callSite { minSpan = 20, minCount = 5 } === object Main { val bar1 = foo1( @@ -7660,7 +7660,7 @@ newlines.configStyleDefnSite.prefer = true danglingParentheses.defnSite = true binPack.unsafeDefnSite = always maxColumn = 30 -runner.optimizer.forceConfigStyleMinSpan = 20 +runner.optimizer.defnSite { minSpan = 20, minCount = 5 } === object Main { def foo1( @@ -7698,16 +7698,17 @@ object Main { x1: X, x2: X, x3: X, x4: X, xs: X* ): Set[Int] - def foo3(x1: X, x2: X, - x3: X, x4: X, xs: X*) - : Set[Int] + def foo3( + x1: X, x2: X, x3: X, + x4: X, xs: X* + ): Set[Int] } <<< binPack.callSite with !configStyle, danglingParentheses newlines.configStyleCallSite.prefer = false danglingParentheses.callSite = true binPack.unsafeCallSite = always maxColumn = 30 -runner.optimizer.forceConfigStyleMinSpan = 20 +runner.optimizer.callSite { minSpan = 20, minCount = 5 } === object Main { val bar1 = foo1( @@ -7751,7 +7752,7 @@ newlines.configStyleDefnSite.prefer = false danglingParentheses.defnSite = true binPack.unsafeDefnSite = always maxColumn = 30 -runner.optimizer.forceConfigStyleMinSpan = 20 +runner.optimizer.defnSite { minSpan = 20, minCount = 5 } === object Main { def foo1( @@ -7802,7 +7803,7 @@ newlines.configStyleCallSite.prefer = true danglingParentheses.callSite = false binPack.unsafeCallSite = always maxColumn = 30 -runner.optimizer.forceConfigStyleMinSpan = 20 +runner.optimizer.callSite { minSpan = 20, minCount = 5 } === object Main { val bar1 = foo1( @@ -7854,7 +7855,7 @@ newlines.configStyleDefnSite.prefer = true danglingParentheses.defnSite = false binPack.unsafeDefnSite = always maxColumn = 30 -runner.optimizer.forceConfigStyleMinSpan = 20 +runner.optimizer.defnSite { minSpan = 20, minCount = 5 } === object Main { def foo1( @@ -7892,16 +7893,17 @@ object Main { x1: X, x2: X, x3: X, x4: X, xs: X* ): Set[Int] - def foo3(x1: X, x2: X, - x3: X, x4: X, xs: X*) - : Set[Int] + def foo3( + x1: X, x2: X, x3: X, + x4: X, xs: X* + ): Set[Int] } <<< binPack.callSite with !configStyle, !danglingParentheses newlines.configStyleCallSite.prefer = false danglingParentheses.callSite = false binPack.unsafeCallSite = always maxColumn = 30 -runner.optimizer.forceConfigStyleMinSpan = 20 +runner.optimizer.callSite { minSpan = 20, minCount = 5 } === object Main { val bar1 = foo1( @@ -7939,7 +7941,7 @@ newlines.configStyleDefnSite.prefer = false danglingParentheses.defnSite = false binPack.unsafeDefnSite = always maxColumn = 30 -runner.optimizer.forceConfigStyleMinSpan = 20 +runner.optimizer.defnSite { minSpan = 20, minCount = 5 } === object Main { def foo1( diff --git a/scalafmt-tests/src/test/resources/newlines/source_fold.stat b/scalafmt-tests/src/test/resources/newlines/source_fold.stat index 5806244fa9..993f8447c6 100644 --- a/scalafmt-tests/src/test/resources/newlines/source_fold.stat +++ b/scalafmt-tests/src/test/resources/newlines/source_fold.stat @@ -7138,7 +7138,7 @@ newlines.configStyleCallSite.prefer = true danglingParentheses.callSite = true binPack.unsafeCallSite = always maxColumn = 30 -runner.optimizer.forceConfigStyleMinSpan = 20 +runner.optimizer.callSite { minSpan = 20, minCount = 5 } === object Main { val bar1 = foo1( @@ -7187,7 +7187,7 @@ newlines.configStyleDefnSite.prefer = true danglingParentheses.defnSite = true binPack.unsafeDefnSite = always maxColumn = 30 -runner.optimizer.forceConfigStyleMinSpan = 20 +runner.optimizer.defnSite { minSpan = 20, minCount = 5 } === object Main { def foo1( @@ -7238,7 +7238,7 @@ newlines.configStyleCallSite.prefer = false danglingParentheses.callSite = true binPack.unsafeCallSite = always maxColumn = 30 -runner.optimizer.forceConfigStyleMinSpan = 20 +runner.optimizer.callSite { minSpan = 20, minCount = 5 } === object Main { val bar1 = foo1( @@ -7278,7 +7278,7 @@ newlines.configStyleDefnSite.prefer = false danglingParentheses.defnSite = true binPack.unsafeDefnSite = always maxColumn = 30 -runner.optimizer.forceConfigStyleMinSpan = 20 +runner.optimizer.defnSite { minSpan = 20, minCount = 5 } === object Main { def foo1( @@ -7329,7 +7329,7 @@ newlines.configStyleCallSite.prefer = true danglingParentheses.callSite = false binPack.unsafeCallSite = always maxColumn = 30 -runner.optimizer.forceConfigStyleMinSpan = 20 +runner.optimizer.callSite { minSpan = 20, minCount = 5 } === object Main { val bar1 = foo1( @@ -7378,7 +7378,7 @@ newlines.configStyleDefnSite.prefer = true danglingParentheses.defnSite = false binPack.unsafeDefnSite = always maxColumn = 30 -runner.optimizer.forceConfigStyleMinSpan = 20 +runner.optimizer.defnSite { minSpan = 20, minCount = 5 } === object Main { def foo1( @@ -7411,19 +7411,21 @@ object Main { xs: X*): Set[Int] def foo1(x1: X, x2: X, xs: X*): Set[Int] - def foo2(x1: X, x2: X, - x3: X, x4: X, xs: X*) - : Set[Int] - def foo3(x1: X, x2: X, - x3: X, x4: X, xs: X*) - : Set[Int] + def foo2( + x1: X, x2: X, x3: X, + x4: X, xs: X* + ): Set[Int] + def foo3( + x1: X, x2: X, x3: X, + x4: X, xs: X* + ): Set[Int] } <<< binPack.callSite with !configStyle, !danglingParentheses newlines.configStyleCallSite.prefer = false danglingParentheses.callSite = false binPack.unsafeCallSite = always maxColumn = 30 -runner.optimizer.forceConfigStyleMinSpan = 20 +runner.optimizer.callSite { minSpan = 20, minCount = 5 } === object Main { val bar1 = foo1( @@ -7462,7 +7464,7 @@ newlines.configStyleDefnSite.prefer = false danglingParentheses.defnSite = false binPack.unsafeDefnSite = always maxColumn = 30 -runner.optimizer.forceConfigStyleMinSpan = 20 +runner.optimizer.defnSite { minSpan = 20, minCount = 5 } === object Main { def foo1( diff --git a/scalafmt-tests/src/test/resources/newlines/source_keep.stat b/scalafmt-tests/src/test/resources/newlines/source_keep.stat index fa6cf7f62a..678ac743ca 100644 --- a/scalafmt-tests/src/test/resources/newlines/source_keep.stat +++ b/scalafmt-tests/src/test/resources/newlines/source_keep.stat @@ -7551,7 +7551,7 @@ newlines.configStyleCallSite.prefer = true danglingParentheses.callSite = true binPack.unsafeCallSite = always maxColumn = 30 -runner.optimizer.forceConfigStyleMinSpan = 20 +runner.optimizer.callSite { minSpan = 20, minCount = 5 } === object Main { val bar1 = foo1( @@ -7603,7 +7603,7 @@ newlines.configStyleDefnSite.prefer = true danglingParentheses.defnSite = true binPack.unsafeDefnSite = always maxColumn = 30 -runner.optimizer.forceConfigStyleMinSpan = 20 +runner.optimizer.defnSite { minSpan = 20, minCount = 5 } === object Main { def foo1( @@ -7645,14 +7645,15 @@ object Main { ): Set[Int] def foo3( x1: X, x2: X, x3: X, - x4: X, xs: X*): Set[Int] + x4: X, xs: X* + ): Set[Int] } <<< binPack.callSite with !configStyle, danglingParentheses newlines.configStyleCallSite.prefer = false danglingParentheses.callSite = true binPack.unsafeCallSite = always maxColumn = 30 -runner.optimizer.forceConfigStyleMinSpan = 20 +runner.optimizer.callSite { minSpan = 20, minCount = 5 } === object Main { val bar1 = foo1( @@ -7697,7 +7698,7 @@ newlines.configStyleDefnSite.prefer = false danglingParentheses.defnSite = true binPack.unsafeDefnSite = always maxColumn = 30 -runner.optimizer.forceConfigStyleMinSpan = 20 +runner.optimizer.defnSite { minSpan = 20, minCount = 5 } === object Main { def foo1( @@ -7752,7 +7753,7 @@ newlines.configStyleCallSite.prefer = true danglingParentheses.callSite = false binPack.unsafeCallSite = always maxColumn = 30 -runner.optimizer.forceConfigStyleMinSpan = 20 +runner.optimizer.callSite { minSpan = 20, minCount = 5 } === object Main { val bar1 = foo1( @@ -7804,7 +7805,7 @@ newlines.configStyleDefnSite.prefer = true danglingParentheses.defnSite = false binPack.unsafeDefnSite = always maxColumn = 30 -runner.optimizer.forceConfigStyleMinSpan = 20 +runner.optimizer.defnSite { minSpan = 20, minCount = 5 } === object Main { def foo1( @@ -7846,14 +7847,15 @@ object Main { ): Set[Int] def foo3( x1: X, x2: X, x3: X, - x4: X, xs: X*): Set[Int] + x4: X, xs: X* + ): Set[Int] } <<< binPack.callSite with !configStyle, !danglingParentheses newlines.configStyleCallSite.prefer = false danglingParentheses.callSite = false binPack.unsafeCallSite = always maxColumn = 30 -runner.optimizer.forceConfigStyleMinSpan = 20 +runner.optimizer.callSite { minSpan = 20, minCount = 5 } === object Main { val bar1 = foo1( @@ -7895,7 +7897,7 @@ newlines.configStyleDefnSite.prefer = false danglingParentheses.defnSite = false binPack.unsafeDefnSite = always maxColumn = 30 -runner.optimizer.forceConfigStyleMinSpan = 20 +runner.optimizer.defnSite { minSpan = 20, minCount = 5 } === object Main { def foo1( diff --git a/scalafmt-tests/src/test/resources/newlines/source_unfold.stat b/scalafmt-tests/src/test/resources/newlines/source_unfold.stat index b9042e30be..dba65eddd8 100644 --- a/scalafmt-tests/src/test/resources/newlines/source_unfold.stat +++ b/scalafmt-tests/src/test/resources/newlines/source_unfold.stat @@ -7715,7 +7715,7 @@ newlines.configStyleCallSite.prefer = true danglingParentheses.callSite = true binPack.unsafeCallSite = always maxColumn = 30 -runner.optimizer.forceConfigStyleMinSpan = 20 +runner.optimizer.callSite { minSpan = 20, minCount = 5 } === object Main { val bar1 = foo1( @@ -7768,7 +7768,7 @@ newlines.configStyleDefnSite.prefer = true danglingParentheses.defnSite = true binPack.unsafeDefnSite = always maxColumn = 30 -runner.optimizer.forceConfigStyleMinSpan = 20 +runner.optimizer.defnSite { minSpan = 20, minCount = 5 } === object Main { def foo1( @@ -7819,7 +7819,7 @@ newlines.configStyleCallSite.prefer = false danglingParentheses.callSite = true binPack.unsafeCallSite = always maxColumn = 30 -runner.optimizer.forceConfigStyleMinSpan = 20 +runner.optimizer.callSite { minSpan = 20, minCount = 5 } === object Main { val bar1 = foo1( @@ -7863,7 +7863,7 @@ newlines.configStyleDefnSite.prefer = false danglingParentheses.defnSite = true binPack.unsafeDefnSite = always maxColumn = 30 -runner.optimizer.forceConfigStyleMinSpan = 20 +runner.optimizer.defnSite { minSpan = 20, minCount = 5 } === object Main { def foo1( @@ -7914,7 +7914,7 @@ newlines.configStyleCallSite.prefer = true danglingParentheses.callSite = false binPack.unsafeCallSite = always maxColumn = 30 -runner.optimizer.forceConfigStyleMinSpan = 20 +runner.optimizer.callSite { minSpan = 20, minCount = 5 } === object Main { val bar1 = foo1( @@ -7963,7 +7963,7 @@ newlines.configStyleDefnSite.prefer = true danglingParentheses.defnSite = false binPack.unsafeDefnSite = always maxColumn = 30 -runner.optimizer.forceConfigStyleMinSpan = 20 +runner.optimizer.defnSite { minSpan = 20, minCount = 5 } === object Main { def foo1( @@ -8002,17 +8002,19 @@ object Main { : Set[Int] def foo2( x1: X, x2: X, x3: X, - x4: X, xs: X*): Set[Int] + x4: X, xs: X* + ): Set[Int] def foo3( x1: X, x2: X, x3: X, - x4: X, xs: X*): Set[Int] + x4: X, xs: X* + ): Set[Int] } <<< binPack.callSite with !configStyle, !danglingParentheses newlines.configStyleCallSite.prefer = false danglingParentheses.callSite = false binPack.unsafeCallSite = always maxColumn = 30 -runner.optimizer.forceConfigStyleMinSpan = 20 +runner.optimizer.callSite { minSpan = 20, minCount = 5 } === object Main { val bar1 = foo1( @@ -8051,7 +8053,7 @@ newlines.configStyleDefnSite.prefer = false danglingParentheses.defnSite = false binPack.unsafeDefnSite = always maxColumn = 30 -runner.optimizer.forceConfigStyleMinSpan = 20 +runner.optimizer.defnSite { minSpan = 20, minCount = 5 } === object Main { def foo1(