Skip to content

Commit

Permalink
Fix wartremover#288 StringPlusAny
Browse files Browse the repository at this point in the history
  • Loading branch information
tim-zh committed Dec 17, 2016
1 parent 8c7a70e commit 88c06cc
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 24 deletions.
34 changes: 11 additions & 23 deletions core/src/main/scala/wartremover/warts/StringPlusAny.scala
Expand Up @@ -6,38 +6,26 @@ 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]

def isStringExpression(t: Tree) = t match {
//workaround: type of some expressions is inferred to Any during wart search since Scala 2.11
//this check doesn't cover all possible cases
case If(_, thn, els) => isString(thn) && isString(els)
case _ => isString(t)
}

new u.Traverser {
override def traverse(tree: Tree): Unit = {
tree match {
// Ignore trees marked by SuppressWarnings
case t if hasWartAnnotation(u)(t) =>

case Apply(Select(Apply(Select(Select(_, PredefName), Any2StringAddName), _), Plus), _) =>
case t @ Apply(Select(lhs, Plus), List(rhs)) if isString(t) && (isString(lhs) ^ isStringExpression(rhs))
&& !isSynthetic(u)(t) =>
u.error(tree.pos, "Implicit conversion to string is disabled")
super.traverse(tree)
case Apply(Select(TypeApply(Select(Select(_, PredefName), Any2StringAddName), _), Plus), _) =>
u.error(tree.pos, "Implicit conversion to string is disabled")
super.traverse(tree)

case Apply(Select(lhs, Plus), List(rhs))
if (lhs.tpe <:< typeOf[String] ^ rhs.tpe <:< typeOf[String]) && !isSynthetic(u)(tree) =>
val validIf = rhs match {
case If(_, then, els) => then.tpe <:< typeOf[String] && els.tpe <:< typeOf[String]
case _ => false
}
val overriddenPlus = lhs.symbol != null && lhs.symbol.owner != null && {
val owner = lhs.symbol.owner
owner.isClass && !owner.isSynthetic && owner.typeSignature.members.exists { x =>
x.isMethod && x.name.toTermName == Plus && !x.annotations.exists(isWartAnnotation(u))
}
}
if (!(overriddenPlus || validIf)) {
u.error(tree.pos, "Implicit conversion to string is disabled")
}
super.traverse(tree)

case _ => super.traverse(tree)
}
Expand Down
Expand Up @@ -38,9 +38,16 @@ class StringPlusAnyTest extends FunSuite with ResultAssertions {
assertEmpty(result)
}

test("inserting into a Set is allowed") {
val result = WartTestTraverser(StringPlusAny) {
Set("") + ""
}
assertEmpty(result)
}

test("custom-defined + is allowed") {
val result = WartTestTraverser(StringPlusAny) {
class C { def +(s: String) = s }
class C { def +(s: String) = this }
new C + "a"
}
assertEmpty(result)
Expand Down

0 comments on commit 88c06cc

Please sign in to comment.