FIR IDE: null out for erroneous PsiType conversion
This commit is contained in:
committed by
Ilya Kirillov
parent
8e242655f9
commit
5446a8ad10
+11
-3
@@ -11,13 +11,21 @@ import org.jetbrains.kotlin.idea.frontend.api.types.KtType
|
||||
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode
|
||||
|
||||
public abstract class KtPsiTypeProvider : KtAnalysisSessionComponent() {
|
||||
public abstract fun asPsiType(type: KtType, context: PsiElement, mode: TypeMappingMode): PsiType
|
||||
public abstract fun asPsiType(type: KtType, context: PsiElement, mode: TypeMappingMode): PsiType?
|
||||
}
|
||||
|
||||
public interface KtPsiTypeProviderMixIn : KtAnalysisSessionMixIn {
|
||||
/**
|
||||
* Converts the given [KtType] to [PsiType].
|
||||
*
|
||||
* Returns `null` if the conversion encounters any erroneous cases, e.g., errors in type arguments.
|
||||
* A client can handle such case in its own way. For instance,
|
||||
* * UAST will return `UastErrorType` as a default error type.
|
||||
* * LC will return `NonExistentClass` from the [context].
|
||||
*/
|
||||
public fun KtType.asPsiType(
|
||||
context: PsiElement,
|
||||
mode: TypeMappingMode = TypeMappingMode.DEFAULT
|
||||
): PsiType =
|
||||
mode: TypeMappingMode = TypeMappingMode.DEFAULT,
|
||||
): PsiType? =
|
||||
analysisSession.psiTypeProvider.asPsiType(this, context, mode)
|
||||
}
|
||||
|
||||
+13
-11
@@ -43,15 +43,15 @@ internal class KtFirPsiTypeProvider(
|
||||
override val token: ValidityToken,
|
||||
) : KtPsiTypeProvider(), KtFirAnalysisSessionComponent {
|
||||
|
||||
override fun asPsiType(type: KtType, context: PsiElement, mode: TypeMappingMode): PsiType = withValidityAssertion {
|
||||
override fun asPsiType(
|
||||
type: KtType,
|
||||
context: PsiElement,
|
||||
mode: TypeMappingMode,
|
||||
): PsiType? = withValidityAssertion {
|
||||
type.coneType.asPsiType(rootModuleSession, analysisSession.firResolveState, mode, context)
|
||||
}
|
||||
}
|
||||
|
||||
private fun PsiElement.nonExistentType() = JavaPsiFacade.getElementFactory(project)
|
||||
.createTypeFromText("error.NonExistentClass", this)
|
||||
|
||||
|
||||
private fun ConeKotlinType.simplifyType(session: FirSession, state: FirModuleResolveState): ConeKotlinType {
|
||||
val substitutor = AnonymousTypesSubstitutor(session, state)
|
||||
var currentType = this
|
||||
@@ -70,11 +70,12 @@ internal fun ConeKotlinType.asPsiType(
|
||||
state: FirModuleResolveState,
|
||||
mode: TypeMappingMode,
|
||||
psiContext: PsiElement,
|
||||
): PsiType {
|
||||
): PsiType? {
|
||||
val correctedType = simplifyType(session, state)
|
||||
|
||||
if (correctedType is ConeClassErrorType || correctedType !is SimpleTypeMarker) return psiContext.nonExistentType()
|
||||
if (correctedType.typeArguments.any { it is ConeClassErrorType }) return psiContext.nonExistentType()
|
||||
if (correctedType is ConeClassErrorType || correctedType !is SimpleTypeMarker) return null
|
||||
|
||||
if (correctedType.typeArguments.any { it is ConeClassErrorType }) return null
|
||||
|
||||
val signatureWriter = BothSignatureWriter(BothSignatureWriter.Mode.SKIP_CHECKS)
|
||||
|
||||
@@ -83,13 +84,14 @@ internal fun ConeKotlinType.asPsiType(
|
||||
|
||||
val canonicalSignature = signatureWriter.toString()
|
||||
|
||||
if (canonicalSignature.contains("L<error>")) return psiContext.nonExistentType()
|
||||
if (canonicalSignature.contains("L<error>")) return null
|
||||
|
||||
require(!canonicalSignature.contains(SpecialNames.ANONYMOUS_STRING))
|
||||
|
||||
val signature = StringCharacterIterator(canonicalSignature)
|
||||
val javaType = SignatureParsing.parseTypeString(signature, StubBuildingVisitor.GUESSING_MAPPER)
|
||||
val typeInfo = TypeInfo.fromString(javaType, false)
|
||||
val typeText = TypeInfo.createTypeText(typeInfo) ?: return psiContext.nonExistentType()
|
||||
val typeText = TypeInfo.createTypeText(typeInfo) ?: return null
|
||||
|
||||
val typeElement = ClsTypeElementImpl(psiContext, typeText, '\u0000')
|
||||
return typeElement.type
|
||||
@@ -124,4 +126,4 @@ private class AnonymousTypesSubstitutor(
|
||||
return if (type.nullability.isNullable) session.builtinTypes.nullableAnyType.type
|
||||
else session.builtinTypes.anyType.type
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user