Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 32fd7632 authored by Jesse Wilson's avatar Jesse Wilson
Browse files

Fixing apicheck to cope with interfaces inherited from other interfaces.

For example, in Java 5, FutureTask was declared like this:
    public class FutureTask<V> implements Runnable, Future<V> {}

In Java 6, it's declared like this:
    public class FutureTask<V> implements RunnableFuture<V> {}
    public interface RunnableFuture extends Runnable, Future<V> {}

Change-Id: I0cd66a655fbe7fd5c7c48099d656b7a39368dac4
parent f47dc063
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -107,6 +107,7 @@ public class ApiCheck {
            xmlreader.parse(new InputSource(fileReader));
            ApiInfo apiInfo = handler.getApi();
            apiInfo.resolveSuperclasses();
            apiInfo.resolveInterfaces();
            return apiInfo;
        } catch (SAXParseException e) {
            Errors.error(Errors.PARSE_ERROR,
+1 −2
Original line number Diff line number Diff line
@@ -31,14 +31,13 @@ public class ApiInfo {
        return mAllClasses.get(name);
    }

    private void resolveInterfaces() {
    public 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())) {
+21 −5
Original line number Diff line number Diff line
@@ -135,11 +135,7 @@ public class ClassInfo {
            consistent = false;
        }
        for (String iface : mInterfaceNames) {
            boolean found = false;
            for (ClassInfo c = cl; c != null && !found; c = c.mSuperClass) {
                found = c.mInterfaceNames.contains(iface);
            }
            if (!found) {
            if (!implementsInterface(cl, iface)) {
                Errors.error(Errors.REMOVED_INTERFACE, cl.position(),
                        "Class " + qualifiedName() + " no longer implements " + iface);
            }
@@ -274,6 +270,26 @@ public class ClassInfo {
        return consistent;
    }

    /**
     * Returns true if {@code cl} implements the interface {@code iface} either
     * by either being that interface, implementing that interface or extending
     * a type that implements the interface.
     */
    private boolean implementsInterface(ClassInfo cl, String iface) {
        if (cl.qualifiedName().equals(iface)) {
            return true;
        }
        for (ClassInfo clImplements : cl.mInterfaces) {
            if (implementsInterface(clImplements, iface)) {
                return true;
            }
        }
        if (cl.mSuperClass != null && implementsInterface(cl.mSuperClass, iface)) {
            return true;
        }
        return false;
    }

    public void resolveInterfaces(ApiInfo apiInfo) {
        for (String interfaceName : mInterfaceNames) {
            mInterfaces.add(apiInfo.findClass(interfaceName));