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.descriptors.DescriptorVisibilities
|
||||
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.isExported
|
||||
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
|
||||
.takeIf { it.shouldExportAccessor() }
|
||||
.takeIf { it.shouldExportAccessor(context.staticContext.backendContext) }
|
||||
.getOrGenerateIfFinal {
|
||||
propertyAccessorForwarder("getter forwarder") {
|
||||
JsReturn(JsInvocation(it))
|
||||
@@ -184,7 +185,7 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
|
||||
}
|
||||
|
||||
val setterForwarder = property.setter
|
||||
.takeIf { it.shouldExportAccessor() }
|
||||
.takeIf { it.shouldExportAccessor(context.staticContext.backendContext) }
|
||||
.getOrGenerateIfFinal {
|
||||
val setterArgName = JsName("value", false)
|
||||
propertyAccessorForwarder("setter forwarder") {
|
||||
@@ -219,20 +220,6 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
|
||||
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? =
|
||||
when (visibility) {
|
||||
DescriptorVisibilities.PRIVATE -> null
|
||||
@@ -260,12 +247,6 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
|
||||
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 {
|
||||
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.isEffectivelyExternal get() = (owner as? IrDeclaration)?.isEffectivelyExternal() == true
|
||||
|
||||
|
||||
+14
-12
@@ -126,18 +126,20 @@ fun translateCall(
|
||||
property != null &&
|
||||
(property.isEffectivelyExternal() || property.isExportedMember(context.staticContext.backendContext))
|
||||
) {
|
||||
val propertyName = context.getNameForProperty(property)
|
||||
val nameRef = when (jsDispatchReceiver) {
|
||||
null -> JsNameRef(propertyName)
|
||||
else -> jsElementAccess(propertyName.ident, jsDispatchReceiver)
|
||||
}
|
||||
return when (function) {
|
||||
property.getter -> nameRef
|
||||
property.setter -> jsAssignment(nameRef, arguments.single())
|
||||
else -> compilationException(
|
||||
"Function must be an accessor of corresponding property",
|
||||
function
|
||||
)
|
||||
if (function.overriddenSymbols.isEmpty() || function.overriddenStableProperty(context.staticContext.backendContext)) {
|
||||
val propertyName = context.getNameForProperty(property)
|
||||
val nameRef = when (jsDispatchReceiver) {
|
||||
null -> JsNameRef(propertyName)
|
||||
else -> jsElementAccess(propertyName.ident, jsDispatchReceiver)
|
||||
}
|
||||
return when (function) {
|
||||
property.getter -> nameRef
|
||||
property.setter -> jsAssignment(nameRef, arguments.single())
|
||||
else -> compilationException(
|
||||
"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");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("overriddenPropertyFromInterface.kt")
|
||||
public void testOverriddenPropertyFromInterface() throws Exception {
|
||||
runTest("js/js.translator/testData/box/export/overriddenPropertyFromInterface.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("overridenMethod.kt")
|
||||
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