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 179666e3128..9a039f1e3c8 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 @@ -33,8 +33,10 @@ import org.jetbrains.kotlin.resolve.annotations.JVM_STATIC_ANNOTATION_CLASS_ID import org.jetbrains.kotlin.resolve.deprecation.DeprecationLevelValue import org.jetbrains.kotlin.resolve.inline.INLINE_ONLY_ANNOTATION_FQ_NAME -internal fun KtAnnotatedSymbol.hasJvmSyntheticAnnotation(annotationUseSiteTarget: AnnotationUseSiteTarget? = null): Boolean = - hasAnnotation(JVM_SYNTHETIC_ANNOTATION_CLASS_ID, annotationUseSiteTarget) +internal fun KtAnnotatedSymbol.hasJvmSyntheticAnnotation( + annotationUseSiteTarget: AnnotationUseSiteTarget? = null, + strictUseSite: Boolean = true, +): Boolean = hasAnnotation(JVM_SYNTHETIC_ANNOTATION_CLASS_ID, annotationUseSiteTarget, strictUseSite) internal fun KtFileSymbol.hasJvmMultifileClassAnnotation(): Boolean = hasAnnotation(JVM_MULTIFILE_CLASS_ID, AnnotationUseSiteTarget.FILE) @@ -54,14 +56,16 @@ internal fun KtAnnotatedSymbol.getJvmNameFromAnnotation(annotationUseSiteTarget: context(KtAnalysisSession) internal fun isHiddenByDeprecation( symbol: KtAnnotatedSymbol, - annotationUseSiteTarget: AnnotationUseSiteTarget? = null + annotationUseSiteTarget: AnnotationUseSiteTarget? = null, ): Boolean { return symbol.getDeprecationStatus(annotationUseSiteTarget)?.deprecationLevel == DeprecationLevelValue.HIDDEN } context(KtAnalysisSession) -internal fun KtAnnotatedSymbol.isHiddenOrSynthetic(annotationUseSiteTarget: AnnotationUseSiteTarget? = null) = - isHiddenByDeprecation(this, annotationUseSiteTarget) || hasJvmSyntheticAnnotation(annotationUseSiteTarget) +internal fun KtAnnotatedSymbol.isHiddenOrSynthetic( + annotationUseSiteTarget: AnnotationUseSiteTarget? = null, + strictUseSite: Boolean = true, +) = isHiddenByDeprecation(this, annotationUseSiteTarget) || hasJvmSyntheticAnnotation(annotationUseSiteTarget, strictUseSite) internal fun KtAnnotatedSymbol.hasJvmFieldAnnotation(): Boolean = hasAnnotation(JVM_FIELD_ANNOTATION_CLASS_ID, null) @@ -69,27 +73,38 @@ internal fun KtAnnotatedSymbol.hasJvmFieldAnnotation(): Boolean = internal fun KtAnnotatedSymbol.hasPublishedApiAnnotation(annotationUseSiteTarget: AnnotationUseSiteTarget? = null): Boolean = hasAnnotation(StandardClassIds.Annotations.PublishedApi, annotationUseSiteTarget) -internal fun KtAnnotatedSymbol.hasDeprecatedAnnotation(annotationUseSiteTarget: AnnotationUseSiteTarget? = null): Boolean = - hasAnnotation(StandardClassIds.Annotations.Deprecated, annotationUseSiteTarget) +internal fun KtAnnotatedSymbol.hasDeprecatedAnnotation( + annotationUseSiteTarget: AnnotationUseSiteTarget? = null, + strictUseSite: Boolean = true, +): Boolean = hasAnnotation(StandardClassIds.Annotations.Deprecated, annotationUseSiteTarget, strictUseSite) -internal fun KtAnnotatedSymbol.hasJvmOverloadsAnnotation(): Boolean = - hasAnnotation(JVM_OVERLOADS_CLASS_ID, null) +internal fun KtAnnotatedSymbol.hasJvmOverloadsAnnotation(): Boolean = hasAnnotation(JVM_OVERLOADS_CLASS_ID, null) -internal fun KtAnnotatedSymbol.hasJvmStaticAnnotation(annotationUseSiteTarget: AnnotationUseSiteTarget? = null): Boolean = - hasAnnotation(JVM_STATIC_ANNOTATION_CLASS_ID, annotationUseSiteTarget) +internal fun KtAnnotatedSymbol.hasJvmStaticAnnotation( + annotationUseSiteTarget: AnnotationUseSiteTarget? = null, + strictUseSite: Boolean = true, +): Boolean = hasAnnotation(JVM_STATIC_ANNOTATION_CLASS_ID, annotationUseSiteTarget, strictUseSite) internal fun KtAnnotatedSymbol.hasInlineOnlyAnnotation(): Boolean = hasAnnotation(INLINE_ONLY_ANNOTATION_FQ_NAME, null) -internal fun KtAnnotatedSymbol.hasAnnotation(classId: ClassId, annotationUseSiteTarget: AnnotationUseSiteTarget?): Boolean = - annotations.any { - it.useSiteTarget == annotationUseSiteTarget && it.classId == classId - } +internal fun KtAnnotatedSymbol.hasAnnotation( + classId: ClassId, + annotationUseSiteTarget: AnnotationUseSiteTarget?, + strictUseSite: Boolean = true, +): Boolean = annotations.any { + val useSiteTarget = it.useSiteTarget + (useSiteTarget == annotationUseSiteTarget || !strictUseSite && useSiteTarget == null) && it.classId == classId +} -internal fun KtAnnotatedSymbol.hasAnnotation(fqName: FqName, annotationUseSiteTarget: AnnotationUseSiteTarget?): Boolean = - annotations.any { - it.useSiteTarget == annotationUseSiteTarget && it.classId?.asSingleFqName() == fqName - } +internal fun KtAnnotatedSymbol.hasAnnotation( + fqName: FqName, + annotationUseSiteTarget: AnnotationUseSiteTarget?, + strictUseSite: Boolean = true, +): Boolean = annotations.any { + val useSiteTarget = it.useSiteTarget + (useSiteTarget == annotationUseSiteTarget || !strictUseSite && useSiteTarget == null) && it.classId?.asSingleFqName() == fqName +} internal fun NullabilityType.computeNullabilityAnnotation(parent: PsiModifierList): SymbolLightSimpleAnnotation? { return when (this) { diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassForClassOrObject.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassForClassOrObject.kt index 56e8fc40a3f..b5e6dbbd350 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassForClassOrObject.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassForClassOrObject.kt @@ -5,7 +5,10 @@ package org.jetbrains.kotlin.light.classes.symbol.classes -import com.intellij.psi.* +import com.intellij.psi.PsiManager +import com.intellij.psi.PsiMethod +import com.intellij.psi.PsiModifierList +import com.intellij.psi.PsiReferenceList import org.jetbrains.kotlin.analysis.api.KtAnalysisSession import org.jetbrains.kotlin.analysis.api.symbols.* import org.jetbrains.kotlin.analysis.api.symbols.markers.KtSymbolWithMembers @@ -25,13 +28,11 @@ import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.light.classes.symbol.NullabilityType import org.jetbrains.kotlin.light.classes.symbol.annotations.computeAnnotations import org.jetbrains.kotlin.light.classes.symbol.annotations.hasJvmFieldAnnotation -import org.jetbrains.kotlin.light.classes.symbol.computeSimpleModality import org.jetbrains.kotlin.light.classes.symbol.fields.SymbolLightField import org.jetbrains.kotlin.light.classes.symbol.fields.SymbolLightFieldForEnumEntry import org.jetbrains.kotlin.light.classes.symbol.fields.SymbolLightFieldForObject import org.jetbrains.kotlin.light.classes.symbol.methods.SymbolLightSimpleMethod import org.jetbrains.kotlin.light.classes.symbol.modifierLists.SymbolLightClassModifierList -import org.jetbrains.kotlin.light.classes.symbol.toPsiVisibilityForClass import org.jetbrains.kotlin.load.java.JvmAbi import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.StandardClassIds @@ -43,7 +44,6 @@ import org.jetbrains.kotlin.resolve.DataClassResolver import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind import org.jetbrains.kotlin.util.OperatorNameConventions.EQUALS import org.jetbrains.kotlin.util.OperatorNameConventions.TO_STRING -import org.jetbrains.kotlin.utils.addIfNotNull import org.jetbrains.kotlin.utils.addToStdlib.applyIf internal open class SymbolLightClassForClassOrObject : SymbolLightClassForNamedClassLike { @@ -86,30 +86,19 @@ internal open class SymbolLightClassForClassOrObject : SymbolLightClassForNamedC ) private val _modifierList: PsiModifierList? by lazyPub { - val lazyModifiers = lazyPub { - withClassOrObjectSymbol { classOrObjectSymbol -> - buildSet { - add(classOrObjectSymbol.toPsiVisibilityForClass(isNested = !isTopLevel)) - addIfNotNull(classOrObjectSymbol.computeSimpleModality()) - if (!isTopLevel && !classOrObjectSymbol.isInner) { - add(PsiModifier.STATIC) - } - } - } - } - SymbolLightClassModifierList( containingDeclaration = this, - lazyModifiers = lazyModifiers, - ) { modifierList -> - withClassOrObjectSymbol { classOrObjectSymbol -> - classOrObjectSymbol.computeAnnotations( - modifierList = modifierList, - nullability = NullabilityType.Unknown, - annotationUseSiteTarget = null, - ) - } - } + lazyModifiersComputer = ::computeModifiers, + annotationsComputer = { modifierList -> + withClassOrObjectSymbol { classOrObjectSymbol -> + classOrObjectSymbol.computeAnnotations( + modifierList = modifierList, + nullability = NullabilityType.Unknown, + annotationUseSiteTarget = null, + ) + } + }, + ) } override fun getModifierList(): PsiModifierList? = _modifierList diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassForEnumEntry.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassForEnumEntry.kt index 38e5ad4f528..2bc353b8dd4 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassForEnumEntry.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassForEnumEntry.kt @@ -48,7 +48,8 @@ internal class SymbolLightClassForEnumEntry( SymbolLightClassModifierList( containingDeclaration = this, staticModifiers = setOf(PsiModifier.STATIC, PsiModifier.FINAL), - ) { emptyList() } + annotationsComputer = null, + ) } override fun getModifierList(): PsiModifierList = _modifierList diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassForInterfaceDefaultImpls.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassForInterfaceDefaultImpls.kt index eeeb186c7b1..0589cab1983 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassForInterfaceDefaultImpls.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassForInterfaceDefaultImpls.kt @@ -37,7 +37,8 @@ internal class SymbolLightClassForInterfaceDefaultImpls(private val containingCl SymbolLightClassModifierList( containingDeclaration = this, staticModifiers = setOf(PsiModifier.PUBLIC, PsiModifier.STATIC, PsiModifier.FINAL), - ) { emptyList() } + annotationsComputer = null, + ) } override fun getModifierList(): PsiModifierList? = _modifierList diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassForInterfaceOrAnnotationClass.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassForInterfaceOrAnnotationClass.kt index ccc3693436c..1af402e6295 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassForInterfaceOrAnnotationClass.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassForInterfaceOrAnnotationClass.kt @@ -19,8 +19,9 @@ import org.jetbrains.kotlin.asJava.classes.lazyPub import org.jetbrains.kotlin.asJava.elements.KtLightField import org.jetbrains.kotlin.light.classes.symbol.NullabilityType import org.jetbrains.kotlin.light.classes.symbol.annotations.computeAnnotations +import org.jetbrains.kotlin.light.classes.symbol.modifierLists.LazyModifiersBox import org.jetbrains.kotlin.light.classes.symbol.modifierLists.SymbolLightClassModifierList -import org.jetbrains.kotlin.light.classes.symbol.toPsiVisibilityForClass +import org.jetbrains.kotlin.light.classes.symbol.modifierLists.with import org.jetbrains.kotlin.psi.KtClass import org.jetbrains.kotlin.psi.KtClassOrObject @@ -65,22 +66,10 @@ internal abstract class SymbolLightClassForInterfaceOrAnnotationClass : SymbolLi ) private val _modifierList: PsiModifierList? by lazyPub { - val staticModifiers = setOf(PsiModifier.ABSTRACT) - val lazyModifiers = lazyPub { - withClassOrObjectSymbol { classOrObjectSymbol -> - buildSet { - add(classOrObjectSymbol.toPsiVisibilityForClass(isNested = !isTopLevel)) - if (!isTopLevel && !classOrObjectSymbol.isInner) { - add(PsiModifier.STATIC) - } - } - } - } - SymbolLightClassModifierList( containingDeclaration = this, - staticModifiers = staticModifiers, - lazyModifiers = lazyModifiers, + initialValue = LazyModifiersBox.MODALITY_MODIFIERS_MAP.with(PsiModifier.ABSTRACT), + lazyModifiersComputer = ::computeModifiers ) { modifierList -> withClassOrObjectSymbol { classOrObjectSymbol -> classOrObjectSymbol.computeAnnotations( diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassForNamedClassLike.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassForNamedClassLike.kt index 859c7747e00..3fb9c3f486e 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassForNamedClassLike.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/SymbolLightClassForNamedClassLike.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.light.classes.symbol.classes import com.intellij.psi.PsiManager +import com.intellij.psi.PsiModifier import org.jetbrains.kotlin.analysis.api.KtAnalysisSession import org.jetbrains.kotlin.analysis.api.symbols.KtFunctionSymbol import org.jetbrains.kotlin.analysis.api.symbols.KtKotlinPropertySymbol @@ -15,11 +16,17 @@ import org.jetbrains.kotlin.analysis.api.symbols.pointers.KtSymbolPointer import org.jetbrains.kotlin.analysis.project.structure.KtModule import org.jetbrains.kotlin.asJava.elements.KtLightField import org.jetbrains.kotlin.asJava.elements.KtLightMethod +import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.light.classes.symbol.annotations.hasJvmFieldAnnotation import org.jetbrains.kotlin.light.classes.symbol.annotations.hasJvmStaticAnnotation import org.jetbrains.kotlin.light.classes.symbol.fields.SymbolLightFieldForObject import org.jetbrains.kotlin.light.classes.symbol.fields.SymbolLightFieldForProperty +import org.jetbrains.kotlin.light.classes.symbol.modifierLists.LazyModifiersBox +import org.jetbrains.kotlin.light.classes.symbol.modifierLists.with +import org.jetbrains.kotlin.light.classes.symbol.toPsiVisibilityForClass import org.jetbrains.kotlin.psi.KtClassOrObject +import org.jetbrains.kotlin.util.javaslang.ImmutableHashMap +import org.jetbrains.kotlin.util.javaslang.ImmutableMap import org.jetbrains.kotlin.utils.addToStdlib.applyIf abstract class SymbolLightClassForNamedClassLike : SymbolLightClassForClassLike { @@ -78,6 +85,9 @@ abstract class SymbolLightClassForNamedClassLike : SymbolLightClassForClassLike< private val KtPropertySymbol.isConst: Boolean get() = (this as? KtKotlinPropertySymbol)?.isConst == true private val KtPropertySymbol.isLateInit: Boolean get() = (this as? KtKotlinPropertySymbol)?.isLateInit == true + private val isInner: Boolean + get() = classOrObjectDeclaration?.hasModifier(KtTokens.INNER_KEYWORD) ?: withClassOrObjectSymbol { it.isInner } + context(KtAnalysisSession) protected fun addFieldsFromCompanionIfNeeded( result: MutableList, @@ -122,4 +132,19 @@ abstract class SymbolLightClassForNamedClassLike : SymbolLightClassForClassLike< ) } } + + internal fun computeModifiers(modifier: String): ImmutableMap? = when (modifier) { + in LazyModifiersBox.VISIBILITY_MODIFIERS -> { + val visibility = withClassOrObjectSymbol { it.toPsiVisibilityForClass(isNested = !isTopLevel) } + LazyModifiersBox.VISIBILITY_MODIFIERS_MAP.with(visibility) + } + + in LazyModifiersBox.MODALITY_MODIFIERS -> LazyModifiersBox.computeSimpleModality(ktModule, classOrObjectSymbolPointer) + PsiModifier.STATIC -> { + val isStatic = !isTopLevel && !isInner + ImmutableHashMap.of(modifier, isStatic) + } + + else -> null + } } \ No newline at end of file diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/symbolLightClassUtils.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/symbolLightClassUtils.kt index 90bef48f84d..b63316c3f54 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/symbolLightClassUtils.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/classes/symbolLightClassUtils.kt @@ -286,11 +286,15 @@ internal fun SymbolLightClassBase.createPropertyAccessors( if (declaration.hasJvmFieldAnnotation()) return fun KtPropertyAccessorSymbol.needToCreateAccessor(siteTarget: AnnotationUseSiteTarget): Boolean { - if (onlyJvmStatic && !hasJvmStaticAnnotation(siteTarget) && !declaration.hasJvmStaticAnnotation()) return false + if (onlyJvmStatic && + !hasJvmStaticAnnotation(siteTarget, strictUseSite = false) && + !declaration.hasJvmStaticAnnotation(siteTarget, strictUseSite = false) + ) return false + if (declaration.hasReifiedParameters) return false if (!hasBody && visibility.isPrivateOrPrivateToThis()) return false if (declaration.isHiddenOrSynthetic(siteTarget)) return false - return !isHiddenOrSynthetic() + return !isHiddenOrSynthetic(siteTarget, strictUseSite = false) } val originalElement = declaration.sourcePsiSafe() diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/fields/SymbolLightFieldForObject.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/fields/SymbolLightFieldForObject.kt index 0e44c74252e..06499b4eaa8 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/fields/SymbolLightFieldForObject.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/fields/SymbolLightFieldForObject.kt @@ -16,12 +16,18 @@ import org.jetbrains.kotlin.analysis.api.symbols.pointers.KtSymbolPointer import org.jetbrains.kotlin.analysis.api.symbols.sourcePsiSafe import org.jetbrains.kotlin.asJava.builder.LightMemberOrigin import org.jetbrains.kotlin.asJava.classes.lazyPub -import org.jetbrains.kotlin.light.classes.symbol.* import org.jetbrains.kotlin.light.classes.symbol.annotations.SymbolLightSimpleAnnotation import org.jetbrains.kotlin.light.classes.symbol.annotations.hasDeprecatedAnnotation import org.jetbrains.kotlin.light.classes.symbol.classes.SymbolLightClassForClassLike +import org.jetbrains.kotlin.light.classes.symbol.compareSymbolPointers +import org.jetbrains.kotlin.light.classes.symbol.isValid +import org.jetbrains.kotlin.light.classes.symbol.modifierLists.LazyModifiersBox import org.jetbrains.kotlin.light.classes.symbol.modifierLists.SymbolLightMemberModifierList +import org.jetbrains.kotlin.light.classes.symbol.modifierLists.with +import org.jetbrains.kotlin.light.classes.symbol.nonExistentType +import org.jetbrains.kotlin.light.classes.symbol.withSymbol import org.jetbrains.kotlin.psi.KtObjectDeclaration +import org.jetbrains.kotlin.util.javaslang.ImmutableMap internal class SymbolLightFieldForObject private constructor( containingClass: SymbolLightClassForClassLike<*>, @@ -50,22 +56,20 @@ internal class SymbolLightFieldForObject private constructor( override fun getName(): String = name private val _modifierList: PsiModifierList by lazyPub { - val staticModifiers = setOf(PsiModifier.STATIC, PsiModifier.FINAL) - val lazyModifiers = lazyPub { - withObjectDeclarationSymbol { objectSymbol -> - setOf(objectSymbol.toPsiVisibilityForMember()) - } - } - SymbolLightMemberModifierList( containingDeclaration = this, - staticModifiers = staticModifiers, - lazyModifiers = lazyModifiers, + initialValue = LazyModifiersBox.MODALITY_MODIFIERS_MAP.with(PsiModifier.FINAL).with(PsiModifier.STATIC), + lazyModifiersComputer = ::computeModifiers, ) { modifierList -> listOf(SymbolLightSimpleAnnotation(NotNull::class.java.name, modifierList)) } } + private fun computeModifiers(modifier: String): ImmutableMap? { + if (modifier !in LazyModifiersBox.VISIBILITY_MODIFIERS) return null + return LazyModifiersBox.computeVisibilityForMember(ktModule, objectSymbolPointer) + } + private val _isDeprecated: Boolean by lazyPub { withObjectDeclarationSymbol { objectSymbol -> objectSymbol.hasDeprecatedAnnotation() 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 29d41cdb4e9..5315d296583 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 @@ -25,11 +25,15 @@ import org.jetbrains.kotlin.light.classes.symbol.annotations.computeAnnotations import org.jetbrains.kotlin.light.classes.symbol.annotations.hasAnnotation 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 import org.jetbrains.kotlin.light.classes.symbol.modifierLists.SymbolLightMemberModifierList +import org.jetbrains.kotlin.light.classes.symbol.modifierLists.with import org.jetbrains.kotlin.name.JvmNames.TRANSIENT_ANNOTATION_CLASS_ID import org.jetbrains.kotlin.name.JvmNames.VOLATILE_ANNOTATION_CLASS_ID import org.jetbrains.kotlin.psi.KtCallableDeclaration import org.jetbrains.kotlin.psi.KtProperty +import org.jetbrains.kotlin.util.javaslang.ImmutableHashMap +import org.jetbrains.kotlin.util.javaslang.ImmutableMap internal class SymbolLightFieldForProperty private constructor( private val propertySymbolPointer: KtSymbolPointer, @@ -81,7 +85,7 @@ internal class SymbolLightFieldForProperty private constructor( private val _isDeprecated: Boolean by lazyPub { withPropertySymbol { propertySymbol -> - propertySymbol.hasDeprecatedAnnotation(AnnotationUseSiteTarget.FIELD) + propertySymbol.hasDeprecatedAnnotation(AnnotationUseSiteTarget.FIELD, strictUseSite = false) } } @@ -91,46 +95,51 @@ internal class SymbolLightFieldForProperty private constructor( override fun getName(): String = fieldName - private fun computeLazyModifiers(): Set = withPropertySymbol { propertySymbol -> - buildSet { - val suppressFinal = !propertySymbol.isVal - - propertySymbol.computeModalityForMethod( - isTopLevel = isTopLevel, - suppressFinal = suppressFinal, - result = this - ) - - if (takePropertyVisibility) { - add(propertySymbol.toPsiVisibilityForMember()) + private fun computeModifiers(modifier: String): ImmutableMap? = when (modifier) { + in LazyModifiersBox.VISIBILITY_MODIFIERS -> LazyModifiersBox.computeVisibilityForMember(ktModule, propertySymbolPointer) + in LazyModifiersBox.MODALITY_MODIFIERS -> { + val modality = withPropertySymbol { propertySymbol -> + if (propertySymbol.isVal) { + PsiModifier.FINAL + } else { + propertySymbol.computeSimpleModality()?.takeIf { + it != PsiModifier.FINAL || isTopLevel && propertySymbol.isDelegatedProperty + } + } } - if (!suppressFinal) { - add(PsiModifier.FINAL) - } - - if (propertySymbol.hasAnnotation(TRANSIENT_ANNOTATION_CLASS_ID, null)) { - add(PsiModifier.TRANSIENT) - } - - if (propertySymbol.hasAnnotation(VOLATILE_ANNOTATION_CLASS_ID, null)) { - add(PsiModifier.VOLATILE) - } + LazyModifiersBox.MODALITY_MODIFIERS_MAP.with(modality) } + + PsiModifier.STATIC -> { + val isStatic = forceStatic || isTopLevel + ImmutableHashMap.of(modifier, isStatic) + } + + PsiModifier.VOLATILE -> withPropertySymbol { propertySymbol -> + val hasAnnotation = propertySymbol.hasAnnotation(VOLATILE_ANNOTATION_CLASS_ID, null) + ImmutableHashMap.of(modifier, hasAnnotation) + } + + PsiModifier.TRANSIENT -> withPropertySymbol { propertySymbol -> + val hasAnnotation = propertySymbol.hasAnnotation(TRANSIENT_ANNOTATION_CLASS_ID, null) + ImmutableHashMap.of(modifier, hasAnnotation) + } + + else -> null } private val _modifierList: PsiModifierList by lazyPub { - val staticModifiers = setOfNotNull( - PsiModifier.PRIVATE.takeUnless { takePropertyVisibility }, - PsiModifier.STATIC.takeIf { forceStatic }, - ) - - val lazyModifiers = lazyPub { computeLazyModifiers() } + val initializerValue = if (takePropertyVisibility) { + ImmutableHashMap.empty() + } else { + LazyModifiersBox.VISIBILITY_MODIFIERS_MAP.with(PsiModifier.PRIVATE) + } SymbolLightMemberModifierList( containingDeclaration = this, - staticModifiers = staticModifiers, - lazyModifiers = lazyModifiers, + initialValue = initializerValue, + lazyModifiersComputer = ::computeModifiers, ) { modifierList -> withPropertySymbol { propertySymbol -> val nullability = if (!(propertySymbol is KtKotlinPropertySymbol && propertySymbol.isLateInit)) { diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/methods/SymbolLightAccessorMethod.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/methods/SymbolLightAccessorMethod.kt index d381d903e3d..7cf766ee823 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/methods/SymbolLightAccessorMethod.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/methods/SymbolLightAccessorMethod.kt @@ -27,7 +27,9 @@ import org.jetbrains.kotlin.light.classes.symbol.annotations.getJvmNameFromAnnot import org.jetbrains.kotlin.light.classes.symbol.annotations.hasDeprecatedAnnotation import org.jetbrains.kotlin.light.classes.symbol.annotations.hasJvmStaticAnnotation 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 +import org.jetbrains.kotlin.light.classes.symbol.modifierLists.with import org.jetbrains.kotlin.light.classes.symbol.parameters.SymbolLightParameterList import org.jetbrains.kotlin.light.classes.symbol.parameters.SymbolLightSetterParameter import org.jetbrains.kotlin.light.classes.symbol.parameters.SymbolLightTypeParameterList @@ -37,6 +39,8 @@ import org.jetbrains.kotlin.psi.KtCallableDeclaration import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtParameter import org.jetbrains.kotlin.psi.KtPropertyAccessor +import org.jetbrains.kotlin.util.javaslang.ImmutableHashMap +import org.jetbrains.kotlin.util.javaslang.ImmutableMap import org.jetbrains.kotlin.utils.addToStdlib.ifTrue internal class SymbolLightAccessorMethod private constructor( @@ -153,37 +157,41 @@ internal class SymbolLightAccessorMethod private constructor( annotationsFromProperty + annotationsFromAccessor } - private fun computeModifiers(): Set = analyzeForLightClasses(ktModule) { - val propertySymbol = propertySymbol() - val propertyAccessorSymbol = propertyAccessorSymbol() - val modifiers = mutableSetOf() + private fun computeModifiers(modifier: String): ImmutableMap? { + return when (modifier) { + in LazyModifiersBox.VISIBILITY_MODIFIERS -> LazyModifiersBox.computeVisibilityForMember(ktModule, propertyAccessorSymbolPointer) - propertySymbol.computeModalityForMethod( - isTopLevel = isTopLevel, - suppressFinal = containingClass.isInterface, - result = modifiers, - ) + in LazyModifiersBox.MODALITY_MODIFIERS -> { + if (containingClass.isInterface) { + return LazyModifiersBox.MODALITY_MODIFIERS_MAP.with(PsiModifier.ABSTRACT) + } - modifiers.add(propertyAccessorSymbol.toPsiVisibilityForMember()) + LazyModifiersBox.computeSimpleModality(ktModule, containingPropertySymbolPointer) + } - if (!suppressStatic && - (propertySymbol.hasJvmStaticAnnotation() || propertyAccessorSymbol.hasJvmStaticAnnotation(accessorSite)) - ) { - modifiers.add(PsiModifier.STATIC) + PsiModifier.STATIC -> { + val isStatic = if (suppressStatic) { + false + } else { + isTopLevel || hasJvmStaticAnnotation() + } + + ImmutableHashMap.of(modifier, isStatic) + } + + else -> null } + } - modifiers + private fun hasJvmStaticAnnotation(): Boolean = analyzeForLightClasses(ktModule) { + propertySymbol().hasJvmStaticAnnotation(accessorSite, strictUseSite = false) || + propertyAccessorSymbol().hasJvmStaticAnnotation(accessorSite, strictUseSite = false) } private val _modifierList: PsiModifierList by lazyPub { - val staticModifiers = setOfNotNull( - PsiModifier.ABSTRACT.takeIf { containingClass.isInterface }, - ) - SymbolLightMemberModifierList( containingDeclaration = this, - staticModifiers = staticModifiers, - lazyModifiers = lazyPub { computeModifiers() }, + lazyModifiersComputer = ::computeModifiers, annotationsComputer = ::computeAnnotations, ) } @@ -194,7 +202,8 @@ internal class SymbolLightAccessorMethod private constructor( private val _isDeprecated: Boolean by lazyPub { analyzeForLightClasses(ktModule) { - propertySymbol().hasDeprecatedAnnotation(accessorSite) + propertySymbol().hasDeprecatedAnnotation(accessorSite, strictUseSite = false) || + propertyAccessorSymbol().hasDeprecatedAnnotation(accessorSite, strictUseSite = false) } } diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/methods/SymbolLightConstructor.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/methods/SymbolLightConstructor.kt index c61e3435e4e..dab786724e5 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/methods/SymbolLightConstructor.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/methods/SymbolLightConstructor.kt @@ -13,8 +13,11 @@ import org.jetbrains.kotlin.light.classes.symbol.NullabilityType import org.jetbrains.kotlin.light.classes.symbol.annotations.computeAnnotations 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 import org.jetbrains.kotlin.light.classes.symbol.modifierLists.SymbolLightMemberModifierList -import org.jetbrains.kotlin.light.classes.symbol.toPsiVisibilityForMember +import org.jetbrains.kotlin.light.classes.symbol.modifierLists.with +import org.jetbrains.kotlin.util.javaslang.ImmutableHashMap +import org.jetbrains.kotlin.util.javaslang.ImmutableMap import java.util.* internal class SymbolLightConstructor( @@ -42,24 +45,16 @@ internal class SymbolLightConstructor( override fun getTypeParameters(): Array = PsiTypeParameter.EMPTY_ARRAY private val _modifierList: PsiModifierList by lazyPub { - val (staticModifiers, lazyModifiers) = if (containingClass is SymbolLightClassForEnumEntry) { - setOf(PsiModifier.PACKAGE_LOCAL) to null + val initialValue = if (containingClass is SymbolLightClassForEnumEntry) { + LazyModifiersBox.VISIBILITY_MODIFIERS_MAP.with(PsiModifier.PACKAGE_LOCAL) } else { - emptySet() to lazyPub { - // FIR treats an enum entry as an anonymous object w/ its own ctor (not default one). - // On the other hand, FE 1.0 doesn't add anything; then ULC adds default ctor w/ package local visibility. - // Technically, an enum entry should not be instantiated anywhere else, and thus FIR's modeling makes sense. - // But, to be backward compatible, we manually force the visibility of enum entry ctor to be package private. - withFunctionSymbol { constructorSymbol -> - setOf(constructorSymbol.toPsiVisibilityForMember()) - } - } + ImmutableHashMap.empty() } SymbolLightMemberModifierList( containingDeclaration = this, - staticModifiers = staticModifiers, - lazyModifiers = lazyModifiers, + initialValue = initialValue, + lazyModifiersComputer = ::computeModifiers, ) { modifierList -> withFunctionSymbol { constructorSymbol -> constructorSymbol.computeAnnotations( @@ -71,6 +66,11 @@ internal class SymbolLightConstructor( } } + private fun computeModifiers(modifier: String): ImmutableMap? { + if (modifier !in LazyModifiersBox.VISIBILITY_MODIFIERS) return null + return LazyModifiersBox.computeVisibilityForMember(ktModule, functionSymbolPointer) + } + override fun getModifierList(): PsiModifierList = _modifierList override fun getReturnType(): PsiType? = null diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/methods/SymbolLightNoArgConstructor.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/methods/SymbolLightNoArgConstructor.kt index 9253415cd61..afbc3b6570e 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/methods/SymbolLightNoArgConstructor.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/methods/SymbolLightNoArgConstructor.kt @@ -36,7 +36,7 @@ internal class SymbolLightNoArgConstructor( override fun isDeprecated(): Boolean = false private val _modifierList: PsiModifierList by lazyPub { - SymbolLightMemberModifierList(containingDeclaration = this, staticModifiers = setOf(visibility)) { emptyList() } + SymbolLightMemberModifierList(containingDeclaration = this, staticModifiers = setOf(visibility), annotationsComputer = null) } override fun getModifierList(): PsiModifierList = _modifierList 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 eb737108541..d61b4411d7a 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 @@ -12,16 +12,21 @@ import org.jetbrains.kotlin.analysis.api.types.KtType import org.jetbrains.kotlin.analysis.api.types.KtTypeMappingMode 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.computeAnnotations import org.jetbrains.kotlin.light.classes.symbol.annotations.hasAnnotation 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.classes.SymbolLightClassBase +import org.jetbrains.kotlin.light.classes.symbol.modifierLists.LazyModifiersBox import org.jetbrains.kotlin.light.classes.symbol.modifierLists.SymbolLightMemberModifierList +import org.jetbrains.kotlin.light.classes.symbol.modifierLists.with import org.jetbrains.kotlin.light.classes.symbol.parameters.SymbolLightTypeParameterList import org.jetbrains.kotlin.name.JvmNames.STRICTFP_ANNOTATION_CLASS_ID import org.jetbrains.kotlin.name.JvmNames.SYNCHRONIZED_ANNOTATION_CLASS_ID +import org.jetbrains.kotlin.util.javaslang.ImmutableHashMap +import org.jetbrains.kotlin.util.javaslang.ImmutableMap import org.jetbrains.kotlin.utils.addToStdlib.ifTrue import java.util.* @@ -85,48 +90,67 @@ internal class SymbolLightSimpleMethod( ) } - context(KtAnalysisSession) - private fun computeModifiers(functionSymbol: KtFunctionSymbol): Set { - if (functionSymbol.hasInlineOnlyAnnotation()) return setOf(PsiModifier.FINAL, PsiModifier.PRIVATE) - - val modifiers = mutableSetOf() - functionSymbol.computeModalityForMethod( - isTopLevel = isTopLevel, - suppressFinal = containingClass.isInterface, - result = modifiers - ) - - if (functionSymbol.isExternal) { - modifiers.add(PsiModifier.NATIVE) + private fun computeModifiers(modifier: String): ImmutableMap? = when (modifier) { + in LazyModifiersBox.MODALITY_MODIFIERS -> { + ifInlineOnly { return modifiersForInlineOnlyCase() } + val modality = if (isTopLevel) PsiModifier.FINAL else withFunctionSymbol { it.computeSimpleModality() } + LazyModifiersBox.MODALITY_MODIFIERS_MAP.with(modality) } - modifiers.add(functionSymbol.toPsiVisibilityForMember()) - - if (!suppressStatic && functionSymbol.hasJvmStaticAnnotation()) { - modifiers.add(PsiModifier.STATIC) + in LazyModifiersBox.VISIBILITY_MODIFIERS -> { + ifInlineOnly { return modifiersForInlineOnlyCase() } + LazyModifiersBox.computeVisibilityForMember(ktModule, functionSymbolPointer) } - if (functionSymbol.hasAnnotation(STRICTFP_ANNOTATION_CLASS_ID, null)) { - modifiers.add(PsiModifier.STRICTFP) + PsiModifier.STATIC -> { + ifInlineOnly { return null } + val isStatic = if (suppressStatic) { + false + } else { + isTopLevel || withFunctionSymbol { it.hasJvmStaticAnnotation() } + } + + ImmutableHashMap.of(modifier, isStatic) } - if (functionSymbol.hasAnnotation(SYNCHRONIZED_ANNOTATION_CLASS_ID, null)) { - modifiers.add(PsiModifier.SYNCHRONIZED) + PsiModifier.NATIVE -> { + ifInlineOnly { return null } + val isExternal = functionDeclaration?.hasModifier(KtTokens.EXTERNAL_KEYWORD) ?: withFunctionSymbol { it.isExternal } + ImmutableHashMap.of(modifier, isExternal) } - return modifiers + PsiModifier.STRICTFP -> { + ifInlineOnly { return null } + val hasAnnotation = withFunctionSymbol { it.hasAnnotation(STRICTFP_ANNOTATION_CLASS_ID, null) } + ImmutableHashMap.of(modifier, hasAnnotation) + } + + PsiModifier.SYNCHRONIZED -> { + ifInlineOnly { return null } + val hasAnnotation = withFunctionSymbol { it.hasAnnotation(SYNCHRONIZED_ANNOTATION_CLASS_ID, null) } + ImmutableHashMap.of(modifier, hasAnnotation) + } + + else -> null } - private val _modifierList: PsiModifierList by lazyPub { - val lazyModifiers = lazyPub { - withFunctionSymbol { functionSymbol -> - computeModifiers(functionSymbol) - } + private inline fun ifInlineOnly(action: () -> Unit) { + if (hasInlineOnlyAnnotation) { + action() } + } + private fun modifiersForInlineOnlyCase(): ImmutableMap = + LazyModifiersBox.MODALITY_MODIFIERS_MAP.merge(LazyModifiersBox.VISIBILITY_MODIFIERS_MAP) + .with(PsiModifier.FINAL) + .with(PsiModifier.PRIVATE) + + private val hasInlineOnlyAnnotation: Boolean by lazyPub { withFunctionSymbol { it.hasInlineOnlyAnnotation() } } + + private val _modifierList: PsiModifierList by lazyPub { SymbolLightMemberModifierList( containingDeclaration = this, - lazyModifiers = lazyModifiers, + lazyModifiersComputer = ::computeModifiers, annotationsComputer = ::computeAnnotations, ) } diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/modifierLists/SymbolLightClassModifierList.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/modifierLists/SymbolLightClassModifierList.kt index 684f1943604..5e1fcd777ab 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/modifierLists/SymbolLightClassModifierList.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/modifierLists/SymbolLightClassModifierList.kt @@ -10,10 +10,19 @@ import com.intellij.psi.PsiModifierList import com.intellij.psi.PsiModifierListOwner import org.jetbrains.kotlin.asJava.elements.KtLightElement import org.jetbrains.kotlin.psi.KtModifierListOwner +import org.jetbrains.kotlin.util.javaslang.ImmutableHashMap -internal class SymbolLightClassModifierList>( - containingDeclaration: T, - staticModifiers: Set = emptySet(), - lazyModifiers: Lazy>? = null, - annotationsComputer: (PsiModifierList) -> List, -) : SymbolLightModifierList(containingDeclaration, staticModifiers, lazyModifiers, annotationsComputer) +internal class SymbolLightClassModifierList> : SymbolLightModifierList { + constructor( + containingDeclaration: T, + initialValue: ImmutableHashMap = ImmutableHashMap.empty(), + lazyModifiersComputer: LazyModifiersComputer, + annotationsComputer: ((PsiModifierList) -> List)?, + ) : super(containingDeclaration, initialValue, lazyModifiersComputer, annotationsComputer) + + constructor( + containingDeclaration: T, + staticModifiers: Set, + annotationsComputer: ((PsiModifierList) -> List)?, + ) : super(containingDeclaration, staticModifiers, annotationsComputer) +} diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/modifierLists/SymbolLightMemberModifierList.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/modifierLists/SymbolLightMemberModifierList.kt index ff705243de6..9f8f09d84d8 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/modifierLists/SymbolLightMemberModifierList.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/modifierLists/SymbolLightMemberModifierList.kt @@ -14,13 +14,22 @@ import org.jetbrains.kotlin.light.classes.symbol.methods.SymbolLightMethodBase import org.jetbrains.kotlin.psi.KtModifierList import org.jetbrains.kotlin.psi.KtPropertyAccessor import org.jetbrains.kotlin.psi.psiUtil.hasBody +import org.jetbrains.kotlin.util.javaslang.ImmutableHashMap + +internal class SymbolLightMemberModifierList> : SymbolLightModifierList { + constructor( + containingDeclaration: T, + initialValue: ImmutableHashMap = ImmutableHashMap.empty(), + lazyModifiersComputer: LazyModifiersComputer, + annotationsComputer: ((PsiModifierList) -> List)?, + ) : super(containingDeclaration, initialValue, lazyModifiersComputer, annotationsComputer) + + constructor( + containingDeclaration: T, + staticModifiers: Set, + annotationsComputer: ((PsiModifierList) -> List)?, + ) : super(containingDeclaration, staticModifiers, annotationsComputer) -internal class SymbolLightMemberModifierList>( - containingDeclaration: T, - staticModifiers: Set = emptySet(), - lazyModifiers: Lazy>? = null, - annotationsComputer: (PsiModifierList) -> List, -) : SymbolLightModifierList(containingDeclaration, staticModifiers, lazyModifiers, annotationsComputer) { override fun hasModifierProperty(name: String): Boolean = when { name == PsiModifier.ABSTRACT && isImplementationInInterface() -> false // Pretend this method behaves like a `default` method diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/modifierLists/SymbolLightModifierList.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/modifierLists/SymbolLightModifierList.kt index 14ba4ee636c..efd23fae195 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/modifierLists/SymbolLightModifierList.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/modifierLists/SymbolLightModifierList.kt @@ -5,26 +5,58 @@ package org.jetbrains.kotlin.light.classes.symbol.modifierLists -import com.intellij.psi.PsiAnnotation -import com.intellij.psi.PsiElement -import com.intellij.psi.PsiModifierList -import com.intellij.psi.PsiModifierListOwner +import com.intellij.psi.* import com.intellij.util.IncorrectOperationException +import org.jetbrains.kotlin.analysis.api.symbols.markers.KtSymbolWithModality +import org.jetbrains.kotlin.analysis.api.symbols.markers.KtSymbolWithVisibility +import org.jetbrains.kotlin.analysis.api.symbols.pointers.KtSymbolPointer +import org.jetbrains.kotlin.analysis.project.structure.KtModule import org.jetbrains.kotlin.asJava.classes.cannotModify import org.jetbrains.kotlin.asJava.classes.lazyPub import org.jetbrains.kotlin.asJava.elements.KtLightAbstractAnnotation import org.jetbrains.kotlin.asJava.elements.KtLightElement import org.jetbrains.kotlin.asJava.elements.KtLightElementBase -import org.jetbrains.kotlin.light.classes.symbol.invalidAccess +import org.jetbrains.kotlin.light.classes.symbol.* import org.jetbrains.kotlin.psi.KtModifierList import org.jetbrains.kotlin.psi.KtModifierListOwner +import org.jetbrains.kotlin.util.javaslang.ImmutableHashMap +import org.jetbrains.kotlin.util.javaslang.ImmutableMap +import org.jetbrains.kotlin.util.javaslang.getOrNull +import org.jetbrains.kotlin.utils.keysToMap +import java.util.concurrent.atomic.AtomicReference + +internal open class SymbolLightModifierList> : + KtLightElementBase, PsiModifierList, KtLightElement { + protected val owner: T + private val staticModifiers: Set? + private val lazyModifiersBox: LazyModifiersBox? + private val lazyAnnotations: Lazy>? + + constructor( + owner: T, + initialValue: ImmutableHashMap, + lazyModifiersComputer: LazyModifiersComputer, + annotationsComputer: ((PsiModifierList) -> List)?, + ) : super(owner) { + this.owner = owner + this.lazyAnnotations = annotationsComputer?.let { lazyPub { annotationsComputer(this) } } + + this.lazyModifiersBox = LazyModifiersBox(initialValue, lazyModifiersComputer) + this.staticModifiers = null + } + + constructor( + owner: T, + staticModifiers: Set, + annotationsComputer: ((PsiModifierList) -> List)?, + ) : super(owner) { + this.owner = owner + this.lazyAnnotations = annotationsComputer?.let { lazyPub { annotationsComputer(this) } } + + this.lazyModifiersBox = null + this.staticModifiers = staticModifiers + } -internal abstract class SymbolLightModifierList>( - protected val owner: T, - private val staticModifiers: Set, - private val lazyModifiers: Lazy>?, - annotationsComputer: (PsiModifierList) -> List, -) : KtLightElementBase(owner), PsiModifierList, KtLightElement { override val kotlinOrigin: KtModifierList? get() = owner.kotlinOrigin?.modifierList override fun getParent() = owner override fun setModifierProperty(name: String, value: Boolean) = cannotModify() @@ -37,17 +69,69 @@ internal abstract class SymbolLightModifierList get() = invalidAccess() - private val lazyAnnotations: Lazy> = lazyPub { - annotationsComputer(this) - } - - override fun getAnnotations(): Array = lazyAnnotations.value.toTypedArray() + override fun getAnnotations(): Array = lazyAnnotations?.value?.toTypedArray().orEmpty() override fun findAnnotation(qualifiedName: String): PsiAnnotation? = - lazyAnnotations.value.firstOrNull { it.qualifiedName == qualifiedName } + lazyAnnotations?.value?.firstOrNull { it.qualifiedName == qualifiedName } override fun equals(other: Any?): Boolean = this === other override fun hashCode(): Int = kotlinOrigin.hashCode() override fun hasExplicitModifier(name: String) = hasModifierProperty(name) - override fun hasModifierProperty(name: String): Boolean = name in staticModifiers || lazyModifiers?.value?.contains(name) == true + override fun hasModifierProperty(name: String): Boolean = + staticModifiers?.contains(name) == true || lazyModifiersBox?.hasModifier(name) == true +} + +internal typealias LazyModifiersComputer = (modifier: String) -> ImmutableMap? + +@Suppress("NOTHING_TO_INLINE") +internal inline fun ImmutableHashMap.with(modifier: String?): ImmutableHashMap { + return modifier?.let { put(modifier, true) } ?: this +} + +internal class LazyModifiersBox( + initialValue: ImmutableHashMap, + private val computer: LazyModifiersComputer, +) { + private val modifiersMapReference: AtomicReference> = AtomicReference(initialValue) + + fun hasModifier(modifier: String): Boolean { + modifiersMapReference.get().getOrNull(modifier)?.let { return it } + val newValues = computer(modifier) ?: ImmutableHashMap.of(modifier, false) + do { + val currentMap = modifiersMapReference.get() + val newMap = currentMap.merge(newValues) + } while (!modifiersMapReference.compareAndSet(currentMap, newMap)) + + return newValues.getOrNull(modifier) ?: error("Inconsistent state: $modifier") + } + + companion object { + internal val VISIBILITY_MODIFIERS = setOf(PsiModifier.PUBLIC, PsiModifier.PACKAGE_LOCAL, PsiModifier.PROTECTED, PsiModifier.PRIVATE) + internal val VISIBILITY_MODIFIERS_MAP = ImmutableHashMap.ofAll(VISIBILITY_MODIFIERS.keysToMap { false }) + + internal val MODALITY_MODIFIERS = setOf(PsiModifier.FINAL, PsiModifier.ABSTRACT) + internal val MODALITY_MODIFIERS_MAP = ImmutableHashMap.ofAll(MODALITY_MODIFIERS.keysToMap { false }) + + internal fun computeVisibilityForMember( + ktModule: KtModule, + declarationPointer: KtSymbolPointer, + ): ImmutableMap { + val visibility = analyzeForLightClasses(ktModule) { + declarationPointer.restoreSymbolOrThrowIfDisposed().toPsiVisibilityForMember() + } + + return VISIBILITY_MODIFIERS_MAP.with(visibility) + } + + internal fun computeSimpleModality( + ktModule: KtModule, + declarationPointer: KtSymbolPointer, + ): ImmutableMap { + val visibility = analyzeForLightClasses(ktModule) { + declarationPointer.restoreSymbolOrThrowIfDisposed().computeSimpleModality() + } + + return MODALITY_MODIFIERS_MAP.with(visibility) + } + } } diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/parameters/SymbolLightParameter.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/parameters/SymbolLightParameter.kt index 7c0f8f7d803..355dc8fe549 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/parameters/SymbolLightParameter.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/parameters/SymbolLightParameter.kt @@ -27,7 +27,10 @@ internal class SymbolLightParameter( override fun getModifierList(): PsiModifierList = _modifierList private val _modifierList: PsiModifierList by lazyPub { - SymbolLightClassModifierList(containingDeclaration = this) { modifierList -> + SymbolLightClassModifierList( + containingDeclaration = this, + staticModifiers = emptySet(), + ) { modifierList -> val annotationSite = isConstructorParameterSymbol.ifTrue { AnnotationUseSiteTarget.CONSTRUCTOR_PARAMETER } 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 c1272192e07..86284d59324 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 @@ -68,7 +68,10 @@ internal class SymbolLightParameterForReceiver private constructor( override fun getModifierList(): PsiModifierList = _modifierList private val _modifierList: PsiModifierList by lazyPub { - SymbolLightClassModifierList(containingDeclaration = this) { modifierList -> + SymbolLightClassModifierList( + containingDeclaration = this, + staticModifiers = emptySet(), + ) { modifierList -> withReceiverSymbol { receiver -> buildList { receiver.type.nullabilityType.computeNullabilityAnnotation(modifierList)?.let(::add) diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/parameters/SymbolLightSetterParameter.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/parameters/SymbolLightSetterParameter.kt index 996e46c34fa..7da416abb47 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/parameters/SymbolLightSetterParameter.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/parameters/SymbolLightSetterParameter.kt @@ -41,7 +41,10 @@ internal class SymbolLightSetterParameter( override fun getModifierList(): PsiModifierList = _modifierList private val _modifierList: PsiModifierList by lazyPub { - SymbolLightClassModifierList(containingDeclaration = this) { modifierList -> + SymbolLightClassModifierList( + containingDeclaration = this, + staticModifiers = emptySet(), + ) { modifierList -> analyzeForLightClasses(ktModule) { val annotationsFromSetter = parameterSymbolPointer.restoreSymbolOrThrowIfDisposed().computeAnnotations( modifierList = modifierList, diff --git a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/parameters/SymbolLightSuspendContinuationParameter.kt b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/parameters/SymbolLightSuspendContinuationParameter.kt index 962d24849c3..23389864635 100644 --- a/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/parameters/SymbolLightSuspendContinuationParameter.kt +++ b/analysis/symbol-light-classes/src/org/jetbrains/kotlin/light/classes/symbol/parameters/SymbolLightSuspendContinuationParameter.kt @@ -50,7 +50,10 @@ internal class SymbolLightSuspendContinuationParameter( override fun getModifierList(): PsiModifierList = _modifierList private val _modifierList: PsiModifierList by lazyPub { - SymbolLightClassModifierList(containingDeclaration = this) { modifierList -> + SymbolLightClassModifierList( + containingDeclaration = this, + staticModifiers = emptySet(), + ) { modifierList -> if (withFunctionSymbol { it.visibility.isPrivateOrPrivateToThis() }) emptyList() else 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 240cb305977..aa111eaf808 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 @@ -12,9 +12,6 @@ import org.jetbrains.kotlin.analysis.api.KtAnalysisSession import org.jetbrains.kotlin.analysis.api.annotations.* import org.jetbrains.kotlin.analysis.api.base.KtConstantValue import org.jetbrains.kotlin.analysis.api.components.DefaultTypeClassIds -import org.jetbrains.kotlin.analysis.api.symbols.KtClassLikeSymbol -import org.jetbrains.kotlin.analysis.api.symbols.KtFunctionSymbol -import org.jetbrains.kotlin.analysis.api.symbols.KtPropertySymbol import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol import org.jetbrains.kotlin.analysis.api.symbols.markers.KtSymbolWithModality import org.jetbrains.kotlin.analysis.api.symbols.markers.KtSymbolWithTypeParameters @@ -76,37 +73,11 @@ internal fun KtSymbolWithModality.computeSimpleModality(): String? = when (modal Modality.OPEN -> null } -internal fun KtSymbolWithModality.computeModalityForMethod( - isTopLevel: Boolean, - suppressFinal: Boolean, - result: MutableSet -) { - require(this !is KtClassLikeSymbol) - - computeSimpleModality()?.run { - if (this != PsiModifier.FINAL || !suppressFinal) { - result.add(this) - } - } - - if (isTopLevel) { - result.add(PsiModifier.STATIC) - val needFinalModifier = when (this) { - is KtPropertySymbol -> isDelegatedProperty || isVal - else -> true - } - - if (needFinalModifier) { - result.add(PsiModifier.FINAL) - } - } -} - internal fun KtSymbolWithVisibility.toPsiVisibilityForMember(): String = visibility.toPsiVisibilityForMember() internal fun KtSymbolWithVisibility.toPsiVisibilityForClass(isNested: Boolean): String = visibility.toPsiVisibilityForClass(isNested) -internal fun Visibility.toPsiVisibilityForMember(): String = when (this) { +private fun Visibility.toPsiVisibilityForMember(): String = when (this) { Visibilities.Private, Visibilities.PrivateToThis -> PsiModifier.PRIVATE Visibilities.Protected -> PsiModifier.PROTECTED else -> PsiModifier.PUBLIC diff --git a/analysis/symbol-light-classes/tests/org/jetbrains/kotlin/light/classes/symbol/decompiled/SymbolLightClassesLoadingForLibraryTestGenerated.java b/analysis/symbol-light-classes/tests/org/jetbrains/kotlin/light/classes/symbol/decompiled/SymbolLightClassesLoadingForLibraryTestGenerated.java index eef1860f01c..3e88a9d852d 100644 --- a/analysis/symbol-light-classes/tests/org/jetbrains/kotlin/light/classes/symbol/decompiled/SymbolLightClassesLoadingForLibraryTestGenerated.java +++ b/analysis/symbol-light-classes/tests/org/jetbrains/kotlin/light/classes/symbol/decompiled/SymbolLightClassesLoadingForLibraryTestGenerated.java @@ -168,6 +168,12 @@ public class SymbolLightClassesLoadingForLibraryTestGenerated extends AbstractSy runTest("compiler/testData/asJava/ultraLightClasses/jvmRecord.kt"); } + @Test + @TestMetadata("jvmStaticOnPropertySetter.kt") + public void testJvmStaticOnPropertySetter() throws Exception { + runTest("compiler/testData/asJava/ultraLightClasses/jvmStaticOnPropertySetter.kt"); + } + @Test @TestMetadata("jvmSynthetic.kt") public void testJvmSynthetic() throws Exception { diff --git a/analysis/symbol-light-classes/tests/org/jetbrains/kotlin/light/classes/symbol/source/SymbolLightClassesLoadingForSourceTestGenerated.java b/analysis/symbol-light-classes/tests/org/jetbrains/kotlin/light/classes/symbol/source/SymbolLightClassesLoadingForSourceTestGenerated.java index 33c06650314..245c8bce066 100644 --- a/analysis/symbol-light-classes/tests/org/jetbrains/kotlin/light/classes/symbol/source/SymbolLightClassesLoadingForSourceTestGenerated.java +++ b/analysis/symbol-light-classes/tests/org/jetbrains/kotlin/light/classes/symbol/source/SymbolLightClassesLoadingForSourceTestGenerated.java @@ -168,6 +168,12 @@ public class SymbolLightClassesLoadingForSourceTestGenerated extends AbstractSym runTest("compiler/testData/asJava/ultraLightClasses/jvmRecord.kt"); } + @Test + @TestMetadata("jvmStaticOnPropertySetter.kt") + public void testJvmStaticOnPropertySetter() throws Exception { + runTest("compiler/testData/asJava/ultraLightClasses/jvmStaticOnPropertySetter.kt"); + } + @Test @TestMetadata("jvmSynthetic.kt") public void testJvmSynthetic() throws Exception { diff --git a/compiler/testData/asJava/ultraLightClasses/jvmStaticOnPropertySetter.java b/compiler/testData/asJava/ultraLightClasses/jvmStaticOnPropertySetter.java new file mode 100644 index 00000000000..8590f322330 --- /dev/null +++ b/compiler/testData/asJava/ultraLightClasses/jvmStaticOnPropertySetter.java @@ -0,0 +1,38 @@ +public final class MyClass /* MyClass*/ { + @org.jetbrains.annotations.NotNull() + private static java.lang.String prop2 = "" /* initializer type: java.lang.String */; + + @org.jetbrains.annotations.NotNull() + public static final MyClass.Companion Companion; + + private static int prop = 4 /* initializer type: int */; + + @kotlin.jvm.JvmStatic() + @org.jetbrains.annotations.NotNull() + public static final java.lang.String getProp2();// getProp2() + + @kotlin.jvm.JvmStatic() + public static final void setProp(int);// setProp(int) + + public MyClass();// .ctor() + + + class Companion ... + + } + +public static final class Companion /* MyClass.Companion*/ { + @kotlin.jvm.JvmStatic() + @org.jetbrains.annotations.NotNull() + public final java.lang.String getProp2();// getProp2() + + @kotlin.jvm.JvmStatic() + public final void setProp(int);// setProp(int) + + private Companion();// .ctor() + + public final int getProp();// getProp() + + public final void setProp2(@org.jetbrains.annotations.NotNull() java.lang.String);// setProp2(java.lang.String) + +} diff --git a/compiler/testData/asJava/ultraLightClasses/jvmStaticOnPropertySetter.kt b/compiler/testData/asJava/ultraLightClasses/jvmStaticOnPropertySetter.kt new file mode 100644 index 00000000000..8659ba2d091 --- /dev/null +++ b/compiler/testData/asJava/ultraLightClasses/jvmStaticOnPropertySetter.kt @@ -0,0 +1,17 @@ +class MyClass { + companion object { + var prop: Int = 4 + @JvmStatic + set(value) { + field = value + } + + get() = field + + @get:JvmStatic + var prop2: String = "" + set(value) { + field = value + } + } +} diff --git a/compiler/testData/asJava/ultraLightClasses/jvmStaticOnPropertySetter.lib.java b/compiler/testData/asJava/ultraLightClasses/jvmStaticOnPropertySetter.lib.java new file mode 100644 index 00000000000..7f7bf4cb09f --- /dev/null +++ b/compiler/testData/asJava/ultraLightClasses/jvmStaticOnPropertySetter.lib.java @@ -0,0 +1,38 @@ +public final class MyClass /* MyClass*/ { + @org.jetbrains.annotations.NotNull() + private static java.lang.String prop2; + + @org.jetbrains.annotations.NotNull() + public static final MyClass.Companion Companion; + + private static int prop; + + @kotlin.jvm.JvmStatic() + @org.jetbrains.annotations.NotNull() + public static final java.lang.String getProp2();// getProp2() + + @kotlin.jvm.JvmStatic() + public static final void setProp(int);// setProp(int) + + public MyClass();// .ctor() + + + class Companion ... + + } + +public static final class Companion /* MyClass.Companion*/ { + @kotlin.jvm.JvmStatic() + @org.jetbrains.annotations.NotNull() + public final java.lang.String getProp2();// getProp2() + + @kotlin.jvm.JvmStatic() + public final void setProp(int);// setProp(int) + + private Companion();// .ctor() + + public final int getProp();// getProp() + + public final void setProp2(@org.jetbrains.annotations.NotNull() java.lang.String);// setProp2(java.lang.String) + +} diff --git a/compiler/testData/asJava/ultraLightClasses/jvmSynthetic.fir.java b/compiler/testData/asJava/ultraLightClasses/jvmSynthetic.fir.java index 23d128a323b..e35975d7ff4 100644 --- a/compiler/testData/asJava/ultraLightClasses/jvmSynthetic.fir.java +++ b/compiler/testData/asJava/ultraLightClasses/jvmSynthetic.fir.java @@ -1,10 +1,14 @@ public final class A /* A*/ { private int z = 1 /* initializer type: int */; + public A f; + public A();// .ctor() public final int getX();// getX() + public final void setF(@org.jetbrains.annotations.NotNull() A);// setF(A) + public final void setX(int);// setX(int) } diff --git a/compiler/testData/asJava/ultraLightClasses/jvmSynthetic.java b/compiler/testData/asJava/ultraLightClasses/jvmSynthetic.java index 2e100bf494e..ccdfb7162d7 100644 --- a/compiler/testData/asJava/ultraLightClasses/jvmSynthetic.java +++ b/compiler/testData/asJava/ultraLightClasses/jvmSynthetic.java @@ -1,10 +1,14 @@ public final class A /* A*/ { private int z; + public A f; + public A();// .ctor() public final int getX();// getX() + public final void setF(@org.jetbrains.annotations.NotNull() A);// setF(A) + public final void setX(int);// setX(int) } diff --git a/compiler/testData/asJava/ultraLightClasses/jvmSynthetic.kt b/compiler/testData/asJava/ultraLightClasses/jvmSynthetic.kt index ff2ec36afb1..0e74072836a 100644 --- a/compiler/testData/asJava/ultraLightClasses/jvmSynthetic.kt +++ b/compiler/testData/asJava/ultraLightClasses/jvmSynthetic.kt @@ -12,5 +12,8 @@ class A { var z = 1 @JvmSynthetic get @JvmSynthetic set + + @get:JvmSynthetic + lateinit var f: A } diff --git a/compiler/testData/asJava/ultraLightClasses/jvmSyntheticForAccessors.fir.java b/compiler/testData/asJava/ultraLightClasses/jvmSyntheticForAccessors.fir.java index 97887b6819f..9beee35fa63 100644 --- a/compiler/testData/asJava/ultraLightClasses/jvmSyntheticForAccessors.fir.java +++ b/compiler/testData/asJava/ultraLightClasses/jvmSyntheticForAccessors.fir.java @@ -3,12 +3,6 @@ public final class X /* X*/ { private int w = 1 /* initializer type: int */; - @kotlin.jvm.JvmSynthetic() - public final int getV();// getV() - - @kotlin.jvm.JvmSynthetic() - public final void setW(int);// setW(int) - public X();// .ctor() public final int getW();// getW() diff --git a/compiler/testData/asJava/ultraLightClasses/objects.fir.java b/compiler/testData/asJava/ultraLightClasses/objects.fir.java index c956a92ef5e..e043f149c8b 100644 --- a/compiler/testData/asJava/ultraLightClasses/objects.fir.java +++ b/compiler/testData/asJava/ultraLightClasses/objects.fir.java @@ -15,9 +15,19 @@ public final class C /* C*/ { @org.jetbrains.annotations.NotNull() public static final C.Factory Factory; + @kotlin.jvm.JvmStatic() + @org.jetbrains.annotations.NotNull() + public static final java.lang.String getC(@org.jetbrains.annotations.NotNull() I);// getC(I) + @kotlin.jvm.JvmStatic() public static final void foo();// foo() + @kotlin.jvm.JvmStatic() + public static final void setC(@org.jetbrains.annotations.NotNull() I, @org.jetbrains.annotations.NotNull() java.lang.String);// setC(I, java.lang.String) + + @kotlin.jvm.JvmStatic() + public static final void setC1(@org.jetbrains.annotations.NotNull() java.lang.String);// setC1(java.lang.String) + @org.jetbrains.annotations.NotNull() public static final java.lang.String getX();// getX()