diff --git a/analysis/decompiled/decompiler-to-stubs/src/org/jetbrains/kotlin/analysis/decompiler/stub/CallableClsStubBuilder.kt b/analysis/decompiled/decompiler-to-stubs/src/org/jetbrains/kotlin/analysis/decompiler/stub/CallableClsStubBuilder.kt index 8865c9dec55..41801d0ada5 100644 --- a/analysis/decompiled/decompiler-to-stubs/src/org/jetbrains/kotlin/analysis/decompiler/stub/CallableClsStubBuilder.kt +++ b/analysis/decompiled/decompiler-to-stubs/src/org/jetbrains/kotlin/analysis/decompiler/stub/CallableClsStubBuilder.kt @@ -208,7 +208,8 @@ private class FunctionClsStubBuilder( mayHaveContract = hasContract, runIf(hasContract) { ClsContractBuilder(c, typeStubBuilder).loadContract(functionProto) - } + }, + origin = createStubOrigin(protoContainer) ) } } @@ -280,7 +281,8 @@ private class PropertyClsStubBuilder( isExtension = propertyProto.hasReceiver(), hasReturnTypeRef = true, fqName = c.containerFqName.child(callableName), - initializer + initializer, + origin = createStubOrigin(protoContainer) ) } 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 4a5f2ff7877..c60c1135a41 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 @@ -9,6 +9,7 @@ import org.jetbrains.kotlin.analysis.decompiler.stub.flags.FlagsToModifiers import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.descriptors.SourceElement import org.jetbrains.kotlin.lexer.KtModifierKeywordToken +import org.jetbrains.kotlin.load.kotlin.FacadeClassSource import org.jetbrains.kotlin.load.kotlin.JvmPackagePartSource import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader @@ -221,6 +222,23 @@ fun createTargetedAnnotationStubs( } } +internal fun createStubOrigin(protoContainer: ProtoContainer): KotlinStubOrigin? { + if (protoContainer is ProtoContainer.Package) { + val source = protoContainer.source + if (source is FacadeClassSource) { + val className = source.className.internalName + val facadeClassName = source.facadeClassName?.internalName + if (facadeClassName != null) { + return KotlinStubOrigin.MultiFileFacade(className, facadeClassName) + } + + return KotlinStubOrigin.Facade(className) + } + } + + return null +} + val MessageLite.annotatedCallableKind: AnnotatedCallableKind get() = when (this) { is ProtoBuf.Property -> AnnotatedCallableKind.PROPERTY diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/stubBased/deserialization/JvmStubBasedFirDeserializedSymbolProvider.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/stubBased/deserialization/JvmStubBasedFirDeserializedSymbolProvider.kt index a791633df7f..298b7ea57b3 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/stubBased/deserialization/JvmStubBasedFirDeserializedSymbolProvider.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/stubBased/deserialization/JvmStubBasedFirDeserializedSymbolProvider.kt @@ -6,7 +6,6 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.stubBased.deserialization import com.intellij.openapi.project.Project -import com.intellij.openapi.vfs.VirtualFile import com.intellij.psi.search.GlobalSearchScope import org.jetbrains.kotlin.analysis.low.level.api.fir.providers.LLFirKotlinSymbolProvider import org.jetbrains.kotlin.analysis.low.level.api.fir.util.LLFirKotlinSymbolNamesProvider @@ -27,6 +26,7 @@ import org.jetbrains.kotlin.fir.scopes.FirKotlinScopeProvider import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.name.* import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.psi.stubs.impl.* import org.jetbrains.kotlin.resolve.jvm.JvmClassName import org.jetbrains.kotlin.serialization.deserialization.MetadataPackageFragment import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty @@ -124,11 +124,7 @@ internal open class JvmStubBasedFirDeserializedSymbolProvider( StubBasedAnnotationDeserializer(session), kotlinScopeProvider, parentContext = context, - containerSource = if (initialOrigin == FirDeclarationOrigin.BuiltIns) null else JvmFromStubDecompilerSource( - JvmClassName.byClassId( - classId - ) - ), + containerSource = if (initialOrigin == FirDeclarationOrigin.BuiltIns) null else JvmStubDeserializedContainerSource(classId), deserializeNestedClass = this::getClass, initialOrigin = initialOrigin ) @@ -146,14 +142,20 @@ internal open class JvmStubBasedFirDeserializedSymbolProvider( return ArrayList(topLevelFunctions.size).apply { for (function in topLevelFunctions) { val file = function.containingKtFile - val virtualFile = file.virtualFile.takeIf { it.extension != MetadataPackageFragment.METADATA_FILE_EXTENSION } ?: continue - val facadeClassName = computeFacadeClassName(file, virtualFile) + if (file.virtualFile.extension == MetadataPackageFragment.METADATA_FILE_EXTENSION) { + continue + } - if (initialOrigin != FirDeclarationOrigin.BuiltIns && facadeClassName.internalName in KotlinBuiltins) continue + val functionStub = function.stub as? KotlinFunctionStubImpl ?: loadStubByElement(function) + val containerSource = getFacadeContainerSource(function.containingKtFile, functionStub?.origin) + + if (initialOrigin != FirDeclarationOrigin.BuiltIns && containerSource.className.internalName in KotlinBuiltins) { + continue + } val symbol = FirNamedFunctionSymbol(callableId) val rootContext = StubBasedFirDeserializationContext - .createRootContext(session, moduleData, callableId, function, symbol, initialOrigin) + .createRootContext(session, moduleData, callableId, function, symbol, initialOrigin, containerSource) add(rootContext.memberDeserializer.loadFunction(function, null, session, symbol).symbol) } @@ -165,18 +167,36 @@ internal open class JvmStubBasedFirDeserializedSymbolProvider( return buildList { for (property in topLevelProperties) { + val propertyStub = property.stub as? KotlinPropertyStubImpl ?: loadStubByElement(property) + val containerSource = getFacadeContainerSource(property.containingKtFile, propertyStub?.origin) + val symbol = FirPropertySymbol(callableId) val rootContext = StubBasedFirDeserializationContext - .createRootContext(session, moduleData, callableId, property, symbol, initialOrigin) + .createRootContext(session, moduleData, callableId, property, symbol, initialOrigin, containerSource) add(rootContext.memberDeserializer.loadProperty(property, null, symbol).symbol) } } } - private fun computeFacadeClassName(file: KtFile, virtualFile: VirtualFile = file.virtualFile): JvmClassName { - val internalName = file.packageFqName.asString().replace(".", "/") + "/" + virtualFile.nameWithoutExtension - return JvmClassName.byInternalName(internalName) + private fun getFacadeContainerSource(file: KtFile, origin: KotlinStubOrigin?): JvmStubDeserializedFacadeContainerSource { + return when (origin) { + is KotlinStubOrigin.Facade -> { + val className = JvmClassName.byInternalName(origin.className) + JvmStubDeserializedFacadeContainerSource(className, facadeClassName = null) + } + is KotlinStubOrigin.MultiFileFacade -> { + val className = JvmClassName.byInternalName(origin.className) + val facadeClassName = JvmClassName.byInternalName(origin.className) + JvmStubDeserializedFacadeContainerSource(className, facadeClassName) + } + else -> { + val virtualFile = file.virtualFile + val classId = ClassId(file.packageFqName, Name.identifier(virtualFile.nameWithoutExtension)) + val className = JvmClassName.byClassId(classId) + JvmStubDeserializedFacadeContainerSource(className, facadeClassName = null) + } + } } private fun getClass( diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/stubBased/deserialization/JvmFromStubDecompilerSource.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/stubBased/deserialization/JvmStubDeserializedContainerSource.kt similarity index 54% rename from analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/stubBased/deserialization/JvmFromStubDecompilerSource.kt rename to analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/stubBased/deserialization/JvmStubDeserializedContainerSource.kt index f26d75f693a..ef7dfdd3844 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/stubBased/deserialization/JvmFromStubDecompilerSource.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/stubBased/deserialization/JvmStubDeserializedContainerSource.kt @@ -6,10 +6,7 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.stubBased.deserialization import org.jetbrains.kotlin.descriptors.SourceFile -import org.jetbrains.kotlin.load.kotlin.FacadeClassSource -import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion import org.jetbrains.kotlin.name.ClassId -import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.resolve.jvm.JvmClassName import org.jetbrains.kotlin.serialization.deserialization.IncompatibleVersionErrorData import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerAbiStability @@ -17,20 +14,20 @@ import org.jetbrains.kotlin.serialization.deserialization.descriptors.Deserializ //required for LLFirDependenciesSymbolProvider#jvmClassName, to resolve ambiguities //todo check if moving builtins to stubs would solve the issue -internal class JvmFromStubDecompilerSource( - override val className: JvmClassName, - override val facadeClassName: JvmClassName? = null, - override val incompatibility: IncompatibleVersionErrorData? = null, - override val isPreReleaseInvisible: Boolean = false, - override val abiStability: DeserializedContainerAbiStability = DeserializedContainerAbiStability.STABLE, -) : DeserializedContainerSource, FacadeClassSource { - constructor(packageName: FqName) : - this(JvmClassName.byClassId(ClassId.topLevel(JvmClassName.byInternalName(packageName.asString()).fqNameForTopLevelClassMaybeWithDollars))) +internal class JvmStubDeserializedContainerSource(classId: ClassId) : DeserializedContainerSource { + private val className = JvmClassName.byClassId(classId) - override fun getContainingFile(): SourceFile { - return SourceFile.NO_SOURCE_FILE - } + override val incompatibility: IncompatibleVersionErrorData<*>? + get() = null + + override val isPreReleaseInvisible: Boolean + get() = false + + override val abiStability: DeserializedContainerAbiStability + get() = DeserializedContainerAbiStability.STABLE override val presentableString: String get() = className.internalName + + override fun getContainingFile(): SourceFile = SourceFile.NO_SOURCE_FILE } \ No newline at end of file diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/stubBased/deserialization/JvmStubDeserializedFacadeContainerSource.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/stubBased/deserialization/JvmStubDeserializedFacadeContainerSource.kt new file mode 100644 index 00000000000..55584de1f05 --- /dev/null +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/stubBased/deserialization/JvmStubDeserializedFacadeContainerSource.kt @@ -0,0 +1,32 @@ +/* + * 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.low.level.api.fir.stubBased.deserialization + +import org.jetbrains.kotlin.descriptors.SourceFile +import org.jetbrains.kotlin.load.kotlin.FacadeClassSource +import org.jetbrains.kotlin.resolve.jvm.JvmClassName +import org.jetbrains.kotlin.serialization.deserialization.IncompatibleVersionErrorData +import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerAbiStability +import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource + +internal class JvmStubDeserializedFacadeContainerSource( + override val className: JvmClassName, + override val facadeClassName: JvmClassName? +) : DeserializedContainerSource, FacadeClassSource { + override val incompatibility: IncompatibleVersionErrorData<*>? + get() = null + + override val isPreReleaseInvisible: Boolean + get() = false + + override val abiStability: DeserializedContainerAbiStability + get() = DeserializedContainerAbiStability.STABLE + + override val presentableString: String + get() = className.internalName + + override fun getContainingFile(): SourceFile = SourceFile.NO_SOURCE_FILE +} \ No newline at end of file diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/stubBased/deserialization/StubBasedFirMemberDeserializer.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/stubBased/deserialization/StubBasedFirMemberDeserializer.kt index f8a2b2cab9f..f408acbdb70 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/stubBased/deserialization/StubBasedFirMemberDeserializer.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/stubBased/deserialization/StubBasedFirMemberDeserializer.kt @@ -142,19 +142,21 @@ internal class StubBasedFirDeserializationContext( callableId: CallableId, parameterListOwner: KtTypeParameterListOwner, symbol: FirBasedSymbol<*>, - initialOrigin: FirDeclarationOrigin - ): StubBasedFirDeserializationContext = createRootContext( - moduleData, - StubBasedAnnotationDeserializer(session), - callableId.packageName, - callableId.className, - parameterListOwner, - containerSource = if (initialOrigin == FirDeclarationOrigin.BuiltIns || callableId.packageName.isRoot) - null else JvmFromStubDecompilerSource(callableId.packageName), - outerClassSymbol = null, - symbol, - initialOrigin - ) + initialOrigin: FirDeclarationOrigin, + containerSource: DeserializedContainerSource + ): StubBasedFirDeserializationContext { + return createRootContext( + moduleData, + StubBasedAnnotationDeserializer(session), + callableId.packageName, + callableId.className, + parameterListOwner, + containerSource = containerSource.takeIf { initialOrigin != FirDeclarationOrigin.BuiltIns }, + outerClassSymbol = null, + symbol, + initialOrigin + ) + } } } 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 5d63f8d7cf3..bfead7fceb2 100644 --- a/compiler/psi/src/org/jetbrains/kotlin/psi/stubs/KotlinStubVersions.kt +++ b/compiler/psi/src/org/jetbrains/kotlin/psi/stubs/KotlinStubVersions.kt @@ -23,12 +23,12 @@ object KotlinStubVersions { // Though only kotlin declarations (no code in the bodies) are stubbed, please do increase this version // if you are not 100% sure it can be avoided. // Increasing this version will lead to reindexing of all kotlin source files on the first IDE startup with the new version. - const val SOURCE_STUB_VERSION = 153 + const val SOURCE_STUB_VERSION = 154 // 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 = 91 + private const val BINARY_STUB_VERSION = 92 // 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/KtFunctionElementType.java b/compiler/psi/src/org/jetbrains/kotlin/psi/stubs/elements/KtFunctionElementType.java index 41d9ba912db..a8800b6a0a2 100644 --- a/compiler/psi/src/org/jetbrains/kotlin/psi/stubs/elements/KtFunctionElementType.java +++ b/compiler/psi/src/org/jetbrains/kotlin/psi/stubs/elements/KtFunctionElementType.java @@ -29,6 +29,7 @@ import org.jetbrains.kotlin.psi.KtNamedFunction; import org.jetbrains.kotlin.psi.psiUtil.KtPsiUtilKt; import org.jetbrains.kotlin.psi.stubs.KotlinFunctionStub; import org.jetbrains.kotlin.psi.stubs.impl.KotlinFunctionStubImpl; +import org.jetbrains.kotlin.psi.stubs.impl.KotlinStubOrigin; import java.io.IOException; @@ -52,7 +53,8 @@ public class KtFunctionElementType extends KtStubElementType) parentStub, StringRef.fromString(psi.getName()), isTopLevel, fqName, isExtension, hasBlockBody, hasBody, psi.hasTypeParameterListBeforeFunctionName(), psi.mayHaveContract(), - null + /* contract = */ null, + /* origin = */ null ); } @@ -70,8 +72,14 @@ public class KtFunctionElementType extends KtStubElementType) parentStub, name, isTopLevel, fqName, isExtension, hasBlockBody, hasBody, - hasTypeParameterListBeforeFunctionName, mayHaveContract, mayHaveContract ? KotlinFunctionStubImpl.Companion.deserializeContract(dataStream) : null + hasTypeParameterListBeforeFunctionName, mayHaveContract, + mayHaveContract ? KotlinFunctionStubImpl.Companion.deserializeContract(dataStream) : null, + KotlinStubOrigin.deserialize(dataStream) ); } diff --git a/compiler/psi/src/org/jetbrains/kotlin/psi/stubs/elements/KtPropertyElementType.java b/compiler/psi/src/org/jetbrains/kotlin/psi/stubs/elements/KtPropertyElementType.java index 09263724f6b..3ece691d21e 100644 --- a/compiler/psi/src/org/jetbrains/kotlin/psi/stubs/elements/KtPropertyElementType.java +++ b/compiler/psi/src/org/jetbrains/kotlin/psi/stubs/elements/KtPropertyElementType.java @@ -30,6 +30,7 @@ import org.jetbrains.kotlin.psi.psiUtil.KtPsiUtilKt; import org.jetbrains.kotlin.psi.stubs.KotlinPropertyStub; import org.jetbrains.kotlin.psi.stubs.impl.KotlinConstantValueKt; import org.jetbrains.kotlin.psi.stubs.impl.KotlinPropertyStubImpl; +import org.jetbrains.kotlin.psi.stubs.impl.KotlinStubOrigin; import java.io.IOException; @@ -50,7 +51,9 @@ public class KtPropertyElementType extends KtStubElementType constantInitializer = stub instanceof KotlinPropertyStubImpl ? ((KotlinPropertyStubImpl) stub).getConstantInitializer() : null; - if (constantInitializer != null) { - KotlinConstantValueKt.serialize(constantInitializer, dataStream); - } - else { - dataStream.writeInt(-1); + + if (stub instanceof KotlinPropertyStubImpl) { + KotlinPropertyStubImpl stubImpl = (KotlinPropertyStubImpl) stub; + + ConstantValue constantInitializer = ((KotlinPropertyStubImpl) stub).getConstantInitializer(); + if (constantInitializer != null) { + KotlinConstantValueKt.serialize(constantInitializer, dataStream); + } else { + dataStream.writeInt(-1); + } + + KotlinStubOrigin.serialize(stubImpl.getOrigin(), dataStream); } } @@ -93,7 +102,8 @@ public class KtPropertyElementType extends KtStubElementType) parentStub, name, isVar, isTopLevel, hasDelegate, hasDelegateExpression, hasInitializer, - hasReceiverTypeRef, hasReturnTypeRef, fqName, KotlinConstantValueKt.createConstantValue(dataStream) + hasReceiverTypeRef, hasReturnTypeRef, fqName, KotlinConstantValueKt.createConstantValue(dataStream), + KotlinStubOrigin.deserialize(dataStream) ); } diff --git a/compiler/psi/src/org/jetbrains/kotlin/psi/stubs/impl/KotlinFunctionStubImpl.kt b/compiler/psi/src/org/jetbrains/kotlin/psi/stubs/impl/KotlinFunctionStubImpl.kt index 53c04741fe9..51fff71bda5 100644 --- a/compiler/psi/src/org/jetbrains/kotlin/psi/stubs/impl/KotlinFunctionStubImpl.kt +++ b/compiler/psi/src/org/jetbrains/kotlin/psi/stubs/impl/KotlinFunctionStubImpl.kt @@ -38,7 +38,8 @@ class KotlinFunctionStubImpl( private val hasBody: Boolean, private val hasTypeParameterListBeforeFunctionName: Boolean, private val mayHaveContract: Boolean, - val contract: List>? + val contract: List>?, + val origin: KotlinStubOrigin? ) : KotlinStubBaseImpl(parent, KtStubElementTypes.FUNCTION), KotlinFunctionStub { init { if (isTopLevel && fqName == null) { diff --git a/compiler/psi/src/org/jetbrains/kotlin/psi/stubs/impl/KotlinPropertyStubImpl.kt b/compiler/psi/src/org/jetbrains/kotlin/psi/stubs/impl/KotlinPropertyStubImpl.kt index c63d3599667..4eec9e7070b 100644 --- a/compiler/psi/src/org/jetbrains/kotlin/psi/stubs/impl/KotlinPropertyStubImpl.kt +++ b/compiler/psi/src/org/jetbrains/kotlin/psi/stubs/impl/KotlinPropertyStubImpl.kt @@ -36,7 +36,8 @@ class KotlinPropertyStubImpl( private val isExtension: Boolean, private val hasReturnTypeRef: Boolean, private val fqName: FqName?, - val constantInitializer: ConstantValue<*>? + val constantInitializer: ConstantValue<*>?, + val origin: KotlinStubOrigin? ) : KotlinStubBaseImpl(parent, KtStubElementTypes.PROPERTY), KotlinPropertyStub { init { diff --git a/compiler/psi/src/org/jetbrains/kotlin/psi/stubs/impl/KotlinStubOrigin.kt b/compiler/psi/src/org/jetbrains/kotlin/psi/stubs/impl/KotlinStubOrigin.kt new file mode 100644 index 00000000000..aebf69a96b8 --- /dev/null +++ b/compiler/psi/src/org/jetbrains/kotlin/psi/stubs/impl/KotlinStubOrigin.kt @@ -0,0 +1,77 @@ +/* + * 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.psi.stubs.impl + +import com.intellij.psi.stubs.StubInputStream +import com.intellij.psi.stubs.StubOutputStream + +sealed class KotlinStubOrigin { + companion object { + @JvmStatic + fun serialize(origin: KotlinStubOrigin?, dataStream: StubOutputStream) { + if (origin == null) { + dataStream.writeInt(0) + } else { + dataStream.writeInt(origin.kind) + origin.serializeContent(dataStream) + } + } + + @JvmStatic + fun deserialize(dataStream: StubInputStream): KotlinStubOrigin? { + return when (dataStream.readInt()) { + Facade.KIND -> Facade.deserializeContent(dataStream) + MultiFileFacade.KIND -> MultiFileFacade.deserializeContent(dataStream) + else -> null + } + } + } + + protected abstract val kind: Int + + protected abstract fun serializeContent(dataStream: StubOutputStream) + + data class Facade( + val className: String // Internal name of the package part class + ) : KotlinStubOrigin() { + companion object { + const val KIND = 1 + + fun deserializeContent(dataStream: StubInputStream): Facade? { + val className = dataStream.readNameString() ?: return null + return Facade(className) + } + } + + override val kind: Int get() = KIND + + override fun serializeContent(dataStream: StubOutputStream) { + dataStream.writeName(className) + } + } + + data class MultiFileFacade( + val className: String, // Internal name of the package part class + val facadeClassName: String // Internal name of the facade class + ) : KotlinStubOrigin() { + companion object { + const val KIND = 2 + + fun deserializeContent(dataStream: StubInputStream): MultiFileFacade? { + val classId = dataStream.readNameString() ?: return null + val facadeClassId = dataStream.readNameString() ?: return null + return MultiFileFacade(classId, facadeClassId) + } + } + + override val kind: Int get() = Facade.KIND + + override fun serializeContent(dataStream: StubOutputStream) { + dataStream.writeName(className) + dataStream.writeName(facadeClassName) + } + } +} \ No newline at end of file