From 2ef19b55ae6913a289df68c3756a990f376354aa Mon Sep 17 00:00:00 2001 From: Martín Schonaker Date: Wed, 9 Apr 2014 17:24:27 -0300 Subject: Issue #25: @Deprecated should require a minor version bump instead of a major one. --- .../java/org/osjava/jardiff/DOMDiffHandler.java | 28 +++++- .../main/java/org/osjava/jardiff/DiffHandler.java | 35 ++++++- api/src/main/java/org/osjava/jardiff/JarDiff.java | 103 ++++++++++++++++++--- .../java/org/osjava/jardiff/StreamDiffHandler.java | 25 +++++ api/src/main/java/org/semver/Delta.java | 22 ++++- api/src/main/java/org/semver/Dumper.java | 1 - .../jardiff/DifferenceAccumulatingHandler.java | 31 ++++++- 7 files changed, 227 insertions(+), 18 deletions(-) (limited to 'api/src') diff --git a/api/src/main/java/org/osjava/jardiff/DOMDiffHandler.java b/api/src/main/java/org/osjava/jardiff/DOMDiffHandler.java index d2500a5..a05bbbf 100644 --- a/api/src/main/java/org/osjava/jardiff/DOMDiffHandler.java +++ b/api/src/main/java/org/osjava/jardiff/DOMDiffHandler.java @@ -29,8 +29,8 @@ import javax.xml.transform.TransformerException; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import javax.xml.transform.Result; -import org.w3c.dom.*; +import org.w3c.dom.*; import org.objectweb.asm.Type; /** @@ -372,6 +372,15 @@ public class DOMDiffHandler implements DiffHandler this.currentNode = currentNode; } + /** + * Invokes {@link #classChanged(ClassInfo, ClassInfo)}. + */ + public void classDeprecated(ClassInfo oldInfo, ClassInfo newInfo) + throws DiffException + { + classChanged(oldInfo, newInfo); + } + /** * Write out info aboout a changed field. * This writes out a <fieldchange> node, followed by a @@ -401,6 +410,14 @@ public class DOMDiffHandler implements DiffHandler this.currentNode = currentNode; } + /** + * Invokes {@link #fieldChanged(FieldInfo, FieldInfo)}. + */ + public void fieldDeprecated(FieldInfo oldInfo, FieldInfo newInfo) + throws DiffException { + fieldChanged(oldInfo, newInfo); + } + /** * Write out info aboout a changed method. * This writes out a <methodchange> node, followed by a @@ -430,6 +447,15 @@ public class DOMDiffHandler implements DiffHandler this.currentNode = currentNode; } + /** + * Invokes {@link #methodChanged(MethodInfo, MethodInfo)}. + */ + public void methodDeprecated(MethodInfo oldInfo, MethodInfo newInfo) + throws DiffException + { + methodChanged(oldInfo, newInfo); + } + /** * End the changed section for an individual class. * This closes the <classchanged> node. diff --git a/api/src/main/java/org/osjava/jardiff/DiffHandler.java b/api/src/main/java/org/osjava/jardiff/DiffHandler.java index eee74b4..e10f1bf 100644 --- a/api/src/main/java/org/osjava/jardiff/DiffHandler.java +++ b/api/src/main/java/org/osjava/jardiff/DiffHandler.java @@ -193,6 +193,17 @@ public interface DiffHandler public void classChanged(ClassInfo oldClassinfo, ClassInfo newClassinfo) throws DiffException; + /** + * The current class has been deprecated. + * + * @param oldClassinfo Information about the old class. + * @param newClassinfo Information about the new class. + * @throws DiffException when there is an underlying exception, e.g. + * writing to a file caused an IOException + */ + public void classDeprecated(ClassInfo oldClassinfo, ClassInfo newClassinfo) + throws DiffException; + /** * A field on the current class has changed. * @@ -204,6 +215,17 @@ public interface DiffHandler public void fieldChanged(FieldInfo oldFieldinfo, FieldInfo newFieldinfo) throws DiffException; + /** + * A field on the current class has been deprecated. + * + * @param oldFieldinfo Information about the old field. + * @param newFieldinfo Information about the new field. + * @throws DiffException when there is an underlying exception, e.g. + * writing to a file caused an IOException + */ + public void fieldDeprecated(FieldInfo oldFieldinfo, FieldInfo newFieldinfo) + throws DiffException; + /** * A method on the current class has changed. * @@ -214,7 +236,18 @@ public interface DiffHandler */ public void methodChanged (MethodInfo oldMethodInfo, MethodInfo newMethodInfo) throws DiffException; - + + /** + * The method has been deprecated. + * + * @param oldMethodInfo Information about the old method. + * @param newMethodInfo Information about the new method. + * @throws DiffException when there is an underlying exception, e.g. + * writing to a file caused an IOException + */ + public void methodDeprecated(MethodInfo oldMethodInfo, + MethodInfo newMethodInfo) throws DiffException; + /** * End of changes for the current class. * diff --git a/api/src/main/java/org/osjava/jardiff/JarDiff.java b/api/src/main/java/org/osjava/jardiff/JarDiff.java index 77a0c93..e0f89d9 100644 --- a/api/src/main/java/org/osjava/jardiff/JarDiff.java +++ b/api/src/main/java/org/osjava/jardiff/JarDiff.java @@ -41,7 +41,10 @@ import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; */ + + import org.objectweb.asm.ClassReader; +import org.objectweb.asm.Opcodes; /** * A class to perform a diff between two jar files. @@ -123,7 +126,7 @@ public class JarDiff /** * Set the name of the new version. * - * @param newVersion + * @param newVersion the version */ public void setNewVersion(String newVersion) { this.newVersion = newVersion; @@ -273,7 +276,7 @@ public class JarDiff * Load new classes from the specified File. * * @param file The location of a jar file to load classes from. - * @throws DiffExeption if there is an IOException + * @throws DiffException if there is an IOException */ public void loadNewClasses(File file) throws DiffException { loadClasses(newClassInfo, file); @@ -440,20 +443,44 @@ public class JarDiff newMethods.get(j.next())); handler.endAdded(); handler.startChanged(); - if (classchanged) - handler.classChanged(oci, nci); - j = changedFields.iterator(); - while (j.hasNext()) { - Object tmp = j.next(); - handler.fieldChanged((FieldInfo) oldFields.get(tmp), - (FieldInfo) newFields.get(tmp)); + if (classchanged) { + // Was only deprecated? + if (wasDeprecated(oci, nci) + && !criteria.differs(cloneDeprecated(oci), nci)) + handler.classDeprecated(oci, nci); + else + handler.classChanged(oci, nci); } + j = changedFields.iterator(); + while (j.hasNext()) { + Object tmp = j.next(); + FieldInfo oldFieldInfo = (FieldInfo) oldFields.get(tmp); + FieldInfo newFieldInfo = (FieldInfo) newFields.get(tmp); + // Was only deprecated? + if (wasDeprecated(oldFieldInfo, newFieldInfo) + && !criteria.differs( + cloneDeprecated(oldFieldInfo), + newFieldInfo)) + handler.fieldDeprecated(oldFieldInfo, newFieldInfo); + else + handler.fieldChanged(oldFieldInfo, newFieldInfo); + } j = changedMethods.iterator(); while (j.hasNext()) { - Object tmp = j.next(); - handler.methodChanged((MethodInfo) oldMethods.get(tmp), - ((MethodInfo) - newMethods.get(tmp))); + Object tmp = j.next(); + MethodInfo oldMethodInfo = (MethodInfo) oldMethods + .get(tmp); + MethodInfo newMethodInfo = (MethodInfo) newMethods + .get(tmp); + // Was only deprecated? + if (wasDeprecated(oldMethodInfo, newMethodInfo) + && !criteria.differs( + cloneDeprecated(oldMethodInfo), + newMethodInfo)) + handler.methodDeprecated(oldMethodInfo, + newMethodInfo); + else + handler.methodChanged(oldMethodInfo, newMethodInfo); } handler.endChanged(); handler.endClassChanged(); @@ -469,4 +496,54 @@ public class JarDiff handler.endChanged(); handler.endDiff(); } + + /** + * Determines if an {@link AbstractInfo} was deprecated. (Shortcut to avoid + * creating cloned deprecated infos). + */ + private static boolean wasDeprecated(AbstractInfo oldInfo, + AbstractInfo newInfo) { + return !oldInfo.isDeprecated() && newInfo.isDeprecated(); + } + + /** + * Clones the class info, but changes access, setting deprecated flag. + * + * @param classInfo + * the original class info + * @return the cloned and deprecated info. + */ + private static ClassInfo cloneDeprecated(ClassInfo classInfo) { + return new ClassInfo(classInfo.getVersion(), classInfo.getAccess() + | Opcodes.ACC_DEPRECATED, classInfo.getName(), + classInfo.getSignature(), classInfo.getSupername(), + classInfo.getInterfaces(), classInfo.getMethodMap(), + classInfo.getFieldMap()); + } + + /** + * Clones the method, but changes access, setting deprecated flag. + * + * @param methodInfo + * the original method info + * @return the cloned and deprecated method info. + */ + private static MethodInfo cloneDeprecated(MethodInfo methodInfo) { + return new MethodInfo(methodInfo.getAccess() | Opcodes.ACC_DEPRECATED, + methodInfo.getName(), methodInfo.getDesc(), + methodInfo.getSignature(), methodInfo.getExceptions()); + } + + /** + * Clones the field info, but changes access, setting deprecated flag. + * + * @param fieldInfo + * the original field info + * @return the cloned and deprecated field info. + */ + private static FieldInfo cloneDeprecated(FieldInfo fieldInfo) { + return new FieldInfo(fieldInfo.getAccess() | Opcodes.ACC_DEPRECATED, + fieldInfo.getName(), fieldInfo.getDesc(), + fieldInfo.getSignature(), fieldInfo.getValue()); + } } diff --git a/api/src/main/java/org/osjava/jardiff/StreamDiffHandler.java b/api/src/main/java/org/osjava/jardiff/StreamDiffHandler.java index e0600df..f5f7176 100644 --- a/api/src/main/java/org/osjava/jardiff/StreamDiffHandler.java +++ b/api/src/main/java/org/osjava/jardiff/StreamDiffHandler.java @@ -21,6 +21,7 @@ import java.io.BufferedWriter; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; + import org.objectweb.asm.Type; /** @@ -394,6 +395,14 @@ public class StreamDiffHandler implements DiffHandler } } + /** + * Invokes {@link #classChanged(ClassInfo, ClassInfo)}. + */ + public void classDeprecated(ClassInfo oldInfo, ClassInfo newInfo) + throws DiffException { + classChanged(oldInfo, newInfo); + } + /** * Write out info aboout a changed field. * This writes out a <fieldchange> node, followed by a @@ -420,6 +429,14 @@ public class StreamDiffHandler implements DiffHandler } } + /** + * Invokes {@link #fieldChanged(FieldInfo, FieldInfo)}. + */ + public void fieldDeprecated(FieldInfo oldInfo, FieldInfo newInfo) + throws DiffException { + fieldChanged(oldInfo, newInfo); + } + /** * Write out info aboout a changed method. * This writes out a <methodchange> node, followed by a @@ -446,6 +463,14 @@ public class StreamDiffHandler implements DiffHandler } } + /** + * Invokes {@link #methodChanged(MethodInfo, MethodInfo)}. + */ + public void methodDeprecated(MethodInfo oldInfo, MethodInfo newInfo) + throws DiffException { + methodChanged(oldInfo, newInfo); + } + /** * End the changed section for an individual class. * This closes the <classchanged> node. diff --git a/api/src/main/java/org/semver/Delta.java b/api/src/main/java/org/semver/Delta.java index 4af87d3..20d963c 100755 --- a/api/src/main/java/org/semver/Delta.java +++ b/api/src/main/java/org/semver/Delta.java @@ -106,6 +106,24 @@ public final class Delta { } + @Immutable + public static class Deprecate extends Difference { + + private final AbstractInfo modifiedInfo; + + public Deprecate(@Nonnull final String className, + @Nonnull final AbstractInfo info, + @Nonnull final AbstractInfo modifiedInfo) { + super(className, info); + + this.modifiedInfo = modifiedInfo; + } + + public AbstractInfo getModifiedInfo() { + return this.modifiedInfo; + } + } + @Immutable public static class Remove extends Difference { @@ -132,10 +150,12 @@ public final class Delta { */ @Nonnull public final CompatibilityType computeCompatibilityType() { + if (contains(this.differences, Change.class) || contains(this.differences, Remove.class)) { return CompatibilityType.NON_BACKWARD_COMPATIBLE; - } else if (contains(this.differences, Add.class)) { + } else if (contains(this.differences, Add.class) || + contains(this.differences, Deprecate.class)) { return CompatibilityType.BACKWARD_COMPATIBLE_USER; } else { return CompatibilityType.BACKWARD_COMPATIBLE_IMPLEMENTER; diff --git a/api/src/main/java/org/semver/Dumper.java b/api/src/main/java/org/semver/Dumper.java index 86774aa..a226bcc 100755 --- a/api/src/main/java/org/semver/Dumper.java +++ b/api/src/main/java/org/semver/Dumper.java @@ -78,7 +78,6 @@ public final class Dumper { accumulateAccessDetails("abstract", previousInfo.isAbstract(), currentInfo.isAbstract(), added, removed); accumulateAccessDetails("annotation", previousInfo.isAnnotation(), currentInfo.isAnnotation(), added, removed); accumulateAccessDetails("bridge", previousInfo.isBridge(), currentInfo.isBridge(), added, removed); - accumulateAccessDetails("deprecated", previousInfo.isDeprecated(), currentInfo.isDeprecated(), added, removed); accumulateAccessDetails("enum", previousInfo.isEnum(), currentInfo.isEnum(), added, removed); accumulateAccessDetails("final", previousInfo.isFinal(), currentInfo.isFinal(), added, removed); accumulateAccessDetails("interface", previousInfo.isInterface(), currentInfo.isInterface(), added, removed); diff --git a/api/src/main/java/org/semver/jardiff/DifferenceAccumulatingHandler.java b/api/src/main/java/org/semver/jardiff/DifferenceAccumulatingHandler.java index 0fb942e..b33a711 100755 --- a/api/src/main/java/org/semver/jardiff/DifferenceAccumulatingHandler.java +++ b/api/src/main/java/org/semver/jardiff/DifferenceAccumulatingHandler.java @@ -19,10 +19,11 @@ package org.semver.jardiff; import java.util.Collections; import java.util.HashSet; import java.util.Set; -import javax.annotation.Nonnull; import java.util.regex.Matcher; import java.util.regex.Pattern; +import javax.annotation.Nonnull; + import org.osjava.jardiff.AbstractDiffHandler; import org.osjava.jardiff.ClassInfo; import org.osjava.jardiff.DiffException; @@ -31,6 +32,7 @@ import org.osjava.jardiff.MethodInfo; import org.semver.Delta; import org.semver.Delta.Add; import org.semver.Delta.Change; +import org.semver.Delta.Deprecate; import org.semver.Delta.Difference; import org.semver.Delta.Remove; @@ -140,6 +142,15 @@ public final class DifferenceAccumulatingHandler extends AbstractDiffHandler { this.differences.add(new Change(getClassName(oldClassInfo.getName()), oldClassInfo, newClassInfo)); } + @Override + public void classDeprecated(final ClassInfo oldClassInfo, final ClassInfo newClassInfo) throws DiffException { + if (!isClassConsidered(oldClassInfo.getName())) { + return; + } + + this.differences.add(new Deprecate(getClassName(oldClassInfo.getName()), oldClassInfo, newClassInfo)); + } + @Override public void fieldChanged(final FieldInfo oldFieldInfo, final FieldInfo newFieldInfo) throws DiffException { if (!isClassConsidered(getCurrentClassName())) { @@ -149,6 +160,15 @@ public final class DifferenceAccumulatingHandler extends AbstractDiffHandler { this.differences.add(new Change(getCurrentClassName(), oldFieldInfo, newFieldInfo)); } + @Override + public void fieldDeprecated(final FieldInfo oldFieldInfo, final FieldInfo newFieldInfo) throws DiffException { + if (!isClassConsidered(getCurrentClassName())) { + return; + } + + this.differences.add(new Deprecate(getCurrentClassName(), oldFieldInfo, newFieldInfo)); + } + @Override public void methodChanged(final MethodInfo oldMethodInfo, final MethodInfo newMethodInfo) throws DiffException { if (!isClassConsidered(getCurrentClassName())) { @@ -158,6 +178,15 @@ public final class DifferenceAccumulatingHandler extends AbstractDiffHandler { this.differences.add(new Change(getCurrentClassName(), oldMethodInfo, newMethodInfo)); } + @Override + public void methodDeprecated(final MethodInfo oldMethodInfo, final MethodInfo newMethodInfo) throws DiffException { + if (!isClassConsidered(getCurrentClassName())) { + return; + } + + this.differences.add(new Deprecate(getCurrentClassName(), oldMethodInfo, newMethodInfo)); + } + @Override public void endClassChanged() throws DiffException { } -- cgit v1.2.3