JS: refactor flat declaration generator. Add more tests on inter-module dependencies

This commit is contained in:
Alexey Andreev
2016-10-26 17:14:54 +03:00
parent cc38bd3146
commit 0252fe57af
26 changed files with 483 additions and 81 deletions
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.js.naming
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor
import org.jetbrains.kotlin.js.descriptorUtils.getJetTypeFqName
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils.getNameForAnnotatedObject
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils.isNativeObject
import org.jetbrains.kotlin.resolve.DescriptorUtils
@@ -777,6 +777,75 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest {
}
}
@TestMetadata("js/js.translator/testData/box/crossModuleRef")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class CrossModuleRef extends AbstractBoxJsTest {
public void testAllFilesPresentInCrossModuleRef() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/box/crossModuleRef"), Pattern.compile("^([^_](.+))\\.kt$"), true);
}
@TestMetadata("callableObjectRef.kt")
public void testCallableObjectRef() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/crossModuleRef/callableObjectRef.kt");
doTest(fileName);
}
@TestMetadata("constructor.kt")
public void testConstructor() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/crossModuleRef/constructor.kt");
doTest(fileName);
}
@TestMetadata("inheritance.kt")
public void testInheritance() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/crossModuleRef/inheritance.kt");
doTest(fileName);
}
@TestMetadata("object.kt")
public void testObject() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/crossModuleRef/object.kt");
doTest(fileName);
}
@TestMetadata("objectInInlineClosure.kt")
public void testObjectInInlineClosure() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/crossModuleRef/objectInInlineClosure.kt");
doTest(fileName);
}
@TestMetadata("objectIsObject.kt")
public void testObjectIsObject() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/crossModuleRef/objectIsObject.kt");
doTest(fileName);
}
@TestMetadata("topLevelExtension.kt")
public void testTopLevelExtension() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/crossModuleRef/topLevelExtension.kt");
doTest(fileName);
}
@TestMetadata("topLevelFunction.kt")
public void testTopLevelFunction() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/crossModuleRef/topLevelFunction.kt");
doTest(fileName);
}
@TestMetadata("topLevelMutableProperty.kt")
public void testTopLevelMutableProperty() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/crossModuleRef/topLevelMutableProperty.kt");
doTest(fileName);
}
@TestMetadata("topLevelProperty.kt")
public void testTopLevelProperty() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/crossModuleRef/topLevelProperty.kt");
doTest(fileName);
}
}
@TestMetadata("js/js.translator/testData/box/dataClass")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -25,7 +25,6 @@ import org.jetbrains.kotlin.descriptors.PropertyAccessorDescriptor
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.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
@@ -77,9 +77,6 @@ object DefaultFunctionCallCase : FunctionCallCase() {
val functionCallRef = Namer.getFunctionApplyRef(JsNameRef(context.getNameForDescriptor(callableDescriptor)))
return JsInvocation(functionCallRef, argumentsInfo.translateArguments)
}
if (isNative) {
return JsInvocation(JsNameRef(context.getNameForDescriptor(callableDescriptor)), argumentsInfo.translateArguments)
}
val functionRef = ReferenceTranslator.translateAsValueReference(callableDescriptor, context)
return JsInvocation(functionRef, argumentsInfo.translateArguments)
@@ -82,7 +82,7 @@ object DefaultVariableAccessCase : VariableAccessCase() {
}
if (descriptor is FakeCallableDescriptorForObject) {
return JsInvocation(pureFqn(context.getNameForObjectInstance (descriptor.getReferencedObject()), null))
return ReferenceTranslator.translateAsValueReference(descriptor.getReferencedObject(), context)
}
val functionRef = ReferenceTranslator.translateAsValueReference(callableDescriptor, context)
@@ -23,7 +23,9 @@ import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils.assignment
import org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyPublicApi
internal class DeclarationExporter(val context: StaticContext) {
@@ -42,9 +44,16 @@ internal class DeclarationExporter(val context: StaticContext) {
if (!descriptor.shouldBeExported(force)) return
exportedDeclarations.add(descriptor)
val qualifier = when (container) {
is PackageFragmentDescriptor -> getLocalPackageReference(container.fqName)
else -> context.getInnerNameForDescriptor(container).makeRef()
val qualifier = when {
container is PackageFragmentDescriptor -> {
getLocalPackageReference(container.fqName)
}
DescriptorUtils.isObject(container) -> {
JsAstUtils.prototypeOf(context.getInnerNameForDescriptor(container).makeRef())
}
else -> {
context.getInnerNameForDescriptor(container).makeRef()
}
}
when {
@@ -80,8 +89,10 @@ internal class DeclarationExporter(val context: StaticContext) {
val propertyLiteral = JsObjectLiteral(true)
val name = context.getNameForDescriptor(declaration).ident
val simpleProperty = JsDescriptorUtils.isSimpleFinalProperty(declaration) &&
!TranslationUtils.shouldAccessViaFunctions(declaration)
val getterBody: JsExpression = if (JsDescriptorUtils.isSimpleFinalProperty(declaration)) {
val getterBody: JsExpression = if (simpleProperty) {
val accessToField = JsReturn(context.getInnerNameForDescriptor(declaration).makeRef())
JsFunction(context.rootFunction.scope, JsBlock(accessToField), "$declaration getter")
}
@@ -91,7 +102,7 @@ internal class DeclarationExporter(val context: StaticContext) {
propertyLiteral.propertyInitializers += JsPropertyInitializer(JsNameRef("get"), getterBody)
if (declaration.isVar) {
val setterBody: JsExpression = if (JsDescriptorUtils.isSimpleFinalProperty(declaration)) {
val setterBody: JsExpression = if (simpleProperty) {
val statements = mutableListOf<JsStatement>()
val function = JsFunction(context.rootFunction.scope, JsBlock(statements), "$declaration setter")
val valueName = function.scope.declareFreshName("value")
@@ -59,10 +59,7 @@ public class TranslationContext {
private final ClassDescriptor classDescriptor;
@NotNull
public static TranslationContext rootContext(
@NotNull StaticContext staticContext,
@NotNull JsFunction rootFunction
) {
public static TranslationContext rootContext(@NotNull StaticContext staticContext, @NotNull JsFunction rootFunction) {
JsBlock block = new JsBlock(staticContext.getTopLevelStatements());
DynamicContext rootDynamicContext = DynamicContext.rootContext(rootFunction.getScope(), block);
AliasingContext rootAliasingContext = AliasingContext.getCleanContext();
@@ -565,11 +562,6 @@ public class TranslationContext {
return staticContext.getModuleExpressionFor(descriptor);
}
@NotNull
public JsFunction getRootFunction() {
return staticContext.getRootFunction();
}
public void addDeclarationStatement(@NotNull JsStatement statement) {
staticContext.getDeclarationStatements().add(statement);
}
@@ -578,28 +570,19 @@ public class TranslationContext {
staticContext.getTopLevelStatements().add(statement);
}
@NotNull
public JsFunction defineTopLevelFunction(@NotNull DeclarationDescriptor descriptor) {
JsFunction function = createTopLevelFunction(descriptor);
addDeclarationStatement(function.makeStmt());
return function;
}
@NotNull
public JsName createGlobalName(@NotNull String suggestedName) {
return staticContext.getRootFunction().getScope().declareFreshName(suggestedName);
}
@NotNull
private JsFunction createTopLevelFunction(@NotNull DeclarationDescriptor descriptor) {
JsFunction function = createTopLevelAnonymousFunction(descriptor);
function.setName(staticContext.getInnerNameForDescriptor(descriptor));
return function;
public JsFunction createTopLevelFunction(@NotNull DeclarationDescriptor descriptor) {
return createTopLevelFunction(descriptor.toString());
}
@NotNull
public JsFunction createTopLevelAnonymousFunction(@NotNull DeclarationDescriptor descriptor) {
return new JsFunction(getRootFunction().getScope(), new JsBlock(), descriptor.toString());
public JsFunction createTopLevelFunction(@NotNull String description) {
return new JsFunction(staticContext.getRootFunction().getScope(), new JsBlock(), description);
}
public void addClass(@NotNull ClassDescriptor classDescriptor) {
@@ -74,7 +74,9 @@ class ClassTranslator private constructor(
val scope = context().getScopeForDescriptor(descriptor)
val context = context().newDeclaration(descriptor)
val constructorFunction = context.defineTopLevelFunction(descriptor)
val constructorFunction = context.createTopLevelFunction(descriptor)
constructorFunction.name = context.getInnerNameForDescriptor(descriptor)
context.addDeclarationStatement(constructorFunction.makeStmt())
val enumInitFunction = if (descriptor.kind == ClassKind.ENUM_CLASS) createEnumInitFunction() else null
val nonConstructorContext = context.innerWithUsageTracker(scope, descriptor)
@@ -139,9 +141,9 @@ class ClassTranslator private constructor(
}
private fun createEnumInitFunction(): JsFunction {
val function = context().createTopLevelAnonymousFunction(descriptor)
val function = context().createTopLevelFunction(descriptor)
function.name = context().createGlobalName(StaticContext.getSuggestedName(descriptor) + "_initFields")
val emptyFunction = context().createTopLevelAnonymousFunction(descriptor)
val emptyFunction = context().createTopLevelFunction(descriptor)
function.body.statements += JsAstUtils.assignment(JsAstUtils.pureFqn(function.name, null), emptyFunction).makeStmt()
context().addDeclarationStatement(function.makeStmt())
return function
@@ -211,7 +213,9 @@ class ClassTranslator private constructor(
}
// Translate constructor body
val constructorInitializer = context.defineTopLevelFunction(constructorDescriptor)
val constructorInitializer = context.getFunctionObject(constructorDescriptor)
constructorInitializer.name = context.getInnerNameForDescriptor(constructorDescriptor)
context.addTopLevelStatement(constructorInitializer.makeStmt())
FunctionTranslator.newInstance(constructor, context, constructorInitializer).translateAsMethodWithoutMetadata()
// Translate super/this call
@@ -415,7 +419,7 @@ class ClassTranslator private constructor(
private fun addObjectMethods() {
context().addDeclarationStatement(JsAstUtils.newVar(cachedInstanceName, JsLiteral.NULL))
val instanceFun = JsFunction(context().rootFunction.scope, JsBlock(), "Instance function: " + descriptor)
val instanceFun = context().createTopLevelFunction("Instance function: " + descriptor)
instanceFun.name = context().getNameForObjectInstance(descriptor)
if (enumInitializerName == null) {
@@ -69,7 +69,7 @@ class DeclarationBodyVisitor(
context.addDeclarationStatement(JsAstUtils.newVar(enumInstanceName, null))
enumInitializer.body.statements += JsAstUtils.assignment(pureFqn(enumInstanceName, null), jsEnumEntryCreation).makeStmt()
val enumInstanceFunction = context.createTopLevelAnonymousFunction(descriptor)
val enumInstanceFunction = context.createTopLevelFunction(descriptor)
enumInstanceFunction.name = context.getNameForObjectInstance(descriptor)
context.addDeclarationStatement(enumInstanceFunction.makeStmt())
@@ -189,7 +189,7 @@ class JsDataClassGenerator extends DataClassMethodGenerator {
}
private JsFunction generateJsMethod(@NotNull FunctionDescriptor functionDescriptor) {
JsFunction functionObject = context.createTopLevelAnonymousFunction(functionDescriptor);
JsFunction functionObject = context.createTopLevelFunction(functionDescriptor);
ClassDescriptor containingClass = (ClassDescriptor) functionDescriptor.getContainingDeclaration();
UtilsKt.addFunctionToPrototype(context, containingClass, functionDescriptor, functionObject);
return functionObject;
@@ -259,6 +259,8 @@ public final class Translation {
JsBlock rootBlock = rootFunction.getBody();
List<JsStatement> statements = rootBlock.getStatements();
program.getScope().declareName("_");
TranslationContext context = TranslationContext.rootContext(staticContext, rootFunction);
PackageDeclarationTranslator.translateFiles(files, context);
staticContext.postProcess();
@@ -16,7 +16,6 @@
package org.jetbrains.kotlin.js.translate.initializer;
import com.google.dart.compiler.backend.js.JsReservedIdentifiers;
import com.google.dart.compiler.backend.js.ast.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.descriptors.*;
@@ -27,12 +26,10 @@ import org.jetbrains.kotlin.js.translate.context.UsageTracker;
import org.jetbrains.kotlin.js.translate.declaration.DelegationTranslator;
import org.jetbrains.kotlin.js.translate.general.AbstractTranslator;
import org.jetbrains.kotlin.js.translate.reference.CallArgumentTranslator;
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils;
import org.jetbrains.kotlin.js.translate.utils.BindingUtils;
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils;
import org.jetbrains.kotlin.js.translate.utils.jsAstUtils.AstUtilsKt;
import org.jetbrains.kotlin.lexer.KtTokens;
import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.psi.KtClassOrObject;
import org.jetbrains.kotlin.psi.KtEnumEntry;
import org.jetbrains.kotlin.psi.KtParameter;
@@ -76,8 +73,6 @@ public final class ClassInitializerTranslator extends AbstractTranslator {
this.initFunction = initFunction;
this.context = context.contextWithScope(initFunction);
classDescriptor = BindingUtils.getClassDescriptor(bindingContext(), classDeclaration);
fillInitFunction(classDeclaration, context);
}
public void setOrdinal(int ordinal) {
@@ -90,37 +85,6 @@ public final class ClassInitializerTranslator extends AbstractTranslator {
return context;
}
private static void fillInitFunction(KtClassOrObject declaration, TranslationContext context) {
//TODO: it's inconsistent that we have scope for class and function for constructor, currently have problems implementing better way
ClassDescriptor classDescriptor = getClassDescriptor(context.bindingContext(), declaration);
ConstructorDescriptor primaryConstructor = classDescriptor.getUnsubstitutedPrimaryConstructor();
String functionName = AnnotationsUtils.getJsName(classDescriptor);
if (functionName == null) {
Name name = classDescriptor.getName();
if (!name.isSpecial()) {
functionName = name.asString();
}
}
JsFunction ctorFunction;
if (primaryConstructor != null) {
ctorFunction = context.getFunctionObject(primaryConstructor);
}
else {
ctorFunction = new JsFunction(context.scope(), new JsBlock(), "fake constructor for " + functionName);
}
if (functionName != null) {
if (JsReservedIdentifiers.reservedGlobalSymbols.contains(functionName) ||
JsFunctionScope.Companion.getRESERVED_WORDS().contains(functionName)
) {
functionName += "$";
}
ctorFunction.setName(ctorFunction.getScope().declareName(functionName));
}
}
public void generateInitializeMethod(DelegationTranslator delegationTranslator) {
addOuterClassReference(classDescriptor);
ConstructorDescriptor primaryConstructor = classDescriptor.getUnsubstitutedPrimaryConstructor();
@@ -43,7 +43,6 @@ public final class FunctionIntrinsics {
register(LongOperationFIF.INSTANCE);
register(PrimitiveUnaryOperationFIF.INSTANCE);
register(PrimitiveBinaryOperationFIF.INSTANCE);
//register(StringOperationFIF.INSTANCE);
register(ArrayFIF.INSTANCE);
register(TopLevelFIF.INSTANCE);
register(NumberAndCharConversionFIF.INSTANCE);
@@ -93,6 +93,7 @@ object CallableReferenceTranslator {
val packageDescriptor = JsDescriptorUtils.getContainingDeclaration(descriptor)
assert(packageDescriptor is PackageFragmentDescriptor) { "Expected PackageFragmentDescriptor: $packageDescriptor" }
// TODO: revisit
val jsPackageNameRef = context.getQualifiedReference(packageDescriptor)
val jsPropertyName = context.getNameForDescriptor(descriptor)
val jsPropertyNameAsString = context.program().getStringLiteral(jsPropertyName.toString())
@@ -91,20 +91,23 @@ public final class ReferenceTranslator {
if (!shouldTranslateAsFQN(descriptor, context)) {
if (DescriptorUtils.isObject(descriptor) || DescriptorUtils.isEnumEntry(descriptor)) {
if (!context.isFromCurrentModule(descriptor)) {
return getLazyReferenceToObject(descriptor, context);
return getPrototypeIfNecessary(descriptor, getLazyReferenceToObject(descriptor, context));
}
}
return context.getInnerReference(descriptor);
}
JsExpression reference = context.getQualifiedReference(descriptor);
return getPrototypeIfNecessary(descriptor, context.getQualifiedReference(descriptor));
}
@NotNull
private static JsExpression getPrototypeIfNecessary(@NotNull ClassDescriptor descriptor, @NotNull JsExpression reference) {
if (DescriptorUtils.isObject(descriptor) || DescriptorUtils.isEnumEntry(descriptor)) {
JsNameRef getPrototypeRef = JsAstUtils.pureFqn("getPrototypeOf", JsAstUtils.pureFqn("Object", null));
JsInvocation getPrototypeInvocation = new JsInvocation(getPrototypeRef, reference);
MetadataProperties.setSideEffects(getPrototypeInvocation, SideEffectKind.PURE);
reference = JsAstUtils.pureFqn("constructor", getPrototypeInvocation);
}
return reference;
}
@@ -39,8 +39,6 @@ public final class JsAstUtils {
private static final JsPropertyInitializer WRITABLE = new JsPropertyInitializer(pureFqn("writable", null), JsLiteral.TRUE);
private static final JsPropertyInitializer ENUMERABLE = new JsPropertyInitializer(pureFqn("enumerable", null), JsLiteral.TRUE);
public static final String LENDS_JS_DOC_TAG = "lends";
static {
JsNameRef globalObjectReference = new JsNameRef("Object");
DEFINE_PROPERTY.setQualifier(globalObjectReference);
@@ -0,0 +1,25 @@
// MODULE: lib
// FILE: lib.kt
package lib
object O {
operator fun invoke() = "OK"
}
inline fun callO() = O()
// MODULE: main(lib)
// FILE: main.kt
package main
import lib.*
fun box(): String {
val a = O()
if (a != "OK") return "fail: simple: $a"
val b = callO()
if (b != "OK") return "fail: inline: $a"
return "OK"
}
@@ -0,0 +1,70 @@
// MODULE: lib
// FILE: lib.kt
package lib
class A(val x: Int) {
constructor(a: Int, b: Int) : this(a + b)
}
@native class B(x: Int) {
constructor(a: Int, b: Int) : this(0) {}
val x: Int
}
// TODO: may be useful after implementing local classes in inline functions
/*
inline fun foo(p: Int, q: Int, r: Int): Pair<Int, Int> {
class C(val x : Int) {
constructor(a: Int, b: Int) : this(a + b)
}
return Pair(C(p).x, C(q, r).x)
}
*/
inline fun callPrimaryConstructor(x: Int) = A(x).x
inline fun callSecondaryConstructor(x: Int, y: Int) = A(x, y).x
// FILE: lib.js
function B(x, y) {
this.x = x;
if (typeof y !== 'undefined') {
this.x += y;
}
}
// MODULE: main(lib)
// FILE: main.kt
package main
import lib.*
fun box(): String {
val a = A(23).x
if (a != 23) return "fail: primary constructor: $a"
val b = A(40, 2).x
if (b != 42) return "fail: secondary constructor: $b"
val c = B(99).x
if (c != 99) return "fail: native primary constructor: $c"
val d = B(100, 11).x
if (d != 111) return "fail: native secondary constructor: $d"
/*
val (e, f) = foo(123, 320, 1)
if (e != 123) return "fail: local primary constructor: $e"
if (f != 321) return "fail: local secondary constructor: $f"
*/
val g = callPrimaryConstructor(55)
if (g != 55) return "fail: primary constructor from inline function: $g"
val h = callSecondaryConstructor(990, 9)
if (h != 999) return "fail: secondary constructor from inline function: $h"
return "OK"
}
@@ -0,0 +1,25 @@
// MODULE: lib
// FILE: lib.kt
package lib
open class A {
fun foo() = 23
}
// MODULE: main(lib)
// FILE: main.kt
package main
import lib.A
class B : A() {
fun bar() = foo() + 1
}
fun box(): String {
val result = B().bar()
if (result != 24) return "fail: $result"
return "OK"
}
+35
View File
@@ -0,0 +1,35 @@
// MODULE: lib
// FILE: lib.kt
package lib
var log = ""
object O {
init {
log += "O.init;"
}
fun result() = "OK"
}
fun getResult(): String {
log += "before;"
val result = O.result()
log += "after;"
return result
}
// MODULE: main(lib)
// FILE: main.kt
package main
import lib.*
fun box(): String {
val result = getResult()
if (result != "OK") return "fail: unexpected result: $result"
if (log != "before;O.init;after;") return "fail: wrong evaluation order: $log"
return "OK"
}
@@ -0,0 +1,25 @@
// MODULE: lib
// FILE: lib.kt
package lib
object O {
val result = "OK"
inline fun foo(): String {
val o = object {
fun bar() = O
}
return fetch(o.bar())
}
}
fun fetch(o: O) = o.result
// MODULE: main(lib)
// FILE: main.kt
package main
import lib.*
fun box() = O.foo()
@@ -0,0 +1,19 @@
// MODULE: lib
// FILE: lib.kt
package lib
object O
// MODULE: main(lib)
// FILE: main.kt
package main
import lib.*
fun box(): String {
var o: Any = O
if (o !is O) return "fail1"
if (!(o is O)) return "fail2"
return "OK"
}
@@ -0,0 +1,42 @@
// MODULE: lib
// FILE: lib.kt
package lib
class A(val x: Int)
fun A.foo() = 23 + x
inline fun A.baz() = 99 + x
inline fun A.callFoo() = foo()
inline fun A.buzz(): Int {
val o = object {
fun f() = 111 + x
}
return o.f()
}
// MODULE: main(lib)
// FILE: main.kt
package main
import lib.*
fun box(): String {
val a = A(1).foo()
if (a != 24) return "fail: simple function: $a"
val c = A(1).baz()
if (c != 100) return "fail: inline function: $c"
val d = A(1).buzz()
if (d != 112) return "fail: inline function with object expression: $d"
val e = A(2).callFoo()
if (e != 25) return "fail: inline function calling another function: $e"
return "OK"
}
@@ -0,0 +1,49 @@
// MODULE: lib
// FILE: lib.kt
package lib
fun foo() = 23
@native fun bar(): Int = noImpl
inline fun baz() = 99
inline fun callFoo() = foo()
inline fun buzz(): Int {
val o = object {
fun f() = 111
}
return o.f()
}
// FILE: lib.js
function bar() {
return 42;
}
// MODULE: main(lib)
// FILE: main.kt
package main
fun box(): String {
val a = lib.foo()
if (a != 23) return "fail: simple function: $a"
val b = lib.bar()
if (b != 42) return "fail: native function: $b"
val c = lib.baz()
if (c != 99) return "fail: inline function: $c"
val d = lib.buzz()
if (d != 111) return "fail: inline function with object expression: $d"
val e = lib.callFoo()
if (e != 23) return "fail: inline function calling another function: $e"
return "OK"
}
@@ -0,0 +1,36 @@
// MODULE: lib
// FILE: lib.kt
package lib
var foo = 23
var bar: Int = 42
get() = field
set(value) {
field = value
}
@JsName("faz") var baz = 99
// MODULE: main(lib)
// FILE: lib.kt
package main
import lib.*
fun box(): String {
if (foo != 23) return "fail: simple property initial value: $foo"
foo = 24
if (foo != 24) return "fail: simple property new value: $foo"
if (bar != 42) return "fail: property with accessor initial value: $bar"
bar = 43
if (bar != 43) return "fail: property with accessor new value: $bar"
if (baz != 99) return "fail: renamed property initial value: $baz"
baz = 100
if (baz != 100) return "fail: renamed property new value: $baz"
return "OK"
}
@@ -0,0 +1,45 @@
// MODULE: lib
// FILE: lib.kt
package lib
val foo = 23
val boo: Int
get() = 42
@native val bar: Int = noImpl
@native val far: Int
get() = noImpl
// TODO: annotations like this are not serialized properly. Uncomment after KT-14529 gets fixed
/*
val fuzz: Int
@JsName("getBuzz") get() = 55
*/
inline fun fetchFoo() = foo
@JsName("fee") val tee = 2525
// FILE: lib.js
var bar = 99
var far = 111
// MODULE: main(lib)
// FILE: lib.kt
package main
import lib.*
fun box(): String {
if (foo != 23) return "fail: simple property: $foo"
if (boo != 42) return "fail: property with accessor: $boo"
if (bar != 99) return "fail: native property: $bar"
if (far != 111) return "fail: native property with accessor: $far"
//if (fuzz != 55) return "fail: property with JsName on accessor: $fuzz"
if (tee != 2525) return "fail: native property with JsName: $tee"
return "OK"
}