[AA LC] Create proper Psi types for types with errors inside

This commit is contained in:
Dmitriy Novozhilov
2022-09-21 16:13:30 +03:00
committed by Space Team
parent 3a536bb32f
commit a3b9f15ecc
18 changed files with 51 additions and 26 deletions
@@ -41,6 +41,7 @@ internal class KtFe10PsiTypeProvider(
useSitePosition: PsiElement,
mode: KtTypeMappingMode,
isAnnotationMethod: Boolean,
allowErrorTypes: Boolean
): PsiType? {
val kotlinType = (type as KtFe10Type).fe10Type
@@ -51,17 +51,18 @@ internal class KtFirPsiTypeProvider(
useSitePosition: PsiElement,
mode: KtTypeMappingMode,
isAnnotationMethod: Boolean,
allowErrorTypes: Boolean
): PsiType? {
val coneType = type.coneType
with(rootModuleSession.typeContext) {
if (coneType.contains { it.isError() }) {
if (!allowErrorTypes && coneType.contains { it.isError() }) {
return null
}
}
return coneType.simplifyType(rootModuleSession, useSitePosition)
.asPsiType(rootModuleSession, mode.toTypeMappingMode(type, isAnnotationMethod), useSitePosition)
.asPsiType(rootModuleSession, mode.toTypeMappingMode(type, isAnnotationMethod), useSitePosition, allowErrorTypes)
}
private fun KtTypeMappingMode.toTypeMappingMode(type: KtType, isAnnotationMethod: Boolean): TypeMappingMode {
@@ -186,9 +187,12 @@ private fun ConeKotlinType.asPsiType(
session: FirSession,
mode: TypeMappingMode,
useSitePosition: PsiElement,
allowErrorTypes: Boolean
): PsiType? {
if (this !is SimpleTypeMarker) return null
if (!allowErrorTypes && (this is ConeErrorType)) return null
val signatureWriter = BothSignatureWriter(BothSignatureWriter.Mode.SKIP_CHECKS)
//TODO Check thread safety
@@ -30,7 +30,7 @@ abstract class AbstractAnalysisApiExpressionPsiTypeProviderTest : AbstractAnalys
val actual = analyze(ktFile) {
val returnType = declarationAtCaret.getKtType()
?: error("Not a typable expression ${declarationAtCaret::class} ${declarationAtCaret.text}")
val psiType = returnType.asPsiType(psiContext)
val psiType = returnType.asPsiType(psiContext, allowErrorTypes = false)
buildString {
appendLine("KtType: ${returnType.render(position = Variance.INVARIANT)}")
appendLine("PsiType: $psiType")
@@ -39,11 +39,11 @@ abstract class AbstractAnalysisApiPsiTypeProviderTest : AbstractAnalysisApiBased
analyze(declaration) {
val ktType = declaration.getReturnKtType()
appendLine("KtType: ${ktType.render(position = Variance.INVARIANT)}")
appendLine("PsiType: ${ktType.asPsiType(psiContext)}")
appendLine("PsiType: ${ktType.asPsiType(psiContext, allowErrorTypes = false)}")
}
}
}
testServices.assertions.assertEqualsToTestDataFileSibling(actual)
}
}
}
@@ -17,6 +17,7 @@ public abstract class KtPsiTypeProvider : KtAnalysisSessionComponent() {
useSitePosition: PsiElement,
mode: KtTypeMappingMode,
isAnnotationMethod: Boolean,
allowErrorTypes: Boolean
): PsiType?
}
@@ -32,16 +33,19 @@ public interface KtPsiTypeProviderMixIn : KtAnalysisSessionMixIn {
* still use such local type. Otherwise, e.g., exposed to public as a return type, the resulting
* type will be approximated accordingly.
*
* Returns `null` if the conversion encounters any erroneous cases, e.g., errors in type arguments.
* If [allowErrorTypes] set to false then method 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` created from the [useSitePosition].
*
* If [allowErrorTypes] set to true then erroneous types will be replaced with `error.NonExistentClass` type
*/
public fun KtType.asPsiType(
useSitePosition: PsiElement,
allowErrorTypes: Boolean,
mode: KtTypeMappingMode = KtTypeMappingMode.DEFAULT,
isAnnotationMethod: Boolean = false,
): PsiType? =
withValidityAssertion { analysisSession.psiTypeProvider.asPsiType(this, useSitePosition, mode, isAnnotationMethod) }
isAnnotationMethod: Boolean = false
): PsiType? = withValidityAssertion {
analysisSession.psiTypeProvider.asPsiType(this, useSitePosition, mode, isAnnotationMethod, allowErrorTypes)
}
}
@@ -80,8 +80,8 @@ internal object PsiDeclarationAndKtSymbolEqualityChecker {
): Boolean {
// Shortcut: primitive void == Unit as a function return type
if (psi == PsiType.VOID && ktType.isUnit) return true
val ktTypeRendered = ktType.asPsiType(context, mode) ?: return false
val ktTypeRendered = ktType.asPsiType(context, allowErrorTypes = true, mode) ?: return false
val rendered = if (isVararg) ktTypeRendered.createArrayType() else ktTypeRendered
return rendered == psi
}
}
}
@@ -309,8 +309,9 @@ internal fun KtAnnotatedSymbol.computeThrowsList(
is KtNonLocalKClassAnnotationValue -> {
val psiType = buildClassType(annotationValue.classId).asPsiType(
useSitePosition,
allowErrorTypes = true,
KtTypeMappingMode.DEFAULT,
containingClass.isAnnotationType
containingClass.isAnnotationType,
)
(psiType as? PsiClassType)?.let {
builder.addReference(it)
@@ -72,8 +72,11 @@ internal class SymbolLightClassForEnumEntry(
private val _extendsList: PsiReferenceList? by lazyPub {
val mappedType = enumConstant.withEnumEntrySymbol { symbol ->
symbol.returnType.asPsiType(this@SymbolLightClassForEnumEntry, KtTypeMappingMode.SUPER_TYPE) as? PsiClassType
} ?: return@lazyPub null
symbol.returnType.asPsiType(
this@SymbolLightClassForEnumEntry,
allowErrorTypes = true,
KtTypeMappingMode.SUPER_TYPE
) as? PsiClassType} ?: return@lazyPub null
KotlinSuperTypeListBuilder(
kotlinOrigin = enumClass.kotlinOrigin?.getSuperTypeList(),
@@ -85,7 +85,7 @@ internal class SymbolLightFieldForEnumEntry(
private val _type: PsiType by lazyPub {
withEnumEntrySymbol { enumEntrySymbol ->
enumEntrySymbol.returnType.asPsiType(this@SymbolLightFieldForEnumEntry) ?: nonExistentType()
enumEntrySymbol.returnType.asPsiType(this@SymbolLightFieldForEnumEntry, allowErrorTypes = true) ?: nonExistentType()
}
}
@@ -84,7 +84,8 @@ internal class SymbolLightFieldForObject private constructor(
private val _type: PsiType by lazyPub {
withObjectDeclarationSymbol { objectSymbol ->
objectSymbol.buildSelfClassType().asPsiType(this@SymbolLightFieldForObject)
objectSymbol.buildSelfClassType()
.asPsiType(this@SymbolLightFieldForObject, allowErrorTypes = true)
} ?: nonExistentType()
}
@@ -70,10 +70,18 @@ internal class SymbolLightFieldForProperty private constructor(
when {
isDelegated ->
(kotlinOrigin as? KtProperty)?.delegateExpression?.let {
it.getKtType()?.asPsiType(this@SymbolLightFieldForProperty, KtTypeMappingMode.RETURN_TYPE)
it.getKtType()?.asPsiType(
this@SymbolLightFieldForProperty,
allowErrorTypes = true,
KtTypeMappingMode.RETURN_TYPE
)
}
else -> propertySymbol.returnType.asPsiType(this@SymbolLightFieldForProperty, KtTypeMappingMode.RETURN_TYPE)
else -> propertySymbol.returnType.asPsiType(
this@SymbolLightFieldForProperty,
allowErrorTypes = true,
KtTypeMappingMode.RETURN_TYPE
)
} ?: nonExistentType()
}
}
@@ -233,8 +233,9 @@ internal class SymbolLightAccessorMethod private constructor(
analyzeForLightClasses(ktModule) {
propertySymbol().returnType.asPsiType(
this@SymbolLightAccessorMethod,
KtTypeMappingMode.RETURN_TYPE,
containingClass.isAnnotationType,
allowErrorTypes = true,
KtTypeMappingMode.RETURN_TYPE,
containingClass.isAnnotationType,
)
} ?: nonExistentType()
}
@@ -185,6 +185,7 @@ internal class SymbolLightSimpleMethod(
ktType.asPsiType(
this@SymbolLightSimpleMethod,
allowErrorTypes = true,
KtTypeMappingMode.RETURN_TYPE,
containingClass.isAnnotationType,
)
@@ -75,7 +75,7 @@ internal abstract class SymbolLightParameterCommon(
else -> KtTypeMappingMode.VALUE_PARAMETER
}
ktType.asPsiType(this@SymbolLightParameterCommon, typeMappingMode)
ktType.asPsiType(this@SymbolLightParameterCommon, allowErrorTypes = true, typeMappingMode)
} ?: nonExistentType()
if (parameterSymbol.isVararg) {
@@ -85,7 +85,7 @@ internal class SymbolLightParameterForReceiver private constructor(
private val _type: PsiType by lazyPub {
withReceiverSymbol { receiver ->
receiver.type.asPsiType(this)
receiver.type.asPsiType(this, allowErrorTypes = true)
} ?: nonExistentType()
}
@@ -41,7 +41,7 @@ internal class SymbolLightSuspendContinuationParameter(
private val _type by lazyPub {
withFunctionSymbol { functionSymbol ->
buildClassType(StandardClassIds.Continuation) { argument(functionSymbol.returnType) }.asPsiType(this) ?: nonExistentType()
buildClassType(StandardClassIds.Continuation) { argument(functionSymbol.returnType) }.asPsiType(this, allowErrorTypes = true) ?: nonExistentType()
}
}
@@ -46,6 +46,7 @@ internal fun KtAnalysisSession.mapType(
if (type is KtClassErrorType) return null
val psiType = type.asPsiType(
psiContext,
allowErrorTypes = true,
mode,
)
return psiType as? PsiClassType
@@ -24,7 +24,7 @@ public final class JvmWildcardAnnotationsKt /* JvmWildcardAnnotationsKt*/ {
@kotlin.jvm.JvmSuppressWildcards(suppress = true)
@org.jetbrains.annotations.NotNull()
public static final error.NonExistentClass foo2();// foo2()
public static final Out<error.NonExistentClass> foo2();// foo2()
@kotlin.jvm.JvmSuppressWildcards(suppress = true)
public static final int bar(boolean, @org.jetbrains.annotations.NotNull() In<? super java.lang.Long>, long);// bar(boolean, In<? super java.lang.Long>, long)