diff --git a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/KtAnalysisSession.kt b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/KtAnalysisSession.kt index a0de0a13e3d..44a083edb80 100644 --- a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/KtAnalysisSession.kt +++ b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/KtAnalysisSession.kt @@ -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 -} \ No newline at end of file +} diff --git a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/components/KtExpressionTypeProvider.kt b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/components/KtExpressionTypeProvider.kt index 3ce6f076960..81a8af85532 100644 --- a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/components/KtExpressionTypeProvider.kt +++ b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/components/KtExpressionTypeProvider.kt @@ -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) diff --git a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/components/KtPsiTypeProvider.kt b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/components/KtPsiTypeProvider.kt new file mode 100644 index 00000000000..3d369dc1466 --- /dev/null +++ b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/components/KtPsiTypeProvider.kt @@ -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) + +} diff --git a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/components/KtTypeProvider.kt b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/components/KtTypeProvider.kt index deed8a39012..9212f00b5c6 100644 --- a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/components/KtTypeProvider.kt +++ b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/components/KtTypeProvider.kt @@ -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) } diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/firLightUtils.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/firLightUtils.kt index 26c176c3e9e..01e0fbebe70 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/firLightUtils.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/firLightUtils.kt @@ -110,7 +110,7 @@ private class AnonymousTypesSubstitutor( } } -fun ConeKotlinType.asPsiType( +internal fun ConeKotlinType.asPsiType( session: FirSession, state: FirModuleResolveState, mode: TypeMappingMode, diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/KtFirAnalysisSession.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/KtFirAnalysisSession.kt index adecdb381f9..1f9b53f4562 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/KtFirAnalysisSession.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/KtFirAnalysisSession.kt @@ -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( ) } } -} \ No newline at end of file +} diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/components/KtFirExpressionTypeProvider.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/components/KtFirExpressionTypeProvider.kt index 755a1387e8d..9f577929ed0 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/components/KtFirExpressionTypeProvider.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/components/KtFirExpressionTypeProvider.kt @@ -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) diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/components/KtFirPsiTypeProvider.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/components/KtFirPsiTypeProvider.kt new file mode 100644 index 00000000000..3703d8cb58e --- /dev/null +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/components/KtFirPsiTypeProvider.kt @@ -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}") + } + } +} diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/components/KtFirTypeProvider.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/components/KtFirTypeProvider.kt index fc2fb1c34dd..41f23055fbc 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/components/KtFirTypeProvider.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/components/KtFirTypeProvider.kt @@ -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() diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/utils/firUtils.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/utils/firUtils.kt index 76f2106e5ab..fc962648578 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/utils/firUtils.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/utils/firUtils.kt @@ -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 {