From 78105ee42f9caf62492b69a8455bb42f7acef407 Mon Sep 17 00:00:00 2001 From: kmb Date: Wed, 2 Aug 2017 23:48:22 +0200 Subject: Tolerate missing interface markers in method calls from interface methods to methods in that interface. RELNOTES: none PiperOrigin-RevId: 164041648 --- .../build/android/desugar/InterfaceDesugaring.java | 27 +++++++++++----------- 1 file changed, 14 insertions(+), 13 deletions(-) (limited to 'src/tools/android/java') diff --git a/src/tools/android/java/com/google/devtools/build/android/desugar/InterfaceDesugaring.java b/src/tools/android/java/com/google/devtools/build/android/desugar/InterfaceDesugaring.java index f7621dfcc0..97135cf2b4 100644 --- a/src/tools/android/java/com/google/devtools/build/android/desugar/InterfaceDesugaring.java +++ b/src/tools/android/java/com/google/devtools/build/android/desugar/InterfaceDesugaring.java @@ -180,7 +180,8 @@ class InterfaceDesugaring extends ClassVisitor { result = super.visitMethod(access, name, desc, signature, exceptions); } return result != null - ? new InterfaceInvocationRewriter(result, internalName, bootclasspath) + ? new InterfaceInvocationRewriter( + result, isInterface() ? internalName : null, bootclasspath) : null; } @@ -277,29 +278,32 @@ class InterfaceDesugaring extends ClassVisitor { */ static class InterfaceInvocationRewriter extends MethodVisitor { - private final String internalName; + /** + * If we're visiting a method declared in an interface, the internal name of that interface. + * That lets us rewrite invocations of other methods within that interface even if the bytecode + * fails to indicate them as interface method invocations, as older versions of JaCoCo failed to + * do (b/62623509). + */ + @Nullable private final String interfaceName; private final ClassReaderFactory bootclasspath; public InterfaceInvocationRewriter( - MethodVisitor dest, String internalName, ClassReaderFactory bootclasspath) { + MethodVisitor dest, @Nullable String knownInterfaceName, ClassReaderFactory bootclasspath) { super(Opcodes.ASM5, dest); - this.internalName = internalName; + this.interfaceName = knownInterfaceName; this.bootclasspath = bootclasspath; } @Override public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) { // Assume that any static interface methods on the classpath are moved - if (itf) { + if (itf || owner.equals(interfaceName)) { boolean isLambda = name.startsWith("lambda$"); name = normalizeInterfaceMethodName(name, isLambda, opcode == Opcodes.INVOKESTATIC); if (isLambda) { // Redirect lambda invocations to completely remove all lambda methods from interfaces. checkArgument( - !owner.endsWith(COMPANION_SUFFIX), - "%s shouldn't consider %s an interface", - internalName, - owner); + !owner.endsWith(COMPANION_SUFFIX), "shouldn't consider %s an interface", owner); checkArgument(!bootclasspath.isKnown(owner)); // must be in current input if (opcode == Opcodes.INVOKEINTERFACE) { opcode = Opcodes.INVOKESTATIC; @@ -325,10 +329,7 @@ class InterfaceDesugaring extends ClassVisitor { } else if ((opcode == Opcodes.INVOKESTATIC || opcode == Opcodes.INVOKESPECIAL) && !bootclasspath.isKnown(owner)) { checkArgument( - !owner.endsWith(COMPANION_SUFFIX), - "%s shouldn't consider %s an interface", - internalName, - owner); + !owner.endsWith(COMPANION_SUFFIX), "shouldn't consider %s an interface", owner); if (opcode == Opcodes.INVOKESPECIAL) { // Turn Interface.super.m() into Interface$$CC.m(receiver) opcode = Opcodes.INVOKESTATIC; -- cgit v1.2.3