Fix generating cls stubs when is metadata using type tables (KT-23345)
Affected cases: - return type for suspend lambda - aliased type in type alias declaration - using type alias instead of aliased type in declarations #KT-23345 Fixed
This commit is contained in:
@@ -28,7 +28,7 @@ object KotlinStubVersions {
|
||||
// Binary stub version should be increased if stub format (org.jetbrains.kotlin.psi.stubs.impl) is changed
|
||||
// or changes are made to the core stub building code (org.jetbrains.kotlin.idea.decompiler.stubBuilder).
|
||||
// Increasing this version will lead to reindexing of all binary files that are potentially kotlin binaries (including all class files).
|
||||
private const val BINARY_STUB_VERSION = 64
|
||||
private const val BINARY_STUB_VERSION = 66
|
||||
|
||||
// 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.
|
||||
|
||||
@@ -35,3 +35,5 @@ val DO_NOTHING_2: (Any?, Any?) -> Unit = { _, _ -> }
|
||||
val DO_NOTHING_3: (Any?, Any?, Any?) -> Unit = { _, _, _ -> }
|
||||
|
||||
fun <T> doNothing(): (T) -> Unit = DO_NOTHING
|
||||
|
||||
fun doNothing() {}
|
||||
+11
-2
@@ -40,6 +40,7 @@ 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.js.DynamicTypeDeserializer
|
||||
import org.jetbrains.kotlin.utils.doNothing
|
||||
import java.util.*
|
||||
|
||||
// TODO: see DescriptorRendererOptions.excludedTypeAnnotationClasses for decompiler
|
||||
@@ -47,7 +48,11 @@ private val ANNOTATIONS_NOT_LOADED_FOR_TYPES = setOf(KotlinBuiltIns.FQ_NAMES.par
|
||||
|
||||
class TypeClsStubBuilder(private val c: ClsStubBuilderContext) {
|
||||
fun createTypeReferenceStub(parent: StubElement<out PsiElement>, type: Type, additionalAnnotations: () -> List<ClassIdWithTarget> = { emptyList() }) {
|
||||
if (type.hasAbbreviatedType()) return createTypeReferenceStub(parent, type.abbreviatedType, additionalAnnotations)
|
||||
val abbreviatedType = type.abbreviatedType(c.typeTable)
|
||||
if (abbreviatedType != null) {
|
||||
return createTypeReferenceStub(parent, abbreviatedType, additionalAnnotations)
|
||||
}
|
||||
|
||||
val typeReference = KotlinPlaceHolderStubImpl<KtTypeReference>(parent, KtStubElementTypes.TYPE_REFERENCE)
|
||||
|
||||
val annotations = c.components.annotationLoader.loadTypeAnnotations(type, c.nameResolver).filterNot {
|
||||
@@ -64,6 +69,9 @@ class TypeClsStubBuilder(private val c: ClsStubBuilderContext) {
|
||||
createTypeParameterStub(typeReference, type, c.typeParameters[type.typeParameter], allAnnotations)
|
||||
type.hasTypeParameterName() ->
|
||||
createTypeParameterStub(typeReference, type, c.nameResolver.getName(type.typeParameterName), allAnnotations)
|
||||
else -> {
|
||||
doNothing()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -208,7 +216,8 @@ class TypeClsStubBuilder(private val c: ClsStubBuilderContext) {
|
||||
createTypeReferenceStub(functionType, returnType)
|
||||
}
|
||||
else {
|
||||
createTypeReferenceStub(functionType, suspendParameterType.getArgument(0).type)
|
||||
val continuationArgumentType = suspendParameterType.getArgument(0).type(c.typeTable)!!
|
||||
createTypeReferenceStub(functionType, continuationArgumentType)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-1
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.psi.stubs.impl.KotlinTypeAliasStubImpl
|
||||
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.metadata.deserialization.underlyingType
|
||||
|
||||
fun createTypeAliasStub(
|
||||
parent: StubElement<out PsiElement>,
|
||||
@@ -57,5 +58,6 @@ fun createTypeAliasStub(
|
||||
createAnnotationStubs(typeAliasProto.annotationList.map { context.nameResolver.getClassId(it.id) }, modifierList)
|
||||
}
|
||||
|
||||
typeStubBuilder.createTypeReferenceStub(typeAlias, typeAliasProto.underlyingType)
|
||||
val typeAliasUnderlyingType = typeAliasProto.underlyingType(context.typeTable)
|
||||
typeStubBuilder.createTypeReferenceStub(typeAlias, typeAliasUnderlyingType)
|
||||
}
|
||||
|
||||
+31
-8
@@ -45,11 +45,23 @@ abstract class AbstractClsStubBuilderTest : LightCodeInsightFixtureTestCase() {
|
||||
null
|
||||
}
|
||||
|
||||
val classFile = getClassFileToDecompile(sourcePath, jvmFileName)
|
||||
|
||||
val txtFilePath = File("$sourcePath/${lastSegment(sourcePath)}.txt")
|
||||
|
||||
testClsStubsForFile(classFile, txtFilePath)
|
||||
testWithEnabledStringTable(sourcePath, jvmFileName, txtFilePath)
|
||||
testWithDisabledStringTable(sourcePath, jvmFileName, txtFilePath)
|
||||
}
|
||||
|
||||
private fun testWithEnabledStringTable(sourcePath: String, classFileName: String?, txtFile: File?) {
|
||||
doTest(sourcePath, true, classFileName, txtFile)
|
||||
}
|
||||
|
||||
private fun testWithDisabledStringTable(sourcePath: String, classFileName: String?, txtFile: File?) {
|
||||
doTest(sourcePath, false, classFileName, txtFile)
|
||||
}
|
||||
|
||||
protected fun doTest(sourcePath: String, useStringTable: Boolean, classFileName: String?, txtFile: File?) {
|
||||
val classFile = getClassFileToDecompile(sourcePath, useStringTable, classFileName)
|
||||
testClsStubsForFile(classFile, txtFile)
|
||||
}
|
||||
|
||||
protected fun testClsStubsForFile(classFile: VirtualFile, txtFile: File?) {
|
||||
@@ -64,9 +76,16 @@ abstract class AbstractClsStubBuilderTest : LightCodeInsightFixtureTestCase() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun getClassFileToDecompile(sourcePath: String, classFileName: String?): VirtualFile {
|
||||
private fun getClassFileToDecompile(sourcePath: String, isUseStringTable: Boolean, classFileName: String?): VirtualFile {
|
||||
val outDir = KotlinTestUtils.tmpDir("libForStubTest-" + sourcePath)
|
||||
MockLibraryUtil.compileKotlin(sourcePath, outDir, extraOptions = listOf("-Xallow-kotlin-package"))
|
||||
|
||||
val extraOptions = ArrayList<String>()
|
||||
extraOptions.add("-Xallow-kotlin-package")
|
||||
if (isUseStringTable) {
|
||||
extraOptions.add("-Xuse-type-table")
|
||||
}
|
||||
|
||||
MockLibraryUtil.compileKotlin(sourcePath, outDir, extraOptions = extraOptions)
|
||||
val root = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(outDir)!!
|
||||
|
||||
return root.findClassFileByName(classFileName ?: lastSegment(sourcePath))
|
||||
@@ -84,9 +103,13 @@ fun StubElement<out PsiElement>.serializeToString(): String {
|
||||
fun VirtualFile.findClassFileByName(className: String): VirtualFile {
|
||||
val files = LinkedHashSet<VirtualFile>()
|
||||
VfsUtilCore.iterateChildrenRecursively(
|
||||
this,
|
||||
{ virtualFile -> virtualFile.isDirectory || virtualFile.name == "$className.class" },
|
||||
{ virtualFile -> if (!virtualFile.isDirectory) files.addIfNotNull(virtualFile); true })
|
||||
this,
|
||||
{ virtualFile ->
|
||||
virtualFile.isDirectory || virtualFile.name == "$className.class"
|
||||
},
|
||||
{ virtualFile ->
|
||||
if (!virtualFile.isDirectory) files.addIfNotNull(virtualFile); true
|
||||
})
|
||||
|
||||
return files.single()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user