FIR IDE: extract PsiType conversions to KtPsiTypeProvider

This commit is contained in:
Jinseong Jeon
2021-06-04 23:12:17 -07:00
committed by teamcityserver
parent 0db510ad8b
commit ce26d54917
10 changed files with 104 additions and 66 deletions
@@ -31,6 +31,7 @@ abstract class KtAnalysisSession(final override val token: ValidityToken) : Vali
KtCompletionCandidateCheckerMixIn,
KtSymbolDeclarationOverridesProviderMixIn,
KtExpressionTypeProviderMixIn,
KtPsiTypeProviderMixIn,
KtTypeProviderMixIn,
KtTypeInfoProviderMixIn,
KtSymbolProviderMixIn,
@@ -83,6 +84,9 @@ abstract class KtAnalysisSession(final override val token: ValidityToken) : Vali
internal val expressionTypeProvider: KtExpressionTypeProvider get() = expressionTypeProviderImpl
protected abstract val expressionTypeProviderImpl: KtExpressionTypeProvider
internal val psiTypeProvider: KtPsiTypeProvider get() = psiTypeProviderImpl
protected abstract val psiTypeProviderImpl: KtPsiTypeProvider
internal val typeProvider: KtTypeProvider get() = typeProviderImpl
protected abstract val typeProviderImpl: KtTypeProvider
@@ -103,4 +107,4 @@ abstract class KtAnalysisSession(final override val token: ValidityToken) : Vali
internal val inheritorsProvider: KtInheritorsProvider get() = inheritorsProviderImpl
protected abstract val inheritorsProviderImpl: KtInheritorsProvider
}
}
@@ -6,16 +6,13 @@
package org.jetbrains.kotlin.idea.frontend.api.components
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiType
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtExpression
abstract class KtExpressionTypeProvider : KtAnalysisSessionComponent() {
abstract fun getReturnTypeForKtDeclaration(declaration: KtDeclaration): KtType
abstract fun getKtExpressionType(expression: KtExpression): KtType
abstract fun getPsiTypeForKtExpression(expression: KtExpression, mode: TypeMappingMode): PsiType
abstract fun getExpectedType(expression: PsiElement): KtType?
abstract fun isDefinitelyNull(expression: KtExpression): Boolean
abstract fun isDefinitelyNotNull(expression: KtExpression): Boolean
@@ -25,9 +22,6 @@ interface KtExpressionTypeProviderMixIn : KtAnalysisSessionMixIn {
fun KtExpression.getKtType(): KtType =
analysisSession.expressionTypeProvider.getKtExpressionType(this)
fun KtExpression.getPsiType(mode: TypeMappingMode = TypeMappingMode.DEFAULT): PsiType =
analysisSession.expressionTypeProvider.getPsiTypeForKtExpression(this, mode)
fun KtDeclaration.getReturnKtType(): KtType =
analysisSession.expressionTypeProvider.getReturnTypeForKtDeclaration(this)
@@ -0,0 +1,26 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.frontend.api.components
import com.intellij.psi.PsiType
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtTypeReference
abstract class KtPsiTypeProvider : KtAnalysisSessionComponent() {
abstract fun getPsiTypeForKtExpression(expression: KtExpression, mode: TypeMappingMode): PsiType
abstract fun getPsiTypeForKtTypeReference(ktTypeReference: KtTypeReference, mode: TypeMappingMode): PsiType
}
interface KtPsiTypeProviderMixIn : KtAnalysisSessionMixIn {
fun KtExpression.getPsiType(mode: TypeMappingMode = TypeMappingMode.DEFAULT): PsiType =
analysisSession.psiTypeProvider.getPsiTypeForKtExpression(this, mode)
fun KtTypeReference.getPsiType(mode: TypeMappingMode = TypeMappingMode.DEFAULT): PsiType =
analysisSession.psiTypeProvider.getPsiTypeForKtTypeReference(this, mode)
}
@@ -5,13 +5,10 @@
package org.jetbrains.kotlin.idea.frontend.api.components
import com.intellij.psi.PsiType
import org.jetbrains.kotlin.idea.frontend.api.ValidityTokenOwner
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtNamedClassOrObjectSymbol
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
import org.jetbrains.kotlin.idea.frontend.api.types.KtTypeNullability
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode
import org.jetbrains.kotlin.psi.KtTypeReference
abstract class KtTypeProvider : KtAnalysisSessionComponent() {
abstract val builtinTypes: KtBuiltinTypes
@@ -20,8 +17,6 @@ abstract class KtTypeProvider : KtAnalysisSessionComponent() {
abstract fun buildSelfClassType(symbol: KtNamedClassOrObjectSymbol): KtType
abstract fun getPsiType(ktTypeReference: KtTypeReference, mode: TypeMappingMode): PsiType
abstract fun withNullability(type: KtType, newNullability: KtTypeNullability): KtType
}
@@ -41,9 +36,6 @@ interface KtTypeProviderMixIn : KtAnalysisSessionMixIn {
fun KtNamedClassOrObjectSymbol.buildSelfClassType(): KtType =
analysisSession.typeProvider.buildSelfClassType(this)
fun KtTypeReference.getPsiType(mode: TypeMappingMode = TypeMappingMode.DEFAULT): PsiType =
analysisSession.typeProvider.getPsiType(this, mode)
fun KtType.withNullability(newNullability: KtTypeNullability): KtType =
analysisSession.typeProvider.withNullability(this, newNullability)
}
@@ -110,7 +110,7 @@ private class AnonymousTypesSubstitutor(
}
}
fun ConeKotlinType.asPsiType(
internal fun ConeKotlinType.asPsiType(
session: FirSession,
state: FirModuleResolveState,
mode: TypeMappingMode,
@@ -73,6 +73,8 @@ private constructor(
override val visibilityCheckerImpl: KtVisibilityChecker = KtFirVisibilityChecker(this, token)
override val psiTypeProviderImpl = KtFirPsiTypeProvider(this, token)
override val typeProviderImpl = KtFirTypeProvider(this, token)
override val typeInfoProviderImpl = KtFirTypeInfoProvider(this, token)
@@ -132,4 +134,4 @@ private constructor(
)
}
}
}
}
@@ -6,30 +6,23 @@
package org.jetbrains.kotlin.idea.frontend.api.fir.components
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiType
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.psi
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
import org.jetbrains.kotlin.fir.references.FirNamedReference
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnresolvedNameError
import org.jetbrains.kotlin.fir.typeContext
import org.jetbrains.kotlin.fir.types.ConeClassErrorType
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.idea.fir.low.level.api.api.getOrBuildFir
import org.jetbrains.kotlin.idea.fir.low.level.api.api.getOrBuildFirOfType
import org.jetbrains.kotlin.idea.fir.low.level.api.api.getOrBuildFirSafe
import org.jetbrains.kotlin.idea.frontend.api.components.KtExpressionTypeProvider
import org.jetbrains.kotlin.idea.frontend.api.fir.KtFirAnalysisSession
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.getReferencedElementType
import org.jetbrains.kotlin.idea.frontend.api.tokens.ValidityToken
import org.jetbrains.kotlin.idea.frontend.api.types.KtErrorType
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
import org.jetbrains.kotlin.idea.frontend.api.withValidityAssertion
import org.jetbrains.kotlin.idea.references.FirReferenceResolveHelper
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode
import org.jetbrains.kotlin.psi.*
internal class KtFirExpressionTypeProvider(
@@ -50,29 +43,6 @@ internal class KtFirExpressionTypeProvider(
}
}
override fun getPsiTypeForKtExpression(
expression: KtExpression,
mode: TypeMappingMode,
): PsiType = withValidityAssertion {
when (val fir = expression.getOrBuildFir(firResolveState)) {
is FirExpression -> fir.typeRef.coneType.asPsiType(mode, expression)
is FirNamedReference -> fir.getReferencedElementType().asPsiType(mode, expression)
is FirStatement -> PsiType.VOID
else -> error("Unexpected ${fir::class}")
}
}
private fun FirNamedReference.getReferencedElementType(): ConeKotlinType {
val symbols = when (this) {
is FirResolvedNamedReference -> listOf(resolvedSymbol)
is FirErrorNamedReference -> FirReferenceResolveHelper.getFirSymbolsByErrorNamedReference(this)
else -> error("Unexpected ${this::class}")
}
val firCallableDeclaration = symbols.singleOrNull()?.fir as? FirCallableDeclaration<*>
return firCallableDeclaration?.returnTypeRef?.coneType
?: ConeClassErrorType(ConeUnresolvedNameError(name))
}
override fun getExpectedType(expression: PsiElement): KtType? {
val expectedType = getExpectedTypeByReturnExpression(expression)
?: getExpressionTypeByIfOrBooleanCondition(expression)
@@ -0,0 +1,50 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.frontend.api.fir.components
import com.intellij.psi.PsiType
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirStatement
import org.jetbrains.kotlin.fir.references.FirNamedReference
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.idea.fir.low.level.api.api.getOrBuildFir
import org.jetbrains.kotlin.idea.frontend.api.components.KtPsiTypeProvider
import org.jetbrains.kotlin.idea.frontend.api.fir.KtFirAnalysisSession
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.getReferencedElementType
import org.jetbrains.kotlin.idea.frontend.api.tokens.ValidityToken
import org.jetbrains.kotlin.idea.frontend.api.withValidityAssertion
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtTypeReference
internal class KtFirPsiTypeProvider(
override val analysisSession: KtFirAnalysisSession,
override val token: ValidityToken,
) : KtPsiTypeProvider(), KtFirAnalysisSessionComponent {
override fun getPsiTypeForKtExpression(
expression: KtExpression,
mode: TypeMappingMode,
): PsiType = withValidityAssertion {
when (val fir = expression.getOrBuildFir(firResolveState)) {
is FirExpression -> fir.typeRef.coneType.asPsiType(mode, expression)
is FirNamedReference -> fir.getReferencedElementType().asPsiType(mode, expression)
is FirStatement -> PsiType.VOID
else -> error("Unexpected ${fir::class}")
}
}
override fun getPsiTypeForKtTypeReference(
ktTypeReference: KtTypeReference,
mode: TypeMappingMode
): PsiType = withValidityAssertion {
when (val fir = ktTypeReference.getOrBuildFir(firResolveState)) {
// NB: [FirErrorTypeRef] is a subtype of [FirResolvedTypeRef], and the error type in it will be properly handled by [asPsiType].
is FirResolvedTypeRef -> fir.coneType.asPsiType(mode, ktTypeReference)
else -> error("Unexpected ${fir::class}")
}
}
}
@@ -5,15 +5,11 @@
package org.jetbrains.kotlin.idea.frontend.api.fir.components
import com.intellij.psi.PsiType
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.typeContext
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
import org.jetbrains.kotlin.fir.types.withNullability
import org.jetbrains.kotlin.idea.fir.low.level.api.api.getOrBuildFir
import org.jetbrains.kotlin.idea.frontend.api.components.KtBuiltinTypes
import org.jetbrains.kotlin.idea.frontend.api.components.KtTypeProvider
import org.jetbrains.kotlin.idea.frontend.api.fir.KtFirAnalysisSession
@@ -25,9 +21,6 @@ import org.jetbrains.kotlin.idea.frontend.api.symbols.KtNamedClassOrObjectSymbol
import org.jetbrains.kotlin.idea.frontend.api.tokens.ValidityToken
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
import org.jetbrains.kotlin.idea.frontend.api.types.KtTypeNullability
import org.jetbrains.kotlin.idea.frontend.api.withValidityAssertion
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode
import org.jetbrains.kotlin.psi.KtTypeReference
internal class KtFirTypeProvider(
override val analysisSession: KtFirAnalysisSession,
@@ -58,14 +51,6 @@ internal class KtFirTypeProvider(
return type.asKtType()
}
override fun getPsiType(ktTypeReference: KtTypeReference, mode: TypeMappingMode): PsiType = withValidityAssertion {
when (val fir = ktTypeReference.getOrBuildFir(firResolveState)) {
// NB: [FirErrorTypeRef] is a subtype of [FirResolvedTypeRef], and the error type in it will be properly handled by [asPsiType].
is FirResolvedTypeRef -> fir.coneType.asPsiType(mode, ktTypeReference)
else -> error("Unexpected ${fir::class}")
}
}
override fun withNullability(type: KtType, newNullability: KtTypeNullability): KtType {
require(type is KtFirType)
return type.coneType.withNullability(newNullability.toConeNullability(), rootModuleSession.typeContext).asKtType()
@@ -5,20 +5,35 @@
package org.jetbrains.kotlin.idea.frontend.api.fir.utils
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.primaryConstructor
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
import org.jetbrains.kotlin.fir.expressions.FirConstExpression
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirNamedArgumentExpression
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
import org.jetbrains.kotlin.fir.references.FirNamedReference
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnresolvedNameError
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
import org.jetbrains.kotlin.fir.types.ConeNullability
import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtConstantValue
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSimpleConstantValue
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtUnsupportedConstantValue
import org.jetbrains.kotlin.idea.frontend.api.types.KtTypeNullability
import org.jetbrains.kotlin.idea.references.FirReferenceResolveHelper
internal fun FirNamedReference.getReferencedElementType(): ConeKotlinType {
val symbols = when (this) {
is FirResolvedNamedReference -> listOf(resolvedSymbol)
is FirErrorNamedReference -> FirReferenceResolveHelper.getFirSymbolsByErrorNamedReference(this)
else -> error("Unexpected ${this::class}")
}
val firCallableDeclaration = symbols.singleOrNull()?.fir as? FirCallableDeclaration<*>
return firCallableDeclaration?.returnTypeRef?.coneType
?: ConeClassErrorType(ConeUnresolvedNameError(name))
}
internal fun mapAnnotationParameters(annotationCall: FirAnnotationCall, session: FirSession): Map<String, FirExpression> {