[Analysis API] separate non-class error types from class error types and add information about type qualifiers
it's needed for type printing in renderer
This commit is contained in:
@@ -76,4 +76,4 @@ internal fun FirAnnotation.toKtAnnotationApplication(useSiteSession: FirSession)
|
||||
useSiteSession,
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
+11
-5
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.util.withConeTypeEntry
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.withFirEntry
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.withFirSymbolEntry
|
||||
import org.jetbrains.kotlin.analysis.providers.createPackageProvider
|
||||
import org.jetbrains.kotlin.analysis.utils.errors.buildErrorWithAttachment
|
||||
import org.jetbrains.kotlin.builtins.functions.FunctionClassKind
|
||||
import org.jetbrains.kotlin.fir.*
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
@@ -34,6 +35,8 @@ import org.jetbrains.kotlin.fir.diagnostics.ConeCannotInferParameterType
|
||||
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
|
||||
import org.jetbrains.kotlin.fir.java.declarations.FirJavaField
|
||||
import org.jetbrains.kotlin.fir.renderer.FirRenderer
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnmatchedTypeArgumentsError
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnresolvedError
|
||||
import org.jetbrains.kotlin.fir.resolve.getContainingClass
|
||||
import org.jetbrains.kotlin.fir.resolve.getSymbolByLookupTag
|
||||
import org.jetbrains.kotlin.fir.resolve.inference.ConeTypeParameterBasedTypeVariable
|
||||
@@ -45,15 +48,14 @@ import org.jetbrains.kotlin.fir.scopes.impl.toConeType
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag
|
||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
|
||||
import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
import org.jetbrains.kotlin.analysis.utils.errors.buildErrorWithAttachment
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
import kotlin.contracts.contract
|
||||
|
||||
@@ -446,7 +448,11 @@ internal class KtSymbolByFirBuilder constructor(
|
||||
else KtFirUsualClassType(coneType, token, this@KtSymbolByFirBuilder)
|
||||
}
|
||||
is ConeTypeParameterType -> KtFirTypeParameterType(coneType, token, this@KtSymbolByFirBuilder)
|
||||
is ConeErrorType -> KtFirClassErrorType(coneType, token, this@KtSymbolByFirBuilder)
|
||||
is ConeErrorType -> when (val diagnostic = coneType.diagnostic) {
|
||||
is ConeUnresolvedError, is ConeUnmatchedTypeArgumentsError ->
|
||||
KtFirClassErrorType(coneType, diagnostic, token, this@KtSymbolByFirBuilder)
|
||||
else -> KtFirTypeErrorType(coneType, token, this@KtSymbolByFirBuilder)
|
||||
}
|
||||
is ConeDynamicType -> KtFirDynamicType(coneType, token, this@KtSymbolByFirBuilder)
|
||||
is ConeFlexibleType -> KtFirFlexibleType(coneType, token, this@KtSymbolByFirBuilder)
|
||||
is ConeIntersectionType -> KtFirIntersectionType(coneType, token, this@KtSymbolByFirBuilder)
|
||||
@@ -483,8 +489,8 @@ internal class KtSymbolByFirBuilder constructor(
|
||||
return buildKtType(coneType.coneType)
|
||||
}
|
||||
|
||||
fun buildTypeArgument(coneType: ConeTypeProjection): KtTypeArgument = when (coneType) {
|
||||
is ConeStarProjection -> KtStarProjectionTypeArgument(token)
|
||||
fun buildTypeProjection(coneType: ConeTypeProjection): KtTypeProjection = when (coneType) {
|
||||
is ConeStarProjection -> KtStarTypeProjection(token)
|
||||
is ConeKotlinTypeProjection -> KtTypeArgumentWithVariance(
|
||||
buildKtType(coneType.type),
|
||||
coneType.kind.toVariance(),
|
||||
|
||||
+4
-5
@@ -7,8 +7,8 @@ package org.jetbrains.kotlin.analysis.api.fir.components
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import org.jetbrains.kotlin.KtSourceElement
|
||||
import org.jetbrains.kotlin.analysis.api.KtStarProjectionTypeArgument
|
||||
import org.jetbrains.kotlin.analysis.api.KtTypeArgument
|
||||
import org.jetbrains.kotlin.analysis.api.KtStarTypeProjection
|
||||
import org.jetbrains.kotlin.analysis.api.KtTypeProjection
|
||||
import org.jetbrains.kotlin.analysis.api.KtTypeArgumentWithVariance
|
||||
import org.jetbrains.kotlin.analysis.api.diagnostics.KtDiagnosticWithPsi
|
||||
import org.jetbrains.kotlin.analysis.api.fir.KtFirAnalysisSession
|
||||
@@ -26,7 +26,6 @@ import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
|
||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccess
|
||||
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
|
||||
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.ChainedSubstitutor
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutorByMap
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
|
||||
@@ -66,9 +65,9 @@ internal interface KtFirAnalysisSessionComponent {
|
||||
return coneType
|
||||
}
|
||||
|
||||
val KtTypeArgument.coneTypeProjection: ConeTypeProjection
|
||||
val KtTypeProjection.coneTypeProjection: ConeTypeProjection
|
||||
get() = when (this) {
|
||||
is KtStarProjectionTypeArgument -> ConeStarProjection
|
||||
is KtStarTypeProjection -> ConeStarProjection
|
||||
is KtTypeArgumentWithVariance -> {
|
||||
typeContext.createTypeArgument(type.coneType, variance.convertVariance()) as ConeTypeProjection
|
||||
}
|
||||
|
||||
+1
-1
@@ -100,7 +100,7 @@ internal class ConeTypeIdeRenderer(
|
||||
if (options.renderUnresolvedTypeAsResolved) {
|
||||
when (diagnostic) {
|
||||
is ConeUnresolvedError -> {
|
||||
val qualifierRendered = diagnostic.qualifier?.let { FqName(it).render() }.orEmpty()
|
||||
val qualifierRendered = diagnostic.qualifier.let { FqName(it).render() }
|
||||
append(qualifierRendered)
|
||||
}
|
||||
|
||||
|
||||
+4
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.analysis.api.fir.types
|
||||
|
||||
import org.jetbrains.kotlin.analysis.api.KtTypeProjection
|
||||
import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationsList
|
||||
import org.jetbrains.kotlin.analysis.api.fir.KtSymbolByFirBuilder
|
||||
import org.jetbrains.kotlin.analysis.api.fir.annotations.KtFirAnnotationListForType
|
||||
@@ -23,6 +24,9 @@ internal class KtFirCapturedType(
|
||||
) : KtCapturedType(), KtFirType {
|
||||
override val nullability: KtTypeNullability get() = withValidityAssertion { coneType.nullability.asKtNullability() }
|
||||
|
||||
override val projection: KtTypeProjection
|
||||
get() = withValidityAssertion { builder.typeBuilder.buildTypeProjection(coneType.constructor.projection) }
|
||||
|
||||
override val annotationsList: KtAnnotationsList by cached {
|
||||
KtFirAnnotationListForType.create(coneType, builder.rootSession, token)
|
||||
}
|
||||
|
||||
+19
-1
@@ -9,29 +9,47 @@ import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationsList
|
||||
import org.jetbrains.kotlin.analysis.api.fir.KtSymbolByFirBuilder
|
||||
import org.jetbrains.kotlin.analysis.api.fir.annotations.KtFirAnnotationListForType
|
||||
import org.jetbrains.kotlin.analysis.api.fir.getCandidateSymbols
|
||||
import org.jetbrains.kotlin.analysis.api.fir.types.qualifiers.ErrorClassTypeQualifierBuilder
|
||||
import org.jetbrains.kotlin.analysis.api.fir.utils.cached
|
||||
import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeToken
|
||||
import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.KtClassLikeSymbol
|
||||
import org.jetbrains.kotlin.analysis.api.types.KtClassErrorType
|
||||
import org.jetbrains.kotlin.analysis.api.types.KtClassTypeQualifier
|
||||
import org.jetbrains.kotlin.analysis.api.types.KtTypeNullability
|
||||
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnmatchedTypeArgumentsError
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnresolvedError
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
|
||||
import org.jetbrains.kotlin.fir.types.ConeErrorType
|
||||
import org.jetbrains.kotlin.fir.types.renderForDebugging
|
||||
|
||||
internal class KtFirClassErrorType(
|
||||
override val coneType: ConeErrorType,
|
||||
private val coneDiagnostic: ConeDiagnostic,
|
||||
override val token: KtLifetimeToken,
|
||||
private val builder: KtSymbolByFirBuilder,
|
||||
) : KtClassErrorType(), KtFirType {
|
||||
|
||||
override val error: String get() = withValidityAssertion { coneType.diagnostic.reason }
|
||||
override val qualifiers: List<KtClassTypeQualifier> by cached {
|
||||
when (coneDiagnostic) {
|
||||
is ConeUnresolvedError ->
|
||||
ErrorClassTypeQualifierBuilder.createQualifiersForUnresolvedType(coneDiagnostic, builder)
|
||||
is ConeUnmatchedTypeArgumentsError ->
|
||||
ErrorClassTypeQualifierBuilder.createQualifiersForUnmatchedTypeArgumentsType(coneDiagnostic, builder)
|
||||
else -> error("Unsupported ${coneDiagnostic::class}")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override val nullability: KtTypeNullability get() = withValidityAssertion { coneType.nullability.asKtNullability() }
|
||||
override val errorMessage: String get() = withValidityAssertion { coneType.diagnostic.reason }
|
||||
|
||||
override val annotationsList: KtAnnotationsList by cached {
|
||||
KtFirAnnotationListForType.create(coneType, builder.rootSession, token)
|
||||
}
|
||||
|
||||
|
||||
override val candidateClassSymbols: Collection<KtClassLikeSymbol> by cached {
|
||||
val symbols = coneType.diagnostic.getCandidateSymbols().filterIsInstance<FirClassLikeSymbol<*>>()
|
||||
symbols.map { builder.classifierBuilder.buildClassLikeSymbol(it) }
|
||||
|
||||
+11
-9
@@ -5,15 +5,17 @@
|
||||
|
||||
package org.jetbrains.kotlin.analysis.api.fir.types
|
||||
|
||||
import org.jetbrains.kotlin.analysis.api.KtTypeArgument
|
||||
import org.jetbrains.kotlin.analysis.api.KtTypeProjection
|
||||
import org.jetbrains.kotlin.analysis.api.KtTypeArgumentWithVariance
|
||||
import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationsList
|
||||
import org.jetbrains.kotlin.analysis.api.fir.KtSymbolByFirBuilder
|
||||
import org.jetbrains.kotlin.analysis.api.fir.annotations.KtFirAnnotationListForType
|
||||
import org.jetbrains.kotlin.analysis.api.fir.types.qualifiers.UsualClassTypeQualifierBuilder
|
||||
import org.jetbrains.kotlin.analysis.api.fir.utils.cached
|
||||
import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeToken
|
||||
import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.KtClassLikeSymbol
|
||||
import org.jetbrains.kotlin.analysis.api.types.KtClassTypeQualifier
|
||||
import org.jetbrains.kotlin.analysis.api.types.KtFunctionalType
|
||||
import org.jetbrains.kotlin.analysis.api.types.KtType
|
||||
import org.jetbrains.kotlin.analysis.api.types.KtTypeNullability
|
||||
@@ -35,10 +37,10 @@ internal class KtFirFunctionalType(
|
||||
builder.classifierBuilder.buildClassLikeSymbolByLookupTag(coneType.lookupTag)
|
||||
?: errorWithFirSpecificEntries("Class was not found", coneType = coneType)
|
||||
}
|
||||
override val typeArguments: List<KtTypeArgument> by cached {
|
||||
coneType.typeArguments.map { typeArgument ->
|
||||
builder.typeBuilder.buildTypeArgument(typeArgument)
|
||||
}
|
||||
override val ownTypeArguments: List<KtTypeProjection> get() = withValidityAssertion { qualifiers.last().typeArguments }
|
||||
|
||||
override val qualifiers: List<KtClassTypeQualifier.KtResolvedClassTypeQualifier> by cached {
|
||||
UsualClassTypeQualifierBuilder.buildQualifiers(coneType, builder)
|
||||
}
|
||||
|
||||
override val annotationsList: KtAnnotationsList by cached {
|
||||
@@ -56,7 +58,7 @@ internal class KtFirFunctionalType(
|
||||
|
||||
override val receiverType: KtType?
|
||||
get() = withValidityAssertion {
|
||||
if (coneType.isExtensionFunctionType) (typeArguments.first() as KtTypeArgumentWithVariance).type
|
||||
if (coneType.isExtensionFunctionType) (ownTypeArguments.first() as KtTypeArgumentWithVariance).type
|
||||
else null
|
||||
}
|
||||
|
||||
@@ -66,13 +68,13 @@ internal class KtFirFunctionalType(
|
||||
}
|
||||
|
||||
override val parameterTypes: List<KtType> by cached {
|
||||
val parameterTypeArgs = if (coneType.isExtensionFunctionType) typeArguments.subList(1, typeArguments.lastIndex)
|
||||
else typeArguments.subList(0, typeArguments.lastIndex)
|
||||
val parameterTypeArgs = if (coneType.isExtensionFunctionType) ownTypeArguments.subList(1, ownTypeArguments.lastIndex)
|
||||
else ownTypeArguments.subList(0, ownTypeArguments.lastIndex)
|
||||
parameterTypeArgs.map { (it as KtTypeArgumentWithVariance).type }
|
||||
}
|
||||
|
||||
override val returnType: KtType
|
||||
get() = withValidityAssertion { (typeArguments.last() as KtTypeArgumentWithVariance).type }
|
||||
get() = withValidityAssertion { (ownTypeArguments.last() as KtTypeArgumentWithVariance).type }
|
||||
|
||||
override fun asStringForDebugging(): String = withValidityAssertion { coneType.renderForDebugging() }
|
||||
override fun equals(other: Any?) = typeEquals(other)
|
||||
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2010-2022 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.analysis.api.fir.types
|
||||
|
||||
import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationsList
|
||||
import org.jetbrains.kotlin.analysis.api.fir.KtSymbolByFirBuilder
|
||||
import org.jetbrains.kotlin.analysis.api.fir.annotations.KtFirAnnotationListForType
|
||||
import org.jetbrains.kotlin.analysis.api.fir.utils.cached
|
||||
import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeToken
|
||||
import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion
|
||||
import org.jetbrains.kotlin.analysis.api.types.KtTypeErrorType
|
||||
import org.jetbrains.kotlin.analysis.api.types.KtTypeNullability
|
||||
import org.jetbrains.kotlin.fir.diagnostics.ConeCannotInferParameterType
|
||||
import org.jetbrains.kotlin.fir.types.ConeErrorType
|
||||
import org.jetbrains.kotlin.fir.types.renderForDebugging
|
||||
|
||||
internal class KtFirTypeErrorType(
|
||||
override val coneType: ConeErrorType,
|
||||
override val token: KtLifetimeToken,
|
||||
private val builder: KtSymbolByFirBuilder,
|
||||
) : KtTypeErrorType(), KtFirType {
|
||||
|
||||
override val nullability: KtTypeNullability get() = withValidityAssertion { coneType.nullability.asKtNullability() }
|
||||
override val errorMessage: String get() = withValidityAssertion { coneType.diagnostic.reason }
|
||||
|
||||
override fun tryRenderAsNonErrorType(): String? = withValidityAssertion {
|
||||
when (val diagnostic = coneType.diagnostic) {
|
||||
is ConeCannotInferParameterType -> diagnostic.typeParameter.name.asString()
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
override val annotationsList: KtAnnotationsList by cached {
|
||||
KtFirAnnotationListForType.create(coneType, builder.rootSession, token)
|
||||
}
|
||||
|
||||
override fun asStringForDebugging(): String = withValidityAssertion { coneType.renderForDebugging() }
|
||||
override fun equals(other: Any?) = typeEquals(other)
|
||||
override fun hashCode() = typeHashcode()
|
||||
}
|
||||
+8
-5
@@ -5,10 +5,11 @@
|
||||
|
||||
package org.jetbrains.kotlin.analysis.api.fir.types
|
||||
|
||||
import org.jetbrains.kotlin.analysis.api.KtTypeArgument
|
||||
import org.jetbrains.kotlin.analysis.api.KtTypeProjection
|
||||
import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationsList
|
||||
import org.jetbrains.kotlin.analysis.api.fir.KtSymbolByFirBuilder
|
||||
import org.jetbrains.kotlin.analysis.api.fir.annotations.KtFirAnnotationListForType
|
||||
import org.jetbrains.kotlin.analysis.api.fir.types.qualifiers.UsualClassTypeQualifierBuilder
|
||||
import org.jetbrains.kotlin.analysis.api.fir.utils.cached
|
||||
import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeToken
|
||||
import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion
|
||||
@@ -30,12 +31,13 @@ internal class KtFirUsualClassType(
|
||||
builder.classifierBuilder.buildClassLikeSymbolByLookupTag(coneType.lookupTag)
|
||||
?: errorWithFirSpecificEntries("Class was not found", coneType = coneType)
|
||||
}
|
||||
override val typeArguments: List<KtTypeArgument> by cached {
|
||||
coneType.typeArguments.map { typeArgument ->
|
||||
builder.typeBuilder.buildTypeArgument(typeArgument)
|
||||
}
|
||||
|
||||
override val qualifiers by cached {
|
||||
UsualClassTypeQualifierBuilder.buildQualifiers(coneType, builder)
|
||||
}
|
||||
|
||||
override val ownTypeArguments: List<KtTypeProjection> get() = withValidityAssertion { qualifiers.last().typeArguments }
|
||||
|
||||
override val annotationsList: KtAnnotationsList by cached {
|
||||
KtFirAnnotationListForType.create(coneType, builder.rootSession, token)
|
||||
}
|
||||
@@ -45,3 +47,4 @@ internal class KtFirUsualClassType(
|
||||
override fun equals(other: Any?) = typeEquals(other)
|
||||
override fun hashCode() = typeHashcode()
|
||||
}
|
||||
|
||||
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright 2010-2022 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.analysis.api.fir.types.qualifiers
|
||||
|
||||
import org.jetbrains.kotlin.analysis.api.fir.KtSymbolByFirBuilder
|
||||
import org.jetbrains.kotlin.analysis.api.types.KtClassTypeQualifier
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.getContainingClassSymbol
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.*
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
|
||||
import org.jetbrains.kotlin.fir.types.toConeTypeProjection
|
||||
|
||||
internal object ErrorClassTypeQualifierBuilder {
|
||||
fun createQualifiersForUnresolvedType(
|
||||
coneDiagnostic: ConeUnresolvedError,
|
||||
builder: KtSymbolByFirBuilder
|
||||
): List<KtClassTypeQualifier> {
|
||||
return when (coneDiagnostic) {
|
||||
is ConeUnresolvedTypeQualifierError ->
|
||||
coneDiagnostic.qualifiers.map { part ->
|
||||
KtClassTypeQualifier.KtUnresolvedClassTypeQualifier(
|
||||
part.name,
|
||||
part.typeArgumentList.typeArguments.map { builder.typeBuilder.buildTypeProjection(it.toConeTypeProjection()) },
|
||||
builder.token
|
||||
)
|
||||
}
|
||||
|
||||
is ConeUnresolvedNameError -> listOf(
|
||||
KtClassTypeQualifier.KtUnresolvedClassTypeQualifier(coneDiagnostic.name, emptyList(), builder.token)
|
||||
)
|
||||
|
||||
is ConeUnresolvedReferenceError -> listOf(
|
||||
KtClassTypeQualifier.KtUnresolvedClassTypeQualifier(coneDiagnostic.name, emptyList(), builder.token)
|
||||
)
|
||||
|
||||
is ConeUnresolvedSymbolError ->
|
||||
coneDiagnostic.classId.asSingleFqName().pathSegments()
|
||||
.map { KtClassTypeQualifier.KtUnresolvedClassTypeQualifier(it, emptyList(), builder.token) }
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
fun createQualifiersForUnmatchedTypeArgumentsType(
|
||||
coneDiagnostic: ConeUnmatchedTypeArgumentsError,
|
||||
builder: KtSymbolByFirBuilder
|
||||
): List<KtClassTypeQualifier> {
|
||||
return createQualifiersByClassSymbol(coneDiagnostic.symbol, builder)
|
||||
}
|
||||
|
||||
private fun createQualifiersByClassSymbol(
|
||||
firSymbol: FirClassLikeSymbol<*>,
|
||||
builder: KtSymbolByFirBuilder
|
||||
): List<KtClassTypeQualifier.KtResolvedClassTypeQualifier> {
|
||||
return generateSequence(firSymbol) { firSymbol.getContainingClassSymbol(builder.rootSession) }.mapTo(mutableListOf()) { classSymbol ->
|
||||
KtClassTypeQualifier.KtResolvedClassTypeQualifier(
|
||||
builder.classifierBuilder.buildClassLikeSymbol(classSymbol),
|
||||
emptyList(),
|
||||
builder.token
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
+115
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright 2010-2022 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.analysis.api.fir.types.qualifiers
|
||||
|
||||
import org.jetbrains.kotlin.analysis.api.fir.KtSymbolByFirBuilder
|
||||
import org.jetbrains.kotlin.analysis.api.types.KtClassTypeQualifier
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.tryCollectDesignation
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.errorWithFirSpecificEntries
|
||||
import org.jetbrains.kotlin.fir.containingClassForLocal
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isInner
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isLocal
|
||||
import org.jetbrains.kotlin.fir.renderWithType
|
||||
import org.jetbrains.kotlin.fir.resolve.getContainingClass
|
||||
import org.jetbrains.kotlin.fir.resolve.toFirRegularClass
|
||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.LookupTagInternals
|
||||
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
|
||||
|
||||
internal object UsualClassTypeQualifierBuilder {
|
||||
fun buildQualifiers(
|
||||
coneType: ConeClassLikeTypeImpl,
|
||||
builder: KtSymbolByFirBuilder
|
||||
): List<KtClassTypeQualifier.KtResolvedClassTypeQualifier> {
|
||||
|
||||
val classSymbolToRender = coneType.lookupTag.toSymbol(builder.rootSession)
|
||||
?: errorWithFirSpecificEntries("ConeClassLikeTypeImpl is not resolved to symbol for on-error type", coneType = coneType) {
|
||||
withEntry("useSiteSession", builder.rootSession) { it.toString() }
|
||||
}
|
||||
|
||||
|
||||
if (classSymbolToRender !is FirRegularClassSymbol) {
|
||||
return listOf(
|
||||
KtClassTypeQualifier.KtResolvedClassTypeQualifier(
|
||||
builder.classifierBuilder.buildClassifierSymbol(classSymbolToRender),
|
||||
coneType.typeArguments.map { builder.typeBuilder.buildTypeProjection(it) },
|
||||
builder.token
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
val designation = classSymbolToRender.fir.let {
|
||||
val nonLocalDesignation = it.tryCollectDesignation()
|
||||
nonLocalDesignation?.toSequence(includeTarget = true)?.toList()
|
||||
?: collectDesignationPathForLocal(it)
|
||||
?: emptyList()
|
||||
}
|
||||
|
||||
|
||||
var typeParametersLeft = coneType.typeArguments.size
|
||||
|
||||
fun needToRenderTypeParameters(index: Int): Boolean {
|
||||
if (typeParametersLeft <= 0) return false
|
||||
return index == designation.lastIndex ||
|
||||
(designation[index] as? FirRegularClass)?.isInner == true ||
|
||||
(designation[index + 1] as? FirRegularClass)?.isInner == true
|
||||
}
|
||||
|
||||
val result = mutableListOf<KtClassTypeQualifier.KtResolvedClassTypeQualifier>()
|
||||
designation.forEachIndexed { index, currentClass ->
|
||||
check(currentClass is FirRegularClass)
|
||||
val typeParameters = if (needToRenderTypeParameters(index)) {
|
||||
val typeParametersCount = currentClass.typeParameters.count { it is FirTypeParameter }
|
||||
val begin = typeParametersLeft - typeParametersCount
|
||||
val end = typeParametersLeft
|
||||
check(begin >= 0)
|
||||
typeParametersLeft -= typeParametersCount
|
||||
coneType.typeArguments.slice(begin until end).map { builder.typeBuilder.buildTypeProjection(it) }
|
||||
} else emptyList()
|
||||
result += KtClassTypeQualifier.KtResolvedClassTypeQualifier(
|
||||
builder.classifierBuilder.buildClassifierSymbol(currentClass.symbol),
|
||||
typeParameters,
|
||||
builder.token
|
||||
)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private fun FirRegularClass.collectForLocal(): List<FirClassLikeDeclaration> {
|
||||
require(isLocal)
|
||||
var containingClassLookUp = containingClassForLocal()
|
||||
val designation = mutableListOf<FirClassLikeDeclaration>(this)
|
||||
@OptIn(LookupTagInternals::class)
|
||||
while (containingClassLookUp != null && containingClassLookUp.classId.isLocal) {
|
||||
val currentClass = containingClassLookUp.toFirRegularClass(moduleData.session) ?: break
|
||||
designation.add(currentClass)
|
||||
containingClassLookUp = currentClass.containingClassForLocal()
|
||||
}
|
||||
return designation
|
||||
}
|
||||
|
||||
private fun collectDesignationPathForLocal(declaration: FirDeclaration): List<FirDeclaration>? {
|
||||
@OptIn(LookupTagInternals::class)
|
||||
val containingClass = when (declaration) {
|
||||
is FirCallableDeclaration -> declaration.getContainingClass(declaration.moduleData.session)
|
||||
is FirAnonymousObject -> return listOf(declaration)
|
||||
is FirClassLikeDeclaration -> declaration.let {
|
||||
if (!declaration.isLocal) return null
|
||||
(it as? FirRegularClass)?.containingClassForLocal()?.toFirRegularClass(declaration.moduleData.session)
|
||||
}
|
||||
|
||||
else -> error("Invalid declaration ${declaration.renderWithType()}")
|
||||
} ?: return listOf(declaration)
|
||||
|
||||
return if (containingClass.isLocal) {
|
||||
containingClass.collectForLocal().reversed()
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user