diff --git a/scalafix-rules/src/main/scala/scalafix/internal/rule/RedundantSyntax.scala b/scalafix-rules/src/main/scala/scalafix/internal/rule/RedundantSyntax.scala index d703e88c3..5bc311ba4 100644 --- a/scalafix-rules/src/main/scala/scalafix/internal/rule/RedundantSyntax.scala +++ b/scalafix-rules/src/main/scala/scalafix/internal/rule/RedundantSyntax.scala @@ -30,15 +30,29 @@ class RedundantSyntax(config: RedundantSyntaxConfig) finalTok :: TokenList(o.tokens).trailingSpaces(finalTok).toList } } - case interpolator @ Term.Interpolate( - Term.Name(p), - Lit.String(v) :: Nil, + case Term.Interpolate( + interpolator, + lit :: Nil, Nil ) - if config.stringInterpolator - && (p == "s" || p == "f" || (p == "raw" && !v.contains('\\'))) => - Patch.removeTokens(interpolator.prefix.tokens) + if config.stringInterpolator && + !mustKeepInterpolator(interpolator, lit) => + Patch.removeTokens(interpolator.tokens) } .map(_.atomic) .asPatch + + private def mustKeepInterpolator(interpolator: Tree, lit: Tree) = { + val escapedCharacter = lit.syntax.contains('\\') + // termInterpolate.syntax.contains("\"\"\"") does not work in scala 2.13 and scala 3 + // as the syntax uses single quotes even if the litteral was defined with triple quotes + val tripleQuotes = lit.pos.start - interpolator.pos.end == 3 + interpolator.syntax match { + case "s" | "f" => + escapedCharacter && tripleQuotes + case "raw" => + escapedCharacter && !tripleQuotes + case _ => true + } + } } diff --git a/scalafix-tests/input/src/main/scala-2.12/test/redundantSyntax/StringInterpolator.scala b/scalafix-tests/input/src/main/scala-2.12/test/redundantSyntax/StringInterpolator.scala new file mode 100644 index 000000000..897bd7754 --- /dev/null +++ b/scalafix-tests/input/src/main/scala-2.12/test/redundantSyntax/StringInterpolator.scala @@ -0,0 +1,44 @@ +/* +rules = RedundantSyntax +RedundantSyntax.stringInterpolator = true +*/ + +package test.redundantSyntax + +class StringInterpolator { + + val a = 42d + + var b = "" + b = "foo" + b = s"foo" + b = s"foo $a bar" + //b = s"my \"quoted\" string" does not compile as of 2.12.18 as https://github.com/scala/scala/pull/8830 was not backported + + b = """foo""" + b = + s"""foo + |bar""" + b = s"""my \"quoted\" string""" + b = s"""foo $a bar""" + b = s"""$a""" + + b = f"foo" + b = f"foo $a%2.2f" + b = f"foo \n bar" + + b = raw"foo $a \nbar" + b = raw"""foo\nbar\\""" + b = raw"foo\nbar\\" + b = raw"foo bar" + b = raw"a\*b\+" + + b = my"foo" + b = my"foo $a bar" + + b = s"foo" // scalafix:ok + + implicit class MyInterpolator(sc: StringContext) { + def my(subs: Any*): String = sc.toString + subs.mkString("") + } +} diff --git a/scalafix-tests/input/src/main/scala/test/redundantSyntax/StringInterpolator.scala b/scalafix-tests/input/src/main/scala-2.13/test/redundantSyntax/StringInterpolator.scala similarity index 84% rename from scalafix-tests/input/src/main/scala/test/redundantSyntax/StringInterpolator.scala rename to scalafix-tests/input/src/main/scala-2.13/test/redundantSyntax/StringInterpolator.scala index beabe6ab2..5b4828627 100644 --- a/scalafix-tests/input/src/main/scala/test/redundantSyntax/StringInterpolator.scala +++ b/scalafix-tests/input/src/main/scala-2.13/test/redundantSyntax/StringInterpolator.scala @@ -13,18 +13,22 @@ class StringInterpolator { b = "foo" b = s"foo" b = s"foo $a bar" + b = s"my \"quoted\" string" b = """foo""" b = s"""foo |bar""" + b = s"""my \"quoted\" string""" b = s"""foo $a bar""" b = s"""$a""" b = f"foo" b = f"foo $a%2.2f" + b = f"foo \n bar" b = raw"foo $a \nbar" + b = raw"""foo\nbar\\""" b = raw"foo\nbar\\" b = raw"foo bar" b = raw"a\*b\+" diff --git a/scalafix-tests/input/src/main/scala-3/test/redundantSyntax/StringInterpolator.scala b/scalafix-tests/input/src/main/scala-3/test/redundantSyntax/StringInterpolator.scala new file mode 100644 index 000000000..5b4828627 --- /dev/null +++ b/scalafix-tests/input/src/main/scala-3/test/redundantSyntax/StringInterpolator.scala @@ -0,0 +1,44 @@ +/* +rules = RedundantSyntax +RedundantSyntax.stringInterpolator = true +*/ + +package test.redundantSyntax + +class StringInterpolator { + + val a = 42d + + var b = "" + b = "foo" + b = s"foo" + b = s"foo $a bar" + b = s"my \"quoted\" string" + + b = """foo""" + b = + s"""foo + |bar""" + b = s"""my \"quoted\" string""" + b = s"""foo $a bar""" + b = s"""$a""" + + b = f"foo" + b = f"foo $a%2.2f" + b = f"foo \n bar" + + b = raw"foo $a \nbar" + b = raw"""foo\nbar\\""" + b = raw"foo\nbar\\" + b = raw"foo bar" + b = raw"a\*b\+" + + b = my"foo" + b = my"foo $a bar" + + b = s"foo" // scalafix:ok + + implicit class MyInterpolator(sc: StringContext) { + def my(subs: Any*): String = sc.toString + subs.mkString("") + } +} diff --git a/scalafix-tests/output/src/main/scala-2.12/test/redundantSyntax/StringInterpolator.scala b/scalafix-tests/output/src/main/scala-2.12/test/redundantSyntax/StringInterpolator.scala new file mode 100644 index 000000000..2b537c603 --- /dev/null +++ b/scalafix-tests/output/src/main/scala-2.12/test/redundantSyntax/StringInterpolator.scala @@ -0,0 +1,39 @@ +package test.redundantSyntax + +class StringInterpolator { + + val a = 42d + + var b = "" + b = "foo" + b = "foo" + b = s"foo $a bar" + //b = s"my \"quoted\" string" does not compile as of 2.12.18 as https://github.com/scala/scala/pull/8830 was not backported + + b = """foo""" + b = + """foo + |bar""" + b = s"""my \"quoted\" string""" + b = s"""foo $a bar""" + b = s"""$a""" + + b = "foo" + b = f"foo $a%2.2f" + b = "foo \n bar" + + b = raw"foo $a \nbar" + b = """foo\nbar\\""" + b = raw"foo\nbar\\" + b = "foo bar" + b = raw"a\*b\+" + + b = my"foo" + b = my"foo $a bar" + + b = s"foo" // scalafix:ok + + implicit class MyInterpolator(sc: StringContext) { + def my(subs: Any*): String = sc.toString + subs.mkString("") + } +} diff --git a/scalafix-tests/output/src/main/scala/test/redundantSyntax/StringInterpolator.scala b/scalafix-tests/output/src/main/scala-2.13/test/redundantSyntax/StringInterpolator.scala similarity index 83% rename from scalafix-tests/output/src/main/scala/test/redundantSyntax/StringInterpolator.scala rename to scalafix-tests/output/src/main/scala-2.13/test/redundantSyntax/StringInterpolator.scala index b4af54b07..3e381d24b 100644 --- a/scalafix-tests/output/src/main/scala/test/redundantSyntax/StringInterpolator.scala +++ b/scalafix-tests/output/src/main/scala-2.13/test/redundantSyntax/StringInterpolator.scala @@ -8,18 +8,22 @@ class StringInterpolator { b = "foo" b = "foo" b = s"foo $a bar" + b = "my \"quoted\" string" b = """foo""" b = """foo |bar""" + b = s"""my \"quoted\" string""" b = s"""foo $a bar""" b = s"""$a""" b = "foo" b = f"foo $a%2.2f" + b = "foo \n bar" b = raw"foo $a \nbar" + b = """foo\nbar\\""" b = raw"foo\nbar\\" b = "foo bar" b = raw"a\*b\+" diff --git a/scalafix-tests/output/src/main/scala-3/test/redundantSyntax/StringInterpolator.scala b/scalafix-tests/output/src/main/scala-3/test/redundantSyntax/StringInterpolator.scala new file mode 100644 index 000000000..3e381d24b --- /dev/null +++ b/scalafix-tests/output/src/main/scala-3/test/redundantSyntax/StringInterpolator.scala @@ -0,0 +1,39 @@ +package test.redundantSyntax + +class StringInterpolator { + + val a = 42d + + var b = "" + b = "foo" + b = "foo" + b = s"foo $a bar" + b = "my \"quoted\" string" + + b = """foo""" + b = + """foo + |bar""" + b = s"""my \"quoted\" string""" + b = s"""foo $a bar""" + b = s"""$a""" + + b = "foo" + b = f"foo $a%2.2f" + b = "foo \n bar" + + b = raw"foo $a \nbar" + b = """foo\nbar\\""" + b = raw"foo\nbar\\" + b = "foo bar" + b = raw"a\*b\+" + + b = my"foo" + b = my"foo $a bar" + + b = s"foo" // scalafix:ok + + implicit class MyInterpolator(sc: StringContext) { + def my(subs: Any*): String = sc.toString + subs.mkString("") + } +}