FIR IDE: introduce KtType

This commit is contained in:
Ilya Kirillov
2020-06-26 23:32:54 +03:00
parent c44756bbfd
commit 8368284817
24 changed files with 379 additions and 261 deletions
@@ -29,7 +29,7 @@ internal class ExpressionsSmartcastHighlightingVisitor(
KotlinIdeaAnalysisBundle.message(
"0.smart.cast.to.1",
receiverName,
type.asDenotableTypeStringRepresentation()
type.asStringForDebugging()
)
).textAttributes = org.jetbrains.kotlin.idea.highlighter.KotlinHighlightingColors.SMART_CAST_RECEIVER
}
@@ -39,7 +39,7 @@ internal class ExpressionsSmartcastHighlightingVisitor(
getSmartCastTarget(expression),
KotlinIdeaAnalysisBundle.message(
"smart.cast.to.0",
type.asDenotableTypeStringRepresentation()
type.asStringForDebugging()
)
).textAttributes = org.jetbrains.kotlin.idea.highlighter.KotlinHighlightingColors.SMART_CAST_VALUE
}
@@ -18,13 +18,13 @@ abstract class FrontendAnalysisSession(project: Project) : Invalidatable {
abstract val symbolProvider: KtSymbolProvider
abstract fun getSmartCastedToTypes(expression: KtExpression): Collection<TypeInfo>?
abstract fun getSmartCastedToTypes(expression: KtExpression): Collection<KtType>?
abstract fun getImplicitReceiverSmartCasts(expression: KtExpression): Collection<ImplicitReceiverSmartCast>
abstract fun getReturnTypeForKtDeclaration(declaration: KtDeclaration): TypeInfo
abstract fun getReturnTypeForKtDeclaration(declaration: KtDeclaration): KtType
abstract fun getKtExpressionType(expression: KtExpression): TypeInfo
abstract fun getKtExpressionType(expression: KtExpression): KtType
abstract fun isSubclassOf(klass: KtClassOrObject, superClassId: ClassId): Boolean
@@ -5,7 +5,7 @@
package org.jetbrains.kotlin.idea.frontend.api
data class ImplicitReceiverSmartCast(val types: Collection<TypeInfo>, val kind: ImplicitReceiverSmartcastKind)
data class ImplicitReceiverSmartCast(val types: Collection<KtType>, val kind: ImplicitReceiverSmartcastKind)
enum class ImplicitReceiverSmartcastKind {
DISPATCH, EXTENSION
@@ -0,0 +1,48 @@
/*
* Copyright 2010-2020 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
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtClassLikeSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtTypeParameterSymbol
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name
interface KtType : Invalidatable {
fun isEqualTo(other: KtType): Boolean
fun isSubTypeOf(superType: KtType): Boolean
fun asStringForDebugging(): String
}
sealed class KtDenotableType : KtType {
abstract fun asString(): String
}
abstract class KtClassType : KtDenotableType() {
abstract val classId: ClassId
abstract val classSymbol: KtClassLikeSymbol
abstract val typeArguments: List<KtTypeArgument>
}
abstract class KtErrorType : KtType {
abstract val error: String
}
abstract class KtTypeParameterType : KtDenotableType() {
abstract val name: Name
abstract val symbol: KtTypeParameterSymbol
}
sealed class KtNonDenotableType : KtType
abstract class KtFlexibleType : KtNonDenotableType() {
abstract val lowerBound: KtType
abstract val upperBound: KtType
}
abstract class KtIntersectionType : KtNonDenotableType() {
abstract val conjuncts: List<KtType>
}
@@ -0,0 +1,20 @@
/*
* Copyright 2010-2020 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
sealed class KtTypeArgument
object KtStarProjectionTypeArgument : KtTypeArgument()
abstract class KtTypeArgumentWithVariance : KtTypeArgument() {
abstract val type: KtType
abstract val variance: KtTypeArgumentVariance
}
enum class KtTypeArgumentVariance {
COVARIANT, CONTRAVARIANT, INVARIANT
}
@@ -1,28 +0,0 @@
/*
* Copyright 2010-2020 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
import org.jetbrains.kotlin.name.ClassId
abstract class TypeInfo : Invalidatable {
abstract fun isClassType(): Boolean
abstract fun classIdIfClassTypeOrError(): ClassId
abstract fun isErrorType(): Boolean
abstract fun asDenotableTypeStringRepresentation(): String
abstract fun isEqualTo(other: TypeInfo): Boolean
abstract fun isSubTypeOf(superType: TypeInfo): Boolean
abstract fun isDefinitelyNullable(): Boolean
abstract fun isDefinitelyNotNull(): Boolean
override fun toString(): String = asDenotableTypeStringRepresentation()
}
class ErrorTypeClassIdAccessException(override val message: String? = null) : IllegalStateException()
class ClassTypeExpectedException(override val message: String? = null) : IllegalStateException()
@@ -5,7 +5,7 @@
package org.jetbrains.kotlin.idea.frontend.api.symbols
import org.jetbrains.kotlin.idea.frontend.api.TypeInfo
import org.jetbrains.kotlin.idea.frontend.api.KtType
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
@@ -36,7 +36,7 @@ object DebugSymbolRenderer {
value.joinTo(this) { renderValue(it) }
append("]")
}
is TypeInfo -> value.asDenotableTypeStringRepresentation()
is KtType -> value.asStringForDebugging()
is KtSymbol -> {
val symbolTag = when (value) {
is KtClassLikeSymbol -> renderValue(value.classId)
@@ -5,7 +5,7 @@
package org.jetbrains.kotlin.idea.frontend.api.symbols
import org.jetbrains.kotlin.idea.frontend.api.TypeInfo
import org.jetbrains.kotlin.idea.frontend.api.KtType
import org.jetbrains.kotlin.name.Name
interface KtNamedSymbol : KtSymbol {
@@ -21,12 +21,12 @@ enum class KtSymbolKind {
}
interface KtTypedSymbol : KtSymbol {
val type: TypeInfo
val type: KtType
}
interface KtPossibleExtensionSymbol {
val isExtension: Boolean
val receiverType: TypeInfo?
val receiverType: KtType?
}
interface KtSymbolWithTypeParameters {
@@ -1,95 +0,0 @@
/*
* Copyright 2010-2020 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
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
import org.jetbrains.kotlin.idea.frontend.api.*
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.types.AbstractTypeChecker
import org.jetbrains.kotlin.types.AbstractTypeCheckerContext
import java.lang.ref.WeakReference
internal class ConeTypeInfo(
coneType: ConeKotlinType,
private val typeCheckerContext: ConeTypeCheckerContext,
private val validityToken: Invalidatable
) : TypeInfo() {
private val coneTypeWeakRef = WeakReference(coneType)
override fun isClassType(): Boolean {
assertIsValid()
return coneType is ConeClassLikeType
}
override fun isErrorType(): Boolean {
assertIsValid()
return coneType is ConeClassErrorType
}
override fun classIdIfClassTypeOrError(): ClassId {
assertIsValid()
return when (val coneType = coneType) {
is ConeClassLikeTypeImpl -> coneType.lookupTag.classId
is ConeClassErrorType -> throw ErrorTypeClassIdAccessException()
else -> throw ClassTypeExpectedException()
}
}
override fun asDenotableTypeStringRepresentation(): String {
assertIsValid()
return coneType.render()//TODO
}
override fun isEqualTo(other: TypeInfo): Boolean {
assertIsValid()
other.assertIsValid()
check(other is ConeTypeInfo)
return AbstractTypeChecker.equalTypes(
typeCheckerContext as AbstractTypeCheckerContext,
coneType,
other.coneType
)
}
override fun isSubTypeOf(superType: TypeInfo): Boolean {
assertIsValid()
superType.assertIsValid()
check(superType is ConeTypeInfo)
return AbstractTypeChecker.isSubtypeOf(
typeCheckerContext as AbstractTypeCheckerContext,
coneType,
superType.coneType
)
}
override fun isDefinitelyNullable(): Boolean {
assertIsValid()
return coneType.nullability == ConeNullability.NULLABLE
}
override fun isDefinitelyNotNull(): Boolean {
assertIsValid()
return coneType.nullability == ConeNullability.NOT_NULL
}
override fun isValid(): Boolean {
if (coneTypeWeakRef.get() == null) return false
return validityToken.isValid()
}
override fun invalidationReason(): String {
if (coneTypeWeakRef.get() == null) return "Cone type was garbage collected"
return validityToken.invalidationReason()
}
private inline val coneType
get() = coneTypeWeakRef.get() ?: if (validityToken.isValid()) {
error("Cone type was garbage collected while analysis session is still valid")
} else {
error("Accessing the invalid coneType")
}
}
@@ -17,10 +17,7 @@ import org.jetbrains.kotlin.fir.resolve.transformers.firClassLike
import org.jetbrains.kotlin.fir.symbols.CallableId
import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.ConeTypeCheckerContext
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
import org.jetbrains.kotlin.fir.types.coneTypeUnsafe
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.idea.fir.*
import org.jetbrains.kotlin.idea.fir.low.level.api.LowLevelFirApiFacade
import org.jetbrains.kotlin.idea.frontend.api.*
@@ -40,7 +37,12 @@ class FirAnalysisSession(
) : FrontendAnalysisSession(element.project) {
internal val token get() = validityToken
internal val firSymbolBuilder = KtSymbolByFirBuilder(validityToken)
internal val firSymbolBuilder = KtSymbolByFirBuilder(
element.session.firSymbolProvider,
ConeTypeCheckerContext(isErrorTypeEqualsToAnything = true, isStubTypeEqualsToAnything = true, element.session),
validityToken
)
override val symbolProvider: KtSymbolProvider =
FirKtSymbolProvider(
this,
@@ -52,10 +54,10 @@ class FirAnalysisSession(
assertIsValid()
}
override fun getSmartCastedToTypes(expression: KtExpression): Collection<TypeInfo>? {
override fun getSmartCastedToTypes(expression: KtExpression): Collection<KtType>? {
assertIsValid()
// TODO filter out not used smartcasts
return expression.getOrBuildFirSafe<FirExpressionWithSmartcast>()?.typesFromSmartCast?.map { it.asTypeInfo(expression.session) }
return expression.getOrBuildFirSafe<FirExpressionWithSmartcast>()?.typesFromSmartCast?.map { it.asTypeInfo() }
}
@OptIn(ExperimentalStdlibApi::class)
@@ -70,13 +72,13 @@ class FirAnalysisSession(
return buildList {
(qualifiedExpression.dispatchReceiver as? FirExpressionWithSmartcast)?.let { smartCasted ->
ImplicitReceiverSmartCast(
smartCasted.typesFromSmartCast.map { it.asTypeInfo(session) },
smartCasted.typesFromSmartCast.map { it.asTypeInfo() },
ImplicitReceiverSmartcastKind.DISPATCH
)
}?.let(::add)
(qualifiedExpression.extensionReceiver as? FirExpressionWithSmartcast)?.let { smartCasted ->
ImplicitReceiverSmartCast(
smartCasted.typesFromSmartCast.map { it.asTypeInfo(session) },
smartCasted.typesFromSmartCast.map { it.asTypeInfo() },
ImplicitReceiverSmartcastKind.EXTENSION
)
}?.let(::add)
@@ -84,15 +86,15 @@ class FirAnalysisSession(
}
override fun getReturnTypeForKtDeclaration(declaration: KtDeclaration): TypeInfo {
override fun getReturnTypeForKtDeclaration(declaration: KtDeclaration): KtType {
assertIsValid()
val firDeclaration = declaration.getOrBuildFirOfType<FirCallableDeclaration<*>>()
return firDeclaration.returnTypeRef.coneType.asTypeInfo(declaration.session)
return firDeclaration.returnTypeRef.coneType.asTypeInfo()
}
override fun getKtExpressionType(expression: KtExpression): TypeInfo {
override fun getKtExpressionType(expression: KtExpression): KtType {
assertIsValid()
return expression.getOrBuildFirOfType<FirExpression>().typeRef.coneType.asTypeInfo(expression.session)
return expression.getOrBuildFirOfType<FirExpression>().typeRef.coneType.asTypeInfo()
}
override fun isSubclassOf(klass: KtClassOrObject, superClassId: ClassId): Boolean {
@@ -168,14 +170,7 @@ class FirAnalysisSession(
}
}
private fun ConeKotlinType.asTypeInfo(session: FirSession) =
ConeTypeInfo(this, createTypeCheckingContext(session), validityToken)
private fun createTypeCheckingContext(session: FirSession) = ConeTypeCheckerContext(
isErrorTypeEqualsToAnything = true, // TODO?
isStubTypeEqualsToAnything = true, // TODO?
session = session
)
private fun ConeKotlinType.asTypeInfo() = firSymbolBuilder.buildKtType(this)
companion object {
@@ -0,0 +1,134 @@
/*
* Copyright 2010-2020 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
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
import org.jetbrains.kotlin.idea.frontend.api.*
import org.jetbrains.kotlin.idea.frontend.api.KtTypeParameterType
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.cached
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtClassLikeSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtTypeParameterSymbol
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.AbstractTypeChecker
import org.jetbrains.kotlin.types.AbstractTypeCheckerContext
internal interface KtFirType : KtType, InvalidatableByValidityToken {
val coneType: ConeKotlinType
val typeCheckerContext: ConeTypeCheckerContext
override fun asStringForDebugging(): String = withValidityAssertion { coneType.render() }
override fun isEqualTo(other: KtType): Boolean = withValidityAssertion {
other.assertIsValid()
check(other is KtFirType)
return AbstractTypeChecker.equalTypes(
typeCheckerContext as AbstractTypeCheckerContext,
coneType,
other.coneType
)
}
override fun isSubTypeOf(superType: KtType): Boolean = withValidityAssertion {
superType.assertIsValid()
check(superType is KtFirType)
return AbstractTypeChecker.isSubtypeOf(
typeCheckerContext as AbstractTypeCheckerContext,
coneType,
superType.coneType
)
}
}
internal class KtFirClassType(
coneType: ConeClassLikeTypeImpl,
typeCheckerContext: ConeTypeCheckerContext,
override val token: Invalidatable,
private val firBuilder: KtSymbolByFirBuilder,
) : KtClassType(), KtFirType {
override val coneType by weakRef(coneType)
override val typeCheckerContext by weakRef(typeCheckerContext)
override val classId: ClassId get() = withValidityAssertion { coneType.lookupTag.classId }
override val classSymbol: KtClassLikeSymbol by cached {
firBuilder.buildClassLikeSymbolByLookupTag(coneType.lookupTag) ?: error("Class ${coneType.lookupTag} was not found")
}
override val typeArguments: List<KtTypeArgument> by cached {
coneType.typeArguments.map { typeArgument ->
firBuilder.buildTypeArgument(typeArgument)
}
}
override fun asString(): String = withValidityAssertion {
coneType.render() //todo
}
}
internal class KtFirErrorType(
coneType: ConeClassErrorType,
typeCheckerContext: ConeTypeCheckerContext,
override val token: Invalidatable,
) : KtErrorType(), KtFirType {
override val coneType by weakRef(coneType)
override val typeCheckerContext by weakRef(typeCheckerContext)
override val error: String get() = withValidityAssertion { coneType.reason }
}
internal class KtFirTypeParameterType(
coneType: ConeTypeParameterType,
typeCheckerContext: ConeTypeCheckerContext,
override val token: Invalidatable,
private val firBuilder: KtSymbolByFirBuilder,
) : KtTypeParameterType(), KtFirType {
override val coneType by weakRef(coneType)
override val typeCheckerContext by weakRef(typeCheckerContext)
override val name: Name get() = withValidityAssertion { coneType.lookupTag.name }
override val symbol: KtTypeParameterSymbol by cached {
firBuilder.buildTypeParameterSymbolByLookupTag(coneType.lookupTag)
?: error("Type parameter ${coneType.lookupTag} was not found")
}
override fun asString(): String = withValidityAssertion {
coneType.render() //todo
}
}
internal class KtFirFlexibleType(
coneType: ConeFlexibleType,
typeCheckerContext: ConeTypeCheckerContext,
override val token: Invalidatable,
private val firBuilder: KtSymbolByFirBuilder,
) : KtFlexibleType(), KtFirType {
override val coneType by weakRef(coneType)
override val typeCheckerContext by weakRef(typeCheckerContext)
override val lowerBound: KtType by cached { firBuilder.buildKtType(coneType.lowerBound) }
override val upperBound: KtType by cached { firBuilder.buildKtType(coneType.upperBound) }
}
internal class KtFirIntersectionType(
coneType: ConeIntersectionType,
typeCheckerContext: ConeTypeCheckerContext,
override val token: Invalidatable,
private val firBuilder: KtSymbolByFirBuilder,
) : KtIntersectionType(), KtFirType {
override val coneType by weakRef(coneType)
override val typeCheckerContext by weakRef(typeCheckerContext)
override val conjuncts: List<KtType> by cached {
coneType.intersectedTypes.map { conjunct -> firBuilder.buildKtType(conjunct) }
}
}
internal class KtFirTypeArgumentWithVariance(
override val type: KtType,
override val variance: KtTypeArgumentVariance
) : KtTypeArgumentWithVariance()
@@ -8,6 +8,14 @@ package org.jetbrains.kotlin.idea.frontend.api.fir
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.impl.FirValueParameterImpl
import org.jetbrains.kotlin.fir.resolve.providers.FirProvider
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
import org.jetbrains.kotlin.idea.frontend.api.*
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag
@@ -25,45 +33,122 @@ import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.KtFirFunctionValuePara
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtClassLikeSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtTypeParameterSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtVariableSymbol
internal class KtSymbolByFirBuilder(private val validityToken: Invalidatable) {
fun buildSymbol(fir: FirDeclaration): KtSymbol = when (fir) {
internal class KtSymbolByFirBuilder(
firProvider: FirSymbolProvider,
typeCheckerContext: ConeTypeCheckerContext,
private val project: Project,
override val token: ValidityOwner
) : ValidityOwnerByValidityToken {
private val firProvider by weakRef(firProvider)
private val typeCheckerContext by weakRef(typeCheckerContext)
private val symbolsCache = BuilderCache<FirDeclaration, KtSymbol>()
private val typesCache = BuilderCache<ConeKotlinType, KtType>()
fun buildSymbol(fir: FirDeclaration): KtSymbol = symbolsCache.cache(fir) {
when (fir) {
is FirRegularClass -> buildClassSymbol(fir)
is FirSimpleFunction -> buildFunctionSymbol(fir)
is FirProperty -> buildVariableSymbol(fir)
is FirValueParameterImpl -> buildParameterSymbol(fir)
is FirConstructor -> buildConstructorSymbol(fir)
is FirTypeParameter -> buildTypeParameterSymbol(fir)
is FirTypeAlias -> buildTypeAliasSymbol(fir)
is FirEnumEntry -> buildEnumEntrySymbol(fir)
is FirField -> buildFieldSymbol(fir)
is FirAnonymousFunction -> buildAnonymousFunctionSymbol(fir)
else ->
TODO(fir::class.toString())
}
}
fun buildClassLikeSymbol(fir: FirClassLikeDeclaration<*>): KtClassLikeSymbol = when (fir) {
is FirRegularClass -> buildClassSymbol(fir)
is FirSimpleFunction -> buildFunctionSymbol(fir)
is FirProperty -> buildVariableSymbol(fir)
is FirValueParameterImpl -> buildParameterSymbol(fir)
is FirConstructor -> buildConstructorSymbol(fir)
is FirTypeParameter -> buildTypeParameterSymbol(fir)
is FirTypeAlias -> buildTypeAliasSymbol(fir)
is FirEnumEntry -> buildEnumEntrySymbol(fir)
is FirField -> buildFieldSymbol(fir)
is FirAnonymousFunction -> buildAnonymousFunctionSymbol(fir)
else ->
TODO(fir::class.toString())
}
fun buildClassSymbol(fir: FirRegularClass) = KtFirClassOrObjectSymbol(fir, validityToken, this)
fun buildClassSymbol(fir: FirRegularClass) = symbolsCache.cache(fir) { KtFirClassOrObjectSymbol(fir, token, this) }
// TODO it can be a constructor parameter, which may be split into parameter & property
// we should handle them both
fun buildParameterSymbol(fir: FirValueParameterImpl) = KtFirFunctionValueParameterSymbol(fir, validityToken)
fun buildFirConstructorParameter(fir: FirValueParameterImpl) = KtFirConstructorValueParameterSymbol(fir, validityToken)
fun buildParameterSymbol(fir: FirValueParameterImpl) = symbolsCache.cache(fir) { KtFirFunctionValueParameterSymbol(fir, token, this) }
fun buildFirConstructorParameter(fir: FirValueParameterImpl) =
symbolsCache.cache(fir) { KtFirConstructorValueParameterSymbol(fir, token, this) }
fun buildFunctionSymbol(fir: FirSimpleFunction) = KtFirFunctionSymbol(fir, validityToken, this)
fun buildConstructorSymbol(fir: FirConstructor) = KtFirConstructorSymbol(fir, validityToken, this)
fun buildTypeParameterSymbol(fir: FirTypeParameter) = KtFirTypeParameterSymbol(fir, validityToken)
fun buildTypeAliasSymbol(fir: FirTypeAlias) = KtFirTypeAliasSymbol(fir, validityToken)
fun buildEnumEntrySymbol(fir: FirEnumEntry) = KtFirEnumEntrySymbol(fir, validityToken)
fun buildFieldSymbol(fir: FirField) = KtFirFieldSymbol(fir, validityToken)
fun buildAnonymousFunctionSymbol(fir: FirAnonymousFunction) = KtFirAnonymousFunctionSymbol(fir, validityToken, this)
fun buildFunctionSymbol(fir: FirSimpleFunction) = symbolsCache.cache(fir) { KtFirFunctionSymbol(fir, token, this) }
fun buildConstructorSymbol(fir: FirConstructor) = symbolsCache.cache(fir) { KtFirConstructorSymbol(fir, token, this) }
fun buildTypeParameterSymbol(fir: FirTypeParameter) = symbolsCache.cache(fir) { KtFirTypeParameterSymbol(fir, token) }
fun buildVariableSymbol(fir: FirProperty): KtVariableSymbol {
return when {
fir.isLocal -> KtFirLocalVariableSymbol(fir, validityToken)
else -> KtFirPropertySymbol(fir, validityToken)
fun buildTypeAliasSymbol(fir: FirTypeAlias) = symbolsCache.cache(fir) { KtFirTypeAliasSymbol(fir, token) }
fun buildEnumEntrySymbol(fir: FirEnumEntry) = symbolsCache.cache(fir) { KtFirEnumEntrySymbol(fir, token, this) }
fun buildFieldSymbol(fir: FirField) = symbolsCache.cache(fir) { KtFirFieldSymbol(fir, token, this) }
fun buildAnonymousFunctionSymbol(fir: FirAnonymousFunction) = symbolsCache.cache(fir) { KtFirAnonymousFunctionSymbol(fir, token, this) }
fun buildVariableSymbol(fir: FirProperty): KtVariableSymbol = symbolsCache.cache(fir) {
when {
fir.isLocal -> KtFirLocalVariableSymbol(fir, token, this)
else -> KtFirPropertySymbol(fir, token, this)
}
}
fun buildClassLikeSymbolByLookupTag(lookupTag: ConeClassLikeLookupTag): KtClassLikeSymbol? = withValidityAssertion {
firProvider.getSymbolByLookupTag(lookupTag)?.fir?.let(::buildClassLikeSymbol)
}
fun buildTypeParameterSymbolByLookupTag(lookupTag: ConeTypeParameterLookupTag): KtTypeParameterSymbol? = withValidityAssertion {
(firProvider.getSymbolByLookupTag(lookupTag) as? FirTypeParameterSymbol)?.fir?.let(::buildTypeParameterSymbol)
}
fun createPackageSymbolIfOneExists(packageFqName: FqName): KtFirPackageSymbol? {
val exists = firProvider.getPackage(packageFqName) != null
if (!exists) {
return null
}
return KtFirPackageSymbol(packageFqName, project, token)
}
fun buildTypeArgument(coneType: ConeTypeProjection): KtTypeArgument = when (coneType) {
is ConeStarProjection -> KtStarProjectionTypeArgument
is ConeKotlinTypeProjection -> KtFirTypeArgumentWithVariance(
buildKtType(coneType.type),
coneType.kind.toVariance()
)
}
private fun ProjectionKind.toVariance() = when (this) {
ProjectionKind.OUT -> KtTypeArgumentVariance.COVARIANT
ProjectionKind.IN -> KtTypeArgumentVariance.CONTRAVARIANT
ProjectionKind.INVARIANT -> KtTypeArgumentVariance.INVARIANT
ProjectionKind.STAR -> error("KtStarProjectionTypeArgument be directly created")
}
fun buildKtType(coneType: FirTypeRef): KtType = buildKtType(coneType.coneTypeUnsafe<ConeKotlinType>())
fun buildKtType(coneType: ConeKotlinType): KtType = typesCache.cache(coneType) {
when (coneType) {
is ConeClassLikeTypeImpl -> KtFirClassType(coneType, typeCheckerContext, token, this)
is ConeTypeParameterType -> KtFirTypeParameterType(coneType, typeCheckerContext, token, this)
is ConeClassErrorType -> KtFirErrorType(coneType, typeCheckerContext, token)
is ConeFlexibleType -> KtFirFlexibleType(coneType, typeCheckerContext, token, this)
is ConeIntersectionType -> KtFirIntersectionType(coneType, typeCheckerContext, token, this)
else -> TODO()
}
}
}
private class BuilderCache<From, To> {
// the capacity & load factor values here are default ones which are used ing java.util.Map
private val cache = ContainerUtil.createWeakMap<From, To>(16, .75f, ContainerUtil.identityStrategy())
inline fun <reified S : To> cache(key: From, calculation: () -> S): S =
cache.getOrPut(key, calculation) as S
}
internal fun FirElement.buildSymbol(builder: KtSymbolByFirBuilder) =
@@ -7,19 +7,14 @@ package org.jetbrains.kotlin.idea.frontend.api.fir.symbols
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction
import org.jetbrains.kotlin.fir.declarations.FirEnumEntry
import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.declarations.impl.FirValueParameterImpl
import org.jetbrains.kotlin.idea.fir.findPsi
import org.jetbrains.kotlin.idea.frontend.api.Invalidatable
import org.jetbrains.kotlin.idea.frontend.api.TypeInfo
import org.jetbrains.kotlin.idea.frontend.api.KtType
import org.jetbrains.kotlin.idea.frontend.api.fir.KtSymbolByFirBuilder
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.asTypeInfo
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.cached
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef
import org.jetbrains.kotlin.idea.frontend.api.symbols.*
import org.jetbrains.kotlin.idea.frontend.api.withValidityAssertion
import org.jetbrains.kotlin.name.Name
internal class KtFirAnonymousFunctionSymbol(
fir: FirAnonymousFunction,
@@ -29,7 +24,7 @@ internal class KtFirAnonymousFunctionSymbol(
override val fir: FirAnonymousFunction by weakRef(fir)
override val psi: PsiElement? by cached { fir.findPsi(fir.session) }
override val type: TypeInfo by cached { fir.returnTypeRef.asTypeInfo(fir.session, token) }
override val type: KtType by cached { builder.buildKtType(fir.returnTypeRef) }
override val valueParameters: List<KtParameterSymbol> by cached {
fir.valueParameters.map { valueParameter ->
check(valueParameter is FirValueParameterImpl)
@@ -12,9 +12,8 @@ import org.jetbrains.kotlin.fir.declarations.impl.FirValueParameterImpl
import org.jetbrains.kotlin.fir.resolve.firSymbolProvider
import org.jetbrains.kotlin.idea.fir.findPsi
import org.jetbrains.kotlin.idea.frontend.api.Invalidatable
import org.jetbrains.kotlin.idea.frontend.api.TypeInfo
import org.jetbrains.kotlin.idea.frontend.api.KtType
import org.jetbrains.kotlin.idea.frontend.api.fir.KtSymbolByFirBuilder
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.asTypeInfo
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.cached
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtClassOrObjectSymbol
@@ -31,7 +30,7 @@ internal class KtFirConstructorSymbol(
override val fir: FirConstructor by weakRef(fir)
override val psi: PsiElement? by cached { fir.findPsi(fir.session) }
override val type: TypeInfo by cached { fir.returnTypeRef.asTypeInfo(fir.session, token) }
override val type: KtType by cached { builder.buildKtType(fir.returnTypeRef) }
override val valueParameters: List<KtConstructorParameterSymbol> by cached {
fir.valueParameters.map { valueParameter ->
check(valueParameter is FirValueParameterImpl)
@@ -6,12 +6,11 @@
package org.jetbrains.kotlin.idea.frontend.api.fir.symbols
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.declarations.impl.FirValueParameterImpl
import org.jetbrains.kotlin.idea.fir.findPsi
import org.jetbrains.kotlin.idea.frontend.api.Invalidatable
import org.jetbrains.kotlin.idea.frontend.api.TypeInfo
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.asTypeInfo
import org.jetbrains.kotlin.idea.frontend.api.ValidityOwner
import org.jetbrains.kotlin.idea.frontend.api.KtType
import org.jetbrains.kotlin.idea.frontend.api.fir.KtSymbolByFirBuilder
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.cached
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef
import org.jetbrains.kotlin.idea.frontend.api.symbols.*
@@ -20,13 +19,14 @@ import org.jetbrains.kotlin.name.Name
internal class KtFirConstructorValueParameterSymbol(
fir: FirValueParameterImpl,
override val token: Invalidatable
override val token: ValidityOwner,
private val builder: KtSymbolByFirBuilder
) : KtConstructorParameterSymbol(), KtFirSymbol<FirValueParameterImpl> {
override val fir: FirValueParameterImpl by weakRef(fir)
override val psi: PsiElement? by cached { fir.findPsi(fir.session) }
override val name: Name get() = withValidityAssertion { fir.name }
override val type: TypeInfo by cached { fir.returnTypeRef.asTypeInfo(fir.session, token) }
override val type: KtType by cached { builder.buildKtType(fir.returnTypeRef) }
override val symbolKind: KtSymbolKind
get() = withValidityAssertion {
when {
@@ -7,26 +7,24 @@ package org.jetbrains.kotlin.idea.frontend.api.fir.symbols
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.fir.declarations.FirEnumEntry
import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.idea.fir.findPsi
import org.jetbrains.kotlin.idea.frontend.api.Invalidatable
import org.jetbrains.kotlin.idea.frontend.api.TypeInfo
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.asTypeInfo
import org.jetbrains.kotlin.idea.frontend.api.KtType
import org.jetbrains.kotlin.idea.frontend.api.fir.KtSymbolByFirBuilder
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.cached
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtEnumEntrySymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtLocalVariableSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbolKind
import org.jetbrains.kotlin.idea.frontend.api.withValidityAssertion
import org.jetbrains.kotlin.name.Name
internal class KtFirEnumEntrySymbol(
fir: FirEnumEntry,
override val token: Invalidatable
override val token: ValidityOwner,
private val builder: KtSymbolByFirBuilder
) : KtEnumEntrySymbol(), KtFirSymbol<FirEnumEntry> {
override val fir: FirEnumEntry by weakRef(fir)
override val psi: PsiElement? by cached { fir.findPsi(fir.session) }
override val name: Name get() = withValidityAssertion { fir.name }
override val type: TypeInfo by cached { fir.returnTypeRef.asTypeInfo(fir.session, token) }
override val type: KtType by cached { builder.buildKtType(fir.returnTypeRef) }
}
@@ -7,29 +7,25 @@ package org.jetbrains.kotlin.idea.frontend.api.fir.symbols
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.fir.declarations.FirField
import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.declarations.FirTypeParameter
import org.jetbrains.kotlin.idea.fir.findPsi
import org.jetbrains.kotlin.idea.frontend.api.Invalidatable
import org.jetbrains.kotlin.idea.frontend.api.TypeInfo
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.asTypeInfo
import org.jetbrains.kotlin.idea.frontend.api.KtType
import org.jetbrains.kotlin.idea.frontend.api.fir.KtSymbolByFirBuilder
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.cached
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtFieldSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtLocalVariableSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbolKind
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtTypeParameterSymbol
import org.jetbrains.kotlin.idea.frontend.api.withValidityAssertion
import org.jetbrains.kotlin.name.Name
internal class KtFirFieldSymbol(
fir: FirField,
override val token: Invalidatable
override val token: ValidityOwner,
private val builder: KtSymbolByFirBuilder
) : KtFieldSymbol(), KtFirSymbol<FirField> {
override val fir: FirField by weakRef(fir)
override val psi: PsiElement? by cached { fir.findPsi(fir.session) }
override val type: TypeInfo by cached { fir.returnTypeRef.asTypeInfo(fir.session, token) }
override val type: KtType by cached { builder.buildKtType(fir.returnTypeRef) }
override val isVal: Boolean get() = withValidityAssertion { fir.isVal }
override val name: Name get() = withValidityAssertion { fir.name }
}
@@ -13,9 +13,8 @@ import org.jetbrains.kotlin.fir.declarations.isOperator
import org.jetbrains.kotlin.fir.declarations.isSuspend
import org.jetbrains.kotlin.idea.fir.findPsi
import org.jetbrains.kotlin.idea.frontend.api.Invalidatable
import org.jetbrains.kotlin.idea.frontend.api.TypeInfo
import org.jetbrains.kotlin.idea.frontend.api.KtType
import org.jetbrains.kotlin.idea.frontend.api.fir.KtSymbolByFirBuilder
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.asTypeInfo
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.cached
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtFunctionSymbol
@@ -32,7 +31,7 @@ internal class KtFirFunctionSymbol(
override val fir: FirSimpleFunction by weakRef(fir)
override val psi: PsiElement? by cached { fir.findPsi(fir.session) }
override val name: Name get() = withValidityAssertion { fir.name }
override val type: TypeInfo by cached { fir.returnTypeRef.asTypeInfo(fir.session, token) }
override val type: KtType by cached { builder.buildKtType(fir.returnTypeRef) }
override val valueParameters: List<KtFirFunctionValueParameterSymbol> by cached {
fir.valueParameters.map { valueParameter ->
check(valueParameter is FirValueParameterImpl)
@@ -45,7 +44,7 @@ internal class KtFirFunctionSymbol(
}
}
override val isSuspend: Boolean get() = withValidityAssertion { fir.isSuspend }
override val receiverType: TypeInfo? by cached { fir.receiverTypeRef?.asTypeInfo(fir.session, token) }
override val receiverType: KtType? by cached { fir.receiverTypeRef?.let(builder::buildKtType) }
override val isOperator: Boolean get() = withValidityAssertion { fir.isOperator }
override val isExtension: Boolean get() = withValidityAssertion { fir.receiverTypeRef != null }
override val fqName: FqName? get() = withValidityAssertion { fir.symbol.callableId.asFqNameForDebugInfo() }
@@ -6,15 +6,13 @@
package org.jetbrains.kotlin.idea.frontend.api.fir.symbols
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.declarations.impl.FirValueParameterImpl
import org.jetbrains.kotlin.idea.fir.findPsi
import org.jetbrains.kotlin.idea.frontend.api.Invalidatable
import org.jetbrains.kotlin.idea.frontend.api.TypeInfo
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.asTypeInfo
import org.jetbrains.kotlin.idea.frontend.api.KtType
import org.jetbrains.kotlin.idea.frontend.api.fir.KtSymbolByFirBuilder
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.cached
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtLocalVariableSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSimpleFunctionParameterSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbolKind
import org.jetbrains.kotlin.idea.frontend.api.withValidityAssertion
@@ -22,13 +20,14 @@ import org.jetbrains.kotlin.name.Name
internal class KtFirFunctionValueParameterSymbol(
fir: FirValueParameterImpl,
override val token: Invalidatable
override val token: ValidityOwner,
private val builder: KtSymbolByFirBuilder
) : KtSimpleFunctionParameterSymbol(),
KtFirSymbol<FirValueParameterImpl> {
override val fir: FirValueParameterImpl by weakRef(fir)
override val psi: PsiElement? by cached { fir.findPsi(fir.session) }
override val name: Name get() = withValidityAssertion { fir.name }
override val type: TypeInfo by cached { fir.returnTypeRef.asTypeInfo(fir.session, token) }
override val type: KtType by cached { builder.buildKtType(fir.returnTypeRef) }
override val symbolKind: KtSymbolKind get() = KtSymbolKind.LOCAL
}
@@ -9,8 +9,8 @@ import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.idea.fir.findPsi
import org.jetbrains.kotlin.idea.frontend.api.Invalidatable
import org.jetbrains.kotlin.idea.frontend.api.TypeInfo
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.asTypeInfo
import org.jetbrains.kotlin.idea.frontend.api.KtType
import org.jetbrains.kotlin.idea.frontend.api.fir.KtSymbolByFirBuilder
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.cached
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtLocalVariableSymbol
@@ -20,7 +20,8 @@ import org.jetbrains.kotlin.name.Name
internal class KtFirLocalVariableSymbol(
fir: FirProperty,
override val token: Invalidatable
override val token: ValidityOwner,
private val builder: KtSymbolByFirBuilder
) : KtLocalVariableSymbol(),
KtFirSymbol<FirProperty> {
init {
@@ -32,6 +33,6 @@ internal class KtFirLocalVariableSymbol(
override val isVal: Boolean get() = withValidityAssertion { fir.isVal }
override val name: Name get() = withValidityAssertion { fir.name }
override val type: TypeInfo by cached { fir.returnTypeRef.asTypeInfo(fir.session, token) }
override val type: KtType by cached { builder.buildKtType(fir.returnTypeRef) }
override val symbolKind: KtSymbolKind get() = KtSymbolKind.LOCAL
}
@@ -9,8 +9,8 @@ import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.idea.fir.findPsi
import org.jetbrains.kotlin.idea.frontend.api.Invalidatable
import org.jetbrains.kotlin.idea.frontend.api.TypeInfo
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.asTypeInfo
import org.jetbrains.kotlin.idea.frontend.api.KtType
import org.jetbrains.kotlin.idea.frontend.api.fir.KtSymbolByFirBuilder
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.cached
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtPropertySymbol
@@ -21,7 +21,8 @@ import org.jetbrains.kotlin.name.Name
internal class KtFirPropertySymbol(
fir: FirProperty,
override val token: Invalidatable
override val token: ValidityOwner,
private val builder: KtSymbolByFirBuilder
) : KtPropertySymbol(), KtFirSymbol<FirProperty> {
init {
assert(!fir.isLocal)
@@ -33,8 +34,8 @@ internal class KtFirPropertySymbol(
override val fqName: FqName get() = withValidityAssertion { fir.symbol.callableId.asFqNameForDebugInfo() }
override val isVal: Boolean get() = withValidityAssertion { fir.isVal }
override val name: Name get() = withValidityAssertion { fir.name }
override val type: TypeInfo by cached { fir.returnTypeRef.asTypeInfo(fir.session, token) }
override val receiverType: TypeInfo? by cached { fir.returnTypeRef.asTypeInfo(fir.session, token) }
override val type: KtType by cached { builder.buildKtType(fir.returnTypeRef) }
override val receiverType: KtType? by cached { builder.buildKtType(fir.returnTypeRef) }
override val isExtension: Boolean get() = withValidityAssertion { fir.receiverTypeRef != null }
override val symbolKind: KtSymbolKind
get() = withValidityAssertion {
@@ -6,16 +6,11 @@
package org.jetbrains.kotlin.idea.frontend.api.fir.symbols
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.declarations.FirTypeParameter
import org.jetbrains.kotlin.idea.fir.findPsi
import org.jetbrains.kotlin.idea.frontend.api.Invalidatable
import org.jetbrains.kotlin.idea.frontend.api.TypeInfo
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.asTypeInfo
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.cached
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.weakRef
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtLocalVariableSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbolKind
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtTypeParameterSymbol
import org.jetbrains.kotlin.idea.frontend.api.withValidityAssertion
import org.jetbrains.kotlin.name.Name
@@ -1,24 +0,0 @@
/*
* Copyright 2010-2020 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.utils
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.types.ConeTypeCheckerContext
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.types.coneTypeUnsafe
import org.jetbrains.kotlin.idea.frontend.api.Invalidatable
import org.jetbrains.kotlin.idea.frontend.api.InvalidatableByValidityToken
import org.jetbrains.kotlin.idea.frontend.api.TypeInfo
import org.jetbrains.kotlin.idea.frontend.api.fir.ConeTypeInfo
internal fun FirTypeRef.asTypeInfo(session: FirSession, invalidatable: Invalidatable): TypeInfo {
val context = ConeTypeCheckerContext(
isErrorTypeEqualsToAnything = true,
isStubTypeEqualsToAnything = true,
session = session
)
return ConeTypeInfo(coneTypeUnsafe(), context, invalidatable)
}
@@ -11,7 +11,7 @@ import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.idea.addExternalTestFiles
import org.jetbrains.kotlin.idea.executeOnPooledThreadInReadAction
import org.jetbrains.kotlin.idea.frontend.api.CallInfo
import org.jetbrains.kotlin.idea.frontend.api.TypeInfo
import org.jetbrains.kotlin.idea.frontend.api.KtType
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtFunctionLikeSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtFunctionSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtParameterSymbol
@@ -85,7 +85,7 @@ abstract class AbstractResolveCallTest : @Suppress("DEPRECATION") KotlinLightCod
}
private fun CallInfo.stringRepresentation(): String {
fun TypeInfo.render() = asDenotableTypeStringRepresentation().replace('/', '.')
fun KtType.render() = asStringForDebugging().replace('/', '.')
fun Any.stringValue(): String? = when (this) {
is KtFunctionLikeSymbol -> buildString {
append(if (this@stringValue is KtFunctionSymbol) fqName else "<constructor>")