diff options
author | 2018-03-01 12:56:13 -0800 | |
---|---|---|
committer | 2018-03-01 12:58:30 -0800 | |
commit | 4b6c0ec4b54e258763ce22e1a7f529d293aff026 (patch) | |
tree | f4f50ae482c377720ed35feea1a4b33f2b8d60eb /src/tools/android/java/com/google/devtools/build/android/desugar/EmulatedInterfaceRewriter.java | |
parent | e2cc8868c53d88f12552139f548ab6e685403a73 (diff) |
send invocations to emulated interfaces through dispatch helper.
fix logic for implementing emulated interfaces.
RELNOTES: None.
PiperOrigin-RevId: 187520298
Diffstat (limited to 'src/tools/android/java/com/google/devtools/build/android/desugar/EmulatedInterfaceRewriter.java')
-rw-r--r-- | src/tools/android/java/com/google/devtools/build/android/desugar/EmulatedInterfaceRewriter.java | 56 |
1 files changed, 41 insertions, 15 deletions
diff --git a/src/tools/android/java/com/google/devtools/build/android/desugar/EmulatedInterfaceRewriter.java b/src/tools/android/java/com/google/devtools/build/android/desugar/EmulatedInterfaceRewriter.java index d3e786d3f3..f066f2a74c 100644 --- a/src/tools/android/java/com/google/devtools/build/android/desugar/EmulatedInterfaceRewriter.java +++ b/src/tools/android/java/com/google/devtools/build/android/desugar/EmulatedInterfaceRewriter.java @@ -13,18 +13,21 @@ // limitations under the License. package com.google.devtools.build.android.desugar; -import java.util.ArrayList; import java.util.Collections; +import java.util.LinkedHashSet; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.Opcodes; /** * Visitor that renames emulated interfaces and marks classes that extend emulated interfaces to * also implement the renamed interfaces. {@link DefaultMethodClassFixer} makes sure the requisite - * methods are present. Doing this helps with dynamic dispatch on emulated interfaces. + * methods are present in all classes implementing the renamed interface. Doing this helps with + * dynamic dispatch on emulated interfaces. */ public class EmulatedInterfaceRewriter extends ClassVisitor { + private static final String[] EMPTY_ARRAY = new String[0]; + private final CoreLibrarySupport support; public EmulatedInterfaceRewriter(ClassVisitor dest, CoreLibrarySupport support) { @@ -40,24 +43,47 @@ public class EmulatedInterfaceRewriter extends ClassVisitor { String signature, String superName, String[] interfaces) { - boolean isEmulated = support.isEmulatedCoreClassOrInterface(name); - if (interfaces != null && interfaces.length > 0 && !isEmulated) { - // Make classes implementing emulated interfaces also implement the renamed interfaces we - // create below. - ArrayList<String> newInterfaces = new ArrayList<>(interfaces.length + 2); - Collections.addAll(newInterfaces, interfaces); - for (String itf : interfaces) { - if (support.isEmulatedCoreClassOrInterface(itf)) { - newInterfaces.add(support.renameCoreLibrary(itf)); + boolean emulated = support.isEmulatedCoreClassOrInterface(name); + { + // 1. see if we should implement any additional interfaces. + // Use LinkedHashSet to dedupe but maintain deterministic order + LinkedHashSet<String> newInterfaces = new LinkedHashSet<>(); + if (interfaces != null && interfaces.length > 0) { + // Make classes implementing emulated interfaces also implement the renamed interfaces we + // create below. This includes making the renamed interfaces extends each other as needed. + Collections.addAll(newInterfaces, interfaces); + for (String itf : interfaces) { + if (support.isEmulatedCoreClassOrInterface(itf)) { + newInterfaces.add(support.renameCoreLibrary(itf)); + } + } + } + if (!emulated) { + // For an immediate subclass of an emulated class, also fill in any interfaces implemented + // by superclasses, similar to the additional default method stubbing performed in + // DefaultMethodClassFixer in this situation. + Class<?> superclass = support.getEmulatedCoreClassOrInterface(superName); + while (superclass != null) { + for (Class<?> implemented : superclass.getInterfaces()) { + String itf = implemented.getName().replace('.', '/'); + if (support.isEmulatedCoreClassOrInterface(itf)) { + newInterfaces.add(support.renameCoreLibrary(itf)); + } + } + superclass = superclass.getSuperclass(); } } - if (interfaces.length != newInterfaces.size()) { - interfaces = newInterfaces.toArray(interfaces); - signature = null; // additional interfaces invalidate signature + // Update implemented interfaces and signature if we did anything above + if (interfaces == null + ? !newInterfaces.isEmpty() + : interfaces.length != newInterfaces.size()) { + interfaces = newInterfaces.toArray(EMPTY_ARRAY); + signature = null; // additional interfaces invalidate any signature } } - if (BitFlags.isInterface(access) && isEmulated) { + // 2. see if we need to rename this interface itself + if (BitFlags.isInterface(access) && emulated) { name = support.renameCoreLibrary(name); } super.visit(version, access, name, signature, superName, interfaces); |