aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTreehugger Robot <treehugger-gerrit@google.com>2017-03-21 17:17:09 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2017-03-21 17:17:09 +0000
commitce33604360aa38f63921a82604a592acee1d105c (patch)
tree57350c8dc8be15096525e676b6e69563f1a8ecbb
parent7c8fd7bceb7ca05e236386167614ce359e6633b9 (diff)
parent309cc66e50aaac713a5c2c72e3ea6b236716b036 (diff)
downloaddexmaker-ce33604360aa38f63921a82604a592acee1d105c.tar.gz
Merge "Scan for methods in extra interface hierarchy"
-rw-r--r--README.version1
-rw-r--r--dexmaker-tests/src/androidTest/java/com/android/dx/stock/ProxyBuilderTest.java14
-rw-r--r--dexmaker/src/main/java/com/android/dx/stock/ProxyBuilder.java12
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) {