diff --git a/core/src/main/scala/com/typesafe/tools/mima/lib/analyze/method/MethodChecker.scala b/core/src/main/scala/com/typesafe/tools/mima/lib/analyze/method/MethodChecker.scala index 4cc6e06a..348e485a 100644 --- a/core/src/main/scala/com/typesafe/tools/mima/lib/analyze/method/MethodChecker.scala +++ b/core/src/main/scala/com/typesafe/tools/mima/lib/analyze/method/MethodChecker.scala @@ -8,20 +8,28 @@ private[analyze] abstract class BaseMethodChecker extends Checker[MethodInfo, Cl protected val rules = Seq(AccessModifier, FinalModifier, AbstractModifier, JavaStatic) - protected def check(method: MethodInfo, in: Iterator[MethodInfo]): Option[Problem] = { - val meths = in.filter(method.paramsCount == _.paramsCount).toList + protected def check(method: MethodInfo, newclazz: ClassInfo, methsLookup: ClassInfo => Iterator[MethodInfo]): Option[Problem] = { + val meths = methsLookup(newclazz).filter(method.paramsCount == _.paramsCount).toList // newmeths if (meths.isEmpty) Some(DirectMissingMethodProblem(method)) else { meths.find(m => m.descriptor == method.descriptor && m.signature == method.signature) match { case Some(found) => checkRules(rules)(method, found) - case None => meths.filter(method.matchesType(_)) match { - case Nil => Some(IncompatibleMethTypeProblem(method, uniques(meths))) - case filtered @ first :: _ => filtered.find(_.tpe.resultType == method.tpe.resultType) match { - case None => Some(IncompatibleResultTypeProblem(method, first)) + case None => + val filtered = meths.filter(method.matchesType(_)) + filtered.find(_.tpe.resultType == method.tpe.resultType) match { case Some(found) => Some(IncompatibleSignatureProblem(method, found)) + case None => + val oldmethsDescriptors = methsLookup(method.owner).map(_.descriptor).toSet + if (meths.forall(newmeth => oldmethsDescriptors.contains(newmeth.descriptor))) + Some(DirectMissingMethodProblem(method)) + else { + filtered match { + case Nil => Some(IncompatibleMethTypeProblem(method, uniques(meths))) + case first :: _ => Some(IncompatibleResultTypeProblem(method, first)) + } + } } - } } } } @@ -35,9 +43,9 @@ private[analyze] class ClassMethodChecker extends BaseMethodChecker { if (method.nonAccessible) None else if (method.isDeferred) - super.check(method, inclazz.lookupMethods(method.bytecodeName)) + super.check(method, inclazz, _.lookupMethods(method.bytecodeName)) else - super.check(method, inclazz.lookupClassMethods(method.bytecodeName)) + super.check(method, inclazz, _.lookupClassMethods(method.bytecodeName)) } } @@ -48,7 +56,7 @@ private[analyze] class TraitMethodChecker extends BaseMethodChecker { else if (method.owner.hasStaticImpl(method)) checkStaticImplMethod(method, inclazz) else - super.check(method, inclazz.lookupMethods(method.bytecodeName)) + super.check(method, inclazz, _.lookupMethods(method.bytecodeName)) } private def checkStaticImplMethod(method: MethodInfo, inclazz: ClassInfo) = { @@ -66,7 +74,7 @@ private[analyze] class TraitMethodChecker extends BaseMethodChecker { // otherwise we check the all concrete trait methods and report // either that the method is missing or that no method with the // same signature exists. Either way, we expect that a problem is reported! - val prob = super.check(method, inclazz.lookupConcreteTraitMethods(method.bytecodeName)) + val prob = super.check(method, inclazz, _.lookupConcreteTraitMethods(method.bytecodeName)) assert(prob.isDefined) prob } diff --git a/functional-tests/src/test/class-removed-method-overload-ko/problems.txt b/functional-tests/src/test/class-removed-method-overload-ko/problems.txt new file mode 100644 index 00000000..dd9d5856 --- /dev/null +++ b/functional-tests/src/test/class-removed-method-overload-ko/problems.txt @@ -0,0 +1 @@ +method foo(java.lang.Object)java.lang.String in class A does not have a correspondent in new version diff --git a/functional-tests/src/test/class-removed-method-overload-ko/v1/A.scala b/functional-tests/src/test/class-removed-method-overload-ko/v1/A.scala new file mode 100644 index 00000000..b084d86f --- /dev/null +++ b/functional-tests/src/test/class-removed-method-overload-ko/v1/A.scala @@ -0,0 +1,4 @@ +final class A { + def foo(s: String): String = s + def foo(o: Object): String = o.toString +} diff --git a/functional-tests/src/test/class-removed-method-overload-ko/v2/A.scala b/functional-tests/src/test/class-removed-method-overload-ko/v2/A.scala new file mode 100644 index 00000000..e85081f8 --- /dev/null +++ b/functional-tests/src/test/class-removed-method-overload-ko/v2/A.scala @@ -0,0 +1,3 @@ +final class A { + def foo(s: String): String = s +}