rra/ilgonmic/export-call-site
[JS IR] Add test with exported overridden property from interface [JS IR] Accessors should not be exported when overridden from non-exported interface Merge-request: KT-MR-6166 Merged-by: Ilya Goncharov <Ilya.Goncharov@jetbrains.com> ^KT-52144 fixed
This commit is contained in:
+27
-22
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs
|
|||||||
import org.jetbrains.kotlin.backend.common.compilationException
|
import org.jetbrains.kotlin.backend.common.compilationException
|
||||||
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.ir.backend.js.JsIrBackendContext
|
||||||
import org.jetbrains.kotlin.ir.backend.js.export.isAllowedFakeOverriddenDeclaration
|
import org.jetbrains.kotlin.ir.backend.js.export.isAllowedFakeOverriddenDeclaration
|
||||||
import org.jetbrains.kotlin.ir.backend.js.export.isExported
|
import org.jetbrains.kotlin.ir.backend.js.export.isExported
|
||||||
import org.jetbrains.kotlin.ir.backend.js.export.isOverriddenExported
|
import org.jetbrains.kotlin.ir.backend.js.export.isOverriddenExported
|
||||||
@@ -176,7 +177,7 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
|
|||||||
// });
|
// });
|
||||||
|
|
||||||
val getterForwarder = property.getter
|
val getterForwarder = property.getter
|
||||||
.takeIf { it.shouldExportAccessor() }
|
.takeIf { it.shouldExportAccessor(context.staticContext.backendContext) }
|
||||||
.getOrGenerateIfFinal {
|
.getOrGenerateIfFinal {
|
||||||
propertyAccessorForwarder("getter forwarder") {
|
propertyAccessorForwarder("getter forwarder") {
|
||||||
JsReturn(JsInvocation(it))
|
JsReturn(JsInvocation(it))
|
||||||
@@ -184,7 +185,7 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
|
|||||||
}
|
}
|
||||||
|
|
||||||
val setterForwarder = property.setter
|
val setterForwarder = property.setter
|
||||||
.takeIf { it.shouldExportAccessor() }
|
.takeIf { it.shouldExportAccessor(context.staticContext.backendContext) }
|
||||||
.getOrGenerateIfFinal {
|
.getOrGenerateIfFinal {
|
||||||
val setterArgName = JsName("value", false)
|
val setterArgName = JsName("value", false)
|
||||||
propertyAccessorForwarder("setter forwarder") {
|
propertyAccessorForwarder("setter forwarder") {
|
||||||
@@ -219,20 +220,6 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
|
|||||||
overriddenSymbols.any { it.owner.isDefinedInsideExportedInterface() }
|
overriddenSymbols.any { it.owner.isDefinedInsideExportedInterface() }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun IrSimpleFunction?.shouldExportAccessor(): Boolean {
|
|
||||||
if (this == null) return false
|
|
||||||
|
|
||||||
if (parentAsClass.isExported(context.staticContext.backendContext)) return true
|
|
||||||
|
|
||||||
val property = correspondingPropertySymbol!!.owner
|
|
||||||
|
|
||||||
if (property.isOverriddenExported(context.staticContext.backendContext)) {
|
|
||||||
return isOverriddenExported(context.staticContext.backendContext)
|
|
||||||
}
|
|
||||||
|
|
||||||
return overridesExternal() || property.getJsName() != null
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun IrSimpleFunction.accessorRef(): JsNameRef? =
|
private fun IrSimpleFunction.accessorRef(): JsNameRef? =
|
||||||
when (visibility) {
|
when (visibility) {
|
||||||
DescriptorVisibilities.PRIVATE -> null
|
DescriptorVisibilities.PRIVATE -> null
|
||||||
@@ -260,12 +247,6 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
|
|||||||
return jsElementAccess(name.asString(), classPrototypeRef)
|
return jsElementAccess(name.asString(), classPrototypeRef)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun IrSimpleFunction.overridesExternal(): Boolean {
|
|
||||||
if (this.isEffectivelyExternal()) return true
|
|
||||||
|
|
||||||
return this.overriddenSymbols.any { it.owner.overridesExternal() }
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun IrClass.shouldCopyFrom(): Boolean {
|
private fun IrClass.shouldCopyFrom(): Boolean {
|
||||||
return isInterface && !isEffectivelyExternal()
|
return isInterface && !isEffectivelyExternal()
|
||||||
}
|
}
|
||||||
@@ -430,6 +411,30 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun IrSimpleFunction?.shouldExportAccessor(context: JsIrBackendContext): Boolean {
|
||||||
|
if (this == null) return false
|
||||||
|
|
||||||
|
if (parentAsClass.isExported(context)) return true
|
||||||
|
|
||||||
|
return overriddenStableProperty(context)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun IrSimpleFunction.overriddenStableProperty(context: JsIrBackendContext): Boolean {
|
||||||
|
val property = correspondingPropertySymbol!!.owner
|
||||||
|
|
||||||
|
if (property.isOverriddenExported(context)) {
|
||||||
|
return isOverriddenExported(context)
|
||||||
|
}
|
||||||
|
|
||||||
|
return overridesExternal() || property.getJsName() != null
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun IrSimpleFunction.overridesExternal(): Boolean {
|
||||||
|
if (this.isEffectivelyExternal()) return true
|
||||||
|
|
||||||
|
return this.overriddenSymbols.any { it.owner.overridesExternal() }
|
||||||
|
}
|
||||||
|
|
||||||
private val IrClassifierSymbol.isInterface get() = (owner as? IrClass)?.isInterface == true
|
private val IrClassifierSymbol.isInterface get() = (owner as? IrClass)?.isInterface == true
|
||||||
private val IrClassifierSymbol.isEffectivelyExternal get() = (owner as? IrDeclaration)?.isEffectivelyExternal() == true
|
private val IrClassifierSymbol.isEffectivelyExternal get() = (owner as? IrDeclaration)?.isEffectivelyExternal() == true
|
||||||
|
|
||||||
|
|||||||
+14
-12
@@ -126,18 +126,20 @@ fun translateCall(
|
|||||||
property != null &&
|
property != null &&
|
||||||
(property.isEffectivelyExternal() || property.isExportedMember(context.staticContext.backendContext))
|
(property.isEffectivelyExternal() || property.isExportedMember(context.staticContext.backendContext))
|
||||||
) {
|
) {
|
||||||
val propertyName = context.getNameForProperty(property)
|
if (function.overriddenSymbols.isEmpty() || function.overriddenStableProperty(context.staticContext.backendContext)) {
|
||||||
val nameRef = when (jsDispatchReceiver) {
|
val propertyName = context.getNameForProperty(property)
|
||||||
null -> JsNameRef(propertyName)
|
val nameRef = when (jsDispatchReceiver) {
|
||||||
else -> jsElementAccess(propertyName.ident, jsDispatchReceiver)
|
null -> JsNameRef(propertyName)
|
||||||
}
|
else -> jsElementAccess(propertyName.ident, jsDispatchReceiver)
|
||||||
return when (function) {
|
}
|
||||||
property.getter -> nameRef
|
return when (function) {
|
||||||
property.setter -> jsAssignment(nameRef, arguments.single())
|
property.getter -> nameRef
|
||||||
else -> compilationException(
|
property.setter -> jsAssignment(nameRef, arguments.single())
|
||||||
"Function must be an accessor of corresponding property",
|
else -> compilationException(
|
||||||
function
|
"Function must be an accessor of corresponding property",
|
||||||
)
|
function
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+6
@@ -2568,6 +2568,12 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest {
|
|||||||
runTest("js/js.translator/testData/box/export/overriddenExternalMethodWithSameStableNameMethod.kt");
|
runTest("js/js.translator/testData/box/export/overriddenExternalMethodWithSameStableNameMethod.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("overriddenPropertyFromInterface.kt")
|
||||||
|
public void testOverriddenPropertyFromInterface() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/box/export/overriddenPropertyFromInterface.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("overridenMethod.kt")
|
@TestMetadata("overridenMethod.kt")
|
||||||
public void testOverridenMethod() throws Exception {
|
public void testOverridenMethod() throws Exception {
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
// TARGET_BACKEND: JS_IR
|
||||||
|
|
||||||
|
interface Foo {
|
||||||
|
val foo: String
|
||||||
|
|
||||||
|
val foo2: String
|
||||||
|
|
||||||
|
var foo3: String
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsExport
|
||||||
|
class Bar : Foo {
|
||||||
|
override val foo: String
|
||||||
|
get() = "foo"
|
||||||
|
|
||||||
|
override val foo2: String = "foo2"
|
||||||
|
|
||||||
|
override var foo3: String = "foo3"
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val bar = Bar()
|
||||||
|
if (bar.foo != "foo") return "fail 1"
|
||||||
|
if (bar.foo2 != "foo2") return "fail 2"
|
||||||
|
if (bar.foo3 != "foo3") return "fail 3"
|
||||||
|
bar.foo3 = "foo4"
|
||||||
|
if (bar.foo3 != "foo4") return "fail 4"
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user