[K/JS] Exclude componentN methods from JsExport
This commit is contained in:
@@ -135,6 +135,12 @@ private val validateIrAfterLowering = makeCustomJsModulePhase(
|
||||
description = "Validate IR after lowering"
|
||||
).toModuleLowering()
|
||||
|
||||
private val preventExportOfSyntheticDeclarationsLowering = makeDeclarationTransformerPhase(
|
||||
::ExcludeSyntheticDeclarationsFromExportLowering,
|
||||
name = "ExcludeSyntheticDeclarationsFromExportLowering",
|
||||
description = "Exclude synthetic declarations which we don't want to export such as `Enum.entries` or `DataClass::componentN`",
|
||||
)
|
||||
|
||||
val scriptRemoveReceiverLowering = makeJsModulePhase(
|
||||
::ScriptRemoveReceiverLowering,
|
||||
name = "ScriptRemoveReceiver",
|
||||
@@ -358,12 +364,6 @@ private val enumEntryCreateGetInstancesFunsLoweringPhase = makeDeclarationTransf
|
||||
prerequisite = setOf(enumClassConstructorLoweringPhase)
|
||||
)
|
||||
|
||||
private val enumClassPreventExportOfNonExportedMembersLowering = makeDeclarationTransformerPhase(
|
||||
::EnumClassPreventExportOfNonExportedMembersLowering,
|
||||
name = "EnumClassPreventExportOfNonExportedMembersLowering",
|
||||
description = "Exclude non-exportable enum members such as `Enum.entries`",
|
||||
)
|
||||
|
||||
private val enumSyntheticFunsLoweringPhase = makeDeclarationTransformerPhase(
|
||||
{ EnumSyntheticFunctionsAndPropertiesLowering(it, supportRawFunctionReference = true) },
|
||||
name = "EnumSyntheticFunctionsAndPropertiesLowering",
|
||||
@@ -372,7 +372,6 @@ private val enumSyntheticFunsLoweringPhase = makeDeclarationTransformerPhase(
|
||||
enumClassConstructorLoweringPhase,
|
||||
enumClassCreateInitializerLoweringPhase,
|
||||
enumEntryCreateGetInstancesFunsLoweringPhase,
|
||||
enumClassPreventExportOfNonExportedMembersLowering
|
||||
)
|
||||
)
|
||||
|
||||
@@ -847,6 +846,7 @@ private val jsSuspendArityStorePhase = makeDeclarationTransformerPhase(
|
||||
val loweringList = listOf<Lowering>(
|
||||
scriptRemoveReceiverLowering,
|
||||
validateIrBeforeLowering,
|
||||
preventExportOfSyntheticDeclarationsLowering,
|
||||
inventNamesForLocalClassesPhase,
|
||||
annotationInstantiationLowering,
|
||||
expectDeclarationsRemovingPhase,
|
||||
@@ -894,7 +894,6 @@ val loweringList = listOf<Lowering>(
|
||||
enumEntryInstancesBodyLoweringPhase,
|
||||
enumClassCreateInitializerLoweringPhase,
|
||||
enumEntryCreateGetInstancesFunsLoweringPhase,
|
||||
enumClassPreventExportOfNonExportedMembersLowering,
|
||||
enumSyntheticFunsLoweringPhase,
|
||||
enumUsageLoweringPhase,
|
||||
externalEnumUsageLoweringPhase,
|
||||
|
||||
+2
-26
@@ -21,6 +21,8 @@ import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
||||
import org.jetbrains.kotlin.ir.backend.js.JsLoweredDeclarationOrigin
|
||||
import org.jetbrains.kotlin.ir.backend.js.export.isExported
|
||||
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.isInstantiableEnum
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.parentEnumClassOrNull
|
||||
import org.jetbrains.kotlin.ir.builders.*
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.addField
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.buildConstructor
|
||||
@@ -59,26 +61,6 @@ private fun createEntryAccessorName(enumName: String, enumEntry: IrEnumEntry) =
|
||||
|
||||
private fun IrEnumEntry.getType(irClass: IrClass) = (correspondingClass ?: irClass).defaultType
|
||||
|
||||
class EnumClassPreventExportOfNonExportedMembersLowering(val context: JsIrBackendContext) : DeclarationTransformer {
|
||||
override fun transformFlat(declaration: IrDeclaration): List<IrDeclaration>? {
|
||||
if (declaration !is IrSimpleFunction || declaration.parentEnumClassOrNull?.isExported(context) != true) return null
|
||||
|
||||
val syntheticGetterBody = declaration.body as? IrSyntheticBody ?: return null
|
||||
|
||||
if (syntheticGetterBody.kind == IrSyntheticBodyKind.ENUM_ENTRIES) {
|
||||
declaration.correspondingPropertySymbol?.owner?.let {
|
||||
it.annotations += generateJsExportIgnoreCall()
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
private fun generateJsExportIgnoreCall(): IrConstructorCall {
|
||||
return JsIrBuilder.buildConstructorCall(context.intrinsics.jsExportIgnoreAnnotationSymbol.owner.primaryConstructor!!.symbol)
|
||||
}
|
||||
}
|
||||
|
||||
// Should be applied recursively
|
||||
class EnumClassConstructorLowering(val context: JsCommonBackendContext) : DeclarationTransformer {
|
||||
|
||||
@@ -477,12 +459,6 @@ class EnumEntryCreateGetInstancesFunsLowering(val context: JsCommonBackendContex
|
||||
}
|
||||
}
|
||||
|
||||
private val IrClass.isInstantiableEnum: Boolean
|
||||
get() = isEnumClass && !isExpect && !isEffectivelyExternal()
|
||||
|
||||
private val IrDeclaration.parentEnumClassOrNull: IrClass?
|
||||
get() = parents.filterIsInstance<IrClass>().firstOrNull { it.isInstantiableEnum }
|
||||
|
||||
private const val ENTRIES_FIELD_NAME = "\$ENTRIES"
|
||||
|
||||
class EnumSyntheticFunctionsAndPropertiesLowering(
|
||||
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.ir.backend.js.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.DeclarationTransformer
|
||||
import org.jetbrains.kotlin.builtins.StandardNames
|
||||
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
||||
import org.jetbrains.kotlin.ir.backend.js.export.isExported
|
||||
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.parentEnumClassOrNull
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
|
||||
import org.jetbrains.kotlin.ir.expressions.IrSyntheticBody
|
||||
import org.jetbrains.kotlin.ir.expressions.IrSyntheticBodyKind
|
||||
import org.jetbrains.kotlin.ir.util.parentClassOrNull
|
||||
import org.jetbrains.kotlin.ir.util.primaryConstructor
|
||||
|
||||
class ExcludeSyntheticDeclarationsFromExportLowering(val context: JsIrBackendContext) : DeclarationTransformer {
|
||||
override fun transformFlat(declaration: IrDeclaration): List<IrDeclaration>? {
|
||||
if (declaration.shouldBeExcludedFromExport()) {
|
||||
if (declaration is IrSimpleFunction) {
|
||||
declaration.correspondingPropertySymbol?.owner?.excludeFromJsExport()
|
||||
}
|
||||
|
||||
declaration.excludeFromJsExport()
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
private fun IrDeclaration.shouldBeExcludedFromExport(): Boolean {
|
||||
return isExportedSyntheticEnumEntriesProperty() || isComponentMethodOfDataClass()
|
||||
}
|
||||
|
||||
private fun IrDeclaration.isComponentMethodOfDataClass(): Boolean {
|
||||
if (this !is IrSimpleFunction) return false
|
||||
val original = getOriginalFunction()
|
||||
val parent = original.parentClassOrNull ?: return false
|
||||
return parent.isExported(context) &&
|
||||
original.origin == IrDeclarationOrigin.GENERATED_DATA_CLASS_MEMBER &&
|
||||
original.name.identifier.startsWith(StandardNames.DATA_CLASS_COMPONENT_PREFIX)
|
||||
}
|
||||
|
||||
private fun IrDeclaration.isExportedSyntheticEnumEntriesProperty(): Boolean {
|
||||
return this is IrSimpleFunction &&
|
||||
parentEnumClassOrNull?.isExported(context) == true &&
|
||||
(body as? IrSyntheticBody)?.kind == IrSyntheticBodyKind.ENUM_ENTRIES
|
||||
}
|
||||
|
||||
private fun IrDeclaration.excludeFromJsExport() {
|
||||
annotations += generateJsExportIgnoreCall()
|
||||
}
|
||||
|
||||
private fun generateJsExportIgnoreCall(): IrConstructorCall {
|
||||
return JsIrBuilder.buildConstructorCall(context.intrinsics.jsExportIgnoreAnnotationSymbol.owner.primaryConstructor!!.symbol)
|
||||
}
|
||||
|
||||
private fun IrSimpleFunction.getOriginalFunction(): IrSimpleFunction {
|
||||
return if (overriddenSymbols.isEmpty()) {
|
||||
this
|
||||
} else {
|
||||
overriddenSymbols.first().owner.getOriginalFunction()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.ir.backend.js.utils
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.lower.parents
|
||||
import org.jetbrains.kotlin.descriptors.isClass
|
||||
import org.jetbrains.kotlin.descriptors.isInterface
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
@@ -23,6 +24,8 @@ import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.util.defaultType
|
||||
import org.jetbrains.kotlin.ir.util.isAnnotationClass
|
||||
import org.jetbrains.kotlin.ir.util.parentAsClass
|
||||
import org.jetbrains.kotlin.ir.util.isEffectivelyExternal
|
||||
import org.jetbrains.kotlin.ir.util.isEnumClass
|
||||
import org.jetbrains.kotlin.ir.util.parentClassOrNull
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
|
||||
@@ -70,6 +73,11 @@ val IrFunctionAccessExpression.typeArguments: List<IrType?>
|
||||
|
||||
val IrFunctionAccessExpression.valueArguments: List<IrExpression?>
|
||||
get() = List(valueArgumentsCount) { getValueArgument(it) }
|
||||
val IrClass.isInstantiableEnum: Boolean
|
||||
get() = isEnumClass && !isExpect && !isEffectivelyExternal()
|
||||
|
||||
val IrDeclaration.parentEnumClassOrNull: IrClass?
|
||||
get() = parents.filterIsInstance<IrClass>().firstOrNull { it.isInstantiableEnum }
|
||||
|
||||
// TODO: the code is written to pass Repl tests, so we should understand. why in Repl tests we don't have backingField
|
||||
fun JsIrBackendContext.getVoid(): IrExpression =
|
||||
|
||||
Reference in New Issue
Block a user