diff --git a/analysis/decompiled/decompiler-to-file-stubs/testData/additionalClsStubInfo/AnnotatedFlexibleTypes/AnnotatedFlexibleTypes.kt b/analysis/decompiled/decompiler-to-file-stubs/testData/additionalClsStubInfo/AnnotatedFlexibleTypes/AnnotatedFlexibleTypes.kt new file mode 100644 index 00000000000..fd431409026 --- /dev/null +++ b/analysis/decompiled/decompiler-to-file-stubs/testData/additionalClsStubInfo/AnnotatedFlexibleTypes/AnnotatedFlexibleTypes.kt @@ -0,0 +1,9 @@ +package test + +public class AnnotatedFlexibleTypes(val javaClass: d.JavaClass) { + fun foo() = javaClass.foo() + + val bar = javaClass.bar() + + val baz = javaClass.baz() +} \ No newline at end of file diff --git a/analysis/decompiled/decompiler-to-file-stubs/testData/additionalClsStubInfo/AnnotatedFlexibleTypes/AnnotatedFlexibleTypes.txt b/analysis/decompiled/decompiler-to-file-stubs/testData/additionalClsStubInfo/AnnotatedFlexibleTypes/AnnotatedFlexibleTypes.txt new file mode 100644 index 00000000000..f5fbe8347e9 --- /dev/null +++ b/analysis/decompiled/decompiler-to-file-stubs/testData/additionalClsStubInfo/AnnotatedFlexibleTypes/AnnotatedFlexibleTypes.txt @@ -0,0 +1,72 @@ +PsiJetFileStubImpl[package=test] +KotlinStub$PACKAGE_DIRECTIVE + KotlinStub$REFERENCE_EXPRESSION[referencedName=test] +KotlinStub$IMPORT_LIST +KotlinStub$CLASS[classId=test/AnnotatedFlexibleTypes, fqName=test.AnnotatedFlexibleTypes, isEnumEntry=false, isInterface=false, isLocal=false, isTopLevel=true, name=AnnotatedFlexibleTypes, superNames=[]] + KotlinStub$MODIFIER_LIST[public final] + KotlinStub$PRIMARY_CONSTRUCTOR[fqName=null, hasBody=false, isDelegatedCallToThis=false, isExtension=false, isTopLevel=false, name=AnnotatedFlexibleTypes] + KotlinStub$MODIFIER_LIST[public] + KotlinStub$VALUE_PARAMETER_LIST + KotlinStub$VALUE_PARAMETER[fqName=null, hasDefaultValue=false, hasValOrVar=false, isMutable=false, name=javaClass] + KotlinStub$TYPE_REFERENCE + KotlinStub$USER_TYPE + KotlinStub$USER_TYPE + KotlinStub$REFERENCE_EXPRESSION[referencedName=d] + KotlinStub$REFERENCE_EXPRESSION[referencedName=JavaClass] + KotlinStub$CLASS_BODY + KotlinStub$PROPERTY[fqName=test.AnnotatedFlexibleTypes.bar, hasDelegate=false, hasDelegateExpression=false, hasInitializer=false, hasReturnTypeRef=true, isExtension=false, isTopLevel=false, isVar=false, name=bar] + KotlinStub$MODIFIER_LIST[public final] + KotlinStub$TYPE_REFERENCE + KotlinStub$USER_TYPE ft: kotlin.collections.Collection? + KotlinStub$USER_TYPE + KotlinStub$USER_TYPE + KotlinStub$REFERENCE_EXPRESSION[referencedName=kotlin] + KotlinStub$REFERENCE_EXPRESSION[referencedName=collections] + KotlinStub$REFERENCE_EXPRESSION[referencedName=MutableCollection] + KotlinStub$TYPE_ARGUMENT_LIST + KotlinStub$TYPE_PROJECTION[projectionKind=NONE] + KotlinStub$TYPE_REFERENCE + KotlinStub$USER_TYPE ft: kotlin.Int? + KotlinStub$USER_TYPE + KotlinStub$REFERENCE_EXPRESSION[referencedName=kotlin] + KotlinStub$REFERENCE_EXPRESSION[referencedName=Int] + KotlinStub$PROPERTY[fqName=test.AnnotatedFlexibleTypes.baz, hasDelegate=false, hasDelegateExpression=false, hasInitializer=false, hasReturnTypeRef=true, isExtension=false, isTopLevel=false, isVar=false, name=baz] + KotlinStub$MODIFIER_LIST[public final] + KotlinStub$TYPE_REFERENCE + KotlinStub$USER_TYPE ft: kotlin.collections.Collection .. kotlin.collections.Collection?>? + KotlinStub$USER_TYPE + KotlinStub$USER_TYPE + KotlinStub$REFERENCE_EXPRESSION[referencedName=kotlin] + KotlinStub$REFERENCE_EXPRESSION[referencedName=collections] + KotlinStub$REFERENCE_EXPRESSION[referencedName=MutableCollection] + KotlinStub$TYPE_ARGUMENT_LIST + KotlinStub$TYPE_PROJECTION[projectionKind=NONE] + KotlinStub$TYPE_REFERENCE + KotlinStub$USER_TYPE ft: kotlin.collections.Collection? + KotlinStub$USER_TYPE + KotlinStub$USER_TYPE + KotlinStub$REFERENCE_EXPRESSION[referencedName=kotlin] + KotlinStub$REFERENCE_EXPRESSION[referencedName=collections] + KotlinStub$REFERENCE_EXPRESSION[referencedName=MutableCollection] + KotlinStub$TYPE_ARGUMENT_LIST + KotlinStub$TYPE_PROJECTION[projectionKind=NONE] + KotlinStub$TYPE_REFERENCE + KotlinStub$USER_TYPE ft: kotlin.Int? + KotlinStub$USER_TYPE + KotlinStub$REFERENCE_EXPRESSION[referencedName=kotlin] + KotlinStub$REFERENCE_EXPRESSION[referencedName=Int] + KotlinStub$PROPERTY[fqName=test.AnnotatedFlexibleTypes.javaClass, hasDelegate=false, hasDelegateExpression=false, hasInitializer=false, hasReturnTypeRef=true, isExtension=false, isTopLevel=false, isVar=false, name=javaClass] + KotlinStub$MODIFIER_LIST[public final] + KotlinStub$TYPE_REFERENCE + KotlinStub$USER_TYPE + KotlinStub$USER_TYPE + KotlinStub$REFERENCE_EXPRESSION[referencedName=d] + KotlinStub$REFERENCE_EXPRESSION[referencedName=JavaClass] + KotlinStub$FUN[fqName=test.AnnotatedFlexibleTypes.foo, hasBlockBody=true, hasBody=true, hasTypeParameterListBeforeFunctionName=false, isExtension=false, isTopLevel=false, mayHaveContract=false, name=foo] + KotlinStub$MODIFIER_LIST[public final] + KotlinStub$VALUE_PARAMETER_LIST + KotlinStub$TYPE_REFERENCE + KotlinStub$USER_TYPE ft: kotlin.Int? + KotlinStub$USER_TYPE + KotlinStub$REFERENCE_EXPRESSION[referencedName=kotlin] + KotlinStub$REFERENCE_EXPRESSION[referencedName=Int] \ No newline at end of file diff --git a/analysis/decompiled/decompiler-to-file-stubs/testData/additionalClsStubInfo/AnnotatedFlexibleTypes/d/JavaClass.java b/analysis/decompiled/decompiler-to-file-stubs/testData/additionalClsStubInfo/AnnotatedFlexibleTypes/d/JavaClass.java new file mode 100644 index 00000000000..e9cc7bc85e0 --- /dev/null +++ b/analysis/decompiled/decompiler-to-file-stubs/testData/additionalClsStubInfo/AnnotatedFlexibleTypes/d/JavaClass.java @@ -0,0 +1,15 @@ +package d; + +import org.jetbrains.annotations.*; +import kotlin.annotations.jvm.*; + +public abstract class JavaClass { + @Nullable + public abstract Integer foo(); + + @Mutable + public abstract java.util.Collection bar(); + + @Mutable + public abstract java.util.Collection> baz(); +} \ No newline at end of file diff --git a/analysis/decompiled/decompiler-to-file-stubs/testData/additionalClsStubInfo/OuterClassesWithFlexibleArgs/OuterClassesWithFlexibleArgs.kt b/analysis/decompiled/decompiler-to-file-stubs/testData/additionalClsStubInfo/OuterClassesWithFlexibleArgs/OuterClassesWithFlexibleArgs.kt new file mode 100644 index 00000000000..e20120434a2 --- /dev/null +++ b/analysis/decompiled/decompiler-to-file-stubs/testData/additionalClsStubInfo/OuterClassesWithFlexibleArgs/OuterClassesWithFlexibleArgs.kt @@ -0,0 +1,5 @@ +package test + +public class OuterClassesWithFlexibleArgs(k: K, l: L) { + val baz = d.JavaClass.baz(k, l) +} \ No newline at end of file diff --git a/analysis/decompiled/decompiler-to-file-stubs/testData/additionalClsStubInfo/OuterClassesWithFlexibleArgs/OuterClassesWithFlexibleArgs.txt b/analysis/decompiled/decompiler-to-file-stubs/testData/additionalClsStubInfo/OuterClassesWithFlexibleArgs/OuterClassesWithFlexibleArgs.txt new file mode 100644 index 00000000000..f3e64210dc3 --- /dev/null +++ b/analysis/decompiled/decompiler-to-file-stubs/testData/additionalClsStubInfo/OuterClassesWithFlexibleArgs/OuterClassesWithFlexibleArgs.txt @@ -0,0 +1,40 @@ +PsiJetFileStubImpl[package=test] +KotlinStub$PACKAGE_DIRECTIVE + KotlinStub$REFERENCE_EXPRESSION[referencedName=test] +KotlinStub$IMPORT_LIST +KotlinStub$CLASS[classId=test/OuterClassesWithFlexibleArgs, fqName=test.OuterClassesWithFlexibleArgs, isEnumEntry=false, isInterface=false, isLocal=false, isTopLevel=true, name=OuterClassesWithFlexibleArgs, superNames=[]] + KotlinStub$MODIFIER_LIST[public final] + KotlinStub$TYPE_PARAMETER_LIST + KotlinStub$TYPE_PARAMETER[fqName=null, isInVariance=false, isOutVariance=false, name=K] + KotlinStub$TYPE_PARAMETER[fqName=null, isInVariance=false, isOutVariance=false, name=L] + KotlinStub$PRIMARY_CONSTRUCTOR[fqName=null, hasBody=false, isDelegatedCallToThis=false, isExtension=false, isTopLevel=false, name=OuterClassesWithFlexibleArgs] + KotlinStub$MODIFIER_LIST[public] + KotlinStub$VALUE_PARAMETER_LIST + KotlinStub$VALUE_PARAMETER[fqName=null, hasDefaultValue=false, hasValOrVar=false, isMutable=false, name=k] + KotlinStub$TYPE_REFERENCE + KotlinStub$USER_TYPE + KotlinStub$REFERENCE_EXPRESSION[referencedName=K] + KotlinStub$VALUE_PARAMETER[fqName=null, hasDefaultValue=false, hasValOrVar=false, isMutable=false, name=l] + KotlinStub$TYPE_REFERENCE + KotlinStub$USER_TYPE + KotlinStub$REFERENCE_EXPRESSION[referencedName=L] + KotlinStub$CLASS_BODY + KotlinStub$PROPERTY[fqName=test.OuterClassesWithFlexibleArgs.baz, hasDelegate=false, hasDelegateExpression=false, hasInitializer=false, hasReturnTypeRef=true, isExtension=false, isTopLevel=false, isVar=false, name=baz] + KotlinStub$MODIFIER_LIST[public final] + KotlinStub$TYPE_REFERENCE + KotlinStub$USER_TYPE ft: d.JavaClass.InnerClass? + KotlinStub$USER_TYPE + KotlinStub$USER_TYPE + KotlinStub$REFERENCE_EXPRESSION[referencedName=d] + KotlinStub$REFERENCE_EXPRESSION[referencedName=JavaClass] + KotlinStub$TYPE_ARGUMENT_LIST + KotlinStub$TYPE_PROJECTION[projectionKind=NONE] + KotlinStub$TYPE_REFERENCE + KotlinStub$USER_TYPE ft: K? + KotlinStub$REFERENCE_EXPRESSION[referencedName=K] + KotlinStub$REFERENCE_EXPRESSION[referencedName=InnerClass] + KotlinStub$TYPE_ARGUMENT_LIST + KotlinStub$TYPE_PROJECTION[projectionKind=NONE] + KotlinStub$TYPE_REFERENCE + KotlinStub$USER_TYPE ft: L? + KotlinStub$REFERENCE_EXPRESSION[referencedName=L] \ No newline at end of file diff --git a/analysis/decompiled/decompiler-to-file-stubs/testData/additionalClsStubInfo/OuterClassesWithFlexibleArgs/d/JavaClass.java b/analysis/decompiled/decompiler-to-file-stubs/testData/additionalClsStubInfo/OuterClassesWithFlexibleArgs/d/JavaClass.java new file mode 100644 index 00000000000..c163976d9b7 --- /dev/null +++ b/analysis/decompiled/decompiler-to-file-stubs/testData/additionalClsStubInfo/OuterClassesWithFlexibleArgs/d/JavaClass.java @@ -0,0 +1,13 @@ +package d; + +import org.jetbrains.annotations.*; +import kotlin.annotations.jvm.*; + +public abstract class JavaClass { + public class InnerClass {} + + @Mutable + public static JavaClass.InnerClass baz(K k, L l) { + return null; + } +} \ No newline at end of file diff --git a/analysis/decompiled/decompiler-to-file-stubs/testData/additionalClsStubInfo/TypeParametersInFlexibleTypes/TypeParametersInFlexibleTypes.kt b/analysis/decompiled/decompiler-to-file-stubs/testData/additionalClsStubInfo/TypeParametersInFlexibleTypes/TypeParametersInFlexibleTypes.kt new file mode 100644 index 00000000000..c54ffde41fd --- /dev/null +++ b/analysis/decompiled/decompiler-to-file-stubs/testData/additionalClsStubInfo/TypeParametersInFlexibleTypes/TypeParametersInFlexibleTypes.kt @@ -0,0 +1,9 @@ +package test + +public class TypeParametersInFlexibleTypes(val javaClass: d.JavaClass, val t: D & Any) { + fun foo() = javaClass.foo() + + val bar = javaClass.bar() + + val baz = d.JavaClass.baz(t) +} \ No newline at end of file diff --git a/analysis/decompiled/decompiler-to-file-stubs/testData/additionalClsStubInfo/TypeParametersInFlexibleTypes/TypeParametersInFlexibleTypes.txt b/analysis/decompiled/decompiler-to-file-stubs/testData/additionalClsStubInfo/TypeParametersInFlexibleTypes/TypeParametersInFlexibleTypes.txt new file mode 100644 index 00000000000..05f9985d6c2 --- /dev/null +++ b/analysis/decompiled/decompiler-to-file-stubs/testData/additionalClsStubInfo/TypeParametersInFlexibleTypes/TypeParametersInFlexibleTypes.txt @@ -0,0 +1,94 @@ +PsiJetFileStubImpl[package=test] +KotlinStub$PACKAGE_DIRECTIVE + KotlinStub$REFERENCE_EXPRESSION[referencedName=test] +KotlinStub$IMPORT_LIST +KotlinStub$CLASS[classId=test/TypeParametersInFlexibleTypes, fqName=test.TypeParametersInFlexibleTypes, isEnumEntry=false, isInterface=false, isLocal=false, isTopLevel=true, name=TypeParametersInFlexibleTypes, superNames=[]] + KotlinStub$MODIFIER_LIST[public final] + KotlinStub$TYPE_PARAMETER_LIST + KotlinStub$TYPE_PARAMETER[fqName=null, isInVariance=false, isOutVariance=false, name=A] + KotlinStub$TYPE_PARAMETER[fqName=null, isInVariance=false, isOutVariance=false, name=D] + KotlinStub$PRIMARY_CONSTRUCTOR[fqName=null, hasBody=false, isDelegatedCallToThis=false, isExtension=false, isTopLevel=false, name=TypeParametersInFlexibleTypes] + KotlinStub$MODIFIER_LIST[public] + KotlinStub$VALUE_PARAMETER_LIST + KotlinStub$VALUE_PARAMETER[fqName=null, hasDefaultValue=false, hasValOrVar=false, isMutable=false, name=javaClass] + KotlinStub$TYPE_REFERENCE + KotlinStub$USER_TYPE + KotlinStub$USER_TYPE + KotlinStub$REFERENCE_EXPRESSION[referencedName=d] + KotlinStub$REFERENCE_EXPRESSION[referencedName=JavaClass] + KotlinStub$TYPE_ARGUMENT_LIST + KotlinStub$TYPE_PROJECTION[projectionKind=NONE] + KotlinStub$TYPE_REFERENCE + KotlinStub$USER_TYPE + KotlinStub$REFERENCE_EXPRESSION[referencedName=A] + KotlinStub$VALUE_PARAMETER[fqName=null, hasDefaultValue=false, hasValOrVar=false, isMutable=false, name=t] + KotlinStub$TYPE_REFERENCE + KotlinStub$INTERSECTION_TYPE + KotlinStub$TYPE_REFERENCE + KotlinStub$USER_TYPE + KotlinStub$REFERENCE_EXPRESSION[referencedName=D] + KotlinStub$TYPE_REFERENCE + KotlinStub$USER_TYPE + KotlinStub$REFERENCE_EXPRESSION[referencedName=Any] + KotlinStub$CLASS_BODY + KotlinStub$PROPERTY[fqName=test.TypeParametersInFlexibleTypes.bar, hasDelegate=false, hasDelegateExpression=false, hasInitializer=false, hasReturnTypeRef=true, isExtension=false, isTopLevel=false, isVar=false, name=bar] + KotlinStub$MODIFIER_LIST[public final] + KotlinStub$TYPE_REFERENCE + KotlinStub$USER_TYPE ft: kotlin.collections.Collection? + KotlinStub$USER_TYPE + KotlinStub$USER_TYPE + KotlinStub$REFERENCE_EXPRESSION[referencedName=kotlin] + KotlinStub$REFERENCE_EXPRESSION[referencedName=collections] + KotlinStub$REFERENCE_EXPRESSION[referencedName=MutableCollection] + KotlinStub$TYPE_ARGUMENT_LIST + KotlinStub$TYPE_PROJECTION[projectionKind=NONE] + KotlinStub$TYPE_REFERENCE + KotlinStub$USER_TYPE ft: A? + KotlinStub$REFERENCE_EXPRESSION[referencedName=A] + KotlinStub$PROPERTY[fqName=test.TypeParametersInFlexibleTypes.baz, hasDelegate=false, hasDelegateExpression=false, hasInitializer=false, hasReturnTypeRef=true, isExtension=false, isTopLevel=false, isVar=false, name=baz] + KotlinStub$MODIFIER_LIST[public final] + KotlinStub$TYPE_REFERENCE + KotlinStub$USER_TYPE ft: kotlin.collections.Collection? + KotlinStub$USER_TYPE + KotlinStub$USER_TYPE + KotlinStub$REFERENCE_EXPRESSION[referencedName=kotlin] + KotlinStub$REFERENCE_EXPRESSION[referencedName=collections] + KotlinStub$REFERENCE_EXPRESSION[referencedName=MutableCollection] + KotlinStub$TYPE_ARGUMENT_LIST + KotlinStub$TYPE_PROJECTION[projectionKind=NONE] + KotlinStub$TYPE_REFERENCE + KotlinStub$INTERSECTION_TYPE + KotlinStub$TYPE_REFERENCE + KotlinStub$USER_TYPE ft: D? + KotlinStub$REFERENCE_EXPRESSION[referencedName=D] + KotlinStub$TYPE_REFERENCE + KotlinStub$USER_TYPE + KotlinStub$REFERENCE_EXPRESSION[referencedName=Any] + KotlinStub$PROPERTY[fqName=test.TypeParametersInFlexibleTypes.javaClass, hasDelegate=false, hasDelegateExpression=false, hasInitializer=false, hasReturnTypeRef=true, isExtension=false, isTopLevel=false, isVar=false, name=javaClass] + KotlinStub$MODIFIER_LIST[public final] + KotlinStub$TYPE_REFERENCE + KotlinStub$USER_TYPE + KotlinStub$USER_TYPE + KotlinStub$REFERENCE_EXPRESSION[referencedName=d] + KotlinStub$REFERENCE_EXPRESSION[referencedName=JavaClass] + KotlinStub$TYPE_ARGUMENT_LIST + KotlinStub$TYPE_PROJECTION[projectionKind=NONE] + KotlinStub$TYPE_REFERENCE + KotlinStub$USER_TYPE + KotlinStub$REFERENCE_EXPRESSION[referencedName=A] + KotlinStub$PROPERTY[fqName=test.TypeParametersInFlexibleTypes.t, hasDelegate=false, hasDelegateExpression=false, hasInitializer=false, hasReturnTypeRef=true, isExtension=false, isTopLevel=false, isVar=false, name=t] + KotlinStub$MODIFIER_LIST[public final] + KotlinStub$TYPE_REFERENCE + KotlinStub$INTERSECTION_TYPE + KotlinStub$TYPE_REFERENCE + KotlinStub$USER_TYPE + KotlinStub$REFERENCE_EXPRESSION[referencedName=D] + KotlinStub$TYPE_REFERENCE + KotlinStub$USER_TYPE + KotlinStub$REFERENCE_EXPRESSION[referencedName=Any] + KotlinStub$FUN[fqName=test.TypeParametersInFlexibleTypes.foo, hasBlockBody=true, hasBody=true, hasTypeParameterListBeforeFunctionName=false, isExtension=false, isTopLevel=false, mayHaveContract=false, name=foo] + KotlinStub$MODIFIER_LIST[public final] + KotlinStub$VALUE_PARAMETER_LIST + KotlinStub$TYPE_REFERENCE + KotlinStub$USER_TYPE ft: A? + KotlinStub$REFERENCE_EXPRESSION[referencedName=A] \ No newline at end of file diff --git a/analysis/decompiled/decompiler-to-file-stubs/testData/additionalClsStubInfo/TypeParametersInFlexibleTypes/d/JavaClass.java b/analysis/decompiled/decompiler-to-file-stubs/testData/additionalClsStubInfo/TypeParametersInFlexibleTypes/d/JavaClass.java new file mode 100644 index 00000000000..339071bdc75 --- /dev/null +++ b/analysis/decompiled/decompiler-to-file-stubs/testData/additionalClsStubInfo/TypeParametersInFlexibleTypes/d/JavaClass.java @@ -0,0 +1,17 @@ +package d; + +import org.jetbrains.annotations.*; +import kotlin.annotations.jvm.*; + +public abstract class JavaClass { + @Nullable + public abstract T foo(); + + @Mutable + public abstract java.util.Collection bar(); + + @Mutable + public static java.util.Collection baz(K t) { + return new java.util.ArrayList<>(); + } +} \ No newline at end of file diff --git a/analysis/decompiled/decompiler-to-file-stubs/tests/org/jetbrains/kotlin/analysis/decompiler/stub/files/AbstractAdditionalStubInfoTest.kt b/analysis/decompiled/decompiler-to-file-stubs/tests/org/jetbrains/kotlin/analysis/decompiler/stub/files/AbstractAdditionalStubInfoTest.kt new file mode 100644 index 00000000000..5a4b8e57e13 --- /dev/null +++ b/analysis/decompiled/decompiler-to-file-stubs/tests/org/jetbrains/kotlin/analysis/decompiler/stub/files/AbstractAdditionalStubInfoTest.kt @@ -0,0 +1,80 @@ +/* + * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.analysis.decompiler.stub.files + +import com.intellij.psi.stubs.StubElement +import com.intellij.util.indexing.FileContentImpl +import org.jetbrains.kotlin.analysis.decompiler.stub.file.KotlinClsStubBuilder +import org.jetbrains.kotlin.psi.KtProjectionKind +import org.jetbrains.kotlin.psi.stubs.impl.* +import org.jetbrains.kotlin.test.KotlinTestUtils +import java.nio.file.Paths + +abstract class AbstractAdditionalStubInfoTest : AbstractDecompiledClassTest() { + fun runTest(testDirectory: String) { + val testDirectoryPath = Paths.get(testDirectory) + val testData = TestData.createFromDirectory(testDirectoryPath) + val stub = KotlinClsStubBuilder().buildFileStub(FileContentImpl.createByFile(getClassFileToDecompile(testData, false)))!! + val builder = StringBuilder() + extractAdditionInfo(stub, builder, 0) + KotlinTestUtils.assertEqualsToFile(testData.expectedFile, builder.toString()) + } + + private fun extractAdditionInfo(stub: StubElement<*>, builder: StringBuilder, level: Int) { + builder.append(stub.toString()) + if (stub is KotlinUserTypeStubImpl) { + val upperBound = stub.upperBound + if (upperBound != null) { + builder.append(" ft: ") + appendFlexibleTypeInfo(builder, upperBound) + } + } + for (child in stub.childrenStubs) { + builder.append("\n").append(" ".repeat(level)) + extractAdditionInfo(child, builder, level + 1) + } + } + + private fun appendFlexibleTypeInfo(builder: StringBuilder, typeBean: KotlinTypeBean) { + when (typeBean) { + is KotlinClassTypeBean -> { + builder.append(typeBean.classId.asFqNameString()) + val arguments = typeBean.arguments + if (arguments.isNotEmpty()) { + builder.append("<") + arguments.forEachIndexed { index, arg -> + if (index > 0) builder.append(", ") + if (arg.projectionKind != KtProjectionKind.NONE) { + builder.append(arg.projectionKind.name) + } + if (arg.projectionKind != KtProjectionKind.STAR) { + appendFlexibleTypeInfo(builder, arg.type!!) + } + } + builder.append(">") + } + if (typeBean.nullable) { + builder.append("?") + } + } + is KotlinTypeParameterTypeBean -> { + builder.append(typeBean.typeParameterName) + if (typeBean.nullable) { + builder.append("?") + } + if (typeBean.definitelyNotNull) { + builder.append(" & Any") + } + } + + is KotlinFlexibleTypeBean -> { + appendFlexibleTypeInfo(builder, typeBean.lowerBound) + builder.append(" .. ") + appendFlexibleTypeInfo(builder, typeBean.upperBound) + } + } + } +} \ No newline at end of file diff --git a/analysis/decompiled/decompiler-to-file-stubs/tests/org/jetbrains/kotlin/analysis/decompiler/stub/files/AbstractDecompiledClassTest.kt b/analysis/decompiled/decompiler-to-file-stubs/tests/org/jetbrains/kotlin/analysis/decompiler/stub/files/AbstractDecompiledClassTest.kt new file mode 100644 index 00000000000..8a685726d50 --- /dev/null +++ b/analysis/decompiled/decompiler-to-file-stubs/tests/org/jetbrains/kotlin/analysis/decompiler/stub/files/AbstractDecompiledClassTest.kt @@ -0,0 +1,123 @@ +/* + * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.analysis.decompiler.stub.files + +import com.intellij.core.CoreApplicationEnvironment +import com.intellij.openapi.vfs.VfsUtilCore +import com.intellij.openapi.vfs.VirtualFile +import com.intellij.openapi.vfs.impl.jar.CoreJarFileSystem +import org.jetbrains.kotlin.analysis.decompiler.stub.file.CachedAttributeData +import org.jetbrains.kotlin.analysis.decompiler.stub.file.ClsKotlinBinaryClassCache +import org.jetbrains.kotlin.analysis.decompiler.stub.file.FileAttributeService +import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment +import org.jetbrains.kotlin.test.* +import org.jetbrains.kotlin.utils.addIfNotNull +import java.io.DataInput +import java.io.DataOutput +import java.nio.file.Files +import java.nio.file.Path +import java.util.stream.Collectors +import kotlin.io.path.absolutePathString +import kotlin.io.path.name +import kotlin.io.path.readText + +abstract class AbstractDecompiledClassTest : KotlinTestWithEnvironment() { + override fun createEnvironment(): KotlinCoreEnvironment { + return KotlinTestUtils.createEnvironmentWithMockJdkAndIdeaAnnotations( + ApplicationEnvironmentDisposer.ROOT_DISPOSABLE, + ConfigurationKind.JDK_NO_RUNTIME + ) + } + + override fun setUp() { + super.setUp() + + with(environment.projectEnvironment.environment) { + registerApplicationServices() + } + } + + private fun CoreApplicationEnvironment.registerApplicationServices() { + if (application.getService(FileAttributeService::class.java) == null) { + registerApplicationService(FileAttributeService::class.java, DummyFileAttributeService) + registerApplicationService(ClsKotlinBinaryClassCache::class.java, ClsKotlinBinaryClassCache()) + } + } + + internal fun getClassFileToDecompile(testData: TestData, useStringTable: Boolean): VirtualFile { + val extraOptions = buildList { + this.add("-Xallow-kotlin-package") + if (useStringTable) { + this.add("-Xuse-type-table") + } + this.addAll(testData.additionalCompilerOptions) + } + val library = CompilerTestUtil.compileJvmLibrary( + src = testData.directory.toFile(), + extraOptions = extraOptions, + ).toPath() + return findClassFileByName( + library, testData.jvmFileName + ) + } + + private fun findClassFileByName(library: Path, className: String): VirtualFile { + val jarFileSystem = environment.projectEnvironment.environment.jarFileSystem as CoreJarFileSystem + val root = jarFileSystem.refreshAndFindFileByPath(library.absolutePathString() + "!/")!! + val files = mutableSetOf() + VfsUtilCore.iterateChildrenRecursively( + root, + /*filter=*/{ virtualFile -> + virtualFile.isDirectory || virtualFile.name == "$className.class" + }, + /*iterator=*/{ virtualFile -> + if (!virtualFile.isDirectory) { + files.addIfNotNull(virtualFile) + } + true + }) + + return files.single() + } + +} + +internal data class TestData( + val directory: Path, + val mainKotlinFile: Path, + val expectedFile: Path, + val jvmFileName: String, + val additionalCompilerOptions: List, +) { + companion object { + fun createFromDirectory(directory: Path): TestData { + val allFiles = Files.list(directory).collect(Collectors.toList()) + val mainKotlinFile = allFiles.single { path: Path -> + path.name.replaceFirstChar { Character.toUpperCase(it) } == "${directory.name.removeSuffix("Kt")}.kt" + } + val fileText = mainKotlinFile.readText() + val jvmFileName = InTextDirectivesUtils.findStringWithPrefixes(fileText, "JVM_FILE_NAME:") ?: directory.name + val additionalCompilerOptions = InTextDirectivesUtils.findListWithPrefixes(fileText, "// !LANGUAGE: ").map { "-XXLanguage:$it" } + return TestData( + directory = directory, + mainKotlinFile = mainKotlinFile, + expectedFile = allFiles.single { it.fileName.toString() == "${directory.name}.txt" }, + jvmFileName = jvmFileName, + additionalCompilerOptions = additionalCompilerOptions, + ) + } + } +} + +object DummyFileAttributeService : FileAttributeService { + override fun write(file: VirtualFile, id: String, value: T, writeValueFun: (DataOutput, T) -> Unit): CachedAttributeData { + return CachedAttributeData(value, 0) + } + + override fun read(file: VirtualFile, id: String, readValueFun: (DataInput) -> T): CachedAttributeData? { + return null + } +} diff --git a/analysis/decompiled/decompiler-to-file-stubs/tests/org/jetbrains/kotlin/analysis/decompiler/stub/files/AbstractStubBuilderTest.kt b/analysis/decompiled/decompiler-to-file-stubs/tests/org/jetbrains/kotlin/analysis/decompiler/stub/files/AbstractStubBuilderTest.kt index 882b00a3f01..c24950e2714 100644 --- a/analysis/decompiled/decompiler-to-file-stubs/tests/org/jetbrains/kotlin/analysis/decompiler/stub/files/AbstractStubBuilderTest.kt +++ b/analysis/decompiled/decompiler-to-file-stubs/tests/org/jetbrains/kotlin/analysis/decompiler/stub/files/AbstractStubBuilderTest.kt @@ -5,55 +5,17 @@ package org.jetbrains.kotlin.analysis.decompiler.stub.files -import com.intellij.core.CoreApplicationEnvironment -import com.intellij.openapi.vfs.VfsUtilCore import com.intellij.openapi.vfs.VirtualFile -import com.intellij.openapi.vfs.impl.jar.CoreJarFileSystem import com.intellij.psi.PsiElement import com.intellij.psi.impl.DebugUtil import com.intellij.psi.stubs.PsiFileStub import com.intellij.psi.stubs.StubElement -import org.jetbrains.kotlin.analysis.decompiler.stub.file.CachedAttributeData -import org.jetbrains.kotlin.analysis.decompiler.stub.file.ClsKotlinBinaryClassCache -import org.jetbrains.kotlin.analysis.decompiler.stub.file.FileAttributeService -import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.name.SpecialNames import org.jetbrains.kotlin.psi.stubs.impl.STUB_TO_STRING_PREFIX -import org.jetbrains.kotlin.test.* -import org.jetbrains.kotlin.utils.addIfNotNull -import java.io.DataInput -import java.io.DataOutput -import java.nio.file.Files -import java.nio.file.Path +import org.jetbrains.kotlin.test.KotlinTestUtils import java.nio.file.Paths -import java.util.stream.Collectors -import kotlin.io.path.absolutePathString -import kotlin.io.path.name -import kotlin.io.path.readText - -abstract class AbstractStubBuilderTest : KotlinTestWithEnvironment() { - override fun createEnvironment(): KotlinCoreEnvironment { - return KotlinTestUtils.createEnvironmentWithMockJdkAndIdeaAnnotations( - ApplicationEnvironmentDisposer.ROOT_DISPOSABLE, - ConfigurationKind.JDK_NO_RUNTIME - ) - } - - override fun setUp() { - super.setUp() - - with(environment.projectEnvironment.environment) { - registerApplicationServices() - } - } - - private fun CoreApplicationEnvironment.registerApplicationServices() { - if (application.getService(FileAttributeService::class.java) == null) { - registerApplicationService(FileAttributeService::class.java, DummyFileAttributeService) - registerApplicationService(ClsKotlinBinaryClassCache::class.java, ClsKotlinBinaryClassCache()) - } - } +abstract class AbstractStubBuilderTest : AbstractDecompiledClassTest() { fun runTest(testDirectory: String) { val testDirectoryPath = Paths.get(testDirectory) val testData = TestData.createFromDirectory(testDirectoryPath) @@ -73,43 +35,6 @@ abstract class AbstractStubBuilderTest : KotlinTestWithEnvironment() { } protected abstract fun getStubToTest(classFile: VirtualFile): PsiFileStub<*> - - private fun getClassFileToDecompile(testData: TestData, useStringTable: Boolean): VirtualFile { - val extraOptions = buildList { - add("-Xallow-kotlin-package") - if (useStringTable) { - add("-Xuse-type-table") - } - addAll(testData.additionalCompilerOptions) - } - - val library = CompilerTestUtil.compileJvmLibrary( - src = testData.directory.toFile(), - extraOptions = extraOptions, - ).toPath() - - return findClassFileByName(library, testData.jvmFileName) - } - - private fun findClassFileByName(library: Path, className: String): VirtualFile { - val jarFileSystem = environment.projectEnvironment.environment.jarFileSystem as CoreJarFileSystem - val root = jarFileSystem.refreshAndFindFileByPath(library.absolutePathString() + "!/")!! - val files = mutableSetOf() - VfsUtilCore.iterateChildrenRecursively( - root, - /*filter=*/{ virtualFile -> - virtualFile.isDirectory || virtualFile.name == "$className.class" - }, - /*iterator=*/{ virtualFile -> - if (!virtualFile.isDirectory) { - files.addIfNotNull(virtualFile) - } - true - }) - - return files.single() - } - } private fun StubElement.serializeToString(): String { @@ -130,40 +55,3 @@ private fun serializeStubToString(stubElement: StubElement<*>): String { }.replace(", [", "[") } - -private data class TestData( - val directory: Path, - val mainKotlinFile: Path, - val expectedFile: Path, - val jvmFileName: String, - val additionalCompilerOptions: List, -) { - companion object { - fun createFromDirectory(directory: Path): TestData { - val allFiles = Files.list(directory).collect(Collectors.toList()) - val mainKotlinFile = allFiles.single { path: Path -> - path.name.replaceFirstChar { Character.toUpperCase(it) } == "${directory.name.removeSuffix("Kt")}.kt" - } - val fileText = mainKotlinFile.readText() - val jvmFileName = InTextDirectivesUtils.findStringWithPrefixes(fileText, "JVM_FILE_NAME:") ?: directory.name - val additionalCompilerOptions = InTextDirectivesUtils.findListWithPrefixes(fileText, "// !LANGUAGE: ").map { "-XXLanguage:$it" } - return TestData( - directory = directory, - mainKotlinFile = mainKotlinFile, - expectedFile = allFiles.single { it.fileName.toString() == "${directory.name}.txt" }, - jvmFileName = jvmFileName, - additionalCompilerOptions = additionalCompilerOptions, - ) - } - } -} - -object DummyFileAttributeService : FileAttributeService { - override fun write(file: VirtualFile, id: String, value: T, writeValueFun: (DataOutput, T) -> Unit): CachedAttributeData { - return CachedAttributeData(value, 0) - } - - override fun read(file: VirtualFile, id: String, readValueFun: (DataInput) -> T): CachedAttributeData? { - return null - } -} diff --git a/analysis/decompiled/decompiler-to-file-stubs/tests/org/jetbrains/kotlin/analysis/decompiler/stub/files/AdditionalStubInfoTestGenerated.java b/analysis/decompiled/decompiler-to-file-stubs/tests/org/jetbrains/kotlin/analysis/decompiler/stub/files/AdditionalStubInfoTestGenerated.java new file mode 100644 index 00000000000..db254c140fe --- /dev/null +++ b/analysis/decompiled/decompiler-to-file-stubs/tests/org/jetbrains/kotlin/analysis/decompiler/stub/files/AdditionalStubInfoTestGenerated.java @@ -0,0 +1,44 @@ +/* + * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.analysis.decompiler.stub.files; + +import com.intellij.testFramework.TestDataPath; +import org.jetbrains.kotlin.test.util.KtTestUtil; +import org.jetbrains.kotlin.test.TestMetadata; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import java.io.File; +import java.util.regex.Pattern; + +/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.analysis.api.GenerateAnalysisApiTestsKt}. DO NOT MODIFY MANUALLY */ +@SuppressWarnings("all") +@TestMetadata("analysis/decompiled/decompiler-to-file-stubs/testData/additionalClsStubInfo") +@TestDataPath("$PROJECT_ROOT") +public class AdditionalStubInfoTestGenerated extends AbstractAdditionalStubInfoTest { + @Test + public void testAllFilesPresentInAdditionalClsStubInfo() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/decompiled/decompiler-to-file-stubs/testData/additionalClsStubInfo"), Pattern.compile("^([^\\.]+)$"), null, false); + } + + @Test + @TestMetadata("AnnotatedFlexibleTypes") + public void testAnnotatedFlexibleTypes() throws Exception { + runTest("analysis/decompiled/decompiler-to-file-stubs/testData/additionalClsStubInfo/AnnotatedFlexibleTypes/"); + } + + @Test + @TestMetadata("OuterClassesWithFlexibleArgs") + public void testOuterClassesWithFlexibleArgs() throws Exception { + runTest("analysis/decompiled/decompiler-to-file-stubs/testData/additionalClsStubInfo/OuterClassesWithFlexibleArgs/"); + } + + @Test + @TestMetadata("TypeParametersInFlexibleTypes") + public void testTypeParametersInFlexibleTypes() throws Exception { + runTest("analysis/decompiled/decompiler-to-file-stubs/testData/additionalClsStubInfo/TypeParametersInFlexibleTypes/"); + } +} diff --git a/analysis/decompiled/decompiler-to-stubs/src/org/jetbrains/kotlin/analysis/decompiler/stub/TypeClsStubBuilder.kt b/analysis/decompiled/decompiler-to-stubs/src/org/jetbrains/kotlin/analysis/decompiler/stub/TypeClsStubBuilder.kt index 632d23fd034..fa96cda5fdf 100644 --- a/analysis/decompiled/decompiler-to-stubs/src/org/jetbrains/kotlin/analysis/decompiler/stub/TypeClsStubBuilder.kt +++ b/analysis/decompiled/decompiler-to-stubs/src/org/jetbrains/kotlin/analysis/decompiler/stub/TypeClsStubBuilder.kt @@ -21,10 +21,7 @@ import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.stubs.KotlinUserTypeStub import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes import org.jetbrains.kotlin.psi.stubs.impl.* -import org.jetbrains.kotlin.serialization.deserialization.DYNAMIC_TYPE_DESERIALIZER_ID -import org.jetbrains.kotlin.serialization.deserialization.ProtoContainer -import org.jetbrains.kotlin.serialization.deserialization.getClassId -import org.jetbrains.kotlin.serialization.deserialization.getName +import org.jetbrains.kotlin.serialization.deserialization.* import org.jetbrains.kotlin.utils.doNothing // TODO: see DescriptorRendererOptions.excludedTypeAnnotationClasses for decompiler @@ -70,18 +67,23 @@ class TypeClsStubBuilder(private val c: ClsStubBuilderContext) { private fun createTypeParameterStub(parent: KotlinStubBaseImpl<*>, type: Type, name: Name, annotations: List) { createTypeAnnotationStubs(parent, type, annotations) + val upperBoundType = if (type.hasFlexibleTypeCapabilitiesId()) { + createKotlinTypeBean(type.flexibleUpperBound(c.typeTable)!!) + } else null + + val typeParameterClassId = ClassId.topLevel(FqName.topLevel(name)) if (Flags.DEFINITELY_NOT_NULL_TYPE.get(type.flags)) { - createDefinitelyNotNullTypeStub(parent, FqName.topLevel(name)) + createDefinitelyNotNullTypeStub(parent, typeParameterClassId, upperBoundType) } else { val nullableParentWrapper = nullableTypeParent(parent, type) - createStubForTypeName(ClassId.topLevel(FqName.topLevel(name)), nullableParentWrapper) + createStubForTypeName(typeParameterClassId, nullableParentWrapper, { upperBoundType }) } } - private fun createDefinitelyNotNullTypeStub(parent: KotlinStubBaseImpl<*>, name: FqName) { + private fun createDefinitelyNotNullTypeStub(parent: KotlinStubBaseImpl<*>, classId: ClassId, upperBoundType: KotlinTypeBean?) { val intersectionType = KotlinPlaceHolderStubImpl(parent, KtStubElementTypes.INTERSECTION_TYPE) val leftReference = KotlinPlaceHolderStubImpl(intersectionType, KtStubElementTypes.TYPE_REFERENCE) - createStubForTypeName(ClassId.topLevel(name), leftReference) + createStubForTypeName(classId, leftReference, { upperBoundType }) val rightReference = KotlinPlaceHolderStubImpl(intersectionType, KtStubElementTypes.TYPE_REFERENCE) val userType = KotlinUserTypeStubImpl(rightReference) KotlinNameReferenceExpressionStubImpl(userType, StandardNames.FqNames.any.shortName().ref()) @@ -129,11 +131,53 @@ class TypeClsStubBuilder(private val c: ClsStubBuilderContext) { val outerTypeChain = generateSequence(type) { it.outerType(c.typeTable) }.toList() - createStubForTypeName(classId, nullableTypeParent(parent, type)) { userTypeStub, index -> + createStubForTypeName(classId, nullableTypeParent(parent, type), { level -> + if (level == 0) createKotlinTypeBean(type.flexibleUpperBound(c.typeTable)) + else createKotlinTypeBean(outerTypeChain.getOrNull(level)?.flexibleUpperBound(c.typeTable)) + }) { userTypeStub, index -> outerTypeChain.getOrNull(index)?.let { createTypeArgumentListStub(userTypeStub, it.argumentList) } } } + private fun createKotlinTypeBean( + type: Type? + ): KotlinTypeBean? { + if (type == null) return null + val definitelyNotNull = Flags.DEFINITELY_NOT_NULL_TYPE.get(type.flags) + val lowerBound = when { + type.hasTypeParameter() -> { + val lowerBound = KotlinTypeParameterTypeBean( + c.typeParameters[type.typeParameter].asString(), + type.nullable, + definitelyNotNull + ) + lowerBound + } + type.hasTypeParameterName() -> { + KotlinTypeParameterTypeBean( + c.nameResolver.getString(type.typeParameterName), + type.nullable, + definitelyNotNull + ) + } + else -> { + val classId = c.nameResolver.getClassId(if (type.hasClassName()) type.className else type.typeAliasName) + val arguments = type.argumentList.map { argument -> + val kind = argument.projection.toProjectionKind() + KotlinTypeArgumentBean( + kind, + if (kind == KtProjectionKind.STAR) null else createKotlinTypeBean(argument.type(c.typeTable)) + ) + } + KotlinClassTypeBean(classId, arguments, type.nullable) + } + } + val upperBoundBean = createKotlinTypeBean(type.flexibleUpperBound(c.typeTable)) + return if (upperBoundBean != null) { + KotlinFlexibleTypeBean(lowerBound, upperBoundBean) + } else lowerBound + } + private fun createTypeAnnotationStubs(parent: KotlinStubBaseImpl<*>, type: Type, annotations: List) { val typeModifiers = getTypeModifiersAsWritten(type) if (annotations.isEmpty() && typeModifiers.isEmpty()) return diff --git a/analysis/decompiled/decompiler-to-stubs/src/org/jetbrains/kotlin/analysis/decompiler/stub/clsStubBuilding.kt b/analysis/decompiled/decompiler-to-stubs/src/org/jetbrains/kotlin/analysis/decompiler/stub/clsStubBuilding.kt index 716c0f03c8c..0fb5d59c045 100644 --- a/analysis/decompiled/decompiler-to-stubs/src/org/jetbrains/kotlin/analysis/decompiler/stub/clsStubBuilding.kt +++ b/analysis/decompiled/decompiler-to-stubs/src/org/jetbrains/kotlin/analysis/decompiler/stub/clsStubBuilding.kt @@ -131,6 +131,7 @@ fun createStubForPackageName(packageDirectiveStub: KotlinPlaceHolderStubImpl, + upperBoundFun: ((Int) -> KotlinTypeBean?)? = null, bindTypeArguments: (KotlinUserTypeStub, Int) -> Unit = { _, _ -> } ): KotlinUserTypeStub { val substituteWithAny = typeClassId.isLocal @@ -143,7 +144,7 @@ fun createStubForTypeName( fun recCreateStubForType(current: StubElement, level: Int): KotlinUserTypeStub { val lastSegment = segments[level] - val userTypeStub = KotlinUserTypeStubImpl(current) + val userTypeStub = KotlinUserTypeStubImpl(current, upperBoundFun?.invoke(level)) if (level + 1 < segments.size) { recCreateStubForType(userTypeStub, level + 1) } diff --git a/compiler/psi/src/org/jetbrains/kotlin/psi/stubs/KotlinStubVersions.kt b/compiler/psi/src/org/jetbrains/kotlin/psi/stubs/KotlinStubVersions.kt index eade88fc408..c1cc9b9a949 100644 --- a/compiler/psi/src/org/jetbrains/kotlin/psi/stubs/KotlinStubVersions.kt +++ b/compiler/psi/src/org/jetbrains/kotlin/psi/stubs/KotlinStubVersions.kt @@ -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 = 83 + private const val BINARY_STUB_VERSION = 84 // 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. diff --git a/compiler/psi/src/org/jetbrains/kotlin/psi/stubs/elements/KtUserTypeElementType.java b/compiler/psi/src/org/jetbrains/kotlin/psi/stubs/elements/KtUserTypeElementType.java index 7c4388b3004..deec528effd 100644 --- a/compiler/psi/src/org/jetbrains/kotlin/psi/stubs/elements/KtUserTypeElementType.java +++ b/compiler/psi/src/org/jetbrains/kotlin/psi/stubs/elements/KtUserTypeElementType.java @@ -21,9 +21,18 @@ import com.intellij.psi.stubs.StubInputStream; import com.intellij.psi.stubs.StubOutputStream; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.kotlin.name.ClassId; +import org.jetbrains.kotlin.psi.KtProjectionKind; import org.jetbrains.kotlin.psi.KtUserType; import org.jetbrains.kotlin.psi.stubs.KotlinUserTypeStub; -import org.jetbrains.kotlin.psi.stubs.impl.KotlinUserTypeStubImpl; +import org.jetbrains.kotlin.psi.stubs.StubUtils; +import org.jetbrains.kotlin.psi.stubs.impl.*; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; public class KtUserTypeElementType extends KtStubElementType { public KtUserTypeElementType(@NotNull @NonNls String debugName) { @@ -33,16 +42,92 @@ public class KtUserTypeElementType extends KtStubElementType) parentStub); + return new KotlinUserTypeStubImpl((StubElement) parentStub, null); } @Override - public void serialize(@NotNull KotlinUserTypeStub stub, @NotNull StubOutputStream dataStream) { + public void serialize(@NotNull KotlinUserTypeStub stub, @NotNull StubOutputStream dataStream) throws IOException { + serializeType(dataStream, ((KotlinUserTypeStubImpl) stub).getUpperBound()); + } + + private enum KotlinTypeBeanKind { + CLASS, TYPE_PARAMETER, FLEXIBLE, NONE; + + static KotlinTypeBeanKind fromBean(@Nullable KotlinTypeBean typeBean) { + if (typeBean == null) return NONE; + if (typeBean instanceof KotlinTypeParameterTypeBean) return TYPE_PARAMETER; + if (typeBean instanceof KotlinClassTypeBean) return CLASS; + return FLEXIBLE; + } + } + + private static void serializeType(@NotNull StubOutputStream dataStream, @Nullable KotlinTypeBean type) throws IOException { + dataStream.writeInt(KotlinTypeBeanKind.fromBean(type).ordinal()); + if (type instanceof KotlinClassTypeBean) { + StubUtils.serializeClassId(dataStream, ((KotlinClassTypeBean) type).getClassId()); + dataStream.writeBoolean(type.getNullable()); + List arguments = ((KotlinClassTypeBean) type).getArguments(); + dataStream.writeInt(arguments.size()); + for (KotlinTypeArgumentBean argument : arguments) { + KtProjectionKind kind = argument.getProjectionKind(); + dataStream.writeInt(kind.ordinal()); + if (kind != KtProjectionKind.STAR) { + serializeType(dataStream, argument.getType()); + } + } + } + else if (type instanceof KotlinTypeParameterTypeBean) { + dataStream.writeName(((KotlinTypeParameterTypeBean) type).getTypeParameterName()); + dataStream.writeBoolean(type.getNullable()); + dataStream.writeBoolean(((KotlinTypeParameterTypeBean) type).getDefinitelyNotNull()); + } + else if (type instanceof KotlinFlexibleTypeBean) { + serializeType(dataStream, ((KotlinFlexibleTypeBean) type).getLowerBound()); + serializeType(dataStream, ((KotlinFlexibleTypeBean) type).getUpperBound()); + } } @NotNull @Override - public KotlinUserTypeStub deserialize(@NotNull StubInputStream dataStream, StubElement parentStub) { - return new KotlinUserTypeStubImpl((StubElement) parentStub); + public KotlinUserTypeStub deserialize(@NotNull StubInputStream dataStream, StubElement parentStub) throws IOException { + return new KotlinUserTypeStubImpl((StubElement) parentStub, deserializeType(dataStream)); + } + + @Nullable + private static KotlinTypeBean deserializeType(@NotNull StubInputStream dataStream) throws IOException { + KotlinTypeBeanKind typeKind = KotlinTypeBeanKind.values()[dataStream.readInt()]; + switch (typeKind) { + case CLASS: { + ClassId classId = Objects.requireNonNull(StubUtils.deserializeClassId(dataStream)); + boolean isNullable = dataStream.readBoolean(); + int count = dataStream.readInt(); + List arguments = new ArrayList<>(); + for (int i = 0; i < count; i++) { + int kind = dataStream.readInt(); + KotlinTypeArgumentBean argument; + if (kind != KtProjectionKind.STAR.ordinal()) { + argument = new KotlinTypeArgumentBean(KtProjectionKind.values()[kind], deserializeType(dataStream)); + } + else { + argument = new KotlinTypeArgumentBean(KtProjectionKind.STAR, null); + } + arguments.add(argument); + } + return new KotlinClassTypeBean(classId, arguments, isNullable); + } + case TYPE_PARAMETER: { + String typeParameterName = Objects.requireNonNull(dataStream.readNameString()); + boolean nullable = dataStream.readBoolean(); + boolean definitelyNotNull = dataStream.readBoolean(); + return new KotlinTypeParameterTypeBean(typeParameterName, nullable, definitelyNotNull); + } + case FLEXIBLE: { + return new KotlinFlexibleTypeBean(Objects.requireNonNull(deserializeType(dataStream)), + Objects.requireNonNull(deserializeType(dataStream))); + } + case NONE: + return null; + } + return null; } } diff --git a/compiler/psi/src/org/jetbrains/kotlin/psi/stubs/impl/KotlinUserTypeStubImpl.kt b/compiler/psi/src/org/jetbrains/kotlin/psi/stubs/impl/KotlinUserTypeStubImpl.kt index c178a57b4eb..c53baed3a95 100644 --- a/compiler/psi/src/org/jetbrains/kotlin/psi/stubs/impl/KotlinUserTypeStubImpl.kt +++ b/compiler/psi/src/org/jetbrains/kotlin/psi/stubs/impl/KotlinUserTypeStubImpl.kt @@ -18,10 +18,36 @@ package org.jetbrains.kotlin.psi.stubs.impl import com.intellij.psi.PsiElement import com.intellij.psi.stubs.StubElement +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.psi.KtProjectionKind import org.jetbrains.kotlin.psi.KtUserType import org.jetbrains.kotlin.psi.stubs.KotlinUserTypeStub import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes class KotlinUserTypeStubImpl( - parent: StubElement? + parent: StubElement?, + val upperBound: KotlinTypeBean? = null ) : KotlinStubBaseImpl(parent, KtStubElementTypes.USER_TYPE), KotlinUserTypeStub + +sealed interface KotlinTypeBean { + val nullable: Boolean +} + +data class KotlinFlexibleTypeBean(val lowerBound: KotlinTypeBean, val upperBound: KotlinTypeBean) : KotlinTypeBean { + override val nullable: Boolean + get() = lowerBound.nullable +} + +data class KotlinClassTypeBean( + val classId: ClassId, + val arguments: List, + override val nullable: Boolean, +) : KotlinTypeBean + +data class KotlinTypeArgumentBean(val projectionKind: KtProjectionKind, val type: KotlinTypeBean?) + +data class KotlinTypeParameterTypeBean( + val typeParameterName: String, + override val nullable: Boolean, + val definitelyNotNull: Boolean +) : KotlinTypeBean \ No newline at end of file diff --git a/generators/analysis-api-generator/tests/org/jetbrains/kotlin/generators/tests/analysis/api/decompiled.kt b/generators/analysis-api-generator/tests/org/jetbrains/kotlin/generators/tests/analysis/api/decompiled.kt index df6e06c4c8e..2ce5065bd0a 100644 --- a/generators/analysis-api-generator/tests/org/jetbrains/kotlin/generators/tests/analysis/api/decompiled.kt +++ b/generators/analysis-api-generator/tests/org/jetbrains/kotlin/generators/tests/analysis/api/decompiled.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.generators.tests.analysis.api import org.jetbrains.kotlin.analysis.decompiler.psi.AbstractByDecompiledPsiStubBuilderTest +import org.jetbrains.kotlin.analysis.decompiler.stub.files.AbstractAdditionalStubInfoTest import org.jetbrains.kotlin.analysis.decompiler.stub.files.AbstractClsStubBuilderTest import org.jetbrains.kotlin.generators.TestGroupSuite @@ -19,6 +20,15 @@ internal fun TestGroupSuite.generateDecompiledTests() { } } + testGroup( + "analysis/decompiled/decompiler-to-file-stubs/tests", + "analysis/decompiled/decompiler-to-file-stubs/testData", + ) { + testClass { + model("additionalClsStubInfo", extension = null, recursive = false) + } + } + testGroup( "analysis/decompiled/decompiler-to-psi/tests", "analysis/decompiled/decompiler-to-file-stubs/testData",