Repository: scala-steward-org/scala-steward
Pull request #1774 (2020-11-28 23:00:05)

Do not replace a substring in another version
This prevents updates like https://github.com/typelevel/cats-tagless/pull/177 where a substring of an unrelated version was replaced.


Patch:
diff --git a/modules/core/src/main/scala/org/scalasteward/core/edit/UpdateHeuristic.scala b/modules/core/src/main/scala/org/scalasteward/core/edit/UpdateHeuristic.scala
index 8822c473..45050cb2 100644
--- a/modules/core/src/main/scala/org/scalasteward/core/edit/UpdateHeuristic.scala
+++ b/modules/core/src/main/scala/org/scalasteward/core/edit/UpdateHeuristic.scala
@@ -97,9 +97,10 @@ object UpdateHeuristic {
             val group1 = match0.group(1)
             val group2 = match0.group(2)
             val lastGroup = match0.group(match0.groupCount)
-            val versionInQuotes =
-              group2.lastOption.filter(_ === '"').fold(true)(lastGroup.headOption.contains_)
-            if (shouldBeIgnored(group1) || !versionInQuotes) None
+            if (
+              shouldBeIgnored(group1) ||
+              !enclosingCharsDelimitVersion(group2.lastOption, lastGroup.headOption)
+            ) None
             else Some(Regex.quoteReplacement(group1 + group2 + update.nextVersion + lastGroup))
           }
         ).someIfChanged
@@ -108,6 +109,14 @@ object UpdateHeuristic {
     replaceF
   }
 
+  private def enclosingCharsDelimitVersion(before: Option[Char], after: Option[Char]): Boolean =
+    (before, after) match {
+      case (Some('"'), c2) => c2.contains_('"')
+      case (_, Some('"'))  => false
+
+      case _ => true
+    }
+
   private def searchTerms(update: Update): List[String] = {
     val terms = update match {
       case s: Update.Single => Nel.one(s.artifactId.name)


Test patch:
diff --git a/modules/core/src/test/scala/org/scalasteward/core/edit/UpdateHeuristicTest.scala b/modules/core/src/test/scala/org/scalasteward/core/edit/UpdateHeuristicTest.scala
index 7fa1f25f..aa519c6d 100644
--- a/modules/core/src/test/scala/org/scalasteward/core/edit/UpdateHeuristicTest.scala
+++ b/modules/core/src/test/scala/org/scalasteward/core/edit/UpdateHeuristicTest.scala
@@ -479,13 +479,26 @@ class UpdateHeuristicTest extends AnyFunSuite with Matchers {
       """ val jsoniter = "2.4.1"
         | addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.4.0")
         |""".stripMargin
-    Update
-      .Group(
-        "com.github.plokhotnyuk.jsoniter-scala" %
-          Nel.of("jsoniter-scala-core", "jsoniter-scala-macros") % "2.4.0",
-        Nel.of("2.4.1")
-      )
-      .replaceVersionIn(original) shouldBe (Some(expected) -> UpdateHeuristic.relaxed.name)
+    Group(
+      "com.github.plokhotnyuk.jsoniter-scala" %
+        Nel.of("jsoniter-scala-core", "jsoniter-scala-macros")
+        % "2.4.0",
+      Nel.of("2.4.1")
+    ).replaceVersionIn(original) shouldBe (Some(expected) -> UpdateHeuristic.relaxed.name)
+  }
+
+  test("missing enclosing quote before") {
+    val original =
+      """.add("scalatestplus", version = "3.2.2.0", org = "org.scalatestplus", "scalacheck-1-14")"""
+    Single("org.typelevel" % "cats-effect" % "2.2.0", Nel.of("2.3.0"))
+      .replaceVersionIn(original) shouldBe (None -> UpdateHeuristic.all.last.name)
+  }
+
+  test("missing enclosing quote after") {
+    val original =
+      """.add("scalatestplus", version = "2.2.0.3", org = "org.scalatestplus", "scalacheck-1-14")"""
+    Single("org.typelevel" % "cats-effect" % "2.2.0", Nel.of("2.3.0"))
+      .replaceVersionIn(original) shouldBe (None -> UpdateHeuristic.all.last.name)
   }
 }