FIR LC: do not use fir directly to create ASM types

This commit is contained in:
Ilya Kirillov
2021-08-17 15:52:05 +03:00
parent a1497b13c9
commit 6e2c9256cf
10 changed files with 103 additions and 55 deletions
@@ -35,6 +35,7 @@ public abstract class KtAnalysisSession(final override val token: ValidityToken)
KtSymbolDeclarationOverridesProviderMixIn,
KtExpressionTypeProviderMixIn,
KtPsiTypeProviderMixIn,
KtJvmTypeMapperMixIn,
KtTypeProviderMixIn,
KtTypeInfoProviderMixIn,
KtSymbolProviderMixIn,
@@ -92,6 +93,9 @@ public abstract class KtAnalysisSession(final override val token: ValidityToken)
internal val psiTypeProvider: KtPsiTypeProvider get() = psiTypeProviderImpl
protected abstract val psiTypeProviderImpl: KtPsiTypeProvider
internal val jvmTypeMapper: KtJvmTypeMapper get() = jvmTypeMapperImpl
protected abstract val jvmTypeMapperImpl: KtJvmTypeMapper
internal val typeProvider: KtTypeProvider get() = typeProviderImpl
protected abstract val typeProviderImpl: KtTypeProvider
@@ -9,12 +9,16 @@ import org.jetbrains.kotlin.idea.frontend.api.tokens.ValidityToken
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
import org.jetbrains.kotlin.types.Variance
public sealed class KtTypeArgument : ValidityTokenOwner
public sealed class KtTypeArgument : ValidityTokenOwner {
public abstract val type: KtType?
}
public class KtStarProjectionTypeArgument(override val token: ValidityToken) : KtTypeArgument()
public class KtStarProjectionTypeArgument(override val token: ValidityToken) : KtTypeArgument() {
override val type: KtType? get() = withValidityAssertion { null }
}
public class KtTypeArgumentWithVariance(
public val type: KtType,
override val type: KtType,
public val variance: Variance,
override val token: ValidityToken,
) : KtTypeArgument()
@@ -0,0 +1,24 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.frontend.api.components
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode
import org.jetbrains.org.objectweb.asm.Type
public abstract class KtJvmTypeMapper : KtAnalysisSessionComponent() {
public abstract fun mapTypeToJvmType(type: KtType, mode: TypeMappingMode): Type
}
public interface KtJvmTypeMapperMixIn : KtAnalysisSessionMixIn {
/**
* Create ASM JVM type by corresponding KtType
*
* @see TypeMappingMode
*/
public fun KtType.mapTypeToJvmType(mode: TypeMappingMode = TypeMappingMode.DEFAULT): Type =
analysisSession.jvmTypeMapper.mapTypeToJvmType(this, mode)
}
@@ -10,7 +10,6 @@ import org.jetbrains.kotlin.asJava.builder.LightMemberOrigin
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
@@ -82,9 +81,11 @@ internal class FirLightFieldForPropertySymbol(
modifiers.add(PsiModifier.VOLATILE)
}
val nullability = if (!(propertySymbol is KtKotlinPropertySymbol && propertySymbol.isLateInit))
propertySymbol.annotatedType.type.getTypeNullability(propertySymbol, FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE)
else NullabilityType.Unknown
val nullability = if (!(propertySymbol is KtKotlinPropertySymbol && propertySymbol.isLateInit)) {
analyzeWithSymbolAsContext(propertySymbol) {
getTypeNullability(propertySymbol.annotatedType.type)
}
} else NullabilityType.Unknown
val annotations = propertySymbol.computeAnnotations(
parent = this,
@@ -12,27 +12,17 @@ import org.jetbrains.kotlin.asJava.elements.KtLightMember
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.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.isPrimitiveType
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirModuleResolveState
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.symbols.KtFirSymbol
import org.jetbrains.kotlin.idea.frontend.api.fir.types.KtFirType
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
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolWithVisibility
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtTypeAndAnnotations
import org.jetbrains.kotlin.idea.frontend.api.types.KtNonErrorClassType
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
import org.jetbrains.kotlin.idea.frontend.api.types.KtTypeNullability
import org.jetbrains.kotlin.idea.frontend.api.types.*
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.SpecialNames
@@ -154,39 +144,31 @@ internal fun basicIsEquivalentTo(`this`: PsiElement?, that: PsiElement?): Boolea
return thisMemberOrigin.isEquivalentTo(thatMemberOrigin)
}
internal fun KtType.getTypeNullability(context: KtSymbol, phase: FirResolvePhase): NullabilityType {
internal fun KtAnalysisSession.getTypeNullability(ktType: KtType): NullabilityType {
if (ktType.nullabilityType != NullabilityType.NotNull) return ktType.nullabilityType
if (nullabilityType != NullabilityType.NotNull) return nullabilityType
if (ktType.isUnit) return NullabilityType.NotNull
if (isUnit) return NullabilityType.NotNull
require(this is KtFirType)
require(context is KtFirSymbol<*>)
if (coneType is ConeTypeParameterType) {
if (ktType is KtTypeParameterType) {
// TODO Make supertype checking
// val subtypeOfNullableSuperType = context.firRef.withFir(phase) {
// it.session.typeCheckerContext.nullableAnyType().isSupertypeOf(it.session.typeCheckerContext, coneType)
// }
// if (!subtypeOfNullableSuperType) return NullabilityType.NotNull
if (!coneType.isMarkedNullable) return NullabilityType.Unknown
return NullabilityType.NotNull
return if (!ktType.isMarkedNullable) NullabilityType.Unknown else NullabilityType.NotNull
}
if (ktType !is KtClassType) return NullabilityType.NotNull
if (!ktType.isPrimitive) {
return ktType.nullabilityType
}
val coneType = coneType as? ConeClassLikeType ?: return NullabilityType.NotNull
if (ktType !is KtNonErrorClassType) return NullabilityType.NotNull
if (ktType.typeArguments.any { it.type is KtClassErrorType }) return NullabilityType.NotNull
if (ktType.classId.shortClassName.asString() == SpecialNames.ANONYMOUS_STRING) return NullabilityType.NotNull
if (!coneType.isPrimitiveType()) {
return nullabilityType
}
if (coneType is ConeClassErrorType) return NullabilityType.NotNull
if (coneType.typeArguments.any { it is ConeClassErrorType }) return NullabilityType.NotNull
if (coneType.classId?.shortClassName?.asString() == SpecialNames.ANONYMOUS_STRING) return NullabilityType.NotNull
val canonicalSignature = context.firRef.withFir(phase) {
it.moduleData.session.jvmTypeMapper.mapType(coneType, TypeMappingMode.DEFAULT).descriptor
}
val canonicalSignature = ktType.mapTypeToJvmType().descriptor
if (canonicalSignature == "[L<error>;") return NullabilityType.NotNull
@@ -13,7 +13,6 @@ import org.jetbrains.kotlin.asJava.classes.METHOD_INDEX_FOR_SETTER
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.asJava.parameters.FirLightSetterParameterForSymbol
import org.jetbrains.kotlin.idea.frontend.api.fir.analyzeWithSymbolAsContext
import org.jetbrains.kotlin.idea.frontend.api.isValid
@@ -72,9 +71,13 @@ internal class FirLightAccessorMethodForSymbol(
!isPrivate &&
!(isParameter && (containingClass.isAnnotationType || containingClass.isEnum))
val nullabilityType = if (nullabilityApplicable) containingPropertySymbol.annotatedType.type
.getTypeNullability(containingPropertySymbol, FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE)
else NullabilityType.Unknown
val nullabilityType = if (nullabilityApplicable) {
analyzeWithSymbolAsContext(containingPropertySymbol) {
getTypeNullability(
containingPropertySymbol.annotatedType.type
)
}
} else NullabilityType.Unknown
val annotationsFromProperty = containingPropertySymbol.computeAnnotations(
parent = this,
@@ -8,7 +8,6 @@ package org.jetbrains.kotlin.idea.asJava
import com.intellij.psi.*
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
@@ -56,12 +55,15 @@ internal class FirLightSimpleMethodForSymbol(
_typeParameterList?.typeParameters ?: PsiTypeParameter.EMPTY_ARRAY
private fun computeAnnotations(isPrivate: Boolean): List<PsiAnnotation> {
val nullability = if (isVoidReturnType || isPrivate)
val nullability = if (isVoidReturnType || isPrivate) {
NullabilityType.Unknown
else functionSymbol.annotatedType.type.getTypeNullability(
context = functionSymbol,
phase = FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE
)
} else {
analyzeWithSymbolAsContext(functionSymbol) {
getTypeNullability(
functionSymbol.annotatedType.type
)
}
}
return functionSymbol.computeAnnotations(
parent = this,
@@ -8,7 +8,6 @@ package org.jetbrains.kotlin.idea.asJava
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
@@ -36,10 +35,13 @@ internal abstract class FirLightParameterBaseForSymbol(
val nullabilityApplicable = !containingMethod.containingClass.let { it.isAnnotationType || it.isEnum } &&
!containingMethod.hasModifierProperty(PsiModifier.PRIVATE)
return if (nullabilityApplicable) parameterSymbol.annotatedType.type.getTypeNullability(
parameterSymbol,
FirResolvePhase.TYPES
)
return if (nullabilityApplicable) {
analyzeWithSymbolAsContext(parameterSymbol) {
getTypeNullability(
parameterSymbol.annotatedType.type
)
}
}
else NullabilityType.Unknown
}
@@ -75,6 +75,8 @@ private constructor(
override val psiTypeProviderImpl = KtFirPsiTypeProvider(this, token)
override val jvmTypeMapperImpl = KtFirJvmTypeMapper(this, token)
override val typeProviderImpl = KtFirTypeProvider(this, token)
override val typeInfoProviderImpl = KtFirTypeInfoProvider(this, token)
@@ -0,0 +1,24 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.frontend.api.fir.components
import org.jetbrains.kotlin.fir.backend.jvm.jvmTypeMapper
import org.jetbrains.kotlin.idea.frontend.api.components.KtJvmTypeMapper
import org.jetbrains.kotlin.idea.frontend.api.fir.KtFirAnalysisSession
import org.jetbrains.kotlin.idea.frontend.api.tokens.ValidityToken
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode
import org.jetbrains.org.objectweb.asm.Type
internal class KtFirJvmTypeMapper(
override val analysisSession: KtFirAnalysisSession,
override val token: ValidityToken,
) : KtJvmTypeMapper(), KtFirAnalysisSessionComponent {
override fun mapTypeToJvmType(type: KtType, mode: TypeMappingMode): Type {
return analysisSession.rootModuleSession.jvmTypeMapper.mapType(type.coneType, mode)
}
}