diff --git a/.idea/workspace.xml b/.idea/workspace.xml
index 0c6727619f0..279bf7ef194 100644
--- a/.idea/workspace.xml
+++ b/.idea/workspace.xml
@@ -6,25 +6,59 @@
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
-
+
+
+
-
-
+
+
+
@@ -62,19 +96,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -115,31 +136,31 @@
-
+
-
-
+
+
-
+
-
-
+
+
-
+
-
-
+
+
-
+
@@ -147,46 +168,55 @@
-
-
+
+
-
+
-
-
+
+
-
+
-
-
+
+
-
+
-
-
+
+
-
+
-
-
+
+
-
+
+
+
+
+
+
+
+
+
+
@@ -194,20 +224,13 @@
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
@@ -216,77 +239,19 @@
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
@@ -297,16 +262,70 @@
-
+
-
-
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -328,22 +347,22 @@
@@ -414,11 +433,127 @@
-
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -480,50 +615,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -608,65 +699,21 @@
+
+
+
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
@@ -679,7 +726,7 @@
-
+
@@ -708,13 +755,57 @@
-
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -727,7 +818,7 @@
-
+
@@ -809,11 +900,11 @@
-
-
-
-
-
+
+
+
+
+
localhost
@@ -855,7 +946,7 @@
-
+
@@ -863,9 +954,9 @@
-
+
-
+
@@ -903,7 +994,7 @@
-
+
@@ -927,6 +1018,7 @@
+
@@ -936,16 +1028,9 @@
-
+
-
-
-
-
-
-
-
-
+
@@ -954,108 +1039,111 @@
-
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
-
-
+
-
+
-
+
-
+
-
-
-
-
-
-
-
-
-
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
+
-
+
+
+
+
+
+
+
+
diff --git a/translator/src/org/jetbrains/k2js/declarations/ExtractionVisitor.java b/translator/src/org/jetbrains/k2js/declarations/ExtractionVisitor.java
index 1fbea825abb..4c6fce68b65 100644
--- a/translator/src/org/jetbrains/k2js/declarations/ExtractionVisitor.java
+++ b/translator/src/org/jetbrains/k2js/declarations/ExtractionVisitor.java
@@ -1,7 +1,10 @@
package org.jetbrains.k2js.declarations;
+import com.google.dart.compiler.backend.js.ast.JsName;
import com.google.dart.compiler.backend.js.ast.JsScope;
+import com.intellij.util.xml.PropertyAccessor;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.k2js.translate.Namer;
@@ -41,32 +44,25 @@ public final class ExtractionVisitor extends DeclarationDescriptorVisitor
+ D getDescriptorForExpression(@NotNull BindingContext context, @NotNull E expression, Class descriptorClass) {
+ DeclarationDescriptor descriptor = context.get(BindingContext.DECLARATION_TO_DESCRIPTOR, expression);
+ assert descriptor != null;
+ assert descriptorClass.isInstance(descriptor)
+ : expression.toString() + " expected to have of type" + descriptorClass.toString();
+ return (D)descriptor;
+ }
+
@NotNull
static public ClassDescriptor getClassDescriptor(@NotNull BindingContext context, @NotNull JetClass declaration) {
- DeclarationDescriptor descriptor
- = context.get(BindingContext.DECLARATION_TO_DESCRIPTOR, declaration);
- assert descriptor instanceof ClassDescriptor : "Class should have a descriptor" +
- " of type ClassDescriptor";
- return (ClassDescriptor)descriptor;
+ return getDescriptorForExpression(context, declaration, ClassDescriptor.class);
}
@NotNull
static public NamespaceDescriptor getNamespaceDescriptor(@NotNull BindingContext context,
@NotNull JetNamespace declaration) {
- DeclarationDescriptor descriptor
- = context.get(BindingContext.DECLARATION_TO_DESCRIPTOR, declaration);
- assert descriptor instanceof NamespaceDescriptor : "Namespace should have a descriptor" +
- " of type NamespaceDescriptor";
- return (NamespaceDescriptor)descriptor;
+ return getDescriptorForExpression(context, declaration, NamespaceDescriptor.class);
}
@NotNull
static public FunctionDescriptor getFunctionDescriptor(@NotNull BindingContext context,
@NotNull JetNamedFunction declaration) {
- DeclarationDescriptor descriptor =
- context.get(BindingContext.DECLARATION_TO_DESCRIPTOR, declaration);
- assert descriptor instanceof FunctionDescriptor : "JetNamedFunction should have" +
- " descriptor of type FunctionDescriptor.";
- return (FunctionDescriptor)descriptor;
+ return getDescriptorForExpression(context, declaration, FunctionDescriptor.class);
+ }
+
+ @NotNull
+ static public PropertyAccessorDescriptor getPropertyAccessorDescriptor(@NotNull BindingContext context,
+ @NotNull JetPropertyAccessor declaration) {
+ return getDescriptorForExpression(context, declaration, PropertyAccessorDescriptor.class);
+ }
+
+ @NotNull
+ static public PropertyDescriptor getPropertyDescriptor(@NotNull BindingContext context,
+ @NotNull JetProperty declaration) {
+ return getDescriptorForExpression(context, declaration, PropertyDescriptor.class);
+ }
+
+ @NotNull
+ static public String getPropertyNameForPropertyAccessor(@NotNull BindingContext context,
+ @NotNull JetPropertyAccessor accessor) {
+ PropertyAccessorDescriptor descriptor = getPropertyAccessorDescriptor(context, accessor);
+ return descriptor.getCorrespondingProperty().getName();
+ }
+
+ @NotNull
+ static public PropertySetterDescriptor getPropertySetterDescriptorForProperty(@NotNull BindingContext context,
+ @NotNull JetProperty property) {
+ PropertySetterDescriptor result = getPropertyDescriptor(context, property).getSetter();
+ assert result != null : "Property should have a setter descriptor";
+ return result;
+ }
+
+ @NotNull
+ static public PropertyGetterDescriptor getPropertyGetterDescriptorForProperty(@NotNull BindingContext context,
+ @NotNull JetProperty property) {
+ PropertyGetterDescriptor result = getPropertyDescriptor(context, property).getGetter();
+ assert result != null : "Property should have a getter descriptor";
+ return result;
+ }
+
+ @NotNull
+ static public List getSuperclassDescriptors(@NotNull BindingContext context,
+ @NotNull JetClass classDeclaration) {
+ ClassDescriptor classDescriptor = getClassDescriptor(context, classDeclaration);
+ Collection extends JetType> superclassTypes = classDescriptor.getTypeConstructor().getSupertypes();
+ List superClassDescriptors = new ArrayList();
+ for (JetType type : superclassTypes) {
+ DeclarationDescriptor superClassDescriptor =
+ type.getConstructor().getDeclarationDescriptor();
+ assert superClassDescriptor instanceof ClassDescriptor
+ : "Superclass descriptor of a type should be of type ClassDescriptor";
+ if (isNotAny(superClassDescriptor)) {
+ superClassDescriptors.add((ClassDescriptor)superClassDescriptor);
+ }
+ }
+ return superClassDescriptors;
+ }
+
+ //TODO better implementation?
+ private static boolean isNotAny(@NotNull DeclarationDescriptor superClassDescriptor) {
+ return superClassDescriptor.getName() != "Any";
}
}
diff --git a/translator/src/org/jetbrains/k2js/translate/ClassBodyVisitor.java b/translator/src/org/jetbrains/k2js/translate/ClassBodyVisitor.java
index 55a710b77ff..4f7fa13970e 100644
--- a/translator/src/org/jetbrains/k2js/translate/ClassBodyVisitor.java
+++ b/translator/src/org/jetbrains/k2js/translate/ClassBodyVisitor.java
@@ -2,8 +2,9 @@ package org.jetbrains.k2js.translate;
import com.google.dart.compiler.backend.js.ast.*;
import com.google.dart.compiler.util.AstUtil;
-import com.intellij.util.Function;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jet.lang.descriptors.PropertyGetterDescriptor;
+import org.jetbrains.jet.lang.descriptors.PropertySetterDescriptor;
import org.jetbrains.jet.lang.psi.*;
import java.util.ArrayList;
@@ -66,37 +67,31 @@ public final class ClassBodyVisitor extends TranslatorVisitor(), AstUtil.convertToBlock(returnExpression));
}
- //TODO rewrite
- @NotNull
- private JsName declareOrGetBackingFieldName(@NotNull String propertyName, @NotNull TranslationContext context) {
- String backingFieldName = Namer.getBackingFieldNameForProperty(propertyName);
- JsName jsBackingFieldName = context.classScope().findExistingName(backingFieldName);
- if (jsBackingFieldName == null) {
- jsBackingFieldName = context.classScope().declareName(backingFieldName);
- }
- return jsBackingFieldName;
- }
-
@NotNull
private JsPropertyInitializer generateDefaultSetter(@NotNull JetProperty expression,
@NotNull TranslationContext context) {
- JsName setterName = context.classScope().declareName(Namer.getNameForSetter(expression.getName()));
- return AstUtil.newNamedMethod(setterName, generateDefaultSetterFunction(expression, context));
+ PropertySetterDescriptor setterDescriptor =
+ BindingUtils.getPropertySetterDescriptorForProperty(context.bindingContext(), expression);
+ return AstUtil.newNamedMethod(context.getNameForDescriptor(setterDescriptor),
+ generateDefaultSetterFunction(expression, context.newPropertyAccess(setterDescriptor)));
}
@NotNull
@@ -114,7 +109,7 @@ public final class ClassBodyVisitor extends TranslatorVisitor visitPropertyAccessor(@NotNull JetPropertyAccessor expression,
+ @NotNull TranslationContext context) {
+ List methods = new ArrayList();
+ methods.add(generateMethodForAccessor(expression, context));
+ return methods;
+ }
+ @NotNull
+ private JsPropertyInitializer generateMethodForAccessor(@NotNull JetPropertyAccessor expression,
+ @NotNull TranslationContext context) {
+ JsFunction methodBody = translateAccessorBody(expression, context);
+ // we know that custom getters and setters always have their descriptors
+ return AstUtil.newNamedMethod(context.getNameForElement(expression), methodBody);
+ }
+
+ @NotNull
+ private JsFunction translateAccessorBody(@NotNull JetPropertyAccessor expression,
+ @NotNull TranslationContext context) {
+ JsFunction methodBody = JsFunction.getAnonymousFunctionWithScope(context.getScopeForElement(expression));
+ ExpressionTranslator expressionTranslator =
+ new ExpressionTranslator(context.newPropertyAccess(expression));
+ JetExpression bodyExpression = expression.getBodyExpression();
+ assert bodyExpression != null : "Custom accessor should have a body.";
+ JsBlock methodBodyBlock = AstUtil.convertToBlock(expressionTranslator.translate(bodyExpression));
+ methodBody.setBody(methodBodyBlock);
+ return methodBody;
+ }
-// @Override
// @NotNull
-// public List visitPropertyAccessor
-// (JetPropertyAccessor expression, TranslationContext context) {
-// List methods = new ArrayList();
-// JsPropertyInitializer namedMethod = generateMethodForAccessor(expression, context);
-// methods.add(namedMethod);
-// return methods;
+// JsName getNameForGetter(@NotNull String propertyName, @NotNull TranslationContext context) {
+// return getNameForAccessor(propertyName, true, context);
// }
//
-// private JsPropertyInitializer generateMethodForAccessor(JetPropertyAccessor expression, TranslationContext context) {
-// JsFunction methodBody = new JsFunction(context.enclosingScope());
-// ExpressionTranslator expressionTranslator =
-// new ExpressionTranslator(context.newFunction(methodBody));
-// JsBlock methodBodyBlock = AstUtil.convertToBlock(expressionTranslator.translate(expression.getBodyExpression()));
-// methodBody.setBody(methodBodyBlock);
-// //TODO figure out naming pattern
-// return AstUtil.newNamedMethod(Namer.getNameForAccessor("nameForAccessor", expression), methodBody);
+// @NotNull
+// JsName getNameForSetter(@NotNull String propertyName, @NotNull TranslationContext context) {
+// return getNameForAccessor(propertyName, false, context);
+// }
+//
+// @NotNull
+// JsName getNameForAccessor(@NotNull String propertyName, boolean isGetter,
+// @NotNull TranslationContext context) {
+// return context.classScope().findExistingName(Namer.getNameForAccessor(propertyName, isGetter));
// }
diff --git a/translator/src/org/jetbrains/k2js/translate/ClassTranslator.java b/translator/src/org/jetbrains/k2js/translate/ClassTranslator.java
index 2e16e0de72a..3cb1a3cd73b 100644
--- a/translator/src/org/jetbrains/k2js/translate/ClassTranslator.java
+++ b/translator/src/org/jetbrains/k2js/translate/ClassTranslator.java
@@ -2,16 +2,10 @@ package org.jetbrains.k2js.translate;
import com.google.dart.compiler.backend.js.ast.*;
import com.google.dart.compiler.util.AstUtil;
-import org.apache.velocity.runtime.directive.Block;
-import org.eclipse.jdt.core.dom.Initializer;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
-import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.psi.JetClass;
-import org.jetbrains.jet.lang.resolve.BindingContext;
-import org.jetbrains.jet.lang.resolve.DescriptorUtils;
-import org.jetbrains.jet.lang.types.JetType;
-import sun.org.mozilla.javascript.internal.Function;
import java.util.ArrayList;
import java.util.List;
@@ -22,33 +16,51 @@ import java.util.List;
//TODO ClassTranslator needs heavy improvement
public final class ClassTranslator extends AbstractTranslator {
- private final ClassBodyVisitor classBodyVisitor = new ClassBodyVisitor();
+ @NotNull private final ClassBodyVisitor classBodyVisitor = new ClassBodyVisitor();
public ClassTranslator(TranslationContext context) {
super(context);
}
- public JsStatement translateClass(JetClass classDeclaration) {
+ @NotNull
+ public JsStatement translateClass(@NotNull JetClass classDeclaration) {
JsInvocation jsClassDeclaration = new JsInvocation();
jsClassDeclaration.setQualifier(Namer.creationMethodReference());
+ addSuperclassReferences(classDeclaration, jsClassDeclaration);
+ addClassOwnDeclarations(classDeclaration, jsClassDeclaration);
+ JsName jsClassName = translationContext().getNameForElement(classDeclaration);
+ return AstUtil.convertToStatement(
+ AstUtil.newAssignment(translationContext().getNamespaceQualifiedReference(jsClassName), jsClassDeclaration));
+ }
+
+ @NotNull
+ private void addClassOwnDeclarations(@NotNull JetClass classDeclaration,
+ @NotNull JsInvocation jsClassDeclaration) {
JsObjectLiteral jsClassDescription = translateClassDeclarations(classDeclaration);
jsClassDeclaration.getArguments().add(jsClassDescription);
- //getSuperClassName(classDeclaration);
- String className = classDeclaration.getName();
- JsName jsClassName = translationContext().namespaceScope().declareName(className);
- return AstUtil.convertToStatement(AstUtil.newAssignment(
- translationContext().getNamespaceQualifiedReference(jsClassName), jsClassDeclaration));
}
- private void getSuperClassName(JetClass classDeclaration) {
- ClassDescriptor classDescriptor = bindingContext().get(BindingContext.CLASS, classDeclaration);
- JetType superType = classDescriptor.getSuperclassType();
- DeclarationDescriptor descriptor = superType.getConstructor().getDeclarationDescriptor();
- JetClass superClass = (JetClass)bindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, descriptor);
- String superClassName = superClass.getName();
+ private void addSuperclassReferences(@NotNull JetClass classDeclaration,
+ @NotNull JsInvocation jsClassDeclaration) {
+ for (JsNameRef superClassReference : getSuperclassNameReferences(classDeclaration)) {
+ jsClassDeclaration.getArguments().add(superClassReference);
+ }
}
- private JsObjectLiteral translateClassDeclarations(JetClass classDeclaration) {
+ @Nullable
+ private List getSuperclassNameReferences(@NotNull JetClass classDeclaration) {
+ List superclassReferences = new ArrayList();
+ for (ClassDescriptor superClassDescriptor :
+ BindingUtils.getSuperclassDescriptors(translationContext().bindingContext(), classDeclaration)) {
+ //TODO should get a full class name here
+ superclassReferences.add(translationContext().getNamespaceQualifiedReference
+ (translationContext().getNameForDescriptor(superClassDescriptor)));
+ }
+ return superclassReferences;
+ }
+
+ @NotNull
+ private JsObjectLiteral translateClassDeclarations(@NotNull JetClass classDeclaration) {
List propertyList = new ArrayList();
propertyList.add(generateInitializeMethod(classDeclaration));
propertyList.addAll(classDeclaration.accept(classBodyVisitor,
@@ -56,25 +68,18 @@ public final class ClassTranslator extends AbstractTranslator {
return new JsObjectLiteral(propertyList);
}
- private JsPropertyInitializer generateInitializeMethod(JetClass classDeclaration) {
+ @NotNull
+ private JsPropertyInitializer generateInitializeMethod(@NotNull JetClass classDeclaration) {
JsPropertyInitializer initializer = new JsPropertyInitializer();
initializer.setLabelExpr(program().getStringLiteral(Namer.INITIALIZE_METHOD_NAME));
initializer.setValueExpr(generateInitializeMethodBody(classDeclaration));
return initializer;
}
- // Note: we explicitly create JsFunction here because initialize function itself has no descriptor and
- // is never referenced explicitly.
@NotNull
private JsFunction generateInitializeMethodBody(@NotNull JetClass classDeclaration) {
- InitializerVisitor initializerVisitor = new InitializerVisitor();
- List initializerStatements = classDeclaration.accept(initializerVisitor,
+ InitializerVisitor initializerVisitor = new InitializerVisitor(classDeclaration,
translationContext().newClass(classDeclaration));
- JsBlock block = new JsBlock();
- block.setStatements(initializerStatements);
- return AstUtil.newFunction(translationContext().enclosingScope(), null, null, block);
+ return initializerVisitor.generateInitializeMethodBody();
}
-
-
-
}
diff --git a/translator/src/org/jetbrains/k2js/translate/ExpressionVisitor.java b/translator/src/org/jetbrains/k2js/translate/ExpressionVisitor.java
index 7259463428d..758f82c2103 100644
--- a/translator/src/org/jetbrains/k2js/translate/ExpressionVisitor.java
+++ b/translator/src/org/jetbrains/k2js/translate/ExpressionVisitor.java
@@ -5,15 +5,19 @@ import com.google.dart.compiler.backend.js.ast.JsExpression;
import com.google.dart.compiler.backend.js.ast.*;
import com.google.dart.compiler.backend.js.ast.JsReturn;
import com.google.dart.compiler.util.AstUtil;
+import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.descriptors.ConstructorDescriptor;
+import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.calls.ResolvedCall;
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
+import org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils;
import org.jetbrains.jet.lexer.JetToken;
+import org.jetbrains.jet.lexer.JetTokens;
import java.util.ArrayList;
import java.util.Arrays;
@@ -126,19 +130,21 @@ public final class ExpressionVisitor extends TranslatorVisitor {
return new JsBinaryOperation(OperationTranslator.getBinaryOperator(jetOperationToken), left, right);
}
- //TODO correct look-up logic
+ //TODO clearify code
@Override
@NotNull
public JsNode visitSimpleNameExpression(JetSimpleNameExpression expression, TranslationContext context) {
String referencedName = expression.getReferencedName();
JsName jsName = context.enclosingScope().findExistingName(referencedName);
- if (jsName == null) {
- throw new AssertionError("Unindentified name " + expression.getReferencedName());
- }
+ assert jsName != null : "Undeclared name: " + referencedName;
if (context.namespaceScope().ownsName(jsName)) {
return context.getNamespaceQualifiedReference(jsName);
}
- return jsName.makeRef();
+ JsNameRef nameRef = jsName.makeRef();
+ if (expression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER) {
+ nameRef.setQualifier(new JsThisRef());
+ }
+ return nameRef;
}
@Override
diff --git a/translator/src/org/jetbrains/k2js/translate/FunctionTranslator.java b/translator/src/org/jetbrains/k2js/translate/FunctionTranslator.java
index 984954e41e2..afd83519cc1 100644
--- a/translator/src/org/jetbrains/k2js/translate/FunctionTranslator.java
+++ b/translator/src/org/jetbrains/k2js/translate/FunctionTranslator.java
@@ -31,7 +31,8 @@ public final class FunctionTranslator extends AbstractTranslator {
(translationContext().getNamespaceQualifiedReference(functionName), function));
}
- @NotNull JsPropertyInitializer translateAsMethod(@NotNull JetNamedFunction jetFunction) {
+ @NotNull
+ JsPropertyInitializer translateAsMethod(@NotNull JetNamedFunction jetFunction) {
JsName functionName = translationContext().namespaceScope().declareFreshName(jetFunction.getName());
JsFunction function = generateFunctionObject(jetFunction);
return new JsPropertyInitializer(functionName.makeRef(), function);
@@ -39,17 +40,27 @@ public final class FunctionTranslator extends AbstractTranslator {
@NotNull
private JsFunction generateFunctionObject(@NotNull JetNamedFunction jetFunction) {
- JetExpression jetBodyExpression = jetFunction.getBodyExpression();
JsFunction result = JsFunction.getAnonymousFunctionWithScope
(translationContext().getScopeForElement(jetFunction));
- JsNode jsBody = (new ExpressionTranslator(functionContext(jetFunction)))
- .translate(jetBodyExpression);
+ JsNode jsBody = translateBody(jetFunction);
List jsParameters = translateParameters(jetFunction.getValueParameters(), result.getScope());
result.setParameters(jsParameters);
result.setBody(AstUtil.convertToBlock(jsBody));
return result;
}
+ @NotNull
+ private JsNode translateBody(@NotNull JetNamedFunction jetFunction) {
+ JetExpression jetBodyExpression = jetFunction.getBodyExpression();
+ //TODO support them ffs
+ assert jetBodyExpression != null : "Function without body not supported at the moment";
+ JsNode body = (new ExpressionTranslator(functionContext(jetFunction))).translate(jetBodyExpression);
+ if (jetFunction.hasBlockBody()) {
+ return AstUtil.convertToBlock(body);
+ }
+ return AstUtil.convertToBlock(new JsReturn(AstUtil.convertToExpression((body))));
+ }
+
@NotNull
private TranslationContext functionContext(@NotNull JetNamedFunction jetFunction) {
FunctionDescriptor descriptor =
diff --git a/translator/src/org/jetbrains/k2js/translate/InitializerVisitor.java b/translator/src/org/jetbrains/k2js/translate/InitializerVisitor.java
index 834a2c801bf..6a0d125d675 100644
--- a/translator/src/org/jetbrains/k2js/translate/InitializerVisitor.java
+++ b/translator/src/org/jetbrains/k2js/translate/InitializerVisitor.java
@@ -3,7 +3,6 @@ package org.jetbrains.k2js.translate;
import com.google.dart.compiler.backend.js.ast.*;
import com.google.dart.compiler.util.AstUtil;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.jet.lang.descriptors.DeclarationDescriptorVisitor;
import org.jetbrains.jet.lang.psi.*;
import java.util.ArrayList;
@@ -13,11 +12,40 @@ import java.util.List;
/**
* @author Talanov Pavel
*
- * This visitor collects all initializers from a given class in a list of statements.
- * Note: we do use this to preserve the order in which initializers are executed.
+ * This visitor collects all initializers from a given class into JsFunction object.
+ * Note: we do use visitor pattern to preserve the order in which initializers are executed.
*/
public class InitializerVisitor extends TranslatorVisitor> {
+ @NotNull private final JsScope initializerMethodScope;
+ @NotNull private final JetClass classDeclaration;
+ @NotNull private final TranslationContext initializerMethodContext;
+
+ public InitializerVisitor(@NotNull JetClass classDeclaration, @NotNull TranslationContext context) {
+ this.initializerMethodScope = new JsScope(context.getScopeForElement(classDeclaration),
+ "initializer " + classDeclaration.getName());
+ this.classDeclaration = classDeclaration;
+ this.initializerMethodContext = context.newEnclosingScope(initializerMethodScope);
+
+ }
+
+ @NotNull
+ public JsFunction generateInitializeMethodBody() {
+ JsFunction result = JsFunction.getAnonymousFunctionWithScope(initializerMethodScope);
+ result.setBody(getInitializerMethodBody(classDeclaration, initializerMethodContext));
+ return result;
+ }
+
+ @NotNull
+ private JsBlock getInitializerMethodBody(@NotNull JetClass classDeclaration,
+ @NotNull TranslationContext context) {
+ List initializerStatements = classDeclaration.accept(this, context);
+ JsBlock block = new JsBlock();
+ block.setStatements(initializerStatements);
+ return block;
+ }
+
+
@Override
@NotNull
public List visitClass(@NotNull JetClass expression, @NotNull TranslationContext context) {
@@ -35,17 +63,28 @@ public class InitializerVisitor extends TranslatorVisitor> {
if (initializer == null) {
return new ArrayList();
}
+ declareBackingFieldName(expression);
+ return Arrays.asList(translateInitializer(expression, context, initializer));
+ }
+
+ private void declareBackingFieldName(@NotNull JetProperty property) {
+ initializerMethodScope.declareName(Namer.getKotlinBackingFieldName(property.getName()));
+ }
+
+ @NotNull
+ private JsStatement translateInitializer(@NotNull JetProperty property, @NotNull TranslationContext context,
+ @NotNull JetExpression initializer) {
ExpressionTranslator translator = new ExpressionTranslator(context);
JsExpression initExpression = AstUtil.convertToExpression(translator.translate(initializer));
- return Arrays.asList(assignmentToBackingField(expression, initExpression, context));
+ return assignmentToBackingField(property, initExpression, context);
}
@NotNull
JsStatement assignmentToBackingField(@NotNull JetProperty property, @NotNull JsExpression initExpression,
@NotNull TranslationContext context) {
- JsName backingFieldName = context.classScope()
- .findExistingName(Namer.getBackingFieldNameForProperty(property.getName()));
- assert backingFieldName != null : "Class scope should contain backing field names";
+ String propertyName = property.getName();
+ assert propertyName != null : "Named property expected.";
+ JsName backingFieldName = getBackingFieldName(propertyName, context);
JsNameRef backingFieldRef = backingFieldName.makeRef();
backingFieldRef.setQualifier(new JsThisRef());
return AstUtil.convertToStatement(AstUtil.newAssignment(backingFieldRef, initExpression));
diff --git a/translator/src/org/jetbrains/k2js/translate/Namer.java b/translator/src/org/jetbrains/k2js/translate/Namer.java
index 55b20c5aec6..cee2c5eb0f7 100644
--- a/translator/src/org/jetbrains/k2js/translate/Namer.java
+++ b/translator/src/org/jetbrains/k2js/translate/Namer.java
@@ -22,7 +22,7 @@ public final class Namer {
//private static final String CLASS_CREATE_METHOD_NAME = "create";
private static final String SETTER_PREFIX = "set_";
private static final String GETTER_PREFIX = "get_";
- private static final String BACKING_FIELD_PREFIX = "_";
+ private static final String BACKING_FIELD_PREFIX = "$";
// public static final String DEFAULT_SETTER_PARAM_NAME = "val";
public static String getClassObjectName() {
@@ -30,17 +30,16 @@ public final class Namer {
return CLASS_OBJECT_NAME;
}
- public static String getNameForAccessor(String propertyName, JetPropertyAccessor accessor) {
- if (accessor.isGetter()) {
+ public static String getNameForAccessor(String propertyName, boolean isGetter) {
+ if (isGetter) {
return getNameForGetter(propertyName);
}
- if (accessor.isSetter()) {
+ else {
return getNameForSetter(propertyName);
}
- throw new AssertionError("accessor should be a getter or a setter!");
}
- public static String getBackingFieldNameForProperty(String propertyName) {
+ public static String getKotlinBackingFieldName(String propertyName) {
return getNameWithPrefix(propertyName, BACKING_FIELD_PREFIX);
}
diff --git a/translator/src/org/jetbrains/k2js/translate/OperationTranslator.java b/translator/src/org/jetbrains/k2js/translate/OperationTranslator.java
index 871783f72ed..5251729f9e2 100644
--- a/translator/src/org/jetbrains/k2js/translate/OperationTranslator.java
+++ b/translator/src/org/jetbrains/k2js/translate/OperationTranslator.java
@@ -28,6 +28,7 @@ public final class OperationTranslator {
map.put(JetTokens.LTEQ, JsBinaryOperator.LTE);
map.put(JetTokens.EQEQ, JsBinaryOperator.EQ);
map.put(JetTokens.ANDAND, JsBinaryOperator.AND);
+ map.put(JetTokens.EXCLEQ, JsBinaryOperator.NEQ);
}
public static JsBinaryOperator getBinaryOperator(JetToken token) {
diff --git a/translator/src/org/jetbrains/k2js/translate/PropertyAccessTranslator.java b/translator/src/org/jetbrains/k2js/translate/PropertyAccessTranslator.java
index 9a118369366..bf8049a1457 100644
--- a/translator/src/org/jetbrains/k2js/translate/PropertyAccessTranslator.java
+++ b/translator/src/org/jetbrains/k2js/translate/PropertyAccessTranslator.java
@@ -25,17 +25,13 @@ public final class PropertyAccessTranslator extends AbstractTranslator {
@Nullable
public JsInvocation resolveAsPropertyGet(@NotNull JetDotQualifiedExpression expression) {
- if (!(expression instanceof JetDotQualifiedExpression)) {
- return null;
- }
- JetDotQualifiedExpression dotQualifiedExpression = (JetDotQualifiedExpression)expression;
- JetExpression selectorExpression = dotQualifiedExpression.getSelectorExpression();
+ JetExpression selectorExpression = expression.getSelectorExpression();
assert selectorExpression != null : "Selector should not be null.";
JsName getterName = getPropertyGetterName(selectorExpression);
if (getterName == null) {
return null;
}
- return translateReceiverAndReturnAccessorInvocation(dotQualifiedExpression, getterName);
+ return translateReceiverAndReturnAccessorInvocation(expression, getterName);
}
@NotNull
@@ -73,7 +69,7 @@ public final class PropertyAccessTranslator extends AbstractTranslator {
if (getter == null) {
return null;
}
- return translationContext().declarations().getName(getter);
+ return translationContext().getNameForDescriptor(getter);
}
@Nullable
@@ -86,7 +82,7 @@ public final class PropertyAccessTranslator extends AbstractTranslator {
if (setter == null) {
return null;
}
- return translationContext().declarations().getName(setter);
+ return translationContext().getNameForDescriptor(setter);
}
@Nullable
diff --git a/translator/src/org/jetbrains/k2js/translate/TranslationContext.java b/translator/src/org/jetbrains/k2js/translate/TranslationContext.java
index 69c9f0c271a..cb6be7beac3 100644
--- a/translator/src/org/jetbrains/k2js/translate/TranslationContext.java
+++ b/translator/src/org/jetbrains/k2js/translate/TranslationContext.java
@@ -4,14 +4,8 @@ import com.google.dart.compiler.backend.js.ast.*;
import com.google.dart.compiler.util.AstUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
-import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
-import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
-import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
-import org.jetbrains.jet.lang.psi.JetClass;
-import org.jetbrains.jet.lang.psi.JetElement;
-import org.jetbrains.jet.lang.psi.JetNamedFunction;
-import org.jetbrains.jet.lang.psi.JetNamespace;
+import org.jetbrains.jet.lang.descriptors.*;
+import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.k2js.declarations.DeclarationExtractor;
@@ -92,7 +86,17 @@ public final class TranslationContext {
}
@NotNull
- TranslationContext newFunction(@NotNull JetNamedFunction declaration) {
+ public TranslationContext newPropertyAccess(@NotNull JetPropertyAccessor declaration) {
+ return newPropertyAccess(BindingUtils.getPropertyAccessorDescriptor(bindingContext, declaration));
+ }
+
+ @NotNull
+ public TranslationContext newPropertyAccess(@NotNull PropertyAccessorDescriptor descriptor) {
+ return newFunction(descriptor);
+ }
+
+ @NotNull
+ public TranslationContext newFunction(@NotNull JetNamedFunction declaration) {
return newFunction(BindingUtils.getFunctionDescriptor(bindingContext, declaration));
}
@@ -103,6 +107,15 @@ public final class TranslationContext {
return new TranslationContext(namespaceName, program, bindingContext, newScopes, extractor);
}
+ // Note: Should be used if and only if scope has no corresponding descriptor
+ @NotNull
+ public TranslationContext newEnclosingScope(@NotNull JsScope enclosingScope) {
+ Scopes newScopes = new Scopes(enclosingScope, scopes.classScope, scopes.namespaceScope);
+ return new TranslationContext(namespaceName, program, bindingContext, newScopes, extractor);
+ }
+
+
+
@NotNull
public JsNameRef getNamespaceQualifiedReference(JsName name) {
if (namespaceName != null) {
@@ -148,13 +161,24 @@ public final class TranslationContext {
@NotNull
public JsScope getScopeForElement(@NotNull JetElement element) {
- DeclarationDescriptor descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, element);
- assert descriptor != null : "Element should have a descriptor";
+ DeclarationDescriptor descriptor = getDescriptorForElement(element);
return getScopeForDescriptor(descriptor);
}
@NotNull
- public DeclarationExtractor declarations() {
- return extractor;
+ public JsName getNameForDescriptor(@NotNull DeclarationDescriptor descriptor) {
+ return extractor.getName(descriptor);
+ }
+
+ @NotNull JsName getNameForElement(@NotNull JetElement element) {
+ DeclarationDescriptor descriptor = getDescriptorForElement(element);
+ return getNameForDescriptor(descriptor);
+ }
+
+ @NotNull
+ private DeclarationDescriptor getDescriptorForElement(@NotNull JetElement element) {
+ DeclarationDescriptor descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, element);
+ assert descriptor != null : "Element should have a descriptor";
+ return descriptor;
}
}
diff --git a/translator/src/org/jetbrains/k2js/translate/TranslatorVisitor.java b/translator/src/org/jetbrains/k2js/translate/TranslatorVisitor.java
index f28ceb167a8..18c98ddcff7 100644
--- a/translator/src/org/jetbrains/k2js/translate/TranslatorVisitor.java
+++ b/translator/src/org/jetbrains/k2js/translate/TranslatorVisitor.java
@@ -1,5 +1,6 @@
package org.jetbrains.k2js.translate;
+import com.google.dart.compiler.backend.js.ast.JsName;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetElement;
import org.jetbrains.jet.lang.psi.JetProperty;
@@ -26,4 +27,10 @@ public class TranslatorVisitor extends JetVisitor {
}
return propertyName;
}
+
+ @NotNull
+ protected JsName getBackingFieldName(@NotNull String propertyName, @NotNull TranslationContext context) {
+ String backingFieldName = Namer.getKotlinBackingFieldName(propertyName);
+ return context.enclosingScope().findExistingName(backingFieldName);
+ }
}
diff --git a/translator/test/org/jetbrains/k2js/test/AbstractClassTest.java b/translator/test/org/jetbrains/k2js/test/AbstractClassTest.java
new file mode 100644
index 00000000000..a5820a0a674
--- /dev/null
+++ b/translator/test/org/jetbrains/k2js/test/AbstractClassTest.java
@@ -0,0 +1,44 @@
+package org.jetbrains.k2js.test;
+
+import org.jetbrains.k2js.translate.TranslationContext;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.mozilla.javascript.Context;
+import org.mozilla.javascript.Scriptable;
+
+import java.io.FileReader;
+
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author Talanov Pavel
+ */
+public abstract class AbstractClassTest extends TranslationTest {
+
+ private final String KOTLIN_JS_LIB = TEST_FILES + "kotlin_lib.js";
+
+ protected String kotlinLibrartyPath() {
+ return KOTLIN_JS_LIB;
+ }
+
+ protected void runFileWithRhino(String inputFile, Context context, Scriptable scope) throws Exception {
+ FileReader reader = new FileReader(inputFile);
+ context.evaluateReader(scope, reader, inputFile, 1, null);
+ reader.close();
+ }
+
+ @Override
+ protected void runWithRhino(String inputFile, String namespaceName,
+ String functionName, Object expectedResult) throws Exception {
+ Context cx = Context.enter();
+ Scriptable scope = cx.initStandardObjects();
+ runFileWithRhino(kotlinLibrartyPath(), cx, scope);
+ runFileWithRhino(inputFile, cx, scope);
+ Object result = extractAndCallFunctionObject(namespaceName, functionName, cx, scope);
+ assertTrue("Result is not what expected!",result.equals(expectedResult));
+ String report = namespaceName + "." + functionName + "() = " + Context.toString(result);
+ System.out.println(report);
+ Context.exit();
+ }
+
+}
diff --git a/translator/test/org/jetbrains/k2js/test/BasicClassTest.java b/translator/test/org/jetbrains/k2js/test/BasicClassTest.java
new file mode 100644
index 00000000000..28a8fd4ef98
--- /dev/null
+++ b/translator/test/org/jetbrains/k2js/test/BasicClassTest.java
@@ -0,0 +1,42 @@
+package org.jetbrains.k2js.test;
+
+import org.junit.Test;
+import org.mozilla.javascript.Context;
+import org.mozilla.javascript.Scriptable;
+
+/**
+ * @author Talanov Pavel
+ */
+public class BasicClassTest extends AbstractClassTest {
+
+ final private static String MAIN = "class/";
+
+ @Override
+ protected String mainDirectory() {
+ return MAIN;
+ }
+
+ @Test
+ public void kotlinJsLibRunsWithRhino() throws Exception {
+ Context context = Context.enter();
+ Scriptable scope = context.initStandardObjects();
+ runFileWithRhino(kotlinLibrartyPath(), context, scope);
+ Context.exit();
+ }
+
+ @Test
+ public void classInstantiation() throws Exception {
+ testFooBoxIsTrue("classInstantiation.kt");
+ }
+
+ @Test
+ public void methodDeclarationAndCall() throws Exception {
+ testFooBoxIsTrue("methodDeclarationAndCall.kt");
+ }
+
+ // TODO : excluded test
+ @Test
+ public void constructorWithParameter() throws Exception {
+ //testFooBoxIsTrue("constructorWithParameter.kt");
+ }
+}
diff --git a/translator/test/org/jetbrains/k2js/test/ClassInheritanceTest.java b/translator/test/org/jetbrains/k2js/test/ClassInheritanceTest.java
new file mode 100644
index 00000000000..958c506686a
--- /dev/null
+++ b/translator/test/org/jetbrains/k2js/test/ClassInheritanceTest.java
@@ -0,0 +1,28 @@
+package org.jetbrains.k2js.test;
+
+import org.junit.Test;
+
+/**
+ * @author Talanov Pavel
+ */
+public final class ClassInheritanceTest extends AbstractClassTest {
+
+ final private static String MAIN = "inheritance/";
+
+ @Override
+ protected String mainDirectory() {
+ return MAIN;
+ }
+
+ @Test
+ public void initializersOfBasicClassExecute() throws Exception {
+ performTest("initializersOfBasicClassExecute.kt", "foo", "box", 3);
+ }
+
+ @Test
+ public void methodOverride() throws Exception {
+ testFooBoxIsTrue("methodOverride.kt");
+ }
+}
+
+
diff --git a/translator/test/org/jetbrains/k2js/test/ClassTest.java b/translator/test/org/jetbrains/k2js/test/ClassTest.java
deleted file mode 100644
index cfbf4814da8..00000000000
--- a/translator/test/org/jetbrains/k2js/test/ClassTest.java
+++ /dev/null
@@ -1,75 +0,0 @@
-package org.jetbrains.k2js.test;
-
-import org.jetbrains.k2js.translate.TranslationContext;
-import org.junit.Test;
-import org.mozilla.javascript.Context;
-import org.mozilla.javascript.Scriptable;
-
-import java.io.FileReader;
-
-import static org.junit.Assert.assertTrue;
-
-/**
- * @author Talanov Pavel
- */
-public final class ClassTest extends TranslationTest {
-
- private final String KOTLIN_JS_LIB = TEST_DIR + "kotlin_lib.js";
-
- @Override
- protected void runWithRhino(String inputFile, String namespaceName,
- String functionName, Object expectedResult) throws Exception {
- Context cx = Context.enter();
- FileReader testFileReader = new FileReader(inputFile);
- FileReader libReader = new FileReader(KOTLIN_JS_LIB);
- try {
- Scriptable scope = cx.initStandardObjects();
- cx.evaluateReader(scope, libReader, "lib", 1, null);
- cx.evaluateReader(scope, testFileReader, "test case", 1, null);
- Object result = extractAndCallFunctionObject(namespaceName, functionName, cx, scope);
- assertTrue(result.equals(expectedResult));
- String report = namespaceName + "." + functionName + "() = " + Context.toString(result);
- System.out.println(report);
-
- } finally {
- Context.exit();
- testFileReader.close();
- }
- }
-
- @Test
- public void kotlinJsLibRunsWithRhino() throws Exception {
- runWithRhino(TEST_DIR + "testKotlinLib.js", "foo", "box", true);
- }
-
- @Test
- public void classInstantiation() throws Exception {
- testFooBoxIsTrue("classInstantiation.kt");
- }
-
- @Test
- public void methodDeclarationAndCall() throws Exception {
- testFooBoxIsTrue("methodDeclarationAndCall.kt");
- }
-
- @Test
- public void accessToInstanceProperty() throws Exception {
- testFooBoxIsTrue("accessToInstanceProperty.kt");
- }
-
- @Test
- public void twoClassesWithProperties() throws Exception {
- testFooBoxIsTrue("twoClassesWithProperties.kt");
- }
-
- @Test
- public void setter() throws Exception {
- performTest("setter.kt", "foo", "f", 99.0);
- }
-
- @Test
- public void constructorWithParameter() throws Exception {
- testFooBoxIsTrue("constructorWithParameter.kt");
- }
-
-}
diff --git a/translator/test/org/jetbrains/k2js/test/FunctionTest.java b/translator/test/org/jetbrains/k2js/test/FunctionTest.java
index 0b5c626cacc..88b2a6e56e3 100644
--- a/translator/test/org/jetbrains/k2js/test/FunctionTest.java
+++ b/translator/test/org/jetbrains/k2js/test/FunctionTest.java
@@ -1,6 +1,8 @@
package org.jetbrains.k2js.test;
+import org.junit.BeforeClass;
import org.junit.Test;
+import org.kohsuke.rngom.digested.Main;
/**
* @author Talanov Pavel
@@ -10,6 +12,12 @@ import org.junit.Test;
*/
public final class FunctionTest extends TranslationTest {
+ private static final String MAIN = "function/";
+
+ protected String mainDirectory() {
+ return MAIN;
+ }
+
@Test
public void currentTest() throws Exception {
testFooBoxIsTrue("test.kt");
diff --git a/translator/test/org/jetbrains/k2js/test/PropertyAccessorTest.java b/translator/test/org/jetbrains/k2js/test/PropertyAccessorTest.java
new file mode 100644
index 00000000000..5691ff42d20
--- /dev/null
+++ b/translator/test/org/jetbrains/k2js/test/PropertyAccessorTest.java
@@ -0,0 +1,42 @@
+package org.jetbrains.k2js.test;
+
+import org.junit.Test;
+
+/**
+ * @author Talanov Pavel
+ */
+public final class PropertyAccessorTest extends AbstractClassTest {
+
+ final private static String MAIN = "propertyAccess/";
+
+ @Override
+ protected String mainDirectory() {
+ return MAIN;
+ }
+
+ @Test
+ public void accessToInstanceProperty() throws Exception {
+ testFooBoxIsTrue("accessToInstanceProperty.kt");
+ }
+
+ @Test
+ public void twoClassesWithProperties() throws Exception {
+ testFooBoxIsTrue("twoClassesWithProperties.kt");
+ }
+
+ @Test
+ public void setter() throws Exception {
+ performTest("setter.kt", "foo", "f", 99.0);
+ }
+
+ @Test
+ public void customGetter() throws Exception {
+ testFooBoxIsTrue("customGetter.kt");
+ }
+
+ @Test
+ public void customSetter() throws Exception {
+ testFooBoxIsTrue("customSetter.kt");
+ }
+
+}
diff --git a/translator/test/org/jetbrains/k2js/test/TranslationTest.java b/translator/test/org/jetbrains/k2js/test/TranslationTest.java
index 26fba591a5c..db6c22c973b 100644
--- a/translator/test/org/jetbrains/k2js/test/TranslationTest.java
+++ b/translator/test/org/jetbrains/k2js/test/TranslationTest.java
@@ -1,6 +1,8 @@
package org.jetbrains.k2js.test;
import org.jetbrains.k2js.K2JSTranslator;
+import org.junit.Before;
+import org.junit.BeforeClass;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Function;
import org.mozilla.javascript.NativeObject;
@@ -13,21 +15,52 @@ import static org.junit.Assert.*;
/**
* @author Talanov Pavel
*/
-public class TranslationTest {
+public abstract class TranslationTest {
- protected final static String TEST_DIR = "test_files/test_cases/";
+ final protected static String TEST_FILES = "testFiles/";
+ final private static String CASES = "cases/";
+ final private static String OUT = "out/";
- protected void performTest(String inputFile, String namespaceName,
+ protected String testFilesDirectory;
+ protected String testCasesDirectory;
+ protected String outputDirectory;
+
+ @Before
+ public void setUpClass() {
+ testCasesDirectory = CASES;
+ outputDirectory = OUT;
+ testFilesDirectory = TEST_FILES + mainDirectory();
+ }
+
+ protected abstract String mainDirectory();
+
+ private String getOutputDirectory() {
+ return testFilesDirectory + outputDirectory;
+ }
+
+ private String getInputDirectory() {
+ return testFilesDirectory + testCasesDirectory;
+ }
+
+ protected void performTest(String filename, String namespaceName,
String functionName, Object expectedResult) throws Exception {
K2JSTranslator.Arguments args = new K2JSTranslator.Arguments();
- args.src = TEST_DIR + inputFile;
- args.outputDir = getOutputFilename(TEST_DIR + inputFile);
+ args.src = getInputFilePath(filename);
+ args.outputDir = getOutputFilePath(filename);
K2JSTranslator.translate(args);
runWithRhino(args.outputDir, namespaceName, functionName, expectedResult);
}
- private String getOutputFilename(String inputFile) {
- return inputFile.substring(0, inputFile.lastIndexOf('.')) + ".js";
+ private String getOutputFilePath(String filename) {
+ return getOutputDirectory() + convertToDotJsFile(filename);
+ }
+
+ private String convertToDotJsFile(String filename) {
+ return filename.substring(0, filename.lastIndexOf('.')) + ".js";
+ }
+
+ private String getInputFilePath(String filename) {
+ return getInputDirectory() + filename;
}
protected void runWithRhino(String inputFile, String namespaceName,
diff --git a/translator/test_files/test_cases/classInstantiation.kt b/translator/testFiles/class/cases/classInstantiation.kt
similarity index 100%
rename from translator/test_files/test_cases/classInstantiation.kt
rename to translator/testFiles/class/cases/classInstantiation.kt
diff --git a/translator/test_files/test_cases/constructorWithParameter.kt b/translator/testFiles/class/cases/constructorWithParameter.kt
similarity index 100%
rename from translator/test_files/test_cases/constructorWithParameter.kt
rename to translator/testFiles/class/cases/constructorWithParameter.kt
diff --git a/translator/test_files/test_cases/methodDeclarationAndCall.kt b/translator/testFiles/class/cases/methodDeclarationAndCall.kt
similarity index 100%
rename from translator/test_files/test_cases/methodDeclarationAndCall.kt
rename to translator/testFiles/class/cases/methodDeclarationAndCall.kt
diff --git a/translator/test_files/test_cases/assign.jet b/translator/testFiles/function/cases/assign.jet
similarity index 100%
rename from translator/test_files/test_cases/assign.jet
rename to translator/testFiles/function/cases/assign.jet
diff --git a/translator/test_files/test_cases/comparison.kt b/translator/testFiles/function/cases/comparison.kt
similarity index 100%
rename from translator/test_files/test_cases/comparison.kt
rename to translator/testFiles/function/cases/comparison.kt
diff --git a/translator/test_files/test_cases/doWhile.kt b/translator/testFiles/function/cases/doWhile.kt
similarity index 100%
rename from translator/test_files/test_cases/doWhile.kt
rename to translator/testFiles/function/cases/doWhile.kt
diff --git a/translator/test_files/test_cases/doWhile2.kt b/translator/testFiles/function/cases/doWhile2.kt
similarity index 100%
rename from translator/test_files/test_cases/doWhile2.kt
rename to translator/testFiles/function/cases/doWhile2.kt
diff --git a/translator/test_files/test_cases/elseif.kt b/translator/testFiles/function/cases/elseif.kt
similarity index 100%
rename from translator/test_files/test_cases/elseif.kt
rename to translator/testFiles/function/cases/elseif.kt
diff --git a/translator/test_files/test_cases/functionUsedBeforeDeclaration.kt b/translator/testFiles/function/cases/functionUsedBeforeDeclaration.kt
similarity index 100%
rename from translator/test_files/test_cases/functionUsedBeforeDeclaration.kt
rename to translator/testFiles/function/cases/functionUsedBeforeDeclaration.kt
diff --git a/translator/test_files/test_cases/if.kt b/translator/testFiles/function/cases/if.kt
similarity index 100%
rename from translator/test_files/test_cases/if.kt
rename to translator/testFiles/function/cases/if.kt
diff --git a/translator/test_files/test_cases/localProperty.jet b/translator/testFiles/function/cases/localProperty.jet
similarity index 100%
rename from translator/test_files/test_cases/localProperty.jet
rename to translator/testFiles/function/cases/localProperty.jet
diff --git a/translator/test_files/test_cases/stringAssignment.kt b/translator/testFiles/function/cases/stringAssignment.kt
similarity index 100%
rename from translator/test_files/test_cases/stringAssignment.kt
rename to translator/testFiles/function/cases/stringAssignment.kt
diff --git a/translator/test_files/test_cases/stringConstant.kt b/translator/testFiles/function/cases/stringConstant.kt
similarity index 100%
rename from translator/test_files/test_cases/stringConstant.kt
rename to translator/testFiles/function/cases/stringConstant.kt
diff --git a/translator/test_files/test_cases/test.kt b/translator/testFiles/function/cases/test.kt
similarity index 100%
rename from translator/test_files/test_cases/test.kt
rename to translator/testFiles/function/cases/test.kt
diff --git a/translator/test_files/test_cases/while.kt b/translator/testFiles/function/cases/while.kt
similarity index 100%
rename from translator/test_files/test_cases/while.kt
rename to translator/testFiles/function/cases/while.kt
diff --git a/translator/test_files/test_cases/while2.kt b/translator/testFiles/function/cases/while2.kt
similarity index 100%
rename from translator/test_files/test_cases/while2.kt
rename to translator/testFiles/function/cases/while2.kt
diff --git a/translator/testFiles/inheritance/cases/initializersOfBasicClassExecute.kt b/translator/testFiles/inheritance/cases/initializersOfBasicClassExecute.kt
new file mode 100644
index 00000000000..56671af4a58
--- /dev/null
+++ b/translator/testFiles/inheritance/cases/initializersOfBasicClassExecute.kt
@@ -0,0 +1,13 @@
+namespace foo
+
+open class A() {
+ var a = 3;
+}
+
+class B() : A() {
+
+}
+
+fun box() : Int {
+ return (B().a)
+}
diff --git a/translator/testFiles/inheritance/cases/methodOverride.kt b/translator/testFiles/inheritance/cases/methodOverride.kt
new file mode 100644
index 00000000000..82fddf73760
--- /dev/null
+++ b/translator/testFiles/inheritance/cases/methodOverride.kt
@@ -0,0 +1,15 @@
+namespace foo
+
+open class C {
+ open fun f(): Any = "C f"
+}
+
+class D() : C {
+ override fun f(): String = "D f"
+}
+
+fun box(): Boolean {
+ val d : C = D()
+ if(d.f() != "D f") return false
+ return true
+}
\ No newline at end of file
diff --git a/translator/test_files/test_cases/kotlin_lib.js b/translator/testFiles/kotlin_lib.js
similarity index 74%
rename from translator/test_files/test_cases/kotlin_lib.js
rename to translator/testFiles/kotlin_lib.js
index d3c9482a8a7..c9b45fdd90e 100644
--- a/translator/test_files/test_cases/kotlin_lib.js
+++ b/translator/testFiles/kotlin_lib.js
@@ -24,6 +24,9 @@ var Class = (function() {
parent = properties.shift();
function klass() {
+ if (parent != null) {
+ parent.prototype.initialize.apply(this)
+ }
this.initialize.apply(this, arguments);
}
@@ -84,8 +87,6 @@ var Class = (function() {
};
})();
-
-
(function() {
var _toString = Object.prototype.toString,
@@ -285,4 +286,94 @@ var Class = (function() {
isDate: isDate,
isUndefined: isUndefined
});
-})();
\ No newline at end of file
+})();
+
+
+Object.extend(Function.prototype, (function() {
+ var slice = Array.prototype.slice;
+
+ function update(array, args) {
+ var arrayLength = array.length, length = args.length;
+ while (length--) array[arrayLength + length] = args[length];
+ return array;
+ }
+
+ function merge(array, args) {
+ array = slice.call(array, 0);
+ return update(array, args);
+ }
+
+ function argumentNames() {
+ var names = this.toString().match(/^[\s\(]*function[^(]*\(([^)]*)\)/)[1]
+ .replace(/\/\/.*?[\r\n]|\/\*(?:.|[\r\n])*?\*\//g, '')
+ .replace(/\s+/g, '').split(',');
+ return names.length == 1 && !names[0] ? [] : names;
+ }
+
+ function bind(context) {
+ if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this;
+ var __method = this, args = slice.call(arguments, 1);
+ return function() {
+ var a = merge(args, arguments);
+ return __method.apply(context, a);
+ }
+ }
+
+ function bindAsEventListener(context) {
+ var __method = this, args = slice.call(arguments, 1);
+ return function(event) {
+ var a = update([event || window.event], args);
+ return __method.apply(context, a);
+ }
+ }
+
+ function curry() {
+ if (!arguments.length) return this;
+ var __method = this, args = slice.call(arguments, 0);
+ return function() {
+ var a = merge(args, arguments);
+ return __method.apply(this, a);
+ }
+ }
+
+ function delay(timeout) {
+ var __method = this, args = slice.call(arguments, 1);
+ timeout = timeout * 1000;
+ return window.setTimeout(function() {
+ return __method.apply(__method, args);
+ }, timeout);
+ }
+
+ function defer() {
+ var args = update([0.01], arguments);
+ return this.delay.apply(this, args);
+ }
+
+ function wrap(wrapper) {
+ var __method = this;
+ return function() {
+ var a = update([__method.bind(this)], arguments);
+ return wrapper.apply(this, a);
+ }
+ }
+
+ function methodize() {
+ if (this._methodized) return this._methodized;
+ var __method = this;
+ return this._methodized = function() {
+ var a = update([this], arguments);
+ return __method.apply(null, a);
+ };
+ }
+
+ return {
+ argumentNames: argumentNames,
+ bind: bind,
+ bindAsEventListener: bindAsEventListener,
+ curry: curry,
+ delay: delay,
+ defer: defer,
+ wrap: wrap,
+ methodize: methodize
+ }
+})());
diff --git a/translator/test_files/test_cases/accessToInstanceProperty.kt b/translator/testFiles/propertyAccess/cases/accessToInstanceProperty.kt
similarity index 100%
rename from translator/test_files/test_cases/accessToInstanceProperty.kt
rename to translator/testFiles/propertyAccess/cases/accessToInstanceProperty.kt
diff --git a/translator/testFiles/propertyAccess/cases/customGetter.kt b/translator/testFiles/propertyAccess/cases/customGetter.kt
new file mode 100644
index 00000000000..53200e6c544
--- /dev/null
+++ b/translator/testFiles/propertyAccess/cases/customGetter.kt
@@ -0,0 +1,13 @@
+namespace foo
+
+class Test() {
+ val a : Int
+ get() {
+ return 5;
+ }
+}
+
+fun box() : Boolean {
+ var test = Test()
+ return (test.a ==5)
+}
\ No newline at end of file
diff --git a/translator/testFiles/propertyAccess/cases/customSetter.kt b/translator/testFiles/propertyAccess/cases/customSetter.kt
new file mode 100644
index 00000000000..3c4d947547e
--- /dev/null
+++ b/translator/testFiles/propertyAccess/cases/customSetter.kt
@@ -0,0 +1,14 @@
+namespace foo
+
+class Test() {
+ var a : Int = 5
+ set(b : Int) {
+ $a = 3
+ }
+}
+
+fun box() : Boolean {
+ var test = Test()
+ test.a = 5
+ return (test.a == 3)
+}
\ No newline at end of file
diff --git a/translator/test_files/test_cases/setter.kt b/translator/testFiles/propertyAccess/cases/setter.kt
similarity index 100%
rename from translator/test_files/test_cases/setter.kt
rename to translator/testFiles/propertyAccess/cases/setter.kt
diff --git a/translator/test_files/test_cases/twoClassesWithProperties.kt b/translator/testFiles/propertyAccess/cases/twoClassesWithProperties.kt
similarity index 100%
rename from translator/test_files/test_cases/twoClassesWithProperties.kt
rename to translator/testFiles/propertyAccess/cases/twoClassesWithProperties.kt
diff --git a/translator/test_files/test_cases/assign.js b/translator/test_files/test_cases/assign.js
deleted file mode 100644
index 367d630c335..00000000000
--- a/translator/test_files/test_cases/assign.js
+++ /dev/null
@@ -1,10 +0,0 @@
-foo = {};
-(function(foo){
- foo.f = function(){
- var x = 1;
- x = x + 1;
- return x;
- }
- ;
-}
-(foo));
diff --git a/translator/test_files/test_cases/classInstantiation.js b/translator/test_files/test_cases/classInstantiation.js
deleted file mode 100644
index 4a18b69cade..00000000000
--- a/translator/test_files/test_cases/classInstantiation.js
+++ /dev/null
@@ -1,12 +0,0 @@
-foo = {};
-(function(foo){
- foo.Test = Class.create({initialize:function(){
- }
- });
- foo.box = function(){
- var test = new foo.Test;
- return true;
- }
- ;
-}
-(foo));
diff --git a/translator/test_files/test_cases/comparison.js b/translator/test_files/test_cases/comparison.js
deleted file mode 100644
index 82dd4d83d09..00000000000
--- a/translator/test_files/test_cases/comparison.js
+++ /dev/null
@@ -1,11 +0,0 @@
-foo = {};
-(function(foo){
- foo.box = function(){
- var a = 2;
- var b = 3;
- var c = 4;
- return a < c;
- }
- ;
-}
-(foo));
diff --git a/translator/test_files/test_cases/incrementProperty.jet b/translator/test_files/test_cases/incrementProperty.jet
deleted file mode 100644
index 7fba26d1359..00000000000
--- a/translator/test_files/test_cases/incrementProperty.jet
+++ /dev/null
@@ -1,14 +0,0 @@
-class Slot() {
- var vitality: Int = 10000
-
- fun increaseVitality(delta: Int) {
- vitality += delta
- if (vitality > 65535) vitality = 65535;
- }
-}
-
-fun box(): Boolean {
- val s = Slot()
- s.increaseVitality(1000)
- return (s.vitality == 11000)
-}
diff --git a/translator/test_files/test_cases/localProperty.js b/translator/test_files/test_cases/localProperty.js
deleted file mode 100644
index f7cf3f2343d..00000000000
--- a/translator/test_files/test_cases/localProperty.js
+++ /dev/null
@@ -1,15 +0,0 @@
-foo = {};
-(function(foo){
- foo.y = 3;
- foo.f = function(a){
- var x = 42;
- var y = 50;
- return y;
- }
- ;
- foo.box = function(){
- return foo.f(foo.y);
- }
- ;
-}
-(foo));
diff --git a/translator/test_files/test_cases/prototype.js b/translator/test_files/test_cases/prototype.js
deleted file mode 100644
index 9474d0e2189..00000000000
--- a/translator/test_files/test_cases/prototype.js
+++ /dev/null
@@ -1,6008 +0,0 @@
-/* Prototype JavaScript framework, version 1.7
- * (c) 2005-2010 Sam Stephenson
- *
- * Prototype is freely distributable under the terms of an MIT-style license.
- * For details, see the Prototype web site: http://www.prototypejs.org/
- *
- *--------------------------------------------------------------------------*/
-
-var Prototype = {
-
- Version: '1.7',
-
- Browser: (function(){
- var ua = navigator.userAgent;
- var isOpera = Object.prototype.toString.call(window.opera) == '[object Opera]';
- return {
- IE: !!window.attachEvent && !isOpera,
- Opera: isOpera,
- WebKit: ua.indexOf('AppleWebKit/') > -1,
- Gecko: ua.indexOf('Gecko') > -1 && ua.indexOf('KHTML') === -1,
- MobileSafari: /Apple.*Mobile/.test(ua)
- }
- })(),
-
- BrowserFeatures: {
- XPath: !!document.evaluate,
-
- SelectorsAPI: !!document.querySelector,
-
- ElementExtensions: (function() {
- var constructor = window.Element || window.HTMLElement;
- return !!(constructor && constructor.prototype);
- })(),
- SpecificElementExtensions: (function() {
- if (typeof window.HTMLDivElement !== 'undefined')
- return true;
-
- var div = document.createElement('div'),
- form = document.createElement('form'),
- isSupported = false;
-
- if (div['__proto__'] && (div['__proto__'] !== form['__proto__'])) {
- isSupported = true;
- }
-
- div = form = null;
-
- return isSupported;
- })()
- },
-
- ScriptFragment: '