diff --git a/core/src/main/scala/wartremover/warts/StringPlusAny.scala b/core/src/main/scala/wartremover/warts/StringPlusAny.scala index 44a61983..6a0dbc8a 100644 --- a/core/src/main/scala/wartremover/warts/StringPlusAny.scala +++ b/core/src/main/scala/wartremover/warts/StringPlusAny.scala @@ -6,6 +6,8 @@ object StringPlusAny extends WartTraverser { import u.universe._ val Plus: TermName = "$plus" + val PredefName: TermName = "Predef" + val Any2StringAddName: TermName = "any2stringadd" def isString(t: Tree) = t.tpe <:< typeOf[String] @@ -22,7 +24,18 @@ object StringPlusAny extends WartTraverser { // Ignore trees marked by SuppressWarnings case t if hasWartAnnotation(u)(t) => - case t @ Apply(Select(lhs, Plus), List(rhs)) if isString(t) && (isString(lhs) ^ isStringExpression(rhs)) + case Apply(Select(Select(_, PredefName), Any2StringAddName), _) => + u.error(tree.pos, "Implicit conversion to string is disabled") + super.traverse(tree) + case TypeApply(Select(Select(_, PredefName), Any2StringAddName), _) => + u.error(tree.pos, "Implicit conversion to string is disabled") + super.traverse(tree) + + case Apply(Select(Literal(Constant(c)), Plus), _) if !c.isInstanceOf[String] => + u.error(tree.pos, "Implicit conversion to string is disabled") + super.traverse(tree) + + case t @ Apply(Select(lhs, Plus), List(rhs)) if isString(lhs) && !isStringExpression(rhs) && !isSynthetic(u)(t) => u.error(tree.pos, "Implicit conversion to string is disabled") super.traverse(tree) diff --git a/core/src/test/scala/wartremover/warts/StringPlusAnyTest.scala b/core/src/test/scala/wartremover/warts/StringPlusAnyTest.scala index cdd85ca9..fd8f623e 100644 --- a/core/src/test/scala/wartremover/warts/StringPlusAnyTest.scala +++ b/core/src/test/scala/wartremover/warts/StringPlusAnyTest.scala @@ -9,11 +9,17 @@ class StringPlusAnyTest extends FunSuite with ResultAssertions { test("Implicit conversion to string is disabled") { val result = WartTestTraverser(StringPlusAny) { {} + "lol" - 1 + "lol" "lol" + 1 "" + (if (true) 5 else "") } - assertErrors(result)("Implicit conversion to string is disabled", 4) + assertErrors(result)("Implicit conversion to string is disabled", 3) + } + + test("Primitive conversion to string is disabled") { + val result = WartTestTraverser(StringPlusAny) { + 1 + "lol" + } + assertError(result)("Implicit conversion to string is disabled") } test("Non-string + usage is allowed") { @@ -47,7 +53,7 @@ class StringPlusAnyTest extends FunSuite with ResultAssertions { test("custom-defined + is allowed") { val result = WartTestTraverser(StringPlusAny) { - class C { def +(s: String) = this } + class C { def +(s: String) = s } new C + "a" } assertEmpty(result)