[cls] include annotation arguments in cls stubs
^ KTIJ-24666 this would allow to build fir based on stubs, do not keep ProtoBuf in memory and search in decompiled code by stubs
This commit is contained in:
+13
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* 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.analysis.decompiler.stub
|
||||
|
||||
import org.jetbrains.kotlin.constant.ConstantValue
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
|
||||
data class AnnotationWithArgs(val classId: ClassId, val args: Map<Name, ConstantValue<*>>)
|
||||
+78
-75
@@ -114,7 +114,7 @@ abstract class CallableClsStubBuilder(
|
||||
}
|
||||
|
||||
abstract val receiverType: ProtoBuf.Type?
|
||||
abstract val receiverAnnotations: List<ClassIdWithTarget>
|
||||
abstract val receiverAnnotations: List<AnnotationWithTarget>
|
||||
|
||||
abstract val returnType: ProtoBuf.Type?
|
||||
abstract val contextReceiverTypes: List<ProtoBuf.Type>
|
||||
@@ -149,11 +149,11 @@ private class FunctionClsStubBuilder(
|
||||
override val receiverType: ProtoBuf.Type?
|
||||
get() = functionProto.receiverType(c.typeTable)
|
||||
|
||||
override val receiverAnnotations: List<ClassIdWithTarget>
|
||||
override val receiverAnnotations: List<AnnotationWithTarget>
|
||||
get() {
|
||||
return c.components.annotationLoader
|
||||
.loadExtensionReceiverParameterAnnotations(protoContainer, functionProto, AnnotatedCallableKind.FUNCTION)
|
||||
.map { ClassIdWithTarget(it, AnnotationUseSiteTarget.RECEIVER) }
|
||||
.map { AnnotationWithTarget(it, AnnotationUseSiteTarget.RECEIVER) }
|
||||
}
|
||||
|
||||
override val returnType: ProtoBuf.Type
|
||||
@@ -176,10 +176,10 @@ private class FunctionClsStubBuilder(
|
||||
// If function is marked as having no annotations, we don't create stubs for it
|
||||
if (!Flags.HAS_ANNOTATIONS.get(functionProto.flags)) return
|
||||
|
||||
val annotationIds = c.components.annotationLoader.loadCallableAnnotations(
|
||||
val annotations = c.components.annotationLoader.loadCallableAnnotations(
|
||||
protoContainer, functionProto, AnnotatedCallableKind.FUNCTION
|
||||
)
|
||||
createAnnotationStubs(annotationIds, modifierListStubImpl)
|
||||
createAnnotationStubs(annotations, modifierListStubImpl)
|
||||
}
|
||||
|
||||
override fun doCreateCallableStub(parent: StubElement<out PsiElement>): StubElement<out PsiElement> {
|
||||
@@ -217,10 +217,10 @@ private class PropertyClsStubBuilder(
|
||||
override val receiverType: ProtoBuf.Type?
|
||||
get() = propertyProto.receiverType(c.typeTable)
|
||||
|
||||
override val receiverAnnotations: List<ClassIdWithTarget>
|
||||
override val receiverAnnotations: List<AnnotationWithTarget>
|
||||
get() = c.components.annotationLoader
|
||||
.loadExtensionReceiverParameterAnnotations(protoContainer, propertyProto, AnnotatedCallableKind.PROPERTY_GETTER)
|
||||
.map { ClassIdWithTarget(it, AnnotationUseSiteTarget.RECEIVER) }
|
||||
.map { AnnotationWithTarget(it, AnnotationUseSiteTarget.RECEIVER) }
|
||||
|
||||
override val returnType: ProtoBuf.Type
|
||||
get() = propertyProto.returnType(c.typeTable)
|
||||
@@ -250,9 +250,9 @@ private class PropertyClsStubBuilder(
|
||||
val delegateFieldAnnotations =
|
||||
c.components.annotationLoader.loadPropertyDelegateFieldAnnotations(protoContainer, propertyProto)
|
||||
val allAnnotations =
|
||||
propertyAnnotations.map { ClassIdWithTarget(it, null) } +
|
||||
backingFieldAnnotations.map { ClassIdWithTarget(it, AnnotationUseSiteTarget.FIELD) } +
|
||||
delegateFieldAnnotations.map { ClassIdWithTarget(it, AnnotationUseSiteTarget.PROPERTY_DELEGATE_FIELD) }
|
||||
propertyAnnotations.map { AnnotationWithTarget(it, null) } +
|
||||
backingFieldAnnotations.map { AnnotationWithTarget(it, AnnotationUseSiteTarget.FIELD) } +
|
||||
delegateFieldAnnotations.map { AnnotationWithTarget(it, AnnotationUseSiteTarget.PROPERTY_DELEGATE_FIELD) }
|
||||
createTargetedAnnotationStubs(allAnnotations, modifierListStubImpl)
|
||||
}
|
||||
|
||||
@@ -360,74 +360,11 @@ private class PropertyClsStubBuilder(
|
||||
): KotlinJvmBinaryClass.AnnotationArgumentVisitor? = null
|
||||
|
||||
override fun visitAnnotationMemberDefaultValue(): KotlinJvmBinaryClass.AnnotationArgumentVisitor {
|
||||
class AnnotationMemberDefaultValueVisitor : KotlinJvmBinaryClass.AnnotationArgumentVisitor {
|
||||
private val args = mutableMapOf<Name, ConstantValue<*>>()
|
||||
|
||||
private fun nameOrSpecial(name: Name?): Name {
|
||||
return name ?: Name.special("<no_name>")
|
||||
}
|
||||
|
||||
override fun visit(name: Name?, value: Any?) {
|
||||
args[nameOrSpecial(name)] = createConstantValue(value)
|
||||
}
|
||||
|
||||
override fun visitClassLiteral(name: Name?, value: ClassLiteralValue) {
|
||||
args[nameOrSpecial(name)] = createConstantValue(KClassData(value.classId, value.arrayNestedness))
|
||||
}
|
||||
|
||||
override fun visitEnum(name: Name?, enumClassId: ClassId, enumEntryName: Name) {
|
||||
args[nameOrSpecial(name)] = createConstantValue(EnumData(enumClassId, enumEntryName))
|
||||
}
|
||||
|
||||
override fun visitAnnotation(
|
||||
name: Name?,
|
||||
classId: ClassId
|
||||
): KotlinJvmBinaryClass.AnnotationArgumentVisitor {
|
||||
val visitor = AnnotationMemberDefaultValueVisitor()
|
||||
return object : KotlinJvmBinaryClass.AnnotationArgumentVisitor by visitor {
|
||||
override fun visitEnd() {
|
||||
args[nameOrSpecial(name)] = createConstantValue(AnnotationData(classId, visitor.args))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitArray(name: Name?): KotlinJvmBinaryClass.AnnotationArrayArgumentVisitor {
|
||||
return object : KotlinJvmBinaryClass.AnnotationArrayArgumentVisitor {
|
||||
private val elements = mutableListOf<Any>()
|
||||
|
||||
override fun visit(value: Any?) {
|
||||
elements.addIfNotNull(value)
|
||||
}
|
||||
|
||||
override fun visitEnum(enumClassId: ClassId, enumEntryName: Name) {
|
||||
elements.add(EnumData(enumClassId, enumEntryName))
|
||||
}
|
||||
|
||||
override fun visitClassLiteral(value: ClassLiteralValue) {
|
||||
elements.add(KClassData(value.classId, value.arrayNestedness))
|
||||
}
|
||||
|
||||
override fun visitAnnotation(classId: ClassId): KotlinJvmBinaryClass.AnnotationArgumentVisitor {
|
||||
val visitor = AnnotationMemberDefaultValueVisitor()
|
||||
return object : KotlinJvmBinaryClass.AnnotationArgumentVisitor by visitor {
|
||||
override fun visitEnd() {
|
||||
elements.addIfNotNull(AnnotationData(classId, visitor.args))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitEnd() {
|
||||
args[nameOrSpecial(name)] = createConstantValue(elements.toTypedArray())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return object : AnnotationMemberDefaultValueVisitor() {
|
||||
override fun visitEnd() {
|
||||
constantInitializer = args.values.firstOrNull()
|
||||
}
|
||||
}
|
||||
|
||||
return AnnotationMemberDefaultValueVisitor()
|
||||
}
|
||||
|
||||
override fun visitAnnotation(
|
||||
@@ -482,7 +419,7 @@ private class ConstructorClsStubBuilder(
|
||||
override val receiverType: ProtoBuf.Type?
|
||||
get() = null
|
||||
|
||||
override val receiverAnnotations: List<ClassIdWithTarget>
|
||||
override val receiverAnnotations: List<AnnotationWithTarget>
|
||||
get() = emptyList()
|
||||
|
||||
override val returnType: ProtoBuf.Type?
|
||||
@@ -519,3 +456,69 @@ private class ConstructorClsStubBuilder(
|
||||
KotlinConstructorStubImpl(parent, KtStubElementTypes.PRIMARY_CONSTRUCTOR, name, hasBody = false, isDelegatedCallToThis = false)
|
||||
}
|
||||
}
|
||||
|
||||
open class AnnotationMemberDefaultValueVisitor : KotlinJvmBinaryClass.AnnotationArgumentVisitor {
|
||||
protected val args = mutableMapOf<Name, ConstantValue<*>>()
|
||||
|
||||
private fun nameOrSpecial(name: Name?): Name {
|
||||
return name ?: Name.special("<no_name>")
|
||||
}
|
||||
|
||||
override fun visit(name: Name?, value: Any?) {
|
||||
val constantValue = createConstantValue(value)
|
||||
args[nameOrSpecial(name)] = constantValue
|
||||
}
|
||||
|
||||
override fun visitClassLiteral(name: Name?, value: ClassLiteralValue) {
|
||||
args[nameOrSpecial(name)] = createConstantValue(KClassData(value.classId, value.arrayNestedness))
|
||||
}
|
||||
|
||||
override fun visitEnum(name: Name?, enumClassId: ClassId, enumEntryName: Name) {
|
||||
args[nameOrSpecial(name)] = createConstantValue(EnumData(enumClassId, enumEntryName))
|
||||
}
|
||||
|
||||
override fun visitAnnotation(
|
||||
name: Name?,
|
||||
classId: ClassId
|
||||
): KotlinJvmBinaryClass.AnnotationArgumentVisitor? {
|
||||
val visitor = AnnotationMemberDefaultValueVisitor()
|
||||
return object : KotlinJvmBinaryClass.AnnotationArgumentVisitor by visitor {
|
||||
override fun visitEnd() {
|
||||
args[nameOrSpecial(name)] = createConstantValue(AnnotationData(classId, visitor.args))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitArray(name: Name?): KotlinJvmBinaryClass.AnnotationArrayArgumentVisitor? {
|
||||
return object : KotlinJvmBinaryClass.AnnotationArrayArgumentVisitor {
|
||||
private val elements = mutableListOf<Any>()
|
||||
|
||||
override fun visit(value: Any?) {
|
||||
elements.addIfNotNull(value)
|
||||
}
|
||||
|
||||
override fun visitEnum(enumClassId: ClassId, enumEntryName: Name) {
|
||||
elements.add(EnumData(enumClassId, enumEntryName))
|
||||
}
|
||||
|
||||
override fun visitClassLiteral(value: ClassLiteralValue) {
|
||||
elements.add(KClassData(value.classId, value.arrayNestedness))
|
||||
}
|
||||
|
||||
override fun visitAnnotation(classId: ClassId): KotlinJvmBinaryClass.AnnotationArgumentVisitor {
|
||||
val visitor = AnnotationMemberDefaultValueVisitor()
|
||||
return object : KotlinJvmBinaryClass.AnnotationArgumentVisitor by visitor {
|
||||
override fun visitEnd() {
|
||||
elements.addIfNotNull(AnnotationData(classId, visitor.args))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitEnd() {
|
||||
args[nameOrSpecial(name)] = createConstantValue(elements.toTypedArray())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitEnd() {}
|
||||
}
|
||||
+2
-2
@@ -18,11 +18,11 @@ import org.jetbrains.kotlin.serialization.deserialization.ClassDataFinder
|
||||
import org.jetbrains.kotlin.serialization.deserialization.ProtoContainer
|
||||
import org.jetbrains.kotlin.serialization.deserialization.getName
|
||||
|
||||
data class ClassIdWithTarget(val classId: ClassId, val target: AnnotationUseSiteTarget?)
|
||||
data class AnnotationWithTarget(val annotationWithArgs: AnnotationWithArgs, val target: AnnotationUseSiteTarget?)
|
||||
|
||||
class ClsStubBuilderComponents(
|
||||
val classDataFinder: ClassDataFinder,
|
||||
val annotationLoader: AnnotationLoader<ClassId>,
|
||||
val annotationLoader: AnnotationLoader<AnnotationWithArgs>,
|
||||
val virtualFileForDebug: VirtualFile,
|
||||
val serializationProtocol: SerializerExtensionProtocol,
|
||||
val classFinder: KotlinClassFinder? = null,
|
||||
|
||||
+9
-9
@@ -37,7 +37,7 @@ class TypeClsStubBuilder(private val c: ClsStubBuilderContext) {
|
||||
fun createTypeReferenceStub(
|
||||
parent: StubElement<out PsiElement>,
|
||||
type: Type,
|
||||
additionalAnnotations: () -> List<ClassIdWithTarget> = { emptyList() }
|
||||
additionalAnnotations: () -> List<AnnotationWithTarget> = { emptyList() }
|
||||
) {
|
||||
val abbreviatedType = type.abbreviatedType(c.typeTable)
|
||||
if (abbreviatedType != null) {
|
||||
@@ -47,11 +47,11 @@ class TypeClsStubBuilder(private val c: ClsStubBuilderContext) {
|
||||
val typeReference = KotlinPlaceHolderStubImpl<KtTypeReference>(parent, KtStubElementTypes.TYPE_REFERENCE)
|
||||
|
||||
val annotations = c.components.annotationLoader.loadTypeAnnotations(type, c.nameResolver).filterNot {
|
||||
val isTopLevelClass = !it.isNestedClass
|
||||
isTopLevelClass && it.asSingleFqName() in ANNOTATIONS_NOT_LOADED_FOR_TYPES
|
||||
val isTopLevelClass = !it.classId.isNestedClass
|
||||
isTopLevelClass && it.classId.asSingleFqName() in ANNOTATIONS_NOT_LOADED_FOR_TYPES
|
||||
}
|
||||
|
||||
val allAnnotations = additionalAnnotations() + annotations.map { ClassIdWithTarget(it, null) }
|
||||
val allAnnotations = additionalAnnotations() + annotations.map { AnnotationWithTarget(it, null) }
|
||||
|
||||
when {
|
||||
type.hasClassName() || type.hasTypeAliasName() ->
|
||||
@@ -71,7 +71,7 @@ class TypeClsStubBuilder(private val c: ClsStubBuilderContext) {
|
||||
else
|
||||
parent
|
||||
|
||||
private fun createTypeParameterStub(parent: KotlinStubBaseImpl<*>, type: Type, name: Name, annotations: List<ClassIdWithTarget>) {
|
||||
private fun createTypeParameterStub(parent: KotlinStubBaseImpl<*>, type: Type, name: Name, annotations: List<AnnotationWithTarget>) {
|
||||
createTypeAnnotationStubs(parent, type, annotations)
|
||||
val upperBoundType = if (type.hasFlexibleTypeCapabilitiesId()) {
|
||||
createKotlinTypeBean(type.flexibleUpperBound(c.typeTable)!!)
|
||||
@@ -95,7 +95,7 @@ class TypeClsStubBuilder(private val c: ClsStubBuilderContext) {
|
||||
KotlinNameReferenceExpressionStubImpl(userType, StandardNames.FqNames.any.shortName().ref())
|
||||
}
|
||||
|
||||
private fun createClassReferenceTypeStub(parent: KotlinStubBaseImpl<*>, type: Type, annotations: List<ClassIdWithTarget>) {
|
||||
private fun createClassReferenceTypeStub(parent: KotlinStubBaseImpl<*>, type: Type, annotations: List<AnnotationWithTarget>) {
|
||||
if (type.hasFlexibleTypeCapabilitiesId()) {
|
||||
val id = c.nameResolver.getString(type.flexibleTypeCapabilitiesId)
|
||||
|
||||
@@ -113,11 +113,11 @@ class TypeClsStubBuilder(private val c: ClsStubBuilderContext) {
|
||||
val shouldBuildAsFunctionType = isBuiltinFunctionClass(classId) && type.argumentList.none { it.projection == Projection.STAR }
|
||||
if (shouldBuildAsFunctionType) {
|
||||
val (extensionAnnotations, notExtensionAnnotations) = annotations.partition {
|
||||
it.classId.asSingleFqName() == StandardNames.FqNames.extensionFunctionType
|
||||
it.annotationWithArgs.classId.asSingleFqName() == StandardNames.FqNames.extensionFunctionType
|
||||
}
|
||||
|
||||
val (contextReceiverAnnotations, otherAnnotations) = notExtensionAnnotations.partition {
|
||||
it.classId.asSingleFqName() == StandardNames.FqNames.contextFunctionTypeParams
|
||||
it.annotationWithArgs.classId.asSingleFqName() == StandardNames.FqNames.contextFunctionTypeParams
|
||||
}
|
||||
|
||||
val isExtension = extensionAnnotations.isNotEmpty()
|
||||
@@ -194,7 +194,7 @@ class TypeClsStubBuilder(private val c: ClsStubBuilderContext) {
|
||||
} else lowerBound
|
||||
}
|
||||
|
||||
private fun createTypeAnnotationStubs(parent: KotlinStubBaseImpl<*>, type: Type, annotations: List<ClassIdWithTarget>) {
|
||||
private fun createTypeAnnotationStubs(parent: KotlinStubBaseImpl<*>, type: Type, annotations: List<AnnotationWithTarget>) {
|
||||
val typeModifiers = getTypeModifiersAsWritten(type)
|
||||
if (annotations.isEmpty() && typeModifiers.isEmpty()) return
|
||||
val typeModifiersMask = ModifierMaskUtils.computeMask { it in typeModifiers }
|
||||
|
||||
+10
-9
@@ -192,22 +192,23 @@ fun createEmptyModifierListStub(parent: KotlinStubBaseImpl<*>): KotlinModifierLi
|
||||
)
|
||||
}
|
||||
|
||||
fun createAnnotationStubs(annotationIds: List<ClassId>, parent: KotlinStubBaseImpl<*>) {
|
||||
return createTargetedAnnotationStubs(annotationIds.map { ClassIdWithTarget(it, null) }, parent)
|
||||
fun createAnnotationStubs(annotations: List<AnnotationWithArgs>, parent: KotlinStubBaseImpl<*>) {
|
||||
return createTargetedAnnotationStubs(annotations.map { AnnotationWithTarget(it, null) }, parent)
|
||||
}
|
||||
|
||||
fun createTargetedAnnotationStubs(
|
||||
annotationIds: List<ClassIdWithTarget>,
|
||||
annotations: List<AnnotationWithTarget>,
|
||||
parent: KotlinStubBaseImpl<*>
|
||||
) {
|
||||
if (annotationIds.isEmpty()) return
|
||||
if (annotations.isEmpty()) return
|
||||
|
||||
annotationIds.forEach { annotation ->
|
||||
val (annotationClassId, target) = annotation
|
||||
annotations.forEach { annotation ->
|
||||
val (annotationWithArgs, target) = annotation
|
||||
val annotationEntryStubImpl = KotlinAnnotationEntryStubImpl(
|
||||
parent,
|
||||
shortName = annotationClassId.shortClassName.ref(),
|
||||
hasValueArguments = false
|
||||
shortName = annotationWithArgs.classId.shortClassName.ref(),
|
||||
hasValueArguments = false,
|
||||
annotationWithArgs.args
|
||||
)
|
||||
if (target != null) {
|
||||
KotlinAnnotationUseSiteTargetStubImpl(annotationEntryStubImpl, StringRef.fromString(target.name)!!)
|
||||
@@ -215,7 +216,7 @@ fun createTargetedAnnotationStubs(
|
||||
val constructorCallee =
|
||||
KotlinPlaceHolderStubImpl<KtConstructorCalleeExpression>(annotationEntryStubImpl, KtStubElementTypes.CONSTRUCTOR_CALLEE)
|
||||
val typeReference = KotlinPlaceHolderStubImpl<KtTypeReference>(constructorCallee, KtStubElementTypes.TYPE_REFERENCE)
|
||||
createStubForTypeName(annotationClassId, typeReference)
|
||||
createStubForTypeName(annotationWithArgs.classId, typeReference)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+6
-2
@@ -11,7 +11,6 @@ import org.jetbrains.kotlin.metadata.deserialization.underlyingType
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.psi.stubs.impl.KotlinTypeAliasStubImpl
|
||||
import org.jetbrains.kotlin.serialization.deserialization.ProtoContainer
|
||||
import org.jetbrains.kotlin.serialization.deserialization.getClassId
|
||||
import org.jetbrains.kotlin.serialization.deserialization.getName
|
||||
|
||||
fun createTypeAliasStub(
|
||||
@@ -42,7 +41,12 @@ fun createTypeAliasStub(
|
||||
}
|
||||
|
||||
if (Flags.HAS_ANNOTATIONS.get(typeAliasProto.flags)) {
|
||||
createAnnotationStubs(typeAliasProto.annotationList.map { c.nameResolver.getClassId(it.id) }, modifierList)
|
||||
createAnnotationStubs(
|
||||
typeAliasProto.annotationList.map {
|
||||
c.components.annotationLoader.loadAnnotation(it, c.nameResolver)
|
||||
},
|
||||
modifierList
|
||||
)
|
||||
}
|
||||
|
||||
val typeAliasUnderlyingType = typeAliasProto.underlyingType(c.typeTable)
|
||||
|
||||
Reference in New Issue
Block a user