Effectively this is a return of "${facadeName}__${partName}" scheme.
Suggestions from @udalov: - Make multifile class parts synthetic. - Multifile class parts should have well-formed Java identifiers as names. - Multifile class part names should contain facade name. Add test with clashing part names. Add test with local generic classes used in method signatures (it works with parts names not being well-formed Java identifiers, though). Capitalized annotations.
This commit is contained in:
@@ -44,10 +44,10 @@ public class MultifileClassPartCodegen(
|
|||||||
private val multifileClassFqName: FqName,
|
private val multifileClassFqName: FqName,
|
||||||
partContext: FieldOwnerContext<*>,
|
partContext: FieldOwnerContext<*>,
|
||||||
state: GenerationState
|
state: GenerationState
|
||||||
) : MemberCodegen<JetFile>(state, null, partContext, file, v){
|
) : MemberCodegen<JetFile>(state, null, partContext, file, v) {
|
||||||
override fun generateDeclaration() {
|
override fun generateDeclaration() {
|
||||||
v.defineClass(element, Opcodes.V1_6,
|
v.defineClass(element, Opcodes.V1_6,
|
||||||
Opcodes.ACC_FINAL,
|
Opcodes.ACC_FINAL or Opcodes.ACC_SYNTHETIC,
|
||||||
filePartType.internalName,
|
filePartType.internalName,
|
||||||
null,
|
null,
|
||||||
"java/lang/Object",
|
"java/lang/Object",
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ public object JvmFileClassUtil {
|
|||||||
file.packageFqName.child(Name.identifier(manglePartName(jvmFileClassAnnotations.name, file.name)))
|
file.packageFqName.child(Name.identifier(manglePartName(jvmFileClassAnnotations.name, file.name)))
|
||||||
|
|
||||||
public @JvmStatic fun manglePartName(facadeName: String, fileName: String): String =
|
public @JvmStatic fun manglePartName(facadeName: String, fileName: String): String =
|
||||||
"1${PackagePartClassUtils.getFilePartShortName(fileName)}"
|
"${facadeName}__${PackagePartClassUtils.getFilePartShortName(fileName)}"
|
||||||
|
|
||||||
public @JvmStatic fun parseJvmFileClass(jvmName: AnnotationDescriptor, jvmMultifileClass: AnnotationDescriptor?): ParsedJmvFileClassAnnotations? {
|
public @JvmStatic fun parseJvmFileClass(jvmName: AnnotationDescriptor, jvmMultifileClass: AnnotationDescriptor?): ParsedJmvFileClassAnnotations? {
|
||||||
val jvmNameArgument = jvmName.allValueArguments.values().singleOrNull() ?: return null
|
val jvmNameArgument = jvmName.allValueArguments.values().singleOrNull() ?: return null
|
||||||
|
|||||||
+15
-15
@@ -31,21 +31,21 @@ import org.jetbrains.kotlin.serialization.jvm.JvmProtoBuf
|
|||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
public object PackagePartClassUtils {
|
public object PackagePartClassUtils {
|
||||||
public @jvmStatic fun getPathHashCode(file: VirtualFile): Int =
|
public @JvmStatic fun getPathHashCode(file: VirtualFile): Int =
|
||||||
file.path.toLowerCase().hashCode()
|
file.path.toLowerCase().hashCode()
|
||||||
|
|
||||||
private val PART_CLASS_NAME_SUFFIX = "Kt"
|
private val PART_CLASS_NAME_SUFFIX = "Kt"
|
||||||
|
|
||||||
private @jvmStatic fun getPartClassName(str: String): String =
|
private @JvmStatic fun getPartClassName(str: String): String =
|
||||||
if (str.isEmpty())
|
if (str.isEmpty())
|
||||||
"_$PART_CLASS_NAME_SUFFIX"
|
"_$PART_CLASS_NAME_SUFFIX"
|
||||||
else
|
else
|
||||||
capitalizeAsJavaClassName(sanitizeAsJavaIdentifier(str)) + PART_CLASS_NAME_SUFFIX
|
capitalizeAsJavaClassName(sanitizeAsJavaIdentifier(str)) + PART_CLASS_NAME_SUFFIX
|
||||||
|
|
||||||
private @jvmStatic fun sanitizeAsJavaIdentifier(str: String): String =
|
private @JvmStatic fun sanitizeAsJavaIdentifier(str: String): String =
|
||||||
str.replace("[^\\p{L}\\p{Digit}]".toRegex(), "_")
|
str.replace("[^\\p{L}\\p{Digit}]".toRegex(), "_")
|
||||||
|
|
||||||
private @jvmStatic fun capitalizeAsJavaClassName(str: String): String =
|
private @JvmStatic fun capitalizeAsJavaClassName(str: String): String =
|
||||||
// NB use Locale.ENGLISH so that build is locale-independent.
|
// NB use Locale.ENGLISH so that build is locale-independent.
|
||||||
// See Javadoc on java.lang.String.toUpperCase() for more details.
|
// See Javadoc on java.lang.String.toUpperCase() for more details.
|
||||||
if (Character.isJavaIdentifierStart(str.charAt(0)))
|
if (Character.isJavaIdentifierStart(str.charAt(0)))
|
||||||
@@ -54,38 +54,38 @@ public object PackagePartClassUtils {
|
|||||||
"_$str"
|
"_$str"
|
||||||
|
|
||||||
@TestOnly
|
@TestOnly
|
||||||
public @jvmStatic fun getDefaultPartFqName(facadeClassFqName: FqName, file: VirtualFile): FqName =
|
public @JvmStatic fun getDefaultPartFqName(facadeClassFqName: FqName, file: VirtualFile): FqName =
|
||||||
getPackagePartFqName(facadeClassFqName.parent(), file.name)
|
getPackagePartFqName(facadeClassFqName.parent(), file.name)
|
||||||
|
|
||||||
public @jvmStatic fun getPackagePartFqName(packageFqName: FqName, fileName: String): FqName {
|
public @JvmStatic fun getPackagePartFqName(packageFqName: FqName, fileName: String): FqName {
|
||||||
val partClassName = getFilePartShortName(fileName)
|
val partClassName = getFilePartShortName(fileName)
|
||||||
return packageFqName.child(Name.identifier(partClassName))
|
return packageFqName.child(Name.identifier(partClassName))
|
||||||
}
|
}
|
||||||
|
|
||||||
@deprecated("Migrate to JvmFileClassesProvider")
|
@Deprecated("Migrate to JvmFileClassesProvider")
|
||||||
public @jvmStatic fun getPackagePartInternalName(file: JetFile): String =
|
public @JvmStatic fun getPackagePartInternalName(file: JetFile): String =
|
||||||
JvmClassName.byFqNameWithoutInnerClasses(getPackagePartFqName(file)).internalName
|
JvmClassName.byFqNameWithoutInnerClasses(getPackagePartFqName(file)).internalName
|
||||||
|
|
||||||
@deprecated("Migrate to JvmFileClassesProvider")
|
@Deprecated("Migrate to JvmFileClassesProvider")
|
||||||
public @jvmStatic fun getPackagePartFqName(file: JetFile): FqName =
|
public @JvmStatic fun getPackagePartFqName(file: JetFile): FqName =
|
||||||
getPackagePartFqName(file.packageFqName, file.name)
|
getPackagePartFqName(file.packageFqName, file.name)
|
||||||
|
|
||||||
public @jvmStatic fun getPackagePartFqName(callable: DeserializedCallableMemberDescriptor): FqName {
|
public @JvmStatic fun getPackagePartFqName(callable: DeserializedCallableMemberDescriptor): FqName {
|
||||||
val implClassName = callable.nameResolver.getName(callable.proto.getExtension(JvmProtoBuf.implClassName))
|
val implClassName = callable.nameResolver.getName(callable.proto.getExtension(JvmProtoBuf.implClassName))
|
||||||
val packageFqName = (callable.containingDeclaration as PackageFragmentDescriptor).fqName
|
val packageFqName = (callable.containingDeclaration as PackageFragmentDescriptor).fqName
|
||||||
return packageFqName.child(implClassName)
|
return packageFqName.child(implClassName)
|
||||||
}
|
}
|
||||||
|
|
||||||
public @jvmStatic fun getFilesWithCallables(files: Collection<JetFile>): List<JetFile> =
|
public @JvmStatic fun getFilesWithCallables(files: Collection<JetFile>): List<JetFile> =
|
||||||
files.filter { fileHasTopLevelCallables(it) }
|
files.filter { fileHasTopLevelCallables(it) }
|
||||||
|
|
||||||
public @jvmStatic fun fileHasTopLevelCallables(file: JetFile): Boolean =
|
public @JvmStatic fun fileHasTopLevelCallables(file: JetFile): Boolean =
|
||||||
file.declarations.any { it is JetProperty || it is JetNamedFunction }
|
file.declarations.any { it is JetProperty || it is JetNamedFunction }
|
||||||
|
|
||||||
public @jvmStatic fun getFilesForPart(partFqName: FqName, files: Collection<JetFile>): List<JetFile> =
|
public @JvmStatic fun getFilesForPart(partFqName: FqName, files: Collection<JetFile>): List<JetFile> =
|
||||||
getFilesWithCallables(files).filter { getPackagePartFqName(it) == partFqName }
|
getFilesWithCallables(files).filter { getPackagePartFqName(it) == partFqName }
|
||||||
|
|
||||||
public @jvmStatic fun getFilePartShortName(fileName: String): String =
|
public @JvmStatic fun getFilePartShortName(fileName: String): String =
|
||||||
getPartClassName(FileUtil.getNameWithoutExtension(fileName))
|
getPartClassName(FileUtil.getNameWithoutExtension(fileName))
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
@file:JvmName("Foo")
|
||||||
|
@file:JvmMultifileClass
|
||||||
|
package test
|
||||||
|
|
||||||
|
fun foo(): String = "O"
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
@file:JvmName("Bar")
|
||||||
|
@file:JvmMultifileClass
|
||||||
|
package test
|
||||||
|
|
||||||
|
fun bar(): String = "K"
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
fun box(): String = foo() + bar()
|
||||||
+17
@@ -0,0 +1,17 @@
|
|||||||
|
@file:JvmName("TestPackage")
|
||||||
|
@file:JvmMultifileClass
|
||||||
|
package test
|
||||||
|
|
||||||
|
fun foo(): String = bar()
|
||||||
|
fun bar(): String {
|
||||||
|
open class LocalGeneric<T>(val x: T)
|
||||||
|
class Derived(x: String) : LocalGeneric<String>(x)
|
||||||
|
fun <T> LocalGeneric<T>.extFun() = this
|
||||||
|
fun <T> localFun(x: LocalGeneric<T>) = x
|
||||||
|
class Local3 {
|
||||||
|
fun <T> method(x: LocalGeneric<T>) = x.x
|
||||||
|
}
|
||||||
|
return Local3().method(localFun(Derived("OK")).extFun())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String = foo()
|
||||||
+6
@@ -101,6 +101,12 @@ public class BlackBoxMultiFileCodegenTestGenerated extends AbstractBlackBoxCodeg
|
|||||||
doTestMultiFile(fileName);
|
doTestMultiFile(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("samePartNameDifferentFacades")
|
||||||
|
public void testSamePartNameDifferentFacades() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxMultiFile/samePartNameDifferentFacades/");
|
||||||
|
doTestMultiFile(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("simple")
|
@TestMetadata("simple")
|
||||||
public void testSimple() throws Exception {
|
public void testSimple() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxMultiFile/simple/");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxMultiFile/simple/");
|
||||||
|
|||||||
+6
@@ -2245,6 +2245,12 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode
|
|||||||
doTestWithStdlib(fileName);
|
doTestWithStdlib(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("multifileClassWithLocalGeneric.kt")
|
||||||
|
public void testMultifileClassWithLocalGeneric() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/platformNames/multifileClassWithLocalGeneric.kt");
|
||||||
|
doTestWithStdlib(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("propertyName.kt")
|
@TestMetadata("propertyName.kt")
|
||||||
public void testPropertyName() throws Exception {
|
public void testPropertyName() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/platformNames/propertyName.kt");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/platformNames/propertyName.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user