[FIR] Cleanup FIR modules. Part 4 (providers and resolve packages)

This commit is contained in:
Dmitriy Novozhilov
2020-06-26 14:05:12 +03:00
parent 1d90302848
commit 285b6d28af
14 changed files with 112 additions and 133 deletions
@@ -12,7 +12,5 @@ import org.jetbrains.kotlin.name.ClassId
interface FirQualifierResolver : FirSessionComponent {
fun resolveSymbolWithPrefix(parts: List<FirQualifierPart>, prefix: ClassId): FirClassifierSymbol<*>?
fun resolveSymbol(parts: List<FirQualifierPart>): FirClassifierSymbol<*>?
}
@@ -10,9 +10,9 @@ import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.symbols.impl.FirClassifierSymbol
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.types.FirUserTypeRef
interface FirTypeResolver : FirSessionComponent {
fun resolveType(typeRef: FirTypeRef, scope: FirScope): ConeKotlinType
fun resolveToSymbol(typeRef: FirTypeRef, scope: FirScope): FirClassifierSymbol<*>?
}
@@ -77,7 +77,7 @@ class PersistentImplicitReceiverStack private constructor(
return originalTypes[index]
}
// This method is only used from DFA and it's in some sense breaks persistency contracts of the data structure
// This method is only used from DFA and it's in some sense breaks persistence contracts of the data structure
// But it's ok since DFA handles everything properly yet, but still may be it should be rewritten somehow
fun replaceReceiverType(index: Int, type: ConeKotlinType) {
assert(index >= 0 && index < stack.size)
@@ -43,7 +43,6 @@ import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
inline fun <K, V, VA : V> MutableMap<K, V>.getOrPut(key: K, defaultValue: (K) -> VA, postCompute: (VA) -> Unit): V {
val value = get(key)
@@ -111,9 +110,8 @@ fun ConeClassLikeType.directExpansionType(
useSiteSession: FirSession,
expandedConeType: (FirTypeAlias) -> ConeClassLikeType? = FirTypeAlias::expandedConeType,
): ConeClassLikeType? {
val typeAlias = lookupTag
.toSymbol(useSiteSession)
?.safeAs<FirTypeAliasSymbol>()?.fir ?: return null
val typeAliasSymbol = lookupTag.toSymbol(useSiteSession) as? FirTypeAliasSymbol ?: return null
val typeAlias = typeAliasSymbol.fir
val resultType = expandedConeType(typeAlias)?.applyNullabilityFrom(this) ?: return null
@@ -143,6 +141,8 @@ private fun mapTypeAliasArguments(
val symbol = (type as? ConeTypeParameterType)?.lookupTag?.toSymbol() ?: return super.substituteArgument(projection)
val mappedProjection = typeAliasMap[symbol] ?: return super.substituteArgument(projection)
val mappedType = (mappedProjection as? ConeKotlinTypeProjection)?.type ?: return mappedProjection
@Suppress("MoveVariableDeclarationIntoWhen")
val resultingKind = mappedProjection.kind + projection.kind
return when (resultingKind) {
ProjectionKind.STAR -> ConeStarProjection
@@ -209,7 +209,7 @@ fun FirClassifierSymbol<*>.constructType(
private fun List<FirQualifierPart>.toTypeProjections(): Array<ConeTypeProjection> =
asReversed().flatMap { it.typeArguments.map { typeArgument -> typeArgument.toConeTypeProjection() } }.toTypedArray()
fun FirFunction<*>.constructFunctionalTypeRef(session: FirSession, isSuspend: Boolean = false): FirResolvedTypeRef {
fun FirFunction<*>.constructFunctionalTypeRef(isSuspend: Boolean = false): FirResolvedTypeRef {
val receiverTypeRef = when (this) {
is FirSimpleFunction -> receiverTypeRef
is FirAnonymousFunction -> receiverTypeRef
@@ -323,7 +323,6 @@ internal fun typeForQualifierByDeclaration(declaration: FirDeclaration, resultTy
}
fun <T : FirResolvable> BodyResolveComponents.typeFromCallee(access: T): FirResolvedTypeRef {
return when (val newCallee = access.calleeReference) {
is FirErrorNamedReference ->
buildErrorTypeRef {
@@ -196,7 +196,6 @@ class FirSamResolverImpl(
isVararg = false
}
resolvePhase = FirResolvePhase.BODY_RESOLVE
}
}
@@ -224,7 +223,6 @@ private fun FirRegularClass.getSingleAbstractMethodOrNull(
if (classKind != ClassKind.INTERFACE || hasMoreThenOneAbstractFunctionOrHasAbstractProperty()) return null
val samCandidateNames = computeSamCandidateNames(session)
return findSingleAbstractMethodByNames(session, scopeSession, samCandidateNames)
}
@@ -332,7 +330,6 @@ fun FirSimpleFunction.isPublicInObject(checkOnlyName: Boolean): Boolean {
}
else -> error("Unexpected method name: $name")
}
}
private fun FirValueParameter.hasTypeOf(classId: ClassId, allowNullable: Boolean): Boolean {
@@ -52,7 +52,6 @@ fun ConeKotlinType.scope(useSiteSession: FirSession, scopeSession: ScopeSession)
)
is ConeDefinitelyNotNullType -> original.scope(useSiteSession, scopeSession)
is ConeIntegerLiteralType -> {
@Suppress("USELESS_CAST") // TODO: remove once fixed: https://youtrack.jetbrains.com/issue/KT-35635
scopeSession.getOrBuild(
when {
@@ -48,10 +48,6 @@ val USE_SITE = scopeSessionKey<FirClassSymbol<*>, FirTypeScope>()
data class SubstitutionScopeKey(val type: ConeClassLikeType) : ScopeSessionKey<FirClassLikeSymbol<*>, FirClassSubstitutionScope>()
fun FirClassSymbol<*>.buildUseSiteMemberScope(useSiteSession: FirSession, builder: ScopeSession): FirScope? {
return this.fir.buildUseSiteMemberScope(useSiteSession, builder)
}
fun FirClass<*>.buildUseSiteMemberScope(useSiteSession: FirSession, builder: ScopeSession): FirScope? {
return this.unsubstitutedScope(useSiteSession, builder)
}
@@ -23,10 +23,6 @@ import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
fun ConeClassLikeLookupTagImpl.bindSymbolToLookupTag(provider: FirSymbolProvider, symbol: FirClassLikeSymbol<*>?) {
boundSymbol = Pair(provider, symbol)
}
abstract class FirSymbolProvider : FirSessionComponent {
abstract fun getClassLikeSymbolByFqName(classId: ClassId): FirClassLikeSymbol<*>?
@@ -81,4 +77,8 @@ fun FirSymbolProvider.getClassDeclaredCallableSymbols(classId: ClassId, name: Na
inline fun <reified T : AbstractFirBasedSymbol<*>> FirSymbolProvider.getSymbolByTypeRef(typeRef: FirTypeRef): T? {
val lookupTag = typeRef.coneTypeSafe<ConeLookupTagBasedType>()?.lookupTag ?: return null
return getSymbolByLookupTag(lookupTag) as? T
}
}
fun ConeClassLikeLookupTagImpl.bindSymbolToLookupTag(provider: FirSymbolProvider, symbol: FirClassLikeSymbol<*>?) {
boundSymbol = Pair(provider, symbol)
}
@@ -49,84 +49,11 @@ import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
import java.io.InputStream
class FirBuiltinSymbolProvider(val session: FirSession, val kotlinScopeProvider: KotlinScopeProvider) : FirSymbolProvider() {
private class BuiltInsPackageFragment(
stream: InputStream, val fqName: FqName, val session: FirSession,
val kotlinScopeProvider: KotlinScopeProvider,
) {
lateinit var version: BuiltInsBinaryVersion
val packageProto: ProtoBuf.PackageFragment = run {
private data class SyntheticFunctionalInterfaceSymbolKey(val kind: FunctionClassDescriptor.Kind, val arity: Int)
version = BuiltInsBinaryVersion.readFrom(stream)
if (!version.isCompatible()) {
// TODO: report a proper diagnostic
throw UnsupportedOperationException(
"Kotlin built-in definition format version is not supported: " +
"expected ${BuiltInsBinaryVersion.INSTANCE}, actual $version. " +
"Please update Kotlin",
)
}
ProtoBuf.PackageFragment.parseFrom(stream, BuiltInSerializerProtocol.extensionRegistry)
}
private val nameResolver = NameResolverImpl(packageProto.strings, packageProto.qualifiedNames)
val classDataFinder = ProtoBasedClassDataFinder(packageProto, nameResolver, version) { SourceElement.NO_SOURCE }
private val memberDeserializer by lazy {
FirDeserializationContext.createForPackage(
fqName, packageProto.`package`, nameResolver, session,
FirBuiltinAnnotationDeserializer(session),
FirConstDeserializer(session),
containerSource = null
).memberDeserializer
}
val lookup = mutableMapOf<ClassId, FirRegularClassSymbol>()
fun getClassLikeSymbolByFqName(classId: ClassId): FirRegularClassSymbol? =
findAndDeserializeClass(classId)
private fun findAndDeserializeClass(
classId: ClassId,
parentContext: FirDeserializationContext? = null,
): FirRegularClassSymbol? {
val classIdExists = classId in classDataFinder.allClassIds
if (!classIdExists) return null
return lookup.getOrPut(classId, { FirRegularClassSymbol(classId) }) { symbol ->
val classData = classDataFinder.findClassData(classId)!!
val classProto = classData.classProto
deserializeClassToSymbol(
classId, classProto, symbol, nameResolver, session,
null, kotlinScopeProvider, parentContext,
null,
this::findAndDeserializeClass,
)
}
}
fun getTopLevelCallableSymbols(name: Name): List<FirCallableSymbol<*>> {
return packageProto.`package`.functionList.filter { nameResolver.getName(it.name) == name }.map {
memberDeserializer.loadFunction(it).symbol
}
}
fun getAllCallableNames(): Set<Name> {
return packageProto.`package`.functionList.mapTo(mutableSetOf()) { nameResolver.getName(it.name) }
}
fun getAllClassNames(): Set<Name> {
return classDataFinder.allClassIds.mapTo(mutableSetOf()) { it.shortClassName }
}
}
override fun getPackage(fqName: FqName): FqName? {
if (allPackageFragments.containsKey(fqName)) return fqName
return null
}
private val allPackageFragments = loadBuiltIns().groupBy { it.fqName }
private val syntheticFunctionalInterfaceSymbols = mutableMapOf<SyntheticFunctionalInterfaceSymbolKey, FirRegularClassSymbol>()
private fun loadBuiltIns(): List<BuiltInsPackageFragment> {
val classLoader = this::class.java.classLoader
@@ -140,14 +67,16 @@ class FirBuiltinSymbolProvider(val session: FirSession, val kotlinScopeProvider:
}
}
private val allPackageFragments = loadBuiltIns().groupBy { it.fqName }
override fun getPackage(fqName: FqName): FqName? {
if (allPackageFragments.containsKey(fqName)) return fqName
return null
}
private data class SyntheticFunctionalInterfaceSymbolKey(val kind: FunctionClassDescriptor.Kind, val arity: Int)
private val syntheticFunctionalInterfaceSymbols = mutableMapOf<SyntheticFunctionalInterfaceSymbolKey, FirRegularClassSymbol>()
private fun FunctionClassDescriptor.Kind.classId(arity: Int) = ClassId(packageFqName, numberedClassName(arity))
override fun getClassLikeSymbolByFqName(classId: ClassId): FirRegularClassSymbol? {
return allPackageFragments[classId.packageFqName]?.firstNotNullResult {
it.getClassLikeSymbolByFqName(classId)
} ?: trySyntheticFunctionalInterface(classId)
}
private fun trySyntheticFunctionalInterface(classId: ClassId): FirRegularClassSymbol? {
return with(classId) {
@@ -306,11 +235,7 @@ class FirBuiltinSymbolProvider(val session: FirSession, val kotlinScopeProvider:
return (invoke as FirSimpleFunction).symbol as? FirNamedFunctionSymbol
}
override fun getClassLikeSymbolByFqName(classId: ClassId): FirRegularClassSymbol? {
return allPackageFragments[classId.packageFqName]?.firstNotNullResult {
it.getClassLikeSymbolByFqName(classId)
} ?: trySyntheticFunctionalInterface(classId)
}
private fun FunctionClassDescriptor.Kind.classId(arity: Int) = ClassId(packageFqName, numberedClassName(arity))
override fun getTopLevelCallableSymbols(packageFqName: FqName, name: Name): List<FirCallableSymbol<*>> {
return allPackageFragments[packageFqName]?.flatMap {
@@ -346,15 +271,88 @@ class FirBuiltinSymbolProvider(val session: FirSession, val kotlinScopeProvider:
}
}
override fun getNestedClassesNamesInClass(classId: ClassId): Set<Name> {
return getClassDeclarations(classId).filterIsInstance<FirRegularClass>().mapTo(mutableSetOf()) { it.name }
}
private fun getClassDeclarations(classId: ClassId): List<FirDeclaration> {
return findRegularClass(classId)?.declarations ?: emptyList()
}
private fun findRegularClass(classId: ClassId): FirRegularClass? =
getClassLikeSymbolByFqName(classId)?.fir
override fun getNestedClassesNamesInClass(classId: ClassId): Set<Name> {
return getClassDeclarations(classId).filterIsInstance<FirRegularClass>().mapTo(mutableSetOf()) { it.name }
private class BuiltInsPackageFragment(
stream: InputStream, val fqName: FqName, val session: FirSession,
val kotlinScopeProvider: KotlinScopeProvider,
) {
lateinit var version: BuiltInsBinaryVersion
val packageProto: ProtoBuf.PackageFragment = run {
version = BuiltInsBinaryVersion.readFrom(stream)
if (!version.isCompatible()) {
// TODO: report a proper diagnostic
throw UnsupportedOperationException(
"Kotlin built-in definition format version is not supported: " +
"expected ${BuiltInsBinaryVersion.INSTANCE}, actual $version. " +
"Please update Kotlin",
)
}
ProtoBuf.PackageFragment.parseFrom(stream, BuiltInSerializerProtocol.extensionRegistry)
}
private val nameResolver = NameResolverImpl(packageProto.strings, packageProto.qualifiedNames)
val classDataFinder = ProtoBasedClassDataFinder(packageProto, nameResolver, version) { SourceElement.NO_SOURCE }
private val memberDeserializer by lazy {
FirDeserializationContext.createForPackage(
fqName, packageProto.`package`, nameResolver, session,
FirBuiltinAnnotationDeserializer(session),
FirConstDeserializer(session),
containerSource = null
).memberDeserializer
}
private val lookup = mutableMapOf<ClassId, FirRegularClassSymbol>()
fun getClassLikeSymbolByFqName(classId: ClassId): FirRegularClassSymbol? =
findAndDeserializeClass(classId)
private fun findAndDeserializeClass(
classId: ClassId,
parentContext: FirDeserializationContext? = null,
): FirRegularClassSymbol? {
val classIdExists = classId in classDataFinder.allClassIds
if (!classIdExists) return null
return lookup.getOrPut(classId, { FirRegularClassSymbol(classId) }) { symbol ->
val classData = classDataFinder.findClassData(classId)!!
val classProto = classData.classProto
deserializeClassToSymbol(
classId, classProto, symbol, nameResolver, session,
null, kotlinScopeProvider, parentContext,
null,
this::findAndDeserializeClass,
)
}
}
fun getTopLevelCallableSymbols(name: Name): List<FirCallableSymbol<*>> {
return packageProto.`package`.functionList.filter { nameResolver.getName(it.name) == name }.map {
memberDeserializer.loadFunction(it).symbol
}
}
fun getAllCallableNames(): Set<Name> {
return packageProto.`package`.functionList.mapTo(mutableSetOf()) { nameResolver.getName(it.name) }
}
fun getAllClassNames(): Set<Name> {
return classDataFinder.allClassIds.mapTo(mutableSetOf()) { it.shortClassName }
}
}
}
@@ -47,6 +47,5 @@ class FirQualifierResolverImpl(val session: FirSession) : FirQualifierResolver {
return null
}
private fun List<FirQualifierPart>.toFqNameUnsafe() = toFqName().toUnsafe()
private fun List<FirQualifierPart>.toFqName() = fold(FqName.ROOT) { a, b -> a.child(b.name) }
}
@@ -46,10 +46,9 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver {
): FirClassifierSymbol<*>? {
return when (typeRef) {
is FirResolvedTypeRef -> typeRef.coneTypeSafe<ConeLookupTagBasedType>()?.lookupTag?.let(symbolProvider::getSymbolByLookupTag)
is FirUserTypeRef -> {
val qualifierResolver = session.qualifierResolver
var resolvedSymbol: FirClassifierSymbol<*>? = null
scope.processClassifiersByName(typeRef.qualifier.first().name) { symbol ->
if (resolvedSymbol != null) return@processClassifiersByName
@@ -72,9 +71,11 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver {
// TODO: Imports
resolvedSymbol ?: qualifierResolver.resolveSymbol(typeRef.qualifier)
}
is FirImplicitBuiltinTypeRef -> {
resolveBuiltInQualified(typeRef.id, session)
}
else -> null
}
}
@@ -123,18 +124,10 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver {
): ConeKotlinType {
return when (typeRef) {
is FirResolvedTypeRef -> typeRef.type
is FirUserTypeRef -> {
resolveUserType(typeRef, resolveToSymbol(typeRef, scope))
}
is FirFunctionTypeRef -> {
createFunctionalType(typeRef)
}
is FirDelegatedTypeRef -> {
resolveType(typeRef.typeRef, scope)
}
is FirDynamicTypeRef -> {
ConeKotlinErrorType("Not supported: ${typeRef::class.simpleName}")
}
is FirUserTypeRef -> resolveUserType(typeRef, resolveToSymbol(typeRef, scope))
is FirFunctionTypeRef -> createFunctionalType(typeRef)
is FirDelegatedTypeRef -> resolveType(typeRef.typeRef, scope)
is FirDynamicTypeRef -> ConeKotlinErrorType("Not supported: ${typeRef::class.simpleName}")
else -> error("!")
}
}
@@ -10,7 +10,7 @@ import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
abstract class AbstractConeSubstitutor : ConeSubstitutor() {
protected fun wrapProjection(old: ConeTypeProjection, newType: ConeKotlinType): ConeTypeProjection {
private fun wrapProjection(old: ConeTypeProjection, newType: ConeKotlinType): ConeTypeProjection {
return when (old) {
is ConeStarProjection -> old
is ConeKotlinTypeProjectionIn -> ConeKotlinTypeProjectionIn(newType)
@@ -392,7 +392,7 @@ class FirCallCompletionResultsWriterTransformer(
if (needUpdateLambdaType) {
anonymousFunction.replaceTypeRef(
anonymousFunction.constructFunctionalTypeRef(session, isSuspend = expectedType?.isSuspendFunctionType(session) == true)
anonymousFunction.constructFunctionalTypeRef(isSuspend = expectedType?.isSuspendFunctionType(session) == true)
)
}
@@ -402,7 +402,7 @@ class FirCallCompletionResultsWriterTransformer(
val blockType = resultFunction.body?.typeRef?.coneTypeSafe<ConeKotlinType>()
resultFunction.replaceReturnTypeRef(resultFunction.returnTypeRef.withReplacedConeType(blockType))
resultFunction.replaceTypeRef(
resultFunction.constructFunctionalTypeRef(session, isSuspend = expectedType?.isSuspendFunctionType(session) == true)
resultFunction.constructFunctionalTypeRef(isSuspend = expectedType?.isSuspendFunctionType(session) == true)
)
}
return result
@@ -664,7 +664,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor
inferenceComponents.ctx.commonSuperTypeOrNull(returnTypes) ?: session.builtinTypes.unitType.coneTypeUnsafe()
)
)
af.replaceTypeRef(af.constructFunctionalTypeRef(session))
af.replaceTypeRef(af.constructFunctionalTypeRef())
af.addReturn().compose()
}
is ResolutionMode.WithStatus -> {