[FIR IDE] Add getDispatchReceiverType function and use

This function is under a heavy deprecation and should not be used,
since it will most probably be removed in the future
This commit is contained in:
Roman Golyshev
2021-10-26 16:07:53 +03:00
committed by TeamCityServer
parent 3091269035
commit 4e1e1570df
4 changed files with 58 additions and 7 deletions
@@ -5,21 +5,26 @@
package org.jetbrains.kotlin.analysis.api.descriptors.components
import org.jetbrains.kotlin.analysis.api.assertIsValidAndAccessible
import org.jetbrains.kotlin.analysis.api.components.KtBuiltinTypes
import org.jetbrains.kotlin.analysis.api.components.KtTypeProvider
import org.jetbrains.kotlin.analysis.api.descriptors.Fe10AnalysisContext
import org.jetbrains.kotlin.analysis.api.descriptors.KtFe10AnalysisSession
import org.jetbrains.kotlin.analysis.api.descriptors.Fe10AnalysisFacade.AnalysisMode
import org.jetbrains.kotlin.analysis.api.descriptors.components.base.Fe10KtAnalysisSessionComponent
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.base.KtFe10Symbol
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.base.KtFe10DescSymbol
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.base.classId
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.base.getSymbolDescriptor
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.base.isInterfaceLike
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.descriptorBased.base.toKtType
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.psiBased.base.KtFe10PsiSymbol
import org.jetbrains.kotlin.analysis.api.descriptors.symbols.psiBased.base.getResolutionScope
import org.jetbrains.kotlin.analysis.api.descriptors.types.base.KtFe10Type
import org.jetbrains.kotlin.analysis.api.descriptors.utils.PublicApproximatorConfiguration
import org.jetbrains.kotlin.analysis.api.descriptors.utils.cached
import org.jetbrains.kotlin.analysis.api.symbols.KtNamedClassOrObjectSymbol
import org.jetbrains.kotlin.analysis.api.symbols.markers.KtPossibleMemberSymbol
import org.jetbrains.kotlin.analysis.api.symbols.nameOrAnonymous
import org.jetbrains.kotlin.analysis.api.tokens.ValidityToken
import org.jetbrains.kotlin.analysis.api.types.KtType
@@ -39,7 +44,6 @@ import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.checker.NewCapturedType
import org.jetbrains.kotlin.types.checker.NewTypeVariableConstructor
import org.jetbrains.kotlin.types.typeUtil.isNothing
import org.jetbrains.kotlin.types.typeUtil.supertypes
import org.jetbrains.kotlin.util.containingNonLocalDeclaration
internal class KtFe10TypeProvider(
@@ -115,6 +119,19 @@ internal class KtFe10TypeProvider(
return TypeUtils.getAllSupertypes(type.type).map { it.toKtType(analysisContext) }
}
override fun getDispatchReceiverType(symbol: KtPossibleMemberSymbol): KtType? {
assertIsValidAndAccessible()
require(symbol is KtFe10Symbol)
val descriptor = when (symbol) {
is KtFe10DescSymbol<*> -> symbol.descriptor as? CallableDescriptor
is KtFe10PsiSymbol<*, *> -> symbol.descriptor as? CallableDescriptor
else -> error("No callable descriptor on $symbol")
}
return descriptor?.dispatchReceiverParameter?.type?.toKtType(analysisContext)
}
private fun areTypesCompatible(a: KotlinType, b: KotlinType): Boolean {
if (a.isNothing() || b.isNothing() || TypeUtils.equalTypes(a, b) || (a.isNullable() && b.isNullable())) {
return true
@@ -9,10 +9,12 @@ import org.jetbrains.kotlin.analysis.api.components.KtBuiltinTypes
import org.jetbrains.kotlin.analysis.api.components.KtTypeProvider
import org.jetbrains.kotlin.analysis.api.fir.KtFirAnalysisSession
import org.jetbrains.kotlin.analysis.api.fir.symbols.KtFirNamedClassOrObjectSymbol
import org.jetbrains.kotlin.analysis.api.fir.symbols.KtFirSymbol
import org.jetbrains.kotlin.analysis.api.fir.types.KtFirType
import org.jetbrains.kotlin.analysis.api.fir.types.PublicTypeApproximator
import org.jetbrains.kotlin.analysis.api.fir.utils.toConeNullability
import org.jetbrains.kotlin.analysis.api.symbols.KtNamedClassOrObjectSymbol
import org.jetbrains.kotlin.analysis.api.symbols.markers.KtPossibleMemberSymbol
import org.jetbrains.kotlin.analysis.api.tokens.ValidityToken
import org.jetbrains.kotlin.analysis.api.types.KtType
import org.jetbrains.kotlin.analysis.api.types.KtTypeNullability
@@ -25,6 +27,7 @@ import org.jetbrains.kotlin.fir.analysis.checkers.ConeTypeCompatibilityChecker
import org.jetbrains.kotlin.fir.analysis.checkers.ConeTypeCompatibilityChecker.isCompatible
import org.jetbrains.kotlin.fir.analysis.checkers.fullyExpandedClass
import org.jetbrains.kotlin.fir.analysis.checkers.typeParameterSymbols
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.declarations.utils.superConeTypes
import org.jetbrains.kotlin.fir.expressions.FirCallableReferenceAccess
@@ -183,5 +186,17 @@ internal class KtFirTypeProvider(
.drop(1)
.mapTo(mutableListOf()) { it.asKtType() }
}
override fun getDispatchReceiverType(symbol: KtPossibleMemberSymbol): KtType? {
require(symbol is KtFirSymbol<*>)
return symbol.firRef.withFir { declaration ->
check(declaration is FirCallableDeclaration) {
"Fir declaration should be FirCallableDeclaration; instead it was ${declaration::class}"
}
declaration.dispatchReceiverType?.asKtType()
}
}
}
@@ -37,7 +37,7 @@ abstract class AbstractResolveCallTest(configurator: FrontendApiTestConfigurator
val actual = executeOnPooledThreadInReadAction {
analyseForTest(expression) {
resolveCall(expression)?.stringRepresentation()
resolveCall(expression)?.let { stringRepresentation(it) }
}
} ?: "null"
testServices.assertions.assertEqualsToTestDataFileSibling(actual)
@@ -62,8 +62,8 @@ abstract class AbstractResolveCallTest(configurator: FrontendApiTestConfigurator
}
private fun KtCall.stringRepresentation(): String {
fun KtType.render() = substitutor.substituteOrSelf(this).asStringForDebugging().replace('/', '.')
private fun KtAnalysisSession.stringRepresentation(call: KtCall): String {
fun KtType.render() = call.substitutor.substituteOrSelf(this).asStringForDebugging().replace('/', '.')
fun Any.stringValue(): String = when (this) {
is KtFunctionLikeSymbol -> buildString {
append(
@@ -81,7 +81,9 @@ private fun KtCall.stringRepresentation(): String {
append("<extension receiver>: ${receiver.type.render()}")
if (valueParameters.isNotEmpty()) append(", ")
}
(this@stringValue as? KtPossibleMemberSymbol)?.dispatchType?.let { dispatchReceiverType ->
@Suppress("DEPRECATION")
(this@stringValue as? KtPossibleMemberSymbol)?.getDispatchReceiverType()?.let { dispatchReceiverType ->
append("<dispatch receiver>: ${dispatchReceiverType.render()}")
if (valueParameters.isNotEmpty()) append(", ")
}
@@ -108,7 +110,7 @@ private fun KtCall.stringRepresentation(): String {
else -> error("unexpected parameter type ${this::class}")
}
val callInfoClass = this::class
val callInfoClass = call::class
return buildString {
append(callInfoClass.simpleName!!)
append(":\n")
@@ -118,7 +120,7 @@ private fun KtCall.stringRepresentation(): String {
.filter { it.name != "token" }
.joinTo(this, separator = "\n") { parameter ->
val name = parameter.name!!.removePrefix("_")
val value = propertyByName[name]!!.javaGetter!!(this@stringRepresentation)?.stringValue()
val value = propertyByName[name]!!.javaGetter!!(call)?.stringValue()
"$name = $value"
}
}
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.analysis.api.components
import org.jetbrains.kotlin.analysis.api.ValidityTokenOwner
import org.jetbrains.kotlin.analysis.api.symbols.KtNamedClassOrObjectSymbol
import org.jetbrains.kotlin.analysis.api.symbols.markers.KtPossibleMemberSymbol
import org.jetbrains.kotlin.analysis.api.types.KtFlexibleType
import org.jetbrains.kotlin.analysis.api.types.KtType
import org.jetbrains.kotlin.analysis.api.types.KtTypeNullability
@@ -37,6 +38,7 @@ public abstract class KtTypeProvider : KtAnalysisSessionComponent() {
public abstract fun getAllSuperTypes(type: KtType, shouldApproximate: Boolean): List<KtType>
public abstract fun getDispatchReceiverType(symbol: KtPossibleMemberSymbol): KtType?
}
public interface KtTypeProviderMixIn : KtAnalysisSessionMixIn {
@@ -118,6 +120,21 @@ public interface KtTypeProviderMixIn : KtAnalysisSessionMixIn {
*/
public fun KtType.getAllSuperTypes(shouldApproximate: Boolean = false): List<KtType> =
analysisSession.typeProvider.getAllSuperTypes(this, shouldApproximate)
/**
* This function is provided for a few use-cases where it's hard to go without it.
*
* **Please avoid using it**; it will probably be removed in the future.
*
* The function is instantly deprecated, so it's not shown in the completion.
*
* @receiver A target callable symbol.
* @return A dispatch receiver type for this symbol if it has any.
*/
@Suppress("DeprecatedCallableAddReplaceWith")
@Deprecated("Avoid using this function")
public fun KtPossibleMemberSymbol.getDispatchReceiverType(): KtType? =
analysisSession.typeProvider.getDispatchReceiverType(this)
}
@Suppress("PropertyName")