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:
Nikolay Krasko
2016-10-21 16:50:14 +03:00
parent e53940f4af
commit d1dfcfaca1
8 changed files with 258 additions and 18 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 = 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.
@@ -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) }
}
@@ -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
@@ -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
View File
@@ -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]
+7 -1
View File
@@ -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
@@ -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()
@@ -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/");