diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightClass.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightClass.kt index c870ac26212..e4d57f63012 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightClass.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightClass.kt @@ -40,6 +40,7 @@ import org.jetbrains.kotlin.resolve.annotations.JVM_STATIC_ANNOTATION_FQ_NAME import org.jetbrains.kotlin.resolve.annotations.argumentValue import org.jetbrains.kotlin.resolve.constants.EnumValue import org.jetbrains.kotlin.resolve.jvm.annotations.JVM_OVERLOADS_FQ_NAME +import org.jetbrains.kotlin.resolve.jvm.annotations.JVM_RECORD_ANNOTATION_FQ_NAME import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.typeUtil.isAnyOrNullableAny @@ -282,7 +283,8 @@ open class KtUltraLightClass(classOrObject: KtClassOrObject, internal val suppor parameter.isMutable, forceStatic = false, onlyJvmStatic = false, - createAsAnnotationMethod = isAnnotationType + createAsAnnotationMethod = isAnnotationType, + isJvmRecord = classOrObject.hasAnnotation(JVM_RECORD_ANNOTATION_FQ_NAME), ) ) } @@ -509,4 +511,4 @@ open class KtUltraLightClass(classOrObject: KtClassOrObject, internal val suppor return super.getTextRange() } -} \ No newline at end of file +} diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightMembersCreator.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightMembersCreator.kt index 8952b5394ac..f75639c9810 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightMembersCreator.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightMembersCreator.kt @@ -405,7 +405,8 @@ internal class UltraLightMembersCreator( mutable: Boolean, forceStatic: Boolean, onlyJvmStatic: Boolean, - createAsAnnotationMethod: Boolean = false + createAsAnnotationMethod: Boolean = false, + isJvmRecord: Boolean = false, ): List { val propertyName = declaration.name ?: return emptyList() @@ -454,7 +455,7 @@ internal class UltraLightMembersCreator( auxiliaryOriginalElement = auxiliaryOrigin ) - val defaultGetterName = if (createAsAnnotationMethod) propertyName else JvmAbi.getterName(propertyName) + val defaultGetterName = if (createAsAnnotationMethod || isJvmRecord) propertyName else JvmAbi.getterName(propertyName) val getterName = computeMethodName(auxiliaryOrigin, defaultGetterName, MethodType.GETTER) val getterPrototype = lightMethod(getterName, auxiliaryOrigin, forceStatic = onlyJvmStatic || forceStatic) val getterWrapper = KtUltraLightMethodForSourceDeclaration( diff --git a/compiler/testData/asJava/ultraLightClasses/jvmRecord.java b/compiler/testData/asJava/ultraLightClasses/jvmRecord.java new file mode 100644 index 00000000000..26459b28e6f --- /dev/null +++ b/compiler/testData/asJava/ultraLightClasses/jvmRecord.java @@ -0,0 +1,24 @@ +@kotlin.jvm.JvmRecord() +public final class MyRec /* pkg.MyRec*/ { + @org.jetbrains.annotations.NotNull() + private final java.lang.String name; + + @org.jetbrains.annotations.NotNull() + public final java.lang.String component1();// component1() + + @org.jetbrains.annotations.NotNull() + public final java.lang.String name();// name() + + @org.jetbrains.annotations.NotNull() + public final pkg.MyRec copy(@org.jetbrains.annotations.NotNull() java.lang.String);// copy(java.lang.String) + + @org.jetbrains.annotations.NotNull() + public java.lang.String toString();// toString() + + public MyRec(@org.jetbrains.annotations.NotNull() java.lang.String);// .ctor(java.lang.String) + + public boolean equals(@org.jetbrains.annotations.Nullable() java.lang.Object);// equals(java.lang.Object) + + public int hashCode();// hashCode() + +} diff --git a/compiler/testData/asJava/ultraLightClasses/jvmRecord.kt b/compiler/testData/asJava/ultraLightClasses/jvmRecord.kt new file mode 100644 index 00000000000..d7a04af2228 --- /dev/null +++ b/compiler/testData/asJava/ultraLightClasses/jvmRecord.kt @@ -0,0 +1,8 @@ +// CHECK_BY_JAVA_FILE +// API_VERSION: 1.5 +// JVM_TARGET: 15 +// COMPILER_ARGUMENTS: -XXLanguage:+JvmRecordSupport -Xjvm-enable-preview +package pkg + +@JvmRecord +data class MyRec(val name: String) diff --git a/idea/idea-fir/tests/org/jetbrains/kotlin/asJava/classes/FirClassLoadingTestGenerated.java b/idea/idea-fir/tests/org/jetbrains/kotlin/asJava/classes/FirClassLoadingTestGenerated.java index 7b94904f4a7..f76176205ec 100644 --- a/idea/idea-fir/tests/org/jetbrains/kotlin/asJava/classes/FirClassLoadingTestGenerated.java +++ b/idea/idea-fir/tests/org/jetbrains/kotlin/asJava/classes/FirClassLoadingTestGenerated.java @@ -134,6 +134,11 @@ public class FirClassLoadingTestGenerated extends AbstractFirClassLoadingTest { runTest("compiler/testData/asJava/ultraLightClasses/jvmOverloads.kt"); } + @TestMetadata("jvmRecord.kt") + public void testJvmRecord() throws Exception { + runTest("compiler/testData/asJava/ultraLightClasses/jvmRecord.kt"); + } + @TestMetadata("jvmSynthetic.kt") public void testJvmSynthetic() throws Exception { runTest("compiler/testData/asJava/ultraLightClasses/jvmSynthetic.kt"); diff --git a/idea/idea-test-framework/test/org/jetbrains/kotlin/idea/test/KotlinLightCodeInsightFixtureTestCase.kt b/idea/idea-test-framework/test/org/jetbrains/kotlin/idea/test/KotlinLightCodeInsightFixtureTestCase.kt index cb376751591..bfb2894acee 100644 --- a/idea/idea-test-framework/test/org/jetbrains/kotlin/idea/test/KotlinLightCodeInsightFixtureTestCase.kt +++ b/idea/idea-test-framework/test/org/jetbrains/kotlin/idea/test/KotlinLightCodeInsightFixtureTestCase.kt @@ -46,6 +46,7 @@ import org.jetbrains.kotlin.idea.inspections.UnusedSymbolInspection import org.jetbrains.kotlin.idea.test.CompilerTestDirectives.COMPILER_ARGUMENTS_DIRECTIVE import org.jetbrains.kotlin.idea.test.CompilerTestDirectives.JVM_TARGET_DIRECTIVE import org.jetbrains.kotlin.idea.test.CompilerTestDirectives.LANGUAGE_VERSION_DIRECTIVE +import org.jetbrains.kotlin.idea.test.CompilerTestDirectives.API_VERSION_DIRECTIVE import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.test.InTextDirectivesUtils import org.jetbrains.kotlin.test.KotlinTestUtils @@ -245,6 +246,7 @@ abstract class KotlinLightCodeInsightFixtureTestCase : KotlinLightCodeInsightFix object CompilerTestDirectives { const val LANGUAGE_VERSION_DIRECTIVE = "LANGUAGE_VERSION:" + const val API_VERSION_DIRECTIVE = "API_VERSION:" const val JVM_TARGET_DIRECTIVE = "JVM_TARGET:" const val COMPILER_ARGUMENTS_DIRECTIVE = "COMPILER_ARGUMENTS:" @@ -265,6 +267,7 @@ fun withCustomCompilerOptions(fileText: String, project: Project, module: Mo private fun configureCompilerOptions(fileText: String, project: Project, module: Module): Boolean { val version = InTextDirectivesUtils.findStringWithPrefixes(fileText, "// $LANGUAGE_VERSION_DIRECTIVE ") + val apiVersion = InTextDirectivesUtils.findStringWithPrefixes(fileText, "// $API_VERSION_DIRECTIVE ") val jvmTarget = InTextDirectivesUtils.findStringWithPrefixes(fileText, "// $JVM_TARGET_DIRECTIVE ") // We can have several such directives in quickFixMultiFile tests // TODO: refactor such tests or add sophisticated check for the directive @@ -274,7 +277,7 @@ private fun configureCompilerOptions(fileText: String, project: Project, module: configureLanguageAndApiVersion( project, module, version ?: LanguageVersion.LATEST_STABLE.versionString, - null + apiVersion ) val facetSettings = KotlinFacet.get(module)!!.configuration.settings diff --git a/idea/tests/org/jetbrains/kotlin/asJava/classes/AbstractUltraLightClassLoadingTest.kt b/idea/tests/org/jetbrains/kotlin/asJava/classes/AbstractUltraLightClassLoadingTest.kt index debe8714cdf..fb050f385a8 100644 --- a/idea/tests/org/jetbrains/kotlin/asJava/classes/AbstractUltraLightClassLoadingTest.kt +++ b/idea/tests/org/jetbrains/kotlin/asJava/classes/AbstractUltraLightClassLoadingTest.kt @@ -14,6 +14,7 @@ import org.jetbrains.kotlin.idea.perf.UltraLightChecker.checkByJavaFile import org.jetbrains.kotlin.idea.perf.UltraLightChecker.checkDescriptorsLeak import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor +import org.jetbrains.kotlin.idea.test.withCustomCompilerOptions import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.test.InTextDirectivesUtils import org.jetbrains.kotlin.test.KotlinTestUtils @@ -24,24 +25,26 @@ abstract class AbstractUltraLightClassLoadingTest : KotlinLightCodeInsightFixtur open fun doTest(testDataPath: String) { val sourceText = File(testDataPath).readText() - val file = myFixture.addFileToProject(testDataPath, sourceText) as KtFile + withCustomCompilerOptions(sourceText, project, module) { + val file = myFixture.addFileToProject(testDataPath, sourceText) as KtFile - UltraLightChecker.checkForReleaseCoroutine(sourceText, module) + UltraLightChecker.checkForReleaseCoroutine(sourceText, module) - val checkByJavaFile = InTextDirectivesUtils.isDirectiveDefined(sourceText, "CHECK_BY_JAVA_FILE") + val checkByJavaFile = InTextDirectivesUtils.isDirectiveDefined(sourceText, "CHECK_BY_JAVA_FILE") - val ktClassOrObjects = UltraLightChecker.allClasses(file) + val ktClassOrObjects = UltraLightChecker.allClasses(file) - if (checkByJavaFile) { - val classFabric = LightClassGenerationSupport.getInstance(project) - val classList = ktClassOrObjects.mapNotNull { classFabric.createUltraLightClass(it) } - checkByJavaFile(testDataPath, classList) - classList.forEach { checkDescriptorsLeak(it) } - } else { - for (ktClass in ktClassOrObjects) { - val ultraLightClass = UltraLightChecker.checkClassEquivalence(ktClass) - if (ultraLightClass != null) { - checkDescriptorsLeak(ultraLightClass) + if (checkByJavaFile) { + val classFabric = LightClassGenerationSupport.getInstance(project) + val classList = ktClassOrObjects.mapNotNull { classFabric.createUltraLightClass(it) } + checkByJavaFile(testDataPath, classList) + classList.forEach { checkDescriptorsLeak(it) } + } else { + for (ktClass in ktClassOrObjects) { + val ultraLightClass = UltraLightChecker.checkClassEquivalence(ktClass) + if (ultraLightClass != null) { + checkDescriptorsLeak(ultraLightClass) + } } } } diff --git a/idea/tests/org/jetbrains/kotlin/asJava/classes/UltraLightClassLoadingTestGenerated.java b/idea/tests/org/jetbrains/kotlin/asJava/classes/UltraLightClassLoadingTestGenerated.java index b5ad2192456..092946c7d3d 100644 --- a/idea/tests/org/jetbrains/kotlin/asJava/classes/UltraLightClassLoadingTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/asJava/classes/UltraLightClassLoadingTestGenerated.java @@ -134,6 +134,11 @@ public class UltraLightClassLoadingTestGenerated extends AbstractUltraLightClass runTest("compiler/testData/asJava/ultraLightClasses/jvmOverloads.kt"); } + @TestMetadata("jvmRecord.kt") + public void testJvmRecord() throws Exception { + runTest("compiler/testData/asJava/ultraLightClasses/jvmRecord.kt"); + } + @TestMetadata("jvmSynthetic.kt") public void testJvmSynthetic() throws Exception { runTest("compiler/testData/asJava/ultraLightClasses/jvmSynthetic.kt");