From 7146fa7c03b7dade4e46ec59c2fa88bff5e6684d Mon Sep 17 00:00:00 2001 From: Esko Luontola Date: Tue, 14 Apr 2015 23:14:22 +0300 Subject: [PATCH] Refactored: added MethodRef.tag, removed the hack Fixes #48 --- README.md | 3 ++ .../AddMethodDefaultImplementations.java | 4 +- .../interfaces/ClassHierarchyAnalyzer.java | 18 +++++-- .../retrolambda/interfaces/ClassInfo.java | 2 +- .../retrolambda/interfaces/MethodInfo.java | 12 +++-- .../retrolambda/interfaces/MethodRef.java | 17 +++++-- .../UpdateRelocatedMethodInvocations.java | 19 ++----- .../retrolambda/lambdas/Handles.java | 32 +++++++++++- .../ClassHierarchyAnalyzerTest.java | 51 ++++++++++--------- 9 files changed, 100 insertions(+), 58 deletions(-) diff --git a/README.md b/README.md index ad5cb979..423c570f 100644 --- a/README.md +++ b/README.md @@ -207,6 +207,9 @@ Version History - Fixed a hack which caused lambdas in interfaces to be backported twice, possibly producing broken method calls in the bytecode ([Issue #48](https://github.com/orfjackal/retrolambda/issues/48)) +- Fixed the handling of non-static lambda implementation methods in + interfaces, i.e. lambdas which capture `this` + ([Issue #48](https://github.com/orfjackal/retrolambda/issues/48)) - Removes generic method signatures from the default method implementation methods which are placed in the interface's companion class, to avoid them getting out of sync with their erased method descriptors diff --git a/retrolambda/src/main/java/net/orfjackal/retrolambda/interfaces/AddMethodDefaultImplementations.java b/retrolambda/src/main/java/net/orfjackal/retrolambda/interfaces/AddMethodDefaultImplementations.java index c91f09be..8cc4c73a 100644 --- a/retrolambda/src/main/java/net/orfjackal/retrolambda/interfaces/AddMethodDefaultImplementations.java +++ b/retrolambda/src/main/java/net/orfjackal/retrolambda/interfaces/AddMethodDefaultImplementations.java @@ -30,8 +30,8 @@ public void visitEnd() { for (MethodInfo method : analyzer.getDefaultMethods(Type.getObjectType(className))) { Bytecode.generateDelegateMethod(cv, ACC_PUBLIC | ACC_SYNTHETIC, - method.toMethodRef().toHandle(H_INVOKEVIRTUAL), - method.getDefaultMethodImpl().toHandle(H_INVOKESTATIC)); + method.toMethodRef().toHandle(), + method.getDefaultMethodImpl().toHandle()); } super.visitEnd(); } diff --git a/retrolambda/src/main/java/net/orfjackal/retrolambda/interfaces/ClassHierarchyAnalyzer.java b/retrolambda/src/main/java/net/orfjackal/retrolambda/interfaces/ClassHierarchyAnalyzer.java index f30213dc..6333d981 100644 --- a/retrolambda/src/main/java/net/orfjackal/retrolambda/interfaces/ClassHierarchyAnalyzer.java +++ b/retrolambda/src/main/java/net/orfjackal/retrolambda/interfaces/ClassHierarchyAnalyzer.java @@ -4,6 +4,7 @@ package net.orfjackal.retrolambda.interfaces; +import net.orfjackal.retrolambda.lambdas.Handles; import net.orfjackal.retrolambda.util.*; import org.objectweb.asm.*; @@ -46,7 +47,7 @@ public MethodVisitor visitMethod(int access, String name, String desc, String si if (isConstructor(name) || isStaticMethod(access)) { return null; } - c.addMethod(new MethodRef(owner, name, desc), new MethodKind.Implemented()); + c.addMethod(new MethodRef(H_INVOKEVIRTUAL, owner, name, desc), new MethodKind.Implemented()); return null; } @@ -66,22 +67,22 @@ public void visit(int version, int access, String name, String signature, String @Override public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { - MethodRef method = new MethodRef(owner, name, desc); + MethodRef method = new MethodRef(Handles.accessToTag(access, true), owner, name, desc); if (isAbstractMethod(access)) { c.addMethod(method, new MethodKind.Abstract()); } else if (isDefaultMethod(access)) { - MethodRef defaultImpl = new MethodRef(companion, name, Bytecode.prependArgumentType(desc, Type.getObjectType(owner))); + MethodRef defaultImpl = new MethodRef(H_INVOKESTATIC, companion, name, Bytecode.prependArgumentType(desc, Type.getObjectType(owner))); c.enableCompanionClass(); c.addMethod(method, new MethodKind.Default(defaultImpl)); } else if (isInstanceLambdaImplMethod(access)) { - relocatedMethods.put(method, new MethodRef(companion, name, Bytecode.prependArgumentType(desc, Type.getObjectType(owner)))); + relocatedMethods.put(method, new MethodRef(H_INVOKESTATIC, companion, name, Bytecode.prependArgumentType(desc, Type.getObjectType(owner)))); c.enableCompanionClass(); } else if (isStaticMethod(access)) { - relocatedMethods.put(method, new MethodRef(companion, name, desc)); + relocatedMethods.put(method, new MethodRef(H_INVOKESTATIC, companion, name, desc)); c.enableCompanionClass(); } return null; @@ -140,6 +141,13 @@ private ClassInfo getClass(Type type) { } public MethodRef getMethodCallTarget(MethodRef original) { + if (original.tag == H_INVOKESPECIAL) { + // change Interface.super.defaultMethod() calls to static calls on the companion class + MethodRef impl = getMethodDefaultImplementation(original); + if (impl != null) { + return impl; + } + } return relocatedMethods.getOrDefault(original, original); } diff --git a/retrolambda/src/main/java/net/orfjackal/retrolambda/interfaces/ClassInfo.java b/retrolambda/src/main/java/net/orfjackal/retrolambda/interfaces/ClassInfo.java index ef5e7999..f7d4473c 100644 --- a/retrolambda/src/main/java/net/orfjackal/retrolambda/interfaces/ClassInfo.java +++ b/retrolambda/src/main/java/net/orfjackal/retrolambda/interfaces/ClassInfo.java @@ -47,7 +47,7 @@ public List getMethods() { } public void addMethod(MethodRef method, MethodKind kind) { - methods.add(new MethodInfo(method.getSignature(), Type.getObjectType(method.owner), kind)); + methods.add(new MethodInfo(method.tag, method.getSignature(), Type.getObjectType(method.owner), kind)); } public Optional getCompanionClass() { diff --git a/retrolambda/src/main/java/net/orfjackal/retrolambda/interfaces/MethodInfo.java b/retrolambda/src/main/java/net/orfjackal/retrolambda/interfaces/MethodInfo.java index 4e97a629..9e54789a 100644 --- a/retrolambda/src/main/java/net/orfjackal/retrolambda/interfaces/MethodInfo.java +++ b/retrolambda/src/main/java/net/orfjackal/retrolambda/interfaces/MethodInfo.java @@ -11,15 +11,17 @@ public class MethodInfo { + public final int tag; public final MethodSignature signature; public final Type owner; public final MethodKind kind; - public MethodInfo(String name, String desc, Class owner, MethodKind kind) { - this(new MethodSignature(name, desc), Type.getType(owner), kind); + public MethodInfo(String name, String desc, Class owner, MethodKind kind) { // only for tests, so we can ignore the tag + this(-1, new MethodSignature(name, desc), Type.getType(owner), kind); } - public MethodInfo(MethodSignature signature, Type owner, MethodKind kind) { + public MethodInfo(int tag, MethodSignature signature, Type owner, MethodKind kind) { + this.tag = tag; this.signature = signature; this.owner = owner; this.kind = kind; @@ -30,7 +32,7 @@ public MethodRef getDefaultMethodImpl() { } public MethodRef toMethodRef() { - return new MethodRef(owner.getInternalName(), signature.name, signature.desc); + return new MethodRef(tag, owner.getInternalName(), signature.name, signature.desc); } @Override @@ -38,6 +40,7 @@ public boolean equals(Object obj) { if (!(obj instanceof MethodInfo)) { return false; } + // NOTE: the tag does not not affect method equality, because e.g. super calls have different tag but same method MethodInfo that = (MethodInfo) obj; return this.signature.equals(that.signature) && this.owner.equals(that.owner) @@ -55,6 +58,7 @@ public String toString() { .addValue(signature) .addValue(owner) .addValue(kind) + .addValue("(" + tag + ")") .toString(); } } diff --git a/retrolambda/src/main/java/net/orfjackal/retrolambda/interfaces/MethodRef.java b/retrolambda/src/main/java/net/orfjackal/retrolambda/interfaces/MethodRef.java index bf82a4b5..bffd2d17 100644 --- a/retrolambda/src/main/java/net/orfjackal/retrolambda/interfaces/MethodRef.java +++ b/retrolambda/src/main/java/net/orfjackal/retrolambda/interfaces/MethodRef.java @@ -5,6 +5,7 @@ package net.orfjackal.retrolambda.interfaces; import com.google.common.base.MoreObjects; +import net.orfjackal.retrolambda.lambdas.Handles; import org.objectweb.asm.*; import java.util.Objects; @@ -13,15 +14,17 @@ public final class MethodRef { // TODO: replace MethodRef with ASM's Handle, or merge with MethodInfo? + public final int tag; public final String owner; public final String name; public final String desc; - public MethodRef(Class owner, String name, String desc) { - this(Type.getInternalName(owner), name, desc); + public MethodRef(int tag, Class owner, String name, String desc) { + this(tag, Type.getInternalName(owner), name, desc); } - public MethodRef(String owner, String name, String desc) { + public MethodRef(int tag, String owner, String name, String desc) { + this.tag = tag; this.owner = owner; this.name = name; this.desc = desc; @@ -31,7 +34,11 @@ public MethodSignature getSignature() { return new MethodSignature(name, desc); } - public Handle toHandle(int tag) { + public int getOpcode() { + return Handles.getOpcode(toHandle()); + } + + public Handle toHandle() { return new Handle(tag, owner, name, desc); } @@ -40,6 +47,7 @@ public boolean equals(Object obj) { if (!(obj instanceof MethodRef)) { return false; } + // NOTE: the tag does not not affect method equality, because e.g. super calls have different tag but same method MethodRef that = (MethodRef) obj; return this.owner.equals(that.owner) && this.name.equals(that.name) @@ -57,6 +65,7 @@ public String toString() { .addValue(owner) .addValue(name) .addValue(desc) + .addValue("(" + tag + ")") .toString(); } } diff --git a/retrolambda/src/main/java/net/orfjackal/retrolambda/interfaces/UpdateRelocatedMethodInvocations.java b/retrolambda/src/main/java/net/orfjackal/retrolambda/interfaces/UpdateRelocatedMethodInvocations.java index d3248e09..6189e4fd 100644 --- a/retrolambda/src/main/java/net/orfjackal/retrolambda/interfaces/UpdateRelocatedMethodInvocations.java +++ b/retrolambda/src/main/java/net/orfjackal/retrolambda/interfaces/UpdateRelocatedMethodInvocations.java @@ -4,6 +4,7 @@ package net.orfjackal.retrolambda.interfaces; +import net.orfjackal.retrolambda.lambdas.Handles; import org.objectweb.asm.*; import static org.objectweb.asm.Opcodes.ASM5; @@ -30,23 +31,9 @@ public UpdateMethodCalls(MethodVisitor next) { @Override public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) { - MethodRef method = new MethodRef(owner, name, desc); - - // change Interface.super.defaultMethod() calls to static calls on the companion class - // TODO: move this inside getMethodCallTarget (also opcode, so must first change MethodRef to Handle) - if (opcode == Opcodes.INVOKESPECIAL) { - MethodRef impl = analyzer.getMethodDefaultImplementation(method); - if (impl != null) { - opcode = Opcodes.INVOKESTATIC; - method = impl; - } - if (name.startsWith("lambda$captureThis$")) { // FIXME: remove me - opcode = Opcodes.INVOKESTATIC; - } - } - + MethodRef method = new MethodRef(Handles.opcodeToTag(opcode), owner, name, desc); method = analyzer.getMethodCallTarget(method); - super.visitMethodInsn(opcode, method.owner, method.name, method.desc, itf); + super.visitMethodInsn(method.getOpcode(), method.owner, method.name, method.desc, itf); } } } diff --git a/retrolambda/src/main/java/net/orfjackal/retrolambda/lambdas/Handles.java b/retrolambda/src/main/java/net/orfjackal/retrolambda/lambdas/Handles.java index a91c67ce..7870a057 100644 --- a/retrolambda/src/main/java/net/orfjackal/retrolambda/lambdas/Handles.java +++ b/retrolambda/src/main/java/net/orfjackal/retrolambda/lambdas/Handles.java @@ -1,9 +1,10 @@ -// Copyright © 2013-2014 Esko Luontola +// Copyright © 2013-2015 Esko Luontola // This software is released under the Apache License 2.0. // The license text is at http://www.apache.org/licenses/LICENSE-2.0 package net.orfjackal.retrolambda.lambdas; +import net.orfjackal.retrolambda.util.Flags; import org.objectweb.asm.Handle; import static org.objectweb.asm.Opcodes.*; @@ -27,4 +28,33 @@ public static int getOpcode(Handle handle) { throw new IllegalArgumentException("Unsupported tag " + tag + " in " + handle); } } + + public static int opcodeToTag(int opcode) { + switch (opcode) { + case INVOKEVIRTUAL: + return H_INVOKEVIRTUAL; + case INVOKESTATIC: + return H_INVOKESTATIC; + case INVOKESPECIAL: + return H_INVOKESPECIAL; + case INVOKEINTERFACE: + return H_INVOKEINTERFACE; + default: + throw new IllegalArgumentException("Unsupported opcode " + opcode); + } + } + + public static int accessToTag(int access, boolean itf) { + if (Flags.hasFlag(access, ACC_STATIC)) { + return H_INVOKESTATIC; + } + if (Flags.hasFlag(access, ACC_PRIVATE)) { + return H_INVOKESPECIAL; + } + if (itf) { + return H_INVOKEINTERFACE; + } else { + return H_INVOKEVIRTUAL; + } + } } diff --git a/retrolambda/src/test/java/net/orfjackal/retrolambda/ClassHierarchyAnalyzerTest.java b/retrolambda/src/test/java/net/orfjackal/retrolambda/ClassHierarchyAnalyzerTest.java index 098b2126..79993c74 100644 --- a/retrolambda/src/test/java/net/orfjackal/retrolambda/ClassHierarchyAnalyzerTest.java +++ b/retrolambda/src/test/java/net/orfjackal/retrolambda/ClassHierarchyAnalyzerTest.java @@ -18,6 +18,7 @@ import static java.util.stream.Collectors.toList; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.*; +import static org.objectweb.asm.Opcodes.*; @SuppressWarnings("UnusedDeclaration") public class ClassHierarchyAnalyzerTest { @@ -74,7 +75,7 @@ public void interface_method_types() { containsInAnyOrder( new MethodInfo("abstractMethod", "()V", InterfaceMethodTypes.class, new MethodKind.Abstract()), new MethodInfo("defaultMethod", "()V", InterfaceMethodTypes.class, new MethodKind.Default( - new MethodRef(InterfaceMethodTypes$.class, "defaultMethod", "(Lnet/orfjackal/retrolambda/ClassHierarchyAnalyzerTest$InterfaceMethodTypes;)V"))))); + new MethodRef(H_INVOKESTATIC, InterfaceMethodTypes$.class, "defaultMethod", "(Lnet/orfjackal/retrolambda/ClassHierarchyAnalyzerTest$InterfaceMethodTypes;)V"))))); } @Test @@ -124,19 +125,19 @@ public void default_method_overridden_and_abstracted() { containsInAnyOrder( new MethodInfo("abstractMethod", "()V", HasDefaultMethods.class, new MethodKind.Abstract()), new MethodInfo("defaultMethod", "()V", HasDefaultMethods.class, new MethodKind.Default( - new MethodRef(HasDefaultMethods$.class, "defaultMethod", "(Lnet/orfjackal/retrolambda/ClassHierarchyAnalyzerTest$HasDefaultMethods;)V"))))); + new MethodRef(H_INVOKESTATIC, HasDefaultMethods$.class, "defaultMethod", "(Lnet/orfjackal/retrolambda/ClassHierarchyAnalyzerTest$HasDefaultMethods;)V"))))); assertThat("inherits unchanged", analyzer.getMethods(Type.getType(DoesNotOverrideDefaultMethods.class)), containsInAnyOrder( new MethodInfo("abstractMethod", "()V", HasDefaultMethods.class, new MethodKind.Abstract()), new MethodInfo("defaultMethod", "()V", HasDefaultMethods.class, new MethodKind.Default( - new MethodRef(HasDefaultMethods$.class, "defaultMethod", "(Lnet/orfjackal/retrolambda/ClassHierarchyAnalyzerTest$HasDefaultMethods;)V"))))); + new MethodRef(H_INVOKESTATIC, HasDefaultMethods$.class, "defaultMethod", "(Lnet/orfjackal/retrolambda/ClassHierarchyAnalyzerTest$HasDefaultMethods;)V"))))); assertThat("changes default impl", analyzer.getMethods(Type.getType(OverridesDefaultMethods.class)), containsInAnyOrder( new MethodInfo("abstractMethod", "()V", HasDefaultMethods.class, new MethodKind.Abstract()), new MethodInfo("defaultMethod", "()V", OverridesDefaultMethods.class, new MethodKind.Default( - new MethodRef(OverridesDefaultMethods$.class, "defaultMethod", "(Lnet/orfjackal/retrolambda/ClassHierarchyAnalyzerTest$OverridesDefaultMethods;)V"))))); + new MethodRef(H_INVOKESTATIC, OverridesDefaultMethods$.class, "defaultMethod", "(Lnet/orfjackal/retrolambda/ClassHierarchyAnalyzerTest$OverridesDefaultMethods;)V"))))); assertThat("makes abstract", analyzer.getMethods(Type.getType(AbstractsDefaultMethods.class)), containsInAnyOrder( @@ -206,12 +207,12 @@ public void overriding_default_methods() { assertThat("original", analyzer.getMethods(Type.getType(DefaultMethods.class)), containsInAnyOrder( new MethodInfo("foo", "()V", DefaultMethods.class, new MethodKind.Default( - new MethodRef(DefaultMethods$.class, "foo", "(Lnet/orfjackal/retrolambda/ClassHierarchyAnalyzerTest$DefaultMethods;)V"))))); + new MethodRef(H_INVOKESTATIC, DefaultMethods$.class, "foo", "(Lnet/orfjackal/retrolambda/ClassHierarchyAnalyzerTest$DefaultMethods;)V"))))); assertThat("inherits unchanged", analyzer.getMethods(Type.getType(InheritsDefault.class)), containsInAnyOrder( new MethodInfo("foo", "()V", DefaultMethods.class, new MethodKind.Default( - new MethodRef(DefaultMethods$.class, "foo", "(Lnet/orfjackal/retrolambda/ClassHierarchyAnalyzerTest$DefaultMethods;)V"))))); + new MethodRef(H_INVOKESTATIC, DefaultMethods$.class, "foo", "(Lnet/orfjackal/retrolambda/ClassHierarchyAnalyzerTest$DefaultMethods;)V"))))); assertThat("overrides", analyzer.getMethods(Type.getType(OverridesDefault.class)), containsInAnyOrder( @@ -260,9 +261,9 @@ public void inheriting_same_default_methods_through_many_parent_interfaces() { InheritsOriginalAndOverridden.class); MethodInfo original = new MethodInfo("foo", "()V", SuperOriginal.class, new MethodKind.Default( - new MethodRef(SuperOriginal$.class, "foo", "(Lnet/orfjackal/retrolambda/ClassHierarchyAnalyzerTest$SuperOriginal;)V"))); + new MethodRef(H_INVOKESTATIC, SuperOriginal$.class, "foo", "(Lnet/orfjackal/retrolambda/ClassHierarchyAnalyzerTest$SuperOriginal;)V"))); MethodInfo overridden = new MethodInfo("foo", "()V", SuperOverridden.class, new MethodKind.Default( - new MethodRef(SuperOverridden$.class, "foo", "(Lnet/orfjackal/retrolambda/ClassHierarchyAnalyzerTest$SuperOverridden;)V"))); + new MethodRef(H_INVOKESTATIC, SuperOverridden$.class, "foo", "(Lnet/orfjackal/retrolambda/ClassHierarchyAnalyzerTest$SuperOverridden;)V"))); assertThat("inherits original", analyzer.getMethods(Type.getType(InheritsOriginal.class)), containsInAnyOrder(original)); @@ -314,9 +315,9 @@ public void implements_original_and_overridden_default_method() { ExtendsImplementsOriginalAndImplementsOverriddenDefault.class); MethodInfo original = new MethodInfo("foo", "()V", OriginalDefault.class, new MethodKind.Default( - new MethodRef(OriginalDefault$.class, "foo", "(Lnet/orfjackal/retrolambda/ClassHierarchyAnalyzerTest$OriginalDefault;)V"))); + new MethodRef(H_INVOKESTATIC, OriginalDefault$.class, "foo", "(Lnet/orfjackal/retrolambda/ClassHierarchyAnalyzerTest$OriginalDefault;)V"))); MethodInfo overridden = new MethodInfo("foo", "()V", OverriddenDefault.class, new MethodKind.Default( - new MethodRef(OverriddenDefault$.class, "foo", "(Lnet/orfjackal/retrolambda/ClassHierarchyAnalyzerTest$OverriddenDefault;)V"))); + new MethodRef(H_INVOKESTATIC, OverriddenDefault$.class, "foo", "(Lnet/orfjackal/retrolambda/ClassHierarchyAnalyzerTest$OverriddenDefault;)V"))); assertThat("implements original", analyzer.getMethods(Type.getType(ImplementsOriginal.class)), containsInAnyOrder(original)); @@ -364,9 +365,9 @@ public void default_methods_with_lambdas() { ImplementsUsesLambdas.class); MethodInfo stateless = new MethodInfo("stateless", "()Ljava/util/concurrent/Callable;", UsesLambdas.class, new MethodKind.Default( - new MethodRef(UsesLambdas$.class, "stateless", "(Lnet/orfjackal/retrolambda/ClassHierarchyAnalyzerTest$UsesLambdas;)Ljava/util/concurrent/Callable;"))); + new MethodRef(H_INVOKESTATIC, UsesLambdas$.class, "stateless", "(Lnet/orfjackal/retrolambda/ClassHierarchyAnalyzerTest$UsesLambdas;)Ljava/util/concurrent/Callable;"))); MethodInfo captureThis = new MethodInfo("captureThis", "()Ljava/util/concurrent/Callable;", UsesLambdas.class, new MethodKind.Default( - new MethodRef(UsesLambdas$.class, "captureThis", "(Lnet/orfjackal/retrolambda/ClassHierarchyAnalyzerTest$UsesLambdas;)Ljava/util/concurrent/Callable;"))); + new MethodRef(H_INVOKESTATIC, UsesLambdas$.class, "captureThis", "(Lnet/orfjackal/retrolambda/ClassHierarchyAnalyzerTest$UsesLambdas;)Ljava/util/concurrent/Callable;"))); assertThat("does not copy instance lambda impl methods to implementers", analyzer.getMethods(Type.getType(ImplementsUsesLambdas.class)), @@ -396,7 +397,7 @@ private class ImplementsUsesLambdas implements UsesLambdas { public void abstract_methods_on_interfaces_are_not_relocated() { analyze(InterfaceMethodTypes.class); - MethodRef source = new MethodRef(InterfaceMethodTypes.class, "abstractMethod", voidMethod()); + MethodRef source = new MethodRef(H_INVOKEINTERFACE, InterfaceMethodTypes.class, "abstractMethod", voidMethod()); MethodRef target = analyzer.getMethodCallTarget(source); assertThat(target, is(source)); @@ -406,7 +407,7 @@ public void abstract_methods_on_interfaces_are_not_relocated() { public void default_methods_on_interfaces_are_not_relocated() { analyze(InterfaceMethodTypes.class); - MethodRef source = new MethodRef(InterfaceMethodTypes.class, "defaultMethod", voidMethod()); + MethodRef source = new MethodRef(H_INVOKEINTERFACE, InterfaceMethodTypes.class, "defaultMethod", voidMethod()); MethodRef target = analyzer.getMethodCallTarget(source); assertThat(target, is(source)); @@ -416,17 +417,17 @@ public void default_methods_on_interfaces_are_not_relocated() { public void static_methods_on_interfaces_are_relocated_to_companion_classes() { analyze(InterfaceMethodTypes.class); - MethodRef source = new MethodRef(InterfaceMethodTypes.class, "staticMethod", voidMethod()); + MethodRef source = new MethodRef(H_INVOKESTATIC, InterfaceMethodTypes.class, "staticMethod", voidMethod()); MethodRef target = analyzer.getMethodCallTarget(source); - assertThat(target, is(new MethodRef(InterfaceMethodTypes$.class, "staticMethod", voidMethod()))); + assertThat(target, is(new MethodRef(H_INVOKESTATIC, InterfaceMethodTypes$.class, "staticMethod", voidMethod()))); } @Test public void static_methods_on_classes_are_not_relocated() { analyze(ClassMethodTypes.class); - MethodRef source = new MethodRef(ClassMethodTypes.class, "staticMethod", voidMethod()); + MethodRef source = new MethodRef(H_INVOKESTATIC, ClassMethodTypes.class, "staticMethod", voidMethod()); MethodRef target = analyzer.getMethodCallTarget(source); assertThat(target, is(source)); @@ -439,7 +440,7 @@ public void static_methods_on_classes_are_not_relocated() { public void abstract_methods_have_no_implementation() { analyze(HasDefaultMethods.class); - MethodRef method = new MethodRef(HasDefaultMethods.class, "abstractMethod", voidMethod()); + MethodRef method = new MethodRef(H_INVOKEINTERFACE, HasDefaultMethods.class, "abstractMethod", voidMethod()); MethodRef impl = analyzer.getMethodDefaultImplementation(method); assertThat(impl, is(nullValue())); @@ -449,10 +450,10 @@ public void abstract_methods_have_no_implementation() { public void default_method_implementation_is_moved_to_companion_class() { analyze(HasDefaultMethods.class); - MethodRef method = new MethodRef(HasDefaultMethods.class, "defaultMethod", voidMethod()); + MethodRef method = new MethodRef(H_INVOKEINTERFACE, HasDefaultMethods.class, "defaultMethod", voidMethod()); MethodRef impl = analyzer.getMethodDefaultImplementation(method); - assertThat(impl, is(new MethodRef(HasDefaultMethods$.class, "defaultMethod", voidMethod(HasDefaultMethods.class)))); + assertThat(impl, is(new MethodRef(H_INVOKESTATIC, HasDefaultMethods$.class, "defaultMethod", voidMethod(HasDefaultMethods.class)))); } @Test @@ -460,10 +461,10 @@ public void default_method_implementations_are_inherited_from_parent_interface() analyze(HasDefaultMethods.class, DoesNotOverrideDefaultMethods.class); - MethodRef method = new MethodRef(DoesNotOverrideDefaultMethods.class, "defaultMethod", voidMethod()); + MethodRef method = new MethodRef(H_INVOKEINTERFACE, DoesNotOverrideDefaultMethods.class, "defaultMethod", voidMethod()); MethodRef impl = analyzer.getMethodDefaultImplementation(method); - assertThat(impl, is(new MethodRef(HasDefaultMethods$.class, "defaultMethod", voidMethod(HasDefaultMethods.class)))); + assertThat(impl, is(new MethodRef(H_INVOKESTATIC, HasDefaultMethods$.class, "defaultMethod", voidMethod(HasDefaultMethods.class)))); } @Test @@ -471,10 +472,10 @@ public void overridden_default_method_implementation_is_moved_to_companion_class analyze(HasDefaultMethods.class, OverridesDefaultMethods.class); - MethodRef method = new MethodRef(OverridesDefaultMethods.class, "defaultMethod", voidMethod()); + MethodRef method = new MethodRef(H_INVOKEINTERFACE, OverridesDefaultMethods.class, "defaultMethod", voidMethod()); MethodRef impl = analyzer.getMethodDefaultImplementation(method); - assertThat(impl, is(new MethodRef(OverridesDefaultMethods$.class, "defaultMethod", voidMethod(OverridesDefaultMethods.class)))); + assertThat(impl, is(new MethodRef(H_INVOKESTATIC, OverridesDefaultMethods$.class, "defaultMethod", voidMethod(OverridesDefaultMethods.class)))); } @Test @@ -482,7 +483,7 @@ public void abstracted_default_method_implementations_are_again_abstract() { analyze(HasDefaultMethods.class, AbstractsDefaultMethods.class); - MethodRef method = new MethodRef(AbstractsDefaultMethods.class, "defaultMethod", voidMethod()); + MethodRef method = new MethodRef(H_INVOKEINTERFACE, AbstractsDefaultMethods.class, "defaultMethod", voidMethod()); MethodRef impl = analyzer.getMethodDefaultImplementation(method); assertThat(impl, is(nullValue()));