Support JvmPackageName annotation in binary format

The main changes are in jvm_package_table.proto and ModuleMapping.kt.
With JvmPackageName, package parts can now have a JVM package name that
differs from their Kotlin name. So, in addition to the old package parts
which were stored as short names + short name of multifile facade (we
can't change this because of compatibility with old compilers), we now
store separately those package parts, which have a different JVM package
name. The format is optimized to avoid storing any package name more
than once as a string.

Another notable change is in KotlinCliJavaFileManagerImpl, where we now
load .kotlin_module files when determining whether or not a package
exists. Before this change, no PsiPackage (and thus, no JavaPackage and
eventually, no LazyJavaPackageFragment) was created unless there was at
least one file in the corresponding directory. Now we also create
packages if they are "mapped" to other JVM packages, i.e. if all package
parts in them have been annotated with JvmPackageName.

Most of the other changes are refactorings to allow internal names of
package parts/multifile classes where previously there were only short
names.
This commit is contained in:
Alexander Udalov
2017-09-06 15:14:47 +03:00
parent d07b628e0c
commit 70ae1596fb
44 changed files with 2614 additions and 657 deletions
@@ -197,9 +197,9 @@ public class ClassFileFactory implements OutputFileCollection {
private PackagePartRegistry buildNewPackagePartRegistry(@NotNull FqName packageFqName) {
String packageFqNameAsString = packageFqName.asString();
return (partShortName, facadeShortName) -> {
return (partInternalName, facadeInternalName) -> {
PackageParts packageParts = partsGroupedByPackage.computeIfAbsent(packageFqNameAsString, PackageParts::new);
packageParts.addPart(partShortName, facadeShortName);
packageParts.addPart(partInternalName, facadeInternalName);
};
}
@@ -209,7 +209,7 @@ class MultifileClassCodegenImpl(
if (!state.generateDeclaredClassFilter.shouldGeneratePackagePart(file) || !file.hasDeclarationsForPartClass()) return
packagePartRegistry.addPart(partType.internalName.substringAfterLast('/'), facadeClassType.internalName.substringAfterLast('/'))
packagePartRegistry.addPart(partType.internalName, facadeClassType.internalName)
val builder = state.factory.newVisitor(MultifileClassPart(file, packageFragment), partType, file)
@@ -20,7 +20,6 @@ import com.intellij.openapi.application.ApplicationManager;
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;
@@ -123,8 +122,7 @@ public class PackageCodegenImpl implements PackageCodegen {
if (!generatePackagePart || !state.getGenerateDeclaredClassFilter().shouldGeneratePackagePart(file)) return;
String name = fileClassType.getInternalName();
packagePartRegistry.addPart(StringsKt.substringAfterLast(name, '/', name), null);
packagePartRegistry.addPart(fileClassType.getInternalName(), 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, facadeShortName: String?)
fun addPart(partInternalName: String, facadeInternalName: String?)
}
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.load.kotlin.JvmMetadataVersion
import org.jetbrains.kotlin.load.kotlin.ModuleMapping
import org.jetbrains.kotlin.load.kotlin.PackageParts
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
import org.jetbrains.kotlin.serialization.jvm.JvmPackageTable
import java.io.ByteArrayOutputStream
@@ -43,9 +44,8 @@ private fun Iterable<PackageParts>.addCompiledParts(state: GenerationState): Lis
val mapping = ModuleMapping.create(moduleMappingData, "<incremental>", state.deserializationConfiguration)
incrementalCache.getObsoletePackageParts().forEach { internalName ->
val qualifier = internalName.substringBeforeLast('/', "").replace('/', '.')
val name = internalName.substringAfterLast('/')
mapping.findPackageParts(qualifier)?.removePart(name)
val qualifier = JvmClassName.byInternalName(internalName).packageFqName.asString()
mapping.findPackageParts(qualifier)?.removePart(internalName)
}
return (this + mapping.packageFqName2Parts.values)
@@ -253,12 +253,13 @@ public class KotlinTypeMapper {
@NotNull
private static ContainingClassesInfo forPackageMember(
@NotNull FqName packageFqName,
@NotNull String facadeClassName,
@NotNull String implClassName
@NotNull JvmClassName facadeName,
@NotNull JvmClassName partName
) {
return new ContainingClassesInfo(ClassId.topLevel(packageFqName.child(Name.identifier(facadeClassName))),
ClassId.topLevel(packageFqName.child(Name.identifier(implClassName))));
return new ContainingClassesInfo(
ClassId.topLevel(facadeName.getFqNameForTopLevelClassMaybeWithDollars()),
ClassId.topLevel(partName.getFqNameForTopLevelClassMaybeWithDollars())
);
}
@NotNull
@@ -326,27 +327,24 @@ public class KotlinTypeMapper {
return new ContainingClassesInfo(FAKE_CLASS_ID_FOR_BUILTINS, FAKE_CLASS_ID_FOR_BUILTINS);
}
Name implClassName = UtilKt.getImplClassNameForDeserialized(descriptor);
JvmClassName implClassName = UtilKt.getImplClassNameForDeserialized(descriptor);
assert implClassName != null : "No implClassName for " + descriptor;
String implSimpleName = implClassName.asString();
String facadeSimpleName;
JvmClassName facadeName;
if (containingDeclaration instanceof LazyJavaPackageFragment) {
facadeSimpleName = ((LazyJavaPackageFragment) containingDeclaration).getFacadeSimpleNameForPartSimpleName(implSimpleName);
if (facadeSimpleName == null) return null;
facadeName = ((LazyJavaPackageFragment) containingDeclaration).getFacadeNameForPartName(implClassName);
if (facadeName == null) return null;
}
else if (containingDeclaration instanceof IncrementalMultifileClassPackageFragment) {
facadeSimpleName = ((IncrementalMultifileClassPackageFragment) containingDeclaration).getMultifileClassName().asString();
facadeName = ((IncrementalMultifileClassPackageFragment) containingDeclaration).getFacadeName();
}
else {
throw new AssertionError("Unexpected package fragment for " + descriptor + ": " +
containingDeclaration + " (" + containingDeclaration.getClass().getSimpleName() + ")");
}
return ContainingClassesInfo.forPackageMember(
((PackageFragmentDescriptor) containingDeclaration).getFqName(), facadeSimpleName, implSimpleName
);
return ContainingClassesInfo.forPackageMember(facadeName, implClassName);
}
@NotNull