Render decompiled annotations on enum entries
This commit is contained in:
+1
-1
@@ -34,7 +34,7 @@ import org.jetbrains.kotlin.psi.stubs.KotlinFileStub;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
public class KtFileElementType extends IStubFileElementType<KotlinFileStub> {
|
public class KtFileElementType extends IStubFileElementType<KotlinFileStub> {
|
||||||
public static final int STUB_VERSION = 64;
|
public static final int STUB_VERSION = 65;
|
||||||
|
|
||||||
private static final String NAME = "kotlin.FILE";
|
private static final String NAME = "kotlin.FILE";
|
||||||
|
|
||||||
|
|||||||
+3
-7
@@ -52,10 +52,8 @@ public class AnnotationLoaderForStubBuilderImpl(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun loadEnumEntryAnnotations(container: ProtoContainer, proto: ProtoBuf.EnumEntry): List<ClassId> {
|
override fun loadEnumEntryAnnotations(container: ProtoContainer, proto: ProtoBuf.EnumEntry): List<ClassId> =
|
||||||
// TODO
|
proto.getExtension(protocol.enumEntryAnnotation).orEmpty().map { container.nameResolver.getClassId(it.id) }
|
||||||
return listOf()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun loadValueParameterAnnotations(
|
override fun loadValueParameterAnnotations(
|
||||||
container: ProtoContainer,
|
container: ProtoContainer,
|
||||||
@@ -64,9 +62,7 @@ public class AnnotationLoaderForStubBuilderImpl(
|
|||||||
parameterIndex: Int,
|
parameterIndex: Int,
|
||||||
proto: ProtoBuf.ValueParameter
|
proto: ProtoBuf.ValueParameter
|
||||||
): List<ClassId> =
|
): List<ClassId> =
|
||||||
proto.getExtension(protocol.parameterAnnotation).orEmpty().map {
|
proto.getExtension(protocol.parameterAnnotation).orEmpty().map { container.nameResolver.getClassId(it.id) }
|
||||||
container.nameResolver.getClassId(it.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun loadExtensionReceiverParameterAnnotations(
|
override fun loadExtensionReceiverParameterAnnotations(
|
||||||
container: ProtoContainer,
|
container: ProtoContainer,
|
||||||
|
|||||||
+19
-3
@@ -172,9 +172,22 @@ private class ClassClsStubBuilder(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun createEnumEntryStubs(classBody: KotlinPlaceHolderStubImpl<KtClassBody>) {
|
private fun createEnumEntryStubs(classBody: KotlinPlaceHolderStubImpl<KtClassBody>) {
|
||||||
classProto.getEnumEntryNameList().forEach { id ->
|
if (classKind != ProtoBuf.Class.Kind.ENUM_CLASS) return
|
||||||
val name = c.nameResolver.getName(id)
|
|
||||||
KotlinClassStubImpl(
|
val container = ProtoContainer(classProto, null, c.nameResolver, c.typeTable)
|
||||||
|
val enumEntries: List<Pair<Int, List<ClassId>>> =
|
||||||
|
if (classProto.enumEntryList.isNotEmpty())
|
||||||
|
classProto.enumEntryList.map { enumEntryProto ->
|
||||||
|
enumEntryProto.name to c.components.annotationLoader.loadEnumEntryAnnotations(container, enumEntryProto)
|
||||||
|
}
|
||||||
|
else classProto.enumEntryNameList.map { enumEntryName ->
|
||||||
|
enumEntryName to listOf<ClassId>()
|
||||||
|
}
|
||||||
|
|
||||||
|
enumEntries.forEach { entry ->
|
||||||
|
val name = c.nameResolver.getName(entry.first)
|
||||||
|
val annotations = entry.second
|
||||||
|
val enumEntryStub = KotlinClassStubImpl(
|
||||||
KtStubElementTypes.ENUM_ENTRY,
|
KtStubElementTypes.ENUM_ENTRY,
|
||||||
classBody,
|
classBody,
|
||||||
qualifiedName = c.containerFqName.child(name).ref(),
|
qualifiedName = c.containerFqName.child(name).ref(),
|
||||||
@@ -185,6 +198,9 @@ private class ClassClsStubBuilder(
|
|||||||
isLocal = false,
|
isLocal = false,
|
||||||
isTopLevel = false
|
isTopLevel = false
|
||||||
)
|
)
|
||||||
|
if (annotations.isNotEmpty()) {
|
||||||
|
createAnnotationStubs(annotations, createEmptyModifierListStub(enumEntryStub))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-10
@@ -19,7 +19,6 @@ package org.jetbrains.kotlin.idea.decompiler.stubBuilder
|
|||||||
import com.google.protobuf.MessageLite
|
import com.google.protobuf.MessageLite
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import com.intellij.psi.stubs.StubElement
|
import com.intellij.psi.stubs.StubElement
|
||||||
import com.intellij.util.SmartList
|
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
|
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
@@ -175,21 +174,13 @@ class TypeClsStubBuilder(private val c: ClsStubBuilderContext) {
|
|||||||
container, callableProto, callableProto.annotatedCallableKind, index, valueParameterProto
|
container, callableProto, callableProto.annotatedCallableKind, index, valueParameterProto
|
||||||
)
|
)
|
||||||
if (parameterAnnotations.isNotEmpty()) {
|
if (parameterAnnotations.isNotEmpty()) {
|
||||||
createAnnotationStubs(parameterAnnotations, modifierList ?: createEmptyModifierList(parameterStub))
|
createAnnotationStubs(parameterAnnotations, modifierList ?: createEmptyModifierListStub(parameterStub))
|
||||||
}
|
}
|
||||||
|
|
||||||
createTypeReferenceStub(parameterStub, typeProto)
|
createTypeReferenceStub(parameterStub, typeProto)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createEmptyModifierList(parameterStub: KotlinParameterStubImpl): KotlinModifierListStubImpl {
|
|
||||||
return KotlinModifierListStubImpl(
|
|
||||||
parameterStub,
|
|
||||||
ModifierMaskUtils.computeMask { false },
|
|
||||||
KtStubElementTypes.MODIFIER_LIST
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun createTypeParameterListStub(
|
fun createTypeParameterListStub(
|
||||||
parent: StubElement<out PsiElement>,
|
parent: StubElement<out PsiElement>,
|
||||||
typeParameterProtoList: List<ProtoBuf.TypeParameter>
|
typeParameterProtoList: List<ProtoBuf.TypeParameter>
|
||||||
|
|||||||
+8
@@ -262,6 +262,14 @@ fun createModifierListStub(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun createEmptyModifierListStub(parent: KotlinStubBaseImpl<*>): KotlinModifierListStubImpl {
|
||||||
|
return KotlinModifierListStubImpl(
|
||||||
|
parent,
|
||||||
|
ModifierMaskUtils.computeMask { false },
|
||||||
|
KtStubElementTypes.MODIFIER_LIST
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fun createAnnotationStubs(annotationIds: List<ClassId>, parent: KotlinStubBaseImpl<*>) {
|
fun createAnnotationStubs(annotationIds: List<ClassId>, parent: KotlinStubBaseImpl<*>) {
|
||||||
return createTargetedAnnotationStubs(annotationIds.map { ClassIdWithTarget(it, null) }, parent)
|
return createTargetedAnnotationStubs(annotationIds.map { ClassIdWithTarget(it, null) }, parent)
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-7
@@ -77,13 +77,19 @@ public fun buildDecompiledText(
|
|||||||
if (descriptor is MissingDependencyErrorClass) {
|
if (descriptor is MissingDependencyErrorClass) {
|
||||||
throw IllegalStateException("${descriptor.javaClass.getSimpleName()} cannot be rendered. FqName: ${descriptor.fullFqName}")
|
throw IllegalStateException("${descriptor.javaClass.getSimpleName()} cannot be rendered. FqName: ${descriptor.fullFqName}")
|
||||||
}
|
}
|
||||||
val startOffset = builder.length()
|
val startOffset = builder.length
|
||||||
val header = if (isEnumEntry(descriptor))
|
if (isEnumEntry(descriptor)) {
|
||||||
descriptor.name.asString() + if (lastEnumEntry!!) ";" else ","
|
for (annotation in descriptor.annotations) {
|
||||||
else
|
builder.append(descriptorRenderer.renderAnnotation(annotation))
|
||||||
descriptorRenderer.render(descriptor).replace("= ...", DECOMPILED_COMMENT_FOR_PARAMETER)
|
builder.append(" ")
|
||||||
builder.append(header)
|
}
|
||||||
var endOffset = builder.length()
|
builder.append(descriptor.name.asString())
|
||||||
|
builder.append(if (lastEnumEntry!!) ";" else ",")
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
builder.append(descriptorRenderer.render(descriptor).replace("= ...", DECOMPILED_COMMENT_FOR_PARAMETER))
|
||||||
|
}
|
||||||
|
var endOffset = builder.length
|
||||||
|
|
||||||
if (descriptor is CallableDescriptor) {
|
if (descriptor is CallableDescriptor) {
|
||||||
//NOTE: assuming that only return types can be flexible
|
//NOTE: assuming that only return types can be flexible
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
// IntelliJ API Decompiler stub source generated from a class file
|
||||||
|
// Implementation of methods is not available
|
||||||
|
|
||||||
|
package test
|
||||||
|
|
||||||
|
public final enum class AnnotatedEnumEntry private constructor() : kotlin.Enum<test.AnnotatedEnumEntry> {
|
||||||
|
Entry1,
|
||||||
|
|
||||||
|
@dependency.A @dependency.B Entry2,
|
||||||
|
|
||||||
|
@dependency.A Entry3;
|
||||||
|
}
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
import dependency.*
|
||||||
|
|
||||||
|
enum class AnnotatedEnumEntry {
|
||||||
|
Entry1,
|
||||||
|
@A("2") @B(2) Entry2,
|
||||||
|
@A("3") Entry3
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package dependency
|
||||||
|
|
||||||
|
@Target(AnnotationTarget.FIELD)
|
||||||
|
annotation class A(val s: String)
|
||||||
|
|
||||||
|
@Target(AnnotationTarget.FIELD)
|
||||||
|
annotation class B(val i: Int)
|
||||||
@@ -22,6 +22,8 @@
|
|||||||
|
|
||||||
class Nested @a private @b(E.E1) @b(E.E2) constructor()
|
class Nested @a private @b(E.E1) @b(E.E2) constructor()
|
||||||
|
|
||||||
|
enum class En { Entry1, @a @b(E.E2) Entry2, @a @c Entry3 }
|
||||||
|
|
||||||
fun types(param: @a @b(E.E1) LongRange): @a @b(E.E2) Unit {}
|
fun types(param: @a @b(E.E1) LongRange): @a @b(E.E2) Unit {}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,4 +38,9 @@ annotation class a
|
|||||||
@Repeatable
|
@Repeatable
|
||||||
annotation class b(val e: E)
|
annotation class b(val e: E)
|
||||||
|
|
||||||
enum class E { E1, E2 }
|
@Target(AnnotationTarget.PROPERTY, AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.FUNCTION,
|
||||||
|
AnnotationTarget.CONSTRUCTOR, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER,
|
||||||
|
AnnotationTarget.TYPE, AnnotationTarget.CLASS)
|
||||||
|
annotation class c
|
||||||
|
|
||||||
|
enum class E { E1, E2 }
|
||||||
|
|||||||
@@ -172,6 +172,46 @@ PsiJetFileStubImpl[package=]
|
|||||||
USER_TYPE:[isAbsoluteInRootPackage=false]
|
USER_TYPE:[isAbsoluteInRootPackage=false]
|
||||||
REFERENCE_EXPRESSION:[referencedName=kotlin]
|
REFERENCE_EXPRESSION:[referencedName=kotlin]
|
||||||
REFERENCE_EXPRESSION:[referencedName=Unit]
|
REFERENCE_EXPRESSION:[referencedName=Unit]
|
||||||
|
CLASS:[fqName=Annotations.En, isEnumEntry=false, isInterface=false, isLocal=false, isTopLevel=false, name=En, superNames=[Enum]]
|
||||||
|
MODIFIER_LIST:[enum public final]
|
||||||
|
PRIMARY_CONSTRUCTOR:
|
||||||
|
MODIFIER_LIST:[private]
|
||||||
|
VALUE_PARAMETER_LIST:
|
||||||
|
SUPER_TYPE_LIST:
|
||||||
|
SUPER_TYPE_ENTRY:
|
||||||
|
TYPE_REFERENCE:
|
||||||
|
USER_TYPE:[isAbsoluteInRootPackage=false]
|
||||||
|
USER_TYPE:[isAbsoluteInRootPackage=false]
|
||||||
|
REFERENCE_EXPRESSION:[referencedName=kotlin]
|
||||||
|
REFERENCE_EXPRESSION:[referencedName=Enum]
|
||||||
|
TYPE_ARGUMENT_LIST:
|
||||||
|
TYPE_PROJECTION:[projectionKind=NONE]
|
||||||
|
TYPE_REFERENCE:
|
||||||
|
USER_TYPE:[isAbsoluteInRootPackage=false]
|
||||||
|
USER_TYPE:[isAbsoluteInRootPackage=false]
|
||||||
|
REFERENCE_EXPRESSION:[referencedName=Annotations]
|
||||||
|
REFERENCE_EXPRESSION:[referencedName=En]
|
||||||
|
CLASS_BODY:
|
||||||
|
ENUM_ENTRY:[fqName=Annotations.En.Entry1, isEnumEntry=true, isInterface=false, isLocal=false, isTopLevel=false, name=Entry1, superNames=[]]
|
||||||
|
ENUM_ENTRY:[fqName=Annotations.En.Entry2, isEnumEntry=true, isInterface=false, isLocal=false, isTopLevel=false, name=Entry2, superNames=[]]
|
||||||
|
MODIFIER_LIST:[]
|
||||||
|
ANNOTATION_ENTRY:[hasValueArguments=false, shortName=a]
|
||||||
|
CONSTRUCTOR_CALLEE:
|
||||||
|
TYPE_REFERENCE:
|
||||||
|
USER_TYPE:[isAbsoluteInRootPackage=false]
|
||||||
|
REFERENCE_EXPRESSION:[referencedName=a]
|
||||||
|
ENUM_ENTRY:[fqName=Annotations.En.Entry3, isEnumEntry=true, isInterface=false, isLocal=false, isTopLevel=false, name=Entry3, superNames=[]]
|
||||||
|
MODIFIER_LIST:[]
|
||||||
|
ANNOTATION_ENTRY:[hasValueArguments=false, shortName=a]
|
||||||
|
CONSTRUCTOR_CALLEE:
|
||||||
|
TYPE_REFERENCE:
|
||||||
|
USER_TYPE:[isAbsoluteInRootPackage=false]
|
||||||
|
REFERENCE_EXPRESSION:[referencedName=a]
|
||||||
|
ANNOTATION_ENTRY:[hasValueArguments=false, shortName=c]
|
||||||
|
CONSTRUCTOR_CALLEE:
|
||||||
|
TYPE_REFERENCE:
|
||||||
|
USER_TYPE:[isAbsoluteInRootPackage=false]
|
||||||
|
REFERENCE_EXPRESSION:[referencedName=c]
|
||||||
CLASS:[fqName=Annotations.Nested, isEnumEntry=false, isInterface=false, isLocal=false, isTopLevel=false, name=Nested, superNames=[]]
|
CLASS:[fqName=Annotations.Nested, isEnumEntry=false, isInterface=false, isLocal=false, isTopLevel=false, name=Nested, superNames=[]]
|
||||||
MODIFIER_LIST:[public final]
|
MODIFIER_LIST:[public final]
|
||||||
PRIMARY_CONSTRUCTOR:
|
PRIMARY_CONSTRUCTOR:
|
||||||
|
|||||||
+6
@@ -65,6 +65,12 @@ public class CommonDecompiledTextFromJsMetadataTestGenerated extends AbstractCom
|
|||||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/decompiler/decompiledText"), Pattern.compile("^([^\\.]+)$"), true);
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/decompiler/decompiledText"), Pattern.compile("^([^\\.]+)$"), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("AnnotatedEnumEntry")
|
||||||
|
public void testAnnotatedEnumEntry() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/decompiler/decompiledText/AnnotatedEnumEntry/");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("Annotations")
|
@TestMetadata("Annotations")
|
||||||
public void testAnnotations() throws Exception {
|
public void testAnnotations() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/decompiler/decompiledText/Annotations/");
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/decompiler/decompiledText/Annotations/");
|
||||||
|
|||||||
+6
@@ -35,6 +35,12 @@ public class CommonDecompiledTextTestGenerated extends AbstractCommonDecompiledT
|
|||||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/decompiler/decompiledText"), Pattern.compile("^([^\\.]+)$"), true);
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/decompiler/decompiledText"), Pattern.compile("^([^\\.]+)$"), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("AnnotatedEnumEntry")
|
||||||
|
public void testAnnotatedEnumEntry() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/decompiler/decompiledText/AnnotatedEnumEntry/");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("Annotations")
|
@TestMetadata("Annotations")
|
||||||
public void testAnnotations() throws Exception {
|
public void testAnnotations() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/decompiler/decompiledText/Annotations/");
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/decompiler/decompiledText/Annotations/");
|
||||||
|
|||||||
Reference in New Issue
Block a user