[FIR] Properly collect constructors from class in presence of plugins

This commit is contained in:
Dmitriy Novozhilov
2021-10-11 17:38:11 +03:00
committed by TeamCityServer
parent 6712191538
commit af6d6ec2b9
17 changed files with 124 additions and 73 deletions
@@ -13,7 +13,7 @@ import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
import org.jetbrains.kotlin.fir.types.classId import org.jetbrains.kotlin.fir.types.classId
import org.jetbrains.kotlin.fir.declarations.FirRegularClass import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.resolved import org.jetbrains.kotlin.fir.declarations.resolved
import org.jetbrains.kotlin.fir.declarations.utils.primaryConstructor import org.jetbrains.kotlin.fir.declarations.primaryConstructorIfAny
import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.resolve.toSymbol import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.types.ConeClassLikeType import org.jetbrains.kotlin.fir.types.ConeClassLikeType
@@ -42,7 +42,7 @@ internal fun mapAnnotationParameters(annotation: FirAnnotation, session: FirSess
if (annotation !is FirAnnotationCall) return emptyMap() if (annotation !is FirAnnotationCall) return emptyMap()
val annotationCone = annotation.annotationTypeRef.coneType as? ConeClassLikeType ?: return emptyMap() val annotationCone = annotation.annotationTypeRef.coneType as? ConeClassLikeType ?: return emptyMap()
val annotationPrimaryCtor = (annotationCone.lookupTag.toSymbol(session)?.fir as? FirRegularClass)?.primaryConstructor val annotationPrimaryCtor = (annotationCone.lookupTag.toSymbol(session)?.fir as? FirRegularClass)?.primaryConstructorIfAny(session)?.fir
val annotationCtorParameterNames = annotationPrimaryCtor?.valueParameters?.map { it.name } val annotationCtorParameterNames = annotationPrimaryCtor?.valueParameters?.map { it.name }
val resultMap = mutableMapOf<String, FirExpression>() val resultMap = mutableMapOf<String, FirExpression>()
@@ -75,7 +75,7 @@ object FirJvmRecordChecker : FirRegularClassChecker() {
return return
} }
declaration.primaryConstructor?.valueParameters?.let { params -> declaration.primaryConstructorIfAny(context.session)?.valueParameterSymbols?.let { params ->
if (params.isEmpty()) { if (params.isEmpty()) {
reporter.reportOn(annotationSource, FirJvmErrors.JVM_RECORD_WITHOUT_PRIMARY_CONSTRUCTOR_PARAMETERS, context) reporter.reportOn(annotationSource, FirJvmErrors.JVM_RECORD_WITHOUT_PRIMARY_CONSTRUCTOR_PARAMETERS, context)
return return
@@ -8,13 +8,13 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration
import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.hasValOrVar
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.analysis.diagnostics.hasValOrVar
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
import org.jetbrains.kotlin.fir.declarations.FirRegularClass import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.utils.isData import org.jetbrains.kotlin.fir.declarations.utils.isData
import org.jetbrains.kotlin.fir.declarations.utils.primaryConstructor import org.jetbrains.kotlin.fir.declarations.primaryConstructorIfAny
object FirDataClassPrimaryConstructorChecker : FirRegularClassChecker() { object FirDataClassPrimaryConstructorChecker : FirRegularClassChecker() {
override fun check(declaration: FirRegularClass, context: CheckerContext, reporter: DiagnosticReporter) { override fun check(declaration: FirRegularClass, context: CheckerContext, reporter: DiagnosticReporter) {
@@ -22,14 +22,14 @@ object FirDataClassPrimaryConstructorChecker : FirRegularClassChecker() {
return return
} }
val primaryConstructor = declaration.primaryConstructor val primaryConstructor = declaration.primaryConstructorIfAny(context.session)
if (primaryConstructor == null || primaryConstructor.source.let { it == null || it.kind is FirFakeSourceElementKind }) { if (primaryConstructor == null || primaryConstructor.source.let { it == null || it.kind is FirFakeSourceElementKind }) {
reporter.reportOn(declaration.source, FirErrors.PRIMARY_CONSTRUCTOR_REQUIRED_FOR_DATA_CLASS, context) reporter.reportOn(declaration.source, FirErrors.PRIMARY_CONSTRUCTOR_REQUIRED_FOR_DATA_CLASS, context)
return return
} }
val valueParameters = primaryConstructor.valueParameters val valueParameters = primaryConstructor.valueParameterSymbols
if (valueParameters.isEmpty()) { if (valueParameters.isEmpty()) {
reporter.reportOn(primaryConstructor.source, FirErrors.DATA_CLASS_WITHOUT_PARAMETERS, context) reporter.reportOn(primaryConstructor.source, FirErrors.DATA_CLASS_WITHOUT_PARAMETERS, context)
} }
@@ -37,7 +37,7 @@ object FirDataClassPrimaryConstructorChecker : FirRegularClassChecker() {
if (parameter.isVararg) { if (parameter.isVararg) {
reporter.reportOn(parameter.source, FirErrors.DATA_CLASS_VARARG_PARAMETER, context) reporter.reportOn(parameter.source, FirErrors.DATA_CLASS_VARARG_PARAMETER, context)
} }
if (!parameter.hasValOrVar) { if (parameter.source?.hasValOrVar() != true) {
reporter.reportOn(parameter.source, FirErrors.DATA_CLASS_NOT_PROPERTY_PARAMETER, context) reporter.reportOn(parameter.source, FirErrors.DATA_CLASS_NOT_PROPERTY_PARAMETER, context)
} }
} }
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.contracts.description.isDefinitelyVisited
import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.analysis.cfa.util.PropertyInitializationInfo import org.jetbrains.kotlin.fir.analysis.cfa.util.PropertyInitializationInfo
import org.jetbrains.kotlin.fir.analysis.cfa.util.PropertyInitializationInfoCollector import org.jetbrains.kotlin.fir.analysis.cfa.util.PropertyInitializationInfoCollector
import org.jetbrains.kotlin.fir.analysis.checkers.contains import org.jetbrains.kotlin.fir.analysis.checkers.contains
@@ -26,6 +27,7 @@ import org.jetbrains.kotlin.fir.resolve.dfa.cfg.BlockExitNode
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.ControlFlowGraph import org.jetbrains.kotlin.fir.resolve.dfa.cfg.ControlFlowGraph
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.NormalPath import org.jetbrains.kotlin.fir.resolve.dfa.cfg.NormalPath
import org.jetbrains.kotlin.fir.resolve.dfa.controlFlowGraph import org.jetbrains.kotlin.fir.resolve.dfa.controlFlowGraph
import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.lexer.KtTokens
@@ -40,7 +42,13 @@ object FirMemberPropertiesChecker : FirClassChecker() {
// If all member properties have its own initializer, we don't need to collect property initialization info at all. // If all member properties have its own initializer, we don't need to collect property initialization info at all.
if (memberPropertySymbols.any { !it.hasInitializer }) { if (memberPropertySymbols.any { !it.hasInitializer }) {
collectPropertyInitialization(declaration, memberPropertySymbols, initializedInConstructor, initializedInInitOrOtherProperty) collectPropertyInitialization(
declaration,
context.session,
memberPropertySymbols,
initializedInConstructor,
initializedInInitOrOtherProperty
)
} }
val deadEnds = declaration.collectDeadEndDeclarations() val deadEnds = declaration.collectDeadEndDeclarations()
@@ -60,6 +68,7 @@ object FirMemberPropertiesChecker : FirClassChecker() {
private fun collectPropertyInitialization( private fun collectPropertyInitialization(
klass: FirClass, klass: FirClass,
session: FirSession,
memberPropertySymbols: Set<FirPropertySymbol>, memberPropertySymbols: Set<FirPropertySymbol>,
initializedInConstructor: MutableMap<FirPropertySymbol, EventOccurrencesRange>, initializedInConstructor: MutableMap<FirPropertySymbol, EventOccurrencesRange>,
initializedInInitOrOtherProperty: MutableMap<FirPropertySymbol, EventOccurrencesRange> initializedInInitOrOtherProperty: MutableMap<FirPropertySymbol, EventOccurrencesRange>
@@ -86,13 +95,13 @@ object FirMemberPropertiesChecker : FirClassChecker() {
// To handle the delegated constructor call, we need a cache from constructor to (analyzed) property init info. // To handle the delegated constructor call, we need a cache from constructor to (analyzed) property init info.
val constructorToData = val constructorToData =
mutableMapOf<FirConstructor, PropertyInitializationInfo>().withDefault { PropertyInitializationInfo.EMPTY } mutableMapOf<FirConstructorSymbol, PropertyInitializationInfo>().withDefault { PropertyInitializationInfo.EMPTY }
fun collectInfoFromGraph( fun collectInfoFromGraph(
graph: ControlFlowGraph, graph: ControlFlowGraph,
map: MutableMap<FirPropertySymbol, EventOccurrencesRange>, map: MutableMap<FirPropertySymbol, EventOccurrencesRange>,
acc: (EventOccurrencesRange, EventOccurrencesRange) -> EventOccurrencesRange, acc: (EventOccurrencesRange, EventOccurrencesRange) -> EventOccurrencesRange,
delegatedConstructor: FirConstructor? = null, delegatedConstructor: FirConstructorSymbol? = null,
) { ) {
val delegatedInfo = delegatedConstructor?.let { constructorToData.getValue(it) } ?: PropertyInitializationInfo.EMPTY val delegatedInfo = delegatedConstructor?.let { constructorToData.getValue(it) } ?: PropertyInitializationInfo.EMPTY
@@ -104,7 +113,7 @@ object FirMemberPropertiesChecker : FirClassChecker() {
val info = delegatedInfo.plus(infoAtExitNode) val info = delegatedInfo.plus(infoAtExitNode)
if (graph.declaration is FirConstructor) { if (graph.declaration is FirConstructor) {
constructorToData.putIfAbsent(graph.declaration as FirConstructor, info) constructorToData.putIfAbsent((graph.declaration as FirConstructor).symbol, info)
} }
for (propertySymbol in memberPropertySymbols) { for (propertySymbol in memberPropertySymbols) {
@@ -122,13 +131,15 @@ object FirMemberPropertiesChecker : FirClassChecker() {
} }
} }
val constructorGraphs = klass.constructorsSortedByDelegation.mapNotNull { it.controlFlowGraphReference?.controlFlowGraph } val constructorGraphs = klass.constructorsSortedByDelegation(session).mapNotNull {
it.resolvedControlFlowGraphReference?.controlFlowGraph
}
for (graph in constructorGraphs) { for (graph in constructorGraphs) {
collectInfoFromGraph( collectInfoFromGraph(
graph, graph,
initializedInConstructor, initializedInConstructor,
EventOccurrencesRange::or, EventOccurrencesRange::or,
(graph.declaration as? FirConstructor)?.delegatedThisConstructor (graph.declaration as? FirConstructor)?.symbol?.delegatedThisConstructor
) )
} }
@@ -13,10 +13,10 @@ import org.jetbrains.kotlin.fir.analysis.checkers.toRegularClassSymbol
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
import org.jetbrains.kotlin.fir.declarations.FirConstructor
import org.jetbrains.kotlin.fir.declarations.FirRegularClass import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.utils.isInterface import org.jetbrains.kotlin.fir.declarations.utils.isInterface
import org.jetbrains.kotlin.fir.declarations.utils.primaryConstructor import org.jetbrains.kotlin.fir.declarations.primaryConstructorIfAny
import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol
import org.jetbrains.kotlin.name.StandardClassIds import org.jetbrains.kotlin.name.StandardClassIds
import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.impl.FirImplicitAnyTypeRef import org.jetbrains.kotlin.fir.types.impl.FirImplicitAnyTypeRef
@@ -36,12 +36,12 @@ object FirPrimaryConstructorSuperTypeChecker : FirRegularClassChecker() {
return return
} }
val primaryConstructor = declaration.primaryConstructor val primaryConstructorSymbol = declaration.primaryConstructorIfAny(context.session)
if (primaryConstructor == null) { if (primaryConstructorSymbol == null) {
checkSupertypeInitializedWithoutPrimaryConstructor(declaration, reporter, context) checkSupertypeInitializedWithoutPrimaryConstructor(declaration, reporter, context)
} else { } else {
checkSuperTypeNotInitialized(primaryConstructor, declaration, context, reporter) checkSuperTypeNotInitialized(primaryConstructorSymbol, declaration, context, reporter)
} }
} }
@@ -55,13 +55,13 @@ object FirPrimaryConstructorSuperTypeChecker : FirRegularClassChecker() {
* ``` * ```
*/ */
private fun checkSuperTypeNotInitialized( private fun checkSuperTypeNotInitialized(
primaryConstructor: FirConstructor, primaryConstructorSymbol: FirConstructorSymbol,
regularClass: FirRegularClass, regularClass: FirRegularClass,
context: CheckerContext, context: CheckerContext,
reporter: DiagnosticReporter reporter: DiagnosticReporter
) { ) {
val containingClass = context.containingDeclarations.lastIsInstanceOrNull<FirRegularClass>() val containingClass = context.containingDeclarations.lastIsInstanceOrNull<FirRegularClass>()
val delegatedConstructorCall = primaryConstructor.delegatedConstructor ?: return val delegatedConstructorCall = primaryConstructorSymbol.resolvedDelegatedConstructorCall ?: return
// No need to check implicit call to the constructor of `kotlin.Any`. // No need to check implicit call to the constructor of `kotlin.Any`.
val constructedTypeRef = delegatedConstructorCall.constructedTypeRef val constructedTypeRef = delegatedConstructorCall.constructedTypeRef
if (constructedTypeRef is FirImplicitAnyTypeRef) return if (constructedTypeRef is FirImplicitAnyTypeRef) return
@@ -9,7 +9,7 @@ import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirRegularClass import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.FirValueParameter import org.jetbrains.kotlin.fir.declarations.FirValueParameter
import org.jetbrains.kotlin.fir.declarations.utils.collectEnumEntries import org.jetbrains.kotlin.fir.declarations.collectEnumEntries
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.* import org.jetbrains.kotlin.fir.expressions.*
@@ -186,7 +186,7 @@ class FirElementSerializer private constructor(
builder.typeTable = typeTableProto builder.typeTable = typeTableProto
} }
val representation = (klass as? FirRegularClass)?.getInlineClassUnderlyingParameter() val representation = (klass as? FirRegularClass)?.getInlineClassUnderlyingParameter(session)
if (representation != null) { if (representation != null) {
builder.inlineClassUnderlyingPropertyName = getSimpleNameIndex(representation.name) builder.inlineClassUnderlyingPropertyName = getSimpleNameIndex(representation.name)
@@ -561,7 +561,7 @@ fun Fir2IrComponents.createTemporaryVariableForSafeCallConstruction(
// TODO: implement inlineClassRepresentation in FirRegularClass instead. // TODO: implement inlineClassRepresentation in FirRegularClass instead.
fun Fir2IrComponents.computeInlineClassRepresentation(klass: FirRegularClass): InlineClassRepresentation<IrSimpleType>? { fun Fir2IrComponents.computeInlineClassRepresentation(klass: FirRegularClass): InlineClassRepresentation<IrSimpleType>? {
if (!klass.isInline) return null if (!klass.isInline) return null
val parameter = klass.getInlineClassUnderlyingParameter() ?: error("Inline class has no underlying parameter: ${klass.render()}") val parameter = klass.getInlineClassUnderlyingParameter(session) ?: error("Inline class has no underlying parameter: ${klass.render()}")
val underlyingType = parameter.returnTypeRef.toIrType(typeConverter) val underlyingType = parameter.returnTypeRef.toIrType(typeConverter)
return InlineClassRepresentation( return InlineClassRepresentation(
parameter.name, parameter.name,
@@ -7,7 +7,6 @@ package org.jetbrains.kotlin.fir.backend
import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContextImpl
import org.jetbrains.kotlin.backend.common.ir.BuiltinSymbolsBase import org.jetbrains.kotlin.backend.common.ir.BuiltinSymbolsBase
import org.jetbrains.kotlin.config.AnalysisFlags import org.jetbrains.kotlin.config.AnalysisFlags
import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.config.LanguageVersionSettings
@@ -19,7 +18,7 @@ import org.jetbrains.kotlin.fir.backend.generators.DataClassMembersGenerator
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.utils.isLocal import org.jetbrains.kotlin.fir.declarations.utils.isLocal
import org.jetbrains.kotlin.fir.declarations.utils.isSynthetic import org.jetbrains.kotlin.fir.declarations.utils.isSynthetic
import org.jetbrains.kotlin.fir.declarations.utils.primaryConstructor import org.jetbrains.kotlin.fir.declarations.primaryConstructorIfAny
import org.jetbrains.kotlin.fir.descriptors.FirModuleDescriptor import org.jetbrains.kotlin.fir.descriptors.FirModuleDescriptor
import org.jetbrains.kotlin.fir.extensions.declarationGenerators import org.jetbrains.kotlin.fir.extensions.declarationGenerators
import org.jetbrains.kotlin.fir.extensions.extensionService import org.jetbrains.kotlin.fir.extensions.extensionService
@@ -129,9 +128,9 @@ class Fir2IrConverter(
anonymousObject: FirAnonymousObject, anonymousObject: FirAnonymousObject,
irClass: IrClass = classifierStorage.getCachedIrClass(anonymousObject)!! irClass: IrClass = classifierStorage.getCachedIrClass(anonymousObject)!!
): IrClass { ): IrClass {
anonymousObject.primaryConstructor?.let { anonymousObject.primaryConstructorIfAny(session)?.let {
irClass.declarations += declarationStorage.createIrConstructor( irClass.declarations += declarationStorage.createIrConstructor(
it, irClass, isLocal = true it.fir, irClass, isLocal = true
) )
} }
val processedCallableNames = mutableSetOf<Name>() val processedCallableNames = mutableSetOf<Name>()
@@ -127,7 +127,7 @@ class Fir2IrVisitor(
} else if (initializer is FirAnonymousObjectExpression) { } else if (initializer is FirAnonymousObjectExpression) {
// Otherwise, this is a default-ish enum entry, which doesn't need its own synthetic class. // Otherwise, this is a default-ish enum entry, which doesn't need its own synthetic class.
// During raw FIR building, we put the delegated constructor call inside an anonymous object. // During raw FIR building, we put the delegated constructor call inside an anonymous object.
val delegatedConstructor = initializer.anonymousObject.primaryConstructor?.delegatedConstructor val delegatedConstructor = initializer.anonymousObject.primaryConstructorIfAny(session)?.fir?.delegatedConstructor
if (delegatedConstructor != null) { if (delegatedConstructor != null) {
with(memberGenerator) { with(memberGenerator) {
irEnumEntry.initializerExpression = irFactory.createExpressionBody( irEnumEntry.initializerExpression = irFactory.createExpressionBody(
@@ -10,7 +10,7 @@ import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirRegularClass import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.utils.collectEnumEntries import org.jetbrains.kotlin.fir.declarations.collectEnumEntries
import org.jetbrains.kotlin.fir.declarations.utils.isStatic import org.jetbrains.kotlin.fir.declarations.utils.isStatic
import org.jetbrains.kotlin.fir.declarations.utils.modality import org.jetbrains.kotlin.fir.declarations.utils.modality
import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.FirExpression
@@ -7,7 +7,6 @@ package org.jetbrains.kotlin.fir.declarations
import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.utils.isInline import org.jetbrains.kotlin.fir.declarations.utils.isInline
import org.jetbrains.kotlin.fir.declarations.utils.primaryConstructor
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
import org.jetbrains.kotlin.fir.resolve.substitution.createTypeSubstitutorByTypeConstructor import org.jetbrains.kotlin.fir.resolve.substitution.createTypeSubstitutorByTypeConstructor
import org.jetbrains.kotlin.fir.resolve.toSymbol import org.jetbrains.kotlin.fir.resolve.toSymbol
@@ -31,9 +30,9 @@ internal fun ConeKotlinType.unsubstitutedUnderlyingTypeForInlineClass(session: F
?.toSymbol(session) as? FirRegularClassSymbol ?.toSymbol(session) as? FirRegularClassSymbol
?: return null ?: return null
symbol.ensureResolved(FirResolvePhase.STATUS) symbol.ensureResolved(FirResolvePhase.STATUS)
return symbol.fir.getInlineClassUnderlyingParameter()?.returnTypeRef?.coneType return symbol.fir.getInlineClassUnderlyingParameter(session)?.returnTypeRef?.coneType
} }
// TODO: implement inlineClassRepresentation in FirRegularClass instead. // TODO: implement inlineClassRepresentation in FirRegularClass instead.
fun FirRegularClass.getInlineClassUnderlyingParameter(): FirValueParameter? = fun FirRegularClass.getInlineClassUnderlyingParameter(session: FirSession): FirValueParameter? =
if (isInline) primaryConstructor?.valueParameters?.singleOrNull() else null if (isInline) primaryConstructorIfAny(session)?.fir?.valueParameters?.singleOrNull() else null
@@ -0,0 +1,48 @@
/*
* Copyright 2010-2021 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.declarations
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.scopes.impl.declaredMemberScope
import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol
import org.jetbrains.kotlin.utils.addToStdlib.runIf
fun FirClass.constructors(session: FirSession): List<FirConstructorSymbol> {
val result = mutableListOf<FirConstructorSymbol>()
session.declaredMemberScope(this).processDeclaredConstructors { result += it }
return result
}
fun FirClass.constructorsSortedByDelegation(session: FirSession): List<FirConstructorSymbol> {
return constructors(session).sortedWith(ConstructorDelegationComparator)
}
fun FirClass.primaryConstructorIfAny(session: FirSession): FirConstructorSymbol? {
return constructors(session).find(FirConstructorSymbol::isPrimary)
}
fun FirRegularClass.collectEnumEntries(): Collection<FirEnumEntry> {
assert(classKind == ClassKind.ENUM_CLASS)
return declarations.filterIsInstance<FirEnumEntry>()
}
val FirConstructorSymbol.delegatedThisConstructor: FirConstructorSymbol?
get() = runIf(delegatedConstructorCallIsThis) { this.resolvedDelegatedConstructor }
private object ConstructorDelegationComparator : Comparator<FirConstructorSymbol> {
override fun compare(p0: FirConstructorSymbol?, p1: FirConstructorSymbol?): Int {
if (p0 == null && p1 == null) return 0
if (p0 == null) return -1
if (p1 == null) return 1
if (p0.delegatedThisConstructor == p1) return 1
if (p1.delegatedThisConstructor == p0) return -1
// If neither is a delegation to each other, the order doesn't matter.
// Here we return 0 to preserve the original order.
return 0
}
}
@@ -13,7 +13,7 @@ import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirEnumEntry import org.jetbrains.kotlin.fir.declarations.FirEnumEntry
import org.jetbrains.kotlin.fir.declarations.FirRegularClass import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.getSealedClassInheritors import org.jetbrains.kotlin.fir.declarations.getSealedClassInheritors
import org.jetbrains.kotlin.fir.declarations.utils.collectEnumEntries import org.jetbrains.kotlin.fir.declarations.collectEnumEntries
import org.jetbrains.kotlin.fir.declarations.utils.modality import org.jetbrains.kotlin.fir.declarations.utils.modality
import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.LogicOperationKind.OR import org.jetbrains.kotlin.fir.expressions.LogicOperationKind.OR
@@ -12,7 +12,7 @@ import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyAccessor import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyAccessor
import org.jetbrains.kotlin.fir.declarations.utils.isCompanion import org.jetbrains.kotlin.fir.declarations.utils.isCompanion
import org.jetbrains.kotlin.fir.declarations.utils.isInner import org.jetbrains.kotlin.fir.declarations.utils.isInner
import org.jetbrains.kotlin.fir.declarations.utils.primaryConstructor import org.jetbrains.kotlin.fir.declarations.primaryConstructorIfAny
import org.jetbrains.kotlin.fir.expressions.FirCallableReferenceAccess import org.jetbrains.kotlin.fir.expressions.FirCallableReferenceAccess
import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirWhenExpression import org.jetbrains.kotlin.fir.expressions.FirWhenExpression
@@ -406,7 +406,7 @@ class BodyResolveContext(
): T { ): T {
val labelName = (owner as? FirRegularClass)?.name val labelName = (owner as? FirRegularClass)?.name
?: if (owner.classKind == ClassKind.ENUM_ENTRY) { ?: if (owner.classKind == ClassKind.ENUM_ENTRY) {
owner.primaryConstructor?.symbol?.callableId?.className?.shortName() owner.primaryConstructorIfAny(holder.session)?.callableId?.className?.shortName()
} else null } else null
val type = owner.defaultType() val type = owner.defaultType()
val towerElementsForClass = holder.collectTowerDataElementsForClass(owner, type) val towerElementsForClass = holder.collectTowerDataElementsForClass(owner, type)
@@ -5,14 +5,10 @@
package org.jetbrains.kotlin.fir.declarations.utils package org.jetbrains.kotlin.fir.declarations.utils
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccess import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccess
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
import org.jetbrains.kotlin.fir.symbols.impl.FirAnonymousObjectSymbol import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.fir.types.ConeClassLikeType import org.jetbrains.kotlin.fir.types.ConeClassLikeType
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
@@ -38,24 +34,6 @@ val FirClass.superConeTypes: List<ConeClassLikeType> get() = superTypeRefs.mapNo
val FirClass.anonymousInitializers: List<FirAnonymousInitializer> val FirClass.anonymousInitializers: List<FirAnonymousInitializer>
get() = declarations.filterIsInstance<FirAnonymousInitializer>() get() = declarations.filterIsInstance<FirAnonymousInitializer>()
val FirClass.constructors: List<FirConstructor>
get() = declarations.filterIsInstance<FirConstructor>()
val FirConstructor.delegatedThisConstructor: FirConstructor?
get() = delegatedConstructor?.takeIf { it.isThis }
?.let { (it.calleeReference as? FirResolvedNamedReference)?.resolvedSymbol?.fir as? FirConstructor }
val FirClass.constructorsSortedByDelegation: List<FirConstructor>
get() = constructors.sortedWith(ConstructorDelegationComparator)
val FirClass.primaryConstructor: FirConstructor?
get() = constructors.find(FirConstructor::isPrimary)
fun FirRegularClass.collectEnumEntries(): Collection<FirEnumEntry> {
assert(classKind == ClassKind.ENUM_CLASS)
return declarations.filterIsInstance<FirEnumEntry>()
}
val FirQualifiedAccess.referredPropertySymbol: FirPropertySymbol? val FirQualifiedAccess.referredPropertySymbol: FirPropertySymbol?
get() { get() {
val reference = calleeReference as? FirResolvedNamedReference ?: return null val reference = calleeReference as? FirResolvedNamedReference ?: return null
@@ -69,16 +47,4 @@ inline val FirDeclaration.isFromLibrary: Boolean
inline val FirDeclaration.isSynthetic: Boolean inline val FirDeclaration.isSynthetic: Boolean
get() = origin == FirDeclarationOrigin.Synthetic get() = origin == FirDeclarationOrigin.Synthetic
private object ConstructorDelegationComparator : Comparator<FirConstructor> {
override fun compare(p0: FirConstructor?, p1: FirConstructor?): Int {
if (p0 == null && p1 == null) return 0
if (p0 == null) return -1
if (p1 == null) return 1
if (p0.delegatedThisConstructor == p1) return 1
if (p1.delegatedThisConstructor == p0) return -1
// If neither is a delegation to each other, the order doesn't matter.
// Here we return 0 to preserve the original order.
return 0
}
}
@@ -8,6 +8,9 @@ package org.jetbrains.kotlin.fir.symbols.impl
import org.jetbrains.kotlin.fir.FirLabel import org.jetbrains.kotlin.fir.FirLabel
import org.jetbrains.kotlin.fir.contracts.FirResolvedContractDescription import org.jetbrains.kotlin.fir.contracts.FirResolvedContractDescription
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.expressions.FirDelegatedConstructorCall
import org.jetbrains.kotlin.fir.references.FirControlFlowGraphReference
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
import org.jetbrains.kotlin.fir.symbols.AccessorSymbol import org.jetbrains.kotlin.fir.symbols.AccessorSymbol
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.ensureResolved import org.jetbrains.kotlin.fir.symbols.ensureResolved
@@ -30,6 +33,12 @@ sealed class FirFunctionSymbol<D : FirFunction>(
else -> null else -> null
} as? FirResolvedContractDescription } as? FirResolvedContractDescription
} }
val resolvedControlFlowGraphReference: FirControlFlowGraphReference?
get() {
ensureResolved(FirResolvePhase.BODY_RESOLVE)
return fir.controlFlowGraphReference
}
} }
// ------------------------ named ------------------------ // ------------------------ named ------------------------
@@ -52,6 +61,25 @@ class FirConstructorSymbol(
) : FirFunctionSymbol<FirConstructor>(callableId) { ) : FirFunctionSymbol<FirConstructor>(callableId) {
val isPrimary: Boolean val isPrimary: Boolean
get() = fir.isPrimary get() = fir.isPrimary
val resolvedDelegatedConstructor: FirConstructorSymbol?
get() {
val delegatedConstructorCall = resolvedDelegatedConstructorCall ?: return null
return (delegatedConstructorCall.calleeReference as? FirResolvedNamedReference)?.resolvedSymbol as? FirConstructorSymbol
}
val resolvedDelegatedConstructorCall: FirDelegatedConstructorCall?
get() {
if (fir.delegatedConstructor == null) return null
ensureResolved(FirResolvePhase.BODY_RESOLVE)
return fir.delegatedConstructor
}
val delegatedConstructorCallIsThis: Boolean
get() = fir.delegatedConstructor?.isThis ?: false
val delegatedConstructorCallIsSuper: Boolean
get() = fir.delegatedConstructor?.isSuper ?: false
} }
open class FirAccessorSymbol( open class FirAccessorSymbol(