FIR LC: do not use fir directly to create PSI types
This commit is contained in:
+1
-1
@@ -18,6 +18,6 @@ public interface KtPsiTypeProviderMixIn : KtAnalysisSessionMixIn {
|
||||
public fun KtType.asPsiType(
|
||||
context: PsiElement,
|
||||
mode: TypeMappingMode = TypeMappingMode.DEFAULT
|
||||
): PsiType? =
|
||||
): PsiType =
|
||||
analysisSession.psiTypeProvider.asPsiType(this, context, mode)
|
||||
}
|
||||
|
||||
+6
-4
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.idea.frontend.api.fir.analyzeWithSymbolAsContext
|
||||
import org.jetbrains.kotlin.idea.frontend.api.isValid
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtEnumEntrySymbol
|
||||
import org.jetbrains.kotlin.load.java.structure.LightClassOriginKind
|
||||
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode
|
||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||
|
||||
internal class FirLightClassForEnumEntry(
|
||||
@@ -83,10 +84,11 @@ internal class FirLightClassForEnumEntry(
|
||||
override fun isEnum(): Boolean = false
|
||||
|
||||
private val _extendsList: PsiReferenceList? by lazyPub {
|
||||
|
||||
val mappedType = enumEntrySymbol.annotatedType
|
||||
.mapSupertype(this@FirLightClassForEnumEntry)
|
||||
?: return@lazyPub null
|
||||
val mappedType = analyzeWithSymbolAsContext(enumEntrySymbol) {
|
||||
enumEntrySymbol.annotatedType
|
||||
.type.asPsiType(this@FirLightClassForEnumEntry, TypeMappingMode.SUPER_TYPE) as? PsiClassType
|
||||
?: return@lazyPub null
|
||||
}
|
||||
|
||||
KotlinSuperTypeListBuilder(
|
||||
kotlinOrigin = enumClass.kotlinOrigin?.getSuperTypeList(),
|
||||
|
||||
+7
-1
@@ -315,7 +315,13 @@ internal fun FirLightClassBase.createInheritanceList(forExtendsList: Boolean, su
|
||||
//TODO Add support for kotlin.collections.
|
||||
superTypes.asSequence()
|
||||
.filter { it.type.needToAddTypeIntoList() }
|
||||
.mapNotNull { it.mapSupertype(this, kotlinCollectionAsIs = true) }
|
||||
.mapNotNull { typeAnnotated ->
|
||||
val type = typeAnnotated.type
|
||||
if (type !is KtNonErrorClassType) return@mapNotNull null
|
||||
analyzeWithSymbolAsContext(type.classSymbol) {
|
||||
mapSuperType(type, this@createInheritanceList, kotlinCollectionAsIs = true)
|
||||
}
|
||||
}
|
||||
.forEach { listBuilder.addReference(it) }
|
||||
|
||||
return listBuilder
|
||||
|
||||
+4
-1
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.asJava.classes.*
|
||||
import org.jetbrains.kotlin.asJava.elements.FirLightIdentifier
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||
import org.jetbrains.kotlin.idea.asJava.*
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.analyzeWithSymbolAsContext
|
||||
import org.jetbrains.kotlin.idea.frontend.api.isValid
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtEnumEntrySymbol
|
||||
import org.jetbrains.kotlin.psi.KtEnumEntry
|
||||
@@ -65,7 +66,9 @@ internal class FirLightFieldForEnumEntry(
|
||||
override fun getName(): String = enumEntrySymbol.name.asString()
|
||||
|
||||
private val _type: PsiType by lazyPub {
|
||||
enumEntrySymbol.annotatedType.asPsiType(enumEntrySymbol, this@FirLightFieldForEnumEntry, FirResolvePhase.TYPES)
|
||||
analyzeWithSymbolAsContext(enumEntrySymbol) {
|
||||
enumEntrySymbol.annotatedType.type.asPsiType(this@FirLightFieldForEnumEntry)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getType(): PsiType = _type
|
||||
|
||||
+5
-1
@@ -10,8 +10,10 @@ import org.jetbrains.kotlin.asJava.builder.LightMemberOrigin
|
||||
import org.jetbrains.kotlin.asJava.classes.KtLightClass
|
||||
import org.jetbrains.kotlin.asJava.classes.lazyPub
|
||||
import org.jetbrains.kotlin.asJava.elements.FirLightIdentifier
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.analyzeWithSymbolAsContext
|
||||
import org.jetbrains.kotlin.idea.frontend.api.isValid
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtNamedClassOrObjectSymbol
|
||||
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
|
||||
internal class FirLightFieldForObjectSymbol(
|
||||
@@ -40,7 +42,9 @@ internal class FirLightFieldForObjectSymbol(
|
||||
override fun getModifierList(): PsiModifierList? = _modifierList
|
||||
|
||||
private val _type: PsiType by lazyPub {
|
||||
objectSymbol.typeForClassSymbol(this@FirLightFieldForObjectSymbol)
|
||||
analyzeWithSymbolAsContext(objectSymbol) {
|
||||
objectSymbol.buildSelfClassType().asPsiType(this@FirLightFieldForObjectSymbol)
|
||||
}
|
||||
}
|
||||
|
||||
private val _identifier: PsiIdentifier by lazyPub {
|
||||
|
||||
+4
-5
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.asJava.classes.lazyPub
|
||||
import org.jetbrains.kotlin.asJava.elements.FirLightIdentifier
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.analyzeWithSymbolAsContext
|
||||
import org.jetbrains.kotlin.idea.frontend.api.isValid
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtKotlinPropertySymbol
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtPropertySymbol
|
||||
@@ -30,11 +31,9 @@ internal class FirLightFieldForPropertySymbol(
|
||||
override val kotlinOrigin: KtDeclaration? = propertySymbol.psi as? KtDeclaration
|
||||
|
||||
private val _returnedType: PsiType by lazyPub {
|
||||
propertySymbol.annotatedType.asPsiType(
|
||||
propertySymbol,
|
||||
this@FirLightFieldForPropertySymbol,
|
||||
FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE
|
||||
)
|
||||
analyzeWithSymbolAsContext(propertySymbol) {
|
||||
propertySymbol.annotatedType.type.asPsiType(this@FirLightFieldForPropertySymbol)
|
||||
}
|
||||
}
|
||||
|
||||
private val _isDeprecated: Boolean by lazyPub {
|
||||
|
||||
@@ -6,40 +6,25 @@
|
||||
package org.jetbrains.kotlin.idea.asJava
|
||||
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.psi.impl.cache.TypeInfo
|
||||
import com.intellij.psi.impl.compiled.ClsTypeElementImpl
|
||||
import com.intellij.psi.impl.compiled.SignatureParsing
|
||||
import com.intellij.psi.impl.compiled.StubBuildingVisitor
|
||||
import com.intellij.util.IncorrectOperationException
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightElement
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightMember
|
||||
import org.jetbrains.kotlin.codegen.signature.BothSignatureWriter
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.descriptors.Visibility
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.backend.jvm.jvmTypeMapper
|
||||
import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||
import org.jetbrains.kotlin.fir.declarations.FirConstructor
|
||||
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.modality
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.superConeTypes
|
||||
import org.jetbrains.kotlin.fir.isPrimitiveType
|
||||
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.AbstractConeSubstitutor
|
||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
||||
import org.jetbrains.kotlin.fir.typeContext
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirModuleResolveState
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.api.withFirDeclaration
|
||||
import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession
|
||||
import org.jetbrains.kotlin.idea.frontend.api.components.DefaultTypeClassIds
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.analyzeWithSymbolAsContext
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.KtFirSymbol
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.types.KtFirType
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.types.PublicTypeApproximator
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.*
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSimpleConstantValue
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolWithModality
|
||||
@@ -52,158 +37,34 @@ import org.jetbrains.kotlin.idea.frontend.api.types.KtTypeWithNullability
|
||||
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.SpecialNames
|
||||
import org.jetbrains.kotlin.types.model.SimpleTypeMarker
|
||||
import java.text.StringCharacterIterator
|
||||
import java.util.*
|
||||
|
||||
internal fun <L : Any> L.invalidAccess(): Nothing =
|
||||
error("Cls delegate shouldn't be accessed for fir light classes! Qualified name: ${javaClass.name}")
|
||||
|
||||
|
||||
private fun PsiElement.nonExistentType() = JavaPsiFacade.getElementFactory(project)
|
||||
.createTypeFromText("error.NonExistentClass", this)
|
||||
|
||||
internal fun KtCallableSymbol.asPsiType(parent: PsiElement, phase: FirResolvePhase): PsiType =
|
||||
annotatedType.asPsiType(this, parent, phase)
|
||||
|
||||
internal fun KtTypeAndAnnotations.asPsiType(
|
||||
context: KtSymbol,
|
||||
parent: PsiElement,
|
||||
phase: FirResolvePhase
|
||||
): PsiType {
|
||||
val type = this.type
|
||||
require(type is KtFirType)
|
||||
require(context is KtFirSymbol<*>)
|
||||
val session = context.firRef.withFir(phase) { it.moduleData.session }
|
||||
return type.coneType.asPsiType(session, context.firRef.resolveState, TypeMappingMode.DEFAULT, parent)
|
||||
}
|
||||
|
||||
internal fun KtNamedClassOrObjectSymbol.typeForClassSymbol(psiElement: PsiElement): PsiType {
|
||||
require(this is KtFirSymbol<*>)
|
||||
|
||||
val types = analyzeWithSymbolAsContext(this) {
|
||||
this@typeForClassSymbol.buildSelfClassType()
|
||||
}
|
||||
require(types is KtFirType)
|
||||
|
||||
val session = firRef.withFir { it.moduleData.session }
|
||||
return types.coneType.asPsiType(session, firRef.resolveState, TypeMappingMode.DEFAULT, psiElement)
|
||||
}
|
||||
|
||||
private class AnonymousTypesSubstitutor(
|
||||
private val session: FirSession,
|
||||
private val state: FirModuleResolveState,
|
||||
) : AbstractConeSubstitutor(session.typeContext) {
|
||||
override fun substituteType(type: ConeKotlinType): ConeKotlinType? {
|
||||
|
||||
if (type !is ConeClassLikeType) return null
|
||||
|
||||
val isAnonymous = type.classId.let { it?.shortClassName?.asString() == SpecialNames.ANONYMOUS_STRING }
|
||||
if (!isAnonymous) return null
|
||||
|
||||
fun ConeClassLikeType.isNotInterface(): Boolean {
|
||||
val firClassNode = lookupTag.toSymbol(session)?.fir as? FirClass ?: return false
|
||||
return firClassNode.withFirDeclaration(state) { firSuperClass ->
|
||||
firSuperClass.classKind != ClassKind.INTERFACE
|
||||
}
|
||||
}
|
||||
|
||||
val firClassNode = (type.lookupTag.toSymbol(session) as? FirClassSymbol)?.fir
|
||||
if (firClassNode != null) {
|
||||
val superTypesCones = firClassNode.withFirDeclaration(state, FirResolvePhase.SUPER_TYPES) {
|
||||
(it as? FirClass)?.superConeTypes
|
||||
}
|
||||
val superClass = superTypesCones?.firstOrNull { it.isNotInterface() }
|
||||
if (superClass != null) return superClass
|
||||
}
|
||||
|
||||
return if (type.nullability.isNullable) session.builtinTypes.nullableAnyType.type
|
||||
else session.builtinTypes.anyType.type
|
||||
}
|
||||
}
|
||||
|
||||
private fun ConeKotlinType.simplifyType(session: FirSession, state: FirModuleResolveState): ConeKotlinType {
|
||||
val substitutor = AnonymousTypesSubstitutor(session, state)
|
||||
var currentType = this
|
||||
do {
|
||||
val oldType = currentType
|
||||
currentType = currentType.fullyExpandedType(session)
|
||||
currentType = currentType.upperBoundIfFlexible()
|
||||
currentType = substitutor.substituteOrSelf(currentType)
|
||||
currentType = PublicTypeApproximator.approximateTypeToPublicDenotable(currentType, session) ?: currentType
|
||||
} while (oldType !== currentType)
|
||||
return currentType
|
||||
}
|
||||
|
||||
internal fun ConeKotlinType.asPsiType(
|
||||
session: FirSession,
|
||||
state: FirModuleResolveState,
|
||||
mode: TypeMappingMode,
|
||||
psiContext: PsiElement,
|
||||
): 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()
|
||||
|
||||
val signatureWriter = BothSignatureWriter(BothSignatureWriter.Mode.SKIP_CHECKS)
|
||||
|
||||
//TODO Check thread safety
|
||||
session.jvmTypeMapper.mapType(correctedType, mode, signatureWriter)
|
||||
|
||||
val canonicalSignature = signatureWriter.toString()
|
||||
|
||||
if (canonicalSignature.contains("L<error>")) return psiContext.nonExistentType()
|
||||
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 typeElement = ClsTypeElementImpl(psiContext, typeText, '\u0000')
|
||||
return typeElement.type
|
||||
}
|
||||
|
||||
private fun mapSupertype(
|
||||
psiContext: PsiElement,
|
||||
session: FirSession,
|
||||
firResolvePhase: FirModuleResolveState,
|
||||
supertype: ConeKotlinType,
|
||||
kotlinCollectionAsIs: Boolean = false
|
||||
) =
|
||||
supertype.asPsiType(
|
||||
session,
|
||||
firResolvePhase,
|
||||
if (kotlinCollectionAsIs) TypeMappingMode.SUPER_TYPE_KOTLIN_COLLECTIONS_AS_IS else TypeMappingMode.SUPER_TYPE,
|
||||
psiContext
|
||||
) as? PsiClassType
|
||||
|
||||
internal fun KtTypeAndAnnotations.mapSupertype(
|
||||
internal fun KtAnalysisSession.mapSuperType(
|
||||
type: KtTypeAndAnnotations,
|
||||
psiContext: PsiElement,
|
||||
kotlinCollectionAsIs: Boolean = false
|
||||
): PsiClassType? = type.mapSupertype(psiContext, kotlinCollectionAsIs)
|
||||
|
||||
internal fun KtType.mapSupertype(
|
||||
psiContext: PsiElement,
|
||||
kotlinCollectionAsIs: Boolean = false,
|
||||
): PsiClassType? {
|
||||
if (this !is KtNonErrorClassType) return null
|
||||
require(this is KtFirType)
|
||||
val contextSymbol = classSymbol
|
||||
require(contextSymbol is KtFirSymbol<*>)
|
||||
|
||||
val session = contextSymbol.firRef.withFir { it.moduleData.session }
|
||||
|
||||
return mapSupertype(
|
||||
psiContext,
|
||||
session,
|
||||
contextSymbol.firRef.resolveState,
|
||||
coneType,
|
||||
kotlinCollectionAsIs,
|
||||
)
|
||||
return mapSuperType(type.type, psiContext, kotlinCollectionAsIs)
|
||||
}
|
||||
|
||||
internal fun KtAnalysisSession.mapSuperType(
|
||||
type: KtType,
|
||||
psiContext: PsiElement,
|
||||
kotlinCollectionAsIs: Boolean = false
|
||||
): PsiClassType? {
|
||||
if (type !is KtNonErrorClassType) return null
|
||||
val psiType = type.asPsiType(
|
||||
psiContext,
|
||||
if (kotlinCollectionAsIs) TypeMappingMode.SUPER_TYPE_KOTLIN_COLLECTIONS_AS_IS else TypeMappingMode.SUPER_TYPE,
|
||||
)
|
||||
return psiType as? PsiClassType
|
||||
}
|
||||
|
||||
|
||||
internal enum class NullabilityType {
|
||||
Nullable,
|
||||
NotNull,
|
||||
|
||||
+4
-5
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.asJava.elements.FirLightIdentifier
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||
import org.jetbrains.kotlin.idea.asJava.parameters.FirLightSetterParameterForSymbol
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.analyzeWithSymbolAsContext
|
||||
import org.jetbrains.kotlin.idea.frontend.api.isValid
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.*
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi.getterName
|
||||
@@ -144,11 +145,9 @@ internal class FirLightAccessorMethodForSymbol(
|
||||
|
||||
private val _returnedType: PsiType? by lazyPub {
|
||||
if (!isGetter) return@lazyPub PsiType.VOID
|
||||
return@lazyPub containingPropertySymbol.annotatedType.asPsiType(
|
||||
context = containingPropertySymbol,
|
||||
parent = this@FirLightAccessorMethodForSymbol,
|
||||
phase = FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE
|
||||
)
|
||||
analyzeWithSymbolAsContext(containingPropertySymbol) {
|
||||
containingPropertySymbol.annotatedType.type.asPsiType(this@FirLightAccessorMethodForSymbol)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getReturnType(): PsiType? = _returnedType
|
||||
|
||||
+4
-1
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.asJava.builder.LightMemberOrigin
|
||||
import org.jetbrains.kotlin.asJava.classes.lazyPub
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||
import org.jetbrains.kotlin.idea.asJava.elements.FirLightTypeParameterListForSymbol
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.analyzeWithSymbolAsContext
|
||||
import org.jetbrains.kotlin.idea.frontend.api.isValid
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtFunctionSymbol
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
@@ -127,7 +128,9 @@ internal class FirLightSimpleMethodForSymbol(
|
||||
|
||||
private val _returnedType: PsiType by lazyPub {
|
||||
if (isVoidReturnType) return@lazyPub PsiType.VOID
|
||||
functionSymbol.asPsiType(this@FirLightSimpleMethodForSymbol, FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE)
|
||||
analyzeWithSymbolAsContext(functionSymbol) {
|
||||
functionSymbol.annotatedType.type.asPsiType(this@FirLightSimpleMethodForSymbol)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getReturnType(): PsiType = _returnedType
|
||||
|
||||
+4
-2
@@ -9,6 +9,7 @@ import com.intellij.psi.*
|
||||
import org.jetbrains.kotlin.asJava.classes.lazyPub
|
||||
import org.jetbrains.kotlin.asJava.elements.FirLightIdentifier
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.analyzeWithSymbolAsContext
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.*
|
||||
import org.jetbrains.kotlin.psi.KtParameter
|
||||
|
||||
@@ -45,8 +46,9 @@ internal abstract class FirLightParameterBaseForSymbol(
|
||||
override fun getNameIdentifier(): PsiIdentifier = _identifier
|
||||
|
||||
private val _type by lazyPub {
|
||||
val convertedType = parameterSymbol.asPsiType(this, FirResolvePhase.TYPES)
|
||||
|
||||
val convertedType = analyzeWithSymbolAsContext(parameterSymbol) {
|
||||
parameterSymbol.annotatedType.type.asPsiType(this@FirLightParameterBaseForSymbol)
|
||||
}
|
||||
if (convertedType is PsiArrayType && parameterSymbol.isVararg) {
|
||||
PsiEllipsisType(convertedType.componentType, convertedType.annotationProvider)
|
||||
} else convertedType
|
||||
|
||||
+4
-1
@@ -12,6 +12,7 @@ import com.intellij.psi.PsiType
|
||||
import org.jetbrains.kotlin.asJava.classes.lazyPub
|
||||
import org.jetbrains.kotlin.codegen.AsmUtil
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.analyzeWithSymbolAsContext
|
||||
import org.jetbrains.kotlin.idea.frontend.api.isValid
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtCallableSymbol
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbol
|
||||
@@ -71,7 +72,9 @@ internal class FirLightParameterForReceiver private constructor(
|
||||
}
|
||||
|
||||
private val _type: PsiType by lazyPub {
|
||||
receiverTypeAndAnnotations.asPsiType(context, method, FirResolvePhase.TYPES)
|
||||
analyzeWithSymbolAsContext(context) {
|
||||
receiverTypeAndAnnotations.type.asPsiType(this@FirLightParameterForReceiver)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getType(): PsiType = _type
|
||||
|
||||
+12
-12
@@ -21,10 +21,12 @@ import org.jetbrains.kotlin.asJava.elements.KtLightDeclaration
|
||||
import org.jetbrains.kotlin.idea.KotlinLanguage
|
||||
import org.jetbrains.kotlin.idea.asJava.basicIsEquivalentTo
|
||||
import org.jetbrains.kotlin.idea.asJava.invalidAccess
|
||||
import org.jetbrains.kotlin.idea.asJava.mapSupertype
|
||||
import org.jetbrains.kotlin.idea.asJava.mapSuperType
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.analyzeWithSymbolAsContext
|
||||
import org.jetbrains.kotlin.idea.frontend.api.isValid
|
||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.idea.frontend.api.types.KtNonErrorClassType
|
||||
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode
|
||||
import org.jetbrains.kotlin.name.StandardClassIds
|
||||
import org.jetbrains.kotlin.psi.KtTypeParameter
|
||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||
@@ -61,17 +63,15 @@ internal class FirLightTypeParameter(
|
||||
language = language,
|
||||
role = PsiReferenceList.Role.EXTENDS_LIST
|
||||
)
|
||||
|
||||
typeParameterSymbol.upperBounds
|
||||
.filterIsInstance<KtNonErrorClassType>()
|
||||
.filter { it.classId != StandardClassIds.Any }
|
||||
.mapNotNull {
|
||||
it.mapSupertype(
|
||||
psiContext = this,
|
||||
kotlinCollectionAsIs = true,
|
||||
)
|
||||
}
|
||||
.forEach { listBuilder.addReference(it) }
|
||||
analyzeWithSymbolAsContext(typeParameterSymbol) {
|
||||
typeParameterSymbol.upperBounds
|
||||
.filterIsInstance<KtNonErrorClassType>()
|
||||
.filter { it.classId != StandardClassIds.Any }
|
||||
.mapNotNull {
|
||||
mapSuperType(it, this@FirLightTypeParameter, kotlinCollectionAsIs = true)
|
||||
}
|
||||
.forEach { listBuilder.addReference(it) }
|
||||
}
|
||||
|
||||
listBuilder
|
||||
}
|
||||
|
||||
+102
-1
@@ -5,15 +5,38 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea.frontend.api.fir.components
|
||||
|
||||
import com.intellij.psi.JavaPsiFacade
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiType
|
||||
import org.jetbrains.kotlin.idea.asJava.asPsiType
|
||||
import com.intellij.psi.impl.cache.TypeInfo
|
||||
import com.intellij.psi.impl.compiled.ClsTypeElementImpl
|
||||
import com.intellij.psi.impl.compiled.SignatureParsing
|
||||
import com.intellij.psi.impl.compiled.StubBuildingVisitor
|
||||
import org.jetbrains.kotlin.codegen.signature.BothSignatureWriter
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.backend.jvm.jvmTypeMapper
|
||||
import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.superConeTypes
|
||||
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.AbstractConeSubstitutor
|
||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
||||
import org.jetbrains.kotlin.fir.typeContext
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirModuleResolveState
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.api.withFirDeclaration
|
||||
import org.jetbrains.kotlin.idea.frontend.api.components.KtPsiTypeProvider
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.KtFirAnalysisSession
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.types.PublicTypeApproximator
|
||||
import org.jetbrains.kotlin.idea.frontend.api.tokens.ValidityToken
|
||||
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
|
||||
import org.jetbrains.kotlin.idea.frontend.api.withValidityAssertion
|
||||
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode
|
||||
import org.jetbrains.kotlin.name.SpecialNames
|
||||
import org.jetbrains.kotlin.types.model.SimpleTypeMarker
|
||||
import java.text.StringCharacterIterator
|
||||
|
||||
internal class KtFirPsiTypeProvider(
|
||||
override val analysisSession: KtFirAnalysisSession,
|
||||
@@ -24,3 +47,81 @@ internal class KtFirPsiTypeProvider(
|
||||
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
|
||||
do {
|
||||
val oldType = currentType
|
||||
currentType = currentType.fullyExpandedType(session)
|
||||
currentType = currentType.upperBoundIfFlexible()
|
||||
currentType = substitutor.substituteOrSelf(currentType)
|
||||
currentType = PublicTypeApproximator.approximateTypeToPublicDenotable(currentType, session) ?: currentType
|
||||
} while (oldType !== currentType)
|
||||
return currentType
|
||||
}
|
||||
|
||||
internal fun ConeKotlinType.asPsiType(
|
||||
session: FirSession,
|
||||
state: FirModuleResolveState,
|
||||
mode: TypeMappingMode,
|
||||
psiContext: PsiElement,
|
||||
): 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()
|
||||
|
||||
val signatureWriter = BothSignatureWriter(BothSignatureWriter.Mode.SKIP_CHECKS)
|
||||
|
||||
//TODO Check thread safety
|
||||
session.jvmTypeMapper.mapType(correctedType, mode, signatureWriter)
|
||||
|
||||
val canonicalSignature = signatureWriter.toString()
|
||||
|
||||
if (canonicalSignature.contains("L<error>")) return psiContext.nonExistentType()
|
||||
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 typeElement = ClsTypeElementImpl(psiContext, typeText, '\u0000')
|
||||
return typeElement.type
|
||||
}
|
||||
|
||||
private class AnonymousTypesSubstitutor(
|
||||
private val session: FirSession,
|
||||
private val state: FirModuleResolveState,
|
||||
) : AbstractConeSubstitutor(session.typeContext) {
|
||||
override fun substituteType(type: ConeKotlinType): ConeKotlinType? {
|
||||
if (type !is ConeClassLikeType) return null
|
||||
|
||||
val isAnonymous = type.classId.let { it?.shortClassName?.asString() == SpecialNames.ANONYMOUS_STRING }
|
||||
if (!isAnonymous) return null
|
||||
|
||||
fun ConeClassLikeType.isNotInterface(): Boolean {
|
||||
val firClassNode = lookupTag.toSymbol(session)?.fir as? FirClass ?: return false
|
||||
return firClassNode.withFirDeclaration(state) { firSuperClass ->
|
||||
firSuperClass.classKind != ClassKind.INTERFACE
|
||||
}
|
||||
}
|
||||
|
||||
val firClassNode = (type.lookupTag.toSymbol(session) as? FirClassSymbol)?.fir
|
||||
if (firClassNode != null) {
|
||||
val superTypesCones = firClassNode.withFirDeclaration(state, FirResolvePhase.SUPER_TYPES) {
|
||||
(it as? FirClass)?.superConeTypes
|
||||
}
|
||||
val superClass = superTypesCones?.firstOrNull { it.isNotInterface() }
|
||||
if (superClass != null) return superClass
|
||||
}
|
||||
|
||||
return if (type.nullability.isNullable) session.builtinTypes.nullableAnyType.type
|
||||
else session.builtinTypes.anyType.type
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user