Fix stub-psi mismatch exception on restoring annotation for nullable types
(cherry picked from commit 1aa37f11258dde289a9f7cb700294a038168fbdc) Conflicts: compiler/frontend/src/org/jetbrains/kotlin/psi/stubs/KotlinStubVersions.kt idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/TypeClsStubBuilder.kt
This commit is contained in:
@@ -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 = 53
|
||||
private const val BINARY_STUB_VERSION = 54
|
||||
|
||||
// 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.
|
||||
|
||||
+20
-15
@@ -55,28 +55,31 @@ class TypeClsStubBuilder(private val c: ClsStubBuilderContext) {
|
||||
isTopLevelClass && it.asSingleFqName() in ANNOTATIONS_NOT_LOADED_FOR_TYPES
|
||||
}
|
||||
|
||||
val effectiveParent =
|
||||
if (type.nullable) KotlinPlaceHolderStubImpl<KtNullableType>(typeReference, KtStubElementTypes.NULLABLE_TYPE)
|
||||
else typeReference
|
||||
|
||||
fun createTypeParameterStub(name: Name) {
|
||||
createTypeAnnotationStubs(effectiveParent, annotations)
|
||||
createStubForTypeName(ClassId.topLevel(FqName.topLevel(name)), effectiveParent)
|
||||
}
|
||||
|
||||
when {
|
||||
type.hasClassName() || type.hasTypeAliasName() -> createClassReferenceTypeStub(effectiveParent, type, annotations)
|
||||
type.hasTypeParameter() -> createTypeParameterStub(c.typeParameters[type.typeParameter])
|
||||
type.hasTypeParameterName() -> createTypeParameterStub(c.nameResolver.getName(type.typeParameterName))
|
||||
type.hasClassName() || type.hasTypeAliasName() ->
|
||||
createClassReferenceTypeStub(typeReference, type, annotations)
|
||||
type.hasTypeParameter() ->
|
||||
createTypeParameterStub(typeReference, type, c.typeParameters[type.typeParameter], annotations)
|
||||
type.hasTypeParameterName() ->
|
||||
createTypeParameterStub(typeReference, type, c.nameResolver.getName(type.typeParameterName), annotations)
|
||||
}
|
||||
}
|
||||
|
||||
private fun nullableTypeParent(parent: KotlinStubBaseImpl<*>, type: Type): KotlinStubBaseImpl<*> =
|
||||
if (type.nullable) KotlinPlaceHolderStubImpl<KtNullableType>(parent, KtStubElementTypes.NULLABLE_TYPE)
|
||||
else parent
|
||||
|
||||
private fun createTypeParameterStub(parent: KotlinStubBaseImpl<*>, type: Type, name: Name, annotations: List<ClassId>) {
|
||||
createTypeAnnotationStubs(parent, annotations)
|
||||
createStubForTypeName(ClassId.topLevel(FqName.topLevel(name)), nullableTypeParent(parent, type))
|
||||
}
|
||||
|
||||
private fun createClassReferenceTypeStub(parent: KotlinStubBaseImpl<*>, type: Type, annotations: List<ClassId>) {
|
||||
if (type.hasFlexibleTypeCapabilitiesId()) {
|
||||
val id = c.nameResolver.getString(type.flexibleTypeCapabilitiesId)
|
||||
|
||||
if (id == DynamicTypeDeserializer.id) {
|
||||
KotlinPlaceHolderStubImpl<KtDynamicType>(parent, KtStubElementTypes.DYNAMIC_TYPE)
|
||||
KotlinPlaceHolderStubImpl<KtDynamicType>(nullableTypeParent(parent, type), KtStubElementTypes.DYNAMIC_TYPE)
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -92,13 +95,15 @@ class TypeClsStubBuilder(private val c: ClsStubBuilderContext) {
|
||||
val extension = annotations.any { annotation ->
|
||||
annotation.asSingleFqName() == KotlinBuiltIns.FQ_NAMES.extensionFunctionType
|
||||
}
|
||||
createFunctionTypeStub(parent, type, extension)
|
||||
createFunctionTypeStub(nullableTypeParent(parent, type), type, extension)
|
||||
return
|
||||
}
|
||||
|
||||
createTypeAnnotationStubs(parent, annotations)
|
||||
|
||||
val outerTypeChain = generateSequence(type) { it.outerType(c.typeTable) }.toList()
|
||||
|
||||
createStubForTypeName(classId, parent) {
|
||||
createStubForTypeName(classId, nullableTypeParent(parent, type)) {
|
||||
userTypeStub, index ->
|
||||
outerTypeChain.getOrNull(index)?.let { createTypeArgumentListStub(userTypeStub, it.argumentList) }
|
||||
}
|
||||
|
||||
Vendored
+27
@@ -0,0 +1,27 @@
|
||||
public class AnnotationsOnNullableTypes {
|
||||
fun B<@A C?>.receiverArgument() {}
|
||||
|
||||
fun parameter(a: @A C?) {}
|
||||
|
||||
fun parameterArgument(a: B<@A C?>) {}
|
||||
|
||||
fun returnValue(): @A C? = null
|
||||
|
||||
fun <T> returnTypeParameterValue(): @A T? = null
|
||||
|
||||
fun returnArgument(): B<@A C?> = null!!
|
||||
|
||||
val lambdaType: @A() (() -> C)? = null // TODO: Annotation is lost in stubs
|
||||
|
||||
val lambdaParameter: (@A C?) -> C = null!!
|
||||
|
||||
val lambdaReturnValue: () -> @A C? = null!!
|
||||
|
||||
val lambdaReceiver: @A C.() -> C = null!! // TODO: Annotation is lost in stubs
|
||||
}
|
||||
|
||||
@Target(AnnotationTarget.TYPE, AnnotationTarget.TYPE_PARAMETER)
|
||||
annotation class A
|
||||
|
||||
interface B<T>
|
||||
interface C
|
||||
Vendored
+168
@@ -0,0 +1,168 @@
|
||||
PsiJetFileStubImpl[package=]
|
||||
PACKAGE_DIRECTIVE
|
||||
IMPORT_LIST
|
||||
CLASS[fqName=AnnotationsOnNullableTypes, isEnumEntry=false, isInterface=false, isLocal=false, isTopLevel=true, name=AnnotationsOnNullableTypes, superNames=[]]
|
||||
MODIFIER_LIST[public final]
|
||||
PRIMARY_CONSTRUCTOR
|
||||
MODIFIER_LIST[public]
|
||||
VALUE_PARAMETER_LIST
|
||||
CLASS_BODY
|
||||
PROPERTY[fqName=AnnotationsOnNullableTypes.lambdaParameter, hasDelegate=false, hasDelegateExpression=false, hasInitializer=false, hasReturnTypeRef=true, isExtension=false, isTopLevel=false, isVar=false, name=lambdaParameter]
|
||||
MODIFIER_LIST[public final]
|
||||
TYPE_REFERENCE
|
||||
FUNCTION_TYPE
|
||||
VALUE_PARAMETER_LIST
|
||||
VALUE_PARAMETER[fqName=null, hasDefaultValue=false, hasValOrVar=false, isMutable=false, name=null]
|
||||
TYPE_REFERENCE
|
||||
NULLABLE_TYPE
|
||||
USER_TYPE
|
||||
REFERENCE_EXPRESSION[referencedName=C]
|
||||
TYPE_REFERENCE
|
||||
USER_TYPE
|
||||
REFERENCE_EXPRESSION[referencedName=C]
|
||||
PROPERTY[fqName=AnnotationsOnNullableTypes.lambdaReceiver, hasDelegate=false, hasDelegateExpression=false, hasInitializer=false, hasReturnTypeRef=true, isExtension=false, isTopLevel=false, isVar=false, name=lambdaReceiver]
|
||||
MODIFIER_LIST[public final]
|
||||
TYPE_REFERENCE
|
||||
FUNCTION_TYPE
|
||||
FUNCTION_TYPE_RECEIVER
|
||||
TYPE_REFERENCE
|
||||
ANNOTATION_ENTRY[hasValueArguments=false, shortName=A]
|
||||
CONSTRUCTOR_CALLEE
|
||||
TYPE_REFERENCE
|
||||
USER_TYPE
|
||||
REFERENCE_EXPRESSION[referencedName=A]
|
||||
USER_TYPE
|
||||
REFERENCE_EXPRESSION[referencedName=C]
|
||||
VALUE_PARAMETER_LIST
|
||||
TYPE_REFERENCE
|
||||
USER_TYPE
|
||||
REFERENCE_EXPRESSION[referencedName=C]
|
||||
PROPERTY[fqName=AnnotationsOnNullableTypes.lambdaReturnValue, hasDelegate=false, hasDelegateExpression=false, hasInitializer=false, hasReturnTypeRef=true, isExtension=false, isTopLevel=false, isVar=false, name=lambdaReturnValue]
|
||||
MODIFIER_LIST[public final]
|
||||
TYPE_REFERENCE
|
||||
FUNCTION_TYPE
|
||||
VALUE_PARAMETER_LIST
|
||||
TYPE_REFERENCE
|
||||
ANNOTATION_ENTRY[hasValueArguments=false, shortName=A]
|
||||
CONSTRUCTOR_CALLEE
|
||||
TYPE_REFERENCE
|
||||
USER_TYPE
|
||||
REFERENCE_EXPRESSION[referencedName=A]
|
||||
NULLABLE_TYPE
|
||||
USER_TYPE
|
||||
REFERENCE_EXPRESSION[referencedName=C]
|
||||
PROPERTY[fqName=AnnotationsOnNullableTypes.lambdaType, hasDelegate=false, hasDelegateExpression=false, hasInitializer=false, hasReturnTypeRef=true, isExtension=false, isTopLevel=false, isVar=false, name=lambdaType]
|
||||
MODIFIER_LIST[public final]
|
||||
TYPE_REFERENCE
|
||||
NULLABLE_TYPE
|
||||
FUNCTION_TYPE
|
||||
VALUE_PARAMETER_LIST
|
||||
TYPE_REFERENCE
|
||||
USER_TYPE
|
||||
REFERENCE_EXPRESSION[referencedName=C]
|
||||
FUN[fqName=AnnotationsOnNullableTypes.parameter, hasBlockBody=true, hasBody=true, hasTypeParameterListBeforeFunctionName=false, isExtension=false, isTopLevel=false, name=parameter]
|
||||
MODIFIER_LIST[public final]
|
||||
VALUE_PARAMETER_LIST
|
||||
VALUE_PARAMETER[fqName=null, hasDefaultValue=false, hasValOrVar=false, isMutable=false, name=a]
|
||||
TYPE_REFERENCE
|
||||
ANNOTATION_ENTRY[hasValueArguments=false, shortName=A]
|
||||
CONSTRUCTOR_CALLEE
|
||||
TYPE_REFERENCE
|
||||
USER_TYPE
|
||||
REFERENCE_EXPRESSION[referencedName=A]
|
||||
NULLABLE_TYPE
|
||||
USER_TYPE
|
||||
REFERENCE_EXPRESSION[referencedName=C]
|
||||
TYPE_REFERENCE
|
||||
USER_TYPE
|
||||
USER_TYPE
|
||||
REFERENCE_EXPRESSION[referencedName=kotlin]
|
||||
REFERENCE_EXPRESSION[referencedName=Unit]
|
||||
FUN[fqName=AnnotationsOnNullableTypes.parameterArgument, hasBlockBody=true, hasBody=true, hasTypeParameterListBeforeFunctionName=false, isExtension=false, isTopLevel=false, name=parameterArgument]
|
||||
MODIFIER_LIST[public final]
|
||||
VALUE_PARAMETER_LIST
|
||||
VALUE_PARAMETER[fqName=null, hasDefaultValue=false, hasValOrVar=false, isMutable=false, name=a]
|
||||
TYPE_REFERENCE
|
||||
USER_TYPE
|
||||
REFERENCE_EXPRESSION[referencedName=B]
|
||||
TYPE_ARGUMENT_LIST
|
||||
TYPE_PROJECTION[projectionKind=NONE]
|
||||
TYPE_REFERENCE
|
||||
ANNOTATION_ENTRY[hasValueArguments=false, shortName=A]
|
||||
CONSTRUCTOR_CALLEE
|
||||
TYPE_REFERENCE
|
||||
USER_TYPE
|
||||
REFERENCE_EXPRESSION[referencedName=A]
|
||||
NULLABLE_TYPE
|
||||
USER_TYPE
|
||||
REFERENCE_EXPRESSION[referencedName=C]
|
||||
TYPE_REFERENCE
|
||||
USER_TYPE
|
||||
USER_TYPE
|
||||
REFERENCE_EXPRESSION[referencedName=kotlin]
|
||||
REFERENCE_EXPRESSION[referencedName=Unit]
|
||||
FUN[fqName=AnnotationsOnNullableTypes.returnArgument, hasBlockBody=true, hasBody=true, hasTypeParameterListBeforeFunctionName=false, isExtension=false, isTopLevel=false, name=returnArgument]
|
||||
MODIFIER_LIST[public final]
|
||||
VALUE_PARAMETER_LIST
|
||||
TYPE_REFERENCE
|
||||
USER_TYPE
|
||||
REFERENCE_EXPRESSION[referencedName=B]
|
||||
TYPE_ARGUMENT_LIST
|
||||
TYPE_PROJECTION[projectionKind=NONE]
|
||||
TYPE_REFERENCE
|
||||
ANNOTATION_ENTRY[hasValueArguments=false, shortName=A]
|
||||
CONSTRUCTOR_CALLEE
|
||||
TYPE_REFERENCE
|
||||
USER_TYPE
|
||||
REFERENCE_EXPRESSION[referencedName=A]
|
||||
NULLABLE_TYPE
|
||||
USER_TYPE
|
||||
REFERENCE_EXPRESSION[referencedName=C]
|
||||
FUN[fqName=AnnotationsOnNullableTypes.returnTypeParameterValue, hasBlockBody=true, hasBody=true, hasTypeParameterListBeforeFunctionName=true, isExtension=false, isTopLevel=false, name=returnTypeParameterValue]
|
||||
MODIFIER_LIST[public final]
|
||||
TYPE_PARAMETER_LIST
|
||||
TYPE_PARAMETER[fqName=null, isInVariance=false, isOutVariance=false, name=T]
|
||||
VALUE_PARAMETER_LIST
|
||||
TYPE_REFERENCE
|
||||
ANNOTATION_ENTRY[hasValueArguments=false, shortName=A]
|
||||
CONSTRUCTOR_CALLEE
|
||||
TYPE_REFERENCE
|
||||
USER_TYPE
|
||||
REFERENCE_EXPRESSION[referencedName=A]
|
||||
NULLABLE_TYPE
|
||||
USER_TYPE
|
||||
REFERENCE_EXPRESSION[referencedName=T]
|
||||
FUN[fqName=AnnotationsOnNullableTypes.returnValue, hasBlockBody=true, hasBody=true, hasTypeParameterListBeforeFunctionName=false, isExtension=false, isTopLevel=false, name=returnValue]
|
||||
MODIFIER_LIST[public final]
|
||||
VALUE_PARAMETER_LIST
|
||||
TYPE_REFERENCE
|
||||
ANNOTATION_ENTRY[hasValueArguments=false, shortName=A]
|
||||
CONSTRUCTOR_CALLEE
|
||||
TYPE_REFERENCE
|
||||
USER_TYPE
|
||||
REFERENCE_EXPRESSION[referencedName=A]
|
||||
NULLABLE_TYPE
|
||||
USER_TYPE
|
||||
REFERENCE_EXPRESSION[referencedName=C]
|
||||
FUN[fqName=AnnotationsOnNullableTypes.receiverArgument, hasBlockBody=true, hasBody=true, hasTypeParameterListBeforeFunctionName=false, isExtension=true, isTopLevel=false, name=receiverArgument]
|
||||
MODIFIER_LIST[public final]
|
||||
TYPE_REFERENCE
|
||||
USER_TYPE
|
||||
REFERENCE_EXPRESSION[referencedName=B]
|
||||
TYPE_ARGUMENT_LIST
|
||||
TYPE_PROJECTION[projectionKind=NONE]
|
||||
TYPE_REFERENCE
|
||||
ANNOTATION_ENTRY[hasValueArguments=false, shortName=A]
|
||||
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]
|
||||
+28
@@ -4,3 +4,31 @@ PsiJetFileStubImpl[package=]
|
||||
PROPERTY[fqName=foo, hasDelegate=false, hasDelegateExpression=false, hasInitializer=false, hasReturnTypeRef=true, isExtension=false, isTopLevel=true, isVar=false, name=foo]
|
||||
TYPE_REFERENCE
|
||||
DYNAMIC_TYPE
|
||||
PROPERTY[fqName=foo_nullable, hasDelegate=false, hasDelegateExpression=false, hasInitializer=false, hasReturnTypeRef=true, isExtension=false, isTopLevel=true, isVar=false, name=foo_nullable]
|
||||
TYPE_REFERENCE
|
||||
NULLABLE_TYPE
|
||||
DYNAMIC_TYPE
|
||||
PROPERTY[fqName=foo_a, hasDelegate=false, hasDelegateExpression=false, hasInitializer=false, hasReturnTypeRef=true, isExtension=false, isTopLevel=true, isVar=false, name=foo_a]
|
||||
TYPE_REFERENCE
|
||||
ANNOTATION_ENTRY[hasValueArguments=false, shortName=A]
|
||||
CONSTRUCTOR_CALLEE
|
||||
TYPE_REFERENCE
|
||||
USER_TYPE
|
||||
REFERENCE_EXPRESSION[referencedName=A]
|
||||
DYNAMIC_TYPE
|
||||
PROPERTY[fqName=foo_nullable_a, hasDelegate=false, hasDelegateExpression=false, hasInitializer=false, hasReturnTypeRef=true, isExtension=false, isTopLevel=true, isVar=false, name=foo_nullable_a]
|
||||
TYPE_REFERENCE
|
||||
ANNOTATION_ENTRY[hasValueArguments=false, shortName=A]
|
||||
CONSTRUCTOR_CALLEE
|
||||
TYPE_REFERENCE
|
||||
USER_TYPE
|
||||
REFERENCE_EXPRESSION[referencedName=A]
|
||||
NULLABLE_TYPE
|
||||
DYNAMIC_TYPE
|
||||
CLASS[fqName=A, isEnumEntry=false, isInterface=false, isLocal=false, isTopLevel=true, name=A, superNames=[]]
|
||||
MODIFIER_LIST[annotation]
|
||||
ANNOTATION_ENTRY[hasValueArguments=true, shortName=Target]
|
||||
CONSTRUCTOR_CALLEE
|
||||
TYPE_REFERENCE
|
||||
USER_TYPE
|
||||
REFERENCE_EXPRESSION[referencedName=Target]
|
||||
|
||||
Vendored
+7
-1
@@ -1 +1,7 @@
|
||||
val foo: dynamic
|
||||
val foo: dynamic
|
||||
val foo_nullable: dynamic?
|
||||
val foo_a: @A dynamic
|
||||
val foo_nullable_a: @A dynamic?
|
||||
|
||||
@Target(AnnotationTarget.TYPE, AnnotationTarget.TYPE_PARAMETER)
|
||||
annotation class A
|
||||
+1
-1
@@ -73,7 +73,7 @@ fun VirtualFile.findClassFileByName(className: String): VirtualFile {
|
||||
val files = LinkedHashSet<VirtualFile>()
|
||||
VfsUtilCore.iterateChildrenRecursively(
|
||||
this,
|
||||
{ virtualFile -> virtualFile.isDirectory || virtualFile.name.equals("$className.class") },
|
||||
{ virtualFile -> virtualFile.isDirectory || virtualFile.name == "$className.class" },
|
||||
{ virtualFile -> if (!virtualFile.isDirectory) files.addIfNotNull(virtualFile); true })
|
||||
|
||||
return files.single()
|
||||
|
||||
+6
@@ -53,6 +53,12 @@ public class ClsStubBuilderTestGenerated extends AbstractClsStubBuilderTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("AnnotationsOnNullableTypes")
|
||||
public void testAnnotationsOnNullableTypes() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/decompiler/stubBuilder/AnnotationsOnNullableTypes/");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("ClassMembers")
|
||||
public void testClassMembers() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/decompiler/stubBuilder/ClassMembers/");
|
||||
|
||||
Reference in New Issue
Block a user