[FIR IDE] Make KtSmartcastProvider report resolved smartcast type

This commit is contained in:
Tianyu Geng
2021-02-04 11:59:23 -08:00
committed by Ilya Kirillov
parent d97a2b13c0
commit 58d903c638
5 changed files with 28 additions and 32 deletions
@@ -8,8 +8,8 @@ package org.jetbrains.kotlin.idea.fir.highlighter.visitors
import com.intellij.lang.annotation.AnnotationHolder
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.idea.KotlinIdeaAnalysisBundle
import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession
import org.jetbrains.kotlin.idea.frontend.api.ImplicitReceiverSmartcastKind
import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession
import org.jetbrains.kotlin.idea.highlighter.KotlinHighlightingColors
import org.jetbrains.kotlin.psi.*
@@ -18,25 +18,23 @@ internal class ExpressionsSmartcastHighlightingVisitor(
holder: AnnotationHolder
) : FirAfterResolveHighlightingVisitor(analysisSession, holder) {
override fun visitExpression(expression: KtExpression) = with(analysisSession) {
expression.getImplicitReceiverSmartCasts().forEach { (types, kind) ->
expression.getImplicitReceiverSmartCast().forEach { (type, kind) ->
val receiverName = when (kind) {
ImplicitReceiverSmartcastKind.EXTENSION -> KotlinIdeaAnalysisBundle.message("extension.implicit.receiver")
ImplicitReceiverSmartcastKind.DISPATCH -> KotlinIdeaAnalysisBundle.message("implicit.receiver")
}
types.forEach { type ->
createInfoAnnotation(
expression,
KotlinIdeaAnalysisBundle.message(
"0.smart.cast.to.1",
receiverName,
type.asStringForDebugging()
),
KotlinHighlightingColors.SMART_CAST_RECEIVER
)
}
createInfoAnnotation(
expression,
KotlinIdeaAnalysisBundle.message(
"0.smart.cast.to.1",
receiverName,
type.asStringForDebugging()
),
KotlinHighlightingColors.SMART_CAST_RECEIVER
)
}
expression.getSmartCasts()?.forEach { type ->
expression.getSmartCast()?.let { type ->
createInfoAnnotation(
getSmartCastTarget(expression),
KotlinIdeaAnalysisBundle.message(
@@ -47,8 +45,6 @@ internal class ExpressionsSmartcastHighlightingVisitor(
)
}
//todo smartcast to null
super.visitExpression(expression)
}
}
@@ -7,7 +7,7 @@ package org.jetbrains.kotlin.idea.frontend.api
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
data class ImplicitReceiverSmartCast(val types: Collection<KtType>, val kind: ImplicitReceiverSmartcastKind)
data class ImplicitReceiverSmartCast(val type: KtType, val kind: ImplicitReceiverSmartcastKind)
enum class ImplicitReceiverSmartcastKind {
DISPATCH, EXTENSION
@@ -61,10 +61,10 @@ abstract class KtAnalysisSession(final override val token: ValidityToken) : Vali
fun KtCallableSymbol.getIntersectionOverriddenSymbols(): Collection<KtCallableSymbol> =
symbolDeclarationOverridesProvider.getIntersectionOverriddenSymbols(this)
fun KtExpression.getSmartCasts(): Collection<KtType> = smartCastProvider.getSmartCastedToTypes(this)
fun KtExpression.getSmartCast(): KtType? = smartCastProvider.getSmartCastedToType(this)
fun KtExpression.getImplicitReceiverSmartCasts(): Collection<ImplicitReceiverSmartCast> =
smartCastProvider.getImplicitReceiverSmartCasts(this)
fun KtExpression.getImplicitReceiverSmartCast(): Collection<ImplicitReceiverSmartCast> =
smartCastProvider.getImplicitReceiverSmartCast(this)
fun KtExpression.getKtType(): KtType = expressionTypeProvider.getKtExpressionType(this)
@@ -10,6 +10,6 @@ import org.jetbrains.kotlin.idea.frontend.api.types.KtType
import org.jetbrains.kotlin.psi.KtExpression
abstract class KtSmartCastProvider : KtAnalysisSessionComponent() {
abstract fun getSmartCastedToTypes(expression: KtExpression): Collection<KtType>
abstract fun getImplicitReceiverSmartCasts(expression: KtExpression): Collection<ImplicitReceiverSmartCast>
abstract fun getSmartCastedToType(expression: KtExpression): KtType?
abstract fun getImplicitReceiverSmartCast(expression: KtExpression): Collection<ImplicitReceiverSmartCast>
}
@@ -7,6 +7,8 @@ package org.jetbrains.kotlin.idea.frontend.api.fir.components
import org.jetbrains.kotlin.fir.expressions.FirExpressionWithSmartcast
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.coneTypeSafe
import org.jetbrains.kotlin.idea.fir.low.level.api.api.getOrBuildFirSafe
import org.jetbrains.kotlin.idea.frontend.api.ImplicitReceiverSmartCast
import org.jetbrains.kotlin.idea.frontend.api.ImplicitReceiverSmartcastKind
@@ -20,18 +22,16 @@ import org.jetbrains.kotlin.psi.KtExpression
internal class KtFirSmartcastProvider(
override val analysisSession: KtFirAnalysisSession,
override val token: ValidityToken,
) : KtSmartCastProvider(), KtFirAnalysisSessionComponent {
override fun getSmartCastedToTypes(expression: KtExpression): Collection<KtType> = withValidityAssertion {
// TODO filter out not used smartcasts
) : KtSmartCastProvider(), KtFirAnalysisSessionComponent {
override fun getSmartCastedToType(expression: KtExpression): KtType? = withValidityAssertion {
expression.getOrBuildFirSafe<FirExpressionWithSmartcast>(analysisSession.firResolveState)
?.typesFromSmartCast
?.map { it.asKtType() }
?: emptyList()
?.typeRef
?.coneTypeSafe<ConeKotlinType>()
?.asKtType()
}
@OptIn(ExperimentalStdlibApi::class)
override fun getImplicitReceiverSmartCasts(expression: KtExpression): Collection<ImplicitReceiverSmartCast> = withValidityAssertion {
// TODO filter out not used smartcasts
override fun getImplicitReceiverSmartCast(expression: KtExpression): Collection<ImplicitReceiverSmartCast> = withValidityAssertion {
val qualifiedExpression =
expression.getOrBuildFirSafe<FirQualifiedAccessExpression>(analysisSession.firResolveState) ?: return emptyList()
if (qualifiedExpression.dispatchReceiver !is FirExpressionWithSmartcast
@@ -40,13 +40,13 @@ internal class KtFirSmartcastProvider(
buildList {
(qualifiedExpression.dispatchReceiver as? FirExpressionWithSmartcast)?.let { smartCasted ->
ImplicitReceiverSmartCast(
smartCasted.typesFromSmartCast.map { it.asKtType() },
smartCasted.typeRef.coneTypeSafe<ConeKotlinType>()?.asKtType() ?: return@let null,
ImplicitReceiverSmartcastKind.DISPATCH
)
}?.let(::add)
(qualifiedExpression.extensionReceiver as? FirExpressionWithSmartcast)?.let { smartCasted ->
ImplicitReceiverSmartCast(
smartCasted.typesFromSmartCast.map { it.asKtType() },
smartCasted.typeRef.coneTypeSafe<ConeKotlinType>()?.asKtType() ?: return@let null,
ImplicitReceiverSmartcastKind.EXTENSION
)
}?.let(::add)