Permalink
Browse files

Write multifile part->facade mapping to .kotlin_module

  • Loading branch information...
1 parent 6c1cadf commit 69bfc5b4bbfe9dbfa54edf4be498a94daca60fcf @udalov udalov committed Jan 9, 2017
Oops, something went wrong.
@@ -185,13 +185,13 @@ private PackagePartRegistry buildNewPackagePartRegistry(@NotNull FqName packageF
final String packageFqNameAsString = packageFqName.asString();
return new PackagePartRegistry() {
@Override
- public void addPart(@NotNull String partShortName) {
+ public void addPart(@NotNull String partShortName, @Nullable String facadeShortName) {
PackageParts packageParts = partsGroupedByPackage.get(packageFqNameAsString);
if (packageParts == null) {
packageParts = new PackageParts(packageFqNameAsString);
partsGroupedByPackage.put(packageFqNameAsString, packageParts);
}
- packageParts.addPart(partShortName);
+ packageParts.addPart(partShortName, facadeShortName);
}
};
}
@@ -215,14 +215,13 @@ class MultifileClassCodegenImpl(
if (!state.generateDeclaredClassFilter.shouldGeneratePackagePart(file) || !file.hasDeclarationsForPartClass()) return
- val partInternalName = partType.internalName
- packagePartRegistry.addPart(partInternalName.substring(partInternalName.lastIndexOf('/') + 1))
+ packagePartRegistry.addPart(partType.internalName.substringAfterLast('/'), facadeClassType.internalName.substringAfterLast('/'))
val builder = state.factory.newVisitor(MultifileClassPart(file, packageFragment), partType, file)
MultifileClassPartCodegen(
builder, file, packageFragment,
- getSuperClassForPart(partInternalName),
+ getSuperClassForPart(partType.internalName),
shouldGeneratePartHierarchy,
partContext, state
).generate()
@@ -20,6 +20,7 @@
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.SmartList;
+import kotlin.text.StringsKt;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.codegen.context.PackageContext;
@@ -125,7 +126,7 @@ else if (declaration instanceof KtScript) {
if (!generatePackagePart || !state.getGenerateDeclaredClassFilter().shouldGeneratePackagePart(file)) return;
String name = fileClassType.getInternalName();
- packagePartRegistry.addPart(name.substring(name.lastIndexOf('/') + 1));
+ packagePartRegistry.addPart(StringsKt.substringAfterLast(name, '/', name), null);
ClassBuilder builder = state.getFactory().newVisitor(JvmDeclarationOriginKt.PackagePart(file, packageFragment), fileClassType, file);
@@ -17,5 +17,5 @@
package org.jetbrains.kotlin.codegen
interface PackagePartRegistry {
- fun addPart(partShortName: String)
+ fun addPart(partShortName: String, facadeShortName: String?)
}
@@ -30,6 +30,15 @@ message PackageTable {
message PackageParts {
required string package_fq_name = 1;
- // Short names of files, without extension, present in this package
+ // Short names of files, without extension, present in this package. Only single file facades and multi-file _parts_ are listed here
+ // (multi-file facades are not present in this list, they are defined below)
repeated string class_name = 2;
+
+ // For each class name listed above, index of the name of the corresponding multi-file facade class in multifile_facade_name + 1,
+ // or 0 if the class is not a multi-file part. If there's no value in this list at some index, the value is assumed to be 0.
+ // (e.g. if there are no multi-file classes in the module, this list is not going to exist at all)
+ repeated int32 multifile_facade_id = 3 [packed=true];
+
+ // Short names of multi-file facades, used in multifile_facade_id to store the part -> facade mapping.
+ repeated string multifile_facade_name = 4;
}
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.load.kotlin
import org.jetbrains.kotlin.serialization.jvm.JvmPackageTable
import java.io.ByteArrayInputStream
import java.io.DataInputStream
+import kotlin.comparisons.nullsLast
class ModuleMapping private constructor(val packageFqName2Parts: Map<String, PackageParts>, private val debugName: String) {
fun findPackageParts(packageFqName: String): PackageParts? {
@@ -43,62 +44,76 @@ class ModuleMapping private constructor(val packageFqName2Parts: Map<String, Pac
val version = JvmMetadataVersion(*IntArray(stream.readInt()) { stream.readInt() })
if (version.isCompatible()) {
- val parseFrom = JvmPackageTable.PackageTable.parseFrom(stream)
- if (parseFrom != null) {
- val packageFqNameParts = hashMapOf<String, PackageParts>().apply {
- addParts(this, parseFrom.packagePartsList, PackageParts::addPart)
- addParts(this, parseFrom.metadataPartsList, PackageParts::addMetadataPart)
+ val table = JvmPackageTable.PackageTable.parseFrom(stream) ?: return EMPTY
+ val result = hashMapOf<String, PackageParts>()
+
+ for (proto in table.packagePartsList) {
+ val packageParts = result.getOrPut(proto.packageFqName) { PackageParts(proto.packageFqName) }
+ for ((index, partShortName) in proto.classNameList.withIndex()) {
+ val multifileFacadeId = proto.multifileFacadeIdList.getOrNull(index)?.minus(1)
+ packageParts.addPart(partShortName, multifileFacadeId?.let(proto.multifileFacadeNameList::getOrNull))
}
- return ModuleMapping(packageFqNameParts, debugName ?: "<unknown>")
}
+
+ for (proto in table.metadataPartsList) {
+ val packageParts = result.getOrPut(proto.packageFqName) { PackageParts(proto.packageFqName) }
+ proto.classNameList.forEach(packageParts::addMetadataPart)
+ }
+
+ return ModuleMapping(result, debugName ?: "<unknown>")
}
else {
// TODO: consider reporting "incompatible ABI version" error for package parts
}
return EMPTY
}
-
- private inline fun addParts(
- result: MutableMap<String, PackageParts>,
- partsList: List<JvmPackageTable.PackageParts>,
- addPartOrMetadataPart: (PackageParts, String) -> Unit
- ) {
- for (proto in partsList) {
- PackageParts(proto.packageFqName).apply {
- result.put(proto.packageFqName, this)
- proto.classNameList.forEach { addPartOrMetadataPart(this, it) }
- }
- }
- }
}
}
class PackageParts(val packageFqName: String) {
+ // Short name of package part -> short name of the corresponding multifile facade (or null, if it's not a multifile part)
+ private val packageParts = linkedMapOf<String, String?>()
+
// See JvmPackageTable.PackageTable.package_parts
- val parts: Set<String> = linkedSetOf<String>()
+ val parts: Set<String> get() = packageParts.keys
// See JvmPackageTable.PackageTable.metadata_parts
- val metadataParts: Set<String> = linkedSetOf<String>()
+ val metadataParts: Set<String> = linkedSetOf()
- fun addPart(shortName: String) {
- (parts as MutableSet /* see KT-14663 */).add(shortName)
+ fun addPart(partShortName: String, facadeShortName: String?) {
+ packageParts[partShortName] = facadeShortName
}
fun removePart(shortName: String) {
- (parts as MutableSet).remove(shortName)
+ packageParts.remove(shortName)
}
fun addMetadataPart(shortName: String) {
- (metadataParts as MutableSet).add(shortName)
+ (metadataParts as MutableSet /* see KT-14663 */).add(shortName)
}
fun addTo(builder: JvmPackageTable.PackageTable.Builder) {
if (parts.isNotEmpty()) {
builder.addPackageParts(JvmPackageTable.PackageParts.newBuilder().apply {
packageFqName = this@PackageParts.packageFqName
- addAllClassName(parts.sorted())
+
+ val facadeNameToId = mutableMapOf<String, Int>()
+ for ((facadeName, partNames) in parts.groupBy { getMultifileFacadeName(it) }.toSortedMap(nullsLast())) {
+ for (partName in partNames.sorted()) {
+ addClassName(partName)
+ if (facadeName != null) {
+ addMultifileFacadeId(1 + facadeNameToId.getOrPut(facadeName) { facadeNameToId.size })
+ }
+ }
+ }
+
+ for ((facadeId, facadeName) in facadeNameToId.values.zip(facadeNameToId.keys).sortedBy(Pair<Int, String>::first)) {
+ assert(facadeId == multifileFacadeNameCount) { "Multifile facades are loaded incorrectly: $facadeNameToId" }
+ addMultifileFacadeName(facadeName)
+ }
})
}
+
if (metadataParts.isNotEmpty()) {
builder.addMetadataParts(JvmPackageTable.PackageParts.newBuilder().apply {
packageFqName = this@PackageParts.packageFqName
@@ -107,16 +122,21 @@ class PackageParts(val packageFqName: String) {
}
}
+ fun getMultifileFacadeName(partShortName: String): String? = packageParts[partShortName]
+
operator fun plusAssign(other: PackageParts) {
- other.parts.forEach(this::addPart)
+ for ((partShortName, facadeShortName) in other.packageParts) {
+ addPart(partShortName, facadeShortName)
+ }
other.metadataParts.forEach(this::addMetadataPart)
}
override fun equals(other: Any?) =
- other is PackageParts && other.packageFqName == packageFqName && other.parts == parts && other.metadataParts == metadataParts
+ other is PackageParts &&
+ other.packageFqName == packageFqName && other.packageParts == packageParts && other.metadataParts == metadataParts
override fun hashCode() =
- (packageFqName.hashCode() * 31 + parts.hashCode()) * 31 + metadataParts.hashCode()
+ (packageFqName.hashCode() * 31 + packageParts.hashCode()) * 31 + metadataParts.hashCode()
override fun toString() =
(parts + metadataParts).toString()
Oops, something went wrong.

0 comments on commit 69bfc5b

Please sign in to comment.