summaryrefslogtreecommitdiffstats
path: root/tools/apicheck
diff options
context:
space:
mode:
authorElliott Hughes <enh@google.com>2009-11-09 23:49:43 -0800
committerElliott Hughes <enh@google.com>2009-11-09 23:49:43 -0800
commit03ead3365d0d9d90ee4e40c70334a323022de8c4 (patch)
treed5bb7beaee1e122ccd4b4bf15a28049442eeb136 /tools/apicheck
parent9dd765ff2c85bd33334ebd3876bde005bdf5ce8d (diff)
downloadbuild-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')
-rw-r--r--tools/apicheck/src/com/android/apicheck/ApiInfo.java11
-rw-r--r--tools/apicheck/src/com/android/apicheck/ClassInfo.java37
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) {