diff --git a/js/js.translator/js.translator.iml b/js/js.translator/js.translator.iml
index 517bbe9302c..6969f8cd869 100644
--- a/js/js.translator/js.translator.iml
+++ b/js/js.translator/js.translator.iml
@@ -14,5 +14,6 @@
+
\ No newline at end of file
diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/expression/ExpressionVisitor.java b/js/js.translator/src/org/jetbrains/k2js/translate/expression/ExpressionVisitor.java
index 108ee21c886..50c8845cae5 100644
--- a/js/js.translator/src/org/jetbrains/k2js/translate/expression/ExpressionVisitor.java
+++ b/js/js.translator/src/org/jetbrains/k2js/translate/expression/ExpressionVisitor.java
@@ -191,8 +191,12 @@ public final class ExpressionVisitor extends TranslatorVisitor {
if (shouldBeInlined(expression, context) &&
BindingContextUtilPackage.isUsedAsExpression(expression, context.bindingContext())) {
TemporaryVariable temporaryVariable = context.declareTemporary(null);
- JsExpression callResult = CallExpressionTranslator.translate(expression, null, context).source(expression);
- context.addStatementToCurrentBlock(JsAstUtils.assignment(temporaryVariable.reference(), callResult).makeStmt());
+
+ JsNode callResult = CallExpressionTranslator.translate(expression, null, context).source(expression);
+ assert callResult instanceof JsExpression;
+
+ JsExpression assignment = JsAstUtils.assignment(temporaryVariable.reference(), (JsExpression) callResult);
+ context.addStatementToCurrentBlock(assignment.makeStmt());
return temporaryVariable.reference();
} else {
return CallExpressionTranslator.translate(expression, null, context).source(expression);
diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/reference/CallExpressionTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/reference/CallExpressionTranslator.java
index 6816b8d8293..faad74a2617 100644
--- a/js/js.translator/src/org/jetbrains/k2js/translate/reference/CallExpressionTranslator.java
+++ b/js/js.translator/src/org/jetbrains/k2js/translate/reference/CallExpressionTranslator.java
@@ -16,32 +16,51 @@
package org.jetbrains.k2js.translate.reference;
-import com.google.dart.compiler.backend.js.ast.JsExpression;
-import com.google.dart.compiler.backend.js.ast.JsInvocation;
+import com.google.dart.compiler.backend.js.ast.*;
import com.google.dart.compiler.backend.js.ast.metadata.MetadataPackage;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
-import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
-import org.jetbrains.jet.lang.descriptors.SimpleFunctionDescriptor;
-import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
+import com.google.dart.compiler.common.SourceInfoImpl;
+import com.google.gwt.dev.js.JsParser;
+import com.google.gwt.dev.js.JsParserException;
+import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.JetCallExpression;
+import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.resolve.calls.callUtil.CallUtilPackage;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
import org.jetbrains.jet.lang.resolve.calls.model.VariableAsFunctionResolvedCall;
import org.jetbrains.jet.lang.types.lang.InlineStrategy;
import org.jetbrains.jet.lang.types.lang.InlineUtil;
+import org.jetbrains.jet.lang.psi.ValueArgument;
import org.jetbrains.k2js.translate.callTranslator.CallTranslator;
import org.jetbrains.k2js.translate.context.TranslationContext;
+import org.jetbrains.k2js.translate.intrinsic.functions.patterns.DescriptorPredicate;
+import org.jetbrains.k2js.translate.intrinsic.functions.patterns.PatternBuilder;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.k2js.translate.utils.BindingUtils;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.jetbrains.jet.lang.resolve.calls.callUtil.CallUtilPackage.getFunctionResolvedCallWithAssert;
public final class CallExpressionTranslator extends AbstractCallExpressionTranslator {
@NotNull
- public static JsExpression translate(
+ private final static DescriptorPredicate JSCODE_PATTERN = PatternBuilder.pattern("kotlin.js.js(String)");
+
+ @NotNull
+ public static JsNode translate(
@NotNull JetCallExpression expression,
@Nullable JsExpression receiver,
@NotNull TranslationContext context
) {
+ if (matchesJsCode(expression, context)) {
+ return (new CallExpressionTranslator(expression, receiver, context)).translateJsCode();
+ }
+
JsExpression callExpression = (new CallExpressionTranslator(expression, receiver, context)).translate();
if (shouldBeInlined(expression, context)
@@ -80,6 +99,16 @@ public final class CallExpressionTranslator extends AbstractCallExpressionTransl
return false;
}
+ private static boolean matchesJsCode(
+ @NotNull JetCallExpression expression,
+ @NotNull TranslationContext context
+ ) {
+ FunctionDescriptor descriptor = getFunctionResolvedCallWithAssert(expression, context.bindingContext())
+ .getResultingDescriptor();
+
+ return JSCODE_PATTERN.apply(descriptor) && expression.getValueArguments().size() == 1;
+ }
+
private CallExpressionTranslator(
@NotNull JetCallExpression expression,
@Nullable JsExpression receiver,
@@ -92,4 +121,47 @@ public final class CallExpressionTranslator extends AbstractCallExpressionTransl
private JsExpression translate() {
return CallTranslator.INSTANCE$.translate(context(), resolvedCall, receiver);
}
+
+ @NotNull
+ private JsNode translateJsCode() {
+ List extends ValueArgument> arguments = expression.getValueArguments();
+ JetExpression argumentExpression = arguments.get(0).getArgumentExpression();
+ assert argumentExpression != null;
+
+ Object jsCode = BindingUtils.getCompileTimeValue(bindingContext(), argumentExpression);
+ assert jsCode instanceof String: "jsCode must be compile time string";
+ List statements = parseJsCode((String) jsCode);
+ int size = statements.size();
+
+ if (size == 0) {
+ return program().getEmptyStatement();
+ } else if (size > 1) {
+ return new JsBlock(statements);
+ } else {
+ JsStatement resultStatement = statements.get(0);
+ if (resultStatement instanceof JsExpressionStatement) {
+ return ((JsExpressionStatement) resultStatement).getExpression();
+ }
+
+ return resultStatement;
+ }
+ }
+
+ @NotNull
+ private List parseJsCode(@NotNull String jsCode) {
+ List statements = new ArrayList();
+
+ try {
+ SourceInfoImpl info = new SourceInfoImpl(null, 0, 0, 0, 0);
+ JsScope scope = context().scope();
+ StringReader reader = new StringReader(jsCode);
+ statements.addAll(JsParser.parse(info, scope, reader, /* insideFunction= */ true));
+ } catch (JsParserException e) {
+ throw new RuntimeException(e);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+
+ return statements;
+ }
}
diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/reference/QualifiedExpressionTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/reference/QualifiedExpressionTranslator.java
index 0a0af77c9ce..dc4042d2d1b 100644
--- a/js/js.translator/src/org/jetbrains/k2js/translate/reference/QualifiedExpressionTranslator.java
+++ b/js/js.translator/src/org/jetbrains/k2js/translate/reference/QualifiedExpressionTranslator.java
@@ -17,6 +17,7 @@
package org.jetbrains.k2js.translate.reference;
import com.google.dart.compiler.backend.js.ast.JsExpression;
+import com.google.dart.compiler.backend.js.ast.JsNode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
@@ -52,15 +53,17 @@ public final class QualifiedExpressionTranslator {
}
@NotNull
- public static JsExpression translateQualifiedExpression(@NotNull JetQualifiedExpression expression,
- @NotNull TranslationContext context) {
+ public static JsNode translateQualifiedExpression(
+ @NotNull JetQualifiedExpression expression,
+ @NotNull TranslationContext context
+ ) {
JsExpression receiver = translateReceiver(expression, context);
JetExpression selector = getSelector(expression);
return dispatchToCorrectTranslator(receiver, selector, context);
}
@NotNull
- private static JsExpression dispatchToCorrectTranslator(
+ private static JsNode dispatchToCorrectTranslator(
@Nullable JsExpression receiver,
@NotNull JetExpression selector,
@NotNull TranslationContext context
@@ -73,8 +76,12 @@ public final class QualifiedExpressionTranslator {
if (shouldBeInlined((JetCallExpression) selector, context) &&
BindingContextUtilPackage.isUsedAsExpression(selector, context.bindingContext())) {
TemporaryVariable temporaryVariable = context.declareTemporary(null);
- JsExpression result = invokeCallExpressionTranslator(receiver, selector, context);
- context.addStatementToCurrentBlock(JsAstUtils.assignment(temporaryVariable.reference(), result).makeStmt());
+
+ JsNode result = invokeCallExpressionTranslator(receiver, selector, context);
+ assert result instanceof JsExpression;
+
+ JsExpression assignment = JsAstUtils.assignment(temporaryVariable.reference(), (JsExpression) result);
+ context.addStatementToCurrentBlock(assignment.makeStmt());
return temporaryVariable.reference();
} else {
return invokeCallExpressionTranslator(receiver, selector, context);
@@ -88,7 +95,7 @@ public final class QualifiedExpressionTranslator {
}
@NotNull
- private static JsExpression invokeCallExpressionTranslator(
+ private static JsNode invokeCallExpressionTranslator(
@Nullable JsExpression receiver,
@NotNull JetExpression selector,
@NotNull TranslationContext context