clirr-devel Mailing List for Clirr (Page 40)
Status: Alpha
Brought to you by:
lkuehne
You can subscribe to this list here.
2003 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
(15) |
Oct
(23) |
Nov
|
Dec
(25) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2004 |
Jan
(9) |
Feb
|
Mar
|
Apr
|
May
(76) |
Jun
(207) |
Jul
(242) |
Aug
(42) |
Sep
(33) |
Oct
|
Nov
(7) |
Dec
(1) |
2005 |
Jan
|
Feb
|
Mar
(5) |
Apr
|
May
|
Jun
|
Jul
(3) |
Aug
(66) |
Sep
(38) |
Oct
(6) |
Nov
|
Dec
(2) |
2006 |
Jan
(17) |
Feb
(5) |
Mar
(28) |
Apr
(6) |
May
|
Jun
|
Jul
(1) |
Aug
|
Sep
|
Oct
(1) |
Nov
(1) |
Dec
(7) |
2007 |
Jan
|
Feb
|
Mar
|
Apr
(7) |
May
(33) |
Jun
(4) |
Jul
(3) |
Aug
|
Sep
(5) |
Oct
|
Nov
|
Dec
|
2008 |
Jan
(4) |
Feb
(3) |
Mar
(2) |
Apr
|
May
(1) |
Jun
|
Jul
(6) |
Aug
(8) |
Sep
(5) |
Oct
(20) |
Nov
(7) |
Dec
(9) |
2009 |
Jan
(8) |
Feb
(3) |
Mar
(20) |
Apr
(10) |
May
(40) |
Jun
(11) |
Jul
(23) |
Aug
(4) |
Sep
(1) |
Oct
(1) |
Nov
|
Dec
(2) |
2010 |
Jan
(5) |
Feb
(1) |
Mar
|
Apr
|
May
|
Jun
(1) |
Jul
|
Aug
(2) |
Sep
|
Oct
|
Nov
|
Dec
|
2011 |
Jan
|
Feb
|
Mar
|
Apr
(3) |
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(1) |
2012 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
(1) |
Sep
|
Oct
|
Nov
|
Dec
|
2013 |
Jan
|
Feb
|
Mar
|
Apr
(6) |
May
(22) |
Jun
(2) |
Jul
|
Aug
|
Sep
|
Oct
(2) |
Nov
(1) |
Dec
(2) |
2014 |
Jan
(5) |
Feb
|
Mar
|
Apr
|
May
(1) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
(1) |
Dec
|
2015 |
Jan
(1) |
Feb
(2) |
Mar
(1) |
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2016 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(1) |
Nov
|
Dec
|
2017 |
Jan
|
Feb
|
Mar
(1) |
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: Lars K?h. <lk...@us...> - 2004-05-22 13:26:16
|
Update of /cvsroot/clirr/clirr/conf In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv20999/conf Modified Files: javaheader.txt Log Message: changed copyright year Index: javaheader.txt =================================================================== RCS file: /cvsroot/clirr/clirr/conf/javaheader.txt,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- javaheader.txt 27 Sep 2003 05:28:43 -0000 1.2 +++ javaheader.txt 22 May 2004 13:26:02 -0000 1.3 @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // Clirr: compares two versions of a java library for binary compatibility -// Copyright (C) 2003 Lars Kühne +// Copyright (C) 2003 - 2004 Lars Kühne // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public |
From: Lars K?h. <lk...@us...> - 2004-05-22 13:26:14
|
Update of /cvsroot/clirr/clirr/src/java/net/sf/clirr In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv20999/src/java/net/sf/clirr Modified Files: Checker.java Log Message: changed copyright year Index: Checker.java =================================================================== RCS file: /cvsroot/clirr/clirr/src/java/net/sf/clirr/Checker.java,v retrieving revision 1.9 retrieving revision 1.10 diff -u -r1.9 -r1.10 --- Checker.java 18 Jan 2004 12:04:59 -0000 1.9 +++ Checker.java 22 May 2004 13:26:02 -0000 1.10 @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // Clirr: compares two versions of a java library for binary compatibility -// Copyright (C) 2003 Lars Kühne +// Copyright (C) 2003 - 2004 Lars Kühne // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public |
From: Lars K?h. <lk...@us...> - 2004-05-22 13:22:57
|
Update of /cvsroot/clirr/clirr In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv20448 Modified Files: LICENSE.txt Log Message: more fun with umlaut encodings Index: LICENSE.txt =================================================================== RCS file: /cvsroot/clirr/clirr/LICENSE.txt,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- LICENSE.txt 14 Sep 2003 11:04:38 -0000 1.1 +++ LICENSE.txt 22 May 2004 13:22:48 -0000 1.2 @@ -1,5 +1,5 @@ Clirr: compares two versions of a java library for binary compatibility -Copyright (C) 2003 Lars Kühne +Copyright (C) 2003 - 2004 Lars Kühne This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public |
From: Lars K?h. <lk...@us...> - 2004-05-22 13:21:54
|
Update of /cvsroot/clirr/clirr/src/java/net/sf/clirr/checks In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv20264/java/net/sf/clirr/checks Modified Files: MethodSetCheck.java Log Message: improved the way covariant methods matched when before comparing them Index: MethodSetCheck.java =================================================================== RCS file: /cvsroot/clirr/clirr/src/java/net/sf/clirr/checks/MethodSetCheck.java,v retrieving revision 1.3 retrieving revision 1.4 diff -u -r1.3 -r1.4 --- MethodSetCheck.java 25 Jan 2004 08:16:45 -0000 1.3 +++ MethodSetCheck.java 22 May 2004 13:21:44 -0000 1.4 @@ -19,11 +19,6 @@ package net.sf.clirr.checks; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Comparator; -import java.util.List; - import net.sf.clirr.event.ApiDifference; import net.sf.clirr.event.Severity; import net.sf.clirr.framework.AbstractDiffReporter; @@ -33,6 +28,15 @@ import org.apache.bcel.classfile.Method; import org.apache.bcel.generic.Type; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeSet; + /** * Checks the methods of a class. * @@ -42,68 +46,200 @@ extends AbstractDiffReporter implements ClassChangeCheck { - private class MethodComparator implements Comparator + /** {@inheritDoc} */ + public MethodSetCheck(ApiDiffDispatcher dispatcher) + { + super(dispatcher); + } + + public final void check(JavaClass compatBaseline, JavaClass currentVersion) { - public final int compare(Object o1, Object o2) + // Dont't report method problems when gender has changed, as + // really the whole API is a pile of crap then - let GenderChange check + // do it's job, and that's it + if (compatBaseline.isInterface() ^ currentVersion.isInterface()) + { + return; + } + + // The main problem here is to figure out which old method corresponds to which new method. + + // Methods that are named differently are trated as unrelated + // + // For Methods that differ only in their parameter list we build a similarity table, i.e. + // for new method i and old method j we have number that charaterizes how similar + // the method signatures are (0 means equal, higher number means more different) + + Map bNameToMethod = buildNameToMethodMap(compatBaseline); + Map cNameToMethod = buildNameToMethodMap(currentVersion); + + checkAddedOrRemoved(bNameToMethod, cNameToMethod, compatBaseline, currentVersion); + + // now the key sets of the two maps are equal, + // we only have collections of methods that have the same name + + // for each name analyse the differences + for (Iterator it = bNameToMethod.keySet().iterator(); it.hasNext();) { - Method m1 = (Method) o1; - Method m2 = (Method) o2; + String name = (String) it.next(); - String name1 = m1.getName(); - String name2 = m2.getName(); + List baselineMethods = (List) bNameToMethod.get(name); + List currentMethods = (List) cNameToMethod.get(name); - final int nameComparison = name1.compareTo(name2); - if (nameComparison == 0) + while (baselineMethods.size() * currentMethods.size() > 0) { - return m1.getArgumentTypes().length - m2.getArgumentTypes().length; + int[][] similarityTable = buildSimilarityTable(baselineMethods, currentMethods); + + int min = Integer.MAX_VALUE; + int iMin = baselineMethods.size(); + int jMin = currentMethods.size(); + for (int i = 0; i < baselineMethods.size(); i++) + { + for (int j = 0; j < currentMethods.size(); j++) + { + final int tableEntry = similarityTable[i][j]; + if (tableEntry < min) + { + min = tableEntry; + iMin = i; + jMin = j; + } + } + } + Method iMethod = (Method) baselineMethods.remove(iMin); + Method jMethod = (Method) currentMethods.remove(jMin); + check(compatBaseline, iMethod, jMethod); } - else + } + } + + private int[][] buildSimilarityTable(List baselineMethods, List currentMethods) + { + int[][] similarityTable = new int[baselineMethods.size()][currentMethods.size()]; + for (int i = 0; i < baselineMethods.size(); i++) + { + for (int j = 0; j < currentMethods.size(); j++) { - return nameComparison; + final Method iMethod = (Method) baselineMethods.get(i); + final Method jMethod = (Method) currentMethods.get(j); + similarityTable[i][j] = distance(iMethod, jMethod); } } + return similarityTable; } - /** {@inheritDoc} */ - public MethodSetCheck(ApiDiffDispatcher dispatcher) + private int distance(Method m1, Method m2) { - super(dispatcher); + final Type[] m1Args = m1.getArgumentTypes(); + final Type[] m2Args = m2.getArgumentTypes(); + + if (m1Args.length != m2Args.length) + { + return 1000 * Math.abs(m1Args.length - m2Args.length); + } + + int retVal = 0; + for (int i = 0; i < m1Args.length; i++) + { + if (!m1Args[i].toString().equals(m2Args[i].toString())) + { + retVal += 1; + } + } + return retVal; } - public final void check(JavaClass compatBaseline, JavaClass currentVersion) + /** + * Checks for added or removed methods, modifies the argument maps so their key sets are equal. + */ + private void checkAddedOrRemoved( + Map bNameToMethod, + Map cNameToMethod, + JavaClass compatBaseline, + JavaClass currentVersion) { - // Dont't report method problems when gender has changed, as - // really the whole API is a pile of crap then - let GenderChange check - // do it's job, and that's it - if (compatBaseline.isInterface() ^ currentVersion.isInterface()) + // create copies to avoid concurrent modification exception + Set baselineNames = new TreeSet(bNameToMethod.keySet()); + Set currentNames = new TreeSet(cNameToMethod.keySet()); + + for (Iterator it = baselineNames.iterator(); it.hasNext();) { - return; + String name = (String) it.next(); + if (!currentNames.contains(name)) + { + Collection removedMethods = (Collection) bNameToMethod.get(name); + for (Iterator rmIterator = removedMethods.iterator(); rmIterator.hasNext();) + { + Method method = (Method) rmIterator.next(); + reportMethodRemoved(compatBaseline, method); + } + bNameToMethod.remove(name); + } } - Method[] baselineMethods = sort(compatBaseline.getMethods()); - Method[] currentMethods = sort(currentVersion.getMethods()); - - for (int i = 0; i < baselineMethods.length; i++) + for (Iterator it = currentNames.iterator(); it.hasNext();) { - Method baselineMethod = baselineMethods[i]; + String name = (String) it.next(); + if (!baselineNames.contains(name)) + { + Collection addedMethods = (Collection) cNameToMethod.get(name); + for (Iterator addIterator = addedMethods.iterator(); addIterator.hasNext();) + { + Method method = (Method) addIterator.next(); + reportMethodAdded(currentVersion, method); + } + cNameToMethod.remove(name); + } + } + } - // TODO: We need a global perspective - // to determine which current method matches which baseline method. + private void reportMethodRemoved(JavaClass oldClass, Method oldMethod) + { + fireDiff("Method '" + + getMethodId(oldClass, oldMethod) + + "' has been removed", + Severity.ERROR, oldClass, oldMethod); + } - // simply checking the name and arg numbers won't be enough in all cases - // but I'll stick with it for now to get the framework out + private void reportMethodAdded(JavaClass newClass, Method newMethod) + { + + final Severity severity = !newClass.isInterface() && (newClass.isFinal() || !newMethod.isAbstract()) + ? Severity.INFO + : Severity.ERROR; + + fireDiff("Method '" + + getMethodId(newClass, newMethod) + + "' has been added", + severity, newClass, newMethod); + } - final int idx = Arrays.binarySearch(currentMethods, baselineMethod, new MethodComparator()); - if (idx < 0) + /** + * Builds a map from a method name to a List of methods. + */ + private Map buildNameToMethodMap(JavaClass clazz) + { + Method[] methods = clazz.getMethods(); + Map retVal = new HashMap(); + for (int i = 0; i < methods.length; i++) + { + Method method = methods[i]; + + if (!(method.isPublic() || method.isProtected())) { - fireDiff("Method '" + getMethodId(compatBaseline, baselineMethod) + "' has been removed", - Severity.ERROR, compatBaseline, baselineMethod); + continue; } - else + + final String name = method.getName(); + List set = (List) retVal.get(name); + if (set == null) { - check(compatBaseline, baselineMethod, currentMethods[idx]); + set = new ArrayList(); + retVal.put(name, set); } + set.add(method); } + return retVal; } private void check(JavaClass compatBaseline, Method baselineMethod, Method currentMethod) @@ -118,7 +254,6 @@ Type[] bArgs = baselineMethod.getArgumentTypes(); Type[] cArgs = currentMethod.getArgumentTypes(); - // TODO: This currently never fires because of our poor method matching algorithm if (bArgs.length != cArgs.length) { fireDiff("In Method '" + getMethodId(compatBaseline, baselineMethod) @@ -167,24 +302,6 @@ // TODO } - private Method[] sort(Method[] methods) - { - List target = new ArrayList(); - for (int i = 0; i < methods.length; i++) - { - final Method method = methods[i]; - if ((method.isPublic() || method.isProtected()) - && !"<clinit>".equals(method.getName())) - { - target.add(method); - } - } - Method[] retval = new Method[target.size()]; - target.toArray(retval); - Arrays.sort(retval, new MethodComparator()); - return retval; - } - /** * Creates a human readable String that is similar to the method signature * and identifies the method within a class. @@ -218,6 +335,13 @@ } buf.append(name); buf.append('('); + appendHumanReadableArgTypeList(method, buf); + buf.append(')'); + return buf.toString(); + } + + private void appendHumanReadableArgTypeList(Method method, StringBuffer buf) + { Type[] argTypes = method.getArgumentTypes(); String argSeparator = ""; for (int i = 0; i < argTypes.length; i++) @@ -226,8 +350,6 @@ buf.append(argTypes[i].toString()); argSeparator = ", "; } - buf.append(')'); - return buf.toString(); } private void fireDiff(String report, Severity severity, JavaClass clazz, Method method) |
From: Lars K?h. <lk...@us...> - 2004-05-22 13:21:53
|
Update of /cvsroot/clirr/clirr/src/test/net/sf/clirr/checks In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv20264/test/net/sf/clirr/checks Modified Files: MethodSetCheckTest.java Log Message: improved the way covariant methods matched when before comparing them Index: MethodSetCheckTest.java =================================================================== RCS file: /cvsroot/clirr/clirr/src/test/net/sf/clirr/checks/MethodSetCheckTest.java,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- MethodSetCheckTest.java 25 Jan 2004 08:16:46 -0000 1.2 +++ MethodSetCheckTest.java 22 May 2004 13:21:44 -0000 1.3 @@ -20,16 +20,8 @@ Severity.ERROR, "testlib.MethodsChange", "public void removedMethod(java.lang.String)", null), new ApiDifference("Method 'public int getPriv2()' has been removed in testlib.MethodsChange", Severity.ERROR, "testlib.MethodsChange", "public int getPriv2()", null), - new ApiDifference("Method 'public void printPriv()' has been removed in testlib.MethodsChange", - Severity.ERROR, "testlib.MethodsChange", "public void printPriv()", null), - - // parameter type changes - //new ApiDifference("Parameter type of method 'public void changeParamterType(java.lang.String)' has changed.", - // Severity.ERROR, "testlib.MethodsChange", "public void changeParamterType(java.lang.String)", null), - //new ApiDifference("Parameter type of method 'public void weakenParamterType(java.lang.String)' has changed.", - // Severity.ERROR, "testlib.MethodsChange", "public void weakenParamterType(java.lang.String)", null), - //new ApiDifference("Parameter type of method 'public void strengthenParamterType(java.lang.String)' has changed.", - // Severity.INFO, "testlib.MethodsChange", "public void strengthenParamterType(java.lang.Object)", null), + new ApiDifference("Method 'public java.lang.Long getPrivSquare()' has been added in testlib.MethodsChange", + Severity.INFO, "testlib.MethodsChange", "public java.lang.Long getPrivSquare()", null), // Constructor changes new ApiDifference("Parameter 1 of 'protected MethodsChange(int)' has changed it's type to java.lang.Integer in testlib.MethodsChange", @@ -47,6 +39,8 @@ // parameter list changes // Note: This is the current behaviour, not necessarily the spec of the desired behaviour // TODO: need to check assignability of types (and check if method or class is final?) + new ApiDifference("In Method 'public void printPriv()' the number of arguments has changed in testlib.MethodsChange", + Severity.ERROR, "testlib.MethodsChange", "public void printPriv()", null), new ApiDifference("Parameter 1 of 'public void strengthenParamType(java.lang.Object)' has changed it's type to java.lang.String in testlib.MethodsChange", Severity.ERROR, "testlib.MethodsChange", "public void strengthenParamType(java.lang.Object)", null), new ApiDifference("Parameter 1 of 'public void weakenParamType(java.lang.String)' has changed it's type to java.lang.Object in testlib.MethodsChange", @@ -54,6 +48,7 @@ new ApiDifference("Parameter 1 of 'public void changeParamType(java.lang.String)' has changed it's type to java.lang.Integer in testlib.MethodsChange", Severity.ERROR, "testlib.MethodsChange", "public void changeParamType(java.lang.String)", null), + // declared exceptions // TODO }; |
From: Lars K?h. <lk...@us...> - 2004-05-20 14:08:06
|
Update of /cvsroot/clirr/clirr/src/java/net/sf/clirr/checks In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv17796 Modified Files: InterfaceSetCheck.java Log Message: getAllInterfaces might return multiple array entries with the same interface, so we need to use sets to remove duplicates... use sets to eliminate duplicates and avoid false alarms Index: InterfaceSetCheck.java =================================================================== RCS file: /cvsroot/clirr/clirr/src/java/net/sf/clirr/checks/InterfaceSetCheck.java,v retrieving revision 1.6 retrieving revision 1.7 diff -u -r1.6 -r1.7 --- InterfaceSetCheck.java 27 Dec 2003 19:08:42 -0000 1.6 +++ InterfaceSetCheck.java 20 May 2004 14:07:57 -0000 1.7 @@ -56,17 +56,17 @@ // Note: an interface has itself in the set of all interfaces // we have to consider that below to avoid funny messages for gender changes - Set current = new HashSet(); - for (int i = 0; i < currentInterfaces.length; i++) - { - String currentInterface = currentInterfaces[i].getClassName(); - current.add(currentInterface); - } + // Note: getAllInterfaces might return multiple array entries with the same + // interface, so we need to use sets to remove duplicates... + Set compat = createClassSet(compatInterfaces); + Set current = createClassSet(currentInterfaces); final String className = compatBaseline.getClassName(); - for (int i = 0; i < compatInterfaces.length; i++) + + for (Iterator it = compat.iterator(); it.hasNext();) { - String compatInterface = compatInterfaces[i].getClassName(); + String compatInterface = (String) it.next(); + if (!current.contains(compatInterface) && !compatInterface.equals(className)) { @@ -93,4 +93,15 @@ } } } + + private Set createClassSet(JavaClass[] classes) + { + Set current = new HashSet(); + for (int i = 0; i < classes.length; i++) + { + String currentInterface = classes[i].getClassName(); + current.add(currentInterface); + } + return current; + } } |
From: Lars K?h. <lk...@us...> - 2004-05-20 13:28:12
|
Update of /cvsroot/clirr/clirr/xdocs In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv10351 Modified Files: index.xml Log Message: even more fun with umlauts Index: index.xml =================================================================== RCS file: /cvsroot/clirr/clirr/xdocs/index.xml,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- index.xml 20 May 2004 13:18:12 -0000 1.4 +++ index.xml 20 May 2004 13:28:02 -0000 1.5 @@ -1,3 +1,5 @@ +<?xml version="1.0" encoding="ISO-8859-1"?> + <document> <properties> <title>Clirr</title> |
From: Lars K?h. <lk...@us...> - 2004-05-20 13:18:47
|
Update of /cvsroot/clirr/clirr/xdocs In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv8718 Modified Files: anttask.xml Log Message: fix indentation of ant sample code Index: anttask.xml =================================================================== RCS file: /cvsroot/clirr/clirr/xdocs/anttask.xml,v retrieving revision 1.3 retrieving revision 1.4 diff -u -r1.3 -r1.4 --- anttask.xml 16 Oct 2003 05:41:46 -0000 1.3 +++ anttask.xml 20 May 2004 13:18:37 -0000 1.4 @@ -23,25 +23,25 @@ </p> <source> - <target name="checkbinarycompatibility" depends="build"> +<target name="checkbinarycompatibility" depends="build"> - <!-- buildtools.classpath should contain clirr.jar and the libraries it depends on --> + <!-- buildtools.classpath should contain clirr.jar and the libraries it depends on --> - <taskdef classpathref="buildtools.classpath" resource="clirrtask.properties"/> + <taskdef classpathref="buildtools.classpath" resource="clirrtask.properties"/> - <property name="jar.baseline" value="${ant.project.name}-${compatibility.baseline.version}.jar"/> + <property name="jar.baseline" value="${ant.project.name}-${compatibility.baseline.version}.jar"/> - <get src="${url.libbase}/${ant.project.name}/${jar.baseline}" dest="build/tmp/${jar.baseline}"/> + <get src="${url.libbase}/${ant.project.name}/${jar.baseline}" dest="build/tmp/${jar.baseline}"/> - <clirr> - <origfiles dir="build/tmp" includes="${jar.baseline}"/> - <newfiles dir="build/lib" includes="${jar.buildresult}"/> + <clirr> + <origfiles dir="build/tmp" includes="${jar.baseline}"/> + <newfiles dir="build/lib" includes="${jar.buildresult}"/> - <!-- <formatter type="xml" outfile="build/clirr.xml" /> --> - <!-- TODO: example for 3rd party classpath --> - </clirr> + <!-- <formatter type="xml" outfile="build/clirr.xml" /> --> + <!-- TODO: example for 3rd party classpath --> + </clirr> - </target> +</target> </source> </section> <section name="Parameters"> |
From: Lars K?h. <lk...@us...> - 2004-05-20 13:18:25
|
Update of /cvsroot/clirr/clirr/xdocs In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv8675 Modified Files: index.xml Log Message: those Umlauts are killing me... Index: index.xml =================================================================== RCS file: /cvsroot/clirr/clirr/xdocs/index.xml,v retrieving revision 1.3 retrieving revision 1.4 diff -u -r1.3 -r1.4 --- index.xml 28 Dec 2003 09:42:48 -0000 1.3 +++ index.xml 20 May 2004 13:18:12 -0000 1.4 @@ -1,7 +1,7 @@ <document> <properties> <title>Clirr</title> - <author>Lars Kühne</author> + <author>Lars Kühne</author> <meta name="keyword" content="java, api, diff, compare, jar, binary, compatibility, compatible, detect, incompatibility, incompatible"/> </properties> <body> @@ -65,4 +65,4 @@ </p> </section> </body> -</document> \ No newline at end of file +</document> |
From: Lars K?h. <lk...@us...> - 2004-05-20 13:16:05
|
Update of /cvsroot/clirr/clirr/src/java/net/sf/clirr/ant In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv8160 Modified Files: AntLogger.java Log Message: define the error format explicitly instead of relying on difference.toString() Index: AntLogger.java =================================================================== RCS file: /cvsroot/clirr/clirr/src/java/net/sf/clirr/ant/AntLogger.java,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- AntLogger.java 27 Dec 2003 17:44:59 -0000 1.4 +++ AntLogger.java 20 May 2004 13:15:55 -0000 1.5 @@ -46,6 +46,6 @@ { final Severity severity = difference.getSeverity(); final Integer prio = (Integer) severityPrioMap.get(severity); - task.log(difference.toString(), prio.intValue()); + task.log(severity.toString() + ": " + difference.getReport(), prio.intValue()); } } |
From: Lars K?h. <lk...@us...> - 2004-05-20 06:38:11
|
Update of /cvsroot/clirr/clirr/src/java/net/sf/clirr/event In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv1543 Modified Files: XmlDiffListener.java Log Message: fixed syntax error in XML output (was not well formed) Index: XmlDiffListener.java =================================================================== RCS file: /cvsroot/clirr/clirr/src/java/net/sf/clirr/event/XmlDiffListener.java,v retrieving revision 1.7 retrieving revision 1.8 diff -u -r1.7 -r1.8 --- XmlDiffListener.java 28 Dec 2003 09:39:47 -0000 1.7 +++ XmlDiffListener.java 20 May 2004 06:38:01 -0000 1.8 @@ -43,8 +43,8 @@ { PrintStream out = getOutputStream(); out.print(" <" + DIFFERENCE); - out.print(" severity=\"" + difference.getSeverity() + "\">"); - out.print(" class=\"" + difference.getAffectedClass() + "\""); + out.print(" severity=\"" + difference.getSeverity() + "\""); + out.print(" class=\"" + difference.getAffectedClass() + "\">"); if (difference.getAffectedMethod() != null) { out.print(" method=\"" + difference.getAffectedMethod() + "\""); @@ -67,14 +67,6 @@ PrintStream out = getOutputStream(); out.println("<?xml version=\"1.0\"?>"); out.println('<' + DIFFREPORT + '>'); - out.println("<!--"); - out.println(" In future versions the differences will have more attributes, e.g."); - out.println(" - affected package"); - out.println(" - affected class/interface"); - out.println(" - affected method, if any"); - out.println(" - change type (ADD/REMOVE/CHANGE)"); - out.println(" - ... anything else you need?"); - out.println("-->"); } |
From: Lars K?h. <lk...@us...> - 2004-01-26 09:35:29
|
Update of /cvsroot/clirr/clirr/src/java/net/sf/clirr/checks In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv28527/src/java/net/sf/clirr/checks Modified Files: MethodSetCheck.java Log Message: Implemented initial checking for parameter types and return types The current algorithm for finding matching methods between old and new class is very naive but should be sufficient to serve as a test for the framework (filtering of errors, etc.) There are a few other implementation limitations as well, see TODO comments in the code Index: MethodSetCheck.java =================================================================== RCS file: /cvsroot/clirr/clirr/src/java/net/sf/clirr/checks/MethodSetCheck.java,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- MethodSetCheck.java 18 Jan 2004 12:53:27 -0000 1.2 +++ MethodSetCheck.java 25 Jan 2004 08:16:45 -0000 1.3 @@ -1,11 +1,34 @@ +////////////////////////////////////////////////////////////////////////////// +// Clirr: compares two versions of a java library for binary compatibility +// Copyright (C) 2003 Lars Kühne +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +////////////////////////////////////////////////////////////////////////////// + package net.sf.clirr.checks; -import java.util.Comparator; +import java.util.ArrayList; import java.util.Arrays; +import java.util.Comparator; +import java.util.List; +import net.sf.clirr.event.ApiDifference; +import net.sf.clirr.event.Severity; import net.sf.clirr.framework.AbstractDiffReporter; -import net.sf.clirr.framework.ClassChangeCheck; import net.sf.clirr.framework.ApiDiffDispatcher; +import net.sf.clirr.framework.ClassChangeCheck; import org.apache.bcel.classfile.JavaClass; import org.apache.bcel.classfile.Method; import org.apache.bcel.generic.Type; @@ -21,7 +44,7 @@ { private class MethodComparator implements Comparator { - public int compare(Object o1, Object o2) + public final int compare(Object o1, Object o2) { Method m1 = (Method) o1; Method m2 = (Method) o2; @@ -30,44 +53,150 @@ String name2 = m2.getName(); final int nameComparison = name1.compareTo(name2); - // TODO: compare argcount - return nameComparison; + if (nameComparison == 0) + { + return m1.getArgumentTypes().length - m2.getArgumentTypes().length; + } + else + { + return nameComparison; + } } } + /** {@inheritDoc} */ public MethodSetCheck(ApiDiffDispatcher dispatcher) { super(dispatcher); } - public void check(JavaClass compatBaseline, JavaClass currentVersion) + public final void check(JavaClass compatBaseline, JavaClass currentVersion) { + // Dont't report method problems when gender has changed, as + // really the whole API is a pile of crap then - let GenderChange check + // do it's job, and that's it + if (compatBaseline.isInterface() ^ currentVersion.isInterface()) + { + return; + } + Method[] baselineMethods = sort(compatBaseline.getMethods()); Method[] currentMethods = sort(currentVersion.getMethods()); for (int i = 0; i < baselineMethods.length; i++) { Method baselineMethod = baselineMethods[i]; - System.out.println("baselineMethod " + i + "= " + getMethodId(compatBaseline, baselineMethod)); + + // TODO: We need a global perspective + // to determine which current method matches which baseline method. + + // simply checking the name and arg numbers won't be enough in all cases + // but I'll stick with it for now to get the framework out + + final int idx = Arrays.binarySearch(currentMethods, baselineMethod, new MethodComparator()); + if (idx < 0) + { + fireDiff("Method '" + getMethodId(compatBaseline, baselineMethod) + "' has been removed", + Severity.ERROR, compatBaseline, baselineMethod); + } + else + { + check(compatBaseline, baselineMethod, currentMethods[idx]); + } } } - private Method[] sort(Method[] methods) + private void check(JavaClass compatBaseline, Method baselineMethod, Method currentMethod) { + checkParameterTypes(compatBaseline, baselineMethod, currentMethod); + checkReturnType(compatBaseline, baselineMethod, currentMethod); + checkDeclaredExceptions(compatBaseline, baselineMethod, currentMethod); + } + + private void checkParameterTypes(JavaClass compatBaseline, Method baselineMethod, Method currentMethod) + { + Type[] bArgs = baselineMethod.getArgumentTypes(); + Type[] cArgs = currentMethod.getArgumentTypes(); + + // TODO: This currently never fires because of our poor method matching algorithm + if (bArgs.length != cArgs.length) + { + fireDiff("In Method '" + getMethodId(compatBaseline, baselineMethod) + + "' the number of arguments has changed", + Severity.ERROR, compatBaseline, baselineMethod); + return; + } + + //System.out.println("baselineMethod = " + getMethodId(compatBaseline, baselineMethod)); + for (int i = 0; i < bArgs.length; i++) + { + Type bArg = bArgs[i]; + Type cArg = cArgs[i]; + + if (bArg.toString().equals(cArg.toString())) + { + continue; + } + + // TODO: Check assignability... + fireDiff("Parameter " + (i + 1) + " of '" + getMethodId(compatBaseline, baselineMethod) + + "' has changed it's type to " + cArg, + Severity.ERROR, compatBaseline, baselineMethod); + } + } - Method[] retval = new Method[methods.length]; - // TODO: filter public + protected - // TODO: remove <clinit> - System.arraycopy(methods, 0, retval, 0, methods.length); + private void checkReturnType(JavaClass compatBaseline, Method baselineMethod, Method currentMethod) + { + Type bReturnType = baselineMethod.getReturnType(); + Type cReturnType = currentMethod.getReturnType(); + + // TODO: Check assignability... + if (!bReturnType.toString().equals(cReturnType.toString())) + { + fireDiff("Return type of Method '" + getMethodId(compatBaseline, baselineMethod) + + "' has been changed to " + cReturnType, + Severity.ERROR, compatBaseline, baselineMethod); + } + + + } + + private void checkDeclaredExceptions( + JavaClass compatBaseline, Method baselineMethod, Method currentMethod) + { + // TODO + } + + private Method[] sort(Method[] methods) + { + List target = new ArrayList(); + for (int i = 0; i < methods.length; i++) + { + final Method method = methods[i]; + if ((method.isPublic() || method.isProtected()) + && !"<clinit>".equals(method.getName())) + { + target.add(method); + } + } + Method[] retval = new Method[target.size()]; + target.toArray(retval); Arrays.sort(retval, new MethodComparator()); return retval; } + /** + * Creates a human readable String that is similar to the method signature + * and identifies the method within a class. + * @param clazz the container of the method + * @param method the method to identify. + * @return a human readable id, for example "public void print(java.lang.String)" + */ private String getMethodId(JavaClass clazz, Method method) { if (!method.isPublic() && !method.isProtected()) { - //throw new IllegalArgumentException(); + throw new IllegalArgumentException(); } StringBuffer buf = new StringBuffer(); @@ -82,6 +211,11 @@ int idx = className.lastIndexOf('.'); name = className.substring(idx + 1); } + else + { + buf.append(method.getReturnType()); + buf.append(' '); + } buf.append(name); buf.append('('); Type[] argTypes = method.getArgumentTypes(); @@ -95,4 +229,15 @@ buf.append(')'); return buf.toString(); } + + private void fireDiff(String report, Severity severity, JavaClass clazz, Method method) + { + final String className = clazz.getClassName(); + final ApiDifference diff = + new ApiDifference(report + " in " + className, + severity, className, getMethodId(clazz, method), null); + getApiDiffDispatcher().fireDiff(diff); + + } + } |
From: Lars K?h. <lk...@us...> - 2004-01-26 09:34:55
|
Update of /cvsroot/clirr/clirr/src/test/net/sf/clirr/checks In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv28527/src/test/net/sf/clirr/checks Modified Files: MethodSetCheckTest.java Log Message: Implemented initial checking for parameter types and return types The current algorithm for finding matching methods between old and new class is very naive but should be sufficient to serve as a test for the framework (filtering of errors, etc.) There are a few other implementation limitations as well, see TODO comments in the code Index: MethodSetCheckTest.java =================================================================== RCS file: /cvsroot/clirr/clirr/src/test/net/sf/clirr/checks/MethodSetCheckTest.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- MethodSetCheckTest.java 18 Jan 2004 12:04:59 -0000 1.1 +++ MethodSetCheckTest.java 25 Jan 2004 08:16:46 -0000 1.2 @@ -15,9 +15,13 @@ { ApiDifference[] expected = new ApiDifference[] { - // method visibility changes - //new ApiDifference("Accessibility of method 'public int getPriv2()' has been weakened in testlib.MethodsChange", - // Severity.ERROR, "testlib.MethodsChange", "public int getPriv2()", null), + // method addition and removal + new ApiDifference("Method 'public void removedMethod(java.lang.String)' has been removed in testlib.MethodsChange", + Severity.ERROR, "testlib.MethodsChange", "public void removedMethod(java.lang.String)", null), + new ApiDifference("Method 'public int getPriv2()' has been removed in testlib.MethodsChange", + Severity.ERROR, "testlib.MethodsChange", "public int getPriv2()", null), + new ApiDifference("Method 'public void printPriv()' has been removed in testlib.MethodsChange", + Severity.ERROR, "testlib.MethodsChange", "public void printPriv()", null), // parameter type changes //new ApiDifference("Parameter type of method 'public void changeParamterType(java.lang.String)' has changed.", @@ -28,27 +32,27 @@ // Severity.INFO, "testlib.MethodsChange", "public void strengthenParamterType(java.lang.Object)", null), // Constructor changes - /* - new ApiDifference("Method 'public void removedMethod(java.lang.String)' has been removed in testlib.MethodsChange", - Severity.ERROR, "testlib.MethodsChange", "public void removedMethod(java.lang.String)", null), - new ApiDifference("Constructor 'protected MethodsChange(int)' has been removed in testlib.MethodsChange", - Severity.ERROR, "testlib.MethodsChange", "public MethodsChange(int)", null), - new ApiDifference("Constructor 'protected MethodsChange(java.lang.Integer)' has been added in testlib.MethodsChange", - Severity.INFO, "testlib.MethodsChange", "public MethodsChange(java.lang.Integer)", null), - new ApiDifference("Constructor 'protected MethodsChange(int, boolean)' has been added in testlib.MethodsChange", - Severity.INFO, "testlib.MethodsChange", "public MethodsChange(int, boolean)", null), - */ + new ApiDifference("Parameter 1 of 'protected MethodsChange(int)' has changed it's type to java.lang.Integer in testlib.MethodsChange", + Severity.ERROR, "testlib.MethodsChange", "protected MethodsChange(int)", null), +// new ApiDifference("Constructor 'protected MethodsChange(int, boolean)' has been added in testlib.MethodsChange", +// Severity.INFO, "testlib.MethodsChange", "public MethodsChange(int, boolean)", null), // return type changes - /* - new ApiDifference("Return type of Method 'public java.lang.Number getPrivAsNumber()' has been changed to java.lang.Integer", - Severity.INFO, "testlib.MethodsChange", "public java.lang.Number getPrivAsNumber()", null), - new ApiDifference("Return type of Method 'public java.lang.Integer getPrivAsInteger()' has been changed to java.lang.Number", + new ApiDifference("Return type of Method 'public java.lang.Number getPrivAsNumber()' has been changed to java.lang.Integer in testlib.MethodsChange", + Severity.ERROR, "testlib.MethodsChange", "public java.lang.Number getPrivAsNumber()", null), + // TODO: INFO if method is final + new ApiDifference("Return type of Method 'public java.lang.Integer getPrivAsInteger()' has been changed to java.lang.Number in testlib.MethodsChange", Severity.ERROR, "testlib.MethodsChange", "public java.lang.Integer getPrivAsInteger()", null), - */ // parameter list changes - // TODO + // Note: This is the current behaviour, not necessarily the spec of the desired behaviour + // TODO: need to check assignability of types (and check if method or class is final?) + new ApiDifference("Parameter 1 of 'public void strengthenParamType(java.lang.Object)' has changed it's type to java.lang.String in testlib.MethodsChange", + Severity.ERROR, "testlib.MethodsChange", "public void strengthenParamType(java.lang.Object)", null), + new ApiDifference("Parameter 1 of 'public void weakenParamType(java.lang.String)' has changed it's type to java.lang.Object in testlib.MethodsChange", + Severity.ERROR, "testlib.MethodsChange", "public void weakenParamType(java.lang.String)", null), + new ApiDifference("Parameter 1 of 'public void changeParamType(java.lang.String)' has changed it's type to java.lang.Integer in testlib.MethodsChange", + Severity.ERROR, "testlib.MethodsChange", "public void changeParamType(java.lang.String)", null), // declared exceptions // TODO |
From: Lars K?h. <lk...@us...> - 2004-01-18 12:53:32
|
Update of /cvsroot/clirr/clirr/src/java/net/sf/clirr/checks In directory sc8-pr-cvs1:/tmp/cvs-serv19670/src/java/net/sf/clirr/checks Modified Files: MethodSetCheck.java Log Message: added helper method to generate method signature in error messages Index: MethodSetCheck.java =================================================================== RCS file: /cvsroot/clirr/clirr/src/java/net/sf/clirr/checks/MethodSetCheck.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- MethodSetCheck.java 18 Jan 2004 12:04:59 -0000 1.1 +++ MethodSetCheck.java 18 Jan 2004 12:53:27 -0000 1.2 @@ -1,10 +1,14 @@ package net.sf.clirr.checks; +import java.util.Comparator; +import java.util.Arrays; + import net.sf.clirr.framework.AbstractDiffReporter; import net.sf.clirr.framework.ClassChangeCheck; import net.sf.clirr.framework.ApiDiffDispatcher; import org.apache.bcel.classfile.JavaClass; import org.apache.bcel.classfile.Method; +import org.apache.bcel.generic.Type; /** * Checks the methods of a class. @@ -15,6 +19,22 @@ extends AbstractDiffReporter implements ClassChangeCheck { + private class MethodComparator implements Comparator + { + public int compare(Object o1, Object o2) + { + Method m1 = (Method) o1; + Method m2 = (Method) o2; + + String name1 = m1.getName(); + String name2 = m2.getName(); + + final int nameComparison = name1.compareTo(name2); + // TODO: compare argcount + return nameComparison; + } + } + public MethodSetCheck(ApiDiffDispatcher dispatcher) { super(dispatcher); @@ -22,22 +42,57 @@ public void check(JavaClass compatBaseline, JavaClass currentVersion) { - Method[] baselineMethods = compatBaseline.getMethods(); - Method[] currentMethods = currentVersion.getMethods(); + Method[] baselineMethods = sort(compatBaseline.getMethods()); + Method[] currentMethods = sort(currentVersion.getMethods()); - for (int i = 0; i < currentMethods.length; i++) + for (int i = 0; i < baselineMethods.length; i++) { - Method currentMethod = currentMethods[i]; - System.out.println("currentMethod " + i + "= " + currentMethod); + Method baselineMethod = baselineMethods[i]; + System.out.println("baselineMethod " + i + "= " + getMethodId(compatBaseline, baselineMethod)); } } - /** - * Returns an identifier for the method. If the ID has't changed - * @return - */ - private String getMethodId() + private Method[] sort(Method[] methods) { - return null; + + Method[] retval = new Method[methods.length]; + // TODO: filter public + protected + // TODO: remove <clinit> + System.arraycopy(methods, 0, retval, 0, methods.length); + Arrays.sort(retval, new MethodComparator()); + return retval; + } + + private String getMethodId(JavaClass clazz, Method method) + { + if (!method.isPublic() && !method.isProtected()) + { + //throw new IllegalArgumentException(); + } + + StringBuffer buf = new StringBuffer(); + + buf.append(method.isPublic() ? "public" : "protected"); + buf.append(" "); + + String name = method.getName(); + if ("<init>".equals(name)) + { + final String className = clazz.getClassName(); + int idx = className.lastIndexOf('.'); + name = className.substring(idx + 1); + } + buf.append(name); + buf.append('('); + Type[] argTypes = method.getArgumentTypes(); + String argSeparator = ""; + for (int i = 0; i < argTypes.length; i++) + { + buf.append(argSeparator); + buf.append(argTypes[i].toString()); + argSeparator = ", "; + } + buf.append(')'); + return buf.toString(); } } |
From: Lars K?h. <lk...@us...> - 2004-01-18 12:05:02
|
Update of /cvsroot/clirr/clirr/src/java/net/sf/clirr In directory sc8-pr-cvs1:/tmp/cvs-serv11756/src/java/net/sf/clirr Modified Files: Checker.java Log Message: added infrastructure for method check Index: Checker.java =================================================================== RCS file: /cvsroot/clirr/clirr/src/java/net/sf/clirr/Checker.java,v retrieving revision 1.8 retrieving revision 1.9 diff -u -r1.8 -r1.9 --- Checker.java 31 Dec 2003 09:48:08 -0000 1.8 +++ Checker.java 18 Jan 2004 12:04:59 -0000 1.9 @@ -39,6 +39,7 @@ import net.sf.clirr.checks.InterfaceSetCheck; import net.sf.clirr.checks.RemovedClassCheck; import net.sf.clirr.checks.FieldSetCheck; +import net.sf.clirr.checks.MethodSetCheck; import net.sf.clirr.event.ApiDifference; import net.sf.clirr.event.DiffListener; import net.sf.clirr.framework.ApiDiffDispatcher; @@ -99,6 +100,7 @@ classChecks.add(new InterfaceSetCheck(this)); classChecks.add(new ClassHierarchyCheck(this)); classChecks.add(new FieldSetCheck(this)); + classChecks.add(new MethodSetCheck(this)); } public void addDiffListener(DiffListener listener) |
From: Lars K?h. <lk...@us...> - 2004-01-18 12:05:02
|
Update of /cvsroot/clirr/clirr/src/test/net/sf/clirr/checks In directory sc8-pr-cvs1:/tmp/cvs-serv11756/src/test/net/sf/clirr/checks Added Files: MethodSetCheckTest.java Log Message: added infrastructure for method check --- NEW FILE --- package net.sf.clirr.checks; import net.sf.clirr.framework.ClassChangeCheck; import net.sf.clirr.event.ApiDifference; import net.sf.clirr.event.Severity; /** * TODO: Docs. * * @author lkuehne */ public class MethodSetCheckTest extends AbstractCheckTestCase { public void testMethodCheck() { ApiDifference[] expected = new ApiDifference[] { // method visibility changes //new ApiDifference("Accessibility of method 'public int getPriv2()' has been weakened in testlib.MethodsChange", // Severity.ERROR, "testlib.MethodsChange", "public int getPriv2()", null), // parameter type changes //new ApiDifference("Parameter type of method 'public void changeParamterType(java.lang.String)' has changed.", // Severity.ERROR, "testlib.MethodsChange", "public void changeParamterType(java.lang.String)", null), //new ApiDifference("Parameter type of method 'public void weakenParamterType(java.lang.String)' has changed.", // Severity.ERROR, "testlib.MethodsChange", "public void weakenParamterType(java.lang.String)", null), //new ApiDifference("Parameter type of method 'public void strengthenParamterType(java.lang.String)' has changed.", // Severity.INFO, "testlib.MethodsChange", "public void strengthenParamterType(java.lang.Object)", null), // Constructor changes /* new ApiDifference("Method 'public void removedMethod(java.lang.String)' has been removed in testlib.MethodsChange", Severity.ERROR, "testlib.MethodsChange", "public void removedMethod(java.lang.String)", null), new ApiDifference("Constructor 'protected MethodsChange(int)' has been removed in testlib.MethodsChange", Severity.ERROR, "testlib.MethodsChange", "public MethodsChange(int)", null), new ApiDifference("Constructor 'protected MethodsChange(java.lang.Integer)' has been added in testlib.MethodsChange", Severity.INFO, "testlib.MethodsChange", "public MethodsChange(java.lang.Integer)", null), new ApiDifference("Constructor 'protected MethodsChange(int, boolean)' has been added in testlib.MethodsChange", Severity.INFO, "testlib.MethodsChange", "public MethodsChange(int, boolean)", null), */ // return type changes /* new ApiDifference("Return type of Method 'public java.lang.Number getPrivAsNumber()' has been changed to java.lang.Integer", Severity.INFO, "testlib.MethodsChange", "public java.lang.Number getPrivAsNumber()", null), new ApiDifference("Return type of Method 'public java.lang.Integer getPrivAsInteger()' has been changed to java.lang.Number", Severity.ERROR, "testlib.MethodsChange", "public java.lang.Integer getPrivAsInteger()", null), */ // parameter list changes // TODO // declared exceptions // TODO }; verify(expected); } protected final ClassChangeCheck createCheck(TestDiffListener tdl) { return new MethodSetCheck(tdl); } } |
From: Lars K?h. <lk...@us...> - 2004-01-18 12:05:02
|
Update of /cvsroot/clirr/clirr/src/java/net/sf/clirr/checks In directory sc8-pr-cvs1:/tmp/cvs-serv11756/src/java/net/sf/clirr/checks Added Files: MethodSetCheck.java Log Message: added infrastructure for method check --- NEW FILE --- package net.sf.clirr.checks; import net.sf.clirr.framework.AbstractDiffReporter; import net.sf.clirr.framework.ClassChangeCheck; import net.sf.clirr.framework.ApiDiffDispatcher; import org.apache.bcel.classfile.JavaClass; import org.apache.bcel.classfile.Method; /** * Checks the methods of a class. * * @author lkuehne */ public class MethodSetCheck extends AbstractDiffReporter implements ClassChangeCheck { public MethodSetCheck(ApiDiffDispatcher dispatcher) { super(dispatcher); } public void check(JavaClass compatBaseline, JavaClass currentVersion) { Method[] baselineMethods = compatBaseline.getMethods(); Method[] currentMethods = currentVersion.getMethods(); for (int i = 0; i < currentMethods.length; i++) { Method currentMethod = currentMethods[i]; System.out.println("currentMethod " + i + "= " + currentMethod); } } /** * Returns an identifier for the method. If the ID has't changed * @return */ private String getMethodId() { return null; } } |
From: Lars K?h. <lk...@us...> - 2004-01-18 12:02:01
|
Update of /cvsroot/clirr/clirr/src/testinput/testlib-v2/testlib In directory sc8-pr-cvs1:/tmp/cvs-serv11339/testlib-v2/testlib Added Files: MethodsChange.java Log Message: added test class for Method checking --- NEW FILE --- package testlib; import java.io.IOException; public class MethodsChange { private int priv; public MethodsChange() { priv = 2; } protected MethodsChange(int initialpriv, boolean newArg) { priv = initialpriv; } protected MethodsChange(Integer initialpriv) { priv = initialpriv.intValue(); } public int getPriv() { return priv; } private int getPriv2() { return priv; } public Integer getPrivAsNumber() { return new Integer(priv); } public Number getPrivAsInteger() { return new Integer(priv); } public Long getPrivSquare() { return new Long(priv * priv); } public void printPriv(String prefix) { System.out.println(prefix + priv); } public void weakenParamType(Object s) { } public void strengthenParamType(String s) { } public void changeParamType(Integer x) { } public void throwIOException() throws Exception { throw new java.io.IOException(); } public void throwException() throws IOException { throw new java.io.IOException(); } public void throwException2() { } public void throwRuntimeException() { throw new RuntimeException(); } public void throwNoRuntimeException() throws RuntimeException { throw new RuntimeException(); } public void throwNoException() throws Exception { throw new Exception(); } } |
From: Lars K?h. <lk...@us...> - 2004-01-18 12:02:01
|
Update of /cvsroot/clirr/clirr/src/testinput/testlib-v1/testlib In directory sc8-pr-cvs1:/tmp/cvs-serv11339/testlib-v1/testlib Added Files: MethodsChange.java Log Message: added test class for Method checking --- NEW FILE --- package testlib; import java.io.IOException; public class MethodsChange { private int priv; static { System.out.println("static initializer"); } { System.out.println("non-static initializer"); } public MethodsChange() { priv = 2; } protected MethodsChange(int initialpriv) { priv = initialpriv; } public int getPriv() { return priv; } public int getPriv2() { return priv; } public Integer getPrivAsInteger() { return new Integer(priv); } public Number getPrivAsNumber() { return new Integer(priv); } public void printPriv() { System.out.println(priv); } public void removedMethod(String x) { } public void weakenParamType(String s) { } public void strengthenParamType(Object s) { } public void changeParamType(String s) { } public void throwIOException() throws IOException { throw new java.io.IOException(); } public void throwException() throws Exception { throw new java.io.IOException(); } public void throwException2() throws Exception { throw new Exception(); } public void throwRuntimeException() throws RuntimeException { throw new RuntimeException(); } public void throwNoRuntimeException() { } public void throwNoException() { } } |
From: Lars K?h. <lk...@us...> - 2004-01-11 14:53:50
|
Update of /cvsroot/clirr/clirr/src/java/net/sf/clirr/checks In directory sc8-pr-cvs1:/tmp/cvs-serv22034/src/java/net/sf/clirr/checks Modified Files: FieldSetCheck.java Log Message: some todo comments Index: FieldSetCheck.java =================================================================== RCS file: /cvsroot/clirr/clirr/src/java/net/sf/clirr/checks/FieldSetCheck.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- FieldSetCheck.java 31 Dec 2003 09:48:08 -0000 1.1 +++ FieldSetCheck.java 11 Jan 2004 14:53:47 -0000 1.2 @@ -119,6 +119,8 @@ } // TODO: Check field types + + // TODO: warn about constant value changes (see JLS, section 13.4.8) } private void checkForModifierChange(Field bField, Field cField, JavaClass clazz) @@ -143,7 +145,10 @@ fireDiff("Field " + bField.getName() + " is now static", Severity.ERROR, clazz, cField); } - // TODO: What about transient and volatile? + // JLS, 13.4.10: Adding or deleting a transient modifier of a field + // does not break compatibility with pre-existing binaries + + // TODO: What about volatile? } private void checkForVisibilityChange(Field bField, Field cField, JavaClass clazz) |
From: Lars K?h. <lk...@us...> - 2003-12-31 09:50:42
|
Update of /cvsroot/clirr/clirr/src/java/net/sf/clirr/event In directory sc8-pr-cvs1:/tmp/cvs-serv18357/src/java/net/sf/clirr/event Modified Files: ApiDifference.java Log Message: fixed formating Index: ApiDifference.java =================================================================== RCS file: /cvsroot/clirr/clirr/src/java/net/sf/clirr/event/ApiDifference.java,v retrieving revision 1.7 retrieving revision 1.8 diff -u -r1.7 -r1.8 --- ApiDifference.java 31 Dec 2003 09:46:30 -0000 1.7 +++ ApiDifference.java 31 Dec 2003 09:50:37 -0000 1.8 @@ -68,7 +68,7 @@ /** * Create a new API differnce representation. * - * @param report a human readable string describing the change that was made. + * @param report a human readable string describing the change that was made. * @param severity the severity in terms of binary API compatibility. */ public ApiDifference(String report, Severity severity, String clazz, String method, String field) @@ -124,7 +124,7 @@ public String toString() { return report + " (" + severity + ") - " - + getAffectedClass() + '[' + getAffectedField() + '/'+ getAffectedMethod() + ']'; + + getAffectedClass() + '[' + getAffectedField() + '/' + getAffectedMethod() + ']'; } /** |
From: Lars K?h. <lk...@us...> - 2003-12-31 09:48:12
|
Update of /cvsroot/clirr/clirr/src/java/net/sf/clirr In directory sc8-pr-cvs1:/tmp/cvs-serv18037/src/java/net/sf/clirr Modified Files: Checker.java Log Message: added check for detecting changed fields Index: Checker.java =================================================================== RCS file: /cvsroot/clirr/clirr/src/java/net/sf/clirr/Checker.java,v retrieving revision 1.7 retrieving revision 1.8 diff -u -r1.7 -r1.8 --- Checker.java 28 Dec 2003 09:39:48 -0000 1.7 +++ Checker.java 31 Dec 2003 09:48:08 -0000 1.8 @@ -38,6 +38,7 @@ import net.sf.clirr.checks.GenderChangeCheck; import net.sf.clirr.checks.InterfaceSetCheck; import net.sf.clirr.checks.RemovedClassCheck; +import net.sf.clirr.checks.FieldSetCheck; import net.sf.clirr.event.ApiDifference; import net.sf.clirr.event.DiffListener; import net.sf.clirr.framework.ApiDiffDispatcher; @@ -97,6 +98,7 @@ classChecks.add(new ClassModifierCheck(this)); classChecks.add(new InterfaceSetCheck(this)); classChecks.add(new ClassHierarchyCheck(this)); + classChecks.add(new FieldSetCheck(this)); } public void addDiffListener(DiffListener listener) |
From: Lars K?h. <lk...@us...> - 2003-12-31 09:48:12
|
Update of /cvsroot/clirr/clirr/src/test/net/sf/clirr/checks In directory sc8-pr-cvs1:/tmp/cvs-serv18037/src/test/net/sf/clirr/checks Added Files: FieldSetCheckTest.java Log Message: added check for detecting changed fields --- NEW FILE --- package net.sf.clirr.checks; import net.sf.clirr.event.ApiDifference; import net.sf.clirr.event.Severity; import net.sf.clirr.framework.ClassChangeCheck; /** * Tests FieldSetCheck. * * @author lkuehne */ public class FieldSetCheckTest extends AbstractCheckTestCase { public void testFieldCheck() { ApiDifference[] expected = new ApiDifference[] { new ApiDifference("Field stat7 has been removed in testlib.MembersChange", Severity.ERROR, "testlib.MembersChange", null, "stat7"), new ApiDifference("Accessibility of field fin2 has been weakened in testlib.MembersChange", Severity.ERROR, "testlib.MembersChange", null, "fin2"), new ApiDifference("Accessibility of field stat4 has been weakened in testlib.MembersChange", Severity.ERROR, "testlib.MembersChange", null, "stat4"), new ApiDifference("Added public field priv2 in testlib.MembersChange", Severity.INFO, "testlib.MembersChange", null, "priv2"), new ApiDifference("Accessibility of field stat5 has been weakened in testlib.MembersChange", Severity.ERROR, "testlib.MembersChange", null, "stat5"), new ApiDifference("Field stat2 is now final in testlib.MembersChange", Severity.ERROR, "testlib.MembersChange", null, "stat2"), new ApiDifference("Accessibility of field stat6 has been weakened in testlib.MembersChange", Severity.ERROR, "testlib.MembersChange", null, "stat6"), new ApiDifference("Field stat2 is now static in testlib.MembersChange", Severity.ERROR, "testlib.MembersChange", null, "stat2"), new ApiDifference("Added public field stat8 in testlib.MembersChange", Severity.INFO, "testlib.MembersChange", null, "stat8"), new ApiDifference("Field fin4 is now non-final in testlib.MembersChange", Severity.INFO, "testlib.MembersChange", null, "fin4") }; verify(expected); } protected final ClassChangeCheck createCheck(TestDiffListener tdl) { return new FieldSetCheck(tdl); } } |
From: Lars K?h. <lk...@us...> - 2003-12-31 09:48:12
|
Update of /cvsroot/clirr/clirr/src/java/net/sf/clirr/checks In directory sc8-pr-cvs1:/tmp/cvs-serv18037/src/java/net/sf/clirr/checks Added Files: FieldSetCheck.java Log Message: added check for detecting changed fields --- NEW FILE --- ////////////////////////////////////////////////////////////////////////////// // Clirr: compares two versions of a java library for binary compatibility // Copyright (C) 2003 Lars Kühne // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ////////////////////////////////////////////////////////////////////////////// package net.sf.clirr.checks; import java.util.Arrays; import java.util.Comparator; import net.sf.clirr.framework.ClassChangeCheck; import net.sf.clirr.framework.AbstractDiffReporter; import net.sf.clirr.framework.ApiDiffDispatcher; import net.sf.clirr.event.ApiDifference; import net.sf.clirr.event.Severity; import org.apache.bcel.classfile.JavaClass; import org.apache.bcel.classfile.Field; /** * Checks the fields of a class. * * @author lkuehne */ public class FieldSetCheck extends AbstractDiffReporter implements ClassChangeCheck { private static final class FieldNameComparator implements Comparator { public int compare(Object o1, Object o2) { Field f1 = (Field) o1; Field f2 = (Field) o2; final String name1 = f1.getName(); final String name2 = f2.getName(); if (name1 == null || name2 == null) { System.out.println("name2 = " + name2); System.out.println("name1 = " + name1); } return name1.compareTo(name2); } } private Comparator comparator = new FieldNameComparator(); public FieldSetCheck(ApiDiffDispatcher dispatcher) { super(dispatcher); } public final void check(JavaClass compatBaseline, JavaClass currentVersion) { final Field[] baselineFields = compatBaseline.getFields(); final Field[] currentFields = currentVersion.getFields(); // Sigh... BCEL 5.1 hands out it's internal datastructure, // so we have to make a copy here to make sure we don't mess up BCEL by sorting final Field[] bFields = createSortedCopy(baselineFields); final Field[] cFields = createSortedCopy(currentFields); checkForChanges(bFields, cFields, compatBaseline, currentVersion); } private void checkForChanges( Field[] bFields, Field[] cFields, JavaClass baseLineClass, JavaClass currentClass) { boolean[] newInCurrent = new boolean[cFields.length]; Arrays.fill(newInCurrent, true); for (int i = 0; i < bFields.length; i++) { Field bField = bFields[i]; if (!bField.isPublic() && !bField.isProtected()) { continue; } int cIdx = Arrays.binarySearch(cFields, bField, comparator); if (cIdx < 0) { final String name = bField.getName(); fireDiff("Field " + name + " has been removed", Severity.ERROR, baseLineClass, bField); } else { Field cField = cFields[cIdx]; newInCurrent[cIdx] = false; checkForModifierChange(bField, cField, currentClass); checkForVisibilityChange(bField, cField, currentClass); } } for (int i = 0; i < newInCurrent.length; i++) { Field field = cFields[i]; if (newInCurrent[i] && (field.isPublic() || field.isProtected())) { String scope = field.isPublic() ? "public" : "protected"; final String fieldName = field.getName(); fireDiff("Added " + scope + " field " + fieldName, Severity.INFO, currentClass, field); } } // TODO: Check field types } private void checkForModifierChange(Field bField, Field cField, JavaClass clazz) { if (bField.isFinal() && !cField.isFinal()) { fireDiff("Field " + bField.getName() + " is now non-final", Severity.INFO, clazz, cField); } if (!bField.isFinal() && cField.isFinal()) { fireDiff("Field " + bField.getName() + " is now final", Severity.ERROR, clazz, cField); } if (!bField.isStatic() && cField.isStatic()) { fireDiff("Field " + bField.getName() + " is now non-static", Severity.ERROR, clazz, cField); } if (!bField.isFinal() && cField.isFinal()) { fireDiff("Field " + bField.getName() + " is now static", Severity.ERROR, clazz, cField); } // TODO: What about transient and volatile? } private void checkForVisibilityChange(Field bField, Field cField, JavaClass clazz) { if (bField.isProtected() && cField.isPublic()) { fireDiff("Field " + bField.getName() + " is now public", Severity.INFO, clazz, cField); } else if (bField.isProtected() && !(cField.isProtected() || cField.isPublic()) || bField.isPublic() && !cField.isPublic()) { fireDiff("Accessibility of field " + bField.getName() + " has been weakened", Severity.ERROR, clazz, cField); } } private void fireDiff(String report, Severity severity, JavaClass clazz, Field field) { final String className = clazz.getClassName(); final ApiDifference diff = new ApiDifference(report + " in " + className, severity, className, null, field.getName()); getApiDiffDispatcher().fireDiff(diff); } private Field[] createSortedCopy(final Field[] orig) { final Field[] fields = new Field[orig.length]; System.arraycopy(orig, 0, fields, 0, orig.length); Arrays.sort(fields, comparator); return fields; } } |
From: Lars K?h. <lk...@us...> - 2003-12-31 09:46:34
|
Update of /cvsroot/clirr/clirr/src/java/net/sf/clirr/event In directory sc8-pr-cvs1:/tmp/cvs-serv17844/src/java/net/sf/clirr/event Modified Files: ApiDifference.java Log Message: improved failure message Index: ApiDifference.java =================================================================== RCS file: /cvsroot/clirr/clirr/src/java/net/sf/clirr/event/ApiDifference.java,v retrieving revision 1.6 retrieving revision 1.7 diff -u -r1.6 -r1.7 --- ApiDifference.java 28 Dec 2003 09:39:47 -0000 1.6 +++ ApiDifference.java 31 Dec 2003 09:46:30 -0000 1.7 @@ -123,7 +123,8 @@ */ public String toString() { - return report + " (" + severity + ')'; + return report + " (" + severity + ") - " + + getAffectedClass() + '[' + getAffectedField() + '/'+ getAffectedMethod() + ']'; } /** |