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 fb0aa5da31e..0e5cefd6e14 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 @@ -6,7 +6,7 @@ package org.jetbrains.kotlin.analysis.api.descriptors.components import com.intellij.psi.PsiElement -import com.intellij.psi.PsiType +import com.intellij.psi.PsiTypeElement import com.intellij.psi.impl.cache.TypeInfo import com.intellij.psi.impl.compiled.ClsTypeElementImpl import com.intellij.psi.impl.compiled.SignatureParsing @@ -36,13 +36,13 @@ internal class KtFe10PsiTypeProvider( private val typeMapper by lazy { KtFe10JvmTypeMapperContext(analysisContext.resolveSession) } - override fun asPsiType( + override fun asPsiTypeElement( type: KtType, useSitePosition: PsiElement, mode: KtTypeMappingMode, isAnnotationMethod: Boolean, allowErrorTypes: Boolean - ): PsiType? { + ): PsiTypeElement? { val kotlinType = (type as KtFe10Type).fe10Type with(typeMapper.typeContext) { @@ -51,7 +51,7 @@ internal class KtFe10PsiTypeProvider( } } - return asPsiType(simplifyType(kotlinType), useSitePosition, mode.toTypeMappingMode(type, isAnnotationMethod)) + return asPsiTypeElement(simplifyType(kotlinType), useSitePosition, mode.toTypeMappingMode(type, isAnnotationMethod)) } private fun KtTypeMappingMode.toTypeMappingMode(type: KtType, isAnnotationMethod: Boolean): TypeMappingMode { @@ -82,7 +82,7 @@ internal class KtFe10PsiTypeProvider( return result } - private fun asPsiType(type: KotlinType, useSitePosition: PsiElement, mode: TypeMappingMode): PsiType? { + private fun asPsiTypeElement(type: KotlinType, useSitePosition: PsiElement, mode: TypeMappingMode): PsiTypeElement? { if (type !is SimpleTypeMarker) return null val signatureWriter = BothSignatureWriter(BothSignatureWriter.Mode.SKIP_CHECKS) @@ -99,7 +99,6 @@ internal class KtFe10PsiTypeProvider( val typeInfo = TypeInfo.fromString(javaType, false) val typeText = TypeInfo.createTypeText(typeInfo) ?: return null - val typeElement = ClsTypeElementImpl(useSitePosition, typeText, '\u0000') - return typeElement.type + return ClsTypeElementImpl(useSitePosition, typeText, '\u0000') } } 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 a29d4bb7d8c..f917f66115e 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 @@ -49,13 +49,13 @@ internal class KtFirPsiTypeProvider( override val token: KtLifetimeToken, ) : KtPsiTypeProvider(), KtFirAnalysisSessionComponent { - override fun asPsiType( + override fun asPsiTypeElement( type: KtType, useSitePosition: PsiElement, mode: KtTypeMappingMode, isAnnotationMethod: Boolean, allowErrorTypes: Boolean - ): PsiType? { + ): PsiTypeElement? { val coneType = type.coneType with(rootModuleSession.typeContext) { @@ -65,7 +65,7 @@ internal class KtFirPsiTypeProvider( } return coneType.simplifyType(rootModuleSession, useSitePosition) - .asPsiType(rootModuleSession, mode.toTypeMappingMode(type, isAnnotationMethod), useSitePosition, allowErrorTypes) + .asPsiTypeElement(rootModuleSession, mode.toTypeMappingMode(type, isAnnotationMethod), useSitePosition, allowErrorTypes) } private fun KtTypeMappingMode.toTypeMappingMode(type: KtType, isAnnotationMethod: Boolean): TypeMappingMode { @@ -189,12 +189,12 @@ private fun ConeKotlinType.isLocalButAvailableAtPosition( context.parents.any { it == localPsi } } -private fun ConeKotlinType.asPsiType( +private fun ConeKotlinType.asPsiTypeElement( session: FirSession, mode: TypeMappingMode, useSitePosition: PsiElement, allowErrorTypes: Boolean -): PsiType? { +): PsiTypeElement? { if (this !is SimpleTypeMarker) return null if (!allowErrorTypes && (this is ConeErrorType)) return null @@ -224,8 +224,7 @@ private fun ConeKotlinType.asPsiType( val typeInfo = TypeInfo.fromString(javaType, false) val typeText = TypeInfo.createTypeText(typeInfo) ?: return null - val typeElement = ClsTypeElementImpl(useSitePosition, typeText, '\u0000') - return typeElement.type + return ClsTypeElementImpl(useSitePosition, typeText, '\u0000') } private val PsiElement.containingKtFile: KtFile? 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 03a0bae9610..8bd3626b05c 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 @@ -7,26 +7,27 @@ package org.jetbrains.kotlin.analysis.api.components import com.intellij.psi.PsiElement import com.intellij.psi.PsiType +import com.intellij.psi.PsiTypeElement import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion import org.jetbrains.kotlin.analysis.api.types.KtType import org.jetbrains.kotlin.analysis.api.types.KtTypeMappingMode public abstract class KtPsiTypeProvider : KtAnalysisSessionComponent() { - public abstract fun asPsiType( + public abstract fun asPsiTypeElement( type: KtType, useSitePosition: PsiElement, mode: KtTypeMappingMode, isAnnotationMethod: Boolean, allowErrorTypes: Boolean - ): PsiType? + ): PsiTypeElement? } public interface KtPsiTypeProviderMixIn : KtAnalysisSessionMixIn { /** - * Converts the given [KtType] to [PsiType] under [useSitePosition] context. + * Converts the given [KtType] to [PsiTypeElement] under [useSitePosition] context. * - * [useSitePosition] is used as the parent of the resulting [PsiType], - * which is in turn used to resolve [PsiType]. + * [useSitePosition] is used as the parent of the resulting [PsiTypeElement], + * which is in turn used to resolve [PsiTypeElement]. * * [useSitePosition] is also used to determine if the given [KtType] needs to be approximated. * For example, if the given type is local yet available in the same scope of use site, we can @@ -40,12 +41,27 @@ public interface KtPsiTypeProviderMixIn : KtAnalysisSessionMixIn { * * If [allowErrorTypes] set to true then erroneous types will be replaced with `error.NonExistentClass` type */ + public fun KtType.asPsiTypeElement( + useSitePosition: PsiElement, + allowErrorTypes: Boolean, + mode: KtTypeMappingMode = KtTypeMappingMode.DEFAULT, + isAnnotationMethod: Boolean = false + ): PsiTypeElement? = withValidityAssertion { + analysisSession.psiTypeProvider.asPsiTypeElement(this, useSitePosition, mode, isAnnotationMethod, allowErrorTypes) + } + + /** + * Converts the given [KtType] to [PsiType] under [useSitePosition] context. + * + * This simply unwraps [PsiTypeElement] returned from [asPsiTypeElement]. + * Use this version if type annotation is not required. Otherwise, use [asPsiTypeElement] to get [PsiTypeElement] as an owner of + * annotations on [PsiType] and annotate the resulting [PsiType] with proper [PsiAnnotation]. + */ public fun KtType.asPsiType( useSitePosition: PsiElement, allowErrorTypes: Boolean, mode: KtTypeMappingMode = KtTypeMappingMode.DEFAULT, isAnnotationMethod: Boolean = false - ): PsiType? = withValidityAssertion { - analysisSession.psiTypeProvider.asPsiType(this, useSitePosition, mode, isAnnotationMethod, allowErrorTypes) - } + ): PsiType? = + asPsiTypeElement(useSitePosition, allowErrorTypes, mode, isAnnotationMethod)?.type } diff --git a/analysis/light-classes-base/src/org/jetbrains/kotlin/asJava/classes/implUtils.kt b/analysis/light-classes-base/src/org/jetbrains/kotlin/asJava/classes/implUtils.kt index 988ac391318..8e3f13ccc5e 100644 --- a/analysis/light-classes-base/src/org/jetbrains/kotlin/asJava/classes/implUtils.kt +++ b/analysis/light-classes-base/src/org/jetbrains/kotlin/asJava/classes/implUtils.kt @@ -5,9 +5,9 @@ package org.jetbrains.kotlin.asJava.classes +import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.util.ModificationTracker -import com.intellij.psi.PsiJavaCodeReferenceElement -import com.intellij.psi.PsiReferenceList +import com.intellij.psi.* import com.intellij.psi.impl.light.LightElement import com.intellij.util.IncorrectOperationException import org.jetbrains.kotlin.analyzer.KotlinModificationTrackerService @@ -68,3 +68,67 @@ fun KtClassOrObject.getExternalDependencies(): List { } } } + +// There is no other known way found to make PSI types annotated for now (without creating a new instance). +// It seems we need for platform changes to do it more convenient way (KTIJ-141). +private val setPsiTypeAnnotationProvider: (PsiType, TypeAnnotationProvider) -> Unit by lazyPub { + val klass = PsiType::class.java + val providerField = try { + klass.getDeclaredField("myAnnotationProvider") + .also { it.isAccessible = true } + } catch (e: NoSuchFieldException) { + if (ApplicationManager.getApplication().isInternal) throw e + null + } catch (e: SecurityException) { + if (ApplicationManager.getApplication().isInternal) throw e + null + } + + { psiType, provider -> + providerField?.set(psiType, provider) + } +} + +fun PsiType.annotateByTypeAnnotationProvider( + annotations: Sequence>, +): PsiType { + val annotationsIterator = annotations.iterator() + if (!annotationsIterator.hasNext()) return this + + if (this is PsiPrimitiveType) { + val typeAnnotation = annotationsIterator.next() + return if (typeAnnotation.isEmpty()) { + this + } else { + val provider = TypeAnnotationProvider.Static.create(typeAnnotation.toTypedArray()) + // NB: [PsiType#annotate] makes a clone of the given [PsiType] while manipulating the type annotation provider. + // For simple primitive type, it will be okay and intuitive (than reflection hack). + annotate(provider) + } + } + + fun recursiveAnnotator(psiType: PsiType) { + if (!annotationsIterator.hasNext()) return + val typeAnnotations = annotationsIterator.next() + + when (psiType) { + is PsiPrimitiveType -> return // Primitive type cannot be type parameter so we skip it + is PsiClassType -> { + for (parameterType in psiType.parameters) { + recursiveAnnotator(parameterType) + } + } + is PsiArrayType -> + recursiveAnnotator(psiType.componentType) + else -> {} + } + + if (typeAnnotations.isEmpty()) return + + val provider = TypeAnnotationProvider.Static.create(typeAnnotations.toTypedArray()) + setPsiTypeAnnotationProvider(psiType, provider) + } + + recursiveAnnotator(this) + return this +} diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/annotations/symbolAnnotationsUtils.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/annotations/symbolAnnotationsUtils.kt index b84224c4f7c..a818722e0d3 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/annotations/symbolAnnotationsUtils.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/annotations/symbolAnnotationsUtils.kt @@ -5,8 +5,7 @@ package org.jetbrains.kotlin.light.classes.symbol.annotations -import com.intellij.psi.PsiClassType -import com.intellij.psi.PsiElement +import com.intellij.psi.* import com.intellij.psi.impl.light.LightReferenceListBuilder import org.jetbrains.kotlin.analysis.api.KtAnalysisSession import org.jetbrains.kotlin.analysis.api.annotations.* @@ -14,7 +13,10 @@ import org.jetbrains.kotlin.analysis.api.annotations.KtKClassAnnotationValue.KtN import org.jetbrains.kotlin.analysis.api.components.buildClassType import org.jetbrains.kotlin.analysis.api.symbols.KtFunctionSymbol import org.jetbrains.kotlin.analysis.api.symbols.markers.KtAnnotatedSymbol +import org.jetbrains.kotlin.analysis.api.types.KtNonErrorClassType +import org.jetbrains.kotlin.analysis.api.types.KtType import org.jetbrains.kotlin.analysis.api.types.KtTypeMappingMode +import org.jetbrains.kotlin.asJava.classes.annotateByTypeAnnotationProvider import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget import org.jetbrains.kotlin.light.classes.symbol.classes.SymbolLightClassBase @@ -126,3 +128,30 @@ internal fun KtAnnotatedSymbol.computeThrowsList( annoApp.arguments.forEach { handleAnnotationValue(it.expression) } } + +context(KtAnalysisSession) +internal fun annotateByKtType( + psiType: PsiType, + ktType: KtType, + psiContext: PsiTypeElement, +): PsiType { + + fun KtType.getAnnotationsSequence(): Sequence> = + sequence { + yield(annotations.map { annoApp -> + SymbolLightSimpleAnnotation( + annoApp.classId?.asFqNameString(), + psiContext, + annoApp.arguments, + annoApp.psi + ) + }) + (this@getAnnotationsSequence as? KtNonErrorClassType)?.ownTypeArguments?.forEach { typeProjection -> + typeProjection.type?.let { + yieldAll(it.getAnnotationsSequence()) + } + } + } + + return psiType.annotateByTypeAnnotationProvider(ktType.getAnnotationsSequence()) +} diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/fields/SymbolLightFieldForEnumEntry.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/fields/SymbolLightFieldForEnumEntry.kt index ced75e26324..e8d9c125952 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/fields/SymbolLightFieldForEnumEntry.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/fields/SymbolLightFieldForEnumEntry.kt @@ -93,7 +93,9 @@ internal class SymbolLightFieldForEnumEntry( private val _type: PsiType by lazyPub { withEnumEntrySymbol { enumEntrySymbol -> - enumEntrySymbol.returnType.asPsiType(this@SymbolLightFieldForEnumEntry, allowErrorTypes = true) ?: nonExistentType() + enumEntrySymbol.returnType + .asPsiType(this@SymbolLightFieldForEnumEntry, allowErrorTypes = true) + ?: nonExistentType() } } diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/fields/SymbolLightFieldForProperty.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/fields/SymbolLightFieldForProperty.kt index 31b85e447da..3f44f0919d9 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/fields/SymbolLightFieldForProperty.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/fields/SymbolLightFieldForProperty.kt @@ -66,23 +66,16 @@ internal class SymbolLightFieldForProperty private constructor( private val _returnedType: PsiType by lazyPub { withPropertySymbol { propertySymbol -> val isDelegated = (propertySymbol as? KtKotlinPropertySymbol)?.isDelegatedProperty == true - when { - isDelegated -> - (kotlinOrigin as? KtProperty)?.delegateExpression?.let { - it.getKtType()?.asPsiType( - this@SymbolLightFieldForProperty, - allowErrorTypes = true, - KtTypeMappingMode.RETURN_TYPE - ) - } - - else -> propertySymbol.returnType.asPsiType( - this@SymbolLightFieldForProperty, - allowErrorTypes = true, - KtTypeMappingMode.RETURN_TYPE - ) - } ?: nonExistentType() - } + val ktType = if (isDelegated) + (kotlinOrigin as? KtProperty)?.delegateExpression?.getKtType() + else + propertySymbol.returnType + ktType?.asPsiType( + this@SymbolLightFieldForProperty, + allowErrorTypes = true, + KtTypeMappingMode.RETURN_TYPE + ) + } ?: nonExistentType() } private val _isDeprecated: Boolean by lazyPub { diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/methods/SymbolLightSimpleMethod.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/methods/SymbolLightSimpleMethod.kt index cca275f1d64..9db5703d866 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/methods/SymbolLightSimpleMethod.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/methods/SymbolLightSimpleMethod.kt @@ -187,12 +187,14 @@ internal class SymbolLightSimpleMethod( functionSymbol.returnType.takeUnless { it.isVoidType } ?: return@withFunctionSymbol PsiType.VOID } - ktType.asPsiType( + ktType.asPsiTypeElement( this@SymbolLightSimpleMethod, allowErrorTypes = true, KtTypeMappingMode.RETURN_TYPE, this@SymbolLightSimpleMethod.containingClass.isAnnotationType, - ) + )?.let { + annotateByKtType(it.type, ktType, it) + } } ?: nonExistentType() } diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/parameters/SymbolLightParameterCommon.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/parameters/SymbolLightParameterCommon.kt index 9aab747b3e5..f1b235d0a96 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/parameters/SymbolLightParameterCommon.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/parameters/SymbolLightParameterCommon.kt @@ -15,6 +15,7 @@ import org.jetbrains.kotlin.analysis.api.types.KtTypeMappingMode import org.jetbrains.kotlin.asJava.classes.lazyPub import org.jetbrains.kotlin.asJava.elements.KtLightIdentifier import org.jetbrains.kotlin.light.classes.symbol.* +import org.jetbrains.kotlin.light.classes.symbol.annotations.annotateByKtType import org.jetbrains.kotlin.light.classes.symbol.methods.SymbolLightMethodBase import org.jetbrains.kotlin.psi.KtParameter @@ -77,7 +78,13 @@ internal abstract class SymbolLightParameterCommon( else -> KtTypeMappingMode.VALUE_PARAMETER } - ktType.asPsiType(this@SymbolLightParameterCommon, allowErrorTypes = true, typeMappingMode) + ktType.asPsiTypeElement( + this@SymbolLightParameterCommon, + allowErrorTypes = true, + typeMappingMode + )?.let { + annotateByKtType(it.type, ktType, it) + } } ?: nonExistentType() if (parameterSymbol.isVararg) { diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/parameters/SymbolLightParameterForReceiver.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/parameters/SymbolLightParameterForReceiver.kt index 360f6d37df1..b45a12b89a7 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/parameters/SymbolLightParameterForReceiver.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/parameters/SymbolLightParameterForReceiver.kt @@ -17,10 +17,7 @@ import org.jetbrains.kotlin.asJava.classes.lazyPub import org.jetbrains.kotlin.codegen.AsmUtil import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget import org.jetbrains.kotlin.light.classes.symbol.* -import org.jetbrains.kotlin.light.classes.symbol.annotations.GranularAnnotationsBox -import org.jetbrains.kotlin.light.classes.symbol.annotations.NullabilityAnnotationsProvider -import org.jetbrains.kotlin.light.classes.symbol.annotations.SymbolAnnotationsProvider -import org.jetbrains.kotlin.light.classes.symbol.annotations.toOptionalFilter +import org.jetbrains.kotlin.light.classes.symbol.annotations.* import org.jetbrains.kotlin.light.classes.symbol.methods.SymbolLightMethodBase import org.jetbrains.kotlin.light.classes.symbol.modifierLists.SymbolLightClassModifierList import org.jetbrains.kotlin.psi.KtParameter @@ -85,7 +82,10 @@ internal class SymbolLightParameterForReceiver private constructor( private val _type: PsiType by lazyPub { withReceiverSymbol { receiver -> - receiver.type.asPsiType(this, allowErrorTypes = true) + val ktType = receiver.type + ktType.asPsiTypeElement(this, allowErrorTypes = true)?.let { + annotateByKtType(it.type, ktType, it) + } } ?: nonExistentType() } diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/symbolLightUtils.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/symbolLightUtils.kt index 99a82b5aff0..9d2e198949c 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/symbolLightUtils.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/symbolLightUtils.kt @@ -41,12 +41,14 @@ internal fun KtAnalysisSession.mapType( psiContext: PsiElement, mode: KtTypeMappingMode ): PsiClassType? { - val psiType = type.asPsiType( + val psiTypeElement = type.asPsiTypeElement( psiContext, allowErrorTypes = true, mode, ) - return psiType as? PsiClassType + return (psiTypeElement?.type as? PsiClassType)?.let { + annotateByKtType(it, type, psiTypeElement) as? PsiClassType + } } diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightUtils.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightUtils.kt index 91687694715..f733a4f3d3b 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightUtils.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightUtils.kt @@ -165,30 +165,10 @@ internal fun KotlinType.asPsiType( typeMapper.mapType(this, signatureWriter, mode) } -// There is no other known way found to make PSI types annotated for now. -// It seems we need for platform changes to do it more convenient way (KTIJ-141). -private val setPsiTypeAnnotationProvider: (PsiType, TypeAnnotationProvider) -> Unit by lazyPub { - val klass = PsiType::class.java - val providerField = try { - klass.getDeclaredField("myAnnotationProvider") - .also { it.isAccessible = true } - } catch (e: NoSuchFieldException) { - if (ApplicationManager.getApplication().isInternal) throw e - null - } catch (e: SecurityException) { - if (ApplicationManager.getApplication().isInternal) throw e - null - } - - { psiType, provider -> - providerField?.set(psiType, provider) - } -} - private fun annotateByKotlinType( psiType: PsiType, kotlinType: KotlinType, - psiContext: PsiElement, + psiContext: PsiTypeElement, ): PsiType { fun KotlinType.getAnnotationsSequence(): Sequence> = @@ -199,37 +179,7 @@ private fun annotateByKotlinType( } } - val annotationsIterator = kotlinType.getAnnotationsSequence().iterator() - if (!annotationsIterator.hasNext()) return psiType - - if (psiType is PsiPrimitiveType) { - val annotation = annotationsIterator.next() - val provider = TypeAnnotationProvider.Static.create(annotation.toTypedArray()) - return psiType.annotate(provider) - } - - fun recursiveAnnotator(psiType: PsiType) { - if (!annotationsIterator.hasNext()) return - val typeAnnotations = annotationsIterator.next() - - if (psiType is PsiPrimitiveType) return //Primitive type cannot be type parameter so we skip it - - if (psiType is PsiClassType) { - for (parameterType in psiType.parameters) { - recursiveAnnotator(parameterType) - } - } else if (psiType is PsiArrayType) { - recursiveAnnotator(psiType.componentType) - } - - if (typeAnnotations.isEmpty()) return - - val provider = TypeAnnotationProvider.Static.create(typeAnnotations.toTypedArray()) - setPsiTypeAnnotationProvider(psiType, provider) - } - - recursiveAnnotator(psiType) - return psiType + return psiType.annotateByTypeAnnotationProvider(kotlinType.getAnnotationsSequence()) } internal fun KtUltraLightSupport.mapType( diff --git a/compiler/testData/asJava/lightClasses/lightClassByPsi/typeAnnotations.fir.java b/compiler/testData/asJava/lightClasses/lightClassByPsi/typeAnnotations.fir.java index 09ed720112b..d90725f5d66 100644 --- a/compiler/testData/asJava/lightClasses/lightClassByPsi/typeAnnotations.fir.java +++ b/compiler/testData/asJava/lightClasses/lightClassByPsi/typeAnnotations.fir.java @@ -58,7 +58,7 @@ public final class klass /* klass*/ { private final int x = 2 /* initializer type: int */; @org.jetbrains.annotations.NotNull() - public final X annotatedMethod(@org.jetbrains.annotations.NotNull() P>, @org.jetbrains.annotations.NotNull() Y[]);// annotatedMethod(P>, Y[]) + public final @A6() X annotatedMethod(@org.jetbrains.annotations.NotNull() @A0() P<@A1() X, P<@A2() @A3() X, @A4() Y>>, @org.jetbrains.annotations.NotNull() @A5() Y[]);// annotatedMethod(@A0() P<@A1() X, P<@A2() @A3() X, @A4() Y>>, @A5() Y[]) @org.jetbrains.annotations.Nullable() public final java.util.List getY();// getY()