diff options
author | Treehugger Robot <treehugger-gerrit@google.com> | 2017-03-21 17:17:09 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2017-03-21 17:17:09 +0000 |
commit | ce33604360aa38f63921a82604a592acee1d105c (patch) | |
tree | 57350c8dc8be15096525e676b6e69563f1a8ecbb | |
parent | 7c8fd7bceb7ca05e236386167614ce359e6633b9 (diff) | |
parent | 309cc66e50aaac713a5c2c72e3ea6b236716b036 (diff) | |
download | dexmaker-ce33604360aa38f63921a82604a592acee1d105c.tar.gz |
Merge "Scan for methods in extra interface hierarchy"
-rw-r--r-- | README.version | 1 | ||||
-rw-r--r-- | dexmaker-tests/src/androidTest/java/com/android/dx/stock/ProxyBuilderTest.java | 14 | ||||
-rw-r--r-- | dexmaker/src/main/java/com/android/dx/stock/ProxyBuilder.java | 12 |
3 files changed, 27 insertions, 0 deletions
diff --git a/README.version b/README.version index f823769..6f448fc 100644 --- a/README.version +++ b/README.version @@ -10,3 +10,4 @@ It includes a stock code generator for class proxies. If you just want to do AOP Local Modifications: Support mocking of package private classes using dexmaker.share_classloader + Scan for methods in extra interface hierarchy diff --git a/dexmaker-tests/src/androidTest/java/com/android/dx/stock/ProxyBuilderTest.java b/dexmaker-tests/src/androidTest/java/com/android/dx/stock/ProxyBuilderTest.java index f0e7599..193a6d1 100644 --- a/dexmaker-tests/src/androidTest/java/com/android/dx/stock/ProxyBuilderTest.java +++ b/dexmaker-tests/src/androidTest/java/com/android/dx/stock/ProxyBuilderTest.java @@ -948,6 +948,20 @@ public class ProxyBuilderTest { proxyFor(YouDoNotChooseYourFamily.class).build(); } + public interface ExtendsAnotherInterface extends FooReturnsString { + + } + + @Test + public void testExtraInterfaceExtendsInterface() throws Exception { + ExtendsAnotherInterface proxy = (ExtendsAnotherInterface) + proxyFor(SimpleClass.class) + .implementing(ExtendsAnotherInterface.class) + .build(); + fakeHandler.setFakeResult(ExtendsAnotherInterface.class.getName()); + assertEquals(ExtendsAnotherInterface.class.getName(), proxy.foo()); + } + /** Simple helper to add the most common args for this test to the proxy builder. */ private <T> ProxyBuilder<T> proxyFor(Class<T> clazz) throws Exception { return ProxyBuilder.forClass(clazz) diff --git a/dexmaker/src/main/java/com/android/dx/stock/ProxyBuilder.java b/dexmaker/src/main/java/com/android/dx/stock/ProxyBuilder.java index 1daf8e3..b618c84 100644 --- a/dexmaker/src/main/java/com/android/dx/stock/ProxyBuilder.java +++ b/dexmaker/src/main/java/com/android/dx/stock/ProxyBuilder.java @@ -632,9 +632,13 @@ public final class ProxyBuilder<T> { private Method[] getMethodsToProxyRecursive() { Set<MethodSetEntry> methodsToProxy = new HashSet<>(); Set<MethodSetEntry> seenFinalMethods = new HashSet<>(); + // Traverse the class hierarchy to ensure that all concrete methods (which could be marked + // as final) are visited before any abstract methods from interfaces. for (Class<?> c = baseClass; c != null; c = c.getSuperclass()) { getMethodsToProxy(methodsToProxy, seenFinalMethods, c); } + // Now traverse the interface hierarchy, starting with the ones implemented by the class, + // followed by any extra interfaces. for (Class<?> c = baseClass; c != null; c = c.getSuperclass()) { for (Class<?> i : c.getInterfaces()) { getMethodsToProxy(methodsToProxy, seenFinalMethods, i); @@ -710,6 +714,14 @@ public final class ProxyBuilder<T> { } sink.add(entry); } + + // Only visit the interfaces of this class if it is itself an interface. That prevents + // visiting interfaces of a class before its super classes. + if (c.isInterface()) { + for (Class<?> i : c.getInterfaces()) { + getMethodsToProxy(sink, seenFinalMethods, i); + } + } } private static <T> String getMethodNameForProxyOf(Class<T> clazz) { |