Retrieve receiver annotation to stubs from compiled code (KT-19209)

#KT-19209 Fixed
This commit is contained in:
Nikolay Krasko
2017-07-27 21:08:53 +03:00
parent 8b149db0ec
commit 99555fa843
9 changed files with 257 additions and 16 deletions
@@ -28,7 +28,7 @@ object KotlinStubVersions {
// Binary stub version should be increased if stub format (org.jetbrains.kotlin.psi.stubs.impl) is changed
// or changes are made to the core stub building code (org.jetbrains.kotlin.idea.decompiler.stubBuilder).
// Increasing this version will lead to reindexing of all binary files that are potentially kotlin binaries (including all class files).
private const val BINARY_STUB_VERSION = 60
private const val BINARY_STUB_VERSION = 61
// Classfile stub version should be increased if changes are made to classfile stub building subsystem (org.jetbrains.kotlin.idea.decompiler.classFile)
// Increasing this version will lead to reindexing of all classfiles.
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.idea.decompiler.stubBuilder
import com.intellij.psi.PsiElement
import com.intellij.psi.stubs.StubElement
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.idea.decompiler.stubBuilder.flags.*
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes
@@ -104,11 +105,13 @@ abstract class CallableClsStubBuilder(
}
abstract val receiverType: ProtoBuf.Type?
abstract val receiverAnnotations: List<ClassIdWithTarget>
abstract val returnType: ProtoBuf.Type?
private fun createReceiverTypeReferenceStub() {
receiverType?.let {
typeStubBuilder.createTypeReferenceStub(callableStub, it)
typeStubBuilder.createTypeReferenceStub(callableStub, it, this::receiverAnnotations)
}
}
@@ -134,6 +137,13 @@ private class FunctionClsStubBuilder(
override val receiverType: ProtoBuf.Type?
get() = functionProto.receiverType(c.typeTable)
override val receiverAnnotations: List<ClassIdWithTarget>
get() {
return c.components.annotationLoader
.loadExtensionReceiverParameterAnnotations(protoContainer, functionProto, AnnotatedCallableKind.FUNCTION)
.map { ClassIdWithTarget(it, AnnotationUseSiteTarget.RECEIVER) }
}
override val returnType: ProtoBuf.Type?
get() = functionProto.returnType(c.typeTable)
@@ -181,6 +191,13 @@ private class PropertyClsStubBuilder(
override val receiverType: ProtoBuf.Type?
get() = propertyProto.receiverType(c.typeTable)
override val receiverAnnotations: List<ClassIdWithTarget>
get() {
return c.components.annotationLoader
.loadExtensionReceiverParameterAnnotations(protoContainer, propertyProto, AnnotatedCallableKind.PROPERTY_GETTER)
.map { ClassIdWithTarget(it, AnnotationUseSiteTarget.RECEIVER) }
}
override val returnType: ProtoBuf.Type?
get() = propertyProto.returnType(c.typeTable)
@@ -229,6 +246,9 @@ private class ConstructorClsStubBuilder(
override val receiverType: ProtoBuf.Type?
get() = null
override val receiverAnnotations: List<ClassIdWithTarget>
get() = emptyList()
override val returnType: ProtoBuf.Type?
get() = null
@@ -44,9 +44,8 @@ import java.util.*
private val ANNOTATIONS_NOT_LOADED_FOR_TYPES = setOf(KotlinBuiltIns.FQ_NAMES.parameterName)
class TypeClsStubBuilder(private val c: ClsStubBuilderContext) {
fun createTypeReferenceStub(parent: StubElement<out PsiElement>, type: Type) {
if (type.hasAbbreviatedType()) return createTypeReferenceStub(parent, type.abbreviatedType)
fun createTypeReferenceStub(parent: StubElement<out PsiElement>, type: Type, additionalAnnotations: () -> List<ClassIdWithTarget> = { emptyList() }) {
if (type.hasAbbreviatedType()) return createTypeReferenceStub(parent, type.abbreviatedType, additionalAnnotations)
val typeReference = KotlinPlaceHolderStubImpl<KtTypeReference>(parent, KtStubElementTypes.TYPE_REFERENCE)
val annotations = c.components.annotationLoader.loadTypeAnnotations(type, c.nameResolver).filterNot {
@@ -54,13 +53,15 @@ class TypeClsStubBuilder(private val c: ClsStubBuilderContext) {
isTopLevelClass && it.asSingleFqName() in ANNOTATIONS_NOT_LOADED_FOR_TYPES
}
val allAnnotations = additionalAnnotations() + annotations.map { ClassIdWithTarget(it, null) }
when {
type.hasClassName() || type.hasTypeAliasName() ->
createClassReferenceTypeStub(typeReference, type, annotations)
createClassReferenceTypeStub(typeReference, type, allAnnotations)
type.hasTypeParameter() ->
createTypeParameterStub(typeReference, type, c.typeParameters[type.typeParameter], annotations)
createTypeParameterStub(typeReference, type, c.typeParameters[type.typeParameter], allAnnotations)
type.hasTypeParameterName() ->
createTypeParameterStub(typeReference, type, c.nameResolver.getName(type.typeParameterName), annotations)
createTypeParameterStub(typeReference, type, c.nameResolver.getName(type.typeParameterName), allAnnotations)
}
}
@@ -68,12 +69,12 @@ class TypeClsStubBuilder(private val c: ClsStubBuilderContext) {
if (type.nullable) KotlinPlaceHolderStubImpl<KtNullableType>(parent, KtStubElementTypes.NULLABLE_TYPE)
else parent
private fun createTypeParameterStub(parent: KotlinStubBaseImpl<*>, type: Type, name: Name, annotations: List<ClassId>) {
private fun createTypeParameterStub(parent: KotlinStubBaseImpl<*>, type: Type, name: Name, annotations: List<ClassIdWithTarget>) {
createTypeAnnotationStubs(parent, type, annotations)
createStubForTypeName(ClassId.topLevel(FqName.topLevel(name)), nullableTypeParent(parent, type))
}
private fun createClassReferenceTypeStub(parent: KotlinStubBaseImpl<*>, type: Type, annotations: List<ClassId>) {
private fun createClassReferenceTypeStub(parent: KotlinStubBaseImpl<*>, type: Type, annotations: List<ClassIdWithTarget>) {
if (type.hasFlexibleTypeCapabilitiesId()) {
val id = c.nameResolver.getString(type.flexibleTypeCapabilitiesId)
@@ -92,7 +93,7 @@ class TypeClsStubBuilder(private val c: ClsStubBuilderContext) {
&& type.argumentList.none { it.projection == Projection.STAR }
if (shouldBuildAsFunctionType) {
val (extensionAnnotations, notExtensionAnnotations) =
annotations.partition { it.asSingleFqName() == KotlinBuiltIns.FQ_NAMES.extensionFunctionType }
annotations.partition { it.classId.asSingleFqName() == KotlinBuiltIns.FQ_NAMES.extensionFunctionType }
createTypeAnnotationStubs(parent, type, notExtensionAnnotations)
@@ -112,12 +113,12 @@ class TypeClsStubBuilder(private val c: ClsStubBuilderContext) {
}
}
private fun createTypeAnnotationStubs(parent: KotlinStubBaseImpl<*>, type: Type, annotations: List<ClassId>) {
private fun createTypeAnnotationStubs(parent: KotlinStubBaseImpl<*>, type: Type, annotations: List<ClassIdWithTarget>) {
val typeModifiers = getTypeModifiersAsWritten(type)
if (annotations.isEmpty() && typeModifiers.isEmpty()) return
val typeModifiersMask = ModifierMaskUtils.computeMask { it in typeModifiers }
val modifiersList = KotlinModifierListStubImpl(parent, typeModifiersMask, KtStubElementTypes.MODIFIER_LIST)
createAnnotationStubs(annotations, modifiersList)
createTargetedAnnotationStubs(annotations, modifiersList)
}
private fun getTypeModifiersAsWritten(type: Type): Set<KtModifierKeywordToken> {
@@ -28,11 +28,31 @@
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 @receiver:a Int.foo() {}
val @receiver:a Int.receiverField: String? get() = null
@get: a
val getterField : String? = null
@set: a
var setterField : String? = null
@field: a
val ownField : String? = null
@setparam:a
var setParam: String? = null
@delegate:a
val deleage by lazy { 12 }
class ClassWithConstructor(@param: a val b: Int)
}
@Target(AnnotationTarget.PROPERTY, AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.FUNCTION,
AnnotationTarget.CONSTRUCTOR, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER,
AnnotationTarget.TYPE, AnnotationTarget.CLASS, AnnotationTarget.TYPE_PARAMETER)
AnnotationTarget.TYPE, AnnotationTarget.CLASS, AnnotationTarget.TYPE_PARAMETER, AnnotationTarget.FIELD)
annotation class a
@Target(AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION, AnnotationTarget.CLASS,
@@ -88,6 +88,27 @@ PsiJetFileStubImpl[package=]
USER_TYPE
REFERENCE_EXPRESSION[referencedName=kotlin]
REFERENCE_EXPRESSION[referencedName=Int]
PROPERTY[fqName=Annotations.deleage, hasDelegate=false, hasDelegateExpression=false, hasInitializer=false, hasReturnTypeRef=true, isExtension=false, isTopLevel=false, isVar=false, name=deleage]
MODIFIER_LIST[public final]
ANNOTATION_ENTRY[hasValueArguments=false, shortName=a]
ANNOTATION_TARGET[useSiteTarget=PROPERTY_DELEGATE_FIELD]
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION[referencedName=a]
TYPE_REFERENCE
USER_TYPE
USER_TYPE
REFERENCE_EXPRESSION[referencedName=kotlin]
REFERENCE_EXPRESSION[referencedName=Int]
PROPERTY[fqName=Annotations.getterField, hasDelegate=false, hasDelegateExpression=false, hasInitializer=false, hasReturnTypeRef=true, isExtension=false, isTopLevel=false, isVar=false, name=getterField]
MODIFIER_LIST[public final]
TYPE_REFERENCE
NULLABLE_TYPE
USER_TYPE
USER_TYPE
REFERENCE_EXPRESSION[referencedName=kotlin]
REFERENCE_EXPRESSION[referencedName=String]
PROPERTY[fqName=Annotations.hasValueArguments, hasDelegate=false, hasDelegateExpression=false, hasInitializer=false, hasReturnTypeRef=true, isExtension=false, isTopLevel=false, isVar=false, name=hasValueArguments]
MODIFIER_LIST[public final]
ANNOTATION_ENTRY[hasValueArguments=false, shortName=a]
@@ -100,6 +121,36 @@ PsiJetFileStubImpl[package=]
USER_TYPE
REFERENCE_EXPRESSION[referencedName=kotlin]
REFERENCE_EXPRESSION[referencedName=Int]
PROPERTY[fqName=Annotations.ownField, hasDelegate=false, hasDelegateExpression=false, hasInitializer=false, hasReturnTypeRef=true, isExtension=false, isTopLevel=false, isVar=false, name=ownField]
MODIFIER_LIST[public final]
ANNOTATION_ENTRY[hasValueArguments=false, shortName=a]
ANNOTATION_TARGET[useSiteTarget=FIELD]
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION[referencedName=a]
TYPE_REFERENCE
NULLABLE_TYPE
USER_TYPE
USER_TYPE
REFERENCE_EXPRESSION[referencedName=kotlin]
REFERENCE_EXPRESSION[referencedName=String]
PROPERTY[fqName=Annotations.setParam, hasDelegate=false, hasDelegateExpression=false, hasInitializer=false, hasReturnTypeRef=true, isExtension=false, isTopLevel=false, isVar=true, name=setParam]
MODIFIER_LIST[public final]
TYPE_REFERENCE
NULLABLE_TYPE
USER_TYPE
USER_TYPE
REFERENCE_EXPRESSION[referencedName=kotlin]
REFERENCE_EXPRESSION[referencedName=String]
PROPERTY[fqName=Annotations.setterField, hasDelegate=false, hasDelegateExpression=false, hasInitializer=false, hasReturnTypeRef=true, isExtension=false, isTopLevel=false, isVar=true, name=setterField]
MODIFIER_LIST[public final]
TYPE_REFERENCE
NULLABLE_TYPE
USER_TYPE
USER_TYPE
REFERENCE_EXPRESSION[referencedName=kotlin]
REFERENCE_EXPRESSION[referencedName=String]
PROPERTY[fqName=Annotations.withCustomAccessors, hasDelegate=false, hasDelegateExpression=false, hasInitializer=false, hasReturnTypeRef=true, isExtension=false, isTopLevel=false, isVar=true, name=withCustomAccessors]
MODIFIER_LIST[public final]
TYPE_REFERENCE
@@ -107,6 +158,26 @@ PsiJetFileStubImpl[package=]
USER_TYPE
REFERENCE_EXPRESSION[referencedName=kotlin]
REFERENCE_EXPRESSION[referencedName=Int]
PROPERTY[fqName=Annotations.receiverField, hasDelegate=false, hasDelegateExpression=false, hasInitializer=false, hasReturnTypeRef=true, isExtension=true, isTopLevel=false, isVar=false, name=receiverField]
MODIFIER_LIST[public final]
TYPE_REFERENCE
MODIFIER_LIST[]
ANNOTATION_ENTRY[hasValueArguments=false, shortName=a]
ANNOTATION_TARGET[useSiteTarget=RECEIVER]
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION[referencedName=a]
USER_TYPE
USER_TYPE
REFERENCE_EXPRESSION[referencedName=kotlin]
REFERENCE_EXPRESSION[referencedName=Int]
TYPE_REFERENCE
NULLABLE_TYPE
USER_TYPE
USER_TYPE
REFERENCE_EXPRESSION[referencedName=kotlin]
REFERENCE_EXPRESSION[referencedName=String]
FUN[fqName=Annotations.annotationWithVararg, hasBlockBody=true, hasBody=true, hasTypeParameterListBeforeFunctionName=false, isExtension=false, isTopLevel=false, name=annotationWithVararg]
MODIFIER_LIST[private final]
VALUE_PARAMETER_LIST
@@ -224,6 +295,51 @@ PsiJetFileStubImpl[package=]
USER_TYPE
REFERENCE_EXPRESSION[referencedName=kotlin]
REFERENCE_EXPRESSION[referencedName=Unit]
FUN[fqName=Annotations.foo, hasBlockBody=true, hasBody=true, hasTypeParameterListBeforeFunctionName=false, isExtension=true, isTopLevel=false, name=foo]
MODIFIER_LIST[public final]
TYPE_REFERENCE
MODIFIER_LIST[]
ANNOTATION_ENTRY[hasValueArguments=false, shortName=a]
ANNOTATION_TARGET[useSiteTarget=RECEIVER]
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION[referencedName=a]
USER_TYPE
USER_TYPE
REFERENCE_EXPRESSION[referencedName=kotlin]
REFERENCE_EXPRESSION[referencedName=Int]
VALUE_PARAMETER_LIST
TYPE_REFERENCE
USER_TYPE
USER_TYPE
REFERENCE_EXPRESSION[referencedName=kotlin]
REFERENCE_EXPRESSION[referencedName=Unit]
CLASS[fqName=Annotations.ClassWithConstructor, isEnumEntry=false, isInterface=false, isLocal=false, isTopLevel=false, name=ClassWithConstructor, superNames=[]]
MODIFIER_LIST[public final]
PRIMARY_CONSTRUCTOR
MODIFIER_LIST[public]
VALUE_PARAMETER_LIST
VALUE_PARAMETER[fqName=null, hasDefaultValue=false, hasValOrVar=false, isMutable=false, name=b]
MODIFIER_LIST[]
ANNOTATION_ENTRY[hasValueArguments=false, shortName=a]
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION[referencedName=a]
TYPE_REFERENCE
USER_TYPE
USER_TYPE
REFERENCE_EXPRESSION[referencedName=kotlin]
REFERENCE_EXPRESSION[referencedName=Int]
CLASS_BODY
PROPERTY[fqName=Annotations.ClassWithConstructor.b, hasDelegate=false, hasDelegateExpression=false, hasInitializer=false, hasReturnTypeRef=true, isExtension=false, isTopLevel=false, isVar=false, name=b]
MODIFIER_LIST[public final]
TYPE_REFERENCE
USER_TYPE
USER_TYPE
REFERENCE_EXPRESSION[referencedName=kotlin]
REFERENCE_EXPRESSION[referencedName=Int]
CLASS[fqName=Annotations.En, isEnumEntry=false, isInterface=false, isLocal=false, isTopLevel=false, name=En, superNames=[Enum]]
MODIFIER_LIST[enum public final]
PRIMARY_CONSTRUCTOR
@@ -20,9 +20,11 @@ public class AnnotationsOnNullableTypes {
val lambdaReceiver: (@A C?).() -> C = null!!
val lambdaTypeWithNullableReceiver: @A C?.() -> C = null!!
fun @receiver:A C?.functionWithAnnotatedReceiver() {}
}
@Target(AnnotationTarget.TYPE, AnnotationTarget.TYPE_PARAMETER)
@Target(AnnotationTarget.TYPE, AnnotationTarget.TYPE_PARAMETER, AnnotationTarget.VALUE_PARAMETER)
annotation class A
interface B<T>
@@ -183,6 +183,25 @@ PsiJetFileStubImpl[package=]
NULLABLE_TYPE
USER_TYPE
REFERENCE_EXPRESSION[referencedName=C]
FUN[fqName=AnnotationsOnNullableTypes.functionWithAnnotatedReceiver, hasBlockBody=true, hasBody=true, hasTypeParameterListBeforeFunctionName=false, isExtension=true, isTopLevel=false, name=functionWithAnnotatedReceiver]
MODIFIER_LIST[public final]
TYPE_REFERENCE
MODIFIER_LIST[]
ANNOTATION_ENTRY[hasValueArguments=false, shortName=A]
ANNOTATION_TARGET[useSiteTarget=RECEIVER]
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION[referencedName=A]
NULLABLE_TYPE
USER_TYPE
REFERENCE_EXPRESSION[referencedName=C]
VALUE_PARAMETER_LIST
TYPE_REFERENCE
USER_TYPE
USER_TYPE
REFERENCE_EXPRESSION[referencedName=kotlin]
REFERENCE_EXPRESSION[referencedName=Unit]
FUN[fqName=AnnotationsOnNullableTypes.receiverArgument, hasBlockBody=true, hasBody=true, hasTypeParameterListBeforeFunctionName=false, isExtension=true, isTopLevel=false, name=receiverArgument]
MODIFIER_LIST[public final]
TYPE_REFERENCE
@@ -3,12 +3,16 @@ package test
class SuspendLambda {
fun <T> (suspend () -> T).createCoroutine(completion: Continuation<T>) {}
fun <R, T> (suspend R.() -> T).createCoroutine(receiver: R, completion: Continuation<T>) {}
fun <R, T> (suspend @receiver:A R.() -> T).createCoroutineAnother() {}
fun <T> testCoroutine(f: suspend (Int) -> T?) {}
fun <T> testCoroutineWithAnnotation(f: suspend (Int) -> @A T?) {}
}
@Target(AnnotationTarget.TYPE, AnnotationTarget.TYPE_PARAMETER)
@Target(AnnotationTarget.TYPE, AnnotationTarget.TYPE_PARAMETER, AnnotationTarget.VALUE_PARAMETER)
annotation class A
class Continuation<T> {}
@@ -94,3 +94,62 @@ PsiJetFileStubImpl[package=test]
USER_TYPE
REFERENCE_EXPRESSION[referencedName=kotlin]
REFERENCE_EXPRESSION[referencedName=Unit]
FUN[fqName=test.SuspendLambda.createCoroutine, hasBlockBody=true, hasBody=true, hasTypeParameterListBeforeFunctionName=true, isExtension=true, isTopLevel=false, name=createCoroutine]
MODIFIER_LIST[public final]
TYPE_PARAMETER_LIST
TYPE_PARAMETER[fqName=null, isInVariance=false, isOutVariance=false, name=R]
TYPE_PARAMETER[fqName=null, isInVariance=false, isOutVariance=false, name=T]
TYPE_REFERENCE
MODIFIER_LIST[suspend]
FUNCTION_TYPE
FUNCTION_TYPE_RECEIVER
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION[referencedName=R]
VALUE_PARAMETER_LIST
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION[referencedName=T]
VALUE_PARAMETER_LIST
VALUE_PARAMETER[fqName=null, hasDefaultValue=false, hasValOrVar=false, isMutable=false, name=receiver]
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION[referencedName=R]
VALUE_PARAMETER[fqName=null, hasDefaultValue=false, hasValOrVar=false, isMutable=false, name=completion]
TYPE_REFERENCE
USER_TYPE
USER_TYPE
REFERENCE_EXPRESSION[referencedName=test]
REFERENCE_EXPRESSION[referencedName=Continuation]
TYPE_ARGUMENT_LIST
TYPE_PROJECTION[projectionKind=NONE]
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION[referencedName=T]
TYPE_REFERENCE
USER_TYPE
USER_TYPE
REFERENCE_EXPRESSION[referencedName=kotlin]
REFERENCE_EXPRESSION[referencedName=Unit]
FUN[fqName=test.SuspendLambda.createCoroutineAnother, hasBlockBody=true, hasBody=true, hasTypeParameterListBeforeFunctionName=true, isExtension=true, isTopLevel=false, name=createCoroutineAnother]
MODIFIER_LIST[public final]
TYPE_PARAMETER_LIST
TYPE_PARAMETER[fqName=null, isInVariance=false, isOutVariance=false, name=R]
TYPE_PARAMETER[fqName=null, isInVariance=false, isOutVariance=false, name=T]
TYPE_REFERENCE
MODIFIER_LIST[suspend]
FUNCTION_TYPE
FUNCTION_TYPE_RECEIVER
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION[referencedName=R]
VALUE_PARAMETER_LIST
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION[referencedName=T]
VALUE_PARAMETER_LIST
TYPE_REFERENCE
USER_TYPE
USER_TYPE
REFERENCE_EXPRESSION[referencedName=kotlin]
REFERENCE_EXPRESSION[referencedName=Unit]