diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/fields/FirLightFieldEnumEntry.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/fields/FirLightFieldEnumEntry.kt index e7e77444465..9b1ed7206ee 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/fields/FirLightFieldEnumEntry.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/fields/FirLightFieldEnumEntry.kt @@ -67,6 +67,7 @@ internal class FirLightFieldForEnumEntry( private val _type: PsiType by lazyPub { analyzeWithSymbolAsContext(enumEntrySymbol) { enumEntrySymbol.annotatedType.type.asPsiType(this@FirLightFieldForEnumEntry) + ?: this@FirLightFieldForEnumEntry.nonExistentType() } } @@ -87,4 +88,4 @@ internal class FirLightFieldForEnumEntry( override fun equals(other: Any?): Boolean = other is FirLightFieldForEnumEntry && enumEntrySymbol == other.enumEntrySymbol -} \ No newline at end of file +} diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/fields/FirLightFieldForObjectSymbol.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/fields/FirLightFieldForObjectSymbol.kt index 0c45b184fdd..ca0da21c6bd 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/fields/FirLightFieldForObjectSymbol.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/fields/FirLightFieldForObjectSymbol.kt @@ -41,6 +41,7 @@ internal class FirLightFieldForObjectSymbol( private val _type: PsiType by lazyPub { analyzeWithSymbolAsContext(objectSymbol) { objectSymbol.buildSelfClassType().asPsiType(this@FirLightFieldForObjectSymbol) + ?: this@FirLightFieldForObjectSymbol.nonExistentType() } } @@ -64,4 +65,4 @@ internal class FirLightFieldForObjectSymbol( override fun hashCode(): Int = kotlinOrigin.hashCode() override fun isValid(): Boolean = super.isValid() && objectSymbol.isValid() -} \ No newline at end of file +} diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/fields/FirLightFieldForPropertySymbol.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/fields/FirLightFieldForPropertySymbol.kt index f3464ef3198..8e05bed561a 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/fields/FirLightFieldForPropertySymbol.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/fields/FirLightFieldForPropertySymbol.kt @@ -30,6 +30,7 @@ internal class FirLightFieldForPropertySymbol( private val _returnedType: PsiType by lazyPub { analyzeWithSymbolAsContext(propertySymbol) { propertySymbol.annotatedType.type.asPsiType(this@FirLightFieldForPropertySymbol) + ?: this@FirLightFieldForPropertySymbol.nonExistentType() } } @@ -114,4 +115,4 @@ internal class FirLightFieldForPropertySymbol( override fun hashCode(): Int = kotlinOrigin.hashCode() override fun isValid(): Boolean = super.isValid() && propertySymbol.isValid() -} \ No newline at end of file +} diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/lightClassUtils.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/lightClassUtils.kt index 09da936a033..250c3058615 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/lightClassUtils.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/lightClassUtils.kt @@ -6,7 +6,9 @@ package org.jetbrains.kotlin.light.classes.symbol import com.intellij.openapi.project.Project +import com.intellij.psi.JavaPsiFacade import com.intellij.psi.PsiElement +import com.intellij.psi.PsiType import org.jetbrains.kotlin.idea.frontend.api.InvalidWayOfUsingAnalysisSession import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSessionProvider @@ -31,4 +33,7 @@ internal inline fun Project.analyzeWithSymbolAsContext( action: KtAnalysisSession.() -> R ): R { return KtAnalysisSessionProvider.getInstance(this).analyzeWithSymbolAsContext(contextSymbol, action) -} \ No newline at end of file +} + +internal fun PsiElement.nonExistentType(): PsiType = + JavaPsiFacade.getElementFactory(project).createTypeFromText("error.NonExistentClass", this) diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/methods/FirLightAccessorMethodForSymbol.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/methods/FirLightAccessorMethodForSymbol.kt index 7db7b64715d..fd62b21fbb9 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/methods/FirLightAccessorMethodForSymbol.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/methods/FirLightAccessorMethodForSymbol.kt @@ -149,14 +149,15 @@ internal class FirLightAccessorMethodForSymbol( override fun getNameIdentifier(): PsiIdentifier = _identifier - private val _returnedType: PsiType? by lazyPub { + private val _returnedType: PsiType by lazyPub { if (!isGetter) return@lazyPub PsiType.VOID analyzeWithSymbolAsContext(containingPropertySymbol) { containingPropertySymbol.annotatedType.type.asPsiType(this@FirLightAccessorMethodForSymbol) + ?: this@FirLightAccessorMethodForSymbol.nonExistentType() } } - override fun getReturnType(): PsiType? = _returnedType + override fun getReturnType(): PsiType = _returnedType override fun equals(other: Any?): Boolean = this === other || diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/methods/FirLightSimpleMethodForSymbol.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/methods/FirLightSimpleMethodForSymbol.kt index b5117fcbbb1..ebbdf7e6289 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/methods/FirLightSimpleMethodForSymbol.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/methods/FirLightSimpleMethodForSymbol.kt @@ -131,6 +131,7 @@ internal class FirLightSimpleMethodForSymbol( if (isVoidReturnType) return@lazyPub PsiType.VOID analyzeWithSymbolAsContext(functionSymbol) { functionSymbol.annotatedType.type.asPsiType(this@FirLightSimpleMethodForSymbol) + ?: this@FirLightSimpleMethodForSymbol.nonExistentType() } } @@ -142,4 +143,4 @@ internal class FirLightSimpleMethodForSymbol( override fun hashCode(): Int = functionSymbol.hashCode() override fun isValid(): Boolean = super.isValid() && functionSymbol.isValid() -} \ No newline at end of file +} diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/parameters/FirLightParameterBaseForSymbol.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/parameters/FirLightParameterBaseForSymbol.kt index 3b29ecc0c9c..441fbae6efc 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/parameters/FirLightParameterBaseForSymbol.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/parameters/FirLightParameterBaseForSymbol.kt @@ -48,6 +48,7 @@ internal abstract class FirLightParameterBaseForSymbol( private val _type by lazyPub { val convertedType = analyzeWithSymbolAsContext(parameterSymbol) { parameterSymbol.annotatedType.type.asPsiType(this@FirLightParameterBaseForSymbol) + ?: this@FirLightParameterBaseForSymbol.nonExistentType() } if (convertedType is PsiArrayType && parameterSymbol.isVararg) { PsiEllipsisType(convertedType.componentType, convertedType.annotationProvider) @@ -59,4 +60,4 @@ internal abstract class FirLightParameterBaseForSymbol( abstract override fun equals(other: Any?): Boolean abstract override fun hashCode(): Int -} \ No newline at end of file +} diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/parameters/FirLightParameterForReceiver.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/parameters/FirLightParameterForReceiver.kt index ebdc5f2cd6e..88d5dd3ae72 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/parameters/FirLightParameterForReceiver.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/parameters/FirLightParameterForReceiver.kt @@ -72,6 +72,7 @@ internal class FirLightParameterForReceiver private constructor( private val _type: PsiType by lazyPub { analyzeWithSymbolAsContext(context) { receiverTypeAndAnnotations.type.asPsiType(this@FirLightParameterForReceiver) + ?: this@FirLightParameterForReceiver.nonExistentType() } } diff --git a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/components/KtPsiTypeProvider.kt b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/components/KtPsiTypeProvider.kt index 807456414a5..363ad34754b 100644 --- a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/components/KtPsiTypeProvider.kt +++ b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/components/KtPsiTypeProvider.kt @@ -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) } diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/components/KtFirPsiTypeProvider.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/components/KtFirPsiTypeProvider.kt index ea6eb6a68d6..3d9b8ae9c60 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/components/KtFirPsiTypeProvider.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/components/KtFirPsiTypeProvider.kt @@ -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")) return psiContext.nonExistentType() + if (canonicalSignature.contains("L")) 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 } -} \ No newline at end of file +}