From 40a830ab69855d052f16fc4457a5e5dc8892001e Mon Sep 17 00:00:00 2001 From: Matt Dziuban Date: Mon, 7 Oct 2024 17:08:02 -0400 Subject: [PATCH] Fix bug that adds `using` incorrectly. --- .../main/scala-3/fix/GivenAndUsingTest.scala | 5 ++++ .../main/scala-3/fix/GivenAndUsingTest.scala | 5 ++++ rules/src/main/scala/fix/GivenAndUsing.scala | 25 +++++++++-------- .../fix/matchers/ImplicitOrUsingMod.scala | 27 +++++++++++++++++++ 4 files changed, 49 insertions(+), 13 deletions(-) create mode 100644 rules/src/main/scala/fix/matchers/ImplicitOrUsingMod.scala diff --git a/input/src/main/scala-3/fix/GivenAndUsingTest.scala b/input/src/main/scala-3/fix/GivenAndUsingTest.scala index 925cbe7..8cef137 100644 --- a/input/src/main/scala-3/fix/GivenAndUsingTest.scala +++ b/input/src/main/scala-3/fix/GivenAndUsingTest.scala @@ -81,4 +81,9 @@ object WithExplicitUsing { def test(using i: Int): Int = i test(using 1) } +object WithApplyAfterUsing { + given i: Int = 1 + def test(using i: Int): String => String = s => s + test("") +} // format: on diff --git a/output/src/main/scala-3/fix/GivenAndUsingTest.scala b/output/src/main/scala-3/fix/GivenAndUsingTest.scala index 23c12c5..ce7a886 100644 --- a/output/src/main/scala-3/fix/GivenAndUsingTest.scala +++ b/output/src/main/scala-3/fix/GivenAndUsingTest.scala @@ -65,4 +65,9 @@ object WithExplicitUsing { def test(using i: Int): Int = i test(using 1) } +object WithApplyAfterUsing { + given i: Int = 1 + def test(using i: Int): String => String = s => s + test("") +} // format: on diff --git a/rules/src/main/scala/fix/GivenAndUsing.scala b/rules/src/main/scala/fix/GivenAndUsing.scala index 8265a68..90a7c53 100644 --- a/rules/src/main/scala/fix/GivenAndUsing.scala +++ b/rules/src/main/scala/fix/GivenAndUsing.scala @@ -16,7 +16,7 @@ package fix -import fix.matchers.ApplyImplicitArgs +import fix.matchers.{ApplyImplicitArgs, ImplicitOrUsingMod} import scalafix.lint.LintSeverity import scalafix.v1._ @@ -59,25 +59,24 @@ class GivenAndUsing extends SemanticRule("GivenAndUsing") { } private def onlyImplicitOrUsingParams(d: Defn.Def): Boolean = - d.paramClauseGroups.forall(_.paramClauses.forall(_.mod.exists(m => m.is[Mod.Implicit] || m.is[Mod.Using]))) + d.paramClauseGroups.forall(_.paramClauses.forall(_.mod.exists { + case ImplicitOrUsingMod(_) => true + case _ => false + })) private def replaceWithUsing(paramss: List[List[Term.Param]])(implicit doc: SemanticDocument): List[APatch] = { val usingPatch = paramss.reverse.flatten - .collectFirst { - case p: Term.Param if p.mods.exists(mod => mod.is[Mod.Implicit] || mod.is[Mod.Using]) => - val pp = p.mods - .find(_.is[Mod.Implicit]) - .toList - .flatMap(_.tokens) - .headOption + .collectFirst { case p @ ImplicitOrUsingMod(mod) => + if (mod.is[Mod.Using]) + APatch.Empty + else { + val pp = mod.tokens.headOption .map(t => Patch.replaceToken(t, "using")) .asPatch APatch.Using(pp, p.symbol.owner) + } } - val lintPatchers = paramss.flatMap(_.collectFirst { - case p: Term.Param if p.mods.exists(mod => mod.is[Mod.Implicit] || mod.is[Mod.Using]) => - p.mods.find(mod => mod.is[Mod.Implicit] || mod.is[Mod.Using]) - }.toList.flatten) match { + val lintPatchers = paramss.flatMap(_.collectFirst { case ImplicitOrUsingMod(mod) => mod }.toList) match { case Nil => List.empty case _ :: Nil => List.empty case other => diff --git a/rules/src/main/scala/fix/matchers/ImplicitOrUsingMod.scala b/rules/src/main/scala/fix/matchers/ImplicitOrUsingMod.scala new file mode 100644 index 0000000..9b8c4a0 --- /dev/null +++ b/rules/src/main/scala/fix/matchers/ImplicitOrUsingMod.scala @@ -0,0 +1,27 @@ +/* + * Copyright 2022 Arktekk + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package fix.matchers + +import scala.meta._ + +object ImplicitOrUsingMod { + def unapply(mod: Mod): Option[Mod] = + if (mod.is[Mod.Implicit] || mod.is[Mod.Using]) Some(mod) else None + + def unapply(param: Term.Param): Option[Mod] = + param.mods.collectFirst { case ImplicitOrUsingMod(mod) => mod } +}