From fe602d34cec228d938cff1feec9fd80d90689c4a Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Thu, 9 Apr 2015 22:49:35 +0300 Subject: [PATCH] Support type annotations in cls stub builder Also add test on decompiler --- .../stubs/elements/JetFileElementType.java | 2 +- ...tBinaryClassAnnotationAndConstantLoader.kt | 29 ++++++----- ...aryClassAnnotationAndConstantLoaderImpl.kt | 8 +-- .../stubBuilder/ClsStubBuilderContext.kt | 25 ++++------ .../stubBuilder/TypeClsStubBuilder.kt | 6 +++ .../decompiler/stubBuilder/clsStubBuilding.kt | 6 +-- .../decompiledText/Annotations.expected.kt | 4 +- .../decompiledText/Annotations/Annotations.kt | 4 +- .../stubBuilder/Annotations/Annotations.kt | 2 + .../stubBuilder/Annotations/Annotations.txt | 36 +++++++++++++ idea/testData/stubs/TypeAnnotation.expected | 50 +++++++++++++++++++ idea/testData/stubs/TypeAnnotation.kt | 7 +++ .../idea/stubs/StubBuilderTestGenerated.java | 6 +++ 13 files changed, 145 insertions(+), 40 deletions(-) create mode 100644 idea/testData/stubs/TypeAnnotation.expected create mode 100644 idea/testData/stubs/TypeAnnotation.kt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/stubs/elements/JetFileElementType.java b/compiler/frontend/src/org/jetbrains/kotlin/psi/stubs/elements/JetFileElementType.java index 5f2dfa1c0d8..22eba9a3e18 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/psi/stubs/elements/JetFileElementType.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/stubs/elements/JetFileElementType.java @@ -36,7 +36,7 @@ import org.jetbrains.kotlin.psi.stubs.impl.KotlinFileStubImpl; import java.io.IOException; public class JetFileElementType extends IStubFileElementType { - public static final int STUB_VERSION = 42; + public static final int STUB_VERSION = 43; private static final String NAME = "kotlin.FILE"; diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/AbstractBinaryClassAnnotationAndConstantLoader.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/AbstractBinaryClassAnnotationAndConstantLoader.kt index fdd2872c58d..92f20fc795d 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/AbstractBinaryClassAnnotationAndConstantLoader.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/AbstractBinaryClassAnnotationAndConstantLoader.kt @@ -16,23 +16,22 @@ package org.jetbrains.kotlin.load.kotlin +import org.jetbrains.kotlin.load.java.JvmAnnotationNames import org.jetbrains.kotlin.name.ClassId -import java.util.ArrayList -import org.jetbrains.kotlin.serialization.deserialization.AnnotatedCallableKind -import org.jetbrains.kotlin.serialization.deserialization.NameResolver -import org.jetbrains.kotlin.serialization.ProtoBuf -import org.jetbrains.kotlin.serialization.jvm.JvmProtoBuf.* -import org.jetbrains.kotlin.serialization.deserialization.ProtoContainer -import org.jetbrains.kotlin.storage.StorageManager -import org.jetbrains.kotlin.serialization.deserialization.ErrorReporter import org.jetbrains.kotlin.name.FqName -import java.util.HashMap import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.serialization.Flags -import org.jetbrains.kotlin.serialization.deserialization.AnnotationAndConstantLoader -import org.jetbrains.kotlin.load.java.JvmAnnotationNames -import org.jetbrains.kotlin.serialization.deserialization.DeserializationContext +import org.jetbrains.kotlin.serialization.ProtoBuf +import org.jetbrains.kotlin.serialization.deserialization.* +import org.jetbrains.kotlin.serialization.jvm.JvmProtoBuf +import org.jetbrains.kotlin.serialization.jvm.JvmProtoBuf.implClassName +import org.jetbrains.kotlin.serialization.jvm.JvmProtoBuf.index +import org.jetbrains.kotlin.serialization.jvm.JvmProtoBuf.methodSignature +import org.jetbrains.kotlin.serialization.jvm.JvmProtoBuf.propertySignature +import org.jetbrains.kotlin.storage.StorageManager import org.jetbrains.kotlin.types.JetType +import java.util.ArrayList +import java.util.HashMap public abstract class AbstractBinaryClassAnnotationAndConstantLoader( storageManager: StorageManager, @@ -51,6 +50,8 @@ public abstract class AbstractBinaryClassAnnotationAndConstantLoader ): KotlinJvmBinaryClass.AnnotationArgumentVisitor? + protected abstract fun loadTypeAnnotation(proto: ProtoBuf.Annotation, nameResolver: NameResolver): A + private fun loadAnnotationIfNotSpecial( annotationClassId: ClassId, result: MutableList @@ -128,6 +129,10 @@ public abstract class AbstractBinaryClassAnnotationAndConstantLoader { + return type.getExtension(JvmProtoBuf.typeAnnotation).map { loadTypeAnnotation(it, nameResolver) } + } + override fun loadPropertyConstant( container: ProtoContainer, proto: ProtoBuf.Callable, diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/BinaryClassAnnotationAndConstantLoaderImpl.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/BinaryClassAnnotationAndConstantLoaderImpl.kt index 5075a007802..3f1075a2a45 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/BinaryClassAnnotationAndConstantLoaderImpl.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/BinaryClassAnnotationAndConstantLoaderImpl.kt @@ -32,7 +32,6 @@ import org.jetbrains.kotlin.serialization.deserialization.AnnotationDeserializer import org.jetbrains.kotlin.serialization.deserialization.ErrorReporter import org.jetbrains.kotlin.serialization.deserialization.NameResolver import org.jetbrains.kotlin.serialization.deserialization.findClassAcrossModuleDependencies -import org.jetbrains.kotlin.serialization.jvm.JvmProtoBuf import org.jetbrains.kotlin.storage.StorageManager import org.jetbrains.kotlin.types.ErrorUtils import java.util.ArrayList @@ -48,11 +47,8 @@ public class BinaryClassAnnotationAndConstantLoaderImpl( ) { private val annotationDeserializer = AnnotationDeserializer(module) - override fun loadTypeAnnotations(type: ProtoBuf.Type, nameResolver: NameResolver): List { - return type.getExtension(JvmProtoBuf.typeAnnotation).map { annotation -> - annotationDeserializer.deserializeAnnotation(annotation, nameResolver) - } - } + override fun loadTypeAnnotation(proto: ProtoBuf.Annotation, nameResolver: NameResolver): AnnotationDescriptor = + annotationDeserializer.deserializeAnnotation(proto, nameResolver) override fun loadConstant(desc: String, initializer: Any): CompileTimeConstant<*>? { val normalizedValue: Any = if (desc in "ZBCS") { diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/ClsStubBuilderContext.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/ClsStubBuilderContext.kt index 8e33c08a91c..b9afcf42adf 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/ClsStubBuilderContext.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/ClsStubBuilderContext.kt @@ -16,18 +16,17 @@ package org.jetbrains.kotlin.idea.decompiler.stubBuilder -import org.jetbrains.kotlin.serialization.deserialization.NameResolver -import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.serialization.deserialization.ClassDataFinder -import org.jetbrains.kotlin.serialization.ProtoBuf -import org.jetbrains.kotlin.load.kotlin.KotlinClassFinder -import org.jetbrains.kotlin.serialization.deserialization.ErrorReporter import org.jetbrains.kotlin.load.kotlin.AbstractBinaryClassAnnotationAndConstantLoader -import org.jetbrains.kotlin.name.ClassId -import org.jetbrains.kotlin.storage.LockBasedStorageManager +import org.jetbrains.kotlin.load.kotlin.KotlinClassFinder import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass - +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.serialization.ProtoBuf +import org.jetbrains.kotlin.serialization.deserialization.ClassDataFinder +import org.jetbrains.kotlin.serialization.deserialization.ErrorReporter +import org.jetbrains.kotlin.serialization.deserialization.NameResolver +import org.jetbrains.kotlin.storage.LockBasedStorageManager class ClsStubBuilderComponents( val classDataFinder: ClassDataFinder, @@ -92,10 +91,8 @@ class AnnotationLoaderForStubBuilder( errorReporter: ErrorReporter ) : AbstractBinaryClassAnnotationAndConstantLoader( LockBasedStorageManager.NO_LOCKS, kotlinClassFinder, errorReporter) { - override fun loadTypeAnnotations(type: ProtoBuf.Type, nameResolver: NameResolver): MutableList { - // TODO: support type annotations in cls stubs - throw UnsupportedOperationException() - } + override fun loadTypeAnnotation(proto: ProtoBuf.Annotation, nameResolver: NameResolver): ClassId = + nameResolver.getClassId(proto.getId()) override fun loadConstant(desc: String, initializer: Any) = null diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/TypeClsStubBuilder.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/TypeClsStubBuilder.kt index c9cdc108add..937ec5a4856 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/TypeClsStubBuilder.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/TypeClsStubBuilder.kt @@ -42,6 +42,12 @@ class TypeClsStubBuilder(private val c: ClsStubBuilderContext) { fun createTypeReferenceStub(parent: StubElement, typeProto: Type) { val typeReference = KotlinPlaceHolderStubImpl(parent, JetStubElementTypes.TYPE_REFERENCE) + + val typeAnnotations = c.components.annotationLoader.loadTypeAnnotations(typeProto, c.nameResolver) + if (typeAnnotations.isNotEmpty()) { + createAnnotationStubs(typeAnnotations, typeReference, needWrappingAnnotationEntries = true) + } + createTypeStub(typeReference, typeProto) } diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/clsStubBuilding.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/clsStubBuilding.kt index 09b50b51a83..28110483b0c 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/clsStubBuilding.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/clsStubBuilding.kt @@ -170,14 +170,14 @@ fun createModifierListStub( fun createAnnotationStubs( annotationIds: List, - modifierList: KotlinModifierListStubImpl, + parent: KotlinStubBaseImpl<*>, needWrappingAnnotationEntries: Boolean = false ) { if (annotationIds.isEmpty()) return val entriesParent = - if (needWrappingAnnotationEntries) KotlinPlaceHolderStubImpl(modifierList, JetStubElementTypes.ANNOTATION) - else modifierList + if (needWrappingAnnotationEntries) KotlinPlaceHolderStubImpl(parent, JetStubElementTypes.ANNOTATION) + else parent annotationIds.forEach { annotationClassId -> diff --git a/idea/testData/decompiler/decompiledText/Annotations.expected.kt b/idea/testData/decompiler/decompiledText/Annotations.expected.kt index 4604db37570..bb9deade971 100644 --- a/idea/testData/decompiler/decompiledText/Annotations.expected.kt +++ b/idea/testData/decompiler/decompiledText/Annotations.expected.kt @@ -4,7 +4,7 @@ package test kotlin.data dependency.A dependency.B dependency.C internal final class Annotations public () { - kotlin.inline dependency.A dependency.B dependency.C internal final val p: kotlin.Int /* compiled code */ + kotlin.inline dependency.A dependency.B dependency.C internal final val p: [dependency.B] kotlin.Int /* compiled code */ - kotlin.inline dependency.A dependency.B dependency.C internal final fun f(dependency.A dependency.B dependency.C kotlin.deprecated i: kotlin.Int): kotlin.Unit { /* compiled code */ } + kotlin.inline dependency.A dependency.B dependency.C internal final fun f(dependency.A dependency.B dependency.C kotlin.deprecated i: [dependency.A] kotlin.Int): kotlin.Unit { /* compiled code */ } } diff --git a/idea/testData/decompiler/decompiledText/Annotations/Annotations.kt b/idea/testData/decompiler/decompiledText/Annotations/Annotations.kt index 245b6dcbfa6..d9938eb6c83 100644 --- a/idea/testData/decompiler/decompiledText/Annotations/Annotations.kt +++ b/idea/testData/decompiler/decompiledText/Annotations/Annotations.kt @@ -4,8 +4,8 @@ import dependency.* data A("a") B(1) C class Annotations { - inline A("f") B(2) C fun f(A("i") B(3) C deprecated("1") i: Int) { + inline A("f") B(2) C fun f(A("i") B(3) C deprecated("1") i: [A("int")] Int) { } - inline A("p") B(3) C val p: Int = 2 + inline A("p") B(3) C val p: [B(4)] Int = 2 } diff --git a/idea/testData/decompiler/stubBuilder/Annotations/Annotations.kt b/idea/testData/decompiler/stubBuilder/Annotations/Annotations.kt index 7344aa8f96c..f1b83673ec3 100644 --- a/idea/testData/decompiler/stubBuilder/Annotations/Annotations.kt +++ b/idea/testData/decompiler/stubBuilder/Annotations/Annotations.kt @@ -21,6 +21,8 @@ a public class Annotations private [a] (private [a] val c1: Int, [a] val c2: Int } class Nested [a] private [b(E.E1) b(E.E2)] () + + fun types(param: [a] [b(E.E1)] DoubleRange): [a] [b(E.E2)] Unit {} } annotation class a diff --git a/idea/testData/decompiler/stubBuilder/Annotations/Annotations.txt b/idea/testData/decompiler/stubBuilder/Annotations/Annotations.txt index 710ee7bc486..de543111a94 100644 --- a/idea/testData/decompiler/stubBuilder/Annotations/Annotations.txt +++ b/idea/testData/decompiler/stubBuilder/Annotations/Annotations.txt @@ -153,6 +153,42 @@ PsiJetFileStubImpl[package=] USER_TYPE:[isAbsoluteInRootPackage=false] REFERENCE_EXPRESSION:[referencedName=kotlin] REFERENCE_EXPRESSION:[referencedName=Unit] + FUN:[fqName=Annotations.types, hasBlockBody=true, hasBody=true, hasTypeParameterListBeforeFunctionName=false, isExtension=false, isTopLevel=false, name=types] + MODIFIER_LIST:[internal final] + VALUE_PARAMETER_LIST: + VALUE_PARAMETER:[fqName=null, hasDefaultValue=false, hasValOrVarNode=false, isMutable=false, name=param] + TYPE_REFERENCE: + ANNOTATION: + ANNOTATION_ENTRY:[hasValueArguments=false, shortName=a] + CONSTRUCTOR_CALLEE: + TYPE_REFERENCE: + USER_TYPE:[isAbsoluteInRootPackage=false] + REFERENCE_EXPRESSION:[referencedName=a] + ANNOTATION_ENTRY:[hasValueArguments=false, shortName=b] + CONSTRUCTOR_CALLEE: + TYPE_REFERENCE: + USER_TYPE:[isAbsoluteInRootPackage=false] + REFERENCE_EXPRESSION:[referencedName=b] + USER_TYPE:[isAbsoluteInRootPackage=false] + USER_TYPE:[isAbsoluteInRootPackage=false] + REFERENCE_EXPRESSION:[referencedName=kotlin] + REFERENCE_EXPRESSION:[referencedName=DoubleRange] + TYPE_REFERENCE: + ANNOTATION: + ANNOTATION_ENTRY:[hasValueArguments=false, shortName=a] + CONSTRUCTOR_CALLEE: + TYPE_REFERENCE: + USER_TYPE:[isAbsoluteInRootPackage=false] + REFERENCE_EXPRESSION:[referencedName=a] + ANNOTATION_ENTRY:[hasValueArguments=false, shortName=b] + CONSTRUCTOR_CALLEE: + TYPE_REFERENCE: + USER_TYPE:[isAbsoluteInRootPackage=false] + REFERENCE_EXPRESSION:[referencedName=b] + USER_TYPE:[isAbsoluteInRootPackage=false] + USER_TYPE:[isAbsoluteInRootPackage=false] + REFERENCE_EXPRESSION:[referencedName=kotlin] + REFERENCE_EXPRESSION:[referencedName=Unit] CLASS:[fqName=Annotations.Nested, isEnumEntry=false, isLocal=false, isTopLevel=false, isTrait=false, name=Nested, superNames=[]] MODIFIER_LIST:[internal final] PRIMARY_CONSTRUCTOR: diff --git a/idea/testData/stubs/TypeAnnotation.expected b/idea/testData/stubs/TypeAnnotation.expected new file mode 100644 index 00000000000..1889484d1bb --- /dev/null +++ b/idea/testData/stubs/TypeAnnotation.expected @@ -0,0 +1,50 @@ +PsiJetFileStubImpl[package=] + PACKAGE_DIRECTIVE: + CLASS:[fqName=a, isEnumEntry=false, isLocal=false, isTopLevel=true, isTrait=false, name=a, superNames=[]] + MODIFIER_LIST:[annotation] + CLASS:[fqName=b, isEnumEntry=false, isLocal=false, isTopLevel=true, isTrait=false, name=b, superNames=[]] + MODIFIER_LIST:[annotation] + PRIMARY_CONSTRUCTOR: + VALUE_PARAMETER_LIST: + VALUE_PARAMETER:[fqName=b.e, hasDefaultValue=false, hasValOrVarNode=true, isMutable=false, name=e] + TYPE_REFERENCE: + USER_TYPE:[isAbsoluteInRootPackage=false] + REFERENCE_EXPRESSION:[referencedName=E] + CLASS:[fqName=E, isEnumEntry=false, isLocal=false, isTopLevel=true, isTrait=false, name=E, superNames=[]] + MODIFIER_LIST:[enum] + CLASS_BODY: + ENUM_ENTRY:[fqName=E.E1, isEnumEntry=true, isLocal=false, isTopLevel=false, isTrait=false, name=E1, superNames=[]] + ENUM_ENTRY:[fqName=E.E2, isEnumEntry=true, isLocal=false, isTopLevel=false, isTrait=false, name=E2, superNames=[]] + FUN:[fqName=types, hasBlockBody=true, hasBody=true, hasTypeParameterListBeforeFunctionName=false, isExtension=false, isTopLevel=true, name=types] + VALUE_PARAMETER_LIST: + VALUE_PARAMETER:[fqName=null, hasDefaultValue=false, hasValOrVarNode=false, isMutable=false, name=param] + TYPE_REFERENCE: + ANNOTATION: + ANNOTATION_ENTRY:[hasValueArguments=false, shortName=a] + CONSTRUCTOR_CALLEE: + TYPE_REFERENCE: + USER_TYPE:[isAbsoluteInRootPackage=false] + REFERENCE_EXPRESSION:[referencedName=a] + ANNOTATION: + ANNOTATION_ENTRY:[hasValueArguments=true, shortName=b] + CONSTRUCTOR_CALLEE: + TYPE_REFERENCE: + USER_TYPE:[isAbsoluteInRootPackage=false] + REFERENCE_EXPRESSION:[referencedName=b] + USER_TYPE:[isAbsoluteInRootPackage=false] + REFERENCE_EXPRESSION:[referencedName=DoubleRange] + TYPE_REFERENCE: + ANNOTATION: + ANNOTATION_ENTRY:[hasValueArguments=false, shortName=a] + CONSTRUCTOR_CALLEE: + TYPE_REFERENCE: + USER_TYPE:[isAbsoluteInRootPackage=false] + REFERENCE_EXPRESSION:[referencedName=a] + ANNOTATION: + ANNOTATION_ENTRY:[hasValueArguments=true, shortName=b] + CONSTRUCTOR_CALLEE: + TYPE_REFERENCE: + USER_TYPE:[isAbsoluteInRootPackage=false] + REFERENCE_EXPRESSION:[referencedName=b] + USER_TYPE:[isAbsoluteInRootPackage=false] + REFERENCE_EXPRESSION:[referencedName=Unit] diff --git a/idea/testData/stubs/TypeAnnotation.kt b/idea/testData/stubs/TypeAnnotation.kt new file mode 100644 index 00000000000..2e6942e1a15 --- /dev/null +++ b/idea/testData/stubs/TypeAnnotation.kt @@ -0,0 +1,7 @@ +annotation class a + +annotation class b(val e: E) + +enum class E { E1 E2 } + +fun types(param: [a] [b(E.E1)] DoubleRange): [a] [b(E.E2)] Unit {} diff --git a/idea/tests/org/jetbrains/kotlin/idea/stubs/StubBuilderTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/stubs/StubBuilderTestGenerated.java index 52f8abefa67..48c41491a3d 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/stubs/StubBuilderTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/stubs/StubBuilderTestGenerated.java @@ -238,4 +238,10 @@ public class StubBuilderTestGenerated extends AbstractStubBuilderTest { String fileName = JetTestUtils.navigationMetadata("idea/testData/stubs/StarProjection.kt"); doTest(fileName); } + + @TestMetadata("TypeAnnotation.kt") + public void testTypeAnnotation() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/stubs/TypeAnnotation.kt"); + doTest(fileName); + } }