From 61328980d5cd68f0537916f60dd7949d0d4be52b Mon Sep 17 00:00:00 2001 From: Albert Meltzer <7529386+kitbellew@users.noreply.github.com> Date: Mon, 27 Nov 2023 14:06:50 -0800 Subject: [PATCH] AvoidInfixSettings: consolidate AvoidInfix params --- docs/configuration.md | 19 ++++++++++------- ...Pattern.scala => AvoidInfixSettings.scala} | 21 ++++++++++--------- .../org/scalafmt/config/RewriteSettings.scala | 15 ++++++++++--- .../org/scalafmt/rewrite/AvoidInfix.scala | 6 +++--- .../test/resources/rewrite/AvoidInfix.stat | 8 +++---- 5 files changed, 42 insertions(+), 27 deletions(-) rename scalafmt-core/shared/src/main/scala/org/scalafmt/config/{NeverInfixPattern.scala => AvoidInfixSettings.scala} (78%) diff --git a/docs/configuration.md b/docs/configuration.md index b3b7a2861d..e71e798b11 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -2852,22 +2852,27 @@ This rule replaces infix expressions `a op b` with proper method calls `a.op(b)` > NB: The rule currently does not support right-associative operators (i.e., > those which end in `:`) which would have had to be rewritten as `b.op(a)`. -The rule takes the following parameters: +The rule takes the following parameters under `rewrite.avoidInfix`: -- `rewrite.neverInfix` parameter group which consists of `includeFilters` and `excludeFilters`, - two lists of regular expressions, which determine which operators are eligible for this rewrite - - (since 3.7.18) if a regular expression contains `\\.`, matching will be against +- `includeFilters` and `excludeFilters`, two lists of regular expressions, which + determine which operators are eligible for this rewrite + - for this rule to be enabled (that is, for the rewrite to be applied), an infix + expression must match `includeFilters` and not match `excludeFilters` + - (since 3.8.0) if a regular expression contains `\\.`, matching will be against not only the infix operator but also its left-hand-side expression (with the non-empty operator part following the last `\\.` in the pattern) -- (since 3.4.4) `rewrite.allowInfixPlaceholderArg` (default: `true`) will not rewrite infix + - (before 3.8.0) these two parameters were nested under `rewrite.neverInfix` +- `excludePlaceholderArg` (default: `true`) will not rewrite infix expressions if the argument is a solo placeholder (`_` or `(_: Type)`) - this parameter does not control any other cases with the infix argument containing a placeholder character; some of them will never be rewritten as adding parentheses will change their syntactic meaning, and others will be rewritten as usual + - (before 3.8.0 and since 3.4.4) this parameter was named + `rewrite.allowInfixPlaceholderArg` ```scala mdoc:scalafmt rewrite.rules = [AvoidInfix] -rewrite.neverInfix.excludeFilters."+" = [ "map" ] +rewrite.avoidInfix.excludeFilters."+" = [ "map" ] --- a success b a error (b, c) @@ -2885,7 +2890,7 @@ future recover { ```scala mdoc:scalafmt rewrite.rules = [AvoidInfix] -rewrite.allowInfixPlaceholderArg = false +rewrite.avoidInfix.excludePlaceholderArg = false --- _ foo _ _ bar (_: Int) diff --git a/scalafmt-core/shared/src/main/scala/org/scalafmt/config/NeverInfixPattern.scala b/scalafmt-core/shared/src/main/scala/org/scalafmt/config/AvoidInfixSettings.scala similarity index 78% rename from scalafmt-core/shared/src/main/scala/org/scalafmt/config/NeverInfixPattern.scala rename to scalafmt-core/shared/src/main/scala/org/scalafmt/config/AvoidInfixSettings.scala index 4e227caf6d..d64035aa3a 100644 --- a/scalafmt-core/shared/src/main/scala/org/scalafmt/config/NeverInfixPattern.scala +++ b/scalafmt-core/shared/src/main/scala/org/scalafmt/config/AvoidInfixSettings.scala @@ -5,21 +5,22 @@ import metaconfig.generic.Surface import java.util.regex.{Matcher, Pattern} -case class NeverInfixPattern( - private val includeFilters: Seq[NeverInfixPattern.Filter], // partial match - private val excludeFilters: Seq[NeverInfixPattern.Filter] // strict match +case class AvoidInfixSettings( + private val includeFilters: Seq[AvoidInfixSettings.Filter], // partial match + private val excludeFilters: Seq[AvoidInfixSettings.Filter], // strict match + excludePlaceholderArg: Option[Boolean] = None ) { - private[config] def forSbt: Option[NeverInfixPattern] = + private[config] def forSbt: Option[AvoidInfixSettings] = // if the user customized these, we don't touch - if (excludeFilters ne NeverInfixPattern.default.excludeFilters) None - else Some(copy(excludeFilters = NeverInfixPattern.sbtExclude)) + if (excludeFilters ne AvoidInfixSettings.default.excludeFilters) None + else Some(copy(excludeFilters = AvoidInfixSettings.sbtExclude)) def matches(lhs: String, op: String): Boolean = includeFilters.forall(_.matches(lhs, op)(_.find())) && !excludeFilters.exists(_.matches(lhs, op)(_.matches())) } -object NeverInfixPattern { +object AvoidInfixSettings { private[config] case class Filter( lhs: Option[Pattern], @@ -55,11 +56,11 @@ object NeverInfixPattern { def apply(value: String): Filter = parse(value).get } - implicit lazy val surface: Surface[NeverInfixPattern] = + implicit lazy val surface: Surface[AvoidInfixSettings] = generic.deriveSurface - implicit lazy val codec: ConfCodecEx[NeverInfixPattern] = + implicit lazy val codec: ConfCodecEx[AvoidInfixSettings] = generic.deriveCodecEx(default).noTypos - val default = NeverInfixPattern( + val default = AvoidInfixSettings( Seq("[\\w\\d_]+").map(Filter.apply), Seq( "until", diff --git a/scalafmt-core/shared/src/main/scala/org/scalafmt/config/RewriteSettings.scala b/scalafmt-core/shared/src/main/scala/org/scalafmt/config/RewriteSettings.scala index 1ab28bfb00..6c7f85048d 100644 --- a/scalafmt-core/shared/src/main/scala/org/scalafmt/config/RewriteSettings.scala +++ b/scalafmt-core/shared/src/main/scala/org/scalafmt/config/RewriteSettings.scala @@ -13,9 +13,18 @@ case class RewriteSettings( imports: Imports.Settings = Imports.Settings(), preferCurlyFors: PreferCurlyFors.Settings = PreferCurlyFors.Settings(), trailingCommas: TrailingCommas = TrailingCommas(), - allowInfixPlaceholderArg: Boolean = true, - neverInfix: NeverInfixPattern = NeverInfixPattern.default + @annotation.DeprecatedName( + "allowInfixPlaceholderArg", + "Use `avoidInfix.excludePlaceholderArg` instead", + "3.8.0" + ) + private val allowInfixPlaceholderArg: Boolean = true, + @annotation.ExtraName("neverInfix") + avoidInfix: AvoidInfixSettings = AvoidInfixSettings.default ) { + def isAllowInfixPlaceholderArg: Boolean = + avoidInfix.excludePlaceholderArg.getOrElse(allowInfixPlaceholderArg) + def withoutRewrites: RewriteSettings = copy(rules = Nil, trailingCommas = trailingCommas.withoutRewrites) @@ -33,7 +42,7 @@ case class RewriteSettings( } private[config] def forSbt: RewriteSettings = - neverInfix.forSbt.fold(this)(x => copy(neverInfix = x)) + avoidInfix.forSbt.fold(this)(x => copy(avoidInfix = x)) } object RewriteSettings { diff --git a/scalafmt-core/shared/src/main/scala/org/scalafmt/rewrite/AvoidInfix.scala b/scalafmt-core/shared/src/main/scala/org/scalafmt/rewrite/AvoidInfix.scala index d681b22efa..96161cd153 100644 --- a/scalafmt-core/shared/src/main/scala/org/scalafmt/rewrite/AvoidInfix.scala +++ b/scalafmt-core/shared/src/main/scala/org/scalafmt/rewrite/AvoidInfix.scala @@ -11,7 +11,7 @@ import org.scalafmt.util.InfixApp object AvoidInfix extends RewriteFactory { override def hasChanged(v1: RewriteSettings, v2: RewriteSettings): Boolean = - v2.neverInfix ne v1.neverInfix + v2.avoidInfix ne v1.avoidInfix override def create(implicit ctx: RewriteCtx): RewriteSession = new AvoidInfix @@ -20,7 +20,7 @@ object AvoidInfix extends RewriteFactory { class AvoidInfix(implicit ctx: RewriteCtx) extends RewriteSession { - private val matcher = ctx.style.rewrite.neverInfix + private val matcher = ctx.style.rewrite.avoidInfix // In a perfect world, we could just use // Tree.transform { @@ -88,7 +88,7 @@ class AvoidInfix(implicit ctx: RewriteCtx) extends RewriteSession { InfixApp.isLeftAssoc(op) && matcher.matches(lhs, op) && (ai.argClause match { case ac @ Term.ArgClause(arg :: Nil, _) if !isWrapped(ac) => - !hasPlaceholder(arg, ctx.style.rewrite.allowInfixPlaceholderArg) + !hasPlaceholder(arg, ctx.style.rewrite.isAllowInfixPlaceholderArg) case _ => true }) && (ai.lhs match { case lhs: Term.ApplyInfix if hasPlaceholder(lhs, true) => diff --git a/scalafmt-tests/src/test/resources/rewrite/AvoidInfix.stat b/scalafmt-tests/src/test/resources/rewrite/AvoidInfix.stat index 5bc2c84a68..992089d66a 100644 --- a/scalafmt-tests/src/test/resources/rewrite/AvoidInfix.stat +++ b/scalafmt-tests/src/test/resources/rewrite/AvoidInfix.stat @@ -145,8 +145,8 @@ object a { _.foo(bar).baz(qux) } <<< in lambda 2, !allowInfixPlaceholderArg -rewrite.allowInfixPlaceholderArg = false -rewrite.neverInfix { +rewrite.avoidInfix { + excludePlaceholderArg = false includeFilters = [ "[^*]+" ] excludeFilters = [] } @@ -219,8 +219,8 @@ object a { b.c(1./(2).+(3)) } <<< in lambda 2, allowInfixPlaceholderArg -rewrite.allowInfixPlaceholderArg = true -rewrite.neverInfix { +rewrite.avoidInfix { + excludePlaceholderArg = true includeFilters = [ "[^*]+" ] excludeFilters = [] }