[FIR] Properly support @JvmRecord
^KT-53867 Fixed
This commit is contained in:
+1
-1
@@ -61,7 +61,7 @@ internal class LLFirDesignatedSupertypeResolverTransformer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private inner class DesignatedFirApplySupertypesTransformer(classDesignation: FirDeclarationDesignation) :
|
private inner class DesignatedFirApplySupertypesTransformer(classDesignation: FirDeclarationDesignation) :
|
||||||
FirApplySupertypesTransformer(supertypeComputationSession) {
|
FirApplySupertypesTransformer(supertypeComputationSession, session, scopeSession) {
|
||||||
|
|
||||||
val declarationTransformer = LLFirDeclarationTransformer(classDesignation)
|
val declarationTransformer = LLFirDeclarationTransformer(classDesignation)
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -25,13 +25,13 @@ import org.jetbrains.kotlin.fir.types.coneType
|
|||||||
import org.jetbrains.kotlin.fir.types.coneTypeSafe
|
import org.jetbrains.kotlin.fir.types.coneTypeSafe
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.name.JvmNames.JVM_RECORD_ANNOTATION_CLASS_ID
|
import org.jetbrains.kotlin.name.JvmNames.JVM_RECORD_ANNOTATION_CLASS_ID
|
||||||
|
import org.jetbrains.kotlin.name.StandardClassIds
|
||||||
|
|
||||||
object FirJvmRecordChecker : FirRegularClassChecker() {
|
object FirJvmRecordChecker : FirRegularClassChecker() {
|
||||||
private val JAVA_RECORD_CLASS_ID = ClassId.fromString("java/lang/Record")
|
|
||||||
|
|
||||||
override fun check(declaration: FirRegularClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
override fun check(declaration: FirRegularClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
declaration.superTypeRefs.firstOrNull()?.let { typeRef ->
|
declaration.superTypeRefs.firstOrNull()?.let { typeRef ->
|
||||||
if (typeRef.coneTypeSafe<ConeClassLikeType>()?.classId == JAVA_RECORD_CLASS_ID) {
|
// compiler automatically adds java.lang.Record supertype, so we should check only for explicit type declarations
|
||||||
|
if (typeRef.source != null && typeRef.coneTypeSafe<ConeClassLikeType>()?.classId == StandardClassIds.Java.Record) {
|
||||||
reporter.reportOn(typeRef.source, FirJvmErrors.ILLEGAL_JAVA_LANG_RECORD_SUPERTYPE, context)
|
reporter.reportOn(typeRef.source, FirJvmErrors.ILLEGAL_JAVA_LANG_RECORD_SUPERTYPE, context)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.fir.declarations.SealedClassInheritorsProviderImpl
|
|||||||
import org.jetbrains.kotlin.fir.extensions.*
|
import org.jetbrains.kotlin.fir.extensions.*
|
||||||
import org.jetbrains.kotlin.fir.java.FirJavaVisibilityChecker
|
import org.jetbrains.kotlin.fir.java.FirJavaVisibilityChecker
|
||||||
import org.jetbrains.kotlin.fir.java.FirJvmDefaultModeComponent
|
import org.jetbrains.kotlin.fir.java.FirJvmDefaultModeComponent
|
||||||
|
import org.jetbrains.kotlin.fir.java.JvmSupertypeUpdater
|
||||||
import org.jetbrains.kotlin.fir.java.enhancement.FirAnnotationTypeQualifierResolver
|
import org.jetbrains.kotlin.fir.java.enhancement.FirAnnotationTypeQualifierResolver
|
||||||
import org.jetbrains.kotlin.fir.java.enhancement.FirEnhancedSymbolsStorage
|
import org.jetbrains.kotlin.fir.java.enhancement.FirEnhancedSymbolsStorage
|
||||||
import org.jetbrains.kotlin.fir.resolve.*
|
import org.jetbrains.kotlin.fir.resolve.*
|
||||||
@@ -30,6 +31,7 @@ import org.jetbrains.kotlin.fir.resolve.inference.InferenceComponents
|
|||||||
import org.jetbrains.kotlin.fir.resolve.providers.impl.FirQualifierResolverImpl
|
import org.jetbrains.kotlin.fir.resolve.providers.impl.FirQualifierResolverImpl
|
||||||
import org.jetbrains.kotlin.fir.resolve.providers.impl.FirTypeResolverImpl
|
import org.jetbrains.kotlin.fir.resolve.providers.impl.FirTypeResolverImpl
|
||||||
import org.jetbrains.kotlin.fir.resolve.transformers.FirCompilerLazyDeclarationResolver
|
import org.jetbrains.kotlin.fir.resolve.transformers.FirCompilerLazyDeclarationResolver
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.transformers.PlatformSupertypeUpdater
|
||||||
import org.jetbrains.kotlin.fir.resolve.transformers.plugin.GeneratedClassIndex
|
import org.jetbrains.kotlin.fir.resolve.transformers.plugin.GeneratedClassIndex
|
||||||
import org.jetbrains.kotlin.fir.scopes.FirOverrideService
|
import org.jetbrains.kotlin.fir.scopes.FirOverrideService
|
||||||
import org.jetbrains.kotlin.fir.scopes.FirPlatformClassMapper
|
import org.jetbrains.kotlin.fir.scopes.FirPlatformClassMapper
|
||||||
@@ -85,6 +87,7 @@ fun FirSession.registerCommonJavaComponents(javaModuleResolver: JavaModuleResolv
|
|||||||
FirJvmDefaultModeComponent::class,
|
FirJvmDefaultModeComponent::class,
|
||||||
FirJvmDefaultModeComponent(languageVersionSettings.getFlag(JvmAnalysisFlags.jvmDefaultMode))
|
FirJvmDefaultModeComponent(languageVersionSettings.getFlag(JvmAnalysisFlags.jvmDefaultMode))
|
||||||
)
|
)
|
||||||
|
register(PlatformSupertypeUpdater::class, JvmSupertypeUpdater(this))
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------- Resolve components --------------------------
|
// -------------------------- Resolve components --------------------------
|
||||||
|
|||||||
Generated
+6
@@ -951,6 +951,12 @@ public class Fir2IrTextTestGenerated extends AbstractFir2IrTextTest {
|
|||||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/ir/irText/declarations/jvmRecord"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/ir/irText/declarations/jvmRecord"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("dataClassWithJvmRecord.kt")
|
||||||
|
public void testDataClassWithJvmRecord() throws Exception {
|
||||||
|
runTest("compiler/testData/ir/irText/declarations/jvmRecord/dataClassWithJvmRecord.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("javaRecordComponentAccess.kt")
|
@TestMetadata("javaRecordComponentAccess.kt")
|
||||||
public void testJavaRecordComponentAccess() throws Exception {
|
public void testJavaRecordComponentAccess() throws Exception {
|
||||||
|
|||||||
+6
@@ -951,6 +951,12 @@ public class LightTreeFir2IrTextTestGenerated extends AbstractLightTreeFir2IrTex
|
|||||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/ir/irText/declarations/jvmRecord"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/ir/irText/declarations/jvmRecord"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("dataClassWithJvmRecord.kt")
|
||||||
|
public void testDataClassWithJvmRecord() throws Exception {
|
||||||
|
runTest("compiler/testData/ir/irText/declarations/jvmRecord/dataClassWithJvmRecord.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("javaRecordComponentAccess.kt")
|
@TestMetadata("javaRecordComponentAccess.kt")
|
||||||
public void testJavaRecordComponentAccess() throws Exception {
|
public void testJavaRecordComponentAccess() throws Exception {
|
||||||
|
|||||||
@@ -0,0 +1,104 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2022 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.fir.java
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
|
import org.jetbrains.kotlin.fir.FirElement
|
||||||
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirConstructor
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.hasAnnotationSafe
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.utils.isData
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirDelegatedConstructorCall
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirStatement
|
||||||
|
import org.jetbrains.kotlin.fir.java.JvmSupertypeUpdater.DelegatedConstructorCallTransformer.Companion.recordType
|
||||||
|
import org.jetbrains.kotlin.fir.references.builder.buildResolvedNamedReference
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.toFirRegularClassSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.transformers.PlatformSupertypeUpdater
|
||||||
|
import org.jetbrains.kotlin.fir.resolvedTypeFromPrototype
|
||||||
|
import org.jetbrains.kotlin.fir.scopes.getDeclaredConstructors
|
||||||
|
import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
|
||||||
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
|
import org.jetbrains.kotlin.fir.types.impl.FirImplicitBuiltinTypeRef
|
||||||
|
import org.jetbrains.kotlin.fir.visitors.FirTransformer
|
||||||
|
import org.jetbrains.kotlin.fir.visitors.transformSingle
|
||||||
|
import org.jetbrains.kotlin.name.StandardClassIds
|
||||||
|
|
||||||
|
class JvmSupertypeUpdater(private val session: FirSession) : PlatformSupertypeUpdater() {
|
||||||
|
private val jvmRecordUpdater = DelegatedConstructorCallTransformer(session)
|
||||||
|
|
||||||
|
override fun updateSupertypesIfNeeded(firClass: FirClass, scopeSession: ScopeSession) {
|
||||||
|
if (!(firClass is FirRegularClass && firClass.isData && firClass.hasAnnotationSafe(StandardClassIds.Annotations.JvmRecord))) return
|
||||||
|
var anyFound = false
|
||||||
|
var hasExplicitSuperClass = false
|
||||||
|
val newSuperTypeRefs = firClass.superTypeRefs.mapTo(mutableListOf()) {
|
||||||
|
when {
|
||||||
|
it is FirImplicitBuiltinTypeRef && it.id == StandardClassIds.Any -> {
|
||||||
|
anyFound = true
|
||||||
|
it.withReplacedConeType(recordType)
|
||||||
|
}
|
||||||
|
it.coneType.toRegularClassSymbol(session)?.classKind == ClassKind.CLASS -> {
|
||||||
|
hasExplicitSuperClass = true
|
||||||
|
it
|
||||||
|
}
|
||||||
|
else -> it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!anyFound && !hasExplicitSuperClass) {
|
||||||
|
newSuperTypeRefs += recordType.toFirResolvedTypeRef()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (anyFound || !hasExplicitSuperClass) {
|
||||||
|
firClass.replaceSuperTypeRefs(newSuperTypeRefs)
|
||||||
|
firClass.transformSingle(jvmRecordUpdater, scopeSession)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class DelegatedConstructorCallTransformer(private val session: FirSession) : FirTransformer<ScopeSession>() {
|
||||||
|
companion object {
|
||||||
|
val recordType = StandardClassIds.Java.Record.constructClassLikeType(emptyArray(), isNullable = false)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun <E : FirElement> transformElement(element: E, data: ScopeSession): E {
|
||||||
|
return element
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun transformRegularClass(regularClass: FirRegularClass, data: ScopeSession): FirStatement {
|
||||||
|
return regularClass.transformDeclarations(this, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun transformConstructor(constructor: FirConstructor, data: ScopeSession): FirStatement {
|
||||||
|
return constructor.transformDelegatedConstructor(this, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun transformDelegatedConstructorCall(
|
||||||
|
delegatedConstructorCall: FirDelegatedConstructorCall,
|
||||||
|
data: ScopeSession
|
||||||
|
): FirStatement {
|
||||||
|
val constructedTypeRef = delegatedConstructorCall.constructedTypeRef
|
||||||
|
if (constructedTypeRef is FirImplicitTypeRef || constructedTypeRef.coneTypeSafe<ConeKotlinType>()?.isAny == true) {
|
||||||
|
delegatedConstructorCall.replaceConstructedTypeRef(constructedTypeRef.resolvedTypeFromPrototype(recordType))
|
||||||
|
}
|
||||||
|
|
||||||
|
val recordConstructorSymbol = recordType.lookupTag.toFirRegularClassSymbol(session)
|
||||||
|
?.unsubstitutedScope(session, data, withForcedTypeCalculator = false)
|
||||||
|
?.getDeclaredConstructors()
|
||||||
|
?.firstOrNull { it.fir.valueParameters.isEmpty() }
|
||||||
|
|
||||||
|
if (recordConstructorSymbol != null) {
|
||||||
|
val newReference = buildResolvedNamedReference {
|
||||||
|
name = StandardClassIds.Java.Record.shortClassName
|
||||||
|
resolvedSymbol = recordConstructorSymbol
|
||||||
|
}
|
||||||
|
delegatedConstructorCall.replaceCalleeReference(newReference)
|
||||||
|
}
|
||||||
|
return delegatedConstructorCall
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+14
@@ -26,9 +26,15 @@ private fun FirAnnotation.toAnnotationLookupTag(): ConeClassLikeLookupTag? =
|
|||||||
// this cast fails when we have generic-typed annotations @T
|
// this cast fails when we have generic-typed annotations @T
|
||||||
(annotationTypeRef.coneType as? ConeClassLikeType)?.lookupTag
|
(annotationTypeRef.coneType as? ConeClassLikeType)?.lookupTag
|
||||||
|
|
||||||
|
private fun FirAnnotation.toAnnotationLookupTagSafe(): ConeClassLikeLookupTag? =
|
||||||
|
annotationTypeRef.coneTypeSafe<ConeClassLikeType>()?.lookupTag
|
||||||
|
|
||||||
fun FirAnnotation.toAnnotationClassId(): ClassId? =
|
fun FirAnnotation.toAnnotationClassId(): ClassId? =
|
||||||
toAnnotationLookupTag()?.classId
|
toAnnotationLookupTag()?.classId
|
||||||
|
|
||||||
|
fun FirAnnotation.toAnnotationClassIdSafe(): ClassId? =
|
||||||
|
toAnnotationLookupTagSafe()?.classId
|
||||||
|
|
||||||
private fun FirAnnotation.toAnnotationClass(session: FirSession): FirRegularClass? =
|
private fun FirAnnotation.toAnnotationClass(session: FirSession): FirRegularClass? =
|
||||||
toAnnotationLookupTag()?.toSymbol(session)?.fir as? FirRegularClass
|
toAnnotationLookupTag()?.toSymbol(session)?.fir as? FirRegularClass
|
||||||
|
|
||||||
@@ -99,6 +105,10 @@ fun FirDeclaration.hasAnnotation(classId: ClassId): Boolean {
|
|||||||
return annotations.hasAnnotation(classId)
|
return annotations.hasAnnotation(classId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun FirDeclaration.hasAnnotationSafe(classId: ClassId): Boolean {
|
||||||
|
return annotations.hasAnnotationSafe(classId)
|
||||||
|
}
|
||||||
|
|
||||||
fun FirBasedSymbol<*>.hasAnnotation(classId: ClassId): Boolean {
|
fun FirBasedSymbol<*>.hasAnnotation(classId: ClassId): Boolean {
|
||||||
return resolvedAnnotationsWithClassIds.hasAnnotation(classId)
|
return resolvedAnnotationsWithClassIds.hasAnnotation(classId)
|
||||||
}
|
}
|
||||||
@@ -107,6 +117,10 @@ fun List<FirAnnotation>.hasAnnotation(classId: ClassId): Boolean {
|
|||||||
return this.any { it.toAnnotationClassId() == classId }
|
return this.any { it.toAnnotationClassId() == classId }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun List<FirAnnotation>.hasAnnotationSafe(classId: ClassId): Boolean {
|
||||||
|
return this.any { it.toAnnotationClassIdSafe() == classId }
|
||||||
|
}
|
||||||
|
|
||||||
fun <D> FirBasedSymbol<out D>.getAnnotationByClassId(classId: ClassId): FirAnnotation? where D : FirAnnotationContainer, D : FirDeclaration {
|
fun <D> FirBasedSymbol<out D>.getAnnotationByClassId(classId: ClassId): FirAnnotation? where D : FirAnnotationContainer, D : FirDeclaration {
|
||||||
return fir.getAnnotationByClassId(classId)
|
return fir.getAnnotationByClassId(classId)
|
||||||
}
|
}
|
||||||
|
|||||||
+16
-6
@@ -8,26 +8,28 @@ package org.jetbrains.kotlin.fir.resolve.transformers
|
|||||||
import kotlinx.collections.immutable.PersistentList
|
import kotlinx.collections.immutable.PersistentList
|
||||||
import kotlinx.collections.immutable.persistentListOf
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
import kotlinx.collections.immutable.toPersistentList
|
import kotlinx.collections.immutable.toPersistentList
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
import org.jetbrains.kotlin.fir.*
|
import org.jetbrains.kotlin.fir.*
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.expandedConeType
|
import org.jetbrains.kotlin.fir.declarations.utils.expandedConeType
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.isCompanion
|
import org.jetbrains.kotlin.fir.declarations.utils.isCompanion
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.utils.isData
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.superConeTypes
|
import org.jetbrains.kotlin.fir.declarations.utils.superConeTypes
|
||||||
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
|
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
|
||||||
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
|
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirDelegatedConstructorCall
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirStatement
|
import org.jetbrains.kotlin.fir.expressions.FirStatement
|
||||||
import org.jetbrains.kotlin.fir.extensions.FirSupertypeGenerationExtension
|
import org.jetbrains.kotlin.fir.extensions.FirSupertypeGenerationExtension
|
||||||
import org.jetbrains.kotlin.fir.extensions.extensionService
|
import org.jetbrains.kotlin.fir.extensions.extensionService
|
||||||
import org.jetbrains.kotlin.fir.extensions.supertypeGenerators
|
import org.jetbrains.kotlin.fir.extensions.supertypeGenerators
|
||||||
|
import org.jetbrains.kotlin.fir.references.builder.buildResolvedNamedReference
|
||||||
import org.jetbrains.kotlin.fir.resolve.*
|
import org.jetbrains.kotlin.fir.resolve.*
|
||||||
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.isLocalClassOrAnonymousObject
|
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.isLocalClassOrAnonymousObject
|
||||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeTypeParameterSupertype
|
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeTypeParameterSupertype
|
||||||
import org.jetbrains.kotlin.fir.resolve.providers.firProvider
|
import org.jetbrains.kotlin.fir.resolve.providers.firProvider
|
||||||
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
|
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
|
||||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.LocalClassesNavigationInfo
|
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.LocalClassesNavigationInfo
|
||||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
import org.jetbrains.kotlin.fir.scopes.*
|
||||||
import org.jetbrains.kotlin.fir.scopes.createImportingScopes
|
|
||||||
import org.jetbrains.kotlin.fir.scopes.getNestedClassifierScope
|
|
||||||
import org.jetbrains.kotlin.fir.scopes.impl.FirMemberTypeParameterScope
|
import org.jetbrains.kotlin.fir.scopes.impl.FirMemberTypeParameterScope
|
||||||
import org.jetbrains.kotlin.fir.scopes.impl.nestedClassifierScope
|
import org.jetbrains.kotlin.fir.scopes.impl.nestedClassifierScope
|
||||||
import org.jetbrains.kotlin.fir.scopes.impl.wrapNestedClassifierScopeWithSubstitutionForSuperType
|
import org.jetbrains.kotlin.fir.scopes.impl.wrapNestedClassifierScopeWithSubstitutionForSuperType
|
||||||
@@ -40,7 +42,9 @@ import org.jetbrains.kotlin.fir.types.impl.FirImplicitBuiltinTypeRef
|
|||||||
import org.jetbrains.kotlin.fir.visitors.FirDefaultTransformer
|
import org.jetbrains.kotlin.fir.visitors.FirDefaultTransformer
|
||||||
import org.jetbrains.kotlin.fir.visitors.FirDefaultVisitor
|
import org.jetbrains.kotlin.fir.visitors.FirDefaultVisitor
|
||||||
import org.jetbrains.kotlin.fir.visitors.FirTransformer
|
import org.jetbrains.kotlin.fir.visitors.FirTransformer
|
||||||
|
import org.jetbrains.kotlin.fir.visitors.transformSingle
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
|
import org.jetbrains.kotlin.name.StandardClassIds
|
||||||
import org.jetbrains.kotlin.types.model.TypeArgumentMarker
|
import org.jetbrains.kotlin.types.model.TypeArgumentMarker
|
||||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
@@ -65,7 +69,7 @@ open class FirSupertypeResolverTransformer(
|
|||||||
protected val supertypeComputationSession = SupertypeComputationSession()
|
protected val supertypeComputationSession = SupertypeComputationSession()
|
||||||
|
|
||||||
private val supertypeResolverVisitor = FirSupertypeResolverVisitor(session, supertypeComputationSession, scopeSession)
|
private val supertypeResolverVisitor = FirSupertypeResolverVisitor(session, supertypeComputationSession, scopeSession)
|
||||||
private val applySupertypesTransformer = FirApplySupertypesTransformer(supertypeComputationSession)
|
private val applySupertypesTransformer = FirApplySupertypesTransformer(supertypeComputationSession, session, scopeSession)
|
||||||
|
|
||||||
override fun <E : FirElement> transformElement(element: E, data: Any?): E {
|
override fun <E : FirElement> transformElement(element: E, data: Any?): E {
|
||||||
return element
|
return element
|
||||||
@@ -101,13 +105,16 @@ fun <F : FirClassLikeDeclaration> F.runSupertypeResolvePhaseForLocalClass(
|
|||||||
this.accept(supertypeResolverVisitor, null)
|
this.accept(supertypeResolverVisitor, null)
|
||||||
supertypeComputationSession.breakLoops(session)
|
supertypeComputationSession.breakLoops(session)
|
||||||
|
|
||||||
val applySupertypesTransformer = FirApplySupertypesTransformer(supertypeComputationSession)
|
val applySupertypesTransformer = FirApplySupertypesTransformer(supertypeComputationSession, session, scopeSession)
|
||||||
return this.transform<F, Nothing?>(applySupertypesTransformer, null)
|
return this.transform<F, Nothing?>(applySupertypesTransformer, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
open class FirApplySupertypesTransformer(
|
open class FirApplySupertypesTransformer(
|
||||||
private val supertypeComputationSession: SupertypeComputationSession
|
private val supertypeComputationSession: SupertypeComputationSession,
|
||||||
|
private val session: FirSession,
|
||||||
|
private val scopeSession: ScopeSession
|
||||||
) : FirDefaultTransformer<Any?>() {
|
) : FirDefaultTransformer<Any?>() {
|
||||||
|
|
||||||
override fun <E : FirElement> transformElement(element: E, data: Any?): E {
|
override fun <E : FirElement> transformElement(element: E, data: Any?): E {
|
||||||
return element
|
return element
|
||||||
}
|
}
|
||||||
@@ -133,8 +140,11 @@ open class FirApplySupertypesTransformer(
|
|||||||
// TODO: Replace with an immutable version or transformer
|
// TODO: Replace with an immutable version or transformer
|
||||||
firClass.replaceSuperTypeRefs(supertypeRefs)
|
firClass.replaceSuperTypeRefs(supertypeRefs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
session.platformSupertypeUpdater?.updateSupertypesIfNeeded(firClass, scopeSession)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
override fun transformAnonymousObject(anonymousObject: FirAnonymousObject, data: Any?): FirStatement {
|
override fun transformAnonymousObject(anonymousObject: FirAnonymousObject, data: Any?): FirStatement {
|
||||||
applyResolvedSupertypesToClass(anonymousObject)
|
applyResolvedSupertypesToClass(anonymousObject)
|
||||||
|
|
||||||
|
|||||||
+17
@@ -0,0 +1,17 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2022 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.fir.resolve.transformers
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
|
import org.jetbrains.kotlin.fir.FirSessionComponent
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||||
|
|
||||||
|
abstract class PlatformSupertypeUpdater : FirSessionComponent {
|
||||||
|
abstract fun updateSupertypesIfNeeded(firClass: FirClass, scopeSession: ScopeSession)
|
||||||
|
}
|
||||||
|
|
||||||
|
val FirSession.platformSupertypeUpdater: PlatformSupertypeUpdater? by FirSession.nullableSessionComponentAccessor()
|
||||||
+3
-1
@@ -32,8 +32,10 @@ import org.jetbrains.kotlin.fir.visitors.transformSingle
|
|||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.name.StandardClassIds
|
||||||
import org.jetbrains.kotlin.name.StandardClassIds.Annotations.Deprecated
|
import org.jetbrains.kotlin.name.StandardClassIds.Annotations.Deprecated
|
||||||
import org.jetbrains.kotlin.name.StandardClassIds.Annotations.DeprecatedSinceKotlin
|
import org.jetbrains.kotlin.name.StandardClassIds.Annotations.DeprecatedSinceKotlin
|
||||||
|
import org.jetbrains.kotlin.name.StandardClassIds.Annotations.JvmRecord
|
||||||
import org.jetbrains.kotlin.name.StandardClassIds.Annotations.WasExperimental
|
import org.jetbrains.kotlin.name.StandardClassIds.Annotations.WasExperimental
|
||||||
|
|
||||||
class FirCompilerRequiredAnnotationsResolveProcessor(
|
class FirCompilerRequiredAnnotationsResolveProcessor(
|
||||||
@@ -154,7 +156,7 @@ private class FirAnnotationResolveTransformer(
|
|||||||
) {
|
) {
|
||||||
companion object {
|
companion object {
|
||||||
private val REQUIRED_ANNOTATIONS: Set<ClassId> = setOf(
|
private val REQUIRED_ANNOTATIONS: Set<ClassId> = setOf(
|
||||||
Deprecated, DeprecatedSinceKotlin, WasExperimental
|
Deprecated, DeprecatedSinceKotlin, WasExperimental, JvmRecord
|
||||||
)
|
)
|
||||||
|
|
||||||
private val REQUIRED_ANNOTATION_NAMES: Set<Name> = REQUIRED_ANNOTATIONS.mapTo(mutableSetOf()) { it.shortClassName }
|
private val REQUIRED_ANNOTATION_NAMES: Set<Name> = REQUIRED_ANNOTATIONS.mapTo(mutableSetOf()) { it.shortClassName }
|
||||||
|
|||||||
+3
-1
@@ -2,9 +2,11 @@
|
|||||||
// API_VERSION: 1.5
|
// API_VERSION: 1.5
|
||||||
// JVM_TARGET: 17
|
// JVM_TARGET: 17
|
||||||
// COMPILER_ARGUMENTS: -XXLanguage:+JvmRecordSupport -Xjvm-enable-preview
|
// COMPILER_ARGUMENTS: -XXLanguage:+JvmRecordSupport -Xjvm-enable-preview
|
||||||
|
// IGNORE_FIR
|
||||||
|
// reason: test framework does not support using JDK 17 as dependency
|
||||||
package pkg
|
package pkg
|
||||||
|
|
||||||
@JvmRecord
|
@JvmRecord
|
||||||
data class MyRec(val name: String)
|
data class MyRec(val name: String)
|
||||||
// JDK 15 should be used to compile this file
|
// JDK 15 should be used to compile this file
|
||||||
// COMPILATION_ERRORS
|
// COMPILATION_ERRORS
|
||||||
|
|||||||
-1
@@ -1,6 +1,5 @@
|
|||||||
// !API_VERSION: 1.5
|
// !API_VERSION: 1.5
|
||||||
// !LANGUAGE: +JvmRecordSupport
|
// !LANGUAGE: +JvmRecordSupport
|
||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
// ENABLE_JVM_PREVIEW
|
// ENABLE_JVM_PREVIEW
|
||||||
// FILE: JavaClass.java
|
// FILE: JavaClass.java
|
||||||
public class JavaClass {
|
public class JavaClass {
|
||||||
|
|||||||
-1
@@ -1,6 +1,5 @@
|
|||||||
// !API_VERSION: 1.5
|
// !API_VERSION: 1.5
|
||||||
// !LANGUAGE: +JvmRecordSupport
|
// !LANGUAGE: +JvmRecordSupport
|
||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
// ENABLE_JVM_PREVIEW
|
// ENABLE_JVM_PREVIEW
|
||||||
|
|
||||||
// FILE: JavaClass.java
|
// FILE: JavaClass.java
|
||||||
|
|||||||
+1
-4
@@ -1,8 +1,5 @@
|
|||||||
// !API_VERSION: 1.5
|
|
||||||
// !LANGUAGE: +JvmRecordSupport
|
|
||||||
// ENABLE_JVM_PREVIEW
|
// ENABLE_JVM_PREVIEW
|
||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
// JVM_DEFAULT_MODE: all-compatibility
|
||||||
// !JVM_DEFAULT_MODE: all-compatibility
|
|
||||||
|
|
||||||
// FILE: JavaClass.java
|
// FILE: JavaClass.java
|
||||||
public class JavaClass {
|
public class JavaClass {
|
||||||
|
|||||||
-1
@@ -1,7 +1,6 @@
|
|||||||
// !API_VERSION: 1.5
|
// !API_VERSION: 1.5
|
||||||
// !LANGUAGE: +JvmRecordSupport
|
// !LANGUAGE: +JvmRecordSupport
|
||||||
// ENABLE_JVM_PREVIEW
|
// ENABLE_JVM_PREVIEW
|
||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
// !JVM_DEFAULT_MODE: enable
|
// !JVM_DEFAULT_MODE: enable
|
||||||
|
|
||||||
// FILE: JavaClass.java
|
// FILE: JavaClass.java
|
||||||
|
|||||||
+98
@@ -0,0 +1,98 @@
|
|||||||
|
FILE fqName:<root> fileName:/dataClassWithJvmRecord.kt
|
||||||
|
CLASS CLASS name:MyRec modality:FINAL visibility:public [data] superTypes:[java.lang.Record]
|
||||||
|
annotations:
|
||||||
|
JvmRecord
|
||||||
|
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.MyRec
|
||||||
|
CONSTRUCTOR visibility:public <> (name:kotlin.String) returnType:<root>.MyRec [primary]
|
||||||
|
VALUE_PARAMETER name:name index:0 type:kotlin.String
|
||||||
|
BLOCK_BODY
|
||||||
|
DELEGATING_CONSTRUCTOR_CALL 'protected/*protected and package*/ constructor <init> () declared in java.lang.Record'
|
||||||
|
INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:MyRec modality:FINAL visibility:public [data] superTypes:[java.lang.Record]'
|
||||||
|
PROPERTY name:name visibility:public modality:FINAL [val]
|
||||||
|
FIELD PROPERTY_BACKING_FIELD name:name type:kotlin.String visibility:private [final]
|
||||||
|
EXPRESSION_BODY
|
||||||
|
GET_VAR 'name: kotlin.String declared in <root>.MyRec.<init>' type=kotlin.String origin=INITIALIZE_PROPERTY_FROM_PARAMETER
|
||||||
|
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-name> visibility:public modality:FINAL <> ($this:<root>.MyRec) returnType:kotlin.String
|
||||||
|
correspondingProperty: PROPERTY name:name visibility:public modality:FINAL [val]
|
||||||
|
$this: VALUE_PARAMETER name:<this> type:<root>.MyRec
|
||||||
|
BLOCK_BODY
|
||||||
|
RETURN type=kotlin.Nothing from='public final fun <get-name> (): kotlin.String declared in <root>.MyRec'
|
||||||
|
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:name type:kotlin.String visibility:private [final]' type=kotlin.String origin=null
|
||||||
|
receiver: GET_VAR '<this>: <root>.MyRec declared in <root>.MyRec.<get-name>' type=<root>.MyRec origin=null
|
||||||
|
FUN name:component1 visibility:public modality:FINAL <> ($this:<root>.MyRec) returnType:kotlin.String [operator]
|
||||||
|
$this: VALUE_PARAMETER name:<this> type:<root>.MyRec
|
||||||
|
BLOCK_BODY
|
||||||
|
RETURN type=kotlin.Nothing from='public final fun component1 (): kotlin.String [operator] declared in <root>.MyRec'
|
||||||
|
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:name type:kotlin.String visibility:private [final]' type=kotlin.String origin=null
|
||||||
|
receiver: GET_VAR '<this>: <root>.MyRec declared in <root>.MyRec.component1' type=<root>.MyRec origin=null
|
||||||
|
FUN name:copy visibility:public modality:FINAL <> ($this:<root>.MyRec, name:kotlin.String) returnType:<root>.MyRec
|
||||||
|
$this: VALUE_PARAMETER name:<this> type:<root>.MyRec
|
||||||
|
VALUE_PARAMETER name:name index:0 type:kotlin.String
|
||||||
|
EXPRESSION_BODY
|
||||||
|
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:name type:kotlin.String visibility:private [final]' type=kotlin.String origin=null
|
||||||
|
receiver: GET_VAR '<this>: <root>.MyRec declared in <root>.MyRec.copy' type=<root>.MyRec origin=null
|
||||||
|
BLOCK_BODY
|
||||||
|
RETURN type=kotlin.Nothing from='public final fun copy (name: kotlin.String): <root>.MyRec declared in <root>.MyRec'
|
||||||
|
CONSTRUCTOR_CALL 'public constructor <init> (name: kotlin.String) [primary] declared in <root>.MyRec' type=<root>.MyRec origin=null
|
||||||
|
name: GET_VAR 'name: kotlin.String declared in <root>.MyRec.copy' type=kotlin.String origin=null
|
||||||
|
FUN GENERATED_DATA_CLASS_MEMBER name:equals visibility:public modality:OPEN <> ($this:<root>.MyRec, other:kotlin.Any?) returnType:kotlin.Boolean
|
||||||
|
overridden:
|
||||||
|
public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any
|
||||||
|
$this: VALUE_PARAMETER GENERATED_DATA_CLASS_MEMBER name:<this> type:<root>.MyRec
|
||||||
|
VALUE_PARAMETER GENERATED_DATA_CLASS_MEMBER name:other index:0 type:kotlin.Any?
|
||||||
|
BLOCK_BODY
|
||||||
|
WHEN type=kotlin.Unit origin=null
|
||||||
|
BRANCH
|
||||||
|
if: CALL 'public final fun EQEQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQEQ
|
||||||
|
arg0: GET_VAR '<this>: <root>.MyRec declared in <root>.MyRec.equals' type=<root>.MyRec origin=null
|
||||||
|
arg1: GET_VAR 'other: kotlin.Any? declared in <root>.MyRec.equals' type=kotlin.Any? origin=null
|
||||||
|
then: RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in <root>.MyRec'
|
||||||
|
CONST Boolean type=kotlin.Boolean value=true
|
||||||
|
WHEN type=kotlin.Unit origin=null
|
||||||
|
BRANCH
|
||||||
|
if: TYPE_OP type=kotlin.Boolean origin=NOT_INSTANCEOF typeOperand=<root>.MyRec
|
||||||
|
GET_VAR 'other: kotlin.Any? declared in <root>.MyRec.equals' type=kotlin.Any? origin=null
|
||||||
|
then: RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in <root>.MyRec'
|
||||||
|
CONST Boolean type=kotlin.Boolean value=false
|
||||||
|
VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:<root>.MyRec [val]
|
||||||
|
TYPE_OP type=<root>.MyRec origin=CAST typeOperand=<root>.MyRec
|
||||||
|
GET_VAR 'other: kotlin.Any? declared in <root>.MyRec.equals' type=kotlin.Any? origin=null
|
||||||
|
WHEN type=kotlin.Unit origin=null
|
||||||
|
BRANCH
|
||||||
|
if: CALL 'public final fun not (): kotlin.Boolean [operator] declared in kotlin.Boolean' type=kotlin.Boolean origin=EXCLEQ
|
||||||
|
$this: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EXCLEQ
|
||||||
|
arg0: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:name type:kotlin.String visibility:private [final]' type=kotlin.String origin=null
|
||||||
|
receiver: GET_VAR '<this>: <root>.MyRec declared in <root>.MyRec.equals' type=<root>.MyRec origin=null
|
||||||
|
arg1: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:name type:kotlin.String visibility:private [final]' type=kotlin.String origin=null
|
||||||
|
receiver: GET_VAR 'val tmp_0: <root>.MyRec [val] declared in <root>.MyRec.equals' type=<root>.MyRec origin=null
|
||||||
|
then: RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in <root>.MyRec'
|
||||||
|
CONST Boolean type=kotlin.Boolean value=false
|
||||||
|
RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in <root>.MyRec'
|
||||||
|
CONST Boolean type=kotlin.Boolean value=true
|
||||||
|
FUN GENERATED_DATA_CLASS_MEMBER name:hashCode visibility:public modality:OPEN <> ($this:<root>.MyRec) returnType:kotlin.Int
|
||||||
|
overridden:
|
||||||
|
public open fun hashCode (): kotlin.Int declared in kotlin.Any
|
||||||
|
$this: VALUE_PARAMETER GENERATED_DATA_CLASS_MEMBER name:<this> type:<root>.MyRec
|
||||||
|
BLOCK_BODY
|
||||||
|
RETURN type=kotlin.Nothing from='public open fun hashCode (): kotlin.Int declared in <root>.MyRec'
|
||||||
|
CALL 'public open fun hashCode (): kotlin.Int [fake_override] declared in kotlin.String' type=kotlin.Int origin=null
|
||||||
|
$this: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:name type:kotlin.String visibility:private [final]' type=kotlin.String origin=null
|
||||||
|
receiver: GET_VAR '<this>: <root>.MyRec declared in <root>.MyRec.hashCode' type=<root>.MyRec origin=null
|
||||||
|
FUN GENERATED_DATA_CLASS_MEMBER name:toString visibility:public modality:OPEN <> ($this:<root>.MyRec) returnType:kotlin.String
|
||||||
|
overridden:
|
||||||
|
public open fun toString (): kotlin.String declared in kotlin.Any
|
||||||
|
$this: VALUE_PARAMETER GENERATED_DATA_CLASS_MEMBER name:<this> type:<root>.MyRec
|
||||||
|
BLOCK_BODY
|
||||||
|
RETURN type=kotlin.Nothing from='public open fun toString (): kotlin.String declared in <root>.MyRec'
|
||||||
|
STRING_CONCATENATION type=kotlin.String
|
||||||
|
CONST String type=kotlin.String value="MyRec("
|
||||||
|
CONST String type=kotlin.String value="name="
|
||||||
|
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:name type:kotlin.String visibility:private [final]' type=kotlin.String origin=null
|
||||||
|
receiver: GET_VAR '<this>: <root>.MyRec declared in <root>.MyRec.toString' type=<root>.MyRec origin=null
|
||||||
|
CONST String type=kotlin.String value=")"
|
||||||
|
FUN name:test visibility:public modality:FINAL <> (rec:<root>.MyRec) returnType:kotlin.Unit
|
||||||
|
VALUE_PARAMETER name:rec index:0 type:<root>.MyRec
|
||||||
|
BLOCK_BODY
|
||||||
|
TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit
|
||||||
|
CALL 'public final fun <get-name> (): kotlin.String declared in <root>.MyRec' type=kotlin.String origin=GET_PROPERTY
|
||||||
|
$this: GET_VAR 'rec: <root>.MyRec declared in <root>.test' type=<root>.MyRec origin=null
|
||||||
+47
@@ -0,0 +1,47 @@
|
|||||||
|
@JvmRecord
|
||||||
|
data class MyRec : Record {
|
||||||
|
constructor(name: String) /* primary */ {
|
||||||
|
super/*Record*/()
|
||||||
|
/* <init>() */
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
val name: String
|
||||||
|
field = name
|
||||||
|
get
|
||||||
|
|
||||||
|
operator fun component1(): String {
|
||||||
|
return <this>.#name
|
||||||
|
}
|
||||||
|
|
||||||
|
fun copy(name: String = <this>.#name): MyRec {
|
||||||
|
return MyRec(name = name)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
when {
|
||||||
|
EQEQEQ(arg0 = <this>, arg1 = other) -> return true
|
||||||
|
}
|
||||||
|
when {
|
||||||
|
other !is MyRec -> return false
|
||||||
|
}
|
||||||
|
val tmp0_other_with_cast: MyRec = other as MyRec
|
||||||
|
when {
|
||||||
|
EQEQ(arg0 = <this>.#name, arg1 = tmp0_other_with_cast.#name).not() -> return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
return <this>.#name.hashCode()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString(): String {
|
||||||
|
return "MyRec(" + "name=" + <this>.#name + ")"
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test(rec: MyRec) {
|
||||||
|
rec.<get-name>() /*~> Unit */
|
||||||
|
}
|
||||||
+98
@@ -0,0 +1,98 @@
|
|||||||
|
FILE fqName:<root> fileName:/dataClassWithJvmRecord.kt
|
||||||
|
CLASS CLASS name:MyRec modality:FINAL visibility:public [data] superTypes:[java.lang.Record]
|
||||||
|
annotations:
|
||||||
|
JvmRecord
|
||||||
|
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.MyRec
|
||||||
|
CONSTRUCTOR visibility:public <> (name:kotlin.String) returnType:<root>.MyRec [primary]
|
||||||
|
VALUE_PARAMETER name:name index:0 type:kotlin.String
|
||||||
|
BLOCK_BODY
|
||||||
|
DELEGATING_CONSTRUCTOR_CALL 'protected/*protected and package*/ constructor <init> () declared in java.lang.Record'
|
||||||
|
INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:MyRec modality:FINAL visibility:public [data] superTypes:[java.lang.Record]'
|
||||||
|
PROPERTY name:name visibility:public modality:FINAL [val]
|
||||||
|
FIELD PROPERTY_BACKING_FIELD name:name type:kotlin.String visibility:private [final]
|
||||||
|
EXPRESSION_BODY
|
||||||
|
GET_VAR 'name: kotlin.String declared in <root>.MyRec.<init>' type=kotlin.String origin=INITIALIZE_PROPERTY_FROM_PARAMETER
|
||||||
|
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-name> visibility:public modality:FINAL <> ($this:<root>.MyRec) returnType:kotlin.String
|
||||||
|
correspondingProperty: PROPERTY name:name visibility:public modality:FINAL [val]
|
||||||
|
$this: VALUE_PARAMETER name:<this> type:<root>.MyRec
|
||||||
|
BLOCK_BODY
|
||||||
|
RETURN type=kotlin.Nothing from='public final fun <get-name> (): kotlin.String declared in <root>.MyRec'
|
||||||
|
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:name type:kotlin.String visibility:private [final]' type=kotlin.String origin=null
|
||||||
|
receiver: GET_VAR '<this>: <root>.MyRec declared in <root>.MyRec.<get-name>' type=<root>.MyRec origin=null
|
||||||
|
FUN GENERATED_DATA_CLASS_MEMBER name:component1 visibility:public modality:FINAL <> ($this:<root>.MyRec) returnType:kotlin.String [operator]
|
||||||
|
$this: VALUE_PARAMETER name:<this> type:<root>.MyRec
|
||||||
|
BLOCK_BODY
|
||||||
|
RETURN type=kotlin.Nothing from='public final fun component1 (): kotlin.String [operator] declared in <root>.MyRec'
|
||||||
|
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:name type:kotlin.String visibility:private [final]' type=kotlin.String origin=null
|
||||||
|
receiver: GET_VAR '<this>: <root>.MyRec declared in <root>.MyRec.component1' type=<root>.MyRec origin=null
|
||||||
|
FUN GENERATED_DATA_CLASS_MEMBER name:copy visibility:public modality:FINAL <> ($this:<root>.MyRec, name:kotlin.String) returnType:<root>.MyRec
|
||||||
|
$this: VALUE_PARAMETER name:<this> type:<root>.MyRec
|
||||||
|
VALUE_PARAMETER name:name index:0 type:kotlin.String
|
||||||
|
EXPRESSION_BODY
|
||||||
|
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:name type:kotlin.String visibility:private [final]' type=kotlin.String origin=null
|
||||||
|
receiver: GET_VAR '<this>: <root>.MyRec declared in <root>.MyRec.copy' type=<root>.MyRec origin=null
|
||||||
|
BLOCK_BODY
|
||||||
|
RETURN type=kotlin.Nothing from='public final fun copy (name: kotlin.String): <root>.MyRec declared in <root>.MyRec'
|
||||||
|
CONSTRUCTOR_CALL 'public constructor <init> (name: kotlin.String) [primary] declared in <root>.MyRec' type=<root>.MyRec origin=null
|
||||||
|
name: GET_VAR 'name: kotlin.String declared in <root>.MyRec.copy' type=kotlin.String origin=null
|
||||||
|
FUN GENERATED_DATA_CLASS_MEMBER name:toString visibility:public modality:OPEN <> ($this:<root>.MyRec) returnType:kotlin.String
|
||||||
|
overridden:
|
||||||
|
public abstract fun toString (): @[EnhancedNullability] kotlin.String declared in java.lang.Record
|
||||||
|
$this: VALUE_PARAMETER name:<this> type:<root>.MyRec
|
||||||
|
BLOCK_BODY
|
||||||
|
RETURN type=kotlin.Nothing from='public open fun toString (): kotlin.String declared in <root>.MyRec'
|
||||||
|
STRING_CONCATENATION type=kotlin.String
|
||||||
|
CONST String type=kotlin.String value="MyRec("
|
||||||
|
CONST String type=kotlin.String value="name="
|
||||||
|
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:name type:kotlin.String visibility:private [final]' type=kotlin.String origin=null
|
||||||
|
receiver: GET_VAR '<this>: <root>.MyRec declared in <root>.MyRec.toString' type=<root>.MyRec origin=null
|
||||||
|
CONST String type=kotlin.String value=")"
|
||||||
|
FUN GENERATED_DATA_CLASS_MEMBER name:hashCode visibility:public modality:OPEN <> ($this:<root>.MyRec) returnType:kotlin.Int
|
||||||
|
overridden:
|
||||||
|
public abstract fun hashCode (): kotlin.Int declared in java.lang.Record
|
||||||
|
$this: VALUE_PARAMETER name:<this> type:<root>.MyRec
|
||||||
|
BLOCK_BODY
|
||||||
|
RETURN type=kotlin.Nothing from='public open fun hashCode (): kotlin.Int declared in <root>.MyRec'
|
||||||
|
CALL 'public open fun hashCode (): kotlin.Int [fake_override] declared in kotlin.String' type=kotlin.Int origin=null
|
||||||
|
$this: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:name type:kotlin.String visibility:private [final]' type=kotlin.String origin=null
|
||||||
|
receiver: GET_VAR '<this>: <root>.MyRec declared in <root>.MyRec.hashCode' type=<root>.MyRec origin=null
|
||||||
|
FUN GENERATED_DATA_CLASS_MEMBER name:equals visibility:public modality:OPEN <> ($this:<root>.MyRec, other:kotlin.Any?) returnType:kotlin.Boolean [operator]
|
||||||
|
overridden:
|
||||||
|
public abstract fun equals (other: @[EnhancedNullability] kotlin.Any?): kotlin.Boolean [operator] declared in java.lang.Record
|
||||||
|
$this: VALUE_PARAMETER name:<this> type:<root>.MyRec
|
||||||
|
VALUE_PARAMETER name:other index:0 type:kotlin.Any?
|
||||||
|
BLOCK_BODY
|
||||||
|
WHEN type=kotlin.Unit origin=null
|
||||||
|
BRANCH
|
||||||
|
if: CALL 'public final fun EQEQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQEQ
|
||||||
|
arg0: GET_VAR '<this>: <root>.MyRec declared in <root>.MyRec.equals' type=<root>.MyRec origin=null
|
||||||
|
arg1: GET_VAR 'other: kotlin.Any? declared in <root>.MyRec.equals' type=kotlin.Any? origin=null
|
||||||
|
then: RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in <root>.MyRec'
|
||||||
|
CONST Boolean type=kotlin.Boolean value=true
|
||||||
|
WHEN type=kotlin.Unit origin=null
|
||||||
|
BRANCH
|
||||||
|
if: TYPE_OP type=kotlin.Boolean origin=NOT_INSTANCEOF typeOperand=<root>.MyRec
|
||||||
|
GET_VAR 'other: kotlin.Any? declared in <root>.MyRec.equals' type=kotlin.Any? origin=null
|
||||||
|
then: RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in <root>.MyRec'
|
||||||
|
CONST Boolean type=kotlin.Boolean value=false
|
||||||
|
VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:<root>.MyRec [val]
|
||||||
|
TYPE_OP type=<root>.MyRec origin=CAST typeOperand=<root>.MyRec
|
||||||
|
GET_VAR 'other: kotlin.Any? declared in <root>.MyRec.equals' type=kotlin.Any? origin=null
|
||||||
|
WHEN type=kotlin.Unit origin=null
|
||||||
|
BRANCH
|
||||||
|
if: CALL 'public final fun not (): kotlin.Boolean [operator] declared in kotlin.Boolean' type=kotlin.Boolean origin=EXCLEQ
|
||||||
|
$this: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EXCLEQ
|
||||||
|
arg0: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:name type:kotlin.String visibility:private [final]' type=kotlin.String origin=null
|
||||||
|
receiver: GET_VAR '<this>: <root>.MyRec declared in <root>.MyRec.equals' type=<root>.MyRec origin=null
|
||||||
|
arg1: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:name type:kotlin.String visibility:private [final]' type=kotlin.String origin=null
|
||||||
|
receiver: GET_VAR 'val tmp_0: <root>.MyRec [val] declared in <root>.MyRec.equals' type=<root>.MyRec origin=null
|
||||||
|
then: RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in <root>.MyRec'
|
||||||
|
CONST Boolean type=kotlin.Boolean value=false
|
||||||
|
RETURN type=kotlin.Nothing from='public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in <root>.MyRec'
|
||||||
|
CONST Boolean type=kotlin.Boolean value=true
|
||||||
|
FUN name:test visibility:public modality:FINAL <> (rec:<root>.MyRec) returnType:kotlin.Unit
|
||||||
|
VALUE_PARAMETER name:rec index:0 type:<root>.MyRec
|
||||||
|
BLOCK_BODY
|
||||||
|
TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit
|
||||||
|
CALL 'public final fun <get-name> (): kotlin.String declared in <root>.MyRec' type=kotlin.String origin=GET_PROPERTY
|
||||||
|
$this: GET_VAR 'rec: <root>.MyRec declared in <root>.test' type=<root>.MyRec origin=null
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
// TARGET_BACKEND: JVM_IR
|
||||||
|
// JDK_KIND: FULL_JDK_17
|
||||||
|
// WITH_STDLIB
|
||||||
|
// JVM_TARGET: 17
|
||||||
|
|
||||||
|
@JvmRecord
|
||||||
|
data class MyRec(val name: String)
|
||||||
|
|
||||||
|
fun test(rec: MyRec) {
|
||||||
|
rec.name
|
||||||
|
}
|
||||||
+47
@@ -0,0 +1,47 @@
|
|||||||
|
@JvmRecord
|
||||||
|
data class MyRec : Record {
|
||||||
|
constructor(name: String) /* primary */ {
|
||||||
|
super/*Record*/()
|
||||||
|
/* <init>() */
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
val name: String
|
||||||
|
field = name
|
||||||
|
get
|
||||||
|
|
||||||
|
operator fun component1(): String {
|
||||||
|
return <this>.#name
|
||||||
|
}
|
||||||
|
|
||||||
|
fun copy(name: String = <this>.#name): MyRec {
|
||||||
|
return MyRec(name = name)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString(): String {
|
||||||
|
return "MyRec(" + "name=" + <this>.#name + ")"
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
return <this>.#name.hashCode()
|
||||||
|
}
|
||||||
|
|
||||||
|
override operator fun equals(other: Any?): Boolean {
|
||||||
|
when {
|
||||||
|
EQEQEQ(arg0 = <this>, arg1 = other) -> return true
|
||||||
|
}
|
||||||
|
when {
|
||||||
|
other !is MyRec -> return false
|
||||||
|
}
|
||||||
|
val tmp0_other_with_cast: MyRec = other as MyRec
|
||||||
|
when {
|
||||||
|
EQEQ(arg0 = <this>.#name, arg1 = tmp0_other_with_cast.#name).not() -> return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test(rec: MyRec) {
|
||||||
|
rec.<get-name>() /*~> Unit */
|
||||||
|
}
|
||||||
@@ -39,20 +39,11 @@ dependencies {
|
|||||||
|
|
||||||
optInToExperimentalCompilerApi()
|
optInToExperimentalCompilerApi()
|
||||||
|
|
||||||
val generationRoot = projectDir.resolve("tests-gen")
|
|
||||||
|
|
||||||
sourceSets {
|
sourceSets {
|
||||||
"main" { none() }
|
"main" { none() }
|
||||||
"test" {
|
"test" {
|
||||||
projectDefault()
|
projectDefault()
|
||||||
this.java.srcDir(generationRoot.name)
|
generatedTestDir()
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (kotlinBuildProperties.isInJpsBuildIdeaSync) {
|
|
||||||
apply(plugin = "idea")
|
|
||||||
idea {
|
|
||||||
this.module.generatedSourceDirs.add(generationRoot)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Generated
+6
@@ -951,6 +951,12 @@ public class IrTextTestGenerated extends AbstractIrTextTest {
|
|||||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/ir/irText/declarations/jvmRecord"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/ir/irText/declarations/jvmRecord"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("dataClassWithJvmRecord.kt")
|
||||||
|
public void testDataClassWithJvmRecord() throws Exception {
|
||||||
|
runTest("compiler/testData/ir/irText/declarations/jvmRecord/dataClassWithJvmRecord.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("javaRecordComponentAccess.kt")
|
@TestMetadata("javaRecordComponentAccess.kt")
|
||||||
public void testJavaRecordComponentAccess() throws Exception {
|
public void testJavaRecordComponentAccess() throws Exception {
|
||||||
|
|||||||
@@ -157,6 +157,7 @@ object StandardClassIds {
|
|||||||
val JvmField = "JvmField".jvmId()
|
val JvmField = "JvmField".jvmId()
|
||||||
val JvmDefault = "JvmDefault".jvmId()
|
val JvmDefault = "JvmDefault".jvmId()
|
||||||
val JvmRepeatable = "JvmRepeatable".jvmId()
|
val JvmRepeatable = "JvmRepeatable".jvmId()
|
||||||
|
val JvmRecord = "JvmRecord".jvmId()
|
||||||
|
|
||||||
val RawTypeAnnotation = "RawType".internalIrId()
|
val RawTypeAnnotation = "RawType".internalIrId()
|
||||||
val FlexibleNullability = "FlexibleNullability".internalIrId()
|
val FlexibleNullability = "FlexibleNullability".internalIrId()
|
||||||
@@ -202,6 +203,10 @@ object StandardClassIds {
|
|||||||
|
|
||||||
val not = "not".callableId(Boolean)
|
val not = "not".callableId(Boolean)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object Java {
|
||||||
|
val Record = "Record".javaLangId()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun String.baseId() = ClassId(StandardClassIds.BASE_KOTLIN_PACKAGE, Name.identifier(this))
|
private fun String.baseId() = ClassId(StandardClassIds.BASE_KOTLIN_PACKAGE, Name.identifier(this))
|
||||||
|
|||||||
Reference in New Issue
Block a user