[cls] write flexible type information to cls
^KTIJ-25172 this information would be used to create resolved FirElements from stubs, so no ProtoBuf would be kept in memory
This commit is contained in:
+9
@@ -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()
|
||||||
|
}
|
||||||
+72
@@ -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<kotlin.Int .. kotlin.Int?>?
|
||||||
|
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.MutableCollection<kotlin.Int .. kotlin.Int?> .. kotlin.collections.Collection<kotlin.Int .. kotlin.Int?>?>?
|
||||||
|
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<kotlin.Int .. kotlin.Int?>?
|
||||||
|
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]
|
||||||
+15
@@ -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<Integer> bar();
|
||||||
|
|
||||||
|
@Mutable
|
||||||
|
public abstract java.util.Collection<java.util.Collection<Integer>> baz();
|
||||||
|
}
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
public class OuterClassesWithFlexibleArgs<K, L>(k: K, l: L) {
|
||||||
|
val baz = d.JavaClass.baz(k, l)
|
||||||
|
}
|
||||||
+40
@@ -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<L .. L?>?
|
||||||
|
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]
|
||||||
+13
@@ -0,0 +1,13 @@
|
|||||||
|
package d;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.*;
|
||||||
|
import kotlin.annotations.jvm.*;
|
||||||
|
|
||||||
|
public abstract class JavaClass<T> {
|
||||||
|
public class InnerClass<M> {}
|
||||||
|
|
||||||
|
@Mutable
|
||||||
|
public static <K, L> JavaClass<K>.InnerClass<L> baz(K k, L l) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
public class TypeParametersInFlexibleTypes<A, D>(val javaClass: d.JavaClass<A>, val t: D & Any) {
|
||||||
|
fun foo() = javaClass.foo()
|
||||||
|
|
||||||
|
val bar = javaClass.bar()
|
||||||
|
|
||||||
|
val baz = d.JavaClass.baz(t)
|
||||||
|
}
|
||||||
+94
@@ -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<A .. A?>?
|
||||||
|
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<D & Any .. D?>?
|
||||||
|
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]
|
||||||
+17
@@ -0,0 +1,17 @@
|
|||||||
|
package d;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.*;
|
||||||
|
import kotlin.annotations.jvm.*;
|
||||||
|
|
||||||
|
public abstract class JavaClass<T> {
|
||||||
|
@Nullable
|
||||||
|
public abstract T foo();
|
||||||
|
|
||||||
|
@Mutable
|
||||||
|
public abstract java.util.Collection<T> bar();
|
||||||
|
|
||||||
|
@Mutable
|
||||||
|
public static <K> java.util.Collection<K> baz(K t) {
|
||||||
|
return new java.util.ArrayList<>();
|
||||||
|
}
|
||||||
|
}
|
||||||
+80
@@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+123
@@ -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<VirtualFile>()
|
||||||
|
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<String>,
|
||||||
|
) {
|
||||||
|
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 <T> write(file: VirtualFile, id: String, value: T, writeValueFun: (DataOutput, T) -> Unit): CachedAttributeData<T> {
|
||||||
|
return CachedAttributeData(value, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun <T> read(file: VirtualFile, id: String, readValueFun: (DataInput) -> T): CachedAttributeData<T>? {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
+2
-114
@@ -5,55 +5,17 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.analysis.decompiler.stub.files
|
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.VirtualFile
|
||||||
import com.intellij.openapi.vfs.impl.jar.CoreJarFileSystem
|
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import com.intellij.psi.impl.DebugUtil
|
import com.intellij.psi.impl.DebugUtil
|
||||||
import com.intellij.psi.stubs.PsiFileStub
|
import com.intellij.psi.stubs.PsiFileStub
|
||||||
import com.intellij.psi.stubs.StubElement
|
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.name.SpecialNames
|
||||||
import org.jetbrains.kotlin.psi.stubs.impl.STUB_TO_STRING_PREFIX
|
import org.jetbrains.kotlin.psi.stubs.impl.STUB_TO_STRING_PREFIX
|
||||||
import org.jetbrains.kotlin.test.*
|
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||||
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.nio.file.Paths
|
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) {
|
fun runTest(testDirectory: String) {
|
||||||
val testDirectoryPath = Paths.get(testDirectory)
|
val testDirectoryPath = Paths.get(testDirectory)
|
||||||
val testData = TestData.createFromDirectory(testDirectoryPath)
|
val testData = TestData.createFromDirectory(testDirectoryPath)
|
||||||
@@ -73,43 +35,6 @@ abstract class AbstractStubBuilderTest : KotlinTestWithEnvironment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected abstract fun getStubToTest(classFile: VirtualFile): PsiFileStub<*>
|
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<VirtualFile>()
|
|
||||||
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<out PsiElement>.serializeToString(): String {
|
private fun StubElement<out PsiElement>.serializeToString(): String {
|
||||||
@@ -130,40 +55,3 @@ private fun serializeStubToString(stubElement: StubElement<*>): String {
|
|||||||
}.replace(", [", "[")
|
}.replace(", [", "[")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private data class TestData(
|
|
||||||
val directory: Path,
|
|
||||||
val mainKotlinFile: Path,
|
|
||||||
val expectedFile: Path,
|
|
||||||
val jvmFileName: String,
|
|
||||||
val additionalCompilerOptions: List<String>,
|
|
||||||
) {
|
|
||||||
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 <T> write(file: VirtualFile, id: String, value: T, writeValueFun: (DataOutput, T) -> Unit): CachedAttributeData<T> {
|
|
||||||
return CachedAttributeData(value, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun <T> read(file: VirtualFile, id: String, readValueFun: (DataInput) -> T): CachedAttributeData<T>? {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
+44
@@ -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/");
|
||||||
|
}
|
||||||
|
}
|
||||||
+53
-9
@@ -21,10 +21,7 @@ import org.jetbrains.kotlin.psi.*
|
|||||||
import org.jetbrains.kotlin.psi.stubs.KotlinUserTypeStub
|
import org.jetbrains.kotlin.psi.stubs.KotlinUserTypeStub
|
||||||
import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes
|
import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes
|
||||||
import org.jetbrains.kotlin.psi.stubs.impl.*
|
import org.jetbrains.kotlin.psi.stubs.impl.*
|
||||||
import org.jetbrains.kotlin.serialization.deserialization.DYNAMIC_TYPE_DESERIALIZER_ID
|
import org.jetbrains.kotlin.serialization.deserialization.*
|
||||||
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.utils.doNothing
|
import org.jetbrains.kotlin.utils.doNothing
|
||||||
|
|
||||||
// TODO: see DescriptorRendererOptions.excludedTypeAnnotationClasses for decompiler
|
// 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<ClassIdWithTarget>) {
|
private fun createTypeParameterStub(parent: KotlinStubBaseImpl<*>, type: Type, name: Name, annotations: List<ClassIdWithTarget>) {
|
||||||
createTypeAnnotationStubs(parent, type, annotations)
|
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)) {
|
if (Flags.DEFINITELY_NOT_NULL_TYPE.get(type.flags)) {
|
||||||
createDefinitelyNotNullTypeStub(parent, FqName.topLevel(name))
|
createDefinitelyNotNullTypeStub(parent, typeParameterClassId, upperBoundType)
|
||||||
} else {
|
} else {
|
||||||
val nullableParentWrapper = nullableTypeParent(parent, type)
|
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<KtIntersectionType>(parent, KtStubElementTypes.INTERSECTION_TYPE)
|
val intersectionType = KotlinPlaceHolderStubImpl<KtIntersectionType>(parent, KtStubElementTypes.INTERSECTION_TYPE)
|
||||||
val leftReference = KotlinPlaceHolderStubImpl<KtTypeReference>(intersectionType, KtStubElementTypes.TYPE_REFERENCE)
|
val leftReference = KotlinPlaceHolderStubImpl<KtTypeReference>(intersectionType, KtStubElementTypes.TYPE_REFERENCE)
|
||||||
createStubForTypeName(ClassId.topLevel(name), leftReference)
|
createStubForTypeName(classId, leftReference, { upperBoundType })
|
||||||
val rightReference = KotlinPlaceHolderStubImpl<KtTypeReference>(intersectionType, KtStubElementTypes.TYPE_REFERENCE)
|
val rightReference = KotlinPlaceHolderStubImpl<KtTypeReference>(intersectionType, KtStubElementTypes.TYPE_REFERENCE)
|
||||||
val userType = KotlinUserTypeStubImpl(rightReference)
|
val userType = KotlinUserTypeStubImpl(rightReference)
|
||||||
KotlinNameReferenceExpressionStubImpl(userType, StandardNames.FqNames.any.shortName().ref())
|
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()
|
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) }
|
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<ClassIdWithTarget>) {
|
private fun createTypeAnnotationStubs(parent: KotlinStubBaseImpl<*>, type: Type, annotations: List<ClassIdWithTarget>) {
|
||||||
val typeModifiers = getTypeModifiersAsWritten(type)
|
val typeModifiers = getTypeModifiersAsWritten(type)
|
||||||
if (annotations.isEmpty() && typeModifiers.isEmpty()) return
|
if (annotations.isEmpty() && typeModifiers.isEmpty()) return
|
||||||
|
|||||||
+2
-1
@@ -131,6 +131,7 @@ fun createStubForPackageName(packageDirectiveStub: KotlinPlaceHolderStubImpl<KtP
|
|||||||
fun createStubForTypeName(
|
fun createStubForTypeName(
|
||||||
typeClassId: ClassId,
|
typeClassId: ClassId,
|
||||||
parent: StubElement<out PsiElement>,
|
parent: StubElement<out PsiElement>,
|
||||||
|
upperBoundFun: ((Int) -> KotlinTypeBean?)? = null,
|
||||||
bindTypeArguments: (KotlinUserTypeStub, Int) -> Unit = { _, _ -> }
|
bindTypeArguments: (KotlinUserTypeStub, Int) -> Unit = { _, _ -> }
|
||||||
): KotlinUserTypeStub {
|
): KotlinUserTypeStub {
|
||||||
val substituteWithAny = typeClassId.isLocal
|
val substituteWithAny = typeClassId.isLocal
|
||||||
@@ -143,7 +144,7 @@ fun createStubForTypeName(
|
|||||||
|
|
||||||
fun recCreateStubForType(current: StubElement<out PsiElement>, level: Int): KotlinUserTypeStub {
|
fun recCreateStubForType(current: StubElement<out PsiElement>, level: Int): KotlinUserTypeStub {
|
||||||
val lastSegment = segments[level]
|
val lastSegment = segments[level]
|
||||||
val userTypeStub = KotlinUserTypeStubImpl(current)
|
val userTypeStub = KotlinUserTypeStubImpl(current, upperBoundFun?.invoke(level))
|
||||||
if (level + 1 < segments.size) {
|
if (level + 1 < segments.size) {
|
||||||
recCreateStubForType(userTypeStub, level + 1)
|
recCreateStubForType(userTypeStub, level + 1)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ object KotlinStubVersions {
|
|||||||
// Binary stub version should be increased if stub format (org.jetbrains.kotlin.psi.stubs.impl) is changed
|
// 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).
|
// 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).
|
// 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)
|
// 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.
|
// Increasing this version will lead to reindexing of all classfiles.
|
||||||
|
|||||||
+90
-5
@@ -21,9 +21,18 @@ import com.intellij.psi.stubs.StubInputStream;
|
|||||||
import com.intellij.psi.stubs.StubOutputStream;
|
import com.intellij.psi.stubs.StubOutputStream;
|
||||||
import org.jetbrains.annotations.NonNls;
|
import org.jetbrains.annotations.NonNls;
|
||||||
import org.jetbrains.annotations.NotNull;
|
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.KtUserType;
|
||||||
import org.jetbrains.kotlin.psi.stubs.KotlinUserTypeStub;
|
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<KotlinUserTypeStub, KtUserType> {
|
public class KtUserTypeElementType extends KtStubElementType<KotlinUserTypeStub, KtUserType> {
|
||||||
public KtUserTypeElementType(@NotNull @NonNls String debugName) {
|
public KtUserTypeElementType(@NotNull @NonNls String debugName) {
|
||||||
@@ -33,16 +42,92 @@ public class KtUserTypeElementType extends KtStubElementType<KotlinUserTypeStub,
|
|||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public KotlinUserTypeStub createStub(@NotNull KtUserType psi, StubElement parentStub) {
|
public KotlinUserTypeStub createStub(@NotNull KtUserType psi, StubElement parentStub) {
|
||||||
return new KotlinUserTypeStubImpl((StubElement<?>) parentStub);
|
return new KotlinUserTypeStubImpl((StubElement<?>) parentStub, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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<KotlinTypeArgumentBean> 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
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public KotlinUserTypeStub deserialize(@NotNull StubInputStream dataStream, StubElement parentStub) {
|
public KotlinUserTypeStub deserialize(@NotNull StubInputStream dataStream, StubElement parentStub) throws IOException {
|
||||||
return new KotlinUserTypeStubImpl((StubElement<?>) parentStub);
|
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<KotlinTypeArgumentBean> 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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,10 +18,36 @@ package org.jetbrains.kotlin.psi.stubs.impl
|
|||||||
|
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import com.intellij.psi.stubs.StubElement
|
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.KtUserType
|
||||||
import org.jetbrains.kotlin.psi.stubs.KotlinUserTypeStub
|
import org.jetbrains.kotlin.psi.stubs.KotlinUserTypeStub
|
||||||
import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes
|
import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes
|
||||||
|
|
||||||
class KotlinUserTypeStubImpl(
|
class KotlinUserTypeStubImpl(
|
||||||
parent: StubElement<out PsiElement>?
|
parent: StubElement<out PsiElement>?,
|
||||||
|
val upperBound: KotlinTypeBean? = null
|
||||||
) : KotlinStubBaseImpl<KtUserType>(parent, KtStubElementTypes.USER_TYPE), KotlinUserTypeStub
|
) : KotlinStubBaseImpl<KtUserType>(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<KotlinTypeArgumentBean>,
|
||||||
|
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
|
||||||
+10
@@ -6,6 +6,7 @@
|
|||||||
package org.jetbrains.kotlin.generators.tests.analysis.api
|
package org.jetbrains.kotlin.generators.tests.analysis.api
|
||||||
|
|
||||||
import org.jetbrains.kotlin.analysis.decompiler.psi.AbstractByDecompiledPsiStubBuilderTest
|
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.analysis.decompiler.stub.files.AbstractClsStubBuilderTest
|
||||||
import org.jetbrains.kotlin.generators.TestGroupSuite
|
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<AbstractAdditionalStubInfoTest> {
|
||||||
|
model("additionalClsStubInfo", extension = null, recursive = false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
testGroup(
|
testGroup(
|
||||||
"analysis/decompiled/decompiler-to-psi/tests",
|
"analysis/decompiled/decompiler-to-psi/tests",
|
||||||
"analysis/decompiled/decompiler-to-file-stubs/testData",
|
"analysis/decompiled/decompiler-to-file-stubs/testData",
|
||||||
|
|||||||
Reference in New Issue
Block a user