[SLC] migrate from computeAnnotations to LazyAnnotationsBox

^KT-56046
This commit is contained in:
Dmitrii Gridin
2023-01-26 18:19:25 +01:00
committed by Space Team
parent 26b17a850d
commit dd5d858ad5
12 changed files with 155 additions and 418 deletions
@@ -1,43 +0,0 @@
/*
* Copyright 2010-2023 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.light.classes.symbol.annotations
import com.intellij.psi.PsiAnnotation
import com.intellij.psi.PsiAnnotationParameterList
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiModifierList
import org.jetbrains.kotlin.analysis.api.annotations.KtAnnotationApplication
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.light.classes.symbol.basicIsEquivalentTo
import org.jetbrains.kotlin.psi.KtCallElement
internal class SymbolLightAnnotationForAnnotationCall(
private val annotationCall: KtAnnotationApplication,
parent: PsiModifierList,
) : SymbolLightAbstractAnnotation(parent) {
private val _parameterList: PsiAnnotationParameterList by lazyPub {
symbolLightAnnotationParameterList(annotationCall.arguments)
}
override fun getParameterList(): PsiAnnotationParameterList = _parameterList
override val kotlinOrigin: KtCallElement? = annotationCall.psi
override fun getQualifiedName(): String? = annotationCall.classId?.asSingleFqName()?.asString()
override fun getName(): String? = qualifiedName
override fun equals(other: Any?): Boolean =
this === other ||
(other is SymbolLightAnnotationForAnnotationCall &&
kotlinOrigin == other.kotlinOrigin &&
annotationCall == other.annotationCall)
override fun hashCode(): Int = kotlinOrigin.hashCode()
override fun isEquivalentTo(another: PsiElement?): Boolean =
basicIsEquivalentTo(this, another as? PsiAnnotation)
}
@@ -5,34 +5,24 @@
package org.jetbrains.kotlin.light.classes.symbol.annotations
import com.intellij.psi.*
import com.intellij.psi.PsiClassType
import com.intellij.psi.PsiElement
import com.intellij.psi.impl.light.LightReferenceListBuilder
import org.jetbrains.annotations.NotNull
import org.jetbrains.annotations.Nullable
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
import org.jetbrains.kotlin.analysis.api.annotations.*
import org.jetbrains.kotlin.analysis.api.annotations.KtKClassAnnotationValue.KtNonLocalKClassAnnotationValue
import org.jetbrains.kotlin.analysis.api.components.buildClassType
import org.jetbrains.kotlin.analysis.api.symbols.KtFunctionSymbol
import org.jetbrains.kotlin.analysis.api.symbols.KtNamedClassOrObjectSymbol
import org.jetbrains.kotlin.analysis.api.symbols.markers.KtAnnotatedSymbol
import org.jetbrains.kotlin.analysis.api.types.KtTypeMappingMode
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.builtins.StandardNames.DEFAULT_VALUE_PARAMETER
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.light.classes.symbol.NullabilityType
import org.jetbrains.kotlin.light.classes.symbol.classes.SymbolLightClassBase
import org.jetbrains.kotlin.light.classes.symbol.methods.SymbolLightMethod
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
import org.jetbrains.kotlin.name.CallableId
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.JvmNames.JVM_OVERLOADS_CLASS_ID
import org.jetbrains.kotlin.name.JvmNames.JVM_SYNTHETIC_ANNOTATION_CLASS_ID
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.StandardClassIds
import org.jetbrains.kotlin.resolve.deprecation.DeprecationLevelValue
import java.lang.annotation.ElementType
internal fun KtAnnotatedSymbol.hasJvmSyntheticAnnotation(
annotationUseSiteTarget: AnnotationUseSiteTarget? = null,
@@ -91,201 +81,6 @@ internal fun KtAnnotatedSymbol.findAnnotation(
}
}
internal fun NullabilityType.computeNullabilityAnnotation(parent: PsiModifierList): SymbolLightSimpleAnnotation? = when (this) {
NullabilityType.NotNull -> NotNull::class.java
NullabilityType.Nullable -> Nullable::class.java
else -> null
}?.let {
SymbolLightSimpleAnnotation(it.name, parent)
}
context(KtAnalysisSession)
internal fun KtAnnotatedSymbol.computeAnnotations(
modifierList: PsiModifierList,
nullability: NullabilityType,
annotationUseSiteTarget: AnnotationUseSiteTarget?,
includeAnnotationsWithoutSite: Boolean = true,
): List<PsiAnnotation> {
val parent = modifierList.parent
val nullabilityAnnotation = nullability.computeNullabilityAnnotation(modifierList)
val parentIsAnnotation = (parent as? PsiClass)?.isAnnotationType == true
val result = mutableListOf<PsiAnnotation>()
if (parent is SymbolLightMethod<*>) {
if (parent.isDelegated || parent.isOverride()) {
result.add(SymbolLightSimpleAnnotation(java.lang.Override::class.java.name, modifierList))
}
}
val foundAnnotations = hashSetOf<String>()
for (annotation in annotations) {
annotation.classId?.asFqNameString()?.let(foundAnnotations::add)
val siteTarget = annotation.useSiteTarget
if (siteTarget == annotationUseSiteTarget || includeAnnotationsWithoutSite && siteTarget == null) {
result.add(SymbolLightAnnotationForAnnotationCall(annotation, modifierList))
}
}
if (parentIsAnnotation) {
for (annotation in annotations) {
val convertedAnnotation = annotation.tryConvertAsRetention(foundAnnotations, modifierList)
?: annotation.tryConvertAsTarget(foundAnnotations, modifierList)
?: annotation.tryConvertAsMustBeDocumented(foundAnnotations, modifierList)
?: annotation.tryConvertAsRepeatable(foundAnnotations, modifierList, this)
?: continue
result += convertedAnnotation
}
if (StandardClassIds.Annotations.Retention.asFqNameString() !in foundAnnotations) {
result += createRetentionAnnotation(modifierList)
}
}
if (nullabilityAnnotation != null) {
result.add(nullabilityAnnotation)
}
return result
}
private fun KtAnnotationApplication.tryConvertAsRetention(foundAnnotations: Set<String>, modifierList: PsiModifierList): PsiAnnotation? {
if (classId != StandardClassIds.Annotations.Retention) return null
if (JvmAnnotationNames.RETENTION_ANNOTATION.asString() in foundAnnotations) return null
val argumentWithKotlinRetention = arguments.firstOrNull {
it.name == DEFAULT_VALUE_PARAMETER
}?.expression as? KtEnumEntryAnnotationValue
val kotlinRetentionName = argumentWithKotlinRetention?.callableId?.callableName?.asString()
return createRetentionAnnotation(modifierList, kotlinRetentionName)
}
private fun KtAnnotationApplication.tryConvertAsTarget(
foundAnnotations: Set<String>,
modifierList: PsiModifierList
): PsiAnnotation? = tryConvertAs(
foundAnnotations = foundAnnotations,
modifierList = modifierList,
kotlinClassId = StandardClassIds.Annotations.Target,
javaQualifier = JvmAnnotationNames.TARGET_ANNOTATION.asString(),
argumentsComputer = fun(): List<KtNamedAnnotationValue>? {
val allowedKotlinTargets = arguments.firstOrNull()?.expression as? KtArrayAnnotationValue ?: return null
val javaTargetNames = allowedKotlinTargets.values.mapNotNullTo(linkedSetOf(), KtAnnotationValue::mapToJavaTarget)
return listOf(
KtNamedAnnotationValue(
name = DEFAULT_VALUE_PARAMETER,
expression = KtArrayAnnotationValue(
values = javaTargetNames.map {
KtEnumEntryAnnotationValue(
callableId = CallableId(
classId = StandardClassIds.Annotations.Java.ElementType,
callableName = Name.identifier(it),
),
sourcePsi = null,
)
},
sourcePsi = null,
)
)
)
}
)
private fun KtAnnotationValue.mapToJavaTarget(): String? {
if (this !is KtEnumEntryAnnotationValue) return null
val callableId = callableId ?: return null
if (callableId.classId != StandardClassIds.AnnotationTarget) return null
return when (callableId.callableName.asString()) {
AnnotationTarget.CLASS.name -> ElementType.TYPE
AnnotationTarget.ANNOTATION_CLASS.name -> ElementType.ANNOTATION_TYPE
AnnotationTarget.FIELD.name -> ElementType.FIELD
AnnotationTarget.LOCAL_VARIABLE.name -> ElementType.LOCAL_VARIABLE
AnnotationTarget.VALUE_PARAMETER.name -> ElementType.PARAMETER
AnnotationTarget.CONSTRUCTOR.name -> ElementType.CONSTRUCTOR
AnnotationTarget.FUNCTION.name, AnnotationTarget.PROPERTY_GETTER.name, AnnotationTarget.PROPERTY_SETTER.name -> ElementType.METHOD
AnnotationTarget.TYPE_PARAMETER.name -> ElementType.TYPE_PARAMETER
AnnotationTarget.TYPE.name -> ElementType.TYPE_USE
else -> null
}?.name
}
context(KtAnalysisSession)
private fun KtAnnotationApplication.tryConvertAsRepeatable(
foundAnnotations: Set<String>,
modifierList: PsiModifierList,
ktAnnotatedSymbol: KtAnnotatedSymbol
): PsiAnnotation? = tryConvertAs(
foundAnnotations = foundAnnotations,
modifierList = modifierList,
kotlinClassId = StandardClassIds.Annotations.Repeatable,
javaQualifier = JvmAnnotationNames.REPEATABLE_ANNOTATION.asString(),
argumentsComputer = fun(): List<KtNamedAnnotationValue>? {
if (ktAnnotatedSymbol !is KtNamedClassOrObjectSymbol) return null
val annotationClassId = ktAnnotatedSymbol.classIdIfNonLocal ?: return null
return listOf(
KtNamedAnnotationValue(
name = DEFAULT_VALUE_PARAMETER,
expression = KtNonLocalKClassAnnotationValue(
classId = annotationClassId.createNestedClassId(Name.identifier(JvmAbi.REPEATABLE_ANNOTATION_CONTAINER_NAME)),
sourcePsi = null,
)
)
)
},
)
private fun KtAnnotationApplication.tryConvertAsMustBeDocumented(
foundAnnotations: Set<String>,
modifierList: PsiModifierList,
): PsiAnnotation? = tryConvertAs(
foundAnnotations = foundAnnotations,
modifierList = modifierList,
kotlinClassId = StandardClassIds.Annotations.MustBeDocumented,
javaQualifier = JvmAnnotationNames.DOCUMENTED_ANNOTATION.asString(),
)
private fun KtAnnotationApplication.tryConvertAs(
foundAnnotations: Set<String>,
modifierList: PsiModifierList,
kotlinClassId: ClassId,
javaQualifier: String,
argumentsComputer: (() -> List<KtNamedAnnotationValue>?)? = null,
): PsiAnnotation? {
if (classId != kotlinClassId) return null
if (javaQualifier in foundAnnotations) return null
val arguments = if (argumentsComputer != null) {
argumentsComputer() ?: return null
} else {
emptyList()
}
return SymbolLightSimpleAnnotation(fqName = javaQualifier, parent = modifierList, arguments = arguments)
}
private fun createRetentionAnnotation(
modifierList: PsiModifierList,
retentionName: String? = null,
): PsiAnnotation = SymbolLightSimpleAnnotation(
fqName = JvmAnnotationNames.RETENTION_ANNOTATION.asString(),
parent = modifierList,
arguments = listOf(
KtNamedAnnotationValue(
name = DEFAULT_VALUE_PARAMETER,
expression = KtEnumEntryAnnotationValue(
callableId = CallableId(
StandardClassIds.Annotations.Java.RetentionPolicy,
Name.identifier(retentionName ?: AnnotationRetention.RUNTIME.name),
),
sourcePsi = null,
)
)
)
)
context(KtAnalysisSession)
internal fun KtAnnotatedSymbol.computeThrowsList(
builder: LightReferenceListBuilder,
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.analysis.api.scopes.KtScope
import org.jetbrains.kotlin.analysis.api.symbols.*
import org.jetbrains.kotlin.analysis.api.symbols.markers.KtAnnotatedSymbol
import org.jetbrains.kotlin.analysis.api.symbols.markers.KtSymbolWithVisibility
import org.jetbrains.kotlin.analysis.api.symbols.pointers.symbolPointerOfType
import org.jetbrains.kotlin.analysis.project.structure.KtModule
import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade
import org.jetbrains.kotlin.asJava.classes.lazyPub
@@ -25,12 +26,8 @@ import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.fileClasses.isJvmMultifileClassFile
import org.jetbrains.kotlin.fileClasses.javaFileFacadeFqName
import org.jetbrains.kotlin.idea.KotlinLanguage
import org.jetbrains.kotlin.light.classes.symbol.NullabilityType
import org.jetbrains.kotlin.light.classes.symbol.analyzeForLightClasses
import org.jetbrains.kotlin.light.classes.symbol.annotations.SimpleAnnotationsBox
import org.jetbrains.kotlin.light.classes.symbol.annotations.computeAnnotations
import org.jetbrains.kotlin.light.classes.symbol.annotations.hasInlineOnlyAnnotation
import org.jetbrains.kotlin.light.classes.symbol.annotations.hasJvmFieldAnnotation
import org.jetbrains.kotlin.light.classes.symbol.annotations.*
import org.jetbrains.kotlin.light.classes.symbol.fields.SymbolLightField
import org.jetbrains.kotlin.light.classes.symbol.modifierLists.SimpleModifiersBox
import org.jetbrains.kotlin.light.classes.symbol.modifierLists.SymbolLightClassModifierList
@@ -67,21 +64,17 @@ class SymbolLightClassForFacade(
SymbolLightClassModifierList(
containingDeclaration = this,
modifiersBox = SimpleModifiersBox(PsiModifier.PUBLIC, PsiModifier.FINAL),
annotationsBox = SimpleAnnotationsBox { modifierList ->
if (multiFileClass) {
emptyList()
} else {
withFileSymbols { fileSymbols ->
fileSymbols.flatMap {
it.computeAnnotations(
modifierList = modifierList,
nullability = NullabilityType.Unknown,
annotationUseSiteTarget = AnnotationUseSiteTarget.FILE,
includeAnnotationsWithoutSite = false,
)
}
}
}
annotationsBox = if (multiFileClass) {
EmptyAnnotationsBox
} else {
LazyAnnotationsBox(
annotationsProvider = SymbolAnnotationsProvider(
ktModule = ktModule,
annotatedSymbolPointer = firstFileInFacade.symbolPointerOfType<KtFileSymbol>(),
annotationUseSiteTarget = AnnotationUseSiteTarget.FILE,
acceptAnnotationsWithoutSite = true,
)
)
},
)
}
@@ -10,10 +10,7 @@ import kotlinx.collections.immutable.persistentHashSetOf
import org.jetbrains.kotlin.asJava.classes.KtLightClass
import org.jetbrains.kotlin.asJava.elements.KtLightField
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.light.classes.symbol.NullabilityType
import org.jetbrains.kotlin.light.classes.symbol.annotations.SimpleAnnotationsBox
import org.jetbrains.kotlin.light.classes.symbol.annotations.SymbolLightSimpleAnnotation
import org.jetbrains.kotlin.light.classes.symbol.annotations.computeAnnotations
import org.jetbrains.kotlin.light.classes.symbol.annotations.*
import org.jetbrains.kotlin.light.classes.symbol.methods.SymbolLightRepeatableAnnotationContainerMethod
import org.jetbrains.kotlin.light.classes.symbol.modifierLists.SimpleModifiersBox
import org.jetbrains.kotlin.light.classes.symbol.modifierLists.SymbolLightClassModifierList
@@ -43,19 +40,17 @@ internal class SymbolLightClassForRepeatableAnnotationContainer(private val cont
// It is marked as Abstract because all the annotation classes are marked as Abstract
// It is marked as Static because all nested interfaces are marked as Static
modifiersBox = SimpleModifiersBox(PsiModifier.PUBLIC, PsiModifier.STATIC, PsiModifier.ABSTRACT),
annotationsBox = SimpleAnnotationsBox { psiModifierList ->
val annotations = withClassOrObjectSymbol { classOrObjectSymbol ->
classOrObjectSymbol.computeAnnotations(
modifierList = psiModifierList,
nullability = NullabilityType.Unknown,
annotationUseSiteTarget = null,
)
}.filter {
it.qualifiedName in allowedAnnotations
}
annotations + SymbolLightSimpleAnnotation(fqName = KOTLIN_JVM_INTERNAL_REPEATABLE_CONTAINER, parent = psiModifierList)
},
annotationsBox = LazyAnnotationsBox(
annotationsProvider = SymbolAnnotationsProvider(
ktModule = ktModule,
annotatedSymbolPointer = classOrObjectSymbolPointer,
),
additionalAnnotationsProvider = CompositeAdditionalAnnotationsProvider(
SimpleAdditionalAnnotationsProvider(KOTLIN_JVM_INTERNAL_REPEATABLE_CONTAINER),
AbstractClassAdditionalAnnotationsProvider,
),
annotationFilter = SimpleAnnotationFilter(allowedAnnotations),
),
)
override fun computeOwnMethods(): List<PsiMethod> = listOf(
@@ -74,13 +69,14 @@ internal class SymbolLightClassForRepeatableAnnotationContainer(private val cont
override fun hashCode(): Int = containerOwner.hashCode()
companion object {
private const val KOTLIN_JVM_INTERNAL_REPEATABLE_CONTAINER = "kotlin.jvm.internal.RepeatableContainer"
private val allowedAnnotations = persistentHashSetOf(
CommonClassNames.JAVA_LANG_ANNOTATION_RETENTION,
StandardNames.FqNames.retention.asString(),
CommonClassNames.JAVA_LANG_ANNOTATION_TARGET,
StandardNames.FqNames.target.asString(),
KOTLIN_JVM_INTERNAL_REPEATABLE_CONTAINER,
)
private const val KOTLIN_JVM_INTERNAL_REPEATABLE_CONTAINER = "kotlin.jvm.internal.RepeatableContainer"
}
}
@@ -8,13 +8,13 @@ package org.jetbrains.kotlin.light.classes.symbol.fields
import com.intellij.psi.*
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
import org.jetbrains.kotlin.analysis.api.symbols.KtEnumEntrySymbol
import org.jetbrains.kotlin.analysis.api.symbols.pointers.symbolPointerOfType
import org.jetbrains.kotlin.asJava.classes.cannotModify
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.light.classes.symbol.NullabilityType
import org.jetbrains.kotlin.light.classes.symbol.analyzeForLightClasses
import org.jetbrains.kotlin.light.classes.symbol.annotations.SimpleAnnotationsBox
import org.jetbrains.kotlin.light.classes.symbol.annotations.computeAnnotations
import org.jetbrains.kotlin.light.classes.symbol.annotations.LazyAnnotationsBox
import org.jetbrains.kotlin.light.classes.symbol.annotations.SymbolAnnotationsProvider
import org.jetbrains.kotlin.light.classes.symbol.classes.SymbolLightClassForClassOrObject
import org.jetbrains.kotlin.light.classes.symbol.classes.SymbolLightClassForEnumEntry
import org.jetbrains.kotlin.light.classes.symbol.isOriginEquivalentTo
@@ -38,15 +38,14 @@ internal class SymbolLightFieldForEnumEntry(
SymbolLightMemberModifierList(
containingDeclaration = this,
modifiersBox = SimpleModifiersBox(PsiModifier.STATIC, PsiModifier.FINAL, PsiModifier.PUBLIC),
annotationsBox = SimpleAnnotationsBox { modifierList ->
withEnumEntrySymbol { enumEntrySymbol ->
enumEntrySymbol.computeAnnotations(
modifierList,
nullability = NullabilityType.Unknown, // there is no need to add nullability annotations on enum entries
annotationUseSiteTarget = AnnotationUseSiteTarget.FIELD,
)
}
},
annotationsBox = LazyAnnotationsBox(
annotationsProvider = SymbolAnnotationsProvider(
ktModule = ktModule,
annotatedSymbolPointer = enumEntry.symbolPointerOfType<KtEnumEntrySymbol>(),
annotationUseSiteTarget = AnnotationUseSiteTarget.FIELD,
acceptAnnotationsWithoutSite = true,
)
),
)
}
@@ -19,8 +19,9 @@ import org.jetbrains.kotlin.asJava.builder.LightMemberOrigin
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.light.classes.symbol.*
import org.jetbrains.kotlin.light.classes.symbol.annotations.SimpleAnnotationsBox
import org.jetbrains.kotlin.light.classes.symbol.annotations.computeAnnotations
import org.jetbrains.kotlin.light.classes.symbol.annotations.LazyAnnotationsBox
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.hasDeprecatedAnnotation
import org.jetbrains.kotlin.light.classes.symbol.classes.SymbolLightClassBase
import org.jetbrains.kotlin.light.classes.symbol.modifierLists.LazyModifiersBox
@@ -147,21 +148,23 @@ internal class SymbolLightFieldForProperty private constructor(
SymbolLightMemberModifierList(
containingDeclaration = this,
modifiersBox = LazyModifiersBox(initializerValue, ::computeModifiers),
annotationsBox = SimpleAnnotationsBox { modifierList ->
withPropertySymbol { propertySymbol ->
val nullability = if (!(propertySymbol is KtKotlinPropertySymbol && propertySymbol.isLateInit)) {
getTypeNullability(propertySymbol.returnType)
} else {
NullabilityType.Unknown
annotationsBox = LazyAnnotationsBox(
annotationsProvider = SymbolAnnotationsProvider(
ktModule = ktModule,
annotatedSymbolPointer = propertySymbolPointer,
annotationUseSiteTarget = AnnotationUseSiteTarget.FIELD,
acceptAnnotationsWithoutSite = true,
),
additionalAnnotationsProvider = NullabilityAnnotationsProvider {
withPropertySymbol { propertySymbol ->
if (!(propertySymbol is KtKotlinPropertySymbol && propertySymbol.isLateInit)) {
getTypeNullability(propertySymbol.returnType)
} else {
NullabilityType.Unknown
}
}
propertySymbol.computeAnnotations(
modifierList = modifierList,
nullability = nullability,
annotationUseSiteTarget = AnnotationUseSiteTarget.FIELD,
)
}
},
),
)
}
@@ -141,30 +141,6 @@ internal class SymbolLightAccessorMethod private constructor(
}
}
private fun computeAnnotations(modifierList: PsiModifierList): List<PsiAnnotation> = analyzeForLightClasses(ktModule) {
val nullabilityApplicable = isGetter &&
!modifierList.hasModifierProperty(PsiModifier.PRIVATE) &&
!(isParameter && containingClass.isAnnotationType)
val propertySymbol = propertySymbol()
val nullabilityType = if (nullabilityApplicable) getTypeNullability(propertySymbol.returnType) else NullabilityType.Unknown
val annotationsFromProperty = propertySymbol.computeAnnotations(
modifierList = modifierList,
nullability = nullabilityType,
annotationUseSiteTarget = accessorSite,
includeAnnotationsWithoutSite = false,
)
val propertyAccessorSymbol = propertyAccessorSymbol()
val annotationsFromAccessor = propertyAccessorSymbol.computeAnnotations(
modifierList = modifierList,
nullability = NullabilityType.Unknown,
annotationUseSiteTarget = accessorSite,
)
annotationsFromProperty + annotationsFromAccessor
}
private fun computeModifiers(modifier: String): Map<String, Boolean>? = when (modifier) {
in LazyModifiersBox.VISIBILITY_MODIFIERS -> LazyModifiersBox.computeVisibilityForMember(ktModule, propertyAccessorSymbolPointer)
@@ -205,7 +181,34 @@ internal class SymbolLightAccessorMethod private constructor(
SymbolLightMemberModifierList(
containingDeclaration = this,
modifiersBox = LazyModifiersBox(computer = ::computeModifiers),
annotationsBox = SimpleAnnotationsBox(::computeAnnotations),
annotationsBox = LazyAnnotationsBox(
annotationsProvider = CompositeAnnotationsProvider(
SymbolAnnotationsProvider(
ktModule = ktModule,
annotatedSymbolPointer = propertyAccessorSymbolPointer,
annotationUseSiteTarget = accessorSite,
acceptAnnotationsWithoutSite = true,
),
SymbolAnnotationsProvider(
ktModule = ktModule,
annotatedSymbolPointer = containingPropertySymbolPointer,
annotationUseSiteTarget = accessorSite,
),
),
additionalAnnotationsProvider = NullabilityAnnotationsProvider {
val nullabilityApplicable = isGetter &&
!(isParameter && containingClass.isAnnotationType) &&
!modifierList.hasModifierProperty(PsiModifier.PRIVATE)
if (nullabilityApplicable) {
analyzeForLightClasses(ktModule) {
getTypeNullability(propertySymbol().returnType)
}
} else {
NullabilityType.Unknown
}
}
),
)
}
@@ -9,9 +9,8 @@ import com.intellij.psi.*
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
import org.jetbrains.kotlin.analysis.api.symbols.KtConstructorSymbol
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.light.classes.symbol.NullabilityType
import org.jetbrains.kotlin.light.classes.symbol.annotations.SimpleAnnotationsBox
import org.jetbrains.kotlin.light.classes.symbol.annotations.computeAnnotations
import org.jetbrains.kotlin.light.classes.symbol.annotations.LazyAnnotationsBox
import org.jetbrains.kotlin.light.classes.symbol.annotations.SymbolAnnotationsProvider
import org.jetbrains.kotlin.light.classes.symbol.classes.SymbolLightClassBase
import org.jetbrains.kotlin.light.classes.symbol.classes.SymbolLightClassForEnumEntry
import org.jetbrains.kotlin.light.classes.symbol.modifierLists.LazyModifiersBox
@@ -57,15 +56,12 @@ internal class SymbolLightConstructor(
initialValue = initialValue,
computer = ::computeModifiers,
),
annotationsBox = SimpleAnnotationsBox { modifierList ->
withFunctionSymbol { constructorSymbol ->
constructorSymbol.computeAnnotations(
modifierList = modifierList,
nullability = NullabilityType.Unknown,
annotationUseSiteTarget = null,
)
}
},
annotationsBox = LazyAnnotationsBox(
annotationsProvider = SymbolAnnotationsProvider(
ktModule = ktModule,
annotatedSymbolPointer = functionSymbolPointer,
)
),
)
}
@@ -17,10 +17,7 @@ import org.jetbrains.kotlin.asJava.builder.LightMemberOrigin
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.light.classes.symbol.*
import org.jetbrains.kotlin.light.classes.symbol.annotations.SimpleAnnotationsBox
import org.jetbrains.kotlin.light.classes.symbol.annotations.computeAnnotations
import org.jetbrains.kotlin.light.classes.symbol.annotations.hasInlineOnlyAnnotation
import org.jetbrains.kotlin.light.classes.symbol.annotations.hasJvmStaticAnnotation
import org.jetbrains.kotlin.light.classes.symbol.annotations.*
import org.jetbrains.kotlin.light.classes.symbol.classes.SymbolLightClassBase
import org.jetbrains.kotlin.light.classes.symbol.modifierLists.LazyModifiersBox
import org.jetbrains.kotlin.light.classes.symbol.modifierLists.SymbolLightMemberModifierList
@@ -72,25 +69,6 @@ internal class SymbolLightSimpleMethod(
override fun getTypeParameterList(): PsiTypeParameterList? = _typeParameterList
override fun getTypeParameters(): Array<PsiTypeParameter> = _typeParameterList?.typeParameters ?: PsiTypeParameter.EMPTY_ARRAY
private fun computeAnnotations(
modifierList: PsiModifierList,
): List<PsiAnnotation> = withFunctionSymbol { functionSymbol ->
val nullability = when {
modifierList.hasModifierProperty(PsiModifier.PRIVATE) -> NullabilityType.Unknown
functionSymbol.isSuspend -> /* Any? */ NullabilityType.Nullable
else -> {
val returnType = functionSymbol.returnType
if (returnType.isVoidType) NullabilityType.Unknown else getTypeNullability(returnType)
}
}
functionSymbol.computeAnnotations(
modifierList = modifierList,
nullability = nullability,
annotationUseSiteTarget = null,
)
}
private fun computeModifiers(modifier: String): Map<String, Boolean>? = when (modifier) {
in LazyModifiersBox.MODALITY_MODIFIERS -> {
ifInlineOnly { return modifiersForInlineOnlyCase() }
@@ -160,7 +138,29 @@ internal class SymbolLightSimpleMethod(
SymbolLightMemberModifierList(
containingDeclaration = this,
modifiersBox = LazyModifiersBox(computer = ::computeModifiers),
annotationsBox = SimpleAnnotationsBox(::computeAnnotations),
annotationsBox = LazyAnnotationsBox(
annotationsProvider = SymbolAnnotationsProvider(
ktModule = ktModule,
annotatedSymbolPointer = functionSymbolPointer,
),
additionalAnnotationsProvider = CompositeAdditionalAnnotationsProvider(
NullabilityAnnotationsProvider {
if (modifierList.hasModifierProperty(PsiModifier.PRIVATE)) {
NullabilityType.Unknown
} else {
withFunctionSymbol { functionSymbol ->
if (functionSymbol.isSuspend) { // Any?
NullabilityType.Nullable
} else {
val returnType = functionSymbol.returnType
if (returnType.isVoidType) NullabilityType.Unknown else getTypeNullability(returnType)
}
}
}
},
MethodAdditionalAnnotationsProvider,
),
)
)
}
@@ -10,9 +10,9 @@ import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
import org.jetbrains.kotlin.analysis.api.symbols.KtValueParameterSymbol
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.light.classes.symbol.NullabilityType
import org.jetbrains.kotlin.light.classes.symbol.annotations.SimpleAnnotationsBox
import org.jetbrains.kotlin.light.classes.symbol.annotations.computeAnnotations
import org.jetbrains.kotlin.light.classes.symbol.annotations.LazyAnnotationsBox
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.methods.SymbolLightMethodBase
import org.jetbrains.kotlin.light.classes.symbol.modifierLists.SymbolLightClassModifierList
import org.jetbrains.kotlin.light.classes.symbol.withSymbol
@@ -30,21 +30,17 @@ internal class SymbolLightParameter(
private val _modifierList: PsiModifierList by lazyPub {
SymbolLightClassModifierList(
containingDeclaration = this,
annotationsBox = SimpleAnnotationsBox { modifierList ->
val annotationSite = isConstructorParameterSymbol.ifTrue {
AnnotationUseSiteTarget.CONSTRUCTOR_PARAMETER
}
parameterSymbolPointer.withSymbol(ktModule) { parameterSymbol ->
val nullability = if (parameterSymbol.isVararg) NullabilityType.NotNull else super.nullabilityType
parameterSymbol.computeAnnotations(
modifierList = modifierList,
nullability = nullability,
annotationUseSiteTarget = annotationSite,
includeAnnotationsWithoutSite = true,
)
}
},
annotationsBox = LazyAnnotationsBox(
annotationsProvider = SymbolAnnotationsProvider(
ktModule = ktModule,
annotatedSymbolPointer = parameterSymbolPointer,
annotationUseSiteTarget = isConstructorParameterSymbol.ifTrue {
AnnotationUseSiteTarget.CONSTRUCTOR_PARAMETER
},
acceptAnnotationsWithoutSite = true,
),
additionalAnnotationsProvider = NullabilityAnnotationsProvider(::nullabilityType),
),
)
}
@@ -51,11 +51,13 @@ internal abstract class SymbolLightParameterCommon(
KtLightIdentifier(this, parameterDeclaration)
}
protected val nullabilityType: NullabilityType by lazyPub {
protected fun nullabilityType(): NullabilityType {
if (isVarArgs) return NullabilityType.NotNull
val nullabilityApplicable = !containingMethod.hasModifierProperty(PsiModifier.PRIVATE) &&
!containingMethod.containingClass.let { it.isAnnotationType || it.isEnum }
if (nullabilityApplicable) {
return if (nullabilityApplicable) {
parameterSymbolPointer.withSymbol(ktModule) { getTypeNullability(it.returnType) }
} else {
NullabilityType.Unknown
@@ -12,13 +12,12 @@ import org.jetbrains.kotlin.analysis.api.symbols.KtValueParameterSymbol
import org.jetbrains.kotlin.analysis.api.symbols.pointers.KtSymbolPointer
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.light.classes.symbol.NullabilityType
import org.jetbrains.kotlin.light.classes.symbol.analyzeForLightClasses
import org.jetbrains.kotlin.light.classes.symbol.annotations.SimpleAnnotationsBox
import org.jetbrains.kotlin.light.classes.symbol.annotations.computeAnnotations
import org.jetbrains.kotlin.light.classes.symbol.annotations.CompositeAnnotationsProvider
import org.jetbrains.kotlin.light.classes.symbol.annotations.LazyAnnotationsBox
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.methods.SymbolLightMethodBase
import org.jetbrains.kotlin.light.classes.symbol.modifierLists.SymbolLightClassModifierList
import org.jetbrains.kotlin.light.classes.symbol.restoreSymbolOrThrowIfDisposed
import org.jetbrains.kotlin.light.classes.symbol.withSymbol
import org.jetbrains.kotlin.name.SpecialNames
@@ -44,24 +43,22 @@ internal class SymbolLightSetterParameter(
private val _modifierList: PsiModifierList by lazyPub {
SymbolLightClassModifierList(
containingDeclaration = this,
annotationsBox = SimpleAnnotationsBox { modifierList ->
analyzeForLightClasses(ktModule) {
val annotationsFromSetter = parameterSymbolPointer.restoreSymbolOrThrowIfDisposed().computeAnnotations(
modifierList = modifierList,
nullability = NullabilityType.Unknown,
annotationsBox = LazyAnnotationsBox(
annotationsProvider = CompositeAnnotationsProvider(
SymbolAnnotationsProvider(
ktModule = ktModule,
annotatedSymbolPointer = parameterSymbolPointer,
annotationUseSiteTarget = AnnotationUseSiteTarget.SETTER_PARAMETER,
)
val annotationsFromProperty = containingPropertySymbolPointer.restoreSymbolOrThrowIfDisposed().computeAnnotations(
modifierList = modifierList,
nullability = nullabilityType,
acceptAnnotationsWithoutSite = true,
),
SymbolAnnotationsProvider(
ktModule = ktModule,
annotatedSymbolPointer = containingPropertySymbolPointer,
annotationUseSiteTarget = AnnotationUseSiteTarget.SETTER_PARAMETER,
includeAnnotationsWithoutSite = false,
)
annotationsFromSetter + annotationsFromProperty
}
},
),
),
additionalAnnotationsProvider = NullabilityAnnotationsProvider(::nullabilityType),
),
)
}