diff --git a/src/main/scala/LinterPlugin.scala b/src/main/scala/LinterPlugin.scala index e7c7e9c..0afc91d 100644 --- a/src/main/scala/LinterPlugin.scala +++ b/src/main/scala/LinterPlugin.scala @@ -259,7 +259,7 @@ final class LinterPlugin(val global: Global) extends Plugin { def seqMemberType(seenFrom: Type): Type = { if (seenFrom.baseClasses.exists(_.tpe =:= SeqLikeClass.tpe)) SeqLikeClass.tpe.typeArgs.head.asSeenFrom(seenFrom, SeqLikeClass) - else + else OptionClass.tpe.typeArgs.head.asSeenFrom(seenFrom, OptionClass) } @@ -788,12 +788,14 @@ final class LinterPlugin(val global: Global) extends Plugin { /// Collection.contains on different types: List(1, 2, 3).contains("2") case Apply(Select(col, Name("contains")), List(target)) if !(target.tpe.widen weak_<:< seqMemberType(col.tpe.widen)) + && !(target.tpe =:= AnyClass.tpe) && (col.tpe.baseClasses.exists(c => c.tpe =:= SeqClass.tpe || c.tpe =:= OptionClass.tpe)) => warn(tree, ContainsTypeMismatch(col.tpe.widen.toString, target.tpe.widen.toString)) case Apply(TypeApply(Select(col, Name("contains")), _), List(target)) if !(target.tpe.widen weak_<:< seqMemberType(col.tpe.widen)) + && !(target.tpe =:= AnyClass.tpe) && (col.tpe.baseClasses.exists(c => c.tpe =:= SeqClass.tpe || c.tpe =:= OptionClass.tpe)) => warn(tree, ContainsTypeMismatch(col.tpe.widen.toString, target.tpe.widen.toString)) diff --git a/src/test/scala/LinterPluginTest.scala b/src/test/scala/LinterPluginTest.scala index f613e6b..94b78a4 100644 --- a/src/test/scala/LinterPluginTest.scala +++ b/src/test/scala/LinterPluginTest.scala @@ -724,9 +724,23 @@ final class LinterPluginTest extends JUnitMustMatchers with StandardMatchResults should("""val x = List(4); x.contains("foo")""") // Contains not present on 2.11 Option if (Properties.versionString.contains("2.11")) { - should("""val x = Some(1); x.contains("foo")""") // Issue #45 + // Issue #45 + should("""val x = Some(1); x.contains("foo")""") should("""val x = Some("foo"); x.contains(1)""") noLint("""val x = Some("foo"); x.contains("ab")""") + // Issue #46 + should("""val foo = Some(4); val bar = Some("bar"); foo.exists(str => bar.contains(str))""") + should("""val foo = Some(4); val bar = Some("bar"); foo.exists(bar.contains(_))""") + should("""val foo = List(4); val bar = List("bar"); foo.exists(str => bar.contains(str))""") + should("""val foo = Some("foo"); val bar = Some(4); foo.exists(str => bar.contains(str))""") + should("""val foo = Some("foo"); val bar = Some(4); foo.exists(bar.contains(_))""") + //TODO false negative + //should("""val foo = Some(4); val bar = Some("bar"); foo.exists(bar.contains)""") + //should("""val foo = Some("foo"); val bar = Some(4); foo.exists(bar.contains)""") + + noLint("""val foo = Some("foo"); val bar = Some("bar"); foo.exists(str => bar.contains(str))""") + noLint("""val foo = Some("foo"); val bar = Some("bar"); foo.exists(bar.contains(_))""") + noLint("""val foo = Some("foo"); val bar = Some("bar"); foo.exists(bar.contains)""") } noLint("""val x = List(scala.util.Random.nextInt); x.contains(5)""")