Support compatibility mode for @JvmDefault
This commit is contained in:
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.codegen.coroutines.CoroutineCodegenUtilKt;
|
||||
import org.jetbrains.kotlin.codegen.coroutines.SuspendFunctionGenerationStrategy;
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
|
||||
import org.jetbrains.kotlin.config.JvmDefaultMode;
|
||||
import org.jetbrains.kotlin.config.JvmTarget;
|
||||
import org.jetbrains.kotlin.config.LanguageFeature;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
@@ -179,7 +180,10 @@ public class FunctionCodegen {
|
||||
) {
|
||||
OwnerKind contextKind = methodContext.getContextKind();
|
||||
DeclarationDescriptor containingDeclaration = functionDescriptor.getContainingDeclaration();
|
||||
if (isInterface(containingDeclaration) && !processInterfaceMethod(functionDescriptor, contextKind, false)) return;
|
||||
if (isInterface(containingDeclaration) &&
|
||||
!processInterfaceMethod(functionDescriptor, contextKind, false, state.getJvmDefaultMode())) {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean hasSpecialBridge = hasSpecialBridgeMethod(functionDescriptor);
|
||||
JvmMethodGenericSignature jvmSignature = strategy.mapMethodSignature(functionDescriptor, typeMapper, contextKind, hasSpecialBridge);
|
||||
@@ -392,7 +396,7 @@ public class FunctionCodegen {
|
||||
}
|
||||
|
||||
if (!functionDescriptor.isExternal()) {
|
||||
generateMethodBody(mv, functionDescriptor, methodContext, jvmSignature, strategy, memberCodegen);
|
||||
generateMethodBody(mv, functionDescriptor, methodContext, jvmSignature, strategy, memberCodegen, state.getJvmDefaultMode());
|
||||
}
|
||||
else if (staticInCompanionObject) {
|
||||
// native @JvmStatic foo() in companion object should delegate to the static native function moved to the outer class
|
||||
@@ -402,7 +406,7 @@ public class FunctionCodegen {
|
||||
Method accessorMethod =
|
||||
typeMapper.mapAsmMethod(memberCodegen.getContext().accessibleDescriptor(staticFunctionDescriptor, null));
|
||||
Type owningType = typeMapper.mapClass((ClassifierDescriptor) staticFunctionDescriptor.getContainingDeclaration());
|
||||
generateDelegateToStaticMethodBody(false, mv, accessorMethod, owningType.getInternalName());
|
||||
generateDelegateToStaticMethodBody(false, mv, accessorMethod, owningType.getInternalName(), false);
|
||||
}
|
||||
|
||||
endVisit(mv, null, origin.getElement());
|
||||
@@ -574,7 +578,8 @@ public class FunctionCodegen {
|
||||
@NotNull MethodContext context,
|
||||
@NotNull JvmMethodSignature signature,
|
||||
@NotNull FunctionGenerationStrategy strategy,
|
||||
@NotNull MemberCodegen<?> parentCodegen
|
||||
@NotNull MemberCodegen<?> parentCodegen,
|
||||
@NotNull JvmDefaultMode jvmDefaultMode
|
||||
) {
|
||||
mv.visitCode();
|
||||
|
||||
@@ -596,6 +601,20 @@ public class FunctionCodegen {
|
||||
generateFacadeDelegateMethodBody(mv, signature.getAsmMethod(), (MultifileClassFacadeContext) context.getParentContext());
|
||||
methodEnd = new Label();
|
||||
}
|
||||
else if (isCompatibilityStubInDefaultImpls(functionDescriptor, context, jvmDefaultMode)) {
|
||||
FunctionDescriptor compatibility = ((DefaultImplsClassContext) context.getParentContext()).getInterfaceContext()
|
||||
.getAccessorForJvmDefaultCompatibility(functionDescriptor);
|
||||
int flags = AsmUtil.getMethodAsmFlags(functionDescriptor, OwnerKind.DEFAULT_IMPLS, context.getState());
|
||||
assert (flags & Opcodes.ACC_ABSTRACT) == 0 : "Interface method with body should be non-abstract" + functionDescriptor;
|
||||
CallableMethod method = typeMapper.mapToCallableMethod(compatibility, false);
|
||||
|
||||
generateDelegateToStaticMethodBody(
|
||||
true, mv,
|
||||
method.getAsmMethod(),
|
||||
method.getOwner().getInternalName(),
|
||||
true);
|
||||
methodEnd = new Label();
|
||||
}
|
||||
else {
|
||||
FrameMap frameMap = createFrameMap(
|
||||
parentCodegen.state, signature, functionDescriptor.getExtensionReceiverParameter(),
|
||||
@@ -690,6 +709,16 @@ public class FunctionCodegen {
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isCompatibilityStubInDefaultImpls(
|
||||
@NotNull FunctionDescriptor functionDescriptor,
|
||||
@NotNull MethodContext context,
|
||||
@NotNull JvmDefaultMode jvmDefaultMode
|
||||
) {
|
||||
return OwnerKind.DEFAULT_IMPLS == context.getContextKind() &&
|
||||
hasJvmDefaultAnnotation(functionDescriptor) &&
|
||||
jvmDefaultMode.isCompatibility();
|
||||
}
|
||||
|
||||
private static void generateLocalVariableTable(
|
||||
@NotNull MethodVisitor mv,
|
||||
@NotNull JvmMethodSignature jvmMethodSignature,
|
||||
@@ -869,7 +898,7 @@ public class FunctionCodegen {
|
||||
@NotNull Method asmMethod,
|
||||
@NotNull MultifileClassFacadeContext context
|
||||
) {
|
||||
generateDelegateToStaticMethodBody(true, mv, asmMethod, context.getFilePartType().getInternalName());
|
||||
generateDelegateToStaticMethodBody(true, mv, asmMethod, context.getFilePartType().getInternalName(), false);
|
||||
}
|
||||
|
||||
private static void generateDelegateToMethodBody(
|
||||
@@ -937,9 +966,10 @@ public class FunctionCodegen {
|
||||
boolean isStatic,
|
||||
@NotNull MethodVisitor mv,
|
||||
@NotNull Method asmMethod,
|
||||
@NotNull String classToDelegateTo
|
||||
@NotNull String classToDelegateTo,
|
||||
boolean isInterfaceMethodCall
|
||||
) {
|
||||
generateDelegateToMethodBody(isStatic ? 0 : 1, mv, asmMethod, classToDelegateTo, Opcodes.INVOKESTATIC, false);
|
||||
generateDelegateToMethodBody(isStatic ? 0 : 1, mv, asmMethod, classToDelegateTo, Opcodes.INVOKESTATIC, isInterfaceMethodCall);
|
||||
}
|
||||
|
||||
private static boolean needIndexForVar(JvmMethodParameterKind kind) {
|
||||
@@ -1119,7 +1149,7 @@ public class FunctionCodegen {
|
||||
DeclarationDescriptor contextClass = owner.getContextDescriptor().getContainingDeclaration();
|
||||
|
||||
if (isInterface(contextClass) &&
|
||||
!processInterfaceMethod(functionDescriptor, kind, true)) {
|
||||
!processInterfaceMethod(functionDescriptor, kind, true, state.getJvmDefaultMode())) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1164,6 +1194,17 @@ public class FunctionCodegen {
|
||||
generateFacadeDelegateMethodBody(mv, defaultMethod, (MultifileClassFacadeContext) this.owner);
|
||||
endVisit(mv, "default method delegation", getSourceFromDescriptor(functionDescriptor));
|
||||
}
|
||||
else if (isCompatibilityStubInDefaultImpls(functionDescriptor, owner, state.getJvmDefaultMode())) {
|
||||
mv.visitCode();
|
||||
Method interfaceDefaultMethod = typeMapper.mapDefaultMethod(functionDescriptor, OwnerKind.IMPLEMENTATION);
|
||||
generateDelegateToStaticMethodBody(
|
||||
true, mv,
|
||||
interfaceDefaultMethod,
|
||||
typeMapper.mapOwner(functionDescriptor).getInternalName(),
|
||||
true
|
||||
);
|
||||
endVisit(mv, "default method delegation to interface one", getSourceFromDescriptor(functionDescriptor));
|
||||
}
|
||||
else {
|
||||
mv.visitCode();
|
||||
generateDefaultImplBody(owner, functionDescriptor, mv, loadStrategy, function, memberCodegen, defaultMethod);
|
||||
@@ -1538,14 +1579,15 @@ public class FunctionCodegen {
|
||||
public static boolean processInterfaceMethod(
|
||||
@NotNull CallableMemberDescriptor memberDescriptor,
|
||||
@NotNull OwnerKind kind,
|
||||
boolean isDefaultOrSynthetic
|
||||
boolean isDefaultOrSynthetic,
|
||||
JvmDefaultMode mode
|
||||
) {
|
||||
DeclarationDescriptor containingDeclaration = memberDescriptor.getContainingDeclaration();
|
||||
assert isInterface(containingDeclaration) : "'processInterfaceMethod' method should be called only for interfaces, but: " +
|
||||
containingDeclaration;
|
||||
|
||||
if (hasJvmDefaultAnnotation(memberDescriptor)) {
|
||||
return kind != OwnerKind.DEFAULT_IMPLS;
|
||||
return kind != OwnerKind.DEFAULT_IMPLS || mode.isCompatibility();
|
||||
} else {
|
||||
switch (kind) {
|
||||
case DEFAULT_IMPLS: return true;
|
||||
|
||||
@@ -726,8 +726,19 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
|
||||
@Override
|
||||
public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) {
|
||||
markLineNumberForElement(element.getPsiOrParent(), codegen.v);
|
||||
|
||||
generateMethodCallTo(original, accessor, codegen.v).coerceTo(signature.getReturnType(), null, codegen.v);
|
||||
if (accessor.getName().asString().endsWith("$" + FieldAccessorKind.JVM_DEFAULT_COMPATIBILITY.getSuffix())) {
|
||||
//TODO pass kind
|
||||
FunctionDescriptor descriptor = unwrapFakeOverrideToAnyDeclaration(original).getOriginal();
|
||||
if (descriptor != original) {
|
||||
descriptor = descriptor
|
||||
.copy(original.getContainingDeclaration(), descriptor.getModality(), descriptor.getVisibility(),
|
||||
descriptor.getKind(), false);
|
||||
}
|
||||
generateMethodCallTo(descriptor, accessor, codegen.v).coerceTo(signature.getReturnType(), null, codegen.v);
|
||||
}
|
||||
else {
|
||||
generateMethodCallTo(original, accessor, codegen.v).coerceTo(signature.getReturnType(), null, codegen.v);
|
||||
}
|
||||
|
||||
codegen.v.areturn(signature.getReturnType());
|
||||
}
|
||||
|
||||
@@ -52,6 +52,7 @@ import java.util.List;
|
||||
|
||||
import static org.jetbrains.kotlin.codegen.AsmUtil.getDeprecatedAccessFlag;
|
||||
import static org.jetbrains.kotlin.codegen.AsmUtil.getVisibilityForBackingField;
|
||||
import static org.jetbrains.kotlin.codegen.FunctionCodegen.processInterfaceMethod;
|
||||
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isConstOrHasJvmFieldAnnotation;
|
||||
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isJvmInterface;
|
||||
import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.DELEGATED_PROPERTIES;
|
||||
@@ -352,7 +353,7 @@ public class PropertyCodegen {
|
||||
if (annotations.getAllAnnotations().isEmpty()) return;
|
||||
|
||||
DeclarationDescriptor contextDescriptor = context.getContextDescriptor();
|
||||
if (!isInterface(contextDescriptor) || FunctionCodegen.processInterfaceMethod(descriptor, kind, true)) {
|
||||
if (!isInterface(contextDescriptor) || processInterfaceMethod(descriptor, kind, true, state.getJvmDefaultMode())) {
|
||||
memberCodegen.generateSyntheticAnnotationsMethod(
|
||||
descriptor, getSyntheticMethodSignature(descriptor), annotations, AnnotationUseSiteTarget.PROPERTY
|
||||
);
|
||||
|
||||
@@ -405,6 +405,12 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
||||
return getAccessor(propertyDescriptor, FieldAccessorKind.NORMAL, null, superCallTarget, getterAccessorRequired, setterAccessorRequired);
|
||||
}
|
||||
|
||||
|
||||
public <D extends CallableMemberDescriptor> D getAccessorForJvmDefaultCompatibility(@NotNull D descriptor) {
|
||||
return getAccessor(descriptor, FieldAccessorKind.JVM_DEFAULT_COMPATIBILITY, null,
|
||||
(ClassDescriptor) descriptor.getContainingDeclaration());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private <D extends CallableMemberDescriptor> D getAccessor(@NotNull D descriptor, @Nullable ClassDescriptor superCallTarget) {
|
||||
return getAccessor(descriptor, FieldAccessorKind.NORMAL, null, superCallTarget);
|
||||
|
||||
@@ -192,7 +192,7 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
|
||||
else -> FunctionGenerationStrategy.FunctionDefault(state, expression as KtDeclarationWithBody)
|
||||
}
|
||||
|
||||
FunctionCodegen.generateMethodBody(adapter, descriptor, context, jvmMethodSignature, strategy, parentCodegen)
|
||||
FunctionCodegen.generateMethodBody(adapter, descriptor, context, jvmMethodSignature, strategy, parentCodegen, state.jvmDefaultMode)
|
||||
|
||||
if (isLambda) {
|
||||
codegen.propagateChildReifiedTypeParametersUsages(parentCodegen.reifiedTypeParametersUsages)
|
||||
|
||||
@@ -227,6 +227,8 @@ class GenerationState private constructor(
|
||||
JVMConstructorCallNormalizationMode.DEFAULT
|
||||
)
|
||||
|
||||
val jvmDefaultMode = languageVersionSettings.getFlag(AnalysisFlag.jvmDefaultMode)
|
||||
|
||||
init {
|
||||
val disableOptimization = configuration.get(JVMConfigurationKeys.DISABLE_OPTIMIZATION, false)
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ enum class FieldAccessorKind(val suffix: String) {
|
||||
IN_CLASS_COMPANION("cp"),
|
||||
FIELD_FROM_LOCAL("lp"),
|
||||
LATEINIT_INTRINSIC("li"),
|
||||
JVM_DEFAULT_COMPATIBILITY("jd")
|
||||
}
|
||||
|
||||
private fun CallableMemberDescriptor.getJvmName() =
|
||||
@@ -42,6 +43,6 @@ fun getAccessorNameSuffix(
|
||||
else ->
|
||||
throw UnsupportedOperationException("Do not know how to create accessor for descriptor " + descriptor)
|
||||
}
|
||||
|
||||
if (accessorKind == FieldAccessorKind.JVM_DEFAULT_COMPATIBILITY) return suffix + "$" + FieldAccessorKind.JVM_DEFAULT_COMPATIBILITY.suffix
|
||||
return if (superCallDescriptor == null) suffix else "$suffix\$s${superCallDescriptor.name.asString().hashCode()}"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
// !API_VERSION: 1.3
|
||||
// !JVM_DEFAULT_MODE: compatibility
|
||||
// FILE: Simple.java
|
||||
|
||||
public interface Simple extends KInterface2 {
|
||||
default String test() {
|
||||
return KInterface2.DefaultImpls.test2(this, "OK");
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: Foo.java
|
||||
public class Foo implements Simple {
|
||||
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
// JVM_TARGET: 1.8
|
||||
// WITH_RUNTIME
|
||||
|
||||
interface KInterface<T> {
|
||||
@JvmDefault
|
||||
fun test2(p: T): T {
|
||||
return p
|
||||
}
|
||||
}
|
||||
|
||||
interface KInterface2 : KInterface<String> {
|
||||
|
||||
}
|
||||
|
||||
|
||||
fun box(): String {
|
||||
|
||||
val result = Foo().test()
|
||||
if (result != "OK") return "fail 1: ${result}"
|
||||
|
||||
return Foo().test2("OK")
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
// !API_VERSION: 1.3
|
||||
// !JVM_DEFAULT_MODE: compatibility
|
||||
// FILE: Simple.java
|
||||
|
||||
public interface Simple extends KInterface2 {
|
||||
default String test() {
|
||||
return KInterface2.DefaultImpls.test2(this, "OK");
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: Foo.java
|
||||
public class Foo implements Simple {
|
||||
public String test2(String p) {
|
||||
return "fail";
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
// JVM_TARGET: 1.8
|
||||
// WITH_RUNTIME
|
||||
|
||||
interface KInterface<T> {
|
||||
@JvmDefault
|
||||
fun test2(p: T): T {
|
||||
return p
|
||||
}
|
||||
}
|
||||
|
||||
interface KInterface2 : KInterface<String> {
|
||||
|
||||
}
|
||||
|
||||
|
||||
fun box(): String {
|
||||
return Foo().test()
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
// !API_VERSION: 1.3
|
||||
// !JVM_DEFAULT_MODE: compatibility
|
||||
// FILE: Simple.java
|
||||
|
||||
public interface Simple extends KInterface3 {
|
||||
default String test() {
|
||||
return KInterface3.DefaultImpls.test2(this, "OK");
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: Foo.java
|
||||
public class Foo implements Simple {
|
||||
public String test2(String p) {
|
||||
return "fail";
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
// JVM_TARGET: 1.8
|
||||
// WITH_RUNTIME
|
||||
|
||||
interface KInterface<T> {
|
||||
@JvmDefault
|
||||
fun test2(p: T): T {
|
||||
return p
|
||||
}
|
||||
}
|
||||
|
||||
interface KInterface2 : KInterface<String> {
|
||||
|
||||
}
|
||||
|
||||
interface KInterface3 : KInterface2 {
|
||||
|
||||
}
|
||||
|
||||
|
||||
fun box(): String {
|
||||
return Foo().test()
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
// !API_VERSION: 1.3
|
||||
// !JVM_DEFAULT_MODE: compatibility
|
||||
// JVM_TARGET: 1.8
|
||||
// WITH_RUNTIME
|
||||
// FULL_JDK
|
||||
interface Test {
|
||||
@JvmDefault
|
||||
fun test(s: String ="OK"): String {
|
||||
return s
|
||||
}
|
||||
}
|
||||
|
||||
class TestClass : Test {
|
||||
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val defaultImpls = java.lang.Class.forName(Test::class.java.canonicalName + "\$DefaultImpls")
|
||||
|
||||
val declaredMethod = defaultImpls.getDeclaredMethod("test\$default", Test::class.java, String::class.java, Int::class.java, Any::class.java)
|
||||
return declaredMethod.invoke(null, TestClass(), null, 1, null) as String
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
// !API_VERSION: 1.3
|
||||
// !JVM_DEFAULT_MODE: compatibility
|
||||
// FILE: Simple.java
|
||||
|
||||
public interface Simple extends KInterface2 {
|
||||
default String test() {
|
||||
return KInterface2.DefaultImpls.test2(this);
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: Foo.java
|
||||
public class Foo implements Simple {
|
||||
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
// JVM_TARGET: 1.8
|
||||
// WITH_RUNTIME
|
||||
|
||||
interface KInterface {
|
||||
@JvmDefault
|
||||
fun test2(): String {
|
||||
return "OK"
|
||||
}
|
||||
}
|
||||
|
||||
interface KInterface2 : KInterface {
|
||||
|
||||
}
|
||||
|
||||
|
||||
fun box(): String {
|
||||
val result = Foo().test()
|
||||
if (result != "OK") return "fail 1: ${result}"
|
||||
|
||||
return Foo().test2()
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
// !API_VERSION: 1.3
|
||||
// !JVM_DEFAULT_MODE: compatibility
|
||||
// FILE: Simple.java
|
||||
|
||||
public interface Simple extends KInterface {
|
||||
default String test() {
|
||||
return KInterface.DefaultImpls.test2(this);
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: Foo.java
|
||||
public class Foo implements Simple {
|
||||
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
// JVM_TARGET: 1.8
|
||||
// WITH_RUNTIME
|
||||
|
||||
interface KInterface {
|
||||
@JvmDefault
|
||||
fun test2(): String {
|
||||
return "OK"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun box(): String {
|
||||
val result = Foo().test()
|
||||
if (result != "OK") return "fail 1: ${result}"
|
||||
|
||||
return Foo().test2()
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
// !API_VERSION: 1.3
|
||||
// !JVM_DEFAULT_MODE: compatibility
|
||||
// JVM_TARGET: 1.8
|
||||
// WITH_RUNTIME
|
||||
// FULL_JDK
|
||||
interface KInterface {
|
||||
@JvmDefault
|
||||
fun test(s: String ="OK"): String {
|
||||
return s
|
||||
}
|
||||
}
|
||||
|
||||
// 1 INVOKESTATIC KInterface.access\$test\$jd
|
||||
// 1 INVOKESTATIC KInterface.test\$default
|
||||
|
||||
// from $default
|
||||
// 1 INVOKEINTERFACE KInterface.test
|
||||
|
||||
//from $jd
|
||||
// 1 INVOKESPECIAL KInterface.test
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
// !API_VERSION: 1.3
|
||||
// !JVM_DEFAULT_MODE: compatibility
|
||||
// JVM_TARGET: 1.8
|
||||
|
||||
interface KInterface {
|
||||
@JvmDefault
|
||||
fun test2(): String {
|
||||
return "OK"
|
||||
}
|
||||
}
|
||||
|
||||
interface KInterface2 : KInterface {
|
||||
|
||||
}
|
||||
|
||||
// 1 INVOKESTATIC KInterface2.access\$test2\$jd
|
||||
// 1 INVOKESTATIC KInterface.access\$test2\$jd
|
||||
|
||||
// 1 INVOKESPECIAL KInterface2.test2
|
||||
// 1 INVOKESPECIAL KInterface.test2
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
// !API_VERSION: 1.3
|
||||
// !JVM_DEFAULT_MODE: compatibility
|
||||
// JVM_TARGET: 1.8
|
||||
|
||||
interface KInterface {
|
||||
@JvmDefault
|
||||
fun test2(): String {
|
||||
return "OK"
|
||||
}
|
||||
}
|
||||
|
||||
interface KInterface2 : KInterface {
|
||||
@JvmDefault
|
||||
abstract override fun test2(): String
|
||||
}
|
||||
|
||||
// 1 INVOKESTATIC KInterface.access\$test2\$jd
|
||||
// +
|
||||
// 0 INVOKESTATIC KInterface2.access\$test2\$jd
|
||||
// =
|
||||
// 1 INVOKESTATIC
|
||||
|
||||
// 1 INVOKESPECIAL KInterface.test2
|
||||
// 0 INVOKESPECIAL KInterface2.test2
|
||||
Generated
+43
@@ -481,6 +481,49 @@ public class BlackBoxWithJava8CodegenTestGenerated extends AbstractBlackBoxCodeg
|
||||
runTest("compiler/testData/codegen/java8/box/jvm8/defaults/superCall.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/java8/box/jvm8/defaults/compatibility")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class Compatibility extends AbstractBlackBoxCodegenTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInCompatibility() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/java8/box/jvm8/defaults/compatibility"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
||||
}
|
||||
|
||||
@TestMetadata("bridge.kt")
|
||||
public void testBridge() throws Exception {
|
||||
runTest("compiler/testData/codegen/java8/box/jvm8/defaults/compatibility/bridge.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("bridge2.kt")
|
||||
public void testBridge2() throws Exception {
|
||||
runTest("compiler/testData/codegen/java8/box/jvm8/defaults/compatibility/bridge2.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("bridge3.kt")
|
||||
public void testBridge3() throws Exception {
|
||||
runTest("compiler/testData/codegen/java8/box/jvm8/defaults/compatibility/bridge3.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("defaultArgs.kt")
|
||||
public void testDefaultArgs() throws Exception {
|
||||
runTest("compiler/testData/codegen/java8/box/jvm8/defaults/compatibility/defaultArgs.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inheritedJvmDefault.kt")
|
||||
public void testInheritedJvmDefault() throws Exception {
|
||||
runTest("compiler/testData/codegen/java8/box/jvm8/defaults/compatibility/inheritedJvmDefault.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("simpleFunction.kt")
|
||||
public void testSimpleFunction() throws Exception {
|
||||
runTest("compiler/testData/codegen/java8/box/jvm8/defaults/compatibility/simpleFunction.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/java8/box/jvm8/defaults/delegationBy")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
Generated
+41
@@ -51,4 +51,45 @@ public class BytecodeTextJava8TestGenerated extends AbstractBytecodeTextTest {
|
||||
runTest("compiler/testData/codegen/java8/bytecodeText/hashCode/hashCode.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/java8/bytecodeText/jvmDefault")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class JvmDefault extends AbstractBytecodeTextTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInJvmDefault() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/java8/bytecodeText/jvmDefault"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/java8/bytecodeText/jvmDefault/compatibility")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class Compatibility extends AbstractBytecodeTextTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInCompatibility() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/java8/bytecodeText/jvmDefault/compatibility"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
||||
}
|
||||
|
||||
@TestMetadata("defaultArgs.kt")
|
||||
public void testDefaultArgs() throws Exception {
|
||||
runTest("compiler/testData/codegen/java8/bytecodeText/jvmDefault/compatibility/defaultArgs.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("simpleFunction.kt")
|
||||
public void testSimpleFunction() throws Exception {
|
||||
runTest("compiler/testData/codegen/java8/bytecodeText/jvmDefault/compatibility/simpleFunction.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("simpleFunctionWithAbstractOverride.kt")
|
||||
public void testSimpleFunctionWithAbstractOverride() throws Exception {
|
||||
runTest("compiler/testData/codegen/java8/bytecodeText/jvmDefault/compatibility/simpleFunctionWithAbstractOverride.kt");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,9 @@ enum class JvmDefaultMode(val description: String) {
|
||||
val isEnabled
|
||||
get() = this != DISABLE
|
||||
|
||||
val isCompatibility
|
||||
get() = this == ENABLE_WITH_DEFAULT_IMPLS
|
||||
|
||||
companion object {
|
||||
@JvmField
|
||||
val DEFAULT = DISABLE
|
||||
|
||||
Reference in New Issue
Block a user