[JVM IR] Make file classes with all private members package-private
This commit is contained in:
committed by
Alexander Udalov
parent
032c64669c
commit
77180a5b13
+21
-11
@@ -22,22 +22,20 @@ import org.jetbrains.kotlin.backend.common.phaser.makeIrModulePhase
|
|||||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||||
import org.jetbrains.kotlin.codegen.AsmUtil
|
import org.jetbrains.kotlin.codegen.AsmUtil
|
||||||
import org.jetbrains.kotlin.config.JvmAnalysisFlags
|
import org.jetbrains.kotlin.config.JvmAnalysisFlags
|
||||||
|
import org.jetbrains.kotlin.config.LanguageFeature
|
||||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassInfo
|
|
||||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
|
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
|
||||||
import org.jetbrains.kotlin.fileClasses.JvmSimpleFileClassInfo
|
import org.jetbrains.kotlin.fileClasses.JvmSimpleFileClassInfo
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrClassImpl
|
import org.jetbrains.kotlin.ir.declarations.impl.IrClassImpl
|
||||||
import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl
|
import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl
|
||||||
import org.jetbrains.kotlin.ir.util.IdSignature
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.ir.util.NaiveSourceBasedFileEntryImpl
|
|
||||||
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
|
|
||||||
import org.jetbrains.kotlin.ir.util.parentAsClass
|
|
||||||
import org.jetbrains.kotlin.load.java.JavaDescriptorVisibilities
|
import org.jetbrains.kotlin.load.java.JavaDescriptorVisibilities
|
||||||
import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils
|
import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils
|
||||||
import org.jetbrains.kotlin.psi2ir.PsiSourceManager
|
import org.jetbrains.kotlin.psi2ir.PsiSourceManager
|
||||||
|
import org.jetbrains.kotlin.resolve.inline.INLINE_ONLY_ANNOTATION_FQ_NAME
|
||||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
@@ -61,7 +59,8 @@ private class FileClassLowering(val context: JvmBackendContext) : FileLoweringPa
|
|||||||
|
|
||||||
irFile.declarations.forEach {
|
irFile.declarations.forEach {
|
||||||
when (it) {
|
when (it) {
|
||||||
is IrScript -> {}
|
is IrScript -> {
|
||||||
|
}
|
||||||
is IrClass -> classes.add(it)
|
is IrClass -> classes.add(it)
|
||||||
else -> fileClassMembers.add(it)
|
else -> fileClassMembers.add(it)
|
||||||
}
|
}
|
||||||
@@ -79,19 +78,27 @@ private class FileClassLowering(val context: JvmBackendContext) : FileLoweringPa
|
|||||||
|
|
||||||
private fun createFileClass(irFile: IrFile, fileClassMembers: List<IrDeclaration>): IrClass {
|
private fun createFileClass(irFile: IrFile, fileClassMembers: List<IrDeclaration>): IrClass {
|
||||||
val fileEntry = irFile.fileEntry
|
val fileEntry = irFile.fileEntry
|
||||||
val fileClassInfo: JvmFileClassInfo?
|
val fileClassInfo = when (fileEntry) {
|
||||||
when (fileEntry) {
|
|
||||||
is PsiSourceManager.PsiFileEntry -> {
|
is PsiSourceManager.PsiFileEntry -> {
|
||||||
val ktFile = context.psiSourceManager.getKtFile(fileEntry)
|
val ktFile = context.psiSourceManager.getKtFile(fileEntry)
|
||||||
?: throw AssertionError("Unexpected file entry: $fileEntry")
|
?: throw AssertionError("Unexpected file entry: $fileEntry")
|
||||||
fileClassInfo = JvmFileClassUtil.getFileClassInfoNoResolve(ktFile)
|
JvmFileClassUtil.getFileClassInfoNoResolve(ktFile)
|
||||||
}
|
}
|
||||||
is NaiveSourceBasedFileEntryImpl -> {
|
is NaiveSourceBasedFileEntryImpl -> {
|
||||||
fileClassInfo = JvmSimpleFileClassInfo(PackagePartClassUtils.getPackagePartFqName(irFile.fqName, fileEntry.name), false)
|
JvmSimpleFileClassInfo(PackagePartClassUtils.getPackagePartFqName(irFile.fqName, fileEntry.name), false)
|
||||||
}
|
}
|
||||||
else -> error("unknown kind of file entry: $fileEntry")
|
else -> error("unknown kind of file entry: $fileEntry")
|
||||||
}
|
}
|
||||||
val isMultifilePart = fileClassInfo.withJvmMultifileClass
|
val isMultifilePart = fileClassInfo.withJvmMultifileClass
|
||||||
|
|
||||||
|
val onlyPrivateDeclarationsAndFeatureIsEnabled =
|
||||||
|
context.state.languageVersionSettings.supportsFeature(LanguageFeature.PackagePrivateFileClassesWithAllPrivateMembers) && fileClassMembers
|
||||||
|
.all {
|
||||||
|
val isPrivate = it is IrDeclarationWithVisibility && DescriptorVisibilities.isPrivate(it.visibility)
|
||||||
|
val isInlineOnly = it.hasAnnotation(INLINE_ONLY_ANNOTATION_FQ_NAME)
|
||||||
|
isPrivate || isInlineOnly
|
||||||
|
}
|
||||||
|
|
||||||
return IrClassImpl(
|
return IrClassImpl(
|
||||||
0, fileEntry.maxOffset,
|
0, fileEntry.maxOffset,
|
||||||
if (!isMultifilePart || context.state.languageVersionSettings.getFlag(JvmAnalysisFlags.inheritMultifileParts))
|
if (!isMultifilePart || context.state.languageVersionSettings.getFlag(JvmAnalysisFlags.inheritMultifileParts))
|
||||||
@@ -99,7 +106,10 @@ private class FileClassLowering(val context: JvmBackendContext) : FileLoweringPa
|
|||||||
symbol = IrClassSymbolImpl(),
|
symbol = IrClassSymbolImpl(),
|
||||||
name = fileClassInfo.fileClassFqName.shortName(),
|
name = fileClassInfo.fileClassFqName.shortName(),
|
||||||
kind = ClassKind.CLASS,
|
kind = ClassKind.CLASS,
|
||||||
visibility = if (!isMultifilePart) DescriptorVisibilities.PUBLIC else JavaDescriptorVisibilities.PACKAGE_VISIBILITY,
|
visibility = if (isMultifilePart || onlyPrivateDeclarationsAndFeatureIsEnabled)
|
||||||
|
JavaDescriptorVisibilities.PACKAGE_VISIBILITY
|
||||||
|
else
|
||||||
|
DescriptorVisibilities.PUBLIC,
|
||||||
modality = Modality.FINAL
|
modality = Modality.FINAL
|
||||||
).apply {
|
).apply {
|
||||||
superTypes = listOf(context.irBuiltIns.anyType)
|
superTypes = listOf(context.irBuiltIns.anyType)
|
||||||
|
|||||||
+14
@@ -0,0 +1,14 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
// IGNORE_BACKEND: JVM
|
||||||
|
// !LANGUAGE: +PackagePrivateFileClassesWithAllPrivateMembers
|
||||||
|
|
||||||
|
private fun f() {
|
||||||
|
}
|
||||||
|
|
||||||
|
private val a = Unit
|
||||||
|
private val b by lazy { Unit }
|
||||||
|
|
||||||
|
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
|
||||||
|
@kotlin.internal.InlineOnly
|
||||||
|
public fun g() {
|
||||||
|
}
|
||||||
+23
@@ -0,0 +1,23 @@
|
|||||||
|
@kotlin.Metadata
|
||||||
|
final class FileClassWithPrivateDeclarationsOnly_afterKt$b$2 {
|
||||||
|
// source: 'fileClassWithPrivateDeclarationsOnly_after.kt'
|
||||||
|
enclosing method FileClassWithPrivateDeclarationsOnly_afterKt.<clinit>()V
|
||||||
|
public final static field INSTANCE: FileClassWithPrivateDeclarationsOnly_afterKt$b$2
|
||||||
|
inner (anonymous) class FileClassWithPrivateDeclarationsOnly_afterKt$b$2
|
||||||
|
static method <clinit>(): void
|
||||||
|
method <init>(): void
|
||||||
|
public synthetic bridge method invoke(): java.lang.Object
|
||||||
|
public final method invoke(): void
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
final class FileClassWithPrivateDeclarationsOnly_afterKt {
|
||||||
|
// source: 'fileClassWithPrivateDeclarationsOnly_after.kt'
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field a: kotlin.Unit
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field b$delegate: kotlin.Lazy
|
||||||
|
inner (anonymous) class FileClassWithPrivateDeclarationsOnly_afterKt$b$2
|
||||||
|
static method <clinit>(): void
|
||||||
|
private final static method f(): void
|
||||||
|
public final static @kotlin.internal.InlineOnly method g(): void
|
||||||
|
private final static method getB(): kotlin.Unit
|
||||||
|
}
|
||||||
+14
@@ -0,0 +1,14 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
// IGNORE_BACKEND: JVM
|
||||||
|
// !LANGUAGE: -PackagePrivateFileClassesWithAllPrivateMembers
|
||||||
|
|
||||||
|
private fun f() {
|
||||||
|
}
|
||||||
|
|
||||||
|
private val a = Unit
|
||||||
|
private val b by lazy { Unit }
|
||||||
|
|
||||||
|
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
|
||||||
|
@kotlin.internal.InlineOnly
|
||||||
|
public fun g() {
|
||||||
|
}
|
||||||
+23
@@ -0,0 +1,23 @@
|
|||||||
|
@kotlin.Metadata
|
||||||
|
final class FileClassWithPrivateDeclarationsOnly_beforeKt$b$2 {
|
||||||
|
// source: 'fileClassWithPrivateDeclarationsOnly_before.kt'
|
||||||
|
enclosing method FileClassWithPrivateDeclarationsOnly_beforeKt.<clinit>()V
|
||||||
|
public final static field INSTANCE: FileClassWithPrivateDeclarationsOnly_beforeKt$b$2
|
||||||
|
inner (anonymous) class FileClassWithPrivateDeclarationsOnly_beforeKt$b$2
|
||||||
|
static method <clinit>(): void
|
||||||
|
method <init>(): void
|
||||||
|
public synthetic bridge method invoke(): java.lang.Object
|
||||||
|
public final method invoke(): void
|
||||||
|
}
|
||||||
|
|
||||||
|
@kotlin.Metadata
|
||||||
|
public final class FileClassWithPrivateDeclarationsOnly_beforeKt {
|
||||||
|
// source: 'fileClassWithPrivateDeclarationsOnly_before.kt'
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field a: kotlin.Unit
|
||||||
|
private final static @org.jetbrains.annotations.NotNull field b$delegate: kotlin.Lazy
|
||||||
|
inner (anonymous) class FileClassWithPrivateDeclarationsOnly_beforeKt$b$2
|
||||||
|
static method <clinit>(): void
|
||||||
|
private final static method f(): void
|
||||||
|
public final static @kotlin.internal.InlineOnly method g(): void
|
||||||
|
private final static method getB(): kotlin.Unit
|
||||||
|
}
|
||||||
+10
@@ -90,6 +90,16 @@ public class BytecodeListingTestGenerated extends AbstractBytecodeListingTest {
|
|||||||
runTest("compiler/testData/codegen/bytecodeListing/extension.kt");
|
runTest("compiler/testData/codegen/bytecodeListing/extension.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("fileClassWithPrivateDeclarationsOnly_after.kt")
|
||||||
|
public void testFileClassWithPrivateDeclarationsOnly_after() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/bytecodeListing/fileClassWithPrivateDeclarationsOnly_after.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("fileClassWithPrivateDeclarationsOnly_before.kt")
|
||||||
|
public void testFileClassWithPrivateDeclarationsOnly_before() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/bytecodeListing/fileClassWithPrivateDeclarationsOnly_before.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("immutableCollection.kt")
|
@TestMetadata("immutableCollection.kt")
|
||||||
public void testImmutableCollection() throws Exception {
|
public void testImmutableCollection() throws Exception {
|
||||||
runTest("compiler/testData/codegen/bytecodeListing/immutableCollection.kt");
|
runTest("compiler/testData/codegen/bytecodeListing/immutableCollection.kt");
|
||||||
|
|||||||
+10
@@ -90,6 +90,16 @@ public class IrBytecodeListingTestGenerated extends AbstractIrBytecodeListingTes
|
|||||||
runTest("compiler/testData/codegen/bytecodeListing/extension.kt");
|
runTest("compiler/testData/codegen/bytecodeListing/extension.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("fileClassWithPrivateDeclarationsOnly_after.kt")
|
||||||
|
public void testFileClassWithPrivateDeclarationsOnly_after() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/bytecodeListing/fileClassWithPrivateDeclarationsOnly_after.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("fileClassWithPrivateDeclarationsOnly_before.kt")
|
||||||
|
public void testFileClassWithPrivateDeclarationsOnly_before() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/bytecodeListing/fileClassWithPrivateDeclarationsOnly_before.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("immutableCollection.kt")
|
@TestMetadata("immutableCollection.kt")
|
||||||
public void testImmutableCollection() throws Exception {
|
public void testImmutableCollection() throws Exception {
|
||||||
runTest("compiler/testData/codegen/bytecodeListing/immutableCollection.kt");
|
runTest("compiler/testData/codegen/bytecodeListing/immutableCollection.kt");
|
||||||
|
|||||||
@@ -145,6 +145,8 @@ enum class LanguageFeature(
|
|||||||
AllowSealedInheritorsInDifferentFilesOfSamePackage(KOTLIN_1_5),
|
AllowSealedInheritorsInDifferentFilesOfSamePackage(KOTLIN_1_5),
|
||||||
SealedInterfaces(KOTLIN_1_5),
|
SealedInterfaces(KOTLIN_1_5),
|
||||||
JvmIrEnabledByDefault(KOTLIN_1_5),
|
JvmIrEnabledByDefault(KOTLIN_1_5),
|
||||||
|
// Disabled until the breaking change is approved by the committee, see KT-10884.
|
||||||
|
PackagePrivateFileClassesWithAllPrivateMembers(KOTLIN_1_5, defaultState = State.DISABLED),
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Improvements include the following:
|
* Improvements include the following:
|
||||||
|
|||||||
Reference in New Issue
Block a user