[FIR] Provide implementation of ExpectActualMatchingContext for FIR
^KT-58578
This commit is contained in:
committed by
Space Team
parent
8338370fbd
commit
b19116d3af
+284
@@ -0,0 +1,284 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2023 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.mpp
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
|
import org.jetbrains.kotlin.descriptors.Visibility
|
||||||
|
import org.jetbrains.kotlin.descriptors.isEnumClass
|
||||||
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.utils.*
|
||||||
|
import org.jetbrains.kotlin.fir.isSubstitutionOrIntersectionOverride
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.*
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
||||||
|
import org.jetbrains.kotlin.fir.scopes.*
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||||
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
|
import org.jetbrains.kotlin.mpp.*
|
||||||
|
import org.jetbrains.kotlin.name.CallableId
|
||||||
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.mpp.ExpectActualMatchingContext
|
||||||
|
import org.jetbrains.kotlin.types.AbstractTypeChecker
|
||||||
|
import org.jetbrains.kotlin.types.Variance
|
||||||
|
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
|
||||||
|
import org.jetbrains.kotlin.types.model.SimpleTypeMarker
|
||||||
|
import org.jetbrains.kotlin.types.model.TypeSubstitutorMarker
|
||||||
|
import org.jetbrains.kotlin.types.model.TypeSystemInferenceExtensionContext
|
||||||
|
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.UnsafeCastFunction
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.castAll
|
||||||
|
|
||||||
|
class FirExpectActualMatchingContext(
|
||||||
|
private val actualSession: FirSession,
|
||||||
|
private val scopeSession: ScopeSession
|
||||||
|
) : ExpectActualMatchingContext<FirBasedSymbol<*>>, TypeSystemInferenceExtensionContext by actualSession.typeContext {
|
||||||
|
override val shouldCheckReturnTypesOfCallables: Boolean
|
||||||
|
get() = false
|
||||||
|
|
||||||
|
private fun CallableSymbolMarker.asSymbol(): FirCallableSymbol<*> = this as FirCallableSymbol<*>
|
||||||
|
private fun FunctionSymbolMarker.asSymbol(): FirFunctionSymbol<*> = this as FirFunctionSymbol<*>
|
||||||
|
private fun PropertySymbolMarker.asSymbol(): FirPropertySymbol = this as FirPropertySymbol
|
||||||
|
private fun ValueParameterSymbolMarker.asSymbol(): FirValueParameterSymbol = this as FirValueParameterSymbol
|
||||||
|
private fun TypeParameterSymbolMarker.asSymbol(): FirTypeParameterSymbol = this as FirTypeParameterSymbol
|
||||||
|
private fun ClassLikeSymbolMarker.asSymbol(): FirClassLikeSymbol<*> = this as FirClassLikeSymbol<*>
|
||||||
|
private fun RegularClassSymbolMarker.asSymbol(): FirRegularClassSymbol = this as FirRegularClassSymbol
|
||||||
|
private fun TypeAliasSymbolMarker.asSymbol(): FirTypeAliasSymbol = this as FirTypeAliasSymbol
|
||||||
|
|
||||||
|
override val RegularClassSymbolMarker.classId: ClassId
|
||||||
|
get() = asSymbol().classId
|
||||||
|
override val TypeAliasSymbolMarker.classId: ClassId
|
||||||
|
get() = asSymbol().classId
|
||||||
|
override val CallableSymbolMarker.callableId: CallableId
|
||||||
|
get() = asSymbol().callableId
|
||||||
|
|
||||||
|
override val TypeParameterSymbolMarker.parameterName: Name
|
||||||
|
get() = asSymbol().name
|
||||||
|
override val ValueParameterSymbolMarker.parameterName: Name
|
||||||
|
get() = asSymbol().name
|
||||||
|
|
||||||
|
override fun TypeAliasSymbolMarker.expandToRegularClass(): RegularClassSymbolMarker? {
|
||||||
|
return asSymbol()
|
||||||
|
.resolvedExpandedTypeRef
|
||||||
|
.coneType
|
||||||
|
.fullyExpandedType(actualSession)
|
||||||
|
.toSymbol(actualSession) as? FirRegularClassSymbol
|
||||||
|
}
|
||||||
|
|
||||||
|
override val RegularClassSymbolMarker.classKind: ClassKind
|
||||||
|
get() = asSymbol().classKind
|
||||||
|
override val RegularClassSymbolMarker.isCompanion: Boolean
|
||||||
|
get() = asSymbol().resolvedStatus.isCompanion
|
||||||
|
override val RegularClassSymbolMarker.isInner: Boolean
|
||||||
|
get() = asSymbol().resolvedStatus.isInner
|
||||||
|
override val RegularClassSymbolMarker.isInline: Boolean
|
||||||
|
get() = asSymbol().resolvedStatus.isInline
|
||||||
|
override val RegularClassSymbolMarker.isValue: Boolean
|
||||||
|
get() = asSymbol().resolvedStatus.isInline
|
||||||
|
override val RegularClassSymbolMarker.isFun: Boolean
|
||||||
|
get() = asSymbol().resolvedStatus.isFun
|
||||||
|
override val ClassLikeSymbolMarker.typeParameters: List<TypeParameterSymbolMarker>
|
||||||
|
get() = asSymbol().typeParameterSymbols
|
||||||
|
|
||||||
|
override val ClassLikeSymbolMarker.modality: Modality?
|
||||||
|
get() = asSymbol().resolvedStatus.modality
|
||||||
|
override val ClassLikeSymbolMarker.visibility: Visibility
|
||||||
|
get() = asSymbol().resolvedStatus.visibility
|
||||||
|
|
||||||
|
override val CallableSymbolMarker.modality: Modality?
|
||||||
|
get() = asSymbol().resolvedStatus.modality
|
||||||
|
override val CallableSymbolMarker.visibility: Visibility
|
||||||
|
get() = asSymbol().resolvedStatus.visibility
|
||||||
|
|
||||||
|
override val CallableSymbolMarker.isExpect: Boolean
|
||||||
|
get() = asSymbol().resolvedStatus.isExpect
|
||||||
|
override val CallableSymbolMarker.isInline: Boolean
|
||||||
|
get() = asSymbol().resolvedStatus.isInline
|
||||||
|
override val CallableSymbolMarker.isSuspend: Boolean
|
||||||
|
get() = asSymbol().resolvedStatus.isSuspend
|
||||||
|
override val CallableSymbolMarker.isExternal: Boolean
|
||||||
|
get() = asSymbol().resolvedStatus.isExternal
|
||||||
|
override val CallableSymbolMarker.isInfix: Boolean
|
||||||
|
get() = asSymbol().resolvedStatus.isInfix
|
||||||
|
override val CallableSymbolMarker.isOperator: Boolean
|
||||||
|
get() = asSymbol().resolvedStatus.isOperator
|
||||||
|
override val CallableSymbolMarker.isTailrec: Boolean
|
||||||
|
get() = asSymbol().resolvedStatus.isTailRec
|
||||||
|
|
||||||
|
override val PropertySymbolMarker.isVar: Boolean
|
||||||
|
get() = asSymbol().isVar
|
||||||
|
override val PropertySymbolMarker.isLateinit: Boolean
|
||||||
|
get() = asSymbol().resolvedStatus.isLateInit
|
||||||
|
override val PropertySymbolMarker.isConst: Boolean
|
||||||
|
get() = asSymbol().resolvedStatus.isConst
|
||||||
|
|
||||||
|
override val PropertySymbolMarker.setter: FunctionSymbolMarker?
|
||||||
|
get() = asSymbol().setterSymbol
|
||||||
|
|
||||||
|
@OptIn(UnsafeCastFunction::class)
|
||||||
|
override fun createExpectActualTypeParameterSubstitutor(
|
||||||
|
expectTypeParameters: List<TypeParameterSymbolMarker>,
|
||||||
|
actualTypeParameters: List<TypeParameterSymbolMarker>,
|
||||||
|
parentSubstitutor: TypeSubstitutorMarker?,
|
||||||
|
): TypeSubstitutorMarker {
|
||||||
|
return createExpectActualTypeParameterSubstitutor(
|
||||||
|
expectTypeParameters.castAll<FirTypeParameterSymbol>(),
|
||||||
|
actualTypeParameters.castAll<FirTypeParameterSymbol>(),
|
||||||
|
actualSession,
|
||||||
|
parentSubstitutor as ConeSubstitutor?
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override val RegularClassSymbolMarker.superTypes: List<KotlinTypeMarker>
|
||||||
|
get() = asSymbol().resolvedSuperTypes
|
||||||
|
|
||||||
|
override fun RegularClassSymbolMarker.collectAllMembers(isActualDeclaration: Boolean): List<FirBasedSymbol<*>> {
|
||||||
|
val symbol = asSymbol()
|
||||||
|
val session = when (isActualDeclaration) {
|
||||||
|
true -> actualSession
|
||||||
|
false -> symbol.moduleData.session
|
||||||
|
}
|
||||||
|
val scope = symbol.defaultType()
|
||||||
|
.scope(useSiteSession = session, scopeSession, FakeOverrideTypeCalculator.DoNothing, requiredPhase = FirResolvePhase.STATUS)
|
||||||
|
?: return emptyList()
|
||||||
|
return mutableListOf<FirBasedSymbol<*>>().apply {
|
||||||
|
for (name in scope.getCallableNames()) {
|
||||||
|
scope.getMembersTo(this, name)
|
||||||
|
}
|
||||||
|
// TODO: replace with scope lookup
|
||||||
|
for (name in symbol.declarationSymbols.mapNotNull { (it as? FirRegularClassSymbol)?.classId?.shortClassName }) {
|
||||||
|
addIfNotNull(scope.getSingleClassifier(name) as? FirRegularClassSymbol)
|
||||||
|
}
|
||||||
|
getConstructorsTo(this, scope)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun RegularClassSymbolMarker.getMembersForExpectClass(name: Name): List<FirCallableSymbol<*>> {
|
||||||
|
val symbol = asSymbol()
|
||||||
|
val scope = symbol.defaultType()
|
||||||
|
.scope(
|
||||||
|
useSiteSession = symbol.moduleData.session,
|
||||||
|
scopeSession,
|
||||||
|
FakeOverrideTypeCalculator.DoNothing,
|
||||||
|
requiredPhase = FirResolvePhase.STATUS
|
||||||
|
)
|
||||||
|
?: return emptyList()
|
||||||
|
return mutableListOf<FirCallableSymbol<*>>().apply {
|
||||||
|
scope.getMembersTo(this, name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun FirClassSymbol<*>.getConstructors(
|
||||||
|
scopeSession: ScopeSession,
|
||||||
|
session: FirSession = moduleData.session
|
||||||
|
): Collection<FirConstructorSymbol> = mutableListOf<FirConstructorSymbol>().apply {
|
||||||
|
getConstructorsTo(
|
||||||
|
this,
|
||||||
|
unsubstitutedScope(
|
||||||
|
session,
|
||||||
|
scopeSession,
|
||||||
|
withForcedTypeCalculator = false,
|
||||||
|
memberRequiredPhase = FirResolvePhase.STATUS,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun getConstructorsTo(destination: MutableList<in FirConstructorSymbol>, scope: FirTypeScope) {
|
||||||
|
scope.getDeclaredConstructors().mapTo(destination) { it }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun FirTypeScope.getMembersTo(destination: MutableList<in FirCallableSymbol<*>>, name: Name) {
|
||||||
|
processFunctionsByName(name) { destination.add(it) }
|
||||||
|
processPropertiesByName(name) { destination.add(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun RegularClassSymbolMarker.collectEnumEntryNames(): List<Name> {
|
||||||
|
return asSymbol().fir.collectEnumEntries().map { it.name }
|
||||||
|
}
|
||||||
|
|
||||||
|
override val CallableSymbolMarker.dispatchReceiverType: SimpleTypeMarker?
|
||||||
|
get() = asSymbol().dispatchReceiverType
|
||||||
|
override val CallableSymbolMarker.extensionReceiverType: KotlinTypeMarker?
|
||||||
|
get() = asSymbol().resolvedReceiverTypeRef?.coneType
|
||||||
|
override val CallableSymbolMarker.returnType: KotlinTypeMarker
|
||||||
|
get() = asSymbol().resolvedReturnType.type
|
||||||
|
override val CallableSymbolMarker.typeParameters: List<TypeParameterSymbolMarker>
|
||||||
|
get() = asSymbol().typeParameterSymbols
|
||||||
|
override val FunctionSymbolMarker.valueParameters: List<ValueParameterSymbolMarker>
|
||||||
|
get() = asSymbol().valueParameterSymbols
|
||||||
|
|
||||||
|
override val ValueParameterSymbolMarker.isVararg: Boolean
|
||||||
|
get() = asSymbol().isVararg
|
||||||
|
override val ValueParameterSymbolMarker.isNoinline: Boolean
|
||||||
|
get() = asSymbol().isNoinline
|
||||||
|
override val ValueParameterSymbolMarker.isCrossinline: Boolean
|
||||||
|
get() = asSymbol().isCrossinline
|
||||||
|
override val ValueParameterSymbolMarker.hasDefaultValue: Boolean
|
||||||
|
get() = asSymbol().hasDefaultValue
|
||||||
|
|
||||||
|
override fun CallableSymbolMarker.isAnnotationConstructor(): Boolean {
|
||||||
|
val symbol = asSymbol()
|
||||||
|
return symbol.isAnnotationConstructor(symbol.moduleData.session)
|
||||||
|
}
|
||||||
|
|
||||||
|
override val TypeParameterSymbolMarker.bounds: List<KotlinTypeMarker>
|
||||||
|
get() = asSymbol().resolvedBounds.map { it.coneType }
|
||||||
|
|
||||||
|
override val TypeParameterSymbolMarker.variance: Variance
|
||||||
|
get() = asSymbol().variance
|
||||||
|
|
||||||
|
override val TypeParameterSymbolMarker.isReified: Boolean
|
||||||
|
get() = asSymbol().isReified
|
||||||
|
|
||||||
|
override fun areCompatibleExpectActualTypes(
|
||||||
|
expectType: KotlinTypeMarker?,
|
||||||
|
actualType: KotlinTypeMarker?,
|
||||||
|
): Boolean {
|
||||||
|
if (expectType == null) return actualType == null
|
||||||
|
if (actualType == null) return false
|
||||||
|
|
||||||
|
return AbstractTypeChecker.equalTypes(
|
||||||
|
actualSession.typeContext.newTypeCheckerState(errorTypesEqualToAnything = true, stubTypesEqualToAnything = false),
|
||||||
|
expectType,
|
||||||
|
actualType
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun RegularClassSymbolMarker.isNotSamInterface(): Boolean {
|
||||||
|
val type = asSymbol().defaultType()
|
||||||
|
val isSam = FirSamResolver(actualSession, scopeSession).isSamType(type)
|
||||||
|
return !isSam
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun CallableSymbolMarker.shouldSkipMatching(containingExpectClass: RegularClassSymbolMarker): Boolean {
|
||||||
|
val symbol = asSymbol()
|
||||||
|
val classSymbol = containingExpectClass.asSymbol()
|
||||||
|
val isConstructor = symbol is FirConstructorSymbol
|
||||||
|
if (isConstructor && classSymbol.classKind.isEnumClass) {
|
||||||
|
/*
|
||||||
|
* Expect enums in FIR have (expect) constructors, but actually there is no need to map them
|
||||||
|
*/
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if (!isConstructor && symbol.dispatchReceiverType?.classId != classSymbol.classId) {
|
||||||
|
// Skip fake overrides
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return symbol.isSubstitutionOrIntersectionOverride // Skip fake overrides
|
||||||
|
|| !symbol.isExpect // Skip non-expect declarations like equals, hashCode, toString and any inherited declarations from non-expect super types
|
||||||
|
}
|
||||||
|
|
||||||
|
override val CallableSymbolMarker.hasStableParameterNames: Boolean
|
||||||
|
get() = when (asSymbol().origin) {
|
||||||
|
is FirDeclarationOrigin.Java,
|
||||||
|
FirDeclarationOrigin.Enhancement,
|
||||||
|
FirDeclarationOrigin.DynamicScope -> false
|
||||||
|
else -> true
|
||||||
|
}
|
||||||
|
}
|
||||||
+59
-594
@@ -5,30 +5,18 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.resolve.transformers.mpp
|
package org.jetbrains.kotlin.fir.resolve.transformers.mpp
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
|
||||||
import org.jetbrains.kotlin.descriptors.Modality.*
|
|
||||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
|
||||||
import org.jetbrains.kotlin.fir.FirSession
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.*
|
|
||||||
import org.jetbrains.kotlin.fir.resolve.*
|
import org.jetbrains.kotlin.fir.resolve.*
|
||||||
import org.jetbrains.kotlin.fir.resolve.providers.dependenciesSymbolProvider
|
import org.jetbrains.kotlin.fir.resolve.providers.dependenciesSymbolProvider
|
||||||
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
|
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
|
||||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
||||||
import org.jetbrains.kotlin.fir.scopes.*
|
|
||||||
import org.jetbrains.kotlin.fir.scopes.impl.FirPackageMemberScope
|
import org.jetbrains.kotlin.fir.scopes.impl.FirPackageMemberScope
|
||||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||||
import org.jetbrains.kotlin.fir.types.*
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.resolve.calls.mpp.AbstractExpectActualCompatibilityChecker
|
||||||
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility
|
import org.jetbrains.kotlin.mpp.CallableSymbolMarker
|
||||||
import org.jetbrains.kotlin.utils.SmartList
|
|
||||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.enumMapOf
|
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.enumSetOf
|
|
||||||
import org.jetbrains.kotlin.utils.keysToMap
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
object FirExpectActualResolver {
|
object FirExpectActualResolver {
|
||||||
fun findExpectForActual(
|
fun findExpectForActual(
|
||||||
@@ -36,593 +24,70 @@ object FirExpectActualResolver {
|
|||||||
useSiteSession: FirSession,
|
useSiteSession: FirSession,
|
||||||
scopeSession: ScopeSession
|
scopeSession: ScopeSession
|
||||||
): ExpectForActualData? {
|
): ExpectForActualData? {
|
||||||
return when (actualSymbol) {
|
val context = FirExpectActualMatchingContext(useSiteSession, scopeSession)
|
||||||
is FirCallableSymbol<*> -> {
|
with(context) {
|
||||||
val callableId = actualSymbol.callableId
|
val result = when (actualSymbol) {
|
||||||
val classId = callableId.classId
|
is FirCallableSymbol<*> -> {
|
||||||
var parentSubstitutor: ConeSubstitutor? = null
|
val callableId = actualSymbol.callableId
|
||||||
var expectContainingClass: FirRegularClassSymbol? = null
|
val classId = callableId.classId
|
||||||
var actualContainingClass: FirRegularClassSymbol? = null
|
var parentSubstitutor: ConeSubstitutor? = null
|
||||||
val candidates = when {
|
var expectContainingClass: FirRegularClassSymbol? = null
|
||||||
classId != null -> {
|
var actualContainingClass: FirRegularClassSymbol? = null
|
||||||
expectContainingClass = useSiteSession.dependenciesSymbolProvider.getClassLikeSymbolByClassId(classId)?.let {
|
val candidates = when {
|
||||||
it.fullyExpandedClass(it.moduleData.session)
|
classId != null -> {
|
||||||
|
expectContainingClass = useSiteSession.dependenciesSymbolProvider.getClassLikeSymbolByClassId(classId)?.let {
|
||||||
|
it.fullyExpandedClass(it.moduleData.session)
|
||||||
|
}
|
||||||
|
actualContainingClass = useSiteSession.symbolProvider.getClassLikeSymbolByClassId(classId)
|
||||||
|
?.fullyExpandedClass(useSiteSession)
|
||||||
|
|
||||||
|
val expectTypeParameters = expectContainingClass?.typeParameterSymbols.orEmpty()
|
||||||
|
val actualTypeParameters = actualContainingClass
|
||||||
|
?.typeParameterSymbols
|
||||||
|
.orEmpty()
|
||||||
|
|
||||||
|
parentSubstitutor = createExpectActualTypeParameterSubstitutor(
|
||||||
|
expectTypeParameters,
|
||||||
|
actualTypeParameters,
|
||||||
|
useSiteSession,
|
||||||
|
)
|
||||||
|
|
||||||
|
when (actualSymbol) {
|
||||||
|
is FirConstructorSymbol -> expectContainingClass?.getConstructors(scopeSession)
|
||||||
|
else -> expectContainingClass?.getMembersForExpectClass(actualSymbol.name)
|
||||||
|
}.orEmpty()
|
||||||
}
|
}
|
||||||
actualContainingClass = useSiteSession.symbolProvider.getClassLikeSymbolByClassId(classId)
|
callableId.isLocal -> return null
|
||||||
?.fullyExpandedClass(useSiteSession)
|
else -> {
|
||||||
|
val scope = FirPackageMemberScope(callableId.packageName, useSiteSession, useSiteSession.dependenciesSymbolProvider)
|
||||||
val expectTypeParameters = expectContainingClass?.typeParameterSymbols.orEmpty()
|
mutableListOf<FirCallableSymbol<*>>().apply {
|
||||||
val actualTypeParameters = actualContainingClass
|
scope.processFunctionsByName(callableId.callableName) { add(it) }
|
||||||
?.typeParameterSymbols
|
scope.processPropertiesByName(callableId.callableName) { add(it) }
|
||||||
.orEmpty()
|
}
|
||||||
|
|
||||||
parentSubstitutor = createExpectActualTypeParameterSubstitutor(
|
|
||||||
expectTypeParameters,
|
|
||||||
actualTypeParameters,
|
|
||||||
useSiteSession,
|
|
||||||
)
|
|
||||||
|
|
||||||
when (actualSymbol) {
|
|
||||||
is FirConstructorSymbol -> expectContainingClass?.getConstructors(scopeSession)
|
|
||||||
else -> expectContainingClass?.getMembers(callableId.callableName, scopeSession)
|
|
||||||
}.orEmpty()
|
|
||||||
}
|
|
||||||
callableId.isLocal -> return null
|
|
||||||
else -> {
|
|
||||||
val scope = FirPackageMemberScope(callableId.packageName, useSiteSession, useSiteSession.dependenciesSymbolProvider)
|
|
||||||
mutableListOf<FirCallableSymbol<*>>().apply {
|
|
||||||
scope.processFunctionsByName(callableId.callableName) { add(it) }
|
|
||||||
scope.processPropertiesByName(callableId.callableName) { add(it) }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
candidates.filter { expectSymbol ->
|
||||||
candidates.filter { expectSymbol ->
|
actualSymbol != expectSymbol && expectSymbol.isExpect
|
||||||
actualSymbol != expectSymbol && expectSymbol.isExpect
|
}.groupBy { expectDeclaration ->
|
||||||
}.groupBy { expectDeclaration ->
|
AbstractExpectActualCompatibilityChecker.areCompatibleCallables(
|
||||||
areCompatibleCallables(
|
expectDeclaration,
|
||||||
expectDeclaration,
|
actualSymbol as CallableSymbolMarker,
|
||||||
actualSymbol,
|
parentSubstitutor,
|
||||||
useSiteSession,
|
expectContainingClass,
|
||||||
parentSubstitutor,
|
actualContainingClass,
|
||||||
expectContainingClass,
|
context
|
||||||
actualContainingClass
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
is FirClassLikeSymbol<*> -> {
|
|
||||||
val expectClassSymbol = useSiteSession.dependenciesSymbolProvider
|
|
||||||
.getClassLikeSymbolByClassId(actualSymbol.classId) as? FirRegularClassSymbol ?: return null
|
|
||||||
val compatibility = areCompatibleClassifiers(expectClassSymbol, actualSymbol, useSiteSession, scopeSession)
|
|
||||||
mapOf(compatibility to listOf(expectClassSymbol))
|
|
||||||
}
|
|
||||||
else -> null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun areCompatibleClassifiers(
|
|
||||||
expectClassSymbol: FirRegularClassSymbol,
|
|
||||||
actualClassLikeSymbol: FirClassLikeSymbol<*>,
|
|
||||||
actualSession: FirSession,
|
|
||||||
scopeSession: ScopeSession
|
|
||||||
): ExpectActualCompatibility<FirBasedSymbol<*>> {
|
|
||||||
// Can't check FQ names here because nested expected class may be implemented via actual typealias's expansion with the other FQ name
|
|
||||||
assert(expectClassSymbol.classId.shortClassName == actualClassLikeSymbol.classId.shortClassName) {
|
|
||||||
"This function should be invoked only for declarations with the same name: $expectClassSymbol, $actualClassLikeSymbol"
|
|
||||||
}
|
|
||||||
|
|
||||||
val actualClass = when (actualClassLikeSymbol) {
|
|
||||||
is FirRegularClassSymbol -> actualClassLikeSymbol
|
|
||||||
is FirTypeAliasSymbol -> actualClassLikeSymbol.resolvedExpandedTypeRef.coneType.fullyExpandedType(actualSession)
|
|
||||||
.toSymbol(actualSession) as? FirRegularClassSymbol
|
|
||||||
?: return ExpectActualCompatibility.Compatible // do not report extra error on erroneous typealias
|
|
||||||
else -> throw IllegalArgumentException("Incorrect actual classifier for $expectClassSymbol: $actualClassLikeSymbol")
|
|
||||||
}
|
|
||||||
|
|
||||||
if (expectClassSymbol.classKind != actualClass.classKind) return ExpectActualCompatibility.Incompatible.ClassKind
|
|
||||||
|
|
||||||
if (!equalBy(expectClassSymbol, actualClass) { listOf(it.isCompanion, it.isInner, it.isInline /*|| it.isValue*/) }) {
|
|
||||||
return ExpectActualCompatibility.Incompatible.ClassModifiers
|
|
||||||
}
|
|
||||||
if (expectClassSymbol.isFun && !actualClass.isFun) {
|
|
||||||
return ExpectActualCompatibility.Incompatible.FunInterfaceModifier
|
|
||||||
}
|
|
||||||
|
|
||||||
val expectTypeParameterSymbols = expectClassSymbol.typeParameterSymbols
|
|
||||||
val actualTypeParameterSymbols = actualClass.typeParameterSymbols
|
|
||||||
if (expectTypeParameterSymbols.size != actualTypeParameterSymbols.size) {
|
|
||||||
return ExpectActualCompatibility.Incompatible.TypeParameterCount
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!areCompatibleModalities(expectClassSymbol.modality, actualClass.modality)) {
|
|
||||||
return ExpectActualCompatibility.Incompatible.Modality
|
|
||||||
}
|
|
||||||
|
|
||||||
if (expectClassSymbol.visibility != actualClass.visibility) {
|
|
||||||
return ExpectActualCompatibility.Incompatible.Visibility
|
|
||||||
}
|
|
||||||
|
|
||||||
val substitutor = createExpectActualTypeParameterSubstitutor(expectTypeParameterSymbols, actualTypeParameterSymbols, actualSession)
|
|
||||||
|
|
||||||
areCompatibleTypeParameters(expectTypeParameterSymbols, actualTypeParameterSymbols, actualSession, substitutor).let {
|
|
||||||
if (it != ExpectActualCompatibility.Compatible) {
|
|
||||||
return it
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Subtract kotlin.Any from supertypes because it's implicitly added if no explicit supertype is specified,
|
|
||||||
// and not added if an explicit supertype _is_ specified
|
|
||||||
val expectSupertypes = expectClassSymbol.resolvedSuperTypes.filterNot { it.classId == actualSession.builtinTypes.anyType.id }
|
|
||||||
val actualSupertypes = actualClass.resolvedSuperTypes.filterNot { it.classId == actualSession.builtinTypes.anyType.id }
|
|
||||||
if (
|
|
||||||
expectSupertypes.map(substitutor::substituteOrSelf).any { expectSupertype ->
|
|
||||||
actualSupertypes.none { actualSupertype ->
|
|
||||||
areCompatibleExpectActualTypes(expectSupertype, actualSupertype, actualSession)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
) {
|
|
||||||
return ExpectActualCompatibility.Incompatible.Supertypes
|
|
||||||
}
|
|
||||||
|
|
||||||
areCompatibleClassScopes(expectClassSymbol, actualClass, actualSession, scopeSession, substitutor).let {
|
|
||||||
if (it != ExpectActualCompatibility.Compatible) {
|
|
||||||
return it
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ExpectActualCompatibility.Compatible
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun areCompatibleClassScopes(
|
|
||||||
expectClassSymbol: FirRegularClassSymbol,
|
|
||||||
actualClassSymbol: FirRegularClassSymbol,
|
|
||||||
actualSession: FirSession,
|
|
||||||
scopeSession: ScopeSession,
|
|
||||||
substitutor: ConeSubstitutor
|
|
||||||
): ExpectActualCompatibility<FirBasedSymbol<*>> {
|
|
||||||
val unfulfilled =
|
|
||||||
mutableListOf<Pair<FirBasedSymbol<*>, Map<ExpectActualCompatibility.Incompatible<FirBasedSymbol<*>>, MutableCollection<FirBasedSymbol<*>>>>>()
|
|
||||||
|
|
||||||
val allActualMembers = actualClassSymbol.getMembers(scopeSession, actualSession)
|
|
||||||
val actualMembersByName = allActualMembers.groupBy { it.name }
|
|
||||||
val actualConstructors = allActualMembers.filterIsInstance<FirConstructorSymbol>()
|
|
||||||
|
|
||||||
outer@ for (expectMember in expectClassSymbol.getMembers(scopeSession)) {
|
|
||||||
// if (expectMember is CallableMemberDescriptor && !expectMember.kind.isReal) continue
|
|
||||||
|
|
||||||
// Skip non-expect declarations like equals, hashCode, toString and any inherited declarations from non-expect super types.
|
|
||||||
if (expectMember is FirCallableSymbol && !expectMember.isExpect) continue
|
|
||||||
|
|
||||||
val actualMembers = when (expectMember) {
|
|
||||||
is FirConstructorSymbol -> actualConstructors
|
|
||||||
else -> actualMembersByName[expectMember.name]?.filter { actualMember ->
|
|
||||||
expectMember is FirRegularClassSymbol && actualMember is FirRegularClassSymbol ||
|
|
||||||
expectMember is FirCallableSymbol<*> && actualMember is FirCallableSymbol<*>
|
|
||||||
}.orEmpty()
|
|
||||||
}
|
|
||||||
|
|
||||||
val mapping = actualMembers.keysToMap { actualMember ->
|
|
||||||
when (expectMember) {
|
|
||||||
is FirCallableSymbol<*> ->
|
|
||||||
areCompatibleCallables(
|
|
||||||
expectMember,
|
|
||||||
actualMember as FirCallableSymbol<*>,
|
|
||||||
actualSession,
|
|
||||||
substitutor,
|
|
||||||
expectClassSymbol,
|
|
||||||
actualClassSymbol
|
|
||||||
)
|
)
|
||||||
is FirRegularClassSymbol ->
|
}
|
||||||
areCompatibleClassifiers(expectMember, actualMember as FirRegularClassSymbol, actualSession, scopeSession)
|
|
||||||
else -> throw UnsupportedOperationException("Unsupported declaration: $expectMember ($actualMembers)")
|
|
||||||
}
|
}
|
||||||
}
|
is FirClassLikeSymbol<*> -> {
|
||||||
if (mapping.values.any { it == ExpectActualCompatibility.Compatible }) continue
|
val expectClassSymbol = useSiteSession.dependenciesSymbolProvider
|
||||||
|
.getClassLikeSymbolByClassId(actualSymbol.classId) as? FirRegularClassSymbol ?: return null
|
||||||
val incompatibilityMap =
|
val compatibility = AbstractExpectActualCompatibilityChecker.areCompatibleClassifiers(expectClassSymbol, actualSymbol, context)
|
||||||
mutableMapOf<ExpectActualCompatibility.Incompatible<FirBasedSymbol<*>>, MutableCollection<FirBasedSymbol<*>>>()
|
mapOf(compatibility to listOf(expectClassSymbol))
|
||||||
for ((declaration, compatibility) in mapping) {
|
|
||||||
when (compatibility) {
|
|
||||||
ExpectActualCompatibility.Compatible -> continue@outer
|
|
||||||
is ExpectActualCompatibility.Incompatible -> incompatibilityMap.getOrPut(compatibility) { SmartList() }.add(declaration)
|
|
||||||
}
|
}
|
||||||
|
else -> null
|
||||||
}
|
}
|
||||||
|
return result
|
||||||
unfulfilled.add(expectMember to incompatibilityMap)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (expectClassSymbol.classKind == ClassKind.ENUM_CLASS) {
|
|
||||||
val expectEntries = expectClassSymbol.fir.collectEnumEntries().map { it.name }
|
|
||||||
val actualEntries = actualClassSymbol.fir.collectEnumEntries().map { it.name }
|
|
||||||
|
|
||||||
if (!actualEntries.containsAll(expectEntries)) {
|
|
||||||
return ExpectActualCompatibility.Incompatible.EnumEntries
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: check static scope?
|
|
||||||
|
|
||||||
if (unfulfilled.isEmpty()) return ExpectActualCompatibility.Compatible
|
|
||||||
|
|
||||||
return ExpectActualCompatibility.Incompatible.ClassScopes(unfulfilled)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun areCompatibleCallables(
|
|
||||||
expectDeclaration: FirCallableSymbol<*>,
|
|
||||||
actualDeclaration: FirCallableSymbol<*>,
|
|
||||||
actualSession: FirSession,
|
|
||||||
parentSubstitutor: ConeSubstitutor?,
|
|
||||||
expectContainingClass: FirRegularClassSymbol?,
|
|
||||||
actualContainingClass: FirRegularClassSymbol?,
|
|
||||||
): ExpectActualCompatibility<FirBasedSymbol<*>> {
|
|
||||||
assert(
|
|
||||||
(expectDeclaration is FirConstructorSymbol && actualDeclaration is FirConstructorSymbol) ||
|
|
||||||
expectDeclaration.callableId.callableName == actualDeclaration.callableId.callableName
|
|
||||||
) {
|
|
||||||
"This function should be invoked only for declarations with the same name: $expectDeclaration, $actualDeclaration"
|
|
||||||
}
|
|
||||||
assert((expectDeclaration.dispatchReceiverType == null) == (actualDeclaration.dispatchReceiverType == null)) {
|
|
||||||
"This function should be invoked only for declarations in the same kind of container (both members or both top level): $expectDeclaration, $actualDeclaration"
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
expectDeclaration is FirConstructorSymbol &&
|
|
||||||
actualDeclaration is FirConstructorSymbol &&
|
|
||||||
expectContainingClass?.classKind == ClassKind.ENUM_CLASS &&
|
|
||||||
actualContainingClass?.classKind == ClassKind.ENUM_CLASS
|
|
||||||
) {
|
|
||||||
return ExpectActualCompatibility.Compatible
|
|
||||||
}
|
|
||||||
|
|
||||||
if (expectDeclaration is FirNamedFunctionSymbol != actualDeclaration is FirNamedFunctionSymbol) {
|
|
||||||
return ExpectActualCompatibility.Incompatible.CallableKind
|
|
||||||
}
|
|
||||||
|
|
||||||
val expectedReceiverType = expectDeclaration.resolvedReceiverTypeRef
|
|
||||||
val actualReceiverType = actualDeclaration.resolvedReceiverTypeRef
|
|
||||||
if ((expectedReceiverType != null) != (actualReceiverType != null)) {
|
|
||||||
return ExpectActualCompatibility.Incompatible.ParameterShape
|
|
||||||
}
|
|
||||||
|
|
||||||
val expectedValueParameters = expectDeclaration.valueParameterSymbols
|
|
||||||
val actualValueParameters = actualDeclaration.valueParameterSymbols
|
|
||||||
if (!valueParametersCountCompatible(expectDeclaration, actualDeclaration, expectedValueParameters, actualValueParameters)) {
|
|
||||||
return ExpectActualCompatibility.Incompatible.ParameterCount
|
|
||||||
}
|
|
||||||
|
|
||||||
val expectedTypeParameters = expectDeclaration.typeParameterSymbols
|
|
||||||
val actualTypeParameters = actualDeclaration.typeParameterSymbols
|
|
||||||
if (expectedTypeParameters.size != actualTypeParameters.size) {
|
|
||||||
return ExpectActualCompatibility.Incompatible.TypeParameterCount
|
|
||||||
}
|
|
||||||
|
|
||||||
val substitutor = createExpectActualTypeParameterSubstitutor(
|
|
||||||
expectedTypeParameters,
|
|
||||||
actualTypeParameters,
|
|
||||||
actualSession,
|
|
||||||
parentSubstitutor,
|
|
||||||
)
|
|
||||||
|
|
||||||
if (
|
|
||||||
!areCompatibleTypeLists(
|
|
||||||
expectedValueParameters.toTypeList(substitutor),
|
|
||||||
actualValueParameters.toTypeList(ConeSubstitutor.Empty),
|
|
||||||
actualSession
|
|
||||||
) ||
|
|
||||||
!areCompatibleExpectActualTypes(
|
|
||||||
expectedReceiverType?.coneType?.let { substitutor.substituteOrSelf(it) },
|
|
||||||
actualReceiverType?.coneType,
|
|
||||||
actualSession
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
return ExpectActualCompatibility.Incompatible.ParameterTypes
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: implement hasStableParameterNames calculation
|
|
||||||
// if (actualDeclaration.hasStableParameterNames() && !equalsBy(expectedValueParameters, actualValueParameters, ValueParameterDescriptor::getName)) return Incompatible.ParameterNames
|
|
||||||
|
|
||||||
if (!equalsBy(expectedTypeParameters, actualTypeParameters) { it.name }) {
|
|
||||||
return ExpectActualCompatibility.Incompatible.TypeParameterNames
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
!areCompatibleModalities(
|
|
||||||
expectDeclaration.modality,
|
|
||||||
actualDeclaration.modality,
|
|
||||||
expectContainingClass?.modality,
|
|
||||||
actualContainingClass?.modality
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
if (expectDeclaration.dispatchReceiverType?.isAny != true) {
|
|
||||||
return ExpectActualCompatibility.Incompatible.Modality
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!areDeclarationsWithCompatibleVisibilities(expectDeclaration.resolvedStatus, actualDeclaration.resolvedStatus)) {
|
|
||||||
return ExpectActualCompatibility.Incompatible.Visibility
|
|
||||||
}
|
|
||||||
|
|
||||||
areCompatibleTypeParameters(expectedTypeParameters, actualTypeParameters, actualSession, substitutor).let {
|
|
||||||
if (it != ExpectActualCompatibility.Compatible) {
|
|
||||||
return it
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!equalsBy(expectedValueParameters, actualValueParameters) { it.isVararg }) {
|
|
||||||
return ExpectActualCompatibility.Incompatible.ValueParameterVararg
|
|
||||||
}
|
|
||||||
|
|
||||||
// Adding noinline/crossinline to parameters is disallowed, except if the expected declaration was not inline at all
|
|
||||||
if (expectDeclaration is FirNamedFunctionSymbol && expectDeclaration.isInline) {
|
|
||||||
if (expectedValueParameters.indices.any { i -> !expectedValueParameters[i].isNoinline && actualValueParameters[i].isNoinline }) {
|
|
||||||
return ExpectActualCompatibility.Incompatible.ValueParameterNoinline
|
|
||||||
}
|
|
||||||
if (expectedValueParameters.indices.any { i -> !expectedValueParameters[i].isCrossinline && actualValueParameters[i].isCrossinline }) {
|
|
||||||
return ExpectActualCompatibility.Incompatible.ValueParameterCrossinline
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
when {
|
|
||||||
expectDeclaration is FirNamedFunctionSymbol && actualDeclaration is FirNamedFunctionSymbol -> areCompatibleFunctions(
|
|
||||||
expectDeclaration,
|
|
||||||
actualDeclaration
|
|
||||||
).let { if (it != ExpectActualCompatibility.Compatible) return it }
|
|
||||||
|
|
||||||
expectDeclaration is FirConstructorSymbol && actualDeclaration is FirConstructorSymbol -> areCompatibleFunctions(
|
|
||||||
expectDeclaration,
|
|
||||||
actualDeclaration
|
|
||||||
).let { if (it != ExpectActualCompatibility.Compatible) return it }
|
|
||||||
|
|
||||||
expectDeclaration is FirPropertySymbol && actualDeclaration is FirPropertySymbol -> areCompatibleProperties(
|
|
||||||
expectDeclaration,
|
|
||||||
actualDeclaration
|
|
||||||
).let { if (it != ExpectActualCompatibility.Compatible) return it }
|
|
||||||
|
|
||||||
else -> throw AssertionError("Unsupported declarations: $expectDeclaration, $actualDeclaration")
|
|
||||||
}
|
|
||||||
|
|
||||||
return ExpectActualCompatibility.Compatible
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun valueParametersCountCompatible(
|
|
||||||
expectDeclaration: FirCallableSymbol<*>,
|
|
||||||
actualDeclaration: FirCallableSymbol<*>,
|
|
||||||
expectValueParameters: List<FirValueParameterSymbol>,
|
|
||||||
actualValueParameters: List<FirValueParameterSymbol>
|
|
||||||
): Boolean {
|
|
||||||
if (expectValueParameters.size == actualValueParameters.size) return true
|
|
||||||
|
|
||||||
return if (
|
|
||||||
expectDeclaration.isAnnotationConstructor(expectDeclaration.moduleData.session) &&
|
|
||||||
actualDeclaration.isAnnotationConstructor(actualDeclaration.moduleData.session)
|
|
||||||
) {
|
|
||||||
expectValueParameters.isEmpty() && actualValueParameters.all { it.hasDefaultValue }
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun areCompatibleTypeLists(
|
|
||||||
expectedTypes: List<ConeKotlinType?>,
|
|
||||||
actualTypes: List<ConeKotlinType?>,
|
|
||||||
actualSession: FirSession
|
|
||||||
): Boolean {
|
|
||||||
for (i in expectedTypes.indices) {
|
|
||||||
if (!areCompatibleExpectActualTypes(expectedTypes[i], actualTypes[i], actualSession)) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun areCompatibleModalities(
|
|
||||||
expectModality: Modality?,
|
|
||||||
actualModality: Modality?,
|
|
||||||
expectContainingClassModality: Modality? = null,
|
|
||||||
actualContainingClassModality: Modality? = null
|
|
||||||
): Boolean {
|
|
||||||
val expectEffectiveModality = effectiveModality(expectModality, expectContainingClassModality)
|
|
||||||
val actualEffectiveModality = effectiveModality(actualModality, actualContainingClassModality)
|
|
||||||
|
|
||||||
val result = actualEffectiveModality in compatibleModalityMap.getValue(expectEffectiveModality)
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If containing class is final then all declarations in it effectively final
|
|
||||||
*/
|
|
||||||
private fun effectiveModality(declarationModality: Modality?, containingClassModality: Modality?): Modality? {
|
|
||||||
return when (containingClassModality) {
|
|
||||||
FINAL -> FINAL
|
|
||||||
else -> declarationModality
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Key is expect modality, value is a set of compatible actual modalities
|
|
||||||
*/
|
|
||||||
private val compatibleModalityMap: EnumMap<Modality, EnumSet<Modality>> = enumMapOf(
|
|
||||||
ABSTRACT to enumSetOf(ABSTRACT, OPEN),
|
|
||||||
OPEN to enumSetOf(OPEN),
|
|
||||||
FINAL to enumSetOf(ABSTRACT, OPEN, FINAL),
|
|
||||||
SEALED to enumSetOf(SEALED),
|
|
||||||
)
|
|
||||||
|
|
||||||
private fun areDeclarationsWithCompatibleVisibilities(
|
|
||||||
expectStatus: FirDeclarationStatus,
|
|
||||||
actualStatus: FirDeclarationStatus
|
|
||||||
): Boolean {
|
|
||||||
val compare = Visibilities.compare(expectStatus.visibility, actualStatus.visibility)
|
|
||||||
return if (expectStatus.modality != FINAL) {
|
|
||||||
// For overridable declarations visibility should match precisely, see KT-19664
|
|
||||||
compare == 0
|
|
||||||
} else {
|
|
||||||
// For non-overridable declarations actuals are allowed to have more permissive visibility
|
|
||||||
compare != null && compare <= 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun areCompatibleTypeParameters(
|
|
||||||
expectTypeParameterSymbols: List<FirTypeParameterSymbol>,
|
|
||||||
actualTypeParameterSymbols: List<FirTypeParameterSymbol>,
|
|
||||||
actualSession: FirSession,
|
|
||||||
substitutor: ConeSubstitutor
|
|
||||||
): ExpectActualCompatibility<FirBasedSymbol<*>> {
|
|
||||||
for (i in expectTypeParameterSymbols.indices) {
|
|
||||||
val expectBounds = expectTypeParameterSymbols[i].resolvedBounds.map { it.coneType }
|
|
||||||
val actualBounds = actualTypeParameterSymbols[i].resolvedBounds.map { it.coneType }
|
|
||||||
if (
|
|
||||||
expectBounds.size != actualBounds.size ||
|
|
||||||
!areCompatibleTypeLists(expectBounds.map(substitutor::substituteOrSelf), actualBounds, actualSession)
|
|
||||||
) {
|
|
||||||
return ExpectActualCompatibility.Incompatible.TypeParameterUpperBounds
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!equalsBy(expectTypeParameterSymbols, actualTypeParameterSymbols) { it.variance }) {
|
|
||||||
return ExpectActualCompatibility.Incompatible.TypeParameterVariance
|
|
||||||
}
|
|
||||||
|
|
||||||
// Removing "reified" from an expected function's type parameter is fine
|
|
||||||
if (
|
|
||||||
expectTypeParameterSymbols.indices.any { i ->
|
|
||||||
!expectTypeParameterSymbols[i].isReified && actualTypeParameterSymbols[i].isReified
|
|
||||||
}
|
|
||||||
) {
|
|
||||||
return ExpectActualCompatibility.Incompatible.TypeParameterReified
|
|
||||||
}
|
|
||||||
|
|
||||||
return ExpectActualCompatibility.Compatible
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun areCompatibleFunctions(
|
|
||||||
expectFunction: FirCallableSymbol<*>,
|
|
||||||
actualFunction: FirCallableSymbol<*>
|
|
||||||
): ExpectActualCompatibility<FirBasedSymbol<*>> {
|
|
||||||
if (!equalBy(expectFunction, actualFunction) { f -> f.isSuspend }) {
|
|
||||||
return ExpectActualCompatibility.Incompatible.FunctionModifiersDifferent
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
expectFunction.isExternal && !actualFunction.isExternal ||
|
|
||||||
expectFunction.isInfix && !actualFunction.isInfix ||
|
|
||||||
expectFunction.isInline && !actualFunction.isInline ||
|
|
||||||
expectFunction.isOperator && !actualFunction.isOperator ||
|
|
||||||
expectFunction.isTailRec && !actualFunction.isTailRec
|
|
||||||
) {
|
|
||||||
return ExpectActualCompatibility.Incompatible.FunctionModifiersNotSubset
|
|
||||||
}
|
|
||||||
|
|
||||||
return ExpectActualCompatibility.Compatible
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun areCompatibleProperties(
|
|
||||||
expected: FirPropertySymbol,
|
|
||||||
actual: FirPropertySymbol,
|
|
||||||
): ExpectActualCompatibility<FirBasedSymbol<*>> {
|
|
||||||
return when {
|
|
||||||
!equalBy(expected, actual) { p -> p.isVar } -> ExpectActualCompatibility.Incompatible.PropertyKind
|
|
||||||
!equalBy(expected, actual) { p -> p.isLateInit } -> ExpectActualCompatibility.Incompatible.PropertyLateinitModifier
|
|
||||||
expected.isConst && !actual.isConst -> ExpectActualCompatibility.Incompatible.PropertyConstModifier
|
|
||||||
!arePropertySettersWithCompatibleVisibilities(expected, actual) -> ExpectActualCompatibility.Incompatible.PropertySetterVisibility
|
|
||||||
else -> ExpectActualCompatibility.Compatible
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun arePropertySettersWithCompatibleVisibilities(
|
|
||||||
expected: FirPropertySymbol,
|
|
||||||
actual: FirPropertySymbol,
|
|
||||||
): Boolean {
|
|
||||||
val expectedSetterStatus = expected.setterSymbol?.resolvedStatus
|
|
||||||
val actualSetterStatus = actual.setterSymbol?.resolvedStatus
|
|
||||||
if (expectedSetterStatus == null || actualSetterStatus == null) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return areDeclarationsWithCompatibleVisibilities(expectedSetterStatus, actualSetterStatus)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------- Utils ----------------------------------------
|
|
||||||
|
|
||||||
private fun List<FirValueParameterSymbol>.toTypeList(substitutor: ConeSubstitutor): List<ConeKotlinType> {
|
|
||||||
return this.map { substitutor.substituteOrSelf(it.resolvedReturnTypeRef.coneType) }
|
|
||||||
}
|
|
||||||
|
|
||||||
private val FirCallableSymbol<*>.valueParameterSymbols: List<FirValueParameterSymbol>
|
|
||||||
get() = (this as? FirFunctionSymbol<*>)?.valueParameterSymbols ?: emptyList()
|
|
||||||
|
|
||||||
private inline fun <T, K> equalsBy(first: List<T>, second: List<T>, selector: (T) -> K): Boolean {
|
|
||||||
for (i in first.indices) {
|
|
||||||
if (selector(first[i]) != selector(second[i])) return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
private inline fun <T, K> equalBy(first: T, second: T, selector: (T) -> K): Boolean =
|
|
||||||
selector(first) == selector(second)
|
|
||||||
|
|
||||||
private fun FirClassSymbol<*>.getMembers(
|
|
||||||
scopeSession: ScopeSession,
|
|
||||||
session: FirSession = moduleData.session
|
|
||||||
): Collection<FirBasedSymbol<*>> {
|
|
||||||
val scope = defaultType()
|
|
||||||
.scope(useSiteSession = session, scopeSession, FakeOverrideTypeCalculator.DoNothing, requiredPhase = FirResolvePhase.STATUS)
|
|
||||||
?: return emptyList()
|
|
||||||
return mutableListOf<FirBasedSymbol<*>>().apply {
|
|
||||||
for (name in scope.getCallableNames()) {
|
|
||||||
scope.getMembersTo(this, name)
|
|
||||||
}
|
|
||||||
for (name in declarationSymbols.mapNotNull { (it as? FirRegularClassSymbol)?.classId?.shortClassName }) {
|
|
||||||
addIfNotNull(scope.getSingleClassifier(name) as? FirRegularClassSymbol)
|
|
||||||
}
|
|
||||||
getConstructorsTo(this, scope)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun FirClassSymbol<*>.getConstructors(
|
|
||||||
scopeSession: ScopeSession,
|
|
||||||
session: FirSession = moduleData.session
|
|
||||||
): Collection<FirConstructorSymbol> = mutableListOf<FirConstructorSymbol>().apply {
|
|
||||||
getConstructorsTo(
|
|
||||||
this,
|
|
||||||
unsubstitutedScope(
|
|
||||||
session,
|
|
||||||
scopeSession,
|
|
||||||
withForcedTypeCalculator = false,
|
|
||||||
memberRequiredPhase = FirResolvePhase.STATUS,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getConstructorsTo(destination: MutableList<in FirConstructorSymbol>, scope: FirTypeScope) {
|
|
||||||
scope.getDeclaredConstructors().mapTo(destination) { it }
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun FirClassSymbol<*>.getMembers(name: Name, scopeSession: ScopeSession): Collection<FirCallableSymbol<*>> {
|
|
||||||
val scope = defaultType()
|
|
||||||
.scope(
|
|
||||||
useSiteSession = moduleData.session,
|
|
||||||
scopeSession,
|
|
||||||
FakeOverrideTypeCalculator.DoNothing,
|
|
||||||
requiredPhase = FirResolvePhase.STATUS
|
|
||||||
)
|
|
||||||
?: return emptyList()
|
|
||||||
return mutableListOf<FirCallableSymbol<*>>().apply {
|
|
||||||
scope.getMembersTo(this, name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun FirTypeScope.getMembersTo(
|
|
||||||
destination: MutableList<in FirCallableSymbol<*>>,
|
|
||||||
name: Name,
|
|
||||||
) {
|
|
||||||
processFunctionsByName(name) { destination.add(it) }
|
|
||||||
processPropertiesByName(name) { destination.add(it) }
|
|
||||||
}
|
|
||||||
|
|
||||||
private val FirBasedSymbol<*>.name: Name
|
|
||||||
get() = when (this) {
|
|
||||||
is FirCallableSymbol<*> -> name
|
|
||||||
is FirRegularClassSymbol -> classId.shortClassName
|
|
||||||
else -> error("Should not be here")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,9 +17,10 @@ import org.jetbrains.kotlin.fir.expressions.arguments
|
|||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirBackingFieldSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirBackingFieldSymbol
|
||||||
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
|
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
|
||||||
import org.jetbrains.kotlin.fir.types.coneType
|
import org.jetbrains.kotlin.fir.types.coneType
|
||||||
|
import org.jetbrains.kotlin.mpp.DeclarationSymbolMarker
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
|
|
||||||
abstract class FirBasedSymbol<E : FirDeclaration> {
|
abstract class FirBasedSymbol<E : FirDeclaration> : DeclarationSymbolMarker {
|
||||||
private var _fir: E? = null
|
private var _fir: E? = null
|
||||||
|
|
||||||
@SymbolInternals
|
@SymbolInternals
|
||||||
|
|||||||
@@ -10,10 +10,11 @@ import org.jetbrains.kotlin.fir.declarations.*
|
|||||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
|
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
|
||||||
import org.jetbrains.kotlin.fir.types.*
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
|
import org.jetbrains.kotlin.mpp.CallableSymbolMarker
|
||||||
import org.jetbrains.kotlin.name.CallableId
|
import org.jetbrains.kotlin.name.CallableId
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
|
||||||
abstract class FirCallableSymbol<D : FirCallableDeclaration> : FirBasedSymbol<D>() {
|
abstract class FirCallableSymbol<D : FirCallableDeclaration> : FirBasedSymbol<D>(), CallableSymbolMarker {
|
||||||
abstract val callableId: CallableId
|
abstract val callableId: CallableId
|
||||||
|
|
||||||
val resolvedReturnTypeRef: FirResolvedTypeRef
|
val resolvedReturnTypeRef: FirResolvedTypeRef
|
||||||
|
|||||||
@@ -15,13 +15,16 @@ import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
|||||||
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
||||||
import org.jetbrains.kotlin.fir.types.coneType
|
import org.jetbrains.kotlin.fir.types.coneType
|
||||||
import org.jetbrains.kotlin.fir.types.toLookupTag
|
import org.jetbrains.kotlin.fir.types.toLookupTag
|
||||||
|
import org.jetbrains.kotlin.mpp.ClassLikeSymbolMarker
|
||||||
|
import org.jetbrains.kotlin.mpp.RegularClassSymbolMarker
|
||||||
|
import org.jetbrains.kotlin.mpp.TypeAliasSymbolMarker
|
||||||
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.SpecialNames
|
import org.jetbrains.kotlin.name.SpecialNames
|
||||||
|
|
||||||
sealed class FirClassLikeSymbol<D : FirClassLikeDeclaration>(
|
sealed class FirClassLikeSymbol<D : FirClassLikeDeclaration>(
|
||||||
val classId: ClassId,
|
val classId: ClassId,
|
||||||
) : FirClassifierSymbol<D>() {
|
) : FirClassifierSymbol<D>(), ClassLikeSymbolMarker {
|
||||||
abstract override fun toLookupTag(): ConeClassLikeLookupTag
|
abstract override fun toLookupTag(): ConeClassLikeLookupTag
|
||||||
|
|
||||||
val name get() = classId.shortClassName
|
val name get() = classId.shortClassName
|
||||||
@@ -68,7 +71,7 @@ sealed class FirClassSymbol<C : FirClass>(classId: ClassId) : FirClassLikeSymbol
|
|||||||
get() = fir.classKind
|
get() = fir.classKind
|
||||||
}
|
}
|
||||||
|
|
||||||
class FirRegularClassSymbol(classId: ClassId) : FirClassSymbol<FirRegularClass>(classId) {
|
class FirRegularClassSymbol(classId: ClassId) : FirClassSymbol<FirRegularClass>(classId), RegularClassSymbolMarker {
|
||||||
val companionObjectSymbol: FirRegularClassSymbol?
|
val companionObjectSymbol: FirRegularClassSymbol?
|
||||||
get() = fir.companionObjectSymbol
|
get() = fir.companionObjectSymbol
|
||||||
|
|
||||||
@@ -84,7 +87,7 @@ val ANONYMOUS_CLASS_ID = ClassId(FqName.ROOT, FqName.topLevel(SpecialNames.ANONY
|
|||||||
|
|
||||||
class FirAnonymousObjectSymbol : FirClassSymbol<FirAnonymousObject>(ANONYMOUS_CLASS_ID)
|
class FirAnonymousObjectSymbol : FirClassSymbol<FirAnonymousObject>(ANONYMOUS_CLASS_ID)
|
||||||
|
|
||||||
class FirTypeAliasSymbol(classId: ClassId) : FirClassLikeSymbol<FirTypeAlias>(classId) {
|
class FirTypeAliasSymbol(classId: ClassId) : FirClassLikeSymbol<FirTypeAlias>(classId), TypeAliasSymbolMarker {
|
||||||
override fun toLookupTag(): ConeClassLikeLookupTag = classId.toLookupTag()
|
override fun toLookupTag(): ConeClassLikeLookupTag = classId.toLookupTag()
|
||||||
|
|
||||||
val resolvedExpandedTypeRef: FirResolvedTypeRef
|
val resolvedExpandedTypeRef: FirResolvedTypeRef
|
||||||
|
|||||||
@@ -8,7 +8,8 @@ package org.jetbrains.kotlin.fir.symbols.impl
|
|||||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||||
import org.jetbrains.kotlin.fir.symbols.ConeClassifierLookupTag
|
import org.jetbrains.kotlin.fir.symbols.ConeClassifierLookupTag
|
||||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||||
|
import org.jetbrains.kotlin.mpp.ClassifierSymbolMarker
|
||||||
|
|
||||||
sealed class FirClassifierSymbol<E : FirDeclaration> : FirBasedSymbol<E>() {
|
sealed class FirClassifierSymbol<E : FirDeclaration> : FirBasedSymbol<E>(), ClassifierSymbolMarker {
|
||||||
abstract fun toLookupTag(): ConeClassifierLookupTag
|
abstract fun toLookupTag(): ConeClassifierLookupTag
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,9 +12,12 @@ import org.jetbrains.kotlin.fir.expressions.FirDelegatedConstructorCall
|
|||||||
import org.jetbrains.kotlin.fir.references.FirControlFlowGraphReference
|
import org.jetbrains.kotlin.fir.references.FirControlFlowGraphReference
|
||||||
import org.jetbrains.kotlin.fir.references.toResolvedConstructorSymbol
|
import org.jetbrains.kotlin.fir.references.toResolvedConstructorSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
|
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
|
||||||
|
import org.jetbrains.kotlin.mpp.ConstructorSymbolMarker
|
||||||
|
import org.jetbrains.kotlin.mpp.FunctionSymbolMarker
|
||||||
|
import org.jetbrains.kotlin.mpp.SimpleFunctionSymbolMarker
|
||||||
import org.jetbrains.kotlin.name.*
|
import org.jetbrains.kotlin.name.*
|
||||||
|
|
||||||
sealed class FirFunctionSymbol<D : FirFunction>(override val callableId: CallableId) : FirCallableSymbol<D>() {
|
sealed class FirFunctionSymbol<D : FirFunction>(override val callableId: CallableId) : FirCallableSymbol<D>(), FunctionSymbolMarker {
|
||||||
val valueParameterSymbols: List<FirValueParameterSymbol>
|
val valueParameterSymbols: List<FirValueParameterSymbol>
|
||||||
get() = fir.valueParameters.map { it.symbol }
|
get() = fir.valueParameters.map { it.symbol }
|
||||||
|
|
||||||
@@ -37,7 +40,7 @@ sealed class FirFunctionSymbol<D : FirFunction>(override val callableId: Callabl
|
|||||||
|
|
||||||
// ------------------------ named ------------------------
|
// ------------------------ named ------------------------
|
||||||
|
|
||||||
open class FirNamedFunctionSymbol(callableId: CallableId) : FirFunctionSymbol<FirSimpleFunction>(callableId)
|
open class FirNamedFunctionSymbol(callableId: CallableId) : FirFunctionSymbol<FirSimpleFunction>(callableId), SimpleFunctionSymbolMarker
|
||||||
|
|
||||||
interface FirIntersectionCallableSymbol {
|
interface FirIntersectionCallableSymbol {
|
||||||
val intersections: Collection<FirCallableSymbol<*>>
|
val intersections: Collection<FirCallableSymbol<*>>
|
||||||
@@ -48,7 +51,7 @@ class FirIntersectionOverrideFunctionSymbol(
|
|||||||
override val intersections: Collection<FirCallableSymbol<*>>,
|
override val intersections: Collection<FirCallableSymbol<*>>,
|
||||||
) : FirNamedFunctionSymbol(callableId), FirIntersectionCallableSymbol
|
) : FirNamedFunctionSymbol(callableId), FirIntersectionCallableSymbol
|
||||||
|
|
||||||
class FirConstructorSymbol(callableId: CallableId) : FirFunctionSymbol<FirConstructor>(callableId) {
|
class FirConstructorSymbol(callableId: CallableId) : FirFunctionSymbol<FirConstructor>(callableId), ConstructorSymbolMarker {
|
||||||
constructor(classId: ClassId) : this(classId.callableIdForConstructor())
|
constructor(classId: ClassId) : this(classId.callableIdForConstructor())
|
||||||
|
|
||||||
val isPrimary: Boolean
|
val isPrimary: Boolean
|
||||||
|
|||||||
+2
-1
@@ -11,10 +11,11 @@ import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag
|
|||||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
|
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
|
||||||
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
||||||
|
import org.jetbrains.kotlin.mpp.TypeParameterSymbolMarker
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.types.Variance
|
import org.jetbrains.kotlin.types.Variance
|
||||||
|
|
||||||
class FirTypeParameterSymbol : FirClassifierSymbol<FirTypeParameter>() {
|
class FirTypeParameterSymbol : FirClassifierSymbol<FirTypeParameter>(), TypeParameterSymbolMarker {
|
||||||
val name: Name
|
val name: Name
|
||||||
get() = fir.name
|
get() = fir.name
|
||||||
|
|
||||||
|
|||||||
@@ -11,15 +11,15 @@ import org.jetbrains.kotlin.fir.expressions.FirAnonymousObjectExpression
|
|||||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||||
import org.jetbrains.kotlin.fir.references.FirControlFlowGraphReference
|
import org.jetbrains.kotlin.fir.references.FirControlFlowGraphReference
|
||||||
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
|
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
|
||||||
|
import org.jetbrains.kotlin.mpp.PropertySymbolMarker
|
||||||
|
import org.jetbrains.kotlin.mpp.ValueParameterSymbolMarker
|
||||||
import org.jetbrains.kotlin.name.CallableId
|
import org.jetbrains.kotlin.name.CallableId
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
|
||||||
sealed class FirVariableSymbol<E : FirVariable>(override val callableId: CallableId) : FirCallableSymbol<E>()
|
sealed class FirVariableSymbol<E : FirVariable>(override val callableId: CallableId) : FirCallableSymbol<E>()
|
||||||
|
|
||||||
open class FirPropertySymbol(
|
open class FirPropertySymbol(callableId: CallableId, ) : FirVariableSymbol<FirProperty>(callableId), PropertySymbolMarker {
|
||||||
callableId: CallableId,
|
|
||||||
) : FirVariableSymbol<FirProperty>(callableId) {
|
|
||||||
// TODO: should we use this constructor for local variables?
|
// TODO: should we use this constructor for local variables?
|
||||||
constructor(name: Name) : this(CallableId(name))
|
constructor(name: Name) : this(CallableId(name))
|
||||||
|
|
||||||
@@ -108,7 +108,7 @@ class FirEnumEntrySymbol(callableId: CallableId) : FirVariableSymbol<FirEnumEntr
|
|||||||
get() = (fir.initializer as? FirAnonymousObjectExpression)?.anonymousObject?.symbol
|
get() = (fir.initializer as? FirAnonymousObjectExpression)?.anonymousObject?.symbol
|
||||||
}
|
}
|
||||||
|
|
||||||
class FirValueParameterSymbol(name: Name) : FirVariableSymbol<FirValueParameter>(CallableId(name)) {
|
class FirValueParameterSymbol(name: Name) : FirVariableSymbol<FirValueParameter>(CallableId(name)), ValueParameterSymbolMarker {
|
||||||
val hasDefaultValue: Boolean
|
val hasDefaultValue: Boolean
|
||||||
get() = fir.defaultValue != null
|
get() = fir.defaultValue != null
|
||||||
|
|
||||||
|
|||||||
+2
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.ir.generator.model
|
|||||||
import org.jetbrains.kotlin.ir.generator.config.*
|
import org.jetbrains.kotlin.ir.generator.config.*
|
||||||
import org.jetbrains.kotlin.ir.generator.elementBaseType
|
import org.jetbrains.kotlin.ir.generator.elementBaseType
|
||||||
import org.jetbrains.kotlin.ir.generator.util.*
|
import org.jetbrains.kotlin.ir.generator.util.*
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.UnsafeCastFunction
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.castAll
|
import org.jetbrains.kotlin.utils.addToStdlib.castAll
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.partitionIsInstance
|
import org.jetbrains.kotlin.utils.addToStdlib.partitionIsInstance
|
||||||
|
|
||||||
@@ -82,6 +83,7 @@ fun config2model(config: Config): Model {
|
|||||||
return Model(elements, rootElement)
|
return Model(elements, rootElement)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(UnsafeCastFunction::class)
|
||||||
private fun replaceElementRefs(config: Config, mapping: Map<ElementConfig, Element>): Element {
|
private fun replaceElementRefs(config: Config, mapping: Map<ElementConfig, Element>): Element {
|
||||||
val visited = mutableMapOf<TypeRef, TypeRef>()
|
val visited = mutableMapOf<TypeRef, TypeRef>()
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -9,7 +9,7 @@ expect class Foo {
|
|||||||
// MODULE: m2-jvm()()(m1-common)
|
// MODULE: m2-jvm()()(m1-common)
|
||||||
// FILE: jvm.kt
|
// FILE: jvm.kt
|
||||||
|
|
||||||
actual class Foo {
|
actual class <!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>Foo<!> {
|
||||||
fun bar(): String = "bar"
|
fun bar(): String = "bar"
|
||||||
fun bas(g: Int) {}
|
fun bas(g: Int) {}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user