All Downloads are FREE. Search and download functionalities are using the official Maven repository.
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.providers.impl.FirTypeResolverImpl.kt Maven / Gradle / Ivy
/*
* Copyright 2010-2020 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.providers.impl
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.ThreadSafeMutableState
import org.jetbrains.kotlin.fir.diagnostics.ConeIntermediateDiagnostic
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
import org.jetbrains.kotlin.fir.diagnostics.ConeUnexpectedTypeArgumentsError
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
import org.jetbrains.kotlin.fir.render
import org.jetbrains.kotlin.fir.resolve.*
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeWrongNumberOfTypeArgumentsError
import org.jetbrains.kotlin.fir.resolve.getSymbolByLookupTag
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
import org.jetbrains.kotlin.fir.types.impl.FirImplicitBuiltinTypeRef
import org.jetbrains.kotlin.name.ClassId
@ThreadSafeMutableState
class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver() {
private val symbolProvider by lazy {
session.firSymbolProvider
}
private data class ClassIdInSession(val session: FirSession, val id: ClassId)
private val implicitBuiltinTypeSymbols = mutableMapOf>()
// TODO: get rid of session used here, and may be also of the cache above (see KT-30275)
private fun resolveBuiltInQualified(id: ClassId, session: FirSession): FirClassLikeSymbol<*> {
val nameInSession = ClassIdInSession(session, id)
return implicitBuiltinTypeSymbols.getOrPut(nameInSession) {
symbolProvider.getClassLikeSymbolByFqName(id)!!
}
}
private fun resolveToSymbol(
typeRef: FirTypeRef,
scope: FirScope
): Pair?, ConeSubstitutor?> {
return when (typeRef) {
is FirResolvedTypeRef -> {
val resultSymbol = typeRef.coneTypeSafe()?.lookupTag?.let(symbolProvider::getSymbolByLookupTag)
resultSymbol to null
}
is FirUserTypeRef -> {
val qualifierResolver = session.qualifierResolver
var resolvedSymbol: FirClassifierSymbol<*>? = null
var substitutor: ConeSubstitutor? = null
scope.processClassifiersByNameWithSubstitution(typeRef.qualifier.first().name) { symbol, substitutorFromScope ->
if (resolvedSymbol != null) return@processClassifiersByNameWithSubstitution
resolvedSymbol = when (symbol) {
is FirClassLikeSymbol<*> -> {
if (typeRef.qualifier.size == 1) {
symbol
} else {
qualifierResolver.resolveSymbolWithPrefix(typeRef.qualifier, symbol.classId)
}
}
is FirTypeParameterSymbol -> {
assert(typeRef.qualifier.size == 1)
symbol
}
else -> error("!")
}
substitutor = substitutorFromScope
}
// TODO: Imports
val resultSymbol: FirClassifierSymbol<*>? = resolvedSymbol ?: qualifierResolver.resolveSymbol(typeRef.qualifier)
resultSymbol to substitutor
}
is FirImplicitBuiltinTypeRef -> {
resolveBuiltInQualified(typeRef.id, session) to null
}
else -> null to null
}
}
private fun resolveUserType(
typeRef: FirUserTypeRef,
symbol: FirClassifierSymbol<*>?,
substitutor: ConeSubstitutor?,
areBareTypesAllowed: Boolean
): ConeKotlinType {
if (symbol == null) {
return ConeKotlinErrorType(ConeSimpleDiagnostic("Symbol not found, for `${typeRef.render()}`", DiagnosticKind.SymbolNotFound))
}
if (symbol is FirTypeParameterSymbol) {
for (part in typeRef.qualifier) {
if (part.typeArgumentList.typeArguments.isNotEmpty()) {
return ConeClassErrorType(
ConeUnexpectedTypeArgumentsError("Type arguments not allowed", part.typeArgumentList.source)
)
}
}
}
var typeArguments = typeRef.qualifier.toTypeProjections()
if (symbol is FirRegularClassSymbol) {
val isPossibleBareType = areBareTypesAllowed && typeArguments.isEmpty()
if (typeArguments.size != symbol.fir.typeParameters.size && !isPossibleBareType) {
@Suppress("NAME_SHADOWING")
val substitutor = substitutor ?: ConeSubstitutor.Empty
val n = symbol.fir.typeParameters.size - typeArguments.size
if (n < 0) {
typeArguments = (1..symbol.fir.typeParameters.size).map {
ConeClassErrorType(ConeWrongNumberOfTypeArgumentsError(typeArguments.size, symbol))
}.toTypedArray()
} else {
val argumentsFromOuterClassesAndParents = symbol.fir.typeParameters.takeLast(n).map {
val type = ConeTypeParameterTypeImpl(ConeTypeParameterLookupTag(it.symbol), isNullable = false)
// we should report ConeSimpleDiagnostic(..., WrongNumberOfTypeArguments)
// but genericArgumentNumberMismatch.kt test fails with
// index out of bounds exception for start offset of
// the source
substitutor.substituteOrNull(type)
?: ConeClassErrorType(ConeIntermediateDiagnostic("Type argument not defined"))
}.toTypedArray()
typeArguments += argumentsFromOuterClassesAndParents
}
}
}
return symbol.constructType(typeArguments, typeRef.isMarkedNullable, typeRef.annotations.computeTypeAttributes())
.also {
val lookupTag = it.lookupTag
if (lookupTag is ConeClassLikeLookupTagImpl && symbol is FirClassLikeSymbol<*>) {
lookupTag.bindSymbolToLookupTag(session, symbol)
}
}
}
private fun createFunctionalType(typeRef: FirFunctionTypeRef): ConeClassLikeType {
val parameters =
listOfNotNull(typeRef.receiverTypeRef?.coneType) +
typeRef.valueParameters.map { it.returnTypeRef.coneType } +
listOf(typeRef.returnTypeRef.coneType)
val classId = if (typeRef.isSuspend) {
StandardNames.getSuspendFunctionClassId(typeRef.parametersCount)
} else {
StandardNames.getFunctionClassId(typeRef.parametersCount)
}
val attributes = typeRef.annotations.computeTypeAttributes()
return ConeClassLikeTypeImpl(
resolveBuiltInQualified(classId, session).toLookupTag(),
parameters.toTypedArray(),
typeRef.isMarkedNullable,
attributes
)
}
override fun resolveType(
typeRef: FirTypeRef,
scope: FirScope,
areBareTypesAllowed: Boolean
): ConeKotlinType {
return when (typeRef) {
is FirResolvedTypeRef -> typeRef.type
is FirUserTypeRef -> {
val (symbol, substitutor) = resolveToSymbol(typeRef, scope)
resolveUserType(typeRef, symbol, substitutor, areBareTypesAllowed)
}
is FirFunctionTypeRef -> createFunctionalType(typeRef)
is FirDynamicTypeRef -> ConeKotlinErrorType(ConeIntermediateDiagnostic("Not supported: ${typeRef::class.simpleName}"))
else -> error("!")
}
}
}