Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.jetbrains.kotlin.fir.resolve.SupertypeUtils.kt Maven / Gradle / Ivy
/*
* Copyright 2010-2019 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
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
import org.jetbrains.kotlin.fir.resolve.transformers.createSubstitutionForSupertype
import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.scopes.FirTypeScope
import org.jetbrains.kotlin.fir.scopes.impl.FirClassSubstitutionScope
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.typeContext
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.types.model.CaptureStatus
abstract class SupertypeSupplier {
abstract fun forClass(firClass: FirClass<*>): List
abstract fun expansionForTypeAlias(typeAlias: FirTypeAlias): ConeClassLikeType?
object Default : SupertypeSupplier() {
override fun forClass(firClass: FirClass<*>) = firClass.superConeTypes
override fun expansionForTypeAlias(typeAlias: FirTypeAlias) = typeAlias.expandedConeType
}
}
fun lookupSuperTypes(
klass: FirClass<*>,
lookupInterfaces: Boolean,
deep: Boolean,
useSiteSession: FirSession,
supertypeSupplier: SupertypeSupplier = SupertypeSupplier.Default,
substituteTypes: Boolean = false
): List {
return mutableListOf().also {
klass.symbol.collectSuperTypes(it, mutableSetOf(), deep, lookupInterfaces, substituteTypes, useSiteSession, supertypeSupplier)
}
}
fun lookupSuperTypes(
symbol: FirClassifierSymbol<*>,
lookupInterfaces: Boolean,
deep: Boolean,
useSiteSession: FirSession,
supertypeSupplier: SupertypeSupplier = SupertypeSupplier.Default
): List {
return mutableListOf().also {
symbol.collectSuperTypes(it, mutableSetOf(), deep, lookupInterfaces, false, useSiteSession, supertypeSupplier)
}
}
inline fun scopeSessionKey(): ScopeSessionKey {
return object : ScopeSessionKey() {}
}
val USE_SITE = scopeSessionKey, FirTypeScope>()
data class SubstitutionScopeKey(
val type: ConeClassLikeType,
// This property is necessary. Otherwise we may have accidental matching when two classes have the same supertype
val derivedClassId: ClassId
) : ScopeSessionKey, FirClassSubstitutionScope>()
/* TODO REMOVE */
fun createSubstitution(
typeParameters: List, // TODO: or really declared?
type: ConeClassLikeType,
session: FirSession
): Map {
val capturedOrType = session.typeContext.captureFromArguments(type, CaptureStatus.FROM_EXPRESSION) ?: type
val typeArguments = (capturedOrType as ConeClassLikeType).typeArguments
return typeParameters.zip(typeArguments) { typeParameter, typeArgument ->
val typeParameterSymbol = typeParameter.symbol
typeParameterSymbol to when (typeArgument) {
is ConeKotlinTypeProjection -> {
typeArgument.type
}
else /* StarProjection */ -> {
ConeTypeIntersector.intersectTypes(
session.typeContext,
typeParameterSymbol.fir.bounds.map { it.coneType }
)
}
}
}.toMap()
}
fun ConeClassLikeType.wrapSubstitutionScopeIfNeed(
session: FirSession,
useSiteMemberScope: FirTypeScope,
declaration: FirClassLikeDeclaration<*>,
builder: ScopeSession,
derivedClass: FirRegularClass
): FirTypeScope {
if (this.typeArguments.isEmpty()) return useSiteMemberScope
return builder.getOrBuild(declaration.symbol, SubstitutionScopeKey(this, derivedClass.symbol.classId)) {
val typeParameters = (declaration as? FirTypeParameterRefsOwner)?.typeParameters.orEmpty()
val originalSubstitution = createSubstitution(typeParameters, this, session)
val platformClass = session.platformClassMapper.getCorrespondingPlatformClass(declaration)
val substitutor = if (platformClass != null) {
// This kind of substitution is necessary when method which is mapped from Java (e.g. Java Map.forEach)
// is called on an external type, like MyMap,
// to determine parameter types properly (e.g. String, String instead of K, V)
val platformTypeParameters = platformClass.typeParameters
val platformSubstitution = createSubstitution(platformTypeParameters, this, session)
substitutorByMap(originalSubstitution + platformSubstitution)
} else {
substitutorByMap(originalSubstitution)
}
FirClassSubstitutionScope(
session, useSiteMemberScope, substitutor,
dispatchReceiverTypeForSubstitutedMembers = derivedClass.defaultType(),
skipPrivateMembers = true,
)
}
}
private fun ConeClassLikeType.computePartialExpansion(
useSiteSession: FirSession,
supertypeSupplier: SupertypeSupplier
): ConeClassLikeType = fullyExpandedType(useSiteSession, supertypeSupplier::expansionForTypeAlias)
private fun FirClassifierSymbol<*>.collectSuperTypes(
list: MutableList,
visitedSymbols: MutableSet>,
deep: Boolean,
lookupInterfaces: Boolean,
substituteSuperTypes: Boolean,
useSiteSession: FirSession,
supertypeSupplier: SupertypeSupplier
) {
if (!visitedSymbols.add(this)) return
when (this) {
is FirClassSymbol<*> -> {
val superClassTypes =
supertypeSupplier.forClass(fir).mapNotNull {
it.computePartialExpansion(useSiteSession, supertypeSupplier)
.takeIf { type -> lookupInterfaces || type.isClassBasedType(useSiteSession) }
}
list += superClassTypes
if (deep)
superClassTypes.forEach {
if (it !is ConeClassErrorType) {
if (substituteSuperTypes) {
val substitutedTypes = mutableListOf()
it.lookupTag.toSymbol(useSiteSession)?.collectSuperTypes(
substitutedTypes,
visitedSymbols,
deep,
lookupInterfaces,
substituteSuperTypes,
useSiteSession,
supertypeSupplier
)
val substitutor = createSubstitutionForSupertype(it, useSiteSession)
substitutedTypes.mapTo(list) { superType -> substitutor.substituteOrSelf(superType) as ConeClassLikeType }
} else {
it.lookupTag.toSymbol(useSiteSession)?.collectSuperTypes(
list,
visitedSymbols,
deep,
lookupInterfaces,
substituteSuperTypes,
useSiteSession,
supertypeSupplier
)
}
}
}
}
is FirTypeAliasSymbol -> {
val expansion =
supertypeSupplier.expansionForTypeAlias(fir)?.computePartialExpansion(useSiteSession, supertypeSupplier) ?: return
expansion.lookupTag.toSymbol(useSiteSession)
?.collectSuperTypes(list, visitedSymbols, deep, lookupInterfaces, substituteSuperTypes, useSiteSession, supertypeSupplier)
}
else -> error("?!id:1")
}
}
private fun ConeClassLikeType?.isClassBasedType(
useSiteSession: FirSession
): Boolean {
if (this is ConeClassErrorType) return false
val symbol = this?.lookupTag?.toSymbol(useSiteSession) as? FirClassSymbol ?: return false
return when (symbol) {
is FirAnonymousObjectSymbol -> true
is FirRegularClassSymbol -> symbol.fir.classKind == ClassKind.CLASS
}
}