JS: refactor flat declaration generator. Add more tests on inter-module dependencies
This commit is contained in:
@@ -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)
|
||||
|
||||
-1
@@ -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
|
||||
|
||||
-3
@@ -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)
|
||||
|
||||
+1
-1
@@ -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)
|
||||
|
||||
+16
-5
@@ -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")
|
||||
|
||||
+5
-22
@@ -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) {
|
||||
|
||||
+9
-5
@@ -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) {
|
||||
|
||||
+1
-1
@@ -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())
|
||||
|
||||
|
||||
+1
-1
@@ -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();
|
||||
|
||||
-36
@@ -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();
|
||||
|
||||
-1
@@ -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);
|
||||
|
||||
+1
@@ -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())
|
||||
|
||||
+6
-3
@@ -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"
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
Reference in New Issue
Block a user