diff options
author | Elliott Hughes <enh@google.com> | 2009-11-09 23:49:43 -0800 |
---|---|---|
committer | Elliott Hughes <enh@google.com> | 2009-11-09 23:49:43 -0800 |
commit | 03ead3365d0d9d90ee4e40c70334a323022de8c4 (patch) | |
tree | d5bb7beaee1e122ccd4b4bf15a28049442eeb136 /tools/apicheck/src/com/android | |
parent | 9dd765ff2c85bd33334ebd3876bde005bdf5ce8d (diff) | |
download | build-03ead3365d0d9d90ee4e40c70334a323022de8c4.zip build-03ead3365d0d9d90ee4e40c70334a323022de8c4.tar.gz build-03ead3365d0d9d90ee4e40c70334a323022de8c4.tar.bz2 |
Teach apicheck about interface methods.
If a method is declared by an interface implemented directly by a class,
or indirectly by any of its superclasses, removing a duplicate declaration
is not an API change.
(This fixes the master build, which is currently broken because getOption
and setOption were removed from DatagramSocketImpl because they were
duplicate declarations of the same methods in the implemented interface
SocketOptions.)
Diffstat (limited to 'tools/apicheck/src/com/android')
-rw-r--r-- | tools/apicheck/src/com/android/apicheck/ApiInfo.java | 11 | ||||
-rw-r--r-- | tools/apicheck/src/com/android/apicheck/ClassInfo.java | 37 |
2 files changed, 41 insertions, 7 deletions
diff --git a/tools/apicheck/src/com/android/apicheck/ApiInfo.java b/tools/apicheck/src/com/android/apicheck/ApiInfo.java index 01d8f9e..c237814 100644 --- a/tools/apicheck/src/com/android/apicheck/ApiInfo.java +++ b/tools/apicheck/src/com/android/apicheck/ApiInfo.java @@ -26,8 +26,19 @@ public class ApiInfo { mPackages = new HashMap<String, PackageInfo>(); mAllClasses = new HashMap<String, ClassInfo>(); } + + public ClassInfo findClass(String name) { + return mAllClasses.get(name); + } + + private void resolveInterfaces() { + for (ClassInfo c : mAllClasses.values()) { + c.resolveInterfaces(this); + } + } public boolean isConsistent(ApiInfo otherApi) { + resolveInterfaces(); boolean consistent = true; for (PackageInfo pInfo : mPackages.values()) { if (otherApi.getPackages().containsKey(pInfo.name())) { diff --git a/tools/apicheck/src/com/android/apicheck/ClassInfo.java b/tools/apicheck/src/com/android/apicheck/ClassInfo.java index d4416f4..e62a3d0 100644 --- a/tools/apicheck/src/com/android/apicheck/ClassInfo.java +++ b/tools/apicheck/src/com/android/apicheck/ClassInfo.java @@ -26,7 +26,8 @@ public class ClassInfo { private boolean mIsFinal; private String mDeprecated; private String mScope; - private List<String> mInterfaces; + private List<String> mInterfaceNames; + private List<ClassInfo> mInterfaces; private HashMap<String, MethodInfo> mMethods; private HashMap<String, FieldInfo> mFields; private HashMap<String, ConstructorInfo> mConstructors; @@ -48,7 +49,8 @@ public class ClassInfo { mIsFinal = isFinal; mDeprecated = deprecated; mScope = visibility; - mInterfaces = new ArrayList<String>(); + mInterfaceNames = new ArrayList<String>(); + mInterfaces = new ArrayList<ClassInfo>(); mMethods = new HashMap<String, MethodInfo>(); mFields = new HashMap<String, FieldInfo>(); mConstructors = new HashMap<String, ConstructorInfo>(); @@ -109,6 +111,18 @@ public class ClassInfo { return null; } + // Find a superinterface declaration of the given method. + public MethodInfo interfaceMethod(MethodInfo candidate) { + for (ClassInfo interfaceInfo : mInterfaces) { + for (MethodInfo mi : interfaceInfo.mMethods.values()) { + if (mi.matches(candidate)) { + return mi; + } + } + } + return (mSuperClass != null) ? mSuperClass.interfaceMethod(candidate) : null; + } + public boolean isConsistent(ClassInfo cl) { cl.mExistsInBoth = true; mExistsInBoth = true; @@ -120,18 +134,18 @@ public class ClassInfo { + " changed class/interface declaration"); consistent = false; } - for (String iface : mInterfaces) { + for (String iface : mInterfaceNames) { boolean found = false; for (ClassInfo c = cl; c != null && !found; c = c.mSuperClass) { - found = c.mInterfaces.contains(iface); + found = c.mInterfaceNames.contains(iface); } if (!found) { Errors.error(Errors.REMOVED_INTERFACE, cl.position(), "Class " + qualifiedName() + " no longer implements " + iface); } } - for (String iface : cl.mInterfaces) { - if (!mInterfaces.contains(iface)) { + for (String iface : cl.mInterfaceNames) { + if (!mInterfaceNames.contains(iface)) { Errors.error(Errors.ADDED_INTERFACE, cl.position(), "Added interface " + iface + " to class " + qualifiedName()); @@ -151,6 +165,9 @@ public class ClassInfo { */ MethodInfo mi = mInfo.containingClass().overriddenMethod(mInfo); if (mi == null) { + mi = mInfo.containingClass().interfaceMethod(mInfo); + } + if (mi == null) { Errors.error(Errors.REMOVED_METHOD, mInfo.position(), "Removed public method " + mInfo.qualifiedName()); consistent = false; @@ -256,9 +273,15 @@ public class ClassInfo { return consistent; } + + public void resolveInterfaces(ApiInfo apiInfo) { + for (String interfaceName : mInterfaceNames) { + mInterfaces.add(apiInfo.findClass(interfaceName)); + } + } public void addInterface(String name) { - mInterfaces.add(name); + mInterfaceNames.add(name); } public void addMethod(MethodInfo mInfo) { |