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()
}
}
@@ -36,6 +36,9 @@ object JvmAnalysisFlags {
@JvmStatic
val useIR by AnalysisFlag.Delegates.Boolean
@JvmStatic
val generatePropertyAnnotationsMethods by AnalysisFlag.Delegates.Boolean
private object Delegates {
object JavaTypeEnhancementStateWarnByDefault {
operator fun provideDelegate(instance: Any?, property: KProperty<*>): AnalysisFlag.Delegate<JavaTypeEnhancementState> =
@@ -81,6 +81,8 @@ class LanguageVersionSettingsBuilder {
analysisFlag(JvmAnalysisFlags.useIR, targetBackend?.isIR != false),
analysisFlag(AnalysisFlags.explicitApiVersion, trueOrNull(apiVersion != null)),
analysisFlag(JvmAnalysisFlags.generatePropertyAnnotationsMethods, trueOrNull(LanguageSettingsDirectives.GENERATE_PROPERTY_ANNOTATIONS_METHODS in directives)),
)
analysisFlags.forEach { withFlag(it.first, it.second) }
@@ -77,6 +77,10 @@ object LanguageSettingsDirectives : SimpleDirectivesContainer() {
val OLD_INNER_CLASSES_LOGIC by directive("Use old logic for generation of InnerClasses attributes")
val LINK_VIA_SIGNATURES by directive("Use linkage via signatures instead of descriptors / FIR")
val ENABLE_JVM_IR_INLINER by directive("Enable inlining on IR, instead of inlining on bytecode")
val GENERATE_PROPERTY_ANNOTATIONS_METHODS by directive(
description = "Enables corresponding analysis flag (JvmAnalysisFlags.generatePropertyAnnotationsMethods)"
)
// --------------------- Utils ---------------------
@@ -0,0 +1,27 @@
public final class Test /* Test*/ {
@MyAnnotation5()
@org.jetbrains.annotations.NotNull()
private java.lang.String bar;
@MyAnnotation()
@org.jetbrains.annotations.NotNull()
public final java.lang.String getBar();// getBar()
@MyAnnotation2()
public final void setBar(@MyAnnotation3() @org.jetbrains.annotations.NotNull() java.lang.String);// setBar(java.lang.String)
@MyAnnotation4()
@java.lang.Deprecated()
public static void getBar$annotations();// getBar$annotations()
@org.jetbrains.annotations.NotNull()
public final kotlin.Unit getFooP(@MyAnnotation7() int);// getFooP(int)
public Test(@MyAnnotation6() @org.jetbrains.annotations.NotNull() java.lang.String);// .ctor(java.lang.String)
public final void fooF(@MyAnnotation7() int);// fooF(int)
public final void fooWithNullableReceiver(@MyAnnotation7() @org.jetbrains.annotations.Nullable() java.lang.Integer, long);// fooWithNullableReceiver(java.lang.Integer, long)
public final void setFooP(@MyAnnotation7() int, @org.jetbrains.annotations.NotNull() kotlin.Unit);// setFooP(int, kotlin.Unit)
}
@@ -20,4 +20,4 @@ public final class Test /* Test*/ {
public final void fooWithNullableReceiver(@MyAnnotation7() @org.jetbrains.annotations.Nullable() java.lang.Integer, long);// fooWithNullableReceiver(java.lang.Integer, long)
public final void setFooP(@MyAnnotation7() int, @org.jetbrains.annotations.NotNull() kotlin.Unit);// setFooP(int, kotlin.Unit)
}
}
@@ -1,4 +1,5 @@
// Test
// !GENERATE_PROPERTY_ANNOTATIONS_METHODS
annotation class MyAnnotation
annotation class MyAnnotation2
annotation class MyAnnotation3
@@ -0,0 +1,98 @@
public abstract class AbstractKotlinClass /* AbstractKotlinClass*/ {
@org.jetbrains.annotations.NotNull()
public static final AbstractKotlinClass.Companion Companion;
public Custom classLateinitVariable;
public static Custom companionLateinitStaticVariable;
public static Custom companionLateinitVariable;
@org.jetbrains.annotations.NotNull()
public final Custom getClassLateinitVariable();// getClassLateinitVariable()
@org.jetbrains.annotations.NotNull()
public static final Custom getCompanionLateinitStaticVariable();// getCompanionLateinitStaticVariable()
public AbstractKotlinClass();// .ctor()
public final void setClassLateinitVariable(@org.jetbrains.annotations.NotNull() Custom);// setClassLateinitVariable(Custom)
public static final void setCompanionLateinitStaticVariable(@org.jetbrains.annotations.NotNull() Custom);// setCompanionLateinitStaticVariable(Custom)
class Companion ...
}
public static final class Companion /* KotlinClass.Companion*/ {
@java.lang.Deprecated()
@kotlin.jvm.JvmStatic()
public static void getCompanionLateinitStaticVariable$annotations();// getCompanionLateinitStaticVariable$annotations()
@org.jetbrains.annotations.NotNull()
public final Custom getCompanionLateinitStaticVariable();// getCompanionLateinitStaticVariable()
@org.jetbrains.annotations.NotNull()
public final Custom getCompanionLateinitVariable();// getCompanionLateinitVariable()
private Companion();// .ctor()
public final void setCompanionLateinitStaticVariable(@org.jetbrains.annotations.NotNull() Custom);// setCompanionLateinitStaticVariable(Custom)
public final void setCompanionLateinitVariable(@org.jetbrains.annotations.NotNull() Custom);// setCompanionLateinitVariable(Custom)
}
public static final class Companion /* AbstractKotlinClass.Companion*/ {
@java.lang.Deprecated()
@kotlin.jvm.JvmStatic()
public static void getCompanionLateinitStaticVariable$annotations();// getCompanionLateinitStaticVariable$annotations()
@org.jetbrains.annotations.NotNull()
public final Custom getCompanionLateinitStaticVariable();// getCompanionLateinitStaticVariable()
@org.jetbrains.annotations.NotNull()
public final Custom getCompanionLateinitVariable();// getCompanionLateinitVariable()
private Companion();// .ctor()
public final void setCompanionLateinitStaticVariable(@org.jetbrains.annotations.NotNull() Custom);// setCompanionLateinitStaticVariable(Custom)
public final void setCompanionLateinitVariable(@org.jetbrains.annotations.NotNull() Custom);// setCompanionLateinitVariable(Custom)
}
public final class Custom /* Custom*/ {
public Custom();// .ctor()
}
public final class KotlinClass /* KotlinClass*/ {
@org.jetbrains.annotations.NotNull()
public static final KotlinClass.Companion Companion;
public Custom classLateinitVariable;
public static Custom companionLateinitStaticVariable;
public static Custom companionLateinitVariable;
@org.jetbrains.annotations.NotNull()
public final Custom getClassLateinitVariable();// getClassLateinitVariable()
@org.jetbrains.annotations.NotNull()
public static final Custom getCompanionLateinitStaticVariable();// getCompanionLateinitStaticVariable()
public KotlinClass();// .ctor()
public final void setClassLateinitVariable(@org.jetbrains.annotations.NotNull() Custom);// setClassLateinitVariable(Custom)
public static final void setCompanionLateinitStaticVariable(@org.jetbrains.annotations.NotNull() Custom);// setCompanionLateinitStaticVariable(Custom)
class Companion ...
}
public final class LateinitPropertiesKt /* LateinitPropertiesKt*/ {
public static Custom topLevelLateinit;
@org.jetbrains.annotations.NotNull()
public static final Custom getTopLevelLateinit();// getTopLevelLateinit()
public static final void setTopLevelLateinit(@org.jetbrains.annotations.NotNull() Custom);// setTopLevelLateinit(Custom)
}
@@ -1,3 +1,4 @@
// !GENERATE_PROPERTY_ANNOTATIONS_METHODS
class KotlinClass {
lateinit var classLateinitVariable: Custom
@@ -26,6 +26,22 @@ public final class MyClass /* MyClass*/ {
private final int x7;
@AnotherUniversalAnnotation()
@java.lang.Deprecated()
public static void getX7$annotations();// getX7$annotations()
@PropertyAnnotation()
@java.lang.Deprecated()
public static void getX1$annotations();// getX1$annotations()
@PropertyOrFieldAnnotation()
@java.lang.Deprecated()
public static void getX2$annotations();// getX2$annotations()
@UniversalAnnotation()
@java.lang.Deprecated()
public static void getX5$annotations();// getX5$annotations()
public MyClass(@AnotherUniversalAnnotation() @ParameterAnnotation() @UniversalAnnotation() int, int, @PropertyOrParameterAnnotation() int, @ParameterOrFieldAnnotation() int, int, @AnotherUniversalAnnotation() int, @UniversalAnnotation() int);// .ctor(int, int, int, int, int, int, int)
public final int getX1();// getX1()
@@ -1,3 +1,4 @@
// !GENERATE_PROPERTY_ANNOTATIONS_METHODS
@Target(AnnotationTarget.PROPERTY)
annotation class PropertyAnnotation
@@ -126,6 +126,10 @@ public final class F /* F*/ implements java.lang.Runnable {
@Anno(p = "f")
public final void f(@Anno() @org.jetbrains.annotations.NotNull() java.lang.String);// f(java.lang.String)
@Anno(p = "p")
@java.lang.Deprecated()
public static void getProp$annotations();// getProp$annotations()
@org.jetbrains.annotations.NotNull()
public final java.lang.String getProp();// getProp()
@@ -1,3 +1,4 @@
// !GENERATE_PROPERTY_ANNOTATIONS_METHODS
import kotlin.reflect.KClass
@Target(*[AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.EXPRESSION])
@@ -77,6 +77,10 @@ public final class ClassWithConstContainer /* ClassWithConstContainer*/ {
}
public static final class Companion /* C.Companion*/ {
@java.lang.Deprecated()
@kotlin.jvm.JvmStatic()
public static void getX$annotations();// getX$annotations()
@kotlin.jvm.JvmStatic()
@org.jetbrains.annotations.NotNull()
public final java.lang.String getC(@org.jetbrains.annotations.NotNull() I);// getC(I)
@@ -155,6 +159,10 @@ public final class Obj /* Obj*/ implements java.lang.Runnable {
@org.jetbrains.annotations.NotNull()
public static final Obj INSTANCE;
@java.lang.Deprecated()
@kotlin.jvm.JvmStatic()
public static void getX$annotations();// getX$annotations()
@java.lang.Override()
public void run();// run()
@@ -1,4 +1,4 @@
// !GENERATE_PROPERTY_ANNOTATIONS_METHODS
class C {
companion object {
@JvmStatic fun foo() {}