From 9c16c525645d86d0d0beda939785a8c866facd41 Mon Sep 17 00:00:00 2001 From: Jinseong Jeon Date: Thu, 22 Feb 2024 21:48:47 -0800 Subject: [PATCH] AA: pass wildcard suppression hints on declarations ^KT-61734 --- .../components/KtFe10PsiTypeProvider.kt | 21 +++++++++--- .../fir/components/KtFirPsiTypeProvider.kt | 22 ++++++++++--- .../api/components/KtPsiTypeProvider.kt | 32 ++++++++++++++++--- .../jetbrains/kotlin/types/typeMappingUtil.kt | 18 ++++++++++- 4 files changed, 79 insertions(+), 14 deletions(-) diff --git a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/components/KtFe10PsiTypeProvider.kt b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/components/KtFe10PsiTypeProvider.kt index 13a7d1abcfb..d6a836571a5 100644 --- a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/components/KtFe10PsiTypeProvider.kt +++ b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/components/KtFe10PsiTypeProvider.kt @@ -45,7 +45,8 @@ internal class KtFe10PsiTypeProvider( useSitePosition: PsiElement, mode: KtTypeMappingMode, isAnnotationMethod: Boolean, - allowErrorTypes: Boolean + suppressWildcards: Boolean?, + allowErrorTypes: Boolean, ): PsiTypeElement? { val kotlinType = (type as KtFe10Type).fe10Type @@ -57,10 +58,18 @@ internal class KtFe10PsiTypeProvider( if (!analysisSession.useSiteModule.platform.has()) return null - return asPsiTypeElement(simplifyType(kotlinType), useSitePosition, mode.toTypeMappingMode(type, isAnnotationMethod)) + return asPsiTypeElement( + simplifyType(kotlinType), + useSitePosition, + mode.toTypeMappingMode(type, isAnnotationMethod, suppressWildcards), + ) } - private fun KtTypeMappingMode.toTypeMappingMode(type: KtType, isAnnotationMethod: Boolean): TypeMappingMode { + private fun KtTypeMappingMode.toTypeMappingMode( + type: KtType, + isAnnotationMethod: Boolean, + suppressWildcards: Boolean?, + ): TypeMappingMode { require(type is KtFe10Type) return when (this) { KtTypeMappingMode.DEFAULT -> TypeMappingMode.DEFAULT @@ -79,7 +88,11 @@ internal class KtFe10PsiTypeProvider( if (type.fe10Type.arguments.isEmpty()) typeMappingMode else - typeMappingMode.updateArgumentModeFromAnnotations(type.fe10Type, typeMapper.typeContext) + typeMappingMode.updateArgumentModeFromAnnotations( + type.fe10Type, + typeMapper.typeContext, + suppressWildcards, + ) } } diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirPsiTypeProvider.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirPsiTypeProvider.kt index 9ed6e5f74d4..8827baa12f3 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirPsiTypeProvider.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirPsiTypeProvider.kt @@ -72,7 +72,8 @@ internal class KtFirPsiTypeProvider( useSitePosition: PsiElement, mode: KtTypeMappingMode, isAnnotationMethod: Boolean, - allowErrorTypes: Boolean + suppressWildcards: Boolean?, + allowErrorTypes: Boolean, ): PsiTypeElement? { val coneType = type.coneType @@ -85,10 +86,19 @@ internal class KtFirPsiTypeProvider( if (!rootModuleSession.moduleData.platform.has()) return null return coneType.simplifyType(rootModuleSession, useSitePosition) - .asPsiTypeElement(rootModuleSession, mode.toTypeMappingMode(type, isAnnotationMethod), useSitePosition, allowErrorTypes) + .asPsiTypeElement( + rootModuleSession, + mode.toTypeMappingMode(type, isAnnotationMethod, suppressWildcards), + useSitePosition, + allowErrorTypes, + ) } - private fun KtTypeMappingMode.toTypeMappingMode(type: KtType, isAnnotationMethod: Boolean): TypeMappingMode { + private fun KtTypeMappingMode.toTypeMappingMode( + type: KtType, + isAnnotationMethod: Boolean, + suppressWildcards: Boolean?, + ): TypeMappingMode { require(type is KtFirType) val expandedType = type.coneType.fullyExpandedType(rootModuleSession) return when (this) { @@ -110,7 +120,11 @@ internal class KtFirPsiTypeProvider( if (expandedType.typeArguments.isEmpty()) typeMappingMode else - typeMappingMode.updateArgumentModeFromAnnotations(expandedType, rootModuleSession.jvmTypeMapper.typeContext) + typeMappingMode.updateArgumentModeFromAnnotations( + expandedType, + rootModuleSession.jvmTypeMapper.typeContext, + suppressWildcards, + ) } } diff --git a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/components/KtPsiTypeProvider.kt b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/components/KtPsiTypeProvider.kt index a026c4162ef..787befe14ea 100644 --- a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/components/KtPsiTypeProvider.kt +++ b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/components/KtPsiTypeProvider.kt @@ -18,7 +18,8 @@ public abstract class KtPsiTypeProvider : KtAnalysisSessionComponent() { useSitePosition: PsiElement, mode: KtTypeMappingMode, isAnnotationMethod: Boolean, - allowErrorTypes: Boolean + suppressWildcards: Boolean?, + allowErrorTypes: Boolean, ): PsiTypeElement? public abstract fun asKtType( @@ -46,15 +47,29 @@ public interface KtPsiTypeProviderMixIn : KtAnalysisSessionMixIn { * * If [allowErrorTypes] set to true then erroneous types will be replaced with `error.NonExistentClass` type. * + * [suppressWildcards] indicates whether wild cards in type arguments need to be suppressed or not, + * e.g., according to the annotation on the containing declarations. + * `true` means they should be suppressed; + * `false` means they should appear; + * `null` is no-op by default, i.e., their suppression/appearance is determined by type annotations. + * * Note: [PsiTypeElement] is JVM conception, so this method will return `null` for non-JVM platforms. */ public fun KtType.asPsiTypeElement( useSitePosition: PsiElement, allowErrorTypes: Boolean, mode: KtTypeMappingMode = KtTypeMappingMode.DEFAULT, - isAnnotationMethod: Boolean = false + isAnnotationMethod: Boolean = false, + suppressWildcards: Boolean? = null, ): PsiTypeElement? = withValidityAssertion { - analysisSession.psiTypeProvider.asPsiTypeElement(this, useSitePosition, mode, isAnnotationMethod, allowErrorTypes) + analysisSession.psiTypeProvider.asPsiTypeElement( + this, + useSitePosition, + mode, + isAnnotationMethod, + suppressWildcards, + allowErrorTypes, + ) } /** @@ -70,9 +85,16 @@ public interface KtPsiTypeProviderMixIn : KtAnalysisSessionMixIn { useSitePosition: PsiElement, allowErrorTypes: Boolean, mode: KtTypeMappingMode = KtTypeMappingMode.DEFAULT, - isAnnotationMethod: Boolean = false + isAnnotationMethod: Boolean = false, + suppressWildcards: Boolean? = null, ): PsiType? = - asPsiTypeElement(useSitePosition, allowErrorTypes, mode, isAnnotationMethod)?.type + asPsiTypeElement( + useSitePosition, + allowErrorTypes, + mode, + isAnnotationMethod, + suppressWildcards, + )?.type /** * Converts given [PsiType] to [KtType]. diff --git a/core/compiler.common.jvm/src/org/jetbrains/kotlin/types/typeMappingUtil.kt b/core/compiler.common.jvm/src/org/jetbrains/kotlin/types/typeMappingUtil.kt index 202a6034a2f..24d21290b2b 100644 --- a/core/compiler.common.jvm/src/org/jetbrains/kotlin/types/typeMappingUtil.kt +++ b/core/compiler.common.jvm/src/org/jetbrains/kotlin/types/typeMappingUtil.kt @@ -13,7 +13,9 @@ import org.jetbrains.kotlin.name.JvmStandardClassIds.JVM_SUPPRESS_WILDCARDS_ANNO import org.jetbrains.kotlin.types.model.KotlinTypeMarker fun TypeMappingMode.updateArgumentModeFromAnnotations( - type: KotlinTypeMarker, typeSystem: TypeSystemCommonBackendContext + type: KotlinTypeMarker, + typeSystem: TypeSystemCommonBackendContext, + suppressWildcardsByContainingDeclaration: Boolean? = null, ): TypeMappingMode { type.suppressWildcardsMode(typeSystem)?.let { return TypeMappingMode.createWithConstantDeclarationSiteWildcardsMode( @@ -34,6 +36,20 @@ fun TypeMappingMode.updateArgumentModeFromAnnotations( ) } + // For example, + // @JvmSuppressWildcards(true) + // fun deepOpen(x: Out>>) {} + // Instead of the return type, the annotation associated with the declaration indicates that its type signature, + // including return type and parameter types, need to suppress wildcards. + suppressWildcardsByContainingDeclaration?.let { + return TypeMappingMode.createWithConstantDeclarationSiteWildcardsMode( + skipDeclarationSiteWildcards = it, + isForAnnotationParameter = isForAnnotationParameter, + needInlineClassWrapping = needInlineClassWrapping, + mapTypeAliases = mapTypeAliases + ) + } + return this }