KT-54804 [SLC] Generate synthetic functions for annotations on properties in light classes

This commit is contained in:
Pavel Mikhailovskii
2023-05-12 09:39:37 +00:00
committed by Space Team
parent 111243f215
commit 7ac5233a32
18 changed files with 399 additions and 9 deletions
@@ -7,8 +7,9 @@ package org.jetbrains.kotlin.asJava.classes
const val METHOD_INDEX_FOR_GETTER = 1
const val METHOD_INDEX_FOR_SETTER = 2
const val METHOD_INDEX_FOR_DEFAULT_CTOR = 3
const val METHOD_INDEX_FOR_NO_ARG_OVERLOAD_CTOR = 4
const val METHOD_INDEX_FOR_NON_ORIGIN_METHOD = 5
const val METHOD_INDEX_FOR_SCRIPT_MAIN = 6
const val METHOD_INDEX_BASE = 7
const val METHOD_INDEX_FOR_ANNOTATIONS = 3
const val METHOD_INDEX_FOR_DEFAULT_CTOR = 4
const val METHOD_INDEX_FOR_NO_ARG_OVERLOAD_CTOR = 5
const val METHOD_INDEX_FOR_NON_ORIGIN_METHOD = 6
const val METHOD_INDEX_FOR_SCRIPT_MAIN = 7
const val METHOD_INDEX_BASE = 8
@@ -0,0 +1,38 @@
/*
* 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.PsiDocCommentOwner
import com.intellij.psi.PsiModifierList
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
internal object DeprecatedAdditionalAnnotationsProvider : AdditionalAnnotationsProvider {
override fun addAllAnnotations(
currentRawAnnotations: MutableList<in PsiAnnotation>,
foundQualifiers: MutableSet<String>,
owner: PsiModifierList
) {
if ((owner.parent as? PsiDocCommentOwner)?.isDeprecated == true) {
addSimpleAnnotationIfMissing(JvmAnnotationNames.DEPRECATED_ANNOTATION.asString(), currentRawAnnotations, foundQualifiers, owner)
}
}
override fun isSpecialQualifier(qualifiedName: String): Boolean = false
override fun findSpecialAnnotation(
annotationsBox: GranularAnnotationsBox,
qualifiedName: String,
owner: PsiModifierList
): PsiAnnotation? = if ((owner.parent as? PsiDocCommentOwner)?.isDeprecated == true)
createSimpleAnnotationIfMatches(
qualifier = qualifiedName,
expectedQualifier = JvmAnnotationNames.DEPRECATED_ANNOTATION.asString(),
owner = owner,
)
else
null
}
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.analysis.project.structure.KtModule
import org.jetbrains.kotlin.analysis.project.structure.KtSourceModule
import org.jetbrains.kotlin.analysis.project.structure.getKtModuleOfTypeSafe
import org.jetbrains.kotlin.analysis.utils.errors.requireIsInstance
import org.jetbrains.kotlin.analysis.utils.printer.parentOfType
import org.jetbrains.kotlin.asJava.builder.LightMemberOriginForDeclaration
import org.jetbrains.kotlin.asJava.classes.*
import org.jetbrains.kotlin.asJava.elements.KtLightField
@@ -42,6 +43,7 @@ import org.jetbrains.kotlin.light.classes.symbol.fields.SymbolLightFieldForEnumE
import org.jetbrains.kotlin.light.classes.symbol.fields.SymbolLightFieldForProperty
import org.jetbrains.kotlin.light.classes.symbol.mapType
import org.jetbrains.kotlin.light.classes.symbol.methods.SymbolLightAccessorMethod
import org.jetbrains.kotlin.light.classes.symbol.methods.SymbolLightAnnotationsMethod
import org.jetbrains.kotlin.light.classes.symbol.methods.SymbolLightConstructor
import org.jetbrains.kotlin.light.classes.symbol.methods.SymbolLightNoArgConstructor
import org.jetbrains.kotlin.light.classes.symbol.methods.SymbolLightSimpleMethod
@@ -285,6 +287,31 @@ internal fun SymbolLightClassBase.createPropertyAccessors(
if (declaration.getter?.hasBody != true && declaration.setter?.hasBody != true && declaration.visibility.isPrivateOrPrivateToThis()) return
val originalElement = declaration.sourcePsiSafe<KtDeclaration>()
val generatePropertyAnnotationsMethods =
(declaration.getContainingModule() as? KtSourceModule)
?.languageVersionSettings
?.getFlag(JvmAnalysisFlags.generatePropertyAnnotationsMethods) == true
if (generatePropertyAnnotationsMethods && !this@createPropertyAccessors.isAnnotationType && declaration.psi?.parentOfType<KtClassOrObject>() == this.kotlinOrigin) {
val lightMemberOrigin = originalElement?.let {
LightMemberOriginForDeclaration(
originalElement = it,
originKind = JvmDeclarationOriginKind.OTHER,
)
}
val method = SymbolLightAnnotationsMethod(
ktAnalysisSession = this@KtAnalysisSession,
containingPropertySymbol = declaration,
lightMemberOrigin = lightMemberOrigin,
containingClass = this@createPropertyAccessors
)
if (method.annotations.size > 1) { // There's always a @java.lang.Deprecated
result.add(method)
}
}
if (declaration.isJvmField) return
val propertyTypeIsValueClass = declaration.hasTypeForValueClassInSignature()
@@ -320,8 +347,6 @@ internal fun SymbolLightClassBase.createPropertyAccessors(
return !isHiddenOrSynthetic(siteTarget, useSiteTargetFilterForPropertyAccessor)
}
val originalElement = declaration.sourcePsiSafe<KtDeclaration>()
val getter = declaration.getter?.takeIf {
it.needToCreateAccessor(AnnotationUseSiteTarget.PROPERTY_GETTER)
}
@@ -0,0 +1,160 @@
/*
* 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.methods
import com.intellij.openapi.util.TextRange
import com.intellij.psi.*
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
import org.jetbrains.kotlin.analysis.api.symbols.KtPropertySymbol
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.METHOD_INDEX_FOR_ANNOTATIONS
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.asJava.elements.KtLightIdentifier
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.light.classes.symbol.*
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.InitializedModifiersBox
import org.jetbrains.kotlin.light.classes.symbol.modifierLists.SymbolLightMemberModifierList
import org.jetbrains.kotlin.light.classes.symbol.parameters.SymbolLightParameterList
import org.jetbrains.kotlin.light.classes.symbol.parameters.SymbolLightTypeParameterList
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.psi.KtCallableDeclaration
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.utils.addToStdlib.ifTrue
internal class SymbolLightAnnotationsMethod private constructor(
lightMemberOrigin: LightMemberOrigin?,
containingClass: SymbolLightClassBase,
private val containingPropertyDeclaration: KtCallableDeclaration?,
private val containingPropertySymbolPointer: KtSymbolPointer<KtPropertySymbol>,
) : SymbolLightMethodBase(
lightMemberOrigin,
containingClass,
METHOD_INDEX_FOR_ANNOTATIONS,
) {
internal constructor(
ktAnalysisSession: KtAnalysisSession,
containingPropertySymbol: KtPropertySymbol,
lightMemberOrigin: LightMemberOrigin?,
containingClass: SymbolLightClassBase,
) : this(
lightMemberOrigin,
containingClass,
containingPropertyDeclaration = containingPropertySymbol.sourcePsiSafe(),
containingPropertySymbolPointer = with(ktAnalysisSession) { containingPropertySymbol.createPointer() },
)
context(KtAnalysisSession)
private fun propertySymbol(): KtPropertySymbol {
return containingPropertySymbolPointer.restoreSymbolOrThrowIfDisposed()
}
private fun String.abiName(): String {
return JvmAbi.getSyntheticMethodNameForAnnotatedProperty(JvmAbi.getterName(this))
}
private val _name: String by lazyPub {
analyzeForLightClasses(ktModule) {
val symbol = propertySymbol()
symbol.getJvmNameFromAnnotation(AnnotationUseSiteTarget.PROPERTY.toOptionalFilter()) ?: run {
val defaultName = symbol.name.identifier.let {
if (containingClass.isAnnotationType) it else it.abiName()
}
symbol.computeJvmMethodName(defaultName, containingClass, AnnotationUseSiteTarget.PROPERTY)
}
}
}
override fun getName(): String = _name
override fun isVarArgs(): Boolean = false
override val kotlinOrigin: KtDeclaration? get() = containingPropertyDeclaration
private val _modifierList: PsiModifierList by lazyPub {
return@lazyPub containingPropertySymbolPointer.withSymbol(ktModule) { propertySymbol ->
SymbolLightMemberModifierList(
containingDeclaration = this@SymbolLightAnnotationsMethod,
modifiersBox = InitializedModifiersBox(PsiModifier.PUBLIC, PsiModifier.STATIC),
annotationsBox = GranularAnnotationsBox(
annotationsProvider = SymbolAnnotationsProvider(
ktModule = ktModule,
annotatedSymbolPointer = propertySymbol.createPointer(),
annotationUseSiteTargetFilter = AnnotationUseSiteTarget.PROPERTY.toOptionalFilter(),
),
additionalAnnotationsProvider = DeprecatedAdditionalAnnotationsProvider
),
)
}
}
override fun getModifierList(): PsiModifierList = _modifierList
override fun isConstructor(): Boolean = false
override fun isDeprecated(): Boolean = true
private val _identifier: PsiIdentifier by lazyPub {
KtLightIdentifier(this, containingPropertyDeclaration)
}
override fun getNameIdentifier(): PsiIdentifier = _identifier
override fun getReturnType(): PsiType = PsiType.VOID
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is SymbolLightAnnotationsMethod) return false
return other.ktModule == ktModule && containingPropertyDeclaration == other.containingPropertyDeclaration
}
override fun hashCode(): Int = containingPropertyDeclaration.hashCode()
private val _typeParameterList: PsiTypeParameterList? by lazyPub {
hasTypeParameters().ifTrue {
SymbolLightTypeParameterList(
owner = this,
symbolWithTypeParameterPointer = containingPropertySymbolPointer,
ktModule = ktModule,
ktDeclaration = containingPropertyDeclaration,
)
}
}
override fun hasTypeParameters(): Boolean = hasTypeParameters(ktModule, containingPropertyDeclaration, containingPropertySymbolPointer)
override fun getTypeParameterList(): PsiTypeParameterList? = _typeParameterList
override fun getTypeParameters(): Array<PsiTypeParameter> = _typeParameterList?.typeParameters ?: PsiTypeParameter.EMPTY_ARRAY
private val _parametersList by lazyPub {
SymbolLightParameterList(
parent = this@SymbolLightAnnotationsMethod,
callableWithReceiverSymbolPointer = containingPropertySymbolPointer,
parameterPopulator = {},
)
}
override fun getParameterList(): PsiParameterList = _parametersList
override fun isValid(): Boolean =
super.isValid() && containingPropertySymbolPointer.isValid(ktModule)
override fun isOverride(): Boolean = false
override fun getText(): String {
return lightMemberOrigin?.auxiliaryOriginalElement?.text ?: super.getText()
}
override fun getTextOffset(): Int {
return lightMemberOrigin?.auxiliaryOriginalElement?.textOffset ?: super.getTextOffset()
}
override fun getTextRange(): TextRange {
return lightMemberOrigin?.auxiliaryOriginalElement?.textRange ?: super.getTextRange()
}
}