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