diff --git a/.idea/artifacts/k2js_jar.xml b/.idea/artifacts/k2js_jar.xml
new file mode 100644
index 00000000000..c80e2b9b132
--- /dev/null
+++ b/.idea/artifacts/k2js_jar.xml
@@ -0,0 +1,18 @@
+
+
+ $PROJECT_DIR$/out/artifacts/k2js_jar
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/translator/src/org/jetbrains/k2js/translate/context/Aliaser.java b/translator/src/org/jetbrains/k2js/translate/context/Aliaser.java
index 13059a924d4..8d48863ac3e 100644
--- a/translator/src/org/jetbrains/k2js/translate/context/Aliaser.java
+++ b/translator/src/org/jetbrains/k2js/translate/context/Aliaser.java
@@ -3,13 +3,13 @@ package org.jetbrains.k2js.translate.context;
import com.google.dart.compiler.backend.js.ast.JsName;
import com.google.dart.compiler.backend.js.ast.JsNameRef;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import java.util.HashMap;
import java.util.Map;
+import java.util.Stack;
-//TODO: implement aliases stack for this need TESTS
+//TODO: implement aliasesForDescriptors stack for this need TESTS
public class Aliaser {
public static Aliaser newInstance() {
@@ -17,50 +17,53 @@ public class Aliaser {
}
@NotNull
- private final Map aliases = new HashMap();
- @Nullable
- private JsName aliasForThis = null;
+ private final Map aliasesForDescriptors = new HashMap();
+ @NotNull
+ private Stack thisAliases = new Stack();
private Aliaser() {
}
@NotNull
public JsNameRef getAliasForThis() {
- assert aliasForThis != null : "Alias is null. Use hasAliasForThis function to check.";
- return aliasForThis.makeRef();
+ assert !thisAliases.empty() : "No alias. Use hasAliasForThis function to check.";
+ return thisAliases.peek().makeRef();
}
@SuppressWarnings("NullableProblems")
public void setAliasForThis(@NotNull JsName alias) {
- aliasForThis = alias;
+ thisAliases.push(alias);
}
- public void removeAliasForThis() {
- aliasForThis = null;
+ //NOTE: here we are passing alias to check that they are set and removed in consistent order.
+ public void removeAliasForThis(@NotNull JsName aliasToRemove) {
+ assert !thisAliases.empty() : "Error: removing alias, when it is not set.";
+ JsName lastAlias = thisAliases.pop();
+ assert lastAlias.equals(aliasToRemove) : "Error: inconsistent alias removing.";
}
public boolean hasAliasForThis() {
- return (aliasForThis != null);
+ return (!thisAliases.empty());
}
public boolean hasAliasForDeclaration(@NotNull DeclarationDescriptor declaration) {
- return aliases.containsKey(declaration.getOriginal());
+ return aliasesForDescriptors.containsKey(declaration.getOriginal());
}
@NotNull
public JsName getAliasForDeclaration(@NotNull DeclarationDescriptor declaration) {
- JsName alias = aliases.get(declaration.getOriginal());
+ JsName alias = aliasesForDescriptors.get(declaration.getOriginal());
assert alias != null : "Use has alias for declaration to check.";
return alias;
}
public void setAliasForDescriptor(@NotNull DeclarationDescriptor declaration, @NotNull JsName alias) {
assert (!hasAliasForDeclaration(declaration.getOriginal())) : "This declaration already has an alias!";
- aliases.put(declaration.getOriginal(), alias);
+ aliasesForDescriptors.put(declaration.getOriginal(), alias);
}
public void removeAliasForDescriptor(@NotNull DeclarationDescriptor declaration) {
assert (hasAliasForDeclaration(declaration.getOriginal())) : "This declaration does not has an alias!";
- aliases.remove(declaration.getOriginal());
+ aliasesForDescriptors.remove(declaration.getOriginal());
}
}
\ No newline at end of file
diff --git a/translator/src/org/jetbrains/k2js/translate/context/StandardClasses.java b/translator/src/org/jetbrains/k2js/translate/context/StandardClasses.java
index 393efa9faef..336de4d56da 100644
--- a/translator/src/org/jetbrains/k2js/translate/context/StandardClasses.java
+++ b/translator/src/org/jetbrains/k2js/translate/context/StandardClasses.java
@@ -128,7 +128,9 @@ public final class StandardClasses {
}
private void declareStandardTopLevelObject(@NotNull String fullQualifiedName, @NotNull String kotlinLibName) {
- nameMap.put(fullQualifiedName, kotlinScope.declareName(kotlinLibName));
+ JsName declaredName = kotlinScope.declareName(kotlinLibName);
+ declaredName.setObfuscatable(false);
+ nameMap.put(fullQualifiedName, declaredName);
scopeMap.put(fullQualifiedName, new JsScope(kotlinScope, "standard object " + kotlinLibName));
}
@@ -143,7 +145,9 @@ public final class StandardClasses {
@NotNull String kotlinLibName) {
JsScope classScope = scopeMap.get(fullQualifiedClassName);
String fullQualifiedMethodName = fullQualifiedClassName + "." + shortMethodName;
- nameMap.put(fullQualifiedMethodName, classScope.declareName(kotlinLibName));
+ JsName declaredName = classScope.declareName(kotlinLibName);
+ declaredName.setObfuscatable(false);
+ nameMap.put(fullQualifiedMethodName, declaredName);
}
public boolean isStandardObject(@NotNull DeclarationDescriptor descriptor) {
diff --git a/translator/src/org/jetbrains/k2js/translate/context/TemporaryVariable.java b/translator/src/org/jetbrains/k2js/translate/context/TemporaryVariable.java
index 59adc6780fc..acacd981de1 100644
--- a/translator/src/org/jetbrains/k2js/translate/context/TemporaryVariable.java
+++ b/translator/src/org/jetbrains/k2js/translate/context/TemporaryVariable.java
@@ -27,7 +27,7 @@ public final class TemporaryVariable {
}
@NotNull
- /*package*/ JsName name() {
+ public JsName name() {
return variableName;
}
diff --git a/translator/src/org/jetbrains/k2js/translate/context/TranslationContext.java b/translator/src/org/jetbrains/k2js/translate/context/TranslationContext.java
index c8f630b2333..98736c5a35f 100644
--- a/translator/src/org/jetbrains/k2js/translate/context/TranslationContext.java
+++ b/translator/src/org/jetbrains/k2js/translate/context/TranslationContext.java
@@ -157,13 +157,13 @@ public final class TranslationContext {
@NotNull
public TemporaryVariable newAliasForThis() {
- TemporaryVariable aliasForThis = dynamicContext.declareTemporaryWithName("that", new JsThisRef());
+ TemporaryVariable aliasForThis = dynamicContext.declareTemporary(new JsThisRef());
aliaser().setAliasForThis(aliasForThis.name());
return aliasForThis;
}
- public void removeAliasForThis() {
- aliaser().removeAliasForThis();
+ public void removeAliasForThis(@NotNull JsName aliasToRemove) {
+ aliaser().removeAliasForThis(aliasToRemove);
}
@NotNull
diff --git a/translator/src/org/jetbrains/k2js/translate/expression/FunctionTranslator.java b/translator/src/org/jetbrains/k2js/translate/expression/FunctionTranslator.java
index 22997d2e730..0f00c5f2710 100644
--- a/translator/src/org/jetbrains/k2js/translate/expression/FunctionTranslator.java
+++ b/translator/src/org/jetbrains/k2js/translate/expression/FunctionTranslator.java
@@ -25,6 +25,15 @@ import static org.jetbrains.k2js.translate.utils.TranslationUtils.functionWithSc
*/
public final class FunctionTranslator extends AbstractTranslator {
+ @NotNull
+ public static FunctionTranslator newInstance(@NotNull JetDeclarationWithBody function,
+ @NotNull TranslationContext context) {
+ return new FunctionTranslator(function, context);
+ }
+
+ //TODO: implement more generic and safe way
+ private static final String RECEIVER_PARAMETER_NAME = "receiver";
+
@NotNull
private final JetDeclarationWithBody functionDeclaration;
@NotNull
@@ -32,11 +41,6 @@ public final class FunctionTranslator extends AbstractTranslator {
@NotNull
private final TranslationContext functionBodyContext;
- @NotNull
- public static FunctionTranslator newInstance(@NotNull JetDeclarationWithBody function,
- @NotNull TranslationContext context) {
- return new FunctionTranslator(function, context);
- }
private FunctionTranslator(@NotNull JetDeclarationWithBody functionDeclaration,
@NotNull TranslationContext context) {
@@ -58,7 +62,7 @@ public final class FunctionTranslator extends AbstractTranslator {
public JsExpression translateAsLiteral() {
TemporaryVariable aliasForThis = context().newAliasForThis();
JsFunction function = generateFunctionObject();
- context().removeAliasForThis();
+ context().removeAliasForThis(aliasForThis.name());
return AstUtil.newSequence(aliasForThis.assignmentExpression(), function);
}
@@ -72,7 +76,8 @@ public final class FunctionTranslator extends AbstractTranslator {
private void restoreContext() {
if (isExtensionFunction()) {
- functionBodyContext.removeAliasForThis();
+ JsName receiverAlias = functionBodyContext.jsScope().findExistingName(RECEIVER_PARAMETER_NAME);
+ functionBodyContext.removeAliasForThis(receiverAlias);
}
}
@@ -165,19 +170,14 @@ public final class FunctionTranslator extends AbstractTranslator {
}
private void mayBeAddThisParameterForExtensionFunction(@NotNull List jsParameters) {
- boolean isExtensionFunction = isExtensionFunction();
- if (isExtensionFunction) {
- JsName receiver = functionBodyContext.jsScope().declareName("receiver");
+ if (isExtensionFunction()) {
+ JsName receiver = functionBodyContext.jsScope().declareName(RECEIVER_PARAMETER_NAME);
context().aliaser().setAliasForThis(receiver);
jsParameters.add(new JsParameter(receiver));
}
}
private boolean isExtensionFunction() {
-// if (!(functionDeclaration instanceof JetNamedFunction)) {
-// return false;
-// }
-
FunctionDescriptor functionDescriptor = getFunctionDescriptor(context().bindingContext(), functionDeclaration);
return DescriptorUtils.isExtensionFunction(functionDescriptor);
}
diff --git a/translator/src/org/jetbrains/k2js/translate/general/Translation.java b/translator/src/org/jetbrains/k2js/translate/general/Translation.java
index ce2a390b98d..8b6609582a0 100644
--- a/translator/src/org/jetbrains/k2js/translate/general/Translation.java
+++ b/translator/src/org/jetbrains/k2js/translate/general/Translation.java
@@ -1,5 +1,7 @@
package org.jetbrains.k2js.translate.general;
+import com.google.dart.compiler.backend.js.JsNamer;
+import com.google.dart.compiler.backend.js.JsPrettyNamer;
import com.google.dart.compiler.backend.js.ast.*;
import com.google.dart.compiler.util.AstUtil;
import com.intellij.openapi.project.Project;
@@ -98,6 +100,10 @@ public final class Translation {
JsBlock block = staticContext.getProgram().getFragmentBlock(0);
TranslationContext context = TranslationContext.rootContext(staticContext);
block.addStatement(Translation.translateNamespace(namespace, context));
+
+ JsNamer namer = new JsPrettyNamer();
+ namer.exec(context.program());
+
return context.program();
}
diff --git a/translator/test/org/jetbrains/k2js/test/ExtensionFunctionTest.java b/translator/test/org/jetbrains/k2js/test/ExtensionFunctionTest.java
index 040555e9de7..c6855d5e876 100644
--- a/translator/test/org/jetbrains/k2js/test/ExtensionFunctionTest.java
+++ b/translator/test/org/jetbrains/k2js/test/ExtensionFunctionTest.java
@@ -47,4 +47,9 @@ public final class ExtensionFunctionTest extends TranslationTest {
public void extensionLiteralPassedToFunction() throws Exception {
testFooBoxIsTrue("extensionLiteralPassedToFunction.kt");
}
+
+ @Test
+ public void extensionInsideFunctionLiteral() throws Exception {
+ testFooBoxIsTrue("extensionInsideFunctionLiteral.kt");
+ }
}
diff --git a/translator/testFiles/extensionFunction/cases/extensionInsideFunctionLiteral.kt b/translator/testFiles/extensionFunction/cases/extensionInsideFunctionLiteral.kt
new file mode 100644
index 00000000000..26d2a07b437
--- /dev/null
+++ b/translator/testFiles/extensionFunction/cases/extensionInsideFunctionLiteral.kt
@@ -0,0 +1,22 @@
+namespace foo
+
+class M() {
+ var m = 0
+
+ fun eval() {
+ var d = {
+ var c = {Int.() => this + 3}
+ m += 3.c()
+ }
+ d();
+ }
+}
+
+fun box() : Boolean {
+ var a = M()
+ if (a.m != 0) return false;
+ a.eval()
+ if (a.m != 6) return false;
+
+ return true;
+}
\ No newline at end of file