KT-2752: declare properties as a pair of functions when accessors are marked with @JsName
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
package foo
|
||||
|
||||
class A {
|
||||
var x: Int
|
||||
<!JS_NAME_CLASH!>@JsName("xx") get() = 0<!>
|
||||
<!JS_NAME_CLASH!>@JsName("xx") set(value) {}<!>
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package
|
||||
|
||||
package foo {
|
||||
|
||||
public final class A {
|
||||
public constructor A()
|
||||
public final var x: kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
}
|
||||
@@ -331,6 +331,12 @@ public class DiagnosticsTestWithJsStdLibGenerated extends AbstractDiagnosticsTes
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("jsNameOnAccessors.kt")
|
||||
public void testJsNameOnAccessors() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithJsStdLib/name/jsNameOnAccessors.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("jsNameOnPropertyAndAccessor.kt")
|
||||
public void testJsNameOnPropertyAndAccessor() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithJsStdLib/name/jsNameOnPropertyAndAccessor.kt");
|
||||
|
||||
@@ -36,6 +36,7 @@ object JsNameChecker : SimpleDeclarationChecker {
|
||||
}
|
||||
}
|
||||
|
||||
if (AnnotationsUtils.getJsName(descriptor) == null) return
|
||||
val jsNamePsi = AnnotationsUtils.getJsNameAnnotationPsi(bindingContext, declaration) ?: return
|
||||
|
||||
when (descriptor) {
|
||||
@@ -45,7 +46,7 @@ object JsNameChecker : SimpleDeclarationChecker {
|
||||
}
|
||||
}
|
||||
is PropertyAccessorDescriptor -> {
|
||||
if (!descriptor.isDefault && AnnotationsUtils.getJsName(descriptor.correspondingProperty) != null) {
|
||||
if (AnnotationsUtils.getJsName(descriptor.correspondingProperty) != null) {
|
||||
diagnosticHolder.report(ErrorsJs.JS_NAME_ON_ACCESSOR_AND_PROPERTY.on(jsNamePsi))
|
||||
}
|
||||
}
|
||||
|
||||
+9
-7
@@ -97,15 +97,17 @@ class JsNameClashChecker : SimpleDeclarationChecker {
|
||||
}
|
||||
|
||||
private fun collect(descriptor: DeclarationDescriptor, target: MutableMap<String, DeclarationDescriptor>) {
|
||||
if (descriptor is PropertyDescriptor && descriptor.isExtension) {
|
||||
descriptor.accessors.forEach { collect(it, target) }
|
||||
}
|
||||
else {
|
||||
val fqn = fqnGenerator.generate(descriptor)
|
||||
if (fqn.shared && isOpaque(fqn.descriptor)) {
|
||||
target[fqn.names.last()] = fqn.descriptor
|
||||
if (descriptor is PropertyDescriptor) {
|
||||
if (descriptor.isExtension || AnnotationsUtils.hasJsNameInAccessors(descriptor)) {
|
||||
descriptor.accessors.forEach { collect(it, target) }
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
val fqn = fqnGenerator.generate(descriptor)
|
||||
if (fqn.shared && isOpaque(fqn.descriptor)) {
|
||||
target[fqn.names.last()] = fqn.descriptor
|
||||
}
|
||||
}
|
||||
|
||||
private fun isOpaque(descriptor: DeclarationDescriptor) =
|
||||
|
||||
@@ -20,10 +20,7 @@ import com.intellij.util.Function;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor;
|
||||
import org.jetbrains.kotlin.js.PredefinedAnnotation;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
@@ -143,6 +140,12 @@ public final class AnnotationsUtils {
|
||||
AnnotationDescriptor annotation = getAnnotationByName(descriptor, new FqName(JS_NAME));
|
||||
if (annotation == null) return null;
|
||||
|
||||
if (descriptor instanceof PropertyAccessorDescriptor) {
|
||||
PropertyAccessorDescriptor accessor = (PropertyAccessorDescriptor) descriptor;
|
||||
AnnotationDescriptor propertyAnnotation = getAnnotationByName(accessor.getCorrespondingProperty(), new FqName(JS_NAME));
|
||||
if (propertyAnnotation == annotation) return null;
|
||||
}
|
||||
|
||||
ConstantValue<?> value = annotation.getAllValueArguments().values().iterator().next();
|
||||
assert value != null : "JsName annotation should always declare string parameter";
|
||||
|
||||
@@ -202,4 +205,11 @@ public final class AnnotationsUtils {
|
||||
ClassDescriptor containingClass = DescriptorUtils.getContainingClass(descriptor);
|
||||
return containingClass != null && hasAnnotationOrInsideAnnotatedClass(containingClass, fqName);
|
||||
}
|
||||
|
||||
public static boolean hasJsNameInAccessors(@NotNull PropertyDescriptor property) {
|
||||
for (PropertyAccessorDescriptor accessor : property.getAccessors()) {
|
||||
if (getJsName(accessor) != null) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
+2
-3
@@ -25,12 +25,11 @@ import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor
|
||||
import org.jetbrains.kotlin.js.translate.context.Namer
|
||||
import org.jetbrains.kotlin.js.translate.context.TranslationContext
|
||||
import org.jetbrains.kotlin.js.translate.reference.ReferenceTranslator
|
||||
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils
|
||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
|
||||
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils
|
||||
import org.jetbrains.kotlin.psi.KtSuperExpression
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
|
||||
@@ -67,7 +66,7 @@ fun VariableAccessInfo.isGetAccess(): Boolean = value == null
|
||||
|
||||
fun VariableAccessInfo.getAccessDescriptor(): DeclarationDescriptor {
|
||||
val descriptor = variableDescriptor
|
||||
if (descriptor is PropertyDescriptor && descriptor.isExtension) {
|
||||
if (descriptor is PropertyDescriptor && (descriptor.isExtension || TranslationUtils.shouldGenerateAccessors(descriptor))) {
|
||||
val propertyAccessorDescriptor = if (isGetAccess()) descriptor.getter else descriptor.setter
|
||||
return propertyAccessorDescriptor!!
|
||||
}
|
||||
|
||||
+52
-21
@@ -24,7 +24,9 @@ import com.google.dart.compiler.backend.js.ast.metadata.sideEffects
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
|
||||
import org.jetbrains.kotlin.js.translate.context.Namer
|
||||
import org.jetbrains.kotlin.js.translate.context.Namer.getCapturedVarAccessor
|
||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils.fqnWithoutSideEffects
|
||||
import org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils
|
||||
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils
|
||||
import org.jetbrains.kotlin.resolve.BindingContextUtils.isVarCapturedInClosure
|
||||
@@ -37,16 +39,36 @@ object NativeVariableAccessCase : VariableAccessCase() {
|
||||
}
|
||||
|
||||
override fun VariableAccessInfo.dispatchReceiver(): JsExpression {
|
||||
return constructAccessExpression(JsNameRef(variableName, dispatchReceiver!!))
|
||||
val descriptor = resolvedCall.resultingDescriptor
|
||||
return if (descriptor is PropertyDescriptor && TranslationUtils.shouldGenerateAccessors(descriptor)) {
|
||||
val methodRef = context.getNameForDescriptor(getAccessDescriptor())
|
||||
JsInvocation(fqnWithoutSideEffects(methodRef, dispatchReceiver!!), *additionalArguments.toTypedArray())
|
||||
}
|
||||
else {
|
||||
constructAccessExpression(JsNameRef(variableName, dispatchReceiver!!))
|
||||
}
|
||||
}
|
||||
|
||||
override fun VariableAccessInfo.noReceivers(): JsExpression {
|
||||
return constructAccessExpression(variableName.makeRef())
|
||||
val descriptor = resolvedCall.resultingDescriptor
|
||||
return if (descriptor is PropertyDescriptor && TranslationUtils.shouldGenerateAccessors(descriptor)) {
|
||||
val methodRef = context.aliasOrValue(callableDescriptor) { context.getQualifiedReference(getAccessDescriptor()) }
|
||||
JsInvocation(methodRef, *additionalArguments.toTypedArray())
|
||||
}
|
||||
else {
|
||||
constructAccessExpression(variableName.makeRef())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object DefaultVariableAccessCase : VariableAccessCase() {
|
||||
override fun VariableAccessInfo.noReceivers(): JsExpression {
|
||||
val descriptor = resolvedCall.resultingDescriptor
|
||||
if (descriptor is PropertyDescriptor && TranslationUtils.shouldGenerateAccessors(descriptor)) {
|
||||
val methodRef = context.aliasOrValue(callableDescriptor) { context.getQualifiedReference(getAccessDescriptor()) }
|
||||
return JsInvocation(methodRef, *additionalArguments.toTypedArray())
|
||||
}
|
||||
|
||||
val functionRef = context.aliasOrValue(callableDescriptor) {
|
||||
context.getQualifiedReference(variableDescriptor)
|
||||
}
|
||||
@@ -73,30 +95,28 @@ object DefaultVariableAccessCase : VariableAccessCase() {
|
||||
}
|
||||
|
||||
override fun VariableAccessInfo.dispatchReceiver(): JsExpression {
|
||||
val accessor = JsNameRef(variableName, dispatchReceiver!!)
|
||||
val descriptor = callableDescriptor
|
||||
if (descriptor is PropertyDescriptor && !JsDescriptorUtils.sideEffectsPossibleOnRead(descriptor)) {
|
||||
accessor.sideEffects = SideEffectKind.DEPENDS_ON_STATE
|
||||
val descriptor = resolvedCall.resultingDescriptor
|
||||
return if (descriptor is PropertyDescriptor && TranslationUtils.shouldGenerateAccessors(descriptor)) {
|
||||
val callExpr = pureFqn(context.getNameForDescriptor(getAccessDescriptor()), dispatchReceiver!!)
|
||||
JsInvocation(callExpr, *additionalArguments.toTypedArray())
|
||||
}
|
||||
else {
|
||||
val accessor = JsNameRef(variableName, dispatchReceiver!!)
|
||||
if (descriptor is PropertyDescriptor && !JsDescriptorUtils.sideEffectsPossibleOnRead(descriptor)) {
|
||||
accessor.sideEffects = SideEffectKind.DEPENDS_ON_STATE
|
||||
}
|
||||
constructAccessExpression(accessor)
|
||||
}
|
||||
return constructAccessExpression(accessor)
|
||||
}
|
||||
|
||||
override fun VariableAccessInfo.extensionReceiver(): JsExpression {
|
||||
val functionRef = context.aliasOrValue(callableDescriptor) { context.getQualifiedReference(getAccessDescriptor()) }
|
||||
return if (isGetAccess()) {
|
||||
JsInvocation(functionRef, extensionReceiver!!)
|
||||
} else {
|
||||
JsInvocation(functionRef, extensionReceiver!!, value!!)
|
||||
}
|
||||
return JsInvocation(functionRef, extensionReceiver!!, *additionalArguments.toTypedArray())
|
||||
}
|
||||
|
||||
override fun VariableAccessInfo.bothReceivers(): JsExpression {
|
||||
val funRef = JsNameRef(context.getNameForDescriptor(getAccessDescriptor()), dispatchReceiver!!)
|
||||
return if (isGetAccess()) {
|
||||
JsInvocation(funRef, extensionReceiver!!)
|
||||
} else {
|
||||
JsInvocation(funRef, extensionReceiver!!, value!!)
|
||||
}
|
||||
return JsInvocation(funRef, extensionReceiver!!, *additionalArguments.toTypedArray())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,14 +148,25 @@ object DelegatePropertyAccessIntrinsic : DelegateIntrinsic<VariableAccessInfo> {
|
||||
object SuperPropertyAccessCase : VariableAccessCase() {
|
||||
override fun VariableAccessInfo.dispatchReceiver(): JsExpression {
|
||||
val variableName = context.program().getStringLiteral(this.variableName.ident)
|
||||
val descriptor = resolvedCall.resultingDescriptor
|
||||
|
||||
return if (isGetAccess())
|
||||
JsInvocation(context.namer().callGetProperty, dispatchReceiver!!, calleeOwner, variableName)
|
||||
else
|
||||
JsInvocation(context.namer().callSetProperty, dispatchReceiver!!, calleeOwner, variableName, value!!)
|
||||
return if (descriptor is PropertyDescriptor && TranslationUtils.shouldGenerateAccessors(descriptor)) {
|
||||
val accessor = getAccessDescriptor()
|
||||
val prototype = fqnWithoutSideEffects(Namer.getPrototypeName(), context.getQualifiedReference(descriptor.containingDeclaration))
|
||||
val funRef = Namer.getFunctionCallRef(fqnWithoutSideEffects(context.getNameForDescriptor(accessor), prototype))
|
||||
val arguments = listOf(dispatchReceiver!!) + additionalArguments
|
||||
JsInvocation(funRef, *arguments.toTypedArray())
|
||||
}
|
||||
else {
|
||||
val callExpr = if (isGetAccess()) context.namer().callGetProperty else context.namer().callSetProperty
|
||||
val arguments = listOf(dispatchReceiver!!, calleeOwner, variableName) + additionalArguments
|
||||
JsInvocation(callExpr, *arguments.toTypedArray())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val VariableAccessInfo.additionalArguments: List<JsExpression> get() = value?.let { listOf(it) }.orEmpty()
|
||||
|
||||
fun VariableAccessInfo.translateVariableAccess(): JsExpression {
|
||||
val intrinsic = DelegatePropertyAccessIntrinsic.intrinsic(this)
|
||||
|
||||
|
||||
@@ -236,7 +236,7 @@ public final class StaticContext {
|
||||
expression = Namer.kotlinObject();
|
||||
partNames = getNameForFQNPart(part);
|
||||
}
|
||||
else if (isNativeObject(part.getDescriptor()) && !isNativeObject(part.getScope())) {
|
||||
else if (isNative(part.getDescriptor()) && !isNativeObject(part.getScope())) {
|
||||
expression = null;
|
||||
partNames = getNameForFQNPart(part);
|
||||
}
|
||||
@@ -258,6 +258,17 @@ public final class StaticContext {
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isNative(DeclarationDescriptor descriptor) {
|
||||
if (isNativeObject(descriptor)) return true;
|
||||
|
||||
if (descriptor instanceof PropertyAccessorDescriptor) {
|
||||
PropertyAccessorDescriptor accessor = (PropertyAccessorDescriptor) descriptor;
|
||||
return isNative(accessor.getCorrespondingProperty());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JsNameRef getQualifiedReference(@NotNull FqName packageFqName) {
|
||||
JsName packageName = getNameForPackage(packageFqName);
|
||||
|
||||
+2
-1
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.js.translate.general.AbstractTranslator
|
||||
import org.jetbrains.kotlin.js.translate.general.Translation
|
||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils.pureFqn
|
||||
import org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils
|
||||
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils
|
||||
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils.assignmentToBackingField
|
||||
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils.backingFieldReference
|
||||
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils.translateFunctionAsEcma5PropertyDescriptor
|
||||
@@ -72,7 +73,7 @@ fun MutableList<JsPropertyInitializer>.addGetterAndSetter(
|
||||
generateSetter: () -> JsPropertyInitializer
|
||||
) {
|
||||
val to: MutableList<JsPropertyInitializer>
|
||||
if (!descriptor.isExtension) {
|
||||
if (!descriptor.isExtension && !TranslationUtils.shouldGenerateAccessors(descriptor)) {
|
||||
to = SmartList<JsPropertyInitializer>()
|
||||
this.add(JsPropertyInitializer(context.getNameForDescriptor(descriptor).makeRef(), JsObjectLiteral(to, true)))
|
||||
}
|
||||
|
||||
@@ -54,7 +54,10 @@ public final class TranslationUtils {
|
||||
public static JsPropertyInitializer translateFunctionAsEcma5PropertyDescriptor(@NotNull JsFunction function,
|
||||
@NotNull FunctionDescriptor descriptor,
|
||||
@NotNull TranslationContext context) {
|
||||
if (DescriptorUtils.isExtension(descriptor)) {
|
||||
if (DescriptorUtils.isExtension(descriptor) ||
|
||||
descriptor instanceof PropertyAccessorDescriptor &&
|
||||
shouldGenerateAccessors(((PropertyAccessorDescriptor) descriptor).getCorrespondingProperty())
|
||||
) {
|
||||
return translateExtensionFunctionAsEcma5DataDescriptor(function, descriptor, context);
|
||||
}
|
||||
else {
|
||||
@@ -299,4 +302,24 @@ public final class TranslationUtils {
|
||||
DeclarationDescriptor descriptor = context.bindingContext().get(BindingContext.REFERENCE_TARGET, ((KtSimpleNameExpression) expression));
|
||||
return !(descriptor instanceof LocalVariableDescriptor) || !((LocalVariableDescriptor) descriptor).isDelegated();
|
||||
}
|
||||
|
||||
public static boolean shouldGenerateAccessors(@NotNull CallableDescriptor descriptor) {
|
||||
if (descriptor instanceof PropertyDescriptor) {
|
||||
return shouldGenerateAccessors((PropertyDescriptor) descriptor);
|
||||
}
|
||||
else if (descriptor instanceof PropertyAccessorDescriptor) {
|
||||
return shouldGenerateAccessors(((PropertyAccessorDescriptor) descriptor).getCorrespondingProperty());
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean shouldGenerateAccessors(@NotNull PropertyDescriptor property) {
|
||||
if (AnnotationsUtils.hasJsNameInAccessors(property)) return true;
|
||||
for (PropertyDescriptor overriddenProperty : property.getOverriddenDescriptors()) {
|
||||
if (shouldGenerateAccessors(overriddenProperty)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
package foo
|
||||
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
class A {
|
||||
@JsName("xx") val x: Int by B()
|
||||
}
|
||||
|
||||
class B {
|
||||
operator fun getValue(thisRef: Any?, property: KProperty<*>): Int = 23
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val a = A()
|
||||
assertEquals(23, a.x)
|
||||
|
||||
val d: dynamic = a
|
||||
assertEquals(23, d.xx)
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package foo
|
||||
|
||||
@native class A {
|
||||
val xx: Int
|
||||
@JsName("getX") get
|
||||
|
||||
var yy: Int
|
||||
@JsName("getY") get
|
||||
@JsName("setY") set
|
||||
}
|
||||
|
||||
@native var zz: Int
|
||||
@JsName("getZ") get
|
||||
@JsName("setZ") set
|
||||
|
||||
fun box(): String {
|
||||
val a = A()
|
||||
|
||||
assertEquals(23, a.xx)
|
||||
assertEquals(0, a.yy)
|
||||
a.yy = 42
|
||||
assertEquals(42, a.yy)
|
||||
|
||||
assertEquals(32, zz)
|
||||
zz = 232
|
||||
assertEquals(232, zz)
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
function A() {
|
||||
this.y_ = 0;
|
||||
}
|
||||
A.prototype.getX = function() {
|
||||
return 23;
|
||||
};
|
||||
A.prototype.getY = function() {
|
||||
return this.y_;
|
||||
};
|
||||
A.prototype.setY = function(y) {
|
||||
return this.y_ = y;
|
||||
};
|
||||
|
||||
var z_ = 32;
|
||||
function getZ() {
|
||||
return z_;
|
||||
}
|
||||
function setZ(z) {
|
||||
z_ = z;
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package foo
|
||||
|
||||
class A {
|
||||
val x: Int
|
||||
@JsName("getX_") get() = 23
|
||||
|
||||
var y: Int = 0
|
||||
@JsName("getY_") get() = field + 10
|
||||
@JsName("setY_") set(value) {
|
||||
field = value
|
||||
}
|
||||
}
|
||||
|
||||
val A.z: Int
|
||||
@JsName("getZ_") get() = 42
|
||||
|
||||
fun getPackage() = js("return Kotlin.modules.JS_TESTS.foo")
|
||||
|
||||
fun box(): String {
|
||||
val a = A()
|
||||
|
||||
assertEquals(23, a.x)
|
||||
assertEquals(10, a.y)
|
||||
a.y = 13
|
||||
assertEquals(23, a.y)
|
||||
assertEquals(42, a.z)
|
||||
|
||||
val d: dynamic = A()
|
||||
|
||||
assertEquals(23, d.getX_())
|
||||
assertEquals(10, d.getY_())
|
||||
d.setY_(13)
|
||||
assertEquals(23, d.getY_())
|
||||
assertEquals(42, getPackage().getZ_(d))
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package foo
|
||||
|
||||
val x: Int
|
||||
@JsName("getX_") get() = 23
|
||||
|
||||
var y: Int = 0
|
||||
@JsName("getY_") get() = field + 10
|
||||
@JsName("setY_") set(value) {
|
||||
field = value
|
||||
}
|
||||
|
||||
|
||||
fun getPackage() = js("return Kotlin.modules.JS_TESTS.foo")
|
||||
|
||||
fun box(): String {
|
||||
assertEquals(23, x)
|
||||
assertEquals(10, y)
|
||||
y = 13
|
||||
assertEquals(23, y)
|
||||
|
||||
y = 0
|
||||
val d = getPackage()
|
||||
|
||||
assertEquals(23, d.getX_())
|
||||
assertEquals(10, d.getY_())
|
||||
d.setY_(13)
|
||||
assertEquals(23, d.getY_())
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
package foo
|
||||
|
||||
open class A {
|
||||
open val x: Int
|
||||
@JsName("getX_") get() = 23
|
||||
|
||||
open var y: Int = 0
|
||||
@JsName("getY_") get() = field + 10
|
||||
@JsName("setY_") set(value) {
|
||||
field = value
|
||||
}
|
||||
}
|
||||
|
||||
class B : A() {
|
||||
override val x: Int
|
||||
get() = 42
|
||||
|
||||
override var y: Int
|
||||
get() = super.y + 5
|
||||
set(value) {
|
||||
super.y = value + 2
|
||||
}
|
||||
}
|
||||
|
||||
fun getPackage() = js("return Kotlin.modules.JS_TESTS.foo")
|
||||
|
||||
fun box(): String {
|
||||
val a = B()
|
||||
|
||||
assertEquals(42, a.x)
|
||||
assertEquals(15, a.y)
|
||||
a.y = 13
|
||||
assertEquals(30, a.y)
|
||||
|
||||
val d: dynamic = B()
|
||||
|
||||
assertEquals(42, d.getX_())
|
||||
assertEquals(15, d.getY_())
|
||||
d.setY_(13)
|
||||
assertEquals(30, d.getY_())
|
||||
|
||||
return "OK"
|
||||
}
|
||||
Reference in New Issue
Block a user