diff --git a/japicmp-testbase/japicmp-test/src/test/java/japicmp/test/FinalMethodTest.java b/japicmp-testbase/japicmp-test/src/test/java/japicmp/test/FinalMethodTest.java index bbb4a827a..c8110f27f 100644 --- a/japicmp-testbase/japicmp-test/src/test/java/japicmp/test/FinalMethodTest.java +++ b/japicmp-testbase/japicmp-test/src/test/java/japicmp/test/FinalMethodTest.java @@ -2,7 +2,6 @@ import japicmp.cmp.JarArchiveComparator; import japicmp.cmp.JarArchiveComparatorOptions; -import japicmp.compat.CompatibilityChanges; import japicmp.model.JApiChangeStatus; import japicmp.model.JApiClass; import japicmp.model.JApiCompatibilityChange; @@ -50,7 +49,7 @@ public void testCompatibilityAddFinalToMethodAndMoveToSuperclass() { assertThat(jApiClass.isSourceCompatible(), is(false)); MatcherAssert.assertThat( getMethodCompatibilityChanges(jApiClass), - containsInAnyOrder(JApiCompatibilityChange.METHOD_NOW_FINAL)); + containsInAnyOrder(JApiCompatibilityChange.METHOD_NOW_FINAL, JApiCompatibilityChange.METHOD_MOVED_TO_SUPERCLASS)); } private static Collection getMethodCompatibilityChanges(JApiClass jApiClass) { diff --git a/japicmp/src/main/java/japicmp/model/JApiCompatibilityChange.java b/japicmp/src/main/java/japicmp/model/JApiCompatibilityChange.java index 5288d4a71..124704dbc 100644 --- a/japicmp/src/main/java/japicmp/model/JApiCompatibilityChange.java +++ b/japicmp/src/main/java/japicmp/model/JApiCompatibilityChange.java @@ -43,6 +43,7 @@ public enum JApiCompatibilityChange { METHOD_ABSTRACT_ADDED_IN_IMPLEMENTED_INTERFACE(true, false, JApiSemanticVersionLevel.MINOR), METHOD_DEFAULT_ADDED_IN_IMPLEMENTED_INTERFACE(true, true, JApiSemanticVersionLevel.MINOR), METHOD_NEW_DEFAULT(false, false, JApiSemanticVersionLevel.MAJOR), + METHOD_MOVED_TO_SUPERCLASS(true, true, JApiSemanticVersionLevel.PATCH), METHOD_ABSTRACT_NOW_DEFAULT(false, false, JApiSemanticVersionLevel.MAJOR), FIELD_STATIC_AND_OVERRIDES_STATIC(false, false, JApiSemanticVersionLevel.MAJOR), FIELD_LESS_ACCESSIBLE_THAN_IN_SUPERCLASS(false, false, JApiSemanticVersionLevel.MAJOR), diff --git a/japicmp/src/test/java/japicmp/compat/CompatibilityChangesTest.java b/japicmp/src/test/java/japicmp/compat/CompatibilityChangesTest.java index 7a24671d3..1f9cc0bc9 100755 --- a/japicmp/src/test/java/japicmp/compat/CompatibilityChangesTest.java +++ b/japicmp/src/test/java/japicmp/compat/CompatibilityChangesTest.java @@ -7,7 +7,6 @@ import javassist.ClassPool; import javassist.CtClass; import javassist.Modifier; - import org.hamcrest.core.Is; import org.junit.Test; @@ -2045,4 +2044,64 @@ public List createNewClasses(ClassPool classPool) throws Exception { JApiClass jApiClass = getJApiClass(jApiClasses, "SI"); assertThat(jApiClass.getCompatibilityChanges(), not(hasItem(JApiCompatibilityChange.METHOD_ABSTRACT_ADDED_IN_IMPLEMENTED_INTERFACE))); } + + @Test + public void testMoveMethodToSuperclassAndMakeFinal() throws Exception { + JarArchiveComparatorOptions jarArchiveComparatorOptions = new JarArchiveComparatorOptions(); + jarArchiveComparatorOptions.setAccessModifier(AccessModifier.PRIVATE); + List jApiClasses = ClassesHelper.compareClasses(jarArchiveComparatorOptions, new ClassesHelper.ClassesGenerator() { + @Override + public List createOldClasses(ClassPool classPool) throws Exception { + CtClass superClass = CtClassBuilder.create().name("SuperClass").addToClassPool(classPool); + CtClass subClass = CtClassBuilder.create().name("SubClass").withSuperclass(superClass).addToClassPool(classPool); + CtMethodBuilder.create().publicAccess().name("method").addToClass(subClass); + return Arrays.asList(superClass, subClass); + } + + @Override + public List createNewClasses(ClassPool classPool) throws Exception { + CtClass superClass = CtClassBuilder.create().name("SuperClass").addToClassPool(classPool); + CtMethodBuilder.create().publicAccess().finalMethod().name("method").addToClass(superClass); + CtClass subClass = CtClassBuilder.create().name("SubClass").withSuperclass(superClass).addToClassPool(classPool); + return Arrays.asList(superClass, subClass); + } + }); + JApiClass jApiClass = getJApiClass(jApiClasses, "SubClass"); + JApiMethod jApiMethod = getJApiMethod(jApiClass.getMethods(), "method"); + assertThat(jApiMethod.getChangeStatus(), is(JApiChangeStatus.REMOVED)); + assertThat(jApiMethod.getCompatibilityChanges(), hasItem(JApiCompatibilityChange.METHOD_NOW_FINAL)); + assertThat(jApiMethod.getCompatibilityChanges(), hasItem(JApiCompatibilityChange.METHOD_MOVED_TO_SUPERCLASS)); + jApiClass = getJApiClass(jApiClasses, "SuperClass"); + jApiMethod = getJApiMethod(jApiClass.getMethods(), "method"); + assertThat(jApiMethod.getCompatibilityChanges(), hasItem(JApiCompatibilityChange.METHOD_NOW_FINAL)); + } + + @Test + public void testRemoveMethodInSubClassAndSuperClass() throws Exception { + JarArchiveComparatorOptions jarArchiveComparatorOptions = new JarArchiveComparatorOptions(); + jarArchiveComparatorOptions.setAccessModifier(AccessModifier.PRIVATE); + List jApiClasses = ClassesHelper.compareClasses(jarArchiveComparatorOptions, new ClassesHelper.ClassesGenerator() { + @Override + public List createOldClasses(ClassPool classPool) throws Exception { + CtClass superClass = CtClassBuilder.create().name("SuperClass").addToClassPool(classPool); + CtMethodBuilder.create().publicAccess().name("method").addToClass(superClass); + CtClass subClass = CtClassBuilder.create().name("SubClass").withSuperclass(superClass).addToClassPool(classPool); + CtMethodBuilder.create().publicAccess().name("method").addToClass(subClass); + return Arrays.asList(superClass, subClass); + } + + @Override + public List createNewClasses(ClassPool classPool) throws Exception { + CtClass superClass = CtClassBuilder.create().name("SuperClass").addToClassPool(classPool); + CtClass subClass = CtClassBuilder.create().name("SubClass").withSuperclass(superClass).addToClassPool(classPool); + return Arrays.asList(superClass, subClass); + } + }); + JApiClass jApiClass = getJApiClass(jApiClasses, "SubClass"); + JApiMethod jApiMethod = getJApiMethod(jApiClass.getMethods(), "method"); + assertThat(jApiMethod.getChangeStatus(), is(JApiChangeStatus.REMOVED)); + jApiClass = getJApiClass(jApiClasses, "SuperClass"); + jApiMethod = getJApiMethod(jApiClass.getMethods(), "method"); + assertThat(jApiMethod.getChangeStatus(), is(JApiChangeStatus.REMOVED)); + } } diff --git a/src/site/markdown/MavenPlugin.md b/src/site/markdown/MavenPlugin.md index e344d479c..7d281f119 100644 --- a/src/site/markdown/MavenPlugin.md +++ b/src/site/markdown/MavenPlugin.md @@ -301,6 +301,7 @@ for each check. This allows you to customize the following verifications: | METHOD_DEFAULT_ADDED_IN_IMPLEMENTED_INTERFACE | true | true | MINOR | | METHOD_NEW_DEFAULT | false | false | MAJOR | | METHOD_ABSTRACT_NOW_DEFAULT | false | false | MAJOR | +| METHOD_MOVED_TO_SUPERCLASS | true | true | PATCH | | FIELD_STATIC_AND_OVERRIDES_STATIC | false | false | MAJOR | | FIELD_LESS_ACCESSIBLE_THAN_IN_SUPERCLASS | false | false | MAJOR | | FIELD_NOW_FINAL | false | false | MAJOR |