This commit is contained in:
pTalanov
2012-06-05 18:35:25 +04:00
parent d4d300d0e9
commit 104061b7f8
14 changed files with 112 additions and 106 deletions
@@ -26,7 +26,6 @@ import org.jetbrains.k2js.test.rhino.RhinoResultChecker;
import org.jetbrains.k2js.test.utils.TranslationUtils;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
@@ -89,8 +88,8 @@ public abstract class BasicTest extends TestWithEnvironment {
assert success;
}
protected List<String> additionalJSFiles(EcmaVersion ecmaVersion) {
List<String> list = new ArrayList<String>(2);
protected List<String> additionalJSFiles(@NotNull EcmaVersion ecmaVersion) {
List<String> list = Lists.newArrayList();
list.add(ecmaVersion == EcmaVersion.v5 ? KOTLIN_JS_LIB_ECMA_5 : KOTLIN_JS_LIB_ECMA_3);
list.add(KOTLIN_JS_LIB);
return list;
@@ -78,7 +78,7 @@ public abstract class SingleFileTranslationTest extends BasicTest {
protected void checkOutput(@NotNull String kotlinFilename,
@NotNull String expectedResult,
@NotNull EnumSet<EcmaVersion> ecmaVersions,
@NotNull Iterable<EcmaVersion> ecmaVersions,
String... args) throws Exception {
generateJavaScriptFiles(kotlinFilename, MainCallParameters.mainWithArguments(Lists.newArrayList(args)), ecmaVersions);
runRhinoTests(kotlinFilename, ecmaVersions, new RhinoSystemOutputChecker(expectedResult));
@@ -18,7 +18,6 @@ package org.jetbrains.k2js.test.semantics;
import junit.framework.Test;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.k2js.config.EcmaVersion;
import org.jetbrains.k2js.test.BasicTest;
import org.jetbrains.k2js.test.SingleFileTranslationTest;
import org.jetbrains.k2js.translate.context.Namer;
@@ -37,7 +36,7 @@ public final class ExamplesTest extends SingleFileTranslationTest {
@Override
public void runTest() throws Exception {
runFunctionOutputTest(EcmaVersion.all(), filename, Namer.getRootNamespaceName(), "box", "OK");
runFunctionOutputTest(filename, Namer.getRootNamespaceName(), "box", "OK");
}
public static Test suite() throws Exception {
@@ -37,7 +37,7 @@ public final class NativeInteropTest extends SingleFileTranslationTest {
}
@Override
protected List<String> additionalJSFiles(EcmaVersion ecmaVersion) {
protected List<String> additionalJSFiles(@NotNull EcmaVersion ecmaVersion) {
List<String> result = Lists.newArrayList(super.additionalJSFiles(ecmaVersion));
result.addAll(JsTestUtils.getAllFilesInDir(pathToTestFiles() + NATIVE));
return result;
@@ -24,7 +24,6 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
/**
@@ -36,22 +35,7 @@ public final class JsTestUtils {
}
@NotNull
public static EnumSet<EcmaVersion> failsOn(EcmaVersion... versions) {
EnumSet<EcmaVersion> result = EcmaVersion.all();
for (EcmaVersion version : versions) {
boolean success = result.remove(version);
assert success;
}
return result;
}
@NotNull
public static EnumSet<EcmaVersion> failsOnEcmaV5() {
return failsOn(EcmaVersion.v5);
}
@NotNull
public static String convertFileNameToDotJsFile(@NotNull String filename, EcmaVersion ecmaVersion) {
public static String convertFileNameToDotJsFile(@NotNull String filename, @NotNull EcmaVersion ecmaVersion) {
String postFix = "_" + ecmaVersion.toString() + ".js";
int index = filename.lastIndexOf('.');
if (index < 0) {
@@ -201,7 +201,7 @@ public final class StaticContext {
return null;
}
boolean isGetter = descriptor instanceof PropertyGetterDescriptor;
final PropertyAccessorDescriptor accessorDescriptor = (PropertyAccessorDescriptor) descriptor;
PropertyAccessorDescriptor accessorDescriptor = (PropertyAccessorDescriptor) descriptor;
String propertyName = accessorDescriptor.getCorrespondingProperty().getName().getName();
String accessorName = Namer.getNameForAccessor(propertyName, isGetter, !accessorDescriptor.getReceiverParameter().exists() && isEcma5());
NamingScope enclosingScope = getEnclosingScope(descriptor);
@@ -16,6 +16,7 @@
package org.jetbrains.k2js.translate.declaration;
import com.google.dart.compiler.backend.js.ast.JsExpression;
import com.google.dart.compiler.backend.js.ast.JsPropertyInitializer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
@@ -32,9 +33,7 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static org.jetbrains.k2js.translate.utils.BindingUtils.getDeclarationsForNamespace;
import static org.jetbrains.k2js.translate.utils.BindingUtils.getFunctionDescriptor;
import static org.jetbrains.k2js.translate.utils.BindingUtils.getPropertyDescriptorForObjectDeclaration;
import static org.jetbrains.k2js.translate.utils.BindingUtils.*;
/**
* @author Pavel Talanov
@@ -70,12 +69,14 @@ public final class DeclarationBodyVisitor extends TranslatorVisitor<List<JsPrope
@NotNull
public List<JsPropertyInitializer> visitNamedFunction(@NotNull JetNamedFunction expression,
@NotNull TranslationContext context) {
JsPropertyInitializer o = Translation.functionTranslator(expression, context).translateAsMethod();
JsPropertyInitializer methodAsPropertyInitializer = Translation.functionTranslator(expression, context).translateAsMethod();
if (context.isEcma5()) {
final FunctionDescriptor descriptor = getFunctionDescriptor(context.bindingContext(), expression);
o.setValueExpr(JsAstUtils.createPropertyDataDescriptor(descriptor.getModality().isOverridable(), o.getValueExpr(), context));
boolean overridable = descriptor.getModality().isOverridable();
JsExpression methodBodyExpression = methodAsPropertyInitializer.getValueExpr();
methodAsPropertyInitializer.setValueExpr(JsAstUtils.createPropertyDataDescriptor(overridable, methodBodyExpression, context));
}
return Collections.singletonList(o);
return Collections.singletonList(methodAsPropertyInitializer);
}
@Override
@@ -71,22 +71,36 @@ public final class NamespaceTranslator extends AbstractTranslator {
@NotNull
private JsInvocation getNamespaceDeclaration() {
JsInvocation namespaceDeclaration = namespaceCreateMethodInvocation();
addNamespaceInitalizersAndProperties(namespaceDeclaration);
namespaceDeclaration.getArguments().add(getClassesAndNestedNamespaces());
return namespaceDeclaration;
}
private void addNamespaceInitalizersAndProperties(@NotNull JsInvocation namespaceDeclaration) {
JsFunction initializer = Translation.generateNamespaceInitializerMethod(descriptor, context());
List<JsPropertyInitializer> properties = new DeclarationBodyVisitor().traverseNamespace(descriptor, context());
if (context().isEcma5()) {
namespaceDeclaration.getArguments().add(initializer);
namespaceDeclaration.getArguments().add(newObjectLiteral(properties));
addEcma5InitializersAndProperties(namespaceDeclaration, initializer, properties);
}
else {
List<JsPropertyInitializer> propertyList = new ArrayList<JsPropertyInitializer>();
propertyList.add(InitializerUtils.generateInitializeMethod(initializer));
propertyList.addAll(properties);
namespaceDeclaration.getArguments().add(newObjectLiteral(propertyList));
addEcma3InitializersAndProperties(namespaceDeclaration, initializer, properties);
}
}
namespaceDeclaration.getArguments().add(getClassesAndNestedNamespaces());
return namespaceDeclaration;
private static void addEcma3InitializersAndProperties(@NotNull JsInvocation namespaceDeclaration,
@NotNull JsFunction initializer,
@NotNull List<JsPropertyInitializer> properties) {
List<JsPropertyInitializer> propertyList = new ArrayList<JsPropertyInitializer>();
propertyList.add(InitializerUtils.generateInitializeMethod(initializer));
propertyList.addAll(properties);
namespaceDeclaration.getArguments().add(newObjectLiteral(propertyList));
}
private static void addEcma5InitializersAndProperties(@NotNull JsInvocation namespaceDeclaration,
@NotNull JsFunction initializer,
@NotNull List<JsPropertyInitializer> properties) {
namespaceDeclaration.getArguments().add(initializer);
namespaceDeclaration.getArguments().add(newObjectLiteral(properties));
}
@NotNull
@@ -50,13 +50,7 @@ import static org.jetbrains.k2js.translate.utils.TranslationUtils.backingFieldRe
public final class PropertyTranslator extends AbstractTranslator {
@NotNull
private final PropertyDescriptor property;
@NotNull
private final List<JsPropertyInitializer> accessors = new ArrayList<JsPropertyInitializer>();
@Nullable
private final JetProperty declaration;
static public List<JsPropertyInitializer> translateAccessors(@NotNull PropertyDescriptor descriptor,
public static List<JsPropertyInitializer> translateAccessors(@NotNull PropertyDescriptor descriptor,
@NotNull TranslationContext context) {
if (context.isEcma5() && !JsDescriptorUtils.isAsPrivate(descriptor)) {
return Collections.emptyList();
@@ -64,15 +58,30 @@ public final class PropertyTranslator extends AbstractTranslator {
PropertyTranslator propertyTranslator = new PropertyTranslator(descriptor, context);
List<JsPropertyInitializer> propertyInitializers = propertyTranslator.translate();
if (context.isEcma5() && !descriptor.getReceiverParameter().exists()) {
JsObjectLiteral objectLiteral = new JsObjectLiteral();
objectLiteral.getPropertyInitializers().addAll(propertyInitializers);
return Collections.singletonList(
new JsPropertyInitializer(context.program().getStringLiteral(descriptor.getName().getName()), objectLiteral));
if (context.isEcma5() && !JsDescriptorUtils.isExtension(descriptor)) {
return translateAsEcma5Accessors(descriptor, propertyInitializers, context);
}
return propertyInitializers;
}
@NotNull
private static List<JsPropertyInitializer> translateAsEcma5Accessors(@NotNull PropertyDescriptor descriptor,
@NotNull List<JsPropertyInitializer> propertyInitializers,
@NotNull TranslationContext context) {
JsObjectLiteral objectLiteral = new JsObjectLiteral();
objectLiteral.getPropertyInitializers().addAll(propertyInitializers);
JsStringLiteral propertyNameLiteral = context.program().getStringLiteral(descriptor.getName().getName());
return Collections.singletonList(new JsPropertyInitializer(propertyNameLiteral, objectLiteral));
}
@NotNull
private final PropertyDescriptor property;
@NotNull
private final List<JsPropertyInitializer> accessors = new ArrayList<JsPropertyInitializer>();
@Nullable
private final JetProperty declaration;
private PropertyTranslator(@NotNull PropertyDescriptor property, @NotNull TranslationContext context) {
super(context);
this.property = property;
@@ -163,7 +172,9 @@ public final class PropertyTranslator extends AbstractTranslator {
return result;
}
private JsPropertyInitializer generateDefaultAccessor(PropertyAccessorDescriptor accessorDescriptor, JsFunction function) {
@NotNull
private JsPropertyInitializer generateDefaultAccessor(@NotNull PropertyAccessorDescriptor accessorDescriptor,
@NotNull JsFunction function) {
if (context().isEcma5()) {
return TranslationUtils.translateFunctionAsEcma5PropertyDescriptor(function, accessorDescriptor, context());
}
@@ -226,7 +226,7 @@ public final class FunctionTranslator extends AbstractTranslator {
}
private boolean isExtensionFunction() {
return JsDescriptorUtils.isExtensionFunction(descriptor) && !isLiteral();
return JsDescriptorUtils.isExtension(descriptor) && !isLiteral();
}
private boolean isLiteral() {
@@ -135,17 +135,22 @@ public final class CallTranslator extends AbstractTranslator {
@NotNull
private JsExpression constructorCall() {
JsExpression constructorReference = translateAsFunctionWithNoThisObject(descriptor);
JsExpression constructorCall;
if (context().isEcma5() && !AnnotationsUtils.isNativeObject(resolvedCall.getCandidateDescriptor())) {
constructorCall = AstUtil.newInvocation(constructorReference);
}
else {
constructorCall = new JsNew(constructorReference);
}
JsExpression constructorCall = createConstructorCallExpression(constructorReference);
assert constructorCall instanceof HasArguments : "Constructor call should be expression with arguments.";
((HasArguments) constructorCall).getArguments().addAll(arguments);
return constructorCall;
}
@NotNull
private JsExpression createConstructorCallExpression(@NotNull JsExpression constructorReference) {
if (context().isEcma5() && !AnnotationsUtils.isNativeObject(resolvedCall.getCandidateDescriptor())) {
return AstUtil.newInvocation(constructorReference);
}
else {
return new JsNew(constructorReference);
}
}
@NotNull
private JsExpression translateAsFunctionWithNoThisObject(@NotNull DeclarationDescriptor descriptor) {
return ReferenceTranslator.translateAsFQReference(descriptor, context());
@@ -306,7 +306,7 @@ public final class JsAstUtils {
}
@NotNull
public static JsInvocation encloseFunction(JsFunction function) {
public static JsInvocation encloseFunction(@NotNull JsFunction function) {
JsInvocation blockFunctionInvocation = new JsInvocation();
blockFunctionInvocation.setQualifier(EMPTY_REF);
blockFunctionInvocation.getArguments().add(function);
@@ -314,7 +314,7 @@ public final class JsAstUtils {
}
@NotNull
public static JsFunction createPackage(List<JsStatement> to, JsScope scope) {
public static JsFunction createPackage(@NotNull List<JsStatement> to, @NotNull JsScope scope) {
JsFunction packageBlockFunction = createFunctionWithEmptyBody(scope);
JsInvocation packageBlockFunctionInvocation = encloseFunction(packageBlockFunction);
@@ -135,7 +135,7 @@ public final class JsDescriptorUtils {
return containing;
}
public static boolean isExtensionFunction(@NotNull CallableDescriptor functionDescriptor) {
public static boolean isExtension(@NotNull CallableDescriptor functionDescriptor) {
return (functionDescriptor.getReceiverParameter().exists());
}
@@ -269,19 +269,6 @@ public final class JsDescriptorUtils {
return result;
}
@Nullable
public static ClassDescriptor getClassDescriptorForMethod(@NotNull SimpleFunctionDescriptor functionDescriptor) {
if (!functionDescriptor.getExpectedThisObject().exists()) {
return null;
}
ClassifierDescriptor descriptor =
functionDescriptor.getExpectedThisObject().getType().getConstructor().getDeclarationDescriptor();
if (descriptor instanceof ClassDescriptor) {
return (ClassDescriptor)descriptor.getOriginal();
}
return null;
}
private static boolean isDefaultAccessor(@Nullable PropertyAccessorDescriptor accessorDescriptor) {
return accessorDescriptor == null || accessorDescriptor.isDefault();
}
@@ -49,37 +49,43 @@ public final class TranslationUtils {
public static JsPropertyInitializer translateFunctionAsEcma5PropertyDescriptor(@NotNull JsFunction function,
@NotNull FunctionDescriptor descriptor,
@NotNull TranslationContext context) {
if (descriptor.getReceiverParameter().exists()) {
JsObjectLiteral meta = new JsObjectLiteral();
meta.getPropertyInitializers().add(new JsPropertyInitializer(context.program().getStringLiteral("value"), function));
if (descriptor.getModality().isOverridable()) {
meta.getPropertyInitializers().add(context.namer().writablePropertyDescriptorField());
}
return new JsPropertyInitializer(context.getNameForDescriptor(descriptor).makeRef(), meta);
if (JsDescriptorUtils.isExtension(descriptor)) {
return translateExtensionFunctionAsEcma5PropertyDescriptor(function, descriptor, context);
}
else {
return new JsPropertyInitializer(
context.program().getStringLiteral(descriptor instanceof PropertyGetterDescriptor ? "get" : "set"), function);
JsStringLiteral getOrSet = context.program().getStringLiteral(descriptor instanceof PropertyGetterDescriptor ? "get" : "set");
return new JsPropertyInitializer(getOrSet, function);
}
}
@NotNull
private static JsPropertyInitializer translateExtensionFunctionAsEcma5PropertyDescriptor(@NotNull JsFunction function,
@NotNull FunctionDescriptor descriptor, @NotNull TranslationContext context) {
JsObjectLiteral meta = new JsObjectLiteral();
meta.getPropertyInitializers().add(new JsPropertyInitializer(context.program().getStringLiteral("value"), function));
if (descriptor.getModality().isOverridable()) {
meta.getPropertyInitializers().add(context.namer().writablePropertyDescriptorField());
}
return new JsPropertyInitializer(context.getNameForDescriptor(descriptor).makeRef(), meta);
}
@NotNull
public static JsBinaryOperation notNullCheck(@NotNull TranslationContext context,
@NotNull JsExpression expressionToCheck) {
@NotNull JsExpression expressionToCheck) {
JsNullLiteral nullLiteral = context.program().getNullLiteral();
return inequality(expressionToCheck, nullLiteral);
}
@NotNull
public static JsBinaryOperation isNullCheck(@NotNull TranslationContext context,
@NotNull JsExpression expressionToCheck) {
@NotNull JsExpression expressionToCheck) {
JsNullLiteral nullLiteral = context.program().getNullLiteral();
return equality(expressionToCheck, nullLiteral);
}
@NotNull
public static List<JsExpression> translateArgumentList(@NotNull TranslationContext context,
@NotNull List<? extends ValueArgument> jetArguments) {
@NotNull List<? extends ValueArgument> jetArguments) {
List<JsExpression> jsArguments = new ArrayList<JsExpression>();
for (ValueArgument argument : jetArguments) {
jsArguments.add(translateArgument(context, argument));
@@ -96,22 +102,22 @@ public final class TranslationUtils {
@NotNull
public static JsNameRef backingFieldReference(@NotNull TranslationContext context,
@NotNull PropertyDescriptor descriptor) {
@NotNull PropertyDescriptor descriptor) {
JsName backingFieldName = context.getNameForDescriptor(descriptor);
return qualified(backingFieldName, new JsThisRef());
}
@NotNull
public static JsExpression assignmentToBackingField(@NotNull TranslationContext context,
@NotNull PropertyDescriptor descriptor,
@NotNull JsExpression assignTo) {
@NotNull PropertyDescriptor descriptor,
@NotNull JsExpression assignTo) {
JsNameRef backingFieldReference = backingFieldReference(context, descriptor);
return newAssignment(backingFieldReference, assignTo);
}
@Nullable
public static JsExpression translateInitializerForProperty(@NotNull JetProperty declaration,
@NotNull TranslationContext context) {
@NotNull TranslationContext context) {
JsExpression jsInitExpression = null;
JetExpression initializer = declaration.getInitializer();
if (initializer != null) {
@@ -122,7 +128,7 @@ public final class TranslationUtils {
@NotNull
public static JsNameRef getQualifiedReference(@NotNull TranslationContext context,
@NotNull DeclarationDescriptor descriptor) {
@NotNull DeclarationDescriptor descriptor) {
JsName name = context.getNameForDescriptor(descriptor);
JsNameRef reference = name.makeRef();
JsNameRef qualifier = context.getQualifierForDescriptor(descriptor);
@@ -135,7 +141,7 @@ public final class TranslationUtils {
//TODO: refactor
@NotNull
public static JsExpression getThisObject(@NotNull TranslationContext context,
@NotNull DeclarationDescriptor correspondingDeclaration) {
@NotNull DeclarationDescriptor correspondingDeclaration) {
if (correspondingDeclaration instanceof ClassDescriptor) {
JsName alias = context.aliasingContext().getAliasForThis(correspondingDeclaration);
if (alias != null) {
@@ -144,7 +150,7 @@ public final class TranslationUtils {
}
if (correspondingDeclaration instanceof CallableDescriptor) {
DeclarationDescriptor receiverDescriptor =
getExpectedReceiverDescriptor((CallableDescriptor)correspondingDeclaration);
getExpectedReceiverDescriptor((CallableDescriptor) correspondingDeclaration);
assert receiverDescriptor != null;
JsName alias = context.aliasingContext().getAliasForThis(receiverDescriptor);
if (alias != null) {
@@ -156,7 +162,7 @@ public final class TranslationUtils {
@NotNull
public static List<JsExpression> translateExpressionList(@NotNull TranslationContext context,
@NotNull List<JetExpression> expressions) {
@NotNull List<JetExpression> expressions) {
List<JsExpression> result = new ArrayList<JsExpression>();
for (JetExpression expression : expressions) {
result.add(Translation.translateAsExpression(expression, context));
@@ -166,29 +172,29 @@ public final class TranslationUtils {
@NotNull
public static JsExpression translateBaseExpression(@NotNull TranslationContext context,
@NotNull JetUnaryExpression expression) {
@NotNull JetUnaryExpression expression) {
JetExpression baseExpression = PsiUtils.getBaseExpression(expression);
return Translation.translateAsExpression(baseExpression, context);
}
@NotNull
public static JsExpression translateLeftExpression(@NotNull TranslationContext context,
@NotNull JetBinaryExpression expression) {
@NotNull JetBinaryExpression expression) {
return Translation.translateAsExpression(expression.getLeft(), context);
}
@NotNull
public static JsExpression translateRightExpression(@NotNull TranslationContext context,
@NotNull JetBinaryExpression expression) {
@NotNull JetBinaryExpression expression) {
JetExpression rightExpression = expression.getRight();
assert rightExpression != null : "Binary expression should have a right expression";
return Translation.translateAsExpression(rightExpression, context);
}
public static boolean isIntrinsicOperation(@NotNull TranslationContext context,
@NotNull JetOperationExpression expression) {
@NotNull JetOperationExpression expression) {
FunctionDescriptor operationDescriptor =
BindingUtils.getFunctionDescriptorForOperationExpression(context.bindingContext(), expression);
BindingUtils.getFunctionDescriptorForOperationExpression(context.bindingContext(), expression);
if (operationDescriptor == null) return true;
if (context.intrinsics().isIntrinsic(operationDescriptor)) return true;
@@ -198,9 +204,9 @@ public final class TranslationUtils {
@NotNull
public static JsNameRef getMethodReferenceForOverloadedOperation(@NotNull TranslationContext context,
@NotNull JetOperationExpression expression) {
@NotNull JetOperationExpression expression) {
FunctionDescriptor overloadedOperationDescriptor = getFunctionDescriptorForOperationExpression
(context.bindingContext(), expression);
(context.bindingContext(), expression);
assert overloadedOperationDescriptor != null;
JsNameRef overloadedOperationReference = context.getNameForDescriptor(overloadedOperationDescriptor).makeRef();
assert overloadedOperationReference != null;
@@ -214,8 +220,8 @@ public final class TranslationUtils {
@NotNull
public static JsExpression applyIntrinsicToBinaryExpression(@NotNull TranslationContext context,
@NotNull Intrinsic intrinsic,
@NotNull JetBinaryExpression binaryExpression) {
@NotNull Intrinsic intrinsic,
@NotNull JetBinaryExpression binaryExpression) {
JsExpression left = translateLeftExpression(context, binaryExpression);
JsExpression right = translateRightExpression(context, binaryExpression);
return intrinsic.apply(left, Arrays.asList(right), context);
@@ -223,7 +229,7 @@ public final class TranslationUtils {
@Nullable
public static JsExpression resolveThisObjectForResolvedCall(@NotNull ResolvedCall<?> call,
@NotNull TranslationContext context) {
@NotNull TranslationContext context) {
ReceiverDescriptor thisObject = call.getThisObject();
if (!thisObject.exists()) {
return null;