Support cross-module usages of @JvmRecord classes
The problem is that JvmRecord has SOURCE retention Probably, increasing its retention might be a more reliable solution (or in some other way serializing that the class is a record) Just checking supertypes seems like a reasonable approximation: only records kotlin are allowed to extend j.l.Record. But the relevant diagnostic has been added only since 1.4.30, so potentially there could have been exist a non-record class with such supertype compiled by 1.4.20, but this case seems to be ill-formed and marginal anyway. For Java classes, it's irrelevant since they don't have member properties (only synthetic extensions) ^KT-43677 In Progress
This commit is contained in:
@@ -61,9 +61,9 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.isPublishedApi
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.DEFAULT_CONSTRUCTOR_MARKER
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE
|
||||
import org.jetbrains.kotlin.resolve.jvm.JAVA_LANG_RECORD_FQ_NAME
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||
import org.jetbrains.kotlin.resolve.jvm.annotations.isCompiledToJvmDefault
|
||||
import org.jetbrains.kotlin.resolve.jvm.annotations.isJvmRecord
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodGenericSignature
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||
@@ -592,7 +592,7 @@ class KotlinTypeMapper @JvmOverloads constructor(
|
||||
return property.name.asString()
|
||||
}
|
||||
|
||||
if ((containingDeclaration as? ClassDescriptor)?.isJvmRecord() == true) return property.name.asString()
|
||||
if ((containingDeclaration as? ClassDescriptor)?.hasJavaLangRecordSupertype() == true) return property.name.asString()
|
||||
|
||||
val isAccessor = property is AccessorForPropertyDescriptor
|
||||
val propertyName = if (isAccessor)
|
||||
@@ -628,6 +628,9 @@ class KotlinTypeMapper @JvmOverloads constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private fun ClassDescriptor.hasJavaLangRecordSupertype() =
|
||||
typeConstructor.supertypes.any { KotlinBuiltIns.isConstructedFromGivenClass(it, JAVA_LANG_RECORD_FQ_NAME) }
|
||||
|
||||
private val shouldMangleByReturnType =
|
||||
languageVersionSettings.supportsFeature(LanguageFeature.MangleClassMembersReturningInlineClasses)
|
||||
|
||||
|
||||
+4
-3
@@ -41,7 +41,7 @@ import org.jetbrains.kotlin.metadata.deserialization.getExtensionOrNull
|
||||
import org.jetbrains.kotlin.metadata.jvm.JvmProtoBuf
|
||||
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmProtoBufUtil
|
||||
import org.jetbrains.kotlin.name.NameUtils
|
||||
import org.jetbrains.kotlin.resolve.jvm.annotations.JVM_RECORD_ANNOTATION_FQ_NAME
|
||||
import org.jetbrains.kotlin.resolve.jvm.JAVA_LANG_RECORD_FQ_NAME
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodGenericSignature
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||
@@ -84,8 +84,7 @@ class MethodSignatureMapper(private val context: JvmBackendContext) {
|
||||
if (property != null) {
|
||||
val propertyName = property.name.asString()
|
||||
val propertyParent = property.parentAsClass
|
||||
if (propertyParent.isAnnotationClass || propertyParent.hasAnnotation(JVM_RECORD_ANNOTATION_FQ_NAME))
|
||||
return propertyName
|
||||
if (propertyParent.isAnnotationClass || propertyParent.superTypes.any { it.isJavaLangRecord() }) return propertyName
|
||||
|
||||
// The enum property getters <get-name> and <get-ordinal> have special names which also
|
||||
// apply to their fake overrides. Unfortunately, getJvmMethodNameIfSpecial does not handle
|
||||
@@ -102,6 +101,8 @@ class MethodSignatureMapper(private val context: JvmBackendContext) {
|
||||
return mangleMemberNameIfRequired(function.name.asString(), function)
|
||||
}
|
||||
|
||||
private fun IrType.isJavaLangRecord() = getClass()!!.hasEqualFqName(JAVA_LANG_RECORD_FQ_NAME)
|
||||
|
||||
private fun mangleMemberNameIfRequired(name: String, function: IrSimpleFunction): String {
|
||||
val newName = JvmCodegenUtil.sanitizeNameIfNeeded(name, context.state.languageVersionSettings)
|
||||
|
||||
|
||||
@@ -17,7 +17,9 @@ import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.ir.types.impl.*
|
||||
import org.jetbrains.kotlin.ir.util.defaultType
|
||||
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
|
||||
import org.jetbrains.kotlin.ir.util.isPropertyAccessor
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
|
||||
import org.jetbrains.kotlin.types.typeUtil.makeNullable
|
||||
@@ -74,6 +76,9 @@ val IrType.classifierOrNull: IrClassifierSymbol?
|
||||
val IrType.classOrNull: IrClassSymbol?
|
||||
get() = classifierOrNull as? IrClassSymbol
|
||||
|
||||
val IrType.classFqName: FqName?
|
||||
get() = classOrNull?.owner?.fqNameWhenAvailable
|
||||
|
||||
val IrTypeArgument.typeOrNull: IrType? get() = (this as? IrTypeProjection)?.type
|
||||
|
||||
fun IrType.makeNotNull() =
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
// !API_VERSION: 1.5
|
||||
// !LANGUAGE: +JvmRecordSupport
|
||||
// JVM_TARGET: 15_PREVIEW
|
||||
// FILE: A.kt
|
||||
@JvmRecord
|
||||
data class MyRecord(val foo: String, val bar: String)
|
||||
|
||||
// FILE: B.kt
|
||||
|
||||
fun main() {
|
||||
val myRecord = MyRecord("O", "K")
|
||||
val s = myRecord.foo + myRecord.bar
|
||||
if (s != "OK") {
|
||||
throw AssertionError("fail: $s")
|
||||
}
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.codegen
|
||||
|
||||
import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||
import org.jetbrains.kotlin.test.TestJdkKind
|
||||
|
||||
abstract class AbstractCompileKotlinAgainstKotlinJdk15Test : AbstractCompileKotlinAgainstKotlinTest() {
|
||||
override fun invokeBox(className: String) {
|
||||
runJvmInstance(
|
||||
KotlinTestUtils.getJdk15Home(),
|
||||
additionalArgs = listOf("--enable-preview"),
|
||||
classPath = listOfNotNull(
|
||||
aDir, bDir, ForTestCompileRuntime.runtimeJarForTests(),
|
||||
),
|
||||
className
|
||||
)
|
||||
}
|
||||
|
||||
override fun getTestJdkKind(files: List<TestFile>): TestJdkKind {
|
||||
return TestJdkKind.FULL_JDK_15
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -35,8 +35,8 @@ import java.util.stream.Collectors;
|
||||
|
||||
public abstract class AbstractCompileKotlinAgainstKotlinTest extends CodegenTestCase {
|
||||
private File tmpdir;
|
||||
private File aDir;
|
||||
private File bDir;
|
||||
protected File aDir;
|
||||
protected File bDir;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
@@ -80,7 +80,7 @@ public abstract class AbstractCompileKotlinAgainstKotlinTest extends CodegenTest
|
||||
return new Pair<>(factoryA, factoryB);
|
||||
}
|
||||
|
||||
private void invokeBox(@NotNull String className) throws Exception {
|
||||
protected void invokeBox(@NotNull String className) throws Exception {
|
||||
callBoxMethodAndCheckResult(createGeneratedClassLoader(), className);
|
||||
}
|
||||
|
||||
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.codegen
|
||||
|
||||
import org.jetbrains.kotlin.test.TargetBackend
|
||||
|
||||
abstract class AbstractIrCompileKotlinAgainstKotlinJdk15Test : AbstractCompileKotlinAgainstKotlinJdk15Test() {
|
||||
override fun getBackendA(): TargetBackend {
|
||||
return TargetBackend.JVM_IR
|
||||
}
|
||||
|
||||
override fun getBackendB(): TargetBackend {
|
||||
return TargetBackend.JVM_IR
|
||||
}
|
||||
}
|
||||
Generated
+35
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.codegen;
|
||||
|
||||
import com.intellij.testFramework.TestDataPath;
|
||||
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils;
|
||||
import org.jetbrains.kotlin.test.TestMetadata;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
|
||||
@SuppressWarnings("all")
|
||||
@TestMetadata("compiler/testData/compileKotlinAgainstKotlinJdk15")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public class CompileKotlinAgainstKotlinJdk15TestGenerated extends AbstractCompileKotlinAgainstKotlinJdk15Test {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInCompileKotlinAgainstKotlinJdk15() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/compileKotlinAgainstKotlinJdk15"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@TestMetadata("jvmRecordBinary.kt")
|
||||
public void testJvmRecordBinary() throws Exception {
|
||||
runTest("compiler/testData/compileKotlinAgainstKotlinJdk15/jvmRecordBinary.kt");
|
||||
}
|
||||
}
|
||||
Generated
+35
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.codegen;
|
||||
|
||||
import com.intellij.testFramework.TestDataPath;
|
||||
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils;
|
||||
import org.jetbrains.kotlin.test.TestMetadata;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
|
||||
@SuppressWarnings("all")
|
||||
@TestMetadata("compiler/testData/compileKotlinAgainstKotlinJdk15")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public class IrCompileKotlinAgainstKotlinJdk15TestGenerated extends AbstractIrCompileKotlinAgainstKotlinJdk15Test {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInCompileKotlinAgainstKotlinJdk15() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/compileKotlinAgainstKotlinJdk15"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@TestMetadata("jvmRecordBinary.kt")
|
||||
public void testJvmRecordBinary() throws Exception {
|
||||
runTest("compiler/testData/compileKotlinAgainstKotlinJdk15/jvmRecordBinary.kt");
|
||||
}
|
||||
}
|
||||
@@ -368,6 +368,14 @@ fun main(args: Array<String>) {
|
||||
model("compileKotlinAgainstKotlin")
|
||||
}
|
||||
|
||||
testClass<AbstractCompileKotlinAgainstKotlinJdk15Test> {
|
||||
model("compileKotlinAgainstKotlinJdk15")
|
||||
}
|
||||
|
||||
testClass<AbstractIrCompileKotlinAgainstKotlinJdk15Test> {
|
||||
model("compileKotlinAgainstKotlinJdk15")
|
||||
}
|
||||
|
||||
testClass<AbstractDescriptorRendererTest> {
|
||||
model("renderer")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user