diff --git a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/KtAnalysisSession.kt b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/KtAnalysisSession.kt index 8254cda4b12..739031537e2 100644 --- a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/KtAnalysisSession.kt +++ b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/KtAnalysisSession.kt @@ -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 diff --git a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/KtTypeArgument.kt b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/KtTypeArgument.kt index 79022ff8e2f..a594c3b6b59 100644 --- a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/KtTypeArgument.kt +++ b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/KtTypeArgument.kt @@ -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() diff --git a/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/components/KtJvmTypeMapper.kt b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/components/KtJvmTypeMapper.kt new file mode 100644 index 00000000000..d821c6f16f8 --- /dev/null +++ b/idea/idea-frontend-api/src/org/jetbrains/kotlin/idea/frontend/api/components/KtJvmTypeMapper.kt @@ -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) +} diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/fields/FirLightFieldForPropertySymbol.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/fields/FirLightFieldForPropertySymbol.kt index 08c0d6dd3d4..d54f1b6e24a 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/fields/FirLightFieldForPropertySymbol.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/fields/FirLightFieldForPropertySymbol.kt @@ -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, diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/firLightUtils.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/firLightUtils.kt index a0c5dbeb040..d7c6199045a 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/firLightUtils.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/firLightUtils.kt @@ -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;") return NullabilityType.NotNull diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/methods/FirLightAccessorMethodForSymbol.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/methods/FirLightAccessorMethodForSymbol.kt index 3136eb37aea..c6c3c3b8731 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/methods/FirLightAccessorMethodForSymbol.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/methods/FirLightAccessorMethodForSymbol.kt @@ -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, diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/methods/FirLightSimpleMethodForSymbol.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/methods/FirLightSimpleMethodForSymbol.kt index bd6dec1d7fc..fd93aba7342 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/methods/FirLightSimpleMethodForSymbol.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/methods/FirLightSimpleMethodForSymbol.kt @@ -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 { - 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, diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/parameters/FirLightParameterBaseForSymbol.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/parameters/FirLightParameterBaseForSymbol.kt index c9cfa8d81dd..7b78205ffdf 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/parameters/FirLightParameterBaseForSymbol.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/asJava/parameters/FirLightParameterBaseForSymbol.kt @@ -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 } diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/KtFirAnalysisSession.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/KtFirAnalysisSession.kt index 8bf648dba18..0fd6ac4bd14 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/KtFirAnalysisSession.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/KtFirAnalysisSession.kt @@ -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) diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/components/KtFirJvmTypeMapper.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/components/KtFirJvmTypeMapper.kt new file mode 100644 index 00000000000..c9b120e33a2 --- /dev/null +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/components/KtFirJvmTypeMapper.kt @@ -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) + } +} \ No newline at end of file