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:
+1094
-268
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
||||
+11
-1
@@ -47,12 +47,19 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ
|
||||
private val perfCounter = PerformanceCounter.create("Find Java class")
|
||||
private lateinit var index: JvmDependenciesIndex
|
||||
private lateinit var singleJavaFileRootsIndex: SingleJavaFileRootsIndex
|
||||
private lateinit var packagePartProviders: List<JvmPackagePartProvider>
|
||||
private val topLevelClassesCache: MutableMap<FqName, VirtualFile?> = THashMap()
|
||||
private val allScope = GlobalSearchScope.allScope(myPsiManager.project)
|
||||
private var useFastClassFilesReading = false
|
||||
|
||||
fun initialize(index: JvmDependenciesIndex, singleJavaFileRootsIndex: SingleJavaFileRootsIndex, useFastClassFilesReading: Boolean) {
|
||||
fun initialize(
|
||||
index: JvmDependenciesIndex,
|
||||
packagePartProviders: List<JvmPackagePartProvider>,
|
||||
singleJavaFileRootsIndex: SingleJavaFileRootsIndex,
|
||||
useFastClassFilesReading: Boolean
|
||||
) {
|
||||
this.index = index
|
||||
this.packagePartProviders = packagePartProviders
|
||||
this.singleJavaFileRootsIndex = singleJavaFileRootsIndex
|
||||
this.useFastClassFilesReading = useFastClassFilesReading
|
||||
}
|
||||
@@ -180,6 +187,9 @@ class KotlinCliJavaFileManagerImpl(private val myPsiManager: PsiManager) : CoreJ
|
||||
//abort on first found
|
||||
false
|
||||
}
|
||||
if (!found) {
|
||||
found = packagePartProviders.any { it.findPackageParts(packageName).isNotEmpty() }
|
||||
}
|
||||
if (!found) {
|
||||
found = singleJavaFileRootsIndex.findJavaSourceClasses(packageFqName).isNotEmpty()
|
||||
}
|
||||
|
||||
@@ -234,6 +234,7 @@ class KotlinCoreEnvironment private constructor(
|
||||
|
||||
(ServiceManager.getService(project, CoreJavaFileManager::class.java) as KotlinCliJavaFileManagerImpl).initialize(
|
||||
rootsIndex,
|
||||
packagePartProviders,
|
||||
SingleJavaFileRootsIndex(singleJavaFileRoots),
|
||||
configuration.getBoolean(JVMConfigurationKeys.USE_FAST_CLASS_FILES_READING)
|
||||
)
|
||||
|
||||
@@ -18,7 +18,6 @@ package org.jetbrains.kotlin.fileClasses
|
||||
|
||||
import com.intellij.psi.util.CachedValueProvider
|
||||
import com.intellij.psi.util.CachedValuesManager
|
||||
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
|
||||
import org.jetbrains.kotlin.load.java.descriptors.getImplClassNameForDeserialized
|
||||
import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
@@ -39,10 +38,9 @@ object JvmFileClassUtil {
|
||||
|
||||
private const val MULTIFILE_PART_NAME_DELIMITER = "__"
|
||||
|
||||
fun getPartFqNameForDeserialized(descriptor: DeserializedMemberDescriptor): FqName {
|
||||
val implClassName = descriptor.getImplClassNameForDeserialized() ?: error("No implClassName for $descriptor")
|
||||
return (descriptor.containingDeclaration as PackageFragmentDescriptor).fqName.child(implClassName)
|
||||
}
|
||||
fun getPartFqNameForDeserialized(descriptor: DeserializedMemberDescriptor): FqName =
|
||||
descriptor.getImplClassNameForDeserialized()?.fqNameForTopLevelClassMaybeWithDollars
|
||||
?: error("No implClassName for $descriptor")
|
||||
|
||||
@JvmStatic
|
||||
fun getFileClassInternalName(file: KtFile): String =
|
||||
|
||||
+12
-18
@@ -64,36 +64,33 @@ class IncrementalPackageFragmentProvider(
|
||||
get() = this@IncrementalPackageFragmentProvider.target
|
||||
|
||||
fun getPackageFragmentForMultifileClass(multifileClassFqName: FqName): IncrementalMultifileClassPackageFragment? {
|
||||
val facadeInternalName = JvmClassName.byFqNameWithoutInnerClasses(multifileClassFqName).internalName
|
||||
val partsNames = incrementalCache.getStableMultifileFacadeParts(facadeInternalName) ?: return null
|
||||
return IncrementalMultifileClassPackageFragment(multifileClassFqName, partsNames)
|
||||
val facadeName = JvmClassName.byFqNameWithoutInnerClasses(multifileClassFqName)
|
||||
val partsNames = incrementalCache.getStableMultifileFacadeParts(facadeName.internalName) ?: return null
|
||||
return IncrementalMultifileClassPackageFragment(facadeName, partsNames, multifileClassFqName.parent())
|
||||
}
|
||||
|
||||
override fun getMemberScope(): MemberScope = MemberScope.Empty
|
||||
}
|
||||
|
||||
inner class IncrementalMultifileClassPackageFragment(
|
||||
private val multifileClassFqName: FqName,
|
||||
val partsInternalNames: Collection<String>
|
||||
) : PackageFragmentDescriptorImpl(moduleDescriptor, multifileClassFqName.parent()) {
|
||||
val facadeName: JvmClassName,
|
||||
val partsInternalNames: Collection<String>,
|
||||
packageFqName: FqName
|
||||
) : PackageFragmentDescriptorImpl(moduleDescriptor, packageFqName) {
|
||||
private val memberScope = storageManager.createLazyValue {
|
||||
ChainedMemberScope.create(
|
||||
"Member scope for incremental compilation: union of multifile class parts data for $multifileClassFqName",
|
||||
"Member scope for incremental compilation: union of multifile class parts data for $facadeName",
|
||||
partsInternalNames.mapNotNull { internalName ->
|
||||
incrementalCache.getPackagePartData(internalName)?.let { (data, strings) ->
|
||||
val (nameResolver, packageProto) = JvmProtoBufUtil.readPackageDataFrom(data, strings)
|
||||
|
||||
val jvmBinaryClass = kotlinClassFinder.findKotlinClass(
|
||||
ClassId.topLevel(FqName(internalName.replace('/', '.')))
|
||||
)
|
||||
val partName = JvmClassName.byInternalName(internalName)
|
||||
val jvmBinaryClass =
|
||||
kotlinClassFinder.findKotlinClass(ClassId.topLevel(partName.fqNameForTopLevelClassMaybeWithDollars))
|
||||
|
||||
DeserializedPackageMemberScope(
|
||||
this, packageProto, nameResolver,
|
||||
JvmPackagePartSource(
|
||||
JvmClassName.byInternalName(internalName),
|
||||
JvmClassName.byFqNameWithoutInnerClasses(multifileClassFqName.asString()),
|
||||
knownJvmBinaryClass = jvmBinaryClass
|
||||
),
|
||||
JvmPackagePartSource(partName, facadeName, knownJvmBinaryClass = jvmBinaryClass),
|
||||
deserializationComponents, classNames = { emptyList() }
|
||||
)
|
||||
}
|
||||
@@ -101,9 +98,6 @@ class IncrementalPackageFragmentProvider(
|
||||
)
|
||||
}
|
||||
|
||||
val multifileClassName: Name
|
||||
get() = multifileClassFqName.shortName()
|
||||
|
||||
override fun getMemberScope() = memberScope()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,9 +18,7 @@ package org.jetbrains.kotlin.resolve.jvm
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptorNonRoot
|
||||
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
|
||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
|
||||
import org.jetbrains.kotlin.load.java.descriptors.getImplClassNameForDeserialized
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||
import org.jetbrains.kotlin.resolve.OverloadFilter
|
||||
@@ -42,14 +40,8 @@ object JvmOverloadFilter : OverloadFilter {
|
||||
if (overload is ConstructorDescriptor) continue
|
||||
if (overload !is DeserializedCallableMemberDescriptor) continue
|
||||
|
||||
val containingDeclaration = overload.containingDeclaration
|
||||
if (containingDeclaration !is PackageFragmentDescriptor) {
|
||||
throw AssertionError("Package member expected; got $overload with containing declaration $containingDeclaration")
|
||||
}
|
||||
|
||||
val implClassName = overload.getImplClassNameForDeserialized() ?: throw AssertionError("No implClassName: $overload")
|
||||
val implClassFQN = containingDeclaration.fqName.child(implClassName)
|
||||
if (!sourceClassesFQNs.contains(implClassFQN)) {
|
||||
val implClassFQN = JvmFileClassUtil.getPartFqNameForDeserialized(overload)
|
||||
if (implClassFQN !in sourceClassesFQNs) {
|
||||
result.add(overload)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
// TARGET_BACKEND: JVM
|
||||
// WITH_RUNTIME
|
||||
// LANGUAGE_VERSION: 1.2
|
||||
|
||||
// FILE: foo.kt
|
||||
|
||||
@file:Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
|
||||
@file:JvmPackageName("jjj")
|
||||
|
||||
fun f(): String = "O"
|
||||
|
||||
val g: String? get() = "K"
|
||||
|
||||
inline fun i(block: () -> String) = block()
|
||||
|
||||
// FILE: bar.kt
|
||||
|
||||
fun box(): String = i { f() + g }
|
||||
@@ -0,0 +1,19 @@
|
||||
// TARGET_BACKEND: JVM
|
||||
// WITH_RUNTIME
|
||||
// LANGUAGE_VERSION: 1.2
|
||||
|
||||
// FILE: foo.kt
|
||||
|
||||
@file:Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
|
||||
@file:JvmPackageName("jjj")
|
||||
@file:JvmName("Foooo")
|
||||
|
||||
fun f(): String = "O"
|
||||
|
||||
val g: String? get() = "K"
|
||||
|
||||
inline fun i(block: () -> String) = block()
|
||||
|
||||
// FILE: bar.kt
|
||||
|
||||
fun box(): String = i { f() + g }
|
||||
@@ -0,0 +1,25 @@
|
||||
// IGNORE_BACKEND: NATIVE
|
||||
// FILE: A.kt
|
||||
// LANGUAGE_VERSION: 1.2
|
||||
|
||||
@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
|
||||
@file:JvmPackageName("bar")
|
||||
package foo
|
||||
|
||||
fun f() = "OK"
|
||||
|
||||
var v: Int = 1
|
||||
|
||||
inline fun i(block: () -> Unit) = block()
|
||||
|
||||
// FILE: B.kt
|
||||
|
||||
import foo.*
|
||||
|
||||
fun box(): String {
|
||||
v = 2
|
||||
if (v != 2) return "Fail"
|
||||
i { v = 3 }
|
||||
if (v != 3) return "Fail"
|
||||
return f()
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// IGNORE_BACKEND: NATIVE
|
||||
// FILE: A.kt
|
||||
// LANGUAGE_VERSION: 1.2
|
||||
|
||||
@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
|
||||
@file:JvmPackageName("bar")
|
||||
|
||||
fun f() = "OK"
|
||||
|
||||
var v: Int = 1
|
||||
|
||||
// FILE: B.kt
|
||||
|
||||
fun box(): String {
|
||||
v = 2
|
||||
if (v != 2) return "Fail"
|
||||
return f()
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// IGNORE_BACKEND: NATIVE
|
||||
// FILE: A.kt
|
||||
// LANGUAGE_VERSION: 1.2
|
||||
|
||||
@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
|
||||
@file:JvmPackageName("bar")
|
||||
@file:JvmName("Baz")
|
||||
package foo
|
||||
|
||||
fun f() = "OK"
|
||||
|
||||
var v: Int = 1
|
||||
|
||||
// FILE: B.kt
|
||||
|
||||
import foo.*
|
||||
|
||||
fun box(): String {
|
||||
v = 2
|
||||
if (v != 2) return "Fail"
|
||||
return f()
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
|
||||
@file:JvmPackageName("j")
|
||||
package bar
|
||||
|
||||
fun file0() {}
|
||||
@@ -0,0 +1,6 @@
|
||||
@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
|
||||
@file:JvmName("JJ")
|
||||
@file:JvmPackageName("jj")
|
||||
package bar
|
||||
|
||||
fun jj() {}
|
||||
@@ -0,0 +1,3 @@
|
||||
package foo
|
||||
|
||||
fun file1() {}
|
||||
@@ -0,0 +1,5 @@
|
||||
@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
|
||||
@file:JvmPackageName("jjj")
|
||||
package foo
|
||||
|
||||
fun file2() {}
|
||||
@@ -0,0 +1,5 @@
|
||||
@file:JvmMultifileClass
|
||||
@file:JvmName("MultiFoo")
|
||||
package foo
|
||||
|
||||
fun multiFile1() {}
|
||||
@@ -0,0 +1,7 @@
|
||||
bar
|
||||
j/BarAsJKt
|
||||
jj/JJ
|
||||
foo
|
||||
foo/MultiFoo__FooMultiFileKt (foo/MultiFoo)
|
||||
foo/FooKt
|
||||
jjj/FooAsJJJKt
|
||||
@@ -0,0 +1,5 @@
|
||||
@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
|
||||
@file:JvmPackageName("foo.jvm")
|
||||
package foo
|
||||
|
||||
fun foo1() {}
|
||||
@@ -0,0 +1,5 @@
|
||||
@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
|
||||
@file:JvmPackageName("foo.jvm")
|
||||
package foo
|
||||
|
||||
fun foo2() {}
|
||||
@@ -0,0 +1,5 @@
|
||||
@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
|
||||
@file:JvmPackageName("foo.jvm")
|
||||
package foo
|
||||
|
||||
fun foo3() {}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
foo
|
||||
foo/jvm/Foo1Kt
|
||||
foo/jvm/Foo2Kt
|
||||
foo/jvm/Foo3Kt
|
||||
@@ -1,10 +1,10 @@
|
||||
bar
|
||||
MultiBar__BarMultiFilePart1Kt (MultiBar)
|
||||
MultiBar__BarMultiFilePart2Kt (MultiBar)
|
||||
BarFileFacade1Kt
|
||||
bar/MultiBar__BarMultiFilePart1Kt (bar/MultiBar)
|
||||
bar/MultiBar__BarMultiFilePart2Kt (bar/MultiBar)
|
||||
bar/BarFileFacade1Kt
|
||||
foo
|
||||
AnotherMultiFoo__AnotherFooMultiFilePart1Kt (AnotherMultiFoo)
|
||||
MultiFoo__FooMultiFilePart1Kt (MultiFoo)
|
||||
MultiFoo__FooMultiFilePart2Kt (MultiFoo)
|
||||
FooFileFacade1Kt
|
||||
FooFileFacade2Kt
|
||||
foo/AnotherMultiFoo__AnotherFooMultiFilePart1Kt (foo/AnotherMultiFoo)
|
||||
foo/MultiFoo__FooMultiFilePart1Kt (foo/MultiFoo)
|
||||
foo/MultiFoo__FooMultiFilePart2Kt (foo/MultiFoo)
|
||||
foo/FooFileFacade1Kt
|
||||
foo/FooFileFacade2Kt
|
||||
|
||||
+12
@@ -10409,11 +10409,23 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/jvmPackageName"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
|
||||
}
|
||||
|
||||
@TestMetadata("rootPackage.kt")
|
||||
public void testRootPackage() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/jvmPackageName/rootPackage.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("simple.kt")
|
||||
public void testSimple() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/jvmPackageName/simple.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("withJvmName.kt")
|
||||
public void testWithJvmName() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/jvmPackageName/withJvmName.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/jvmStatic")
|
||||
|
||||
@@ -204,6 +204,7 @@ class KotlinCliJavaFileManagerTest : KotlinTestWithEnvironment() {
|
||||
val root = StandardFileSystems.local().findFileByPath(javaFilesDir.path)!!
|
||||
coreJavaFileManager.initialize(
|
||||
JvmDependenciesIndexImpl(listOf(JavaRoot(root, JavaRoot.RootType.SOURCE))),
|
||||
emptyList(),
|
||||
SingleJavaFileRootsIndex(emptyList()),
|
||||
useFastClassFilesReading = true
|
||||
)
|
||||
|
||||
@@ -10409,11 +10409,23 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/jvmPackageName"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
|
||||
}
|
||||
|
||||
@TestMetadata("rootPackage.kt")
|
||||
public void testRootPackage() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/jvmPackageName/rootPackage.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("simple.kt")
|
||||
public void testSimple() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/jvmPackageName/simple.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("withJvmName.kt")
|
||||
public void testWithJvmName() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/jvmPackageName/withJvmName.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/jvmStatic")
|
||||
|
||||
+18
@@ -138,6 +138,24 @@ public class CompileKotlinAgainstKotlinTestGenerated extends AbstractCompileKotl
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("jvmPackageName.kt")
|
||||
public void testJvmPackageName() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/compileKotlinAgainstKotlin/jvmPackageName.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("jvmPackageNameInRootPackage.kt")
|
||||
public void testJvmPackageNameInRootPackage() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/compileKotlinAgainstKotlin/jvmPackageNameInRootPackage.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("jvmPackageNameWithJvmName.kt")
|
||||
public void testJvmPackageNameWithJvmName() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/compileKotlinAgainstKotlin/jvmPackageNameWithJvmName.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("jvmStaticInObject.kt")
|
||||
public void testJvmStaticInObject() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/compileKotlinAgainstKotlin/jvmStaticInObject.kt");
|
||||
|
||||
@@ -19,14 +19,21 @@ package org.jetbrains.kotlin.codegen
|
||||
import org.jetbrains.kotlin.cli.AbstractCliTest
|
||||
import org.jetbrains.kotlin.cli.common.ExitCode
|
||||
import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler
|
||||
import org.jetbrains.kotlin.config.ApiVersion
|
||||
import org.jetbrains.kotlin.config.LanguageVersion
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
|
||||
import org.jetbrains.kotlin.load.kotlin.ModuleMapping
|
||||
import org.jetbrains.kotlin.serialization.deserialization.DeserializationConfiguration
|
||||
import org.jetbrains.kotlin.resolve.CompilerDeserializationConfiguration
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||
import org.jetbrains.kotlin.test.testFramework.KtUsefulTestCase
|
||||
import java.io.File
|
||||
|
||||
class JvmPackageTableTest : KtUsefulTestCase() {
|
||||
private fun doTest(relativeDirectory: String) {
|
||||
private fun doTest(
|
||||
relativeDirectory: String,
|
||||
compileWith: LanguageVersion = LanguageVersion.LATEST_STABLE,
|
||||
loadWith: LanguageVersion = LanguageVersion.LATEST_STABLE
|
||||
) {
|
||||
val directory = KotlinTestUtils.getTestDataPathBase() + relativeDirectory
|
||||
val tmpdir = KotlinTestUtils.tmpDir(this::class.simpleName)
|
||||
|
||||
@@ -34,14 +41,17 @@ class JvmPackageTableTest : KtUsefulTestCase() {
|
||||
val (output, exitCode) = AbstractCliTest.executeCompilerGrabOutput(K2JVMCompiler(), listOf(
|
||||
directory,
|
||||
"-d", tmpdir.path,
|
||||
"-module-name", moduleName
|
||||
"-module-name", moduleName,
|
||||
"-language-version", compileWith.versionString
|
||||
))
|
||||
System.err.println(output) // normally output is empty
|
||||
assertEquals("Compilation should complete successfully", ExitCode.OK, exitCode)
|
||||
|
||||
val mapping = ModuleMapping.create(
|
||||
File(tmpdir, "META-INF/$moduleName.${ModuleMapping.MAPPING_FILE_EXT}").readBytes(), "test",
|
||||
DeserializationConfiguration.Default
|
||||
CompilerDeserializationConfiguration(
|
||||
LanguageVersionSettingsImpl(loadWith, ApiVersion.createByLanguageVersion(loadWith))
|
||||
)
|
||||
)
|
||||
val result = buildString {
|
||||
for ((fqName, packageParts) in mapping.packageFqName2Parts) {
|
||||
@@ -66,4 +76,14 @@ class JvmPackageTableTest : KtUsefulTestCase() {
|
||||
fun testSimple() {
|
||||
doTest("/jvmPackageTable/simple")
|
||||
}
|
||||
|
||||
fun testJvmPackageName() {
|
||||
doTest("/jvmPackageTable/jvmPackageName",
|
||||
compileWith = LanguageVersion.KOTLIN_1_2, loadWith = LanguageVersion.KOTLIN_1_2)
|
||||
}
|
||||
|
||||
fun testJvmPackageNameManyParts() {
|
||||
doTest("/jvmPackageTable/jvmPackageNameManyParts",
|
||||
compileWith = LanguageVersion.KOTLIN_1_2, loadWith = LanguageVersion.KOTLIN_1_2)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10409,11 +10409,23 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/jvmPackageName"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
|
||||
}
|
||||
|
||||
@TestMetadata("rootPackage.kt")
|
||||
public void testRootPackage() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/jvmPackageName/rootPackage.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("simple.kt")
|
||||
public void testSimple() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/jvmPackageName/simple.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("withJvmName.kt")
|
||||
public void testWithJvmName() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/jvmPackageName/withJvmName.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/jvmStatic")
|
||||
|
||||
@@ -25,20 +25,37 @@ message PackageTable {
|
||||
|
||||
// Names of .kotlin_metadata files for each package
|
||||
repeated PackageParts metadata_parts = 2;
|
||||
|
||||
// Values of @JvmPackageName annotation used in this module; can be referenced in PackageParts#class_with_jvm_package_name_package_id.
|
||||
// The names here are dot-separated, e.g. "org.foo.bar"
|
||||
repeated string jvm_package_name = 3;
|
||||
}
|
||||
|
||||
message PackageParts {
|
||||
required string package_fq_name = 1;
|
||||
|
||||
// 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;
|
||||
// (multi-file facades are not present in this list, they are defined below). Only files whose JVM package name is equal to the
|
||||
// Kotlin package name (i.e. it has not been changed with @JvmPackageName) are listed here.
|
||||
repeated string short_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,
|
||||
// For each name in short_class_name, index of the name of the corresponding multi-file facade class in multifile_facade_short_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];
|
||||
repeated int32 multifile_facade_short_name_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;
|
||||
// Short names of multi-file facades, used in multifile_facade_short_name_id to store the part -> facade mapping.
|
||||
repeated string multifile_facade_short_name = 4;
|
||||
|
||||
// Short names of files (single file facades), whose JVM package differs from the Kotlin package because of @JvmPackageName.
|
||||
// The JVM package name of each file is stored at the same index in class_with_jvm_package_name_package_id.
|
||||
repeated string class_with_jvm_package_name_short_name = 5;
|
||||
|
||||
// For each name in class_with_jvm_package_name_short_name, the index (into PackageTable#jvm_package_name) of the JVM package name.
|
||||
// This list should have at least one element, otherwise classes with JVM package names are going to be ignored completely.
|
||||
//
|
||||
// If there's no value in this list at some index other than 0, the value is assumed to be the same as the value of the last element
|
||||
// of this list. The intended use case for this optimization is to have just a list of a single element in the most frequent case
|
||||
// when a bunch of files from the same Kotlin package have the same JVM package name.
|
||||
repeated int32 class_with_jvm_package_name_package_id = 6 [packed = true];
|
||||
}
|
||||
|
||||
@@ -22,9 +22,9 @@ import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
|
||||
import org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaStaticClassScope
|
||||
import org.jetbrains.kotlin.load.kotlin.JvmPackagePartSource
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedMemberDescriptor
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
|
||||
@@ -66,9 +66,8 @@ fun ClassDescriptor.getParentJavaStaticClassScope(): LazyJavaStaticClassScope? {
|
||||
return staticScope
|
||||
}
|
||||
|
||||
fun DeserializedMemberDescriptor.getImplClassNameForDeserialized(): Name? {
|
||||
return (containerSource as? JvmPackagePartSource)?.simpleName
|
||||
}
|
||||
fun DeserializedMemberDescriptor.getImplClassNameForDeserialized(): JvmClassName? =
|
||||
(containerSource as? JvmPackagePartSource)?.className
|
||||
|
||||
fun DeserializedMemberDescriptor.isFromJvmPackagePart(): Boolean =
|
||||
containerSource is JvmPackagePartSource
|
||||
|
||||
+7
-7
@@ -29,7 +29,7 @@ import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryPackageSourceElement
|
||||
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||
import org.jetbrains.kotlin.storage.getValue
|
||||
|
||||
class LazyJavaPackageFragment(
|
||||
@@ -40,7 +40,7 @@ class LazyJavaPackageFragment(
|
||||
|
||||
internal val binaryClasses by c.storageManager.createLazyValue {
|
||||
c.components.packageMapper.findPackageParts(fqName.asString()).mapNotNull { partName ->
|
||||
val classId = ClassId(fqName, Name.identifier(partName))
|
||||
val classId = ClassId.topLevel(JvmClassName.byInternalName(partName).fqNameForTopLevelClassMaybeWithDollars)
|
||||
c.components.kotlinClassFinder.findKotlinClass(classId)?.let { partName to it }
|
||||
}.toMap()
|
||||
}
|
||||
@@ -63,13 +63,13 @@ class LazyJavaPackageFragment(
|
||||
internal fun findClassifierByJavaClass(jClass: JavaClass): ClassDescriptor? = scope.javaScope.findClassifierByJavaClass(jClass)
|
||||
|
||||
private val partToFacade by c.storageManager.createLazyValue {
|
||||
val result = hashMapOf<String, String>()
|
||||
kotlinClasses@for ((partName, kotlinClass) in binaryClasses) {
|
||||
val result = hashMapOf<JvmClassName, JvmClassName>()
|
||||
kotlinClasses@for ((partInternalName, kotlinClass) in binaryClasses) {
|
||||
val partName = JvmClassName.byInternalName(partInternalName)
|
||||
val header = kotlinClass.classHeader
|
||||
when (header.kind) {
|
||||
KotlinClassHeader.Kind.MULTIFILE_CLASS_PART -> {
|
||||
val facadeName = header.multifileClassName ?: continue@kotlinClasses
|
||||
result[partName] = facadeName.substringAfterLast('/')
|
||||
result[partName] = JvmClassName.byInternalName(header.multifileClassName ?: continue@kotlinClasses)
|
||||
}
|
||||
KotlinClassHeader.Kind.FILE_FACADE -> {
|
||||
result[partName] = partName
|
||||
@@ -80,7 +80,7 @@ class LazyJavaPackageFragment(
|
||||
result
|
||||
}
|
||||
|
||||
fun getFacadeSimpleNameForPartSimpleName(partName: String): String? = partToFacade[partName]
|
||||
fun getFacadeNameForPartName(partName: JvmClassName): JvmClassName? = partToFacade[partName]
|
||||
|
||||
override fun getMemberScope() = scope
|
||||
|
||||
|
||||
+1
-1
@@ -29,7 +29,7 @@ class JvmMetadataVersion(vararg numbers: Int) : BinaryVersion(*numbers) {
|
||||
|
||||
companion object {
|
||||
@JvmField
|
||||
val INSTANCE = JvmMetadataVersion(1, 1, 7)
|
||||
val INSTANCE = JvmMetadataVersion(1, 1, 8)
|
||||
|
||||
@JvmField
|
||||
val INVALID_VERSION = JvmMetadataVersion()
|
||||
|
||||
+1
-1
@@ -35,6 +35,6 @@ class KotlinJvmBinaryPackageSourceElement(
|
||||
|
||||
fun getContainingBinaryClass(descriptor: DeserializedMemberDescriptor): KotlinJvmBinaryClass? {
|
||||
val name = descriptor.getImplClassNameForDeserialized() ?: return null
|
||||
return packageFragment.binaryClasses[name.asString()]
|
||||
return packageFragment.binaryClasses[name.internalName]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
|
||||
package org.jetbrains.kotlin.load.kotlin
|
||||
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||
import org.jetbrains.kotlin.serialization.deserialization.DeserializationConfiguration
|
||||
import org.jetbrains.kotlin.serialization.jvm.JvmPackageTable
|
||||
import java.io.ByteArrayInputStream
|
||||
@@ -64,16 +67,28 @@ class ModuleMapping private constructor(val packageFqName2Parts: Map<String, Pac
|
||||
val result = linkedMapOf<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))
|
||||
val packageFqName = proto.packageFqName
|
||||
val packageParts = result.getOrPut(packageFqName) { PackageParts(packageFqName) }
|
||||
|
||||
for ((index, partShortName) in proto.shortClassNameList.withIndex()) {
|
||||
val multifileFacadeId = proto.multifileFacadeShortNameIdList.getOrNull(index)?.minus(1)
|
||||
val facadeShortName = multifileFacadeId?.let(proto.multifileFacadeShortNameList::getOrNull)
|
||||
val facadeInternalName = facadeShortName?.let { internalNameOf(packageFqName, it) }
|
||||
packageParts.addPart(internalNameOf(packageFqName, partShortName), facadeInternalName)
|
||||
}
|
||||
|
||||
for ((index, partShortName) in proto.classWithJvmPackageNameShortNameList.withIndex()) {
|
||||
val packageId = proto.classWithJvmPackageNamePackageIdList.getOrNull(index)
|
||||
?: proto.classWithJvmPackageNamePackageIdList.lastOrNull()
|
||||
?: continue
|
||||
val jvmPackageName = table.jvmPackageNameList.getOrNull(packageId) ?: continue
|
||||
packageParts.addPart(internalNameOf(jvmPackageName, partShortName), null)
|
||||
}
|
||||
}
|
||||
|
||||
for (proto in table.metadataPartsList) {
|
||||
val packageParts = result.getOrPut(proto.packageFqName) { PackageParts(proto.packageFqName) }
|
||||
proto.classNameList.forEach(packageParts::addMetadataPart)
|
||||
proto.shortClassNameList.forEach(packageParts::addMetadataPart)
|
||||
}
|
||||
|
||||
return ModuleMapping(result, debugName)
|
||||
@@ -87,21 +102,23 @@ class ModuleMapping private constructor(val packageFqName2Parts: Map<String, Pac
|
||||
}
|
||||
}
|
||||
|
||||
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?>()
|
||||
private fun internalNameOf(packageFqName: String, className: String): String =
|
||||
JvmClassName.byFqNameWithoutInnerClasses(FqName(packageFqName).child(Name.identifier(className))).internalName
|
||||
|
||||
// See JvmPackageTable.PackageTable.package_parts
|
||||
class PackageParts(val packageFqName: String) {
|
||||
// JVM internal name of package part -> JVM internal name of the corresponding multifile facade (or null, if it's not a multifile part)
|
||||
private val packageParts = linkedMapOf<String, String?>()
|
||||
val parts: Set<String> get() = packageParts.keys
|
||||
// See JvmPackageTable.PackageTable.metadata_parts
|
||||
|
||||
// Short names of .kotlin_metadata package parts
|
||||
val metadataParts: Set<String> = linkedSetOf()
|
||||
|
||||
fun addPart(partShortName: String, facadeShortName: String?) {
|
||||
packageParts[partShortName] = facadeShortName
|
||||
fun addPart(partInternalName: String, facadeInternalName: String?) {
|
||||
packageParts[partInternalName] = facadeInternalName
|
||||
}
|
||||
|
||||
fun removePart(shortName: String) {
|
||||
packageParts.remove(shortName)
|
||||
fun removePart(internalName: String) {
|
||||
packageParts.remove(internalName)
|
||||
}
|
||||
|
||||
fun addMetadataPart(shortName: String) {
|
||||
@@ -113,36 +130,76 @@ class PackageParts(val packageFqName: String) {
|
||||
builder.addPackageParts(JvmPackageTable.PackageParts.newBuilder().apply {
|
||||
packageFqName = this@PackageParts.packageFqName
|
||||
|
||||
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 })
|
||||
}
|
||||
}
|
||||
val packageInternalName = packageFqName.replace('.', '/')
|
||||
val (partsWithinPackage, partsOutsidePackage) = parts.partition { partInternalName ->
|
||||
partInternalName.packageName == packageInternalName
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
writePartsWithinPackage(partsWithinPackage)
|
||||
|
||||
writePartsOutsidePackage(partsOutsidePackage, builder)
|
||||
})
|
||||
}
|
||||
|
||||
if (metadataParts.isNotEmpty()) {
|
||||
builder.addMetadataParts(JvmPackageTable.PackageParts.newBuilder().apply {
|
||||
packageFqName = this@PackageParts.packageFqName
|
||||
addAllClassName(metadataParts.sorted())
|
||||
addAllShortClassName(metadataParts.sorted())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fun getMultifileFacadeName(partShortName: String): String? = packageParts[partShortName]
|
||||
private fun JvmPackageTable.PackageParts.Builder.writePartsWithinPackage(parts: List<String>) {
|
||||
val facadeNameToId = mutableMapOf<String, Int>()
|
||||
for ((facadeInternalName, partInternalNames) in parts.groupBy { getMultifileFacadeName(it) }.toSortedMap(nullsLast())) {
|
||||
for (partInternalName in partInternalNames.sorted()) {
|
||||
addShortClassName(partInternalName.className)
|
||||
if (facadeInternalName != null) {
|
||||
addMultifileFacadeShortNameId(1 + facadeNameToId.getOrPut(facadeInternalName.className) { facadeNameToId.size })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for ((facadeId, facadeName) in facadeNameToId.values.zip(facadeNameToId.keys).sortedBy(Pair<Int, String>::first)) {
|
||||
assert(facadeId == multifileFacadeShortNameCount) { "Multifile facades are loaded incorrectly: $facadeNameToId" }
|
||||
addMultifileFacadeShortName(facadeName)
|
||||
}
|
||||
}
|
||||
|
||||
// Writes information about package parts which have a different JVM package from the Kotlin package (with the help of @JvmPackageName)
|
||||
private fun JvmPackageTable.PackageParts.Builder.writePartsOutsidePackage(
|
||||
parts: List<String>,
|
||||
packageTableBuilder: JvmPackageTable.PackageTable.Builder
|
||||
) {
|
||||
val packageIds = mutableListOf<Int>()
|
||||
for ((packageInternalName, partsInPackage) in parts.groupBy { it.packageName }.toSortedMap()) {
|
||||
val packageFqName = packageInternalName.replace('/', '.')
|
||||
if (packageFqName !in packageTableBuilder.jvmPackageNameList) {
|
||||
packageTableBuilder.addJvmPackageName(packageFqName)
|
||||
}
|
||||
val packageId = packageTableBuilder.jvmPackageNameList.indexOf(packageFqName)
|
||||
for (part in partsInPackage.map { it.className }.sorted()) {
|
||||
addClassWithJvmPackageNameShortName(part)
|
||||
packageIds.add(packageId)
|
||||
}
|
||||
}
|
||||
|
||||
// See PackageParts#class_with_jvm_package_name_package_id in jvm_package_table.proto for description of this optimization
|
||||
while (packageIds.size > 1 && packageIds[packageIds.size - 1] == packageIds[packageIds.size - 2]) {
|
||||
packageIds.removeAt(packageIds.size - 1)
|
||||
}
|
||||
|
||||
addAllClassWithJvmPackageNamePackageId(packageIds)
|
||||
}
|
||||
|
||||
private val String.packageName: String get() = substringBeforeLast('/', "")
|
||||
private val String.className: String get() = substringAfterLast('/')
|
||||
|
||||
fun getMultifileFacadeName(partInternalName: String): String? = packageParts[partInternalName]
|
||||
|
||||
operator fun plusAssign(other: PackageParts) {
|
||||
for ((partShortName, facadeShortName) in other.packageParts) {
|
||||
addPart(partShortName, facadeShortName)
|
||||
for ((partInternalName, facadeInternalName) in other.packageParts) {
|
||||
addPart(partInternalName, facadeInternalName)
|
||||
}
|
||||
other.metadataParts.forEach(this::addMetadataPart)
|
||||
}
|
||||
|
||||
@@ -89,7 +89,12 @@ public class JvmClassName {
|
||||
}
|
||||
|
||||
/**
|
||||
* WARNING: internal name cannot be converted to FQ name for a class which contains dollars in the name
|
||||
* WARNING: internal name cannot be reliably converted to FQ name.
|
||||
*
|
||||
* This method treats all dollar characters ('$') in the internal name as inner class separators.
|
||||
* So it _will work incorrectly_ for classes where dollar characters are a part of the identifier.
|
||||
*
|
||||
* E.g. JvmClassName("org/foo/bar/Baz$quux").getFqNameForClassNameWithoutDollars() -> FqName("org.foo.bar.Baz.quux")
|
||||
*/
|
||||
@NotNull
|
||||
public FqName getFqNameForClassNameWithoutDollars() {
|
||||
@@ -99,6 +104,19 @@ public class JvmClassName {
|
||||
return fqName;
|
||||
}
|
||||
|
||||
/**
|
||||
* WARNING: internal name cannot be reliably converted to FQ name.
|
||||
*
|
||||
* This method treats all dollar characters ('$') in the internal name as a part of the identifier.
|
||||
* So it _will work incorrectly_ for inner classes.
|
||||
*
|
||||
* E.g. JvmClassName("org/foo/bar/Baz$quux").getFqNameForTopLevelClassMaybeWithDollars() -> FqName("org.foo.bar.Baz$quux")
|
||||
*/
|
||||
@NotNull
|
||||
public FqName getFqNameForTopLevelClassMaybeWithDollars() {
|
||||
return new FqName(internalName.replace('/', '.'));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public FqName getPackageFqName() {
|
||||
int lastSlash = internalName.lastIndexOf("/");
|
||||
|
||||
+1082
-260
File diff suppressed because it is too large
Load Diff
@@ -18,10 +18,11 @@ package org.jetbrains.kotlin.descriptors
|
||||
|
||||
interface PackagePartProvider {
|
||||
/**
|
||||
* @return simple names of package parts existing in the package with the given FQ name.
|
||||
* @return JVM internal names of package parts existing in the package with the given FQ name.
|
||||
*
|
||||
* For example, if a file named foo.kt in package org.test is compiled to a library, PackagePartProvider for such library
|
||||
* must return the list `["FooKt"]` for the query `"org.test"` (in case the file is not annotated with @JvmName or @JvmMultifile*)
|
||||
* must return the list `["org/test/FooKt"]` for the query `"org.test"`
|
||||
* (in case the file is not annotated with @JvmName, @JvmPackageName or @JvmMultifileClass).
|
||||
*/
|
||||
fun findPackageParts(packageFqName: String): List<String>
|
||||
|
||||
|
||||
+6
-7
@@ -43,9 +43,9 @@ object KotlinModuleMappingIndex : FileBasedIndexExtension<String, PackageParts>(
|
||||
private val VALUE_EXTERNALIZER = object : DataExternalizer<PackageParts> {
|
||||
override fun read(input: DataInput): PackageParts? =
|
||||
PackageParts(IOUtil.readUTF(input)).apply {
|
||||
val shortPartNames = IOUtil.readStringList(input)
|
||||
val shortFacadeNames = IOUtil.readStringList(input)
|
||||
for ((partName, facadeName) in shortPartNames zip shortFacadeNames) {
|
||||
val partInternalNames = IOUtil.readStringList(input)
|
||||
val facadeInternalNames = IOUtil.readStringList(input)
|
||||
for ((partName, facadeName) in partInternalNames zip facadeInternalNames) {
|
||||
addPart(partName, if (facadeName.isNotEmpty()) facadeName else null)
|
||||
}
|
||||
IOUtil.readStringList(input).forEach(this::addMetadataPart)
|
||||
@@ -67,11 +67,10 @@ object KotlinModuleMappingIndex : FileBasedIndexExtension<String, PackageParts>(
|
||||
|
||||
override fun getValueExternalizer() = VALUE_EXTERNALIZER
|
||||
|
||||
override fun getInputFilter(): FileBasedIndex.InputFilter {
|
||||
return FileBasedIndex.InputFilter { file -> file.extension == ModuleMapping.MAPPING_FILE_EXT }
|
||||
}
|
||||
override fun getInputFilter(): FileBasedIndex.InputFilter =
|
||||
FileBasedIndex.InputFilter { file -> file.extension == ModuleMapping.MAPPING_FILE_EXT }
|
||||
|
||||
override fun getVersion(): Int = 4
|
||||
override fun getVersion(): Int = 5
|
||||
|
||||
override fun getIndexer(): DataIndexer<String, PackageParts, FileContent> {
|
||||
return DataIndexer<String, PackageParts, FileContent> { inputData ->
|
||||
|
||||
Reference in New Issue
Block a user