FIR IDE: null out for erroneous PsiType conversion
This commit is contained in:
committed by
Ilya Kirillov
parent
8e242655f9
commit
5446a8ad10
+1
@@ -67,6 +67,7 @@ internal class FirLightFieldForEnumEntry(
|
|||||||
private val _type: PsiType by lazyPub {
|
private val _type: PsiType by lazyPub {
|
||||||
analyzeWithSymbolAsContext(enumEntrySymbol) {
|
analyzeWithSymbolAsContext(enumEntrySymbol) {
|
||||||
enumEntrySymbol.annotatedType.type.asPsiType(this@FirLightFieldForEnumEntry)
|
enumEntrySymbol.annotatedType.type.asPsiType(this@FirLightFieldForEnumEntry)
|
||||||
|
?: this@FirLightFieldForEnumEntry.nonExistentType()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
@@ -41,6 +41,7 @@ internal class FirLightFieldForObjectSymbol(
|
|||||||
private val _type: PsiType by lazyPub {
|
private val _type: PsiType by lazyPub {
|
||||||
analyzeWithSymbolAsContext(objectSymbol) {
|
analyzeWithSymbolAsContext(objectSymbol) {
|
||||||
objectSymbol.buildSelfClassType().asPsiType(this@FirLightFieldForObjectSymbol)
|
objectSymbol.buildSelfClassType().asPsiType(this@FirLightFieldForObjectSymbol)
|
||||||
|
?: this@FirLightFieldForObjectSymbol.nonExistentType()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
@@ -30,6 +30,7 @@ internal class FirLightFieldForPropertySymbol(
|
|||||||
private val _returnedType: PsiType by lazyPub {
|
private val _returnedType: PsiType by lazyPub {
|
||||||
analyzeWithSymbolAsContext(propertySymbol) {
|
analyzeWithSymbolAsContext(propertySymbol) {
|
||||||
propertySymbol.annotatedType.type.asPsiType(this@FirLightFieldForPropertySymbol)
|
propertySymbol.annotatedType.type.asPsiType(this@FirLightFieldForPropertySymbol)
|
||||||
|
?: this@FirLightFieldForPropertySymbol.nonExistentType()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+5
@@ -6,7 +6,9 @@
|
|||||||
package org.jetbrains.kotlin.light.classes.symbol
|
package org.jetbrains.kotlin.light.classes.symbol
|
||||||
|
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
|
import com.intellij.psi.JavaPsiFacade
|
||||||
import com.intellij.psi.PsiElement
|
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.InvalidWayOfUsingAnalysisSession
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession
|
import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSessionProvider
|
import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSessionProvider
|
||||||
@@ -32,3 +34,6 @@ internal inline fun <R> Project.analyzeWithSymbolAsContext(
|
|||||||
): R {
|
): R {
|
||||||
return KtAnalysisSessionProvider.getInstance(this).analyzeWithSymbolAsContext(contextSymbol, action)
|
return KtAnalysisSessionProvider.getInstance(this).analyzeWithSymbolAsContext(contextSymbol, action)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun PsiElement.nonExistentType(): PsiType =
|
||||||
|
JavaPsiFacade.getElementFactory(project).createTypeFromText("error.NonExistentClass", this)
|
||||||
|
|||||||
+3
-2
@@ -149,14 +149,15 @@ internal class FirLightAccessorMethodForSymbol(
|
|||||||
|
|
||||||
override fun getNameIdentifier(): PsiIdentifier = _identifier
|
override fun getNameIdentifier(): PsiIdentifier = _identifier
|
||||||
|
|
||||||
private val _returnedType: PsiType? by lazyPub {
|
private val _returnedType: PsiType by lazyPub {
|
||||||
if (!isGetter) return@lazyPub PsiType.VOID
|
if (!isGetter) return@lazyPub PsiType.VOID
|
||||||
analyzeWithSymbolAsContext(containingPropertySymbol) {
|
analyzeWithSymbolAsContext(containingPropertySymbol) {
|
||||||
containingPropertySymbol.annotatedType.type.asPsiType(this@FirLightAccessorMethodForSymbol)
|
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 =
|
override fun equals(other: Any?): Boolean =
|
||||||
this === other ||
|
this === other ||
|
||||||
|
|||||||
+1
@@ -131,6 +131,7 @@ internal class FirLightSimpleMethodForSymbol(
|
|||||||
if (isVoidReturnType) return@lazyPub PsiType.VOID
|
if (isVoidReturnType) return@lazyPub PsiType.VOID
|
||||||
analyzeWithSymbolAsContext(functionSymbol) {
|
analyzeWithSymbolAsContext(functionSymbol) {
|
||||||
functionSymbol.annotatedType.type.asPsiType(this@FirLightSimpleMethodForSymbol)
|
functionSymbol.annotatedType.type.asPsiType(this@FirLightSimpleMethodForSymbol)
|
||||||
|
?: this@FirLightSimpleMethodForSymbol.nonExistentType()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
@@ -48,6 +48,7 @@ internal abstract class FirLightParameterBaseForSymbol(
|
|||||||
private val _type by lazyPub {
|
private val _type by lazyPub {
|
||||||
val convertedType = analyzeWithSymbolAsContext(parameterSymbol) {
|
val convertedType = analyzeWithSymbolAsContext(parameterSymbol) {
|
||||||
parameterSymbol.annotatedType.type.asPsiType(this@FirLightParameterBaseForSymbol)
|
parameterSymbol.annotatedType.type.asPsiType(this@FirLightParameterBaseForSymbol)
|
||||||
|
?: this@FirLightParameterBaseForSymbol.nonExistentType()
|
||||||
}
|
}
|
||||||
if (convertedType is PsiArrayType && parameterSymbol.isVararg) {
|
if (convertedType is PsiArrayType && parameterSymbol.isVararg) {
|
||||||
PsiEllipsisType(convertedType.componentType, convertedType.annotationProvider)
|
PsiEllipsisType(convertedType.componentType, convertedType.annotationProvider)
|
||||||
|
|||||||
+1
@@ -72,6 +72,7 @@ internal class FirLightParameterForReceiver private constructor(
|
|||||||
private val _type: PsiType by lazyPub {
|
private val _type: PsiType by lazyPub {
|
||||||
analyzeWithSymbolAsContext(context) {
|
analyzeWithSymbolAsContext(context) {
|
||||||
receiverTypeAndAnnotations.type.asPsiType(this@FirLightParameterForReceiver)
|
receiverTypeAndAnnotations.type.asPsiType(this@FirLightParameterForReceiver)
|
||||||
|
?: this@FirLightParameterForReceiver.nonExistentType()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+11
-3
@@ -11,13 +11,21 @@ import org.jetbrains.kotlin.idea.frontend.api.types.KtType
|
|||||||
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode
|
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode
|
||||||
|
|
||||||
public abstract class KtPsiTypeProvider : KtAnalysisSessionComponent() {
|
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 {
|
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(
|
public fun KtType.asPsiType(
|
||||||
context: PsiElement,
|
context: PsiElement,
|
||||||
mode: TypeMappingMode = TypeMappingMode.DEFAULT
|
mode: TypeMappingMode = TypeMappingMode.DEFAULT,
|
||||||
): PsiType =
|
): PsiType? =
|
||||||
analysisSession.psiTypeProvider.asPsiType(this, context, mode)
|
analysisSession.psiTypeProvider.asPsiType(this, context, mode)
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-10
@@ -43,15 +43,15 @@ internal class KtFirPsiTypeProvider(
|
|||||||
override val token: ValidityToken,
|
override val token: ValidityToken,
|
||||||
) : KtPsiTypeProvider(), KtFirAnalysisSessionComponent {
|
) : 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)
|
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 {
|
private fun ConeKotlinType.simplifyType(session: FirSession, state: FirModuleResolveState): ConeKotlinType {
|
||||||
val substitutor = AnonymousTypesSubstitutor(session, state)
|
val substitutor = AnonymousTypesSubstitutor(session, state)
|
||||||
var currentType = this
|
var currentType = this
|
||||||
@@ -70,11 +70,12 @@ internal fun ConeKotlinType.asPsiType(
|
|||||||
state: FirModuleResolveState,
|
state: FirModuleResolveState,
|
||||||
mode: TypeMappingMode,
|
mode: TypeMappingMode,
|
||||||
psiContext: PsiElement,
|
psiContext: PsiElement,
|
||||||
): PsiType {
|
): PsiType? {
|
||||||
val correctedType = simplifyType(session, state)
|
val correctedType = simplifyType(session, state)
|
||||||
|
|
||||||
if (correctedType is ConeClassErrorType || correctedType !is SimpleTypeMarker) return psiContext.nonExistentType()
|
if (correctedType is ConeClassErrorType || correctedType !is SimpleTypeMarker) return null
|
||||||
if (correctedType.typeArguments.any { it is ConeClassErrorType }) return psiContext.nonExistentType()
|
|
||||||
|
if (correctedType.typeArguments.any { it is ConeClassErrorType }) return null
|
||||||
|
|
||||||
val signatureWriter = BothSignatureWriter(BothSignatureWriter.Mode.SKIP_CHECKS)
|
val signatureWriter = BothSignatureWriter(BothSignatureWriter.Mode.SKIP_CHECKS)
|
||||||
|
|
||||||
@@ -83,13 +84,14 @@ internal fun ConeKotlinType.asPsiType(
|
|||||||
|
|
||||||
val canonicalSignature = signatureWriter.toString()
|
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))
|
require(!canonicalSignature.contains(SpecialNames.ANONYMOUS_STRING))
|
||||||
|
|
||||||
val signature = StringCharacterIterator(canonicalSignature)
|
val signature = StringCharacterIterator(canonicalSignature)
|
||||||
val javaType = SignatureParsing.parseTypeString(signature, StubBuildingVisitor.GUESSING_MAPPER)
|
val javaType = SignatureParsing.parseTypeString(signature, StubBuildingVisitor.GUESSING_MAPPER)
|
||||||
val typeInfo = TypeInfo.fromString(javaType, false)
|
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')
|
val typeElement = ClsTypeElementImpl(psiContext, typeText, '\u0000')
|
||||||
return typeElement.type
|
return typeElement.type
|
||||||
|
|||||||
Reference in New Issue
Block a user