diff --git a/libraries/kotlinx-metadata/jvm/ChangeLog.md b/libraries/kotlinx-metadata/jvm/ChangeLog.md index d41bd219683..4ded0e01e08 100644 --- a/libraries/kotlinx-metadata/jvm/ChangeLog.md +++ b/libraries/kotlinx-metadata/jvm/ChangeLog.md @@ -3,6 +3,10 @@ ## Next - Add `JvmPropertyExtensionVisitor.visitSyntheticMethodForDelegate` for optimized delegated properties (KT-39055). +- Add JVM-specific class flags: + - `JvmClassExtensionVisitor.visitJvmFlags` + - `JvmFlag.Class.HAS_METHOD_BODIES_IN_INTERFACE` + - `JvmFlag.Class.IS_COMPILED_IN_COMPATIBILITY_MODE` - [`KT-48965`](https://youtrack.jetbrains.com/issue/KT-48965) Make the type of `KmValueParameter.type` non-null `KmType` ## 0.3.0 diff --git a/libraries/tools/kotlinp/src/org/jetbrains/kotlin/kotlinp/printers.kt b/libraries/tools/kotlinp/src/org/jetbrains/kotlin/kotlinp/printers.kt index 1819491cd16..07c33cac822 100644 --- a/libraries/tools/kotlinp/src/org/jetbrains/kotlin/kotlinp/printers.kt +++ b/libraries/tools/kotlinp/src/org/jetbrains/kotlin/kotlinp/printers.kt @@ -794,11 +794,16 @@ class ClassPrinter(private val settings: KotlinpSettings) : KmClassVisitor(), Ab return object : JvmClassExtensionVisitor() { private val localDelegatedProperties = mutableListOf() private var moduleName: String? = null + private var jvmFlags: Flags? = null override fun visitAnonymousObjectOriginName(internalName: String) { anonymousObjectOriginName = internalName } + override fun visitJvmFlags(flags: Flags) { + jvmFlags = flags + } + override fun visitLocalDelegatedProperty( flags: Flags, name: String, getterFlags: Flags, setterFlags: Flags ): KmPropertyVisitor? = visitProperty( @@ -811,6 +816,17 @@ class ClassPrinter(private val settings: KotlinpSettings) : KmClassVisitor(), Ab override fun visitEnd() { sb.appendDeclarationContainerExtensions(settings, localDelegatedProperties, moduleName) + val flags = jvmFlags + if (flags != null) { + if (JvmFlag.Class.HAS_METHOD_BODIES_IN_INTERFACE(flags)) { + sb.appendLine() + sb.appendLine(" // has method bodies in interface") + } + if (JvmFlag.Class.IS_COMPILED_IN_COMPATIBILITY_MODE(flags)) { + sb.appendLine() + sb.appendLine(" // is compiled in compatibility mode") + } + } } } } diff --git a/libraries/tools/kotlinp/test/org/jetbrains/kotlin/kotlinp/test/KotlinpTestGenerated.java b/libraries/tools/kotlinp/test/org/jetbrains/kotlin/kotlinp/test/KotlinpTestGenerated.java index dcf407c9521..8918c9d6d40 100644 --- a/libraries/tools/kotlinp/test/org/jetbrains/kotlin/kotlinp/test/KotlinpTestGenerated.java +++ b/libraries/tools/kotlinp/test/org/jetbrains/kotlin/kotlinp/test/KotlinpTestGenerated.java @@ -118,4 +118,27 @@ public class KotlinpTestGenerated extends AbstractKotlinpTest { public void testVersionRequirement() throws Exception { runTest("libraries/tools/kotlinp/testData/VersionRequirement.kt"); } + + @TestMetadata("libraries/tools/kotlinp/testData/jvmDefault") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class JvmDefault extends AbstractKotlinpTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + @TestMetadata("All.kt") + public void testAll() throws Exception { + runTest("libraries/tools/kotlinp/testData/jvmDefault/All.kt"); + } + + @TestMetadata("AllCompatibility.kt") + public void testAllCompatibility() throws Exception { + runTest("libraries/tools/kotlinp/testData/jvmDefault/AllCompatibility.kt"); + } + + public void testAllFilesPresentInJvmDefault() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("libraries/tools/kotlinp/testData/jvmDefault"), Pattern.compile("^(.+)\\.kt$"), null, true); + } + } } diff --git a/libraries/tools/kotlinp/testData/jvmDefault/All.kt b/libraries/tools/kotlinp/testData/jvmDefault/All.kt new file mode 100644 index 00000000000..93e426ec6e1 --- /dev/null +++ b/libraries/tools/kotlinp/testData/jvmDefault/All.kt @@ -0,0 +1,12 @@ +// !JVM_DEFAULT_MODE: all + +interface A { + fun f() {} + fun g() +} + +interface B : A { + override fun g() {} +} + +class C : B diff --git a/libraries/tools/kotlinp/testData/jvmDefault/All.txt b/libraries/tools/kotlinp/testData/jvmDefault/All.txt new file mode 100644 index 00000000000..d167f8f626b --- /dev/null +++ b/libraries/tools/kotlinp/testData/jvmDefault/All.txt @@ -0,0 +1,40 @@ +// A.class +// ------------------------------------------ +// requires compiler version 1.4.0 (level=ERROR) +public abstract interface A : kotlin/Any { + + // signature: f()V + public open fun f(): kotlin/Unit + + // signature: g()V + public abstract fun g(): kotlin/Unit + + // module name: test-module + + // has method bodies in interface +} +// B.class +// ------------------------------------------ +// requires compiler version 1.4.0 (level=ERROR) +public abstract interface B : A { + + // signature: g()V + public open fun g(): kotlin/Unit + + // module name: test-module + + // has method bodies in interface +} +// C.class +// ------------------------------------------ +public final class C : B { + + // signature: ()V + public constructor() + + // module name: test-module +} +// META-INF/test-module.kotlin_module +// ------------------------------------------ +module { +} diff --git a/libraries/tools/kotlinp/testData/jvmDefault/AllCompatibility.kt b/libraries/tools/kotlinp/testData/jvmDefault/AllCompatibility.kt new file mode 100644 index 00000000000..69558009752 --- /dev/null +++ b/libraries/tools/kotlinp/testData/jvmDefault/AllCompatibility.kt @@ -0,0 +1,12 @@ +// !JVM_DEFAULT_MODE: all-compatibility + +interface A { + fun f() {} + fun g() +} + +interface B : A { + override fun g() {} +} + +class C : B diff --git a/libraries/tools/kotlinp/testData/jvmDefault/AllCompatibility.txt b/libraries/tools/kotlinp/testData/jvmDefault/AllCompatibility.txt new file mode 100644 index 00000000000..ea2f081fdec --- /dev/null +++ b/libraries/tools/kotlinp/testData/jvmDefault/AllCompatibility.txt @@ -0,0 +1,48 @@ +// A.class +// ------------------------------------------ +public abstract interface A : kotlin/Any { + + // signature: f()V + public open fun f(): kotlin/Unit + + // signature: g()V + public abstract fun g(): kotlin/Unit + + // module name: test-module + + // has method bodies in interface + + // is compiled in compatibility mode +} +// A$DefaultImpls.class +// ------------------------------------------ +synthetic class +// B.class +// ------------------------------------------ +public abstract interface B : A { + + // signature: g()V + public open fun g(): kotlin/Unit + + // module name: test-module + + // has method bodies in interface + + // is compiled in compatibility mode +} +// B$DefaultImpls.class +// ------------------------------------------ +synthetic class +// C.class +// ------------------------------------------ +public final class C : B { + + // signature: ()V + public constructor() + + // module name: test-module +} +// META-INF/test-module.kotlin_module +// ------------------------------------------ +module { +}