Cleanup after review

+ stub builder test for multifile class
This commit is contained in:
Dmitry Petrov
2015-09-09 15:12:12 +03:00
parent 8162272106
commit cd341e957e
16 changed files with 202 additions and 96 deletions
@@ -65,36 +65,32 @@ public class MultifileClassCodegen(
// We can do this (probably without 'compiledPackageFragment') after modifications to part codegen.
private val classBuilder = ClassBuilderOnDemand {
val filesWithTopLevelCallables = files.filter { hasTopLevelCallables(it) }
val sourceFile = filesWithTopLevelCallables.firstOrNull()
val originFile = files.firstOrNull()
val actualPackageFragment = packageFragment ?:
compiledPackageFragment ?:
throw AssertionError("No package fragment for multifile facade $facadeFqName; files: $files")
val declarationOrigin = MultifileClass(sourceFile, actualPackageFragment, facadeFqName)
val classBuilder = state.factory.newVisitor(declarationOrigin, facadeClassType, filesWithTopLevelCallables)
val declarationOrigin = MultifileClass(originFile, actualPackageFragment, facadeFqName)
val classBuilder = state.factory.newVisitor(declarationOrigin, facadeClassType, files)
classBuilder.defineClass(sourceFile, Opcodes.V1_6, FACADE_CLASS_ATTRIBUTES,
val filesWithCallables = files.filter { it.declarations.any { it is JetNamedFunction || it is JetProperty } }
val singleSourceFile = filesWithCallables.singleOrNull()
classBuilder.defineClass(singleSourceFile, Opcodes.V1_6, FACADE_CLASS_ATTRIBUTES,
facadeClassType.internalName,
null, "java/lang/Object", ArrayUtil.EMPTY_STRING_ARRAY)
sourceFile?.let { classBuilder.visitSource(it.name, null) }
if (singleSourceFile != null) {
classBuilder.visitSource(singleSourceFile.name, null)
}
classBuilder
}
private fun hasTopLevelCallables(file: JetFile) =
file.declarations.any { it is JetNamedFunction || it is JetProperty }
public fun generate(errorHandler: CompilationErrorHandler) {
val bindings = ArrayList<JvmSerializationBindings>(files.size() + 1)
val generateCallableMemberTasks = HashMap<CallableMemberDescriptor, () -> Unit>()
val partFqNames = arrayListOf<FqName>()
for (file in files) {
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
try {
val partClassBuilder = generatePart(file, generateCallableMemberTasks, partFqNames)
if (partClassBuilder != null) {
bindings.add(partClassBuilder.serializationBindings)
}
generatePart(file, generateCallableMemberTasks, partFqNames)
}
catch (e: ProcessCanceledException) {
throw e
@@ -113,13 +109,12 @@ public class MultifileClassCodegen(
// generateDelegationsToPreviouslyCompiled(generateCallableMemberTasks)
if (!generateCallableMemberTasks.isEmpty()) {
generateMultifileFacadeClass(generateCallableMemberTasks, bindings, partFqNames)
generateMultifileFacadeClass(generateCallableMemberTasks, partFqNames)
}
}
private fun generateMultifileFacadeClass(
tasks: Map<CallableMemberDescriptor, () -> Unit>,
bindings: MutableList<JvmSerializationBindings>,
partFqNames: List<FqName>
) {
MemberCodegen.generateModuleNameField(state, classBuilder)
@@ -128,8 +123,7 @@ public class MultifileClassCodegen(
tasks[member]!!()
}
bindings.add(classBuilder.serializationBindings)
writeKotlinMultifileFacadeAnnotationIfNeeded(JvmSerializationBindings.union(bindings), partFqNames)
writeKotlinMultifileFacadeAnnotationIfNeeded(partFqNames)
}
public fun generateClassOrObject(classOrObject: JetClassOrObject) {
@@ -196,21 +190,10 @@ public class MultifileClassCodegen(
return builder
}
private fun writeKotlinMultifileFacadeAnnotationIfNeeded(bindings: JvmSerializationBindings, partFqNames: List<FqName>) {
private fun writeKotlinMultifileFacadeAnnotationIfNeeded(partFqNames: List<FqName>) {
if (state.classBuilderMode != ClassBuilderMode.FULL) return
if (files.any { it.isScript }) return
val serializer = DescriptorSerializer.createTopLevel(JvmSerializerExtension(bindings, state.typeMapper))
val packageFragments = arrayListOf<PackageFragmentDescriptor>()
ContainerUtil.addIfNotNull(packageFragments, packageFragment)
ContainerUtil.addIfNotNull(packageFragments, compiledPackageFragment)
val facadeProto = serializer.packageProto(packageFragments, /* skip= */ { true }).build()
val strings = serializer.stringTable
val nameResolver = NameResolver(strings.serializeSimpleNames(), strings.serializeQualifiedNames())
val facadeData = PackageData(nameResolver, facadeProto)
val av = classBuilder.newAnnotation(AsmUtil.asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_MULTIFILE_CLASS), true)
av.visit(JvmAnnotationNames.ABI_VERSION_FIELD_NAME, JvmAbi.VERSION)
@@ -221,12 +204,6 @@ public class MultifileClassCodegen(
}
filePartClassNamesArray.visitEnd()
val dataArray = av.visitArray(JvmAnnotationNames.DATA_FIELD_NAME)
for (string in BitEncoding.encodeBytes(SerializationUtil.serializePackageData(facadeData))) {
dataArray.visit(null, string)
}
dataArray.visitEnd()
av.visitEnd()
}
@@ -48,8 +48,7 @@ public enum class JvmDeclarationOriginKind {
public class JvmDeclarationOrigin(
public val originKind: JvmDeclarationOriginKind,
public val element: PsiElement?,
public val descriptor: DeclarationDescriptor?,
public val multifileClassFqName: FqName? = null
public val descriptor: DeclarationDescriptor?
) {
companion object {
public val NO_ORIGIN: JvmDeclarationOrigin = JvmDeclarationOrigin(OTHER, null, null)
@@ -71,10 +70,13 @@ public fun Bridge(descriptor: DeclarationDescriptor, element: PsiElement? = Desc
public fun PackageFacade(descriptor: PackageFragmentDescriptor): JvmDeclarationOrigin = JvmDeclarationOrigin(PACKAGE_FACADE, null, descriptor)
public fun PackagePart(file: JetFile, descriptor: PackageFragmentDescriptor): JvmDeclarationOrigin = JvmDeclarationOrigin(PACKAGE_PART, file, descriptor)
public fun MultifileClass(someFile: JetFile?, descriptor: PackageFragmentDescriptor, multifileClassFqName: FqName): JvmDeclarationOrigin =
JvmDeclarationOrigin(MULTIFILE_CLASS, someFile, descriptor, multifileClassFqName)
/**
* @param representativeFile one of the files representing this multifile class (will be used for diagnostics)
*/
public fun MultifileClass(representativeFile: JetFile?, descriptor: PackageFragmentDescriptor, multifileClassFqName: FqName): JvmDeclarationOrigin =
JvmDeclarationOrigin(MULTIFILE_CLASS, representativeFile, descriptor)
public fun MultifileClassPart(file: JetFile, descriptor: PackageFragmentDescriptor, multifileClassFqName: FqName): JvmDeclarationOrigin =
JvmDeclarationOrigin(MULTIFILE_CLASS_PART, file, descriptor, multifileClassFqName)
JvmDeclarationOrigin(MULTIFILE_CLASS_PART, file, descriptor)
public fun TraitImpl(element: JetClassOrObject, descriptor: ClassDescriptor): JvmDeclarationOrigin = JvmDeclarationOrigin(TRAIT_IMPL, element, descriptor)
public fun DelegationToTraitImpl(element: PsiElement?, descriptor: FunctionDescriptor): JvmDeclarationOrigin =
@@ -23,6 +23,7 @@ import com.intellij.psi.stubs.PsiFileStubImpl
import com.intellij.psi.tree.IStubFileElementType
import com.intellij.util.io.StringRef
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.JetFile
import org.jetbrains.kotlin.psi.stubs.KotlinFileStub
import org.jetbrains.kotlin.psi.stubs.KotlinImportDirectiveStub
@@ -67,9 +68,19 @@ public class KotlinFileStubImpl(
public fun forFileFacadeStub(facadeFqName: FqName, isScript: Boolean): KotlinFileStubImpl =
KotlinFileStubImpl(jetFile = null,
packageName = StringRef.fromString(facadeFqName.parent().asString())!!,
facadeSimpleName = StringRef.fromString(facadeFqName.shortName().asString())!!,
partSimpleName = StringRef.fromString(facadeFqName.shortName().asString())!!,
packageName = facadeFqName.parent().stringRef(),
facadeSimpleName = facadeFqName.shortName().stringRef(),
partSimpleName = facadeFqName.shortName().stringRef(),
isScript = isScript)
public fun forMultifileClassStub(facadeFqName: FqName, isScript: Boolean): KotlinFileStubImpl =
KotlinFileStubImpl(jetFile = null,
packageName = facadeFqName.parent().stringRef(),
facadeSimpleName = facadeFqName.shortName().stringRef(),
partSimpleName = null,
isScript = isScript)
private fun FqName.stringRef() = StringRef.fromString(asString())!!
private fun Name.stringRef() = StringRef.fromString(asString())!!
}
}
@@ -95,7 +95,6 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor
return headerKind == CLASS ||
headerKind == PACKAGE_FACADE ||
headerKind == FILE_FACADE ||
headerKind == MULTIFILE_CLASS ||
headerKind == MULTIFILE_CLASS_PART;
}
@@ -24,5 +24,4 @@ public @interface KotlinMultifileClass {
int abiVersion();
String[] filePartClassNames();
String[] data();
}
@@ -89,10 +89,7 @@ public object HasCompiledKotlinInJar : JarUserDataManager.JarBooleanPropertyCoun
JarUserDataManager.hasFileWithProperty(HasCompiledKotlinInJar, file) == false
}
public class ReadMultifileClassException(message: String): RuntimeException(message)
public fun findMultifileClassParts(file: VirtualFile, multifileClass: KotlinJvmBinaryClass): List<KotlinJvmBinaryClass> {
val result = arrayListOf<KotlinClassHeader>()
val packageFqName = multifileClass.classId.packageFqName
val partsFinder = DirectoryBasedClassFinder(file.parent!!, packageFqName)
val partNames = multifileClass.classHeader.filePartClassNames ?: return emptyList()
@@ -101,14 +98,5 @@ public fun findMultifileClassParts(file: VirtualFile, multifileClass: KotlinJvmB
}.filterNotNull()
}
@Throws(ReadMultifileClassException::class)
public fun readMultifileClassPartHeaders(file: VirtualFile, multifileClass: KotlinJvmBinaryClass): List<KotlinClassHeader> {
val classId = multifileClass.classId
val classHeader = multifileClass.classHeader
if (classHeader.filePartClassNames == null) {
throw ReadMultifileClassException("Multifile class $classId has no filePartClassNames or wrong ABI version: ${classHeader.version}")
}
else {
return findMultifileClassParts(file, multifileClass).map { it.classHeader }
}
}
public fun readMultifileClassPartHeaders(file: VirtualFile, multifileClass: KotlinJvmBinaryClass): List<KotlinClassHeader> =
findMultifileClassParts(file, multifileClass).map { it.classHeader }
@@ -22,7 +22,6 @@ import com.intellij.psi.compiled.ClsStubBuilder
import com.intellij.psi.impl.compiled.ClassFileStubBuilder
import com.intellij.psi.stubs.PsiFileStub
import com.intellij.util.indexing.FileContent
import org.jetbrains.kotlin.idea.decompiler.ReadMultifileClassException
import org.jetbrains.kotlin.idea.decompiler.isKotlinInternalCompiledFile
import org.jetbrains.kotlin.idea.decompiler.readMultifileClassPartHeaders
import org.jetbrains.kotlin.idea.decompiler.textBuilder.DirectoryBasedClassFinder
@@ -30,10 +29,11 @@ import org.jetbrains.kotlin.idea.decompiler.textBuilder.DirectoryBasedDataFinder
import org.jetbrains.kotlin.idea.decompiler.textBuilder.LoggingErrorReporter
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
import org.jetbrains.kotlin.load.kotlin.KotlinBinaryClassCache
import org.jetbrains.kotlin.load.kotlin.header.*
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.load.kotlin.header.isCompatibleClassKind
import org.jetbrains.kotlin.load.kotlin.header.isCompatibleFileFacadeKind
import org.jetbrains.kotlin.load.kotlin.header.isCompatibleMultifileClassKind
import org.jetbrains.kotlin.load.kotlin.header.isCompatiblePackageFacadeKind
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.JetFile
import org.jetbrains.kotlin.serialization.jvm.JvmProtoBufUtil
@@ -83,17 +83,8 @@ public open class KotlinClsStubBuilder : ClsStubBuilder() {
createFileFacadeStub(packageData.getPackageProto(), classId.asSingleFqName(), context)
}
header.isCompatibleMultifileClassKind() -> {
val packageData = JvmProtoBufUtil.readPackageDataFrom(annotationData)
val context = components.createContext(packageData.nameResolver, packageFqName)
val partHeaders =
try {
readMultifileClassPartHeaders(file, kotlinBinaryClass)
}
catch (e: ReadMultifileClassException) {
LOG.error(e.getMessage())
return null
}
createMultifileClassStub(partHeaders, classId.asSingleFqName(), context)
val partHeaders = readMultifileClassPartHeaders(file, kotlinBinaryClass)
createMultifileClassStub(partHeaders, classId.asSingleFqName(), components)
}
else -> throw IllegalStateException("Should have processed " + file.getPath() + " with header $header")
}
@@ -75,15 +75,15 @@ fun createFileFacadeStub(
fun createMultifileClassStub(
partHeaders: List<KotlinClassHeader>,
facadeFqName: FqName,
c: ClsStubBuilderContext
components: ClsStubBuilderComponents
): KotlinFileStubImpl {
val packageFqName = facadeFqName.parent()
val fileStub = KotlinFileStubImpl.forFileFacadeStub(facadeFqName, packageFqName.isRoot)
val fileStub = KotlinFileStubImpl.forMultifileClassStub(facadeFqName, packageFqName.isRoot)
setupFileStub(fileStub, packageFqName)
val multifileClassContainer = ProtoContainer(null, facadeFqName.parent())
val multifileClassContainer = ProtoContainer(null, packageFqName)
for (partHeader in partHeaders) {
val partData = JvmProtoBufUtil.readPackageDataFrom(partHeader.annotationData!!)
val partContext = c.child(partData.nameResolver)
val partContext = components.createContext(partData.nameResolver, packageFqName)
for (partMember in partData.packageProto.memberList) {
createCallableStub(fileStub, partMember, partContext, multifileClassContainer)
}
@@ -19,10 +19,8 @@ package org.jetbrains.kotlin.idea.decompiler.textBuilder
import com.intellij.openapi.util.TextRange
import com.intellij.openapi.vfs.VirtualFile
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.idea.decompiler.ReadMultifileClassException
import org.jetbrains.kotlin.idea.decompiler.findMultifileClassParts
import org.jetbrains.kotlin.idea.decompiler.navigation.JsMetaFileUtils
import org.jetbrains.kotlin.idea.decompiler.readMultifileClassPartHeaders
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.load.kotlin.KotlinBinaryClassCache
import org.jetbrains.kotlin.load.kotlin.PackageClassUtils
@@ -51,12 +49,6 @@ public val INCOMPATIBLE_ABI_VERSION_COMMENT: String =
"// Current compiler ABI version is $CURRENT_ABI_VERSION_MARKER\n" +
"// File ABI version is $FILE_ABI_VERSION_MARKER"
private val REASON = "REASON"
public val FILE_CANT_BE_DECOMPILED_DUE_TO_ERRORS: String =
"// This class file has inconsistent Kotlin meta-information and can't be decompiled.\n" +
"//\n" +
"// $REASON"
public fun buildDecompiledText(
classFile: VirtualFile,
resolver: ResolverForDecompiler = DeserializerForDecompiler(classFile)
@@ -3,10 +3,18 @@
package test
public val p: kotlin.Int /* compiled code */
public val val1b: kotlin.Int /* compiled code */
public fun f(): kotlin.Unit { /* compiled code */ }
private val kotlin.String.val2b: kotlin.Int /* compiled code */
private var i: kotlin.Int /* compiled code */
public fun fn1b(): kotlin.Unit { /* compiled code */ }
public fun kotlin.Int.plus(i: kotlin.Int /* = compiled code */): kotlin.Int { /* compiled code */ }
public fun kotlin.String.fn2b(): kotlin.Unit { /* compiled code */ }
public val val1a: kotlin.Int /* compiled code */
private val kotlin.String.val2a: kotlin.Int /* compiled code */
public fun fn1a(): kotlin.Unit { /* compiled code */ }
public fun kotlin.String.fn2a(): kotlin.Unit { /* compiled code */ }
@@ -2,9 +2,10 @@
@file:JvmMultifileClass
package test
private var i = 2
fun Int.plus(i: Int = 1) = this + i
public val val1a = 42
private val String.val2a: Int get() = 0
public fun fn1a() {}
public fun String.fn2a() {}
class ShouldNotBeVisible1
interface ShouldNotBeVisible2
@@ -2,5 +2,7 @@
@file:JvmMultifileClass
package test
fun f() {}
val p = 3
public val val1b = 42
private val String.val2b: Int get() = 0
public fun fn1b() {}
public fun String.fn2b() {}
@@ -0,0 +1,10 @@
@file:[JvmName("MultifileClass") JvmMultifileClass]
package test
fun p1Fun() {}
fun String.p1ExtFun() {}
fun p1ExprFun(): Int = 0
fun p1FunWithParams(x: Int): Int { return x }
val p1Val: Int = 0
val String.p1ExtVal: Int get() = 0
var p1Var: Int = 0
@@ -0,0 +1,113 @@
PsiJetFileStubImpl[package=test]
PACKAGE_DIRECTIVE:
REFERENCE_EXPRESSION:[referencedName=test]
IMPORT_LIST:
PROPERTY:[fqName=test.p1Val, hasDelegate=false, hasDelegateExpression=false, hasInitializer=false, hasReturnTypeRef=true, isExtension=false, isTopLevel=true, isVar=false, name=p1Val]
MODIFIER_LIST:[public]
TYPE_REFERENCE:
USER_TYPE:[isAbsoluteInRootPackage=false]
USER_TYPE:[isAbsoluteInRootPackage=false]
REFERENCE_EXPRESSION:[referencedName=kotlin]
REFERENCE_EXPRESSION:[referencedName=Int]
PROPERTY:[fqName=test.p1Var, hasDelegate=false, hasDelegateExpression=false, hasInitializer=false, hasReturnTypeRef=true, isExtension=false, isTopLevel=true, isVar=true, name=p1Var]
MODIFIER_LIST:[public]
TYPE_REFERENCE:
USER_TYPE:[isAbsoluteInRootPackage=false]
USER_TYPE:[isAbsoluteInRootPackage=false]
REFERENCE_EXPRESSION:[referencedName=kotlin]
REFERENCE_EXPRESSION:[referencedName=Int]
PROPERTY:[fqName=test.p1ExtVal, hasDelegate=false, hasDelegateExpression=false, hasInitializer=false, hasReturnTypeRef=true, isExtension=true, isTopLevel=true, isVar=false, name=p1ExtVal]
MODIFIER_LIST:[public]
TYPE_REFERENCE:
USER_TYPE:[isAbsoluteInRootPackage=false]
USER_TYPE:[isAbsoluteInRootPackage=false]
REFERENCE_EXPRESSION:[referencedName=kotlin]
REFERENCE_EXPRESSION:[referencedName=String]
TYPE_REFERENCE:
USER_TYPE:[isAbsoluteInRootPackage=false]
USER_TYPE:[isAbsoluteInRootPackage=false]
REFERENCE_EXPRESSION:[referencedName=kotlin]
REFERENCE_EXPRESSION:[referencedName=Int]
FUN:[fqName=test.p1ExprFun, hasBlockBody=true, hasBody=true, hasTypeParameterListBeforeFunctionName=false, isExtension=false, isTopLevel=true, name=p1ExprFun]
MODIFIER_LIST:[public]
VALUE_PARAMETER_LIST:
TYPE_REFERENCE:
USER_TYPE:[isAbsoluteInRootPackage=false]
USER_TYPE:[isAbsoluteInRootPackage=false]
REFERENCE_EXPRESSION:[referencedName=kotlin]
REFERENCE_EXPRESSION:[referencedName=Int]
FUN:[fqName=test.p1Fun, hasBlockBody=true, hasBody=true, hasTypeParameterListBeforeFunctionName=false, isExtension=false, isTopLevel=true, name=p1Fun]
MODIFIER_LIST:[public]
VALUE_PARAMETER_LIST:
TYPE_REFERENCE:
USER_TYPE:[isAbsoluteInRootPackage=false]
USER_TYPE:[isAbsoluteInRootPackage=false]
REFERENCE_EXPRESSION:[referencedName=kotlin]
REFERENCE_EXPRESSION:[referencedName=Unit]
FUN:[fqName=test.p1FunWithParams, hasBlockBody=true, hasBody=true, hasTypeParameterListBeforeFunctionName=false, isExtension=false, isTopLevel=true, name=p1FunWithParams]
MODIFIER_LIST:[public]
VALUE_PARAMETER_LIST:
VALUE_PARAMETER:[fqName=null, hasDefaultValue=false, hasValOrVar=false, isMutable=false, name=x]
TYPE_REFERENCE:
USER_TYPE:[isAbsoluteInRootPackage=false]
USER_TYPE:[isAbsoluteInRootPackage=false]
REFERENCE_EXPRESSION:[referencedName=kotlin]
REFERENCE_EXPRESSION:[referencedName=Int]
TYPE_REFERENCE:
USER_TYPE:[isAbsoluteInRootPackage=false]
USER_TYPE:[isAbsoluteInRootPackage=false]
REFERENCE_EXPRESSION:[referencedName=kotlin]
REFERENCE_EXPRESSION:[referencedName=Int]
FUN:[fqName=test.p1ExtFun, hasBlockBody=true, hasBody=true, hasTypeParameterListBeforeFunctionName=false, isExtension=true, isTopLevel=true, name=p1ExtFun]
MODIFIER_LIST:[public]
TYPE_REFERENCE:
USER_TYPE:[isAbsoluteInRootPackage=false]
USER_TYPE:[isAbsoluteInRootPackage=false]
REFERENCE_EXPRESSION:[referencedName=kotlin]
REFERENCE_EXPRESSION:[referencedName=String]
VALUE_PARAMETER_LIST:
TYPE_REFERENCE:
USER_TYPE:[isAbsoluteInRootPackage=false]
USER_TYPE:[isAbsoluteInRootPackage=false]
REFERENCE_EXPRESSION:[referencedName=kotlin]
REFERENCE_EXPRESSION:[referencedName=Unit]
PROPERTY:[fqName=test.p2Val, hasDelegate=false, hasDelegateExpression=false, hasInitializer=false, hasReturnTypeRef=true, isExtension=false, isTopLevel=true, isVar=false, name=p2Val]
MODIFIER_LIST:[public]
TYPE_REFERENCE:
USER_TYPE:[isAbsoluteInRootPackage=false]
USER_TYPE:[isAbsoluteInRootPackage=false]
REFERENCE_EXPRESSION:[referencedName=kotlin]
REFERENCE_EXPRESSION:[referencedName=Int]
PROPERTY:[fqName=test.p2ExtVal, hasDelegate=false, hasDelegateExpression=false, hasInitializer=false, hasReturnTypeRef=true, isExtension=true, isTopLevel=true, isVar=false, name=p2ExtVal]
MODIFIER_LIST:[public]
TYPE_REFERENCE:
USER_TYPE:[isAbsoluteInRootPackage=false]
USER_TYPE:[isAbsoluteInRootPackage=false]
REFERENCE_EXPRESSION:[referencedName=kotlin]
REFERENCE_EXPRESSION:[referencedName=String]
TYPE_REFERENCE:
USER_TYPE:[isAbsoluteInRootPackage=false]
USER_TYPE:[isAbsoluteInRootPackage=false]
REFERENCE_EXPRESSION:[referencedName=kotlin]
REFERENCE_EXPRESSION:[referencedName=Int]
FUN:[fqName=test.p2Fun, hasBlockBody=true, hasBody=true, hasTypeParameterListBeforeFunctionName=false, isExtension=false, isTopLevel=true, name=p2Fun]
MODIFIER_LIST:[public]
VALUE_PARAMETER_LIST:
TYPE_REFERENCE:
USER_TYPE:[isAbsoluteInRootPackage=false]
USER_TYPE:[isAbsoluteInRootPackage=false]
REFERENCE_EXPRESSION:[referencedName=kotlin]
REFERENCE_EXPRESSION:[referencedName=Unit]
FUN:[fqName=test.p2ExtFun, hasBlockBody=true, hasBody=true, hasTypeParameterListBeforeFunctionName=false, isExtension=true, isTopLevel=true, name=p2ExtFun]
MODIFIER_LIST:[public]
TYPE_REFERENCE:
USER_TYPE:[isAbsoluteInRootPackage=false]
USER_TYPE:[isAbsoluteInRootPackage=false]
REFERENCE_EXPRESSION:[referencedName=kotlin]
REFERENCE_EXPRESSION:[referencedName=String]
VALUE_PARAMETER_LIST:
TYPE_REFERENCE:
USER_TYPE:[isAbsoluteInRootPackage=false]
USER_TYPE:[isAbsoluteInRootPackage=false]
REFERENCE_EXPRESSION:[referencedName=kotlin]
REFERENCE_EXPRESSION:[referencedName=Unit]
@@ -0,0 +1,7 @@
@file:[JvmName("MultifileClass") JvmMultifileClass]
package test
fun p2Fun() {}
fun String.p2ExtFun() {}
val p2Val: Int = 0
val String.p2ExtVal: Int get() = 0
@@ -107,6 +107,12 @@ public class ClsStubBuilderTestGenerated extends AbstractClsStubBuilderTest {
doTest(fileName);
}
@TestMetadata("MultifileClass")
public void testMultifileClass() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/decompiler/stubBuilder/MultifileClass/");
doTest(fileName);
}
@TestMetadata("NestedClasses")
public void testNestedClasses() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/decompiler/stubBuilder/NestedClasses/");