diff --git a/.idea/inspectionProfiles/idea_default.xml b/.idea/inspectionProfiles/idea_default.xml
index 6c2f8ad45ac..23bae163cd7 100644
--- a/.idea/inspectionProfiles/idea_default.xml
+++ b/.idea/inspectionProfiles/idea_default.xml
@@ -410,9 +410,6 @@
-
diff --git a/.idea/libraries/js_libs.xml b/.idea/libraries/js_libs.xml
index 54a91f2d97b..814aa1befec 100644
--- a/.idea/libraries/js_libs.xml
+++ b/.idea/libraries/js_libs.xml
@@ -2,15 +2,15 @@
-
+
-
+
\ No newline at end of file
diff --git a/compiler/cli/src/org/jetbrains/jet/cli/js/K2JSCompiler.java b/compiler/cli/src/org/jetbrains/jet/cli/js/K2JSCompiler.java
index ea1c42db269..a8b71d9e984 100644
--- a/compiler/cli/src/org/jetbrains/jet/cli/js/K2JSCompiler.java
+++ b/compiler/cli/src/org/jetbrains/jet/cli/js/K2JSCompiler.java
@@ -22,6 +22,7 @@ import com.google.common.base.Predicates;
import com.google.common.collect.Iterables;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.io.FileUtil;
import com.intellij.psi.PsiFile;
import jet.Function0;
import org.jetbrains.annotations.NotNull;
@@ -40,6 +41,7 @@ import org.jetbrains.k2js.config.*;
import org.jetbrains.k2js.facade.K2JSTranslator;
import org.jetbrains.k2js.facade.MainCallParameters;
+import java.io.File;
import java.util.List;
import static org.jetbrains.jet.cli.common.messages.CompilerMessageLocation.NO_LOCATION;
@@ -63,21 +65,15 @@ public class K2JSCompiler extends CLICompiler sourceFiles;
-
@Override
public boolean isHelp() {
return help;
@@ -84,22 +81,16 @@ public class K2JSCompilerArguments extends CompilerArguments {
@Override
public String getSrc() {
- if (sourceFiles != null) {
- return sourceFiles.toString();
- }
- return srcdir;
+ throw new IllegalStateException();
}
public MainCallParameters createMainCallParameters() {
- if (mainCall != null) {
- if (mainCall.equals("main")) {
- return MainCallParameters.mainWithoutArguments();
- }
- if (mainCall.equals("mainWithArgs")) {
- // TODO should we pass the arguments to the compiler?
- return MainCallParameters.mainWithArguments(new ArrayList());
- }
+ if ("noCall".equals(main)) {
+ return MainCallParameters.noCall();
+ }
+ else {
+ // TODO should we pass the arguments to the compiler?
+ return MainCallParameters.mainWithoutArguments();
}
- return MainCallParameters.noCall();
}
}
diff --git a/idea/src/org/jetbrains/jet/plugin/compiler/K2JSCompiler.java b/idea/src/org/jetbrains/jet/plugin/compiler/K2JSCompiler.java
index 500318810b5..14360d671d7 100644
--- a/idea/src/org/jetbrains/jet/plugin/compiler/K2JSCompiler.java
+++ b/idea/src/org/jetbrains/jet/plugin/compiler/K2JSCompiler.java
@@ -17,27 +17,29 @@
package org.jetbrains.jet.plugin.compiler;
import com.google.common.collect.Lists;
+import com.intellij.openapi.application.AccessToken;
import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.compiler.CompileContext;
-import com.intellij.openapi.compiler.CompileScope;
-import com.intellij.openapi.compiler.CompilerMessageCategory;
-import com.intellij.openapi.compiler.TranslatingCompiler;
+import com.intellij.openapi.application.ReadAction;
+import com.intellij.openapi.compiler.*;
import com.intellij.openapi.module.Module;
-import com.intellij.openapi.project.Project;
+import com.intellij.openapi.roots.ModuleOrderEntry;
import com.intellij.openapi.roots.ModuleRootManager;
+import com.intellij.openapi.roots.OrderEntry;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Chunk;
+import com.intellij.util.StringBuilderSpinAllocator;
+import gnu.trove.THashSet;
import jet.Function1;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.plugin.JetFileType;
-import org.jetbrains.jet.plugin.k2jsrun.K2JSRunnerUtils;
import org.jetbrains.jet.plugin.project.JsModuleDetector;
import java.io.PrintStream;
import java.util.ArrayList;
+import java.util.Set;
import static org.jetbrains.jet.plugin.compiler.CompilerUtils.invokeExecMethod;
import static org.jetbrains.jet.plugin.compiler.CompilerUtils.outputCompilerMessagesAndHandleExitCode;
@@ -46,7 +48,6 @@ import static org.jetbrains.jet.plugin.compiler.CompilerUtils.outputCompilerMess
* @author Pavel Talanov
*/
public final class K2JSCompiler implements TranslatingCompiler {
-
@Override
public boolean isCompilableFile(VirtualFile file, CompileContext context) {
if (!(file.getFileType() instanceof JetFileType)) {
@@ -115,16 +116,9 @@ public final class K2JSCompiler implements TranslatingCompiler {
@NotNull
private static Integer doExec(@NotNull CompileContext context, @NotNull CompilerEnvironment environment, @NotNull PrintStream out,
@NotNull Module module) throws Exception {
- VirtualFile[] roots = ModuleRootManager.getInstance(module).getSourceRoots();
- if (roots.length != 1) {
- context.addMessage(CompilerMessageCategory.ERROR, "K2JSCompiler does not support multiple module source roots.", null, -1, -1);
- return -1;
- }
-
VirtualFile outDir = context.getModuleOutputDirectory(module);
- String outFile = outDir == null ? null : K2JSRunnerUtils.constructPathToGeneratedFile(context.getProject(), outDir.getPath());
-
- String[] commandLineArgs = constructArguments(context.getProject(), outFile, roots[0]);
+ String outFile = outDir == null ? null : outDir.getPath() + "/" + module.getName() + ".js";
+ String[] commandLineArgs = constructArguments(module, outFile);
Object rc = invokeExecMethod(environment, out, context, commandLineArgs, "org.jetbrains.jet.cli.js.K2JSCompiler");
if (outDir != null && !ApplicationManager.getApplication().isUnitTestMode()) {
@@ -134,30 +128,96 @@ public final class K2JSCompiler implements TranslatingCompiler {
}
@NotNull
- private static String[] constructArguments(@NotNull Project project, @Nullable String outFile, @NotNull VirtualFile srcDir) {
+ private static String[] constructArguments(@NotNull Module module, @Nullable String outFile) {
+ VirtualFile[] sourceFiles = getSourceFiles(module);
+
ArrayList args = Lists.newArrayList("-tags", "-verbose", "-version");
- addPathToSourcesDir(args, srcDir);
+ addPathToSourcesDir(sourceFiles, args);
addOutputPath(outFile, args);
- addLibLocationAndTarget(project, args);
+ addLibLocationAndTarget(module, args);
return ArrayUtil.toStringArray(args);
}
- private static void addLibLocationAndTarget(@NotNull Project project, @NotNull ArrayList args) {
- Pair libLocationAndTarget = JsModuleDetector.getLibLocationAndTargetForProject(project);
- if (libLocationAndTarget.first != null) {
- args.add("-libzip");
- args.add(libLocationAndTarget.first);
+ // we cannot use OrderEnumerator because it has critical bug — try https://gist.github.com/2953261, processor will never be called for module dependency
+ // we don't use context.getCompileScope().getAffectedModules() because we want to know about linkage type (well, we ignore scope right now, but in future...)
+ private static void collectModuleDependencies(Module dependentModule, Set modules) {
+ for (OrderEntry entry : ModuleRootManager.getInstance(dependentModule).getOrderEntries()) {
+ if (entry instanceof ModuleOrderEntry) {
+ ModuleOrderEntry moduleEntry = (ModuleOrderEntry) entry;
+ if (!moduleEntry.getScope().isForProductionCompile()) {
+ continue;
+ }
+
+ Module module = moduleEntry.getModule();
+ if (module == null) {
+ continue;
+ }
+
+ if (modules.add(module) && moduleEntry.isExported()) {
+ collectModuleDependencies(module, modules);
+ }
+ }
}
+ }
+
+ private static VirtualFile[] getSourceFiles(@NotNull Module module) {
+ return CompilerManager.getInstance(module.getProject()).createModuleCompileScope(module, false)
+ .getFiles(JetFileType.INSTANCE, true);
+ }
+
+ private static void addLibLocationAndTarget(@NotNull Module module, @NotNull ArrayList args) {
+ Pair libLocationAndTarget = JsModuleDetector.getLibLocationAndTargetForProject(module);
+
+ StringBuilder sb = StringBuilderSpinAllocator.alloc();
+ AccessToken token = ReadAction.start();
+ try {
+ THashSet modules = new THashSet();
+ collectModuleDependencies(module, modules);
+ if (!modules.isEmpty()) {
+ for (Module dependency : modules) {
+ sb.append('@').append(dependency.getName()).append(',');
+
+ for (VirtualFile file : getSourceFiles(dependency)) {
+ sb.append(file.getPath()).append(',');
+ }
+ }
+ }
+
+ if (libLocationAndTarget.first != null) {
+ for (String file : libLocationAndTarget.first) {
+ sb.append(file).append(',');
+ }
+ }
+
+ if (sb.length() > 0) {
+ args.add("-libraryFiles");
+ args.add(sb.substring(0, sb.length() - 1));
+ }
+ }
+ finally {
+ token.finish();
+ StringBuilderSpinAllocator.dispose(sb);
+ }
+
if (libLocationAndTarget.second != null) {
args.add("-target");
args.add(libLocationAndTarget.second);
}
}
- private static void addPathToSourcesDir(@NotNull ArrayList args, @NotNull VirtualFile srcDir) {
- String srcPath = srcDir.getPath();
- args.add("-srcdir");
- args.add(srcPath);
+ private static void addPathToSourcesDir(@NotNull VirtualFile[] sourceFiles, @NotNull ArrayList args) {
+ args.add("-sourceFiles");
+
+ StringBuilder sb = StringBuilderSpinAllocator.alloc();
+ try {
+ for (VirtualFile file : sourceFiles) {
+ sb.append(file.getPath()).append(',');
+ }
+ args.add(sb.substring(0, sb.length() - 1));
+ }
+ finally {
+ StringBuilderSpinAllocator.dispose(sb);
+ }
}
private static void addOutputPath(@Nullable String outFile, @NotNull ArrayList args) {
diff --git a/idea/src/org/jetbrains/jet/plugin/project/IDEAConfig.java b/idea/src/org/jetbrains/jet/plugin/project/IDEAConfig.java
index db29e72d794..2afd9df2842 100644
--- a/idea/src/org/jetbrains/jet/plugin/project/IDEAConfig.java
+++ b/idea/src/org/jetbrains/jet/plugin/project/IDEAConfig.java
@@ -19,15 +19,15 @@ package org.jetbrains.jet.plugin.project;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.k2js.config.EcmaVersion;
-import org.jetbrains.k2js.config.ZippedLibrarySourcesConfig;
+import org.jetbrains.k2js.config.LibrarySourcesConfig;
import static org.jetbrains.jet.plugin.project.JsModuleDetector.getLibLocationAndTargetForProject;
/**
* @author Pavel Talanov
*/
-public final class IDEAConfig extends ZippedLibrarySourcesConfig {
+public final class IDEAConfig extends LibrarySourcesConfig {
public IDEAConfig(@NotNull Project project) {
- super(project, getLibLocationAndTargetForProject(project).first, EcmaVersion.defaultVersion());
+ super(project, "default", getLibLocationAndTargetForProject(project).first, EcmaVersion.defaultVersion());
}
}
diff --git a/idea/src/org/jetbrains/jet/plugin/project/JsModuleDetector.java b/idea/src/org/jetbrains/jet/plugin/project/JsModuleDetector.java
index 796791c1179..526be3aa494 100644
--- a/idea/src/org/jetbrains/jet/plugin/project/JsModuleDetector.java
+++ b/idea/src/org/jetbrains/jet/plugin/project/JsModuleDetector.java
@@ -36,10 +36,6 @@ public final class JsModuleDetector {
private JsModuleDetector() {
}
- public static boolean isJsProject(@NotNull Project project) {
- return getJSModule(project) != null;
- }
-
public static boolean isJsModule(@NotNull Module module) {
return K2JSModuleComponent.getInstance(module).isJavaScriptModule();
}
@@ -57,15 +53,22 @@ public final class JsModuleDetector {
}
@NotNull
- public static Pair getLibLocationAndTargetForProject(@NotNull Project project) {
+ public static Pair getLibLocationAndTargetForProject(@NotNull Project project) {
Module module = getJSModule(project);
if (module == null) {
return Pair.empty();
}
+ else {
+ return getLibLocationAndTargetForProject(module);
+ }
+ }
+
+ @NotNull
+ public static Pair getLibLocationAndTargetForProject(@NotNull Module module) {
K2JSModuleComponent jsModuleComponent = K2JSModuleComponent.getInstance(module);
String pathToJavaScriptLibrary = jsModuleComponent.getPathToJavaScriptLibrary();
String basePath = ModuleRootManager.getInstance(module).getContentRoots()[0].getPath();
- return Pair.create(basePath + pathToJavaScriptLibrary, jsModuleComponent.getEcmaVersion().toString());
+ return Pair.create(new String[] {basePath + pathToJavaScriptLibrary}, jsModuleComponent.getEcmaVersion().toString());
}
@Nullable
diff --git a/js/js.libraries/src/core/annotations.kt b/js/js.libraries/src/core/annotations.kt
index 15e9185634a..f1a1793fc7a 100644
--- a/js/js.libraries/src/core/annotations.kt
+++ b/js/js.libraries/src/core/annotations.kt
@@ -3,4 +3,6 @@ package js;
native
public annotation class native(name : String = "") {}
native
-public annotation class library(name : String = "") {}
\ No newline at end of file
+public annotation class library(name : String = "") {}
+native
+public annotation class enumerable() {}
\ No newline at end of file
diff --git a/js/js.libraries/src/core/debug.kt b/js/js.libraries/src/core/debug.kt
index 54000cc79b6..a542b0f5b2d 100644
--- a/js/js.libraries/src/core/debug.kt
+++ b/js/js.libraries/src/core/debug.kt
@@ -1,11 +1,15 @@
package js.debug
-import js.*
+import js.noImpl
+
+// https://developer.mozilla.org/en/DOM/console
+native trait Console {
+ native fun dir(o: Any): Unit = noImpl
+ native fun error(vararg o: Any?): Unit = noImpl
+ native fun info(vararg o: Any?): Unit = noImpl
+ native fun log(vararg o: Any?): Unit = noImpl
+ native fun warn(vararg o: Any?): Unit = noImpl
+}
native
-val console : consoleClass = js.noImpl
-
-native
-class consoleClass() {
- fun log(message : Any?) : Unit = js.noImpl
-}
\ No newline at end of file
+val console:Console = noImpl
\ No newline at end of file
diff --git a/js/js.libraries/src/core/javautil.kt b/js/js.libraries/src/core/javautil.kt
index 414cd77f702..7a57c6c54d5 100644
--- a/js/js.libraries/src/core/javautil.kt
+++ b/js/js.libraries/src/core/javautil.kt
@@ -12,12 +12,11 @@ public trait Comparator {
library
public trait Iterator {
- open fun next() : T = js.noImpl
- open fun hasNext() : Boolean = js.noImpl
- open fun remove() : Unit = js.noImpl
+ open public fun next() : T = js.noImpl
+ open public fun hasNext() : Boolean = js.noImpl
+ open public fun remove() : Unit = js.noImpl
}
-
val Collections = object {
library("collectionsMax")
public fun max(col : Collection, comp : Comparator) : T = js.noImpl
@@ -55,120 +54,74 @@ val Collections = object {
}
library
-public open class ArrayList() : java.util.List {
- public override fun size() : Int = js.noImpl
- public override fun isEmpty() : Boolean = js.noImpl
- public override fun contains(o : Any?) : Boolean = js.noImpl
- public override fun iterator() : Iterator = js.noImpl
- // public override fun indexOf(o : Any?) : Int = js.noImpl
- // public override fun lastIndexOf(o : Any?) : Int = js.noImpl
- // public override fun toArray() : Array = js.noImpl
- // public override fun toArray(a : Array) : Array = js.noImpl
- public override fun get(index : Int) : E = js.noImpl
- public override fun set(index : Int, element : E) : E = js.noImpl
- public override fun add(e : E) : Boolean = js.noImpl
- public override fun add(index : Int, element : E) : Unit = js.noImpl
- library("removeByIndex")
- public override fun remove(index : Int) : E = js.noImpl
- public override fun remove(o : Any?) : Boolean = js.noImpl
- public override fun clear() : Unit = js.noImpl
- public override fun addAll(c : java.util.Collection) : Boolean = js.noImpl
- // public override fun addAll(index : Int, c : java.util.Collection) : Boolean = js.noImpl
-}
-
-library
-public trait Collection : java.lang.Iterable {
- open public fun size() : Int
- open public fun isEmpty() : Boolean
- open public fun contains(o : Any?) : Boolean
- override public fun iterator() : java.util.Iterator
- // open public fun toArray() : Array
- // open public fun toArray(a : Array) : Array
- open public fun add(e : E) : Boolean
- open public fun remove(o : Any?) : Boolean
+public trait Collection: Iterable {
+ open public fun size(): Int
+ open public fun isEmpty(): Boolean
+ open public fun contains(o: Any?): Boolean
+ override public fun iterator(): Iterator
+ public fun toArray(): Array
+ // open public fun toArray(a : Array) : Array
+ open public fun add(e: E): Boolean
+ open public fun remove(o: Any?): Boolean
//open public fun containsAll(c : java.util.Collection<*>) : Boolean
- open public fun addAll(c : java.util.Collection) : Boolean
+ open public fun addAll(c: Collection): Boolean
//open public fun removeAll(c : java.util.Collection<*>) : Boolean
//open public fun retainAll(c : java.util.Collection<*>) : Boolean
- open public fun clear() : Unit
+ open public fun clear(): Unit
}
library
-public abstract open class AbstractCollection() : Collection {
+public abstract class AbstractCollection() : Collection {
+ override public fun toArray(): Array = js.noImpl
+
+ override public fun isEmpty(): Boolean = js.noImpl
+ override public fun contains(o: Any?): Boolean = js.noImpl
+ override public fun iterator(): Iterator = js.noImpl
+
+ override public fun add(e: E): Boolean = js.noImpl
+ override public fun remove(o: Any?): Boolean = js.noImpl
+
+ override public fun addAll(c: Collection): Boolean = js.noImpl
+
+ override public fun clear(): Unit = js.noImpl
+ override public fun size(): Int = js.noImpl
}
library
-public abstract open class AbstractList() : AbstractCollection(), List {
- public override fun isEmpty() : Boolean = js.noImpl
- public override fun contains(o : Any?) : Boolean = js.noImpl
- public override fun iterator() : Iterator = js.noImpl
- // public override fun indexOf(o : Any?) : Int = js.noImpl
- // public override fun lastIndexOf(o : Any?) : Int = js.noImpl
- // public override fun toArray() : Array = js.noImpl
- // public override fun toArray(a : Array) : Array = js.noImpl
- public override fun set(index : Int, element : E) : E = js.noImpl
- public override fun add(e : E) : Boolean = js.noImpl
- public override fun add(index : Int, element : E) : Unit = js.noImpl
- library("removeByIndex")
- public override fun remove(index : Int) : E = js.noImpl
- public override fun remove(o : Any?) : Boolean = js.noImpl
- public override fun clear() : Unit = js.noImpl
- public override fun addAll(c : java.util.Collection) : Boolean = js.noImpl
- // public override fun addAll(index : Int, c : java.util.Collection) : Boolean = js.noImpl
+public trait List: Collection {
+ public fun get(index: Int): E
+ public fun set(index: Int, element: E): E
+
+ public fun add(index: Int, element: E): Unit
+ public fun remove(index: Int): E
+
+ public fun indexOf(o: E?): Int
}
library
-public trait List : Collection {
- override public fun size() : Int
- override public fun isEmpty() : Boolean
- override public fun contains(o : Any?) : Boolean
- override public fun iterator() : java.util.Iterator
- // override public fun toArray() : Array
- // Simulate Java's array covariance
- // override public fun toArray(a : Array) : Array
- override public fun add(e : E) : Boolean
- override public fun remove(o : Any?) : Boolean
- // override public fun containsAll(c : java.util.Collection<*>) : Boolean
- override public fun addAll(c : java.util.Collection) : Boolean
- // open public fun addAll(index : Int, c : java.util.Collection) : Boolean
- // override public fun removeAll(c : java.util.Collection<*>) : Boolean
- // override public fun retainAll(c : java.util.Collection<*>) : Boolean
- override public fun clear() : Unit
- open public fun get(index : Int) : E
- open public fun set(index : Int, element : E) : E
- open public fun add(index : Int, element : E) : Unit
- open public fun remove(index : Int) : E
- // open public fun indexOf(o : Any?) : Int
- // open public fun lastIndexOf(o : Any?) : Int
+public abstract class AbstractList(): AbstractCollection(), List {
+ override public fun get(index: Int): E = js.noImpl
+ override public fun set(index: Int, element: E): E = js.noImpl
+
+ library("addAt")
+ override public public fun add(index: Int, element: E): Unit = js.noImpl
+
+ library("removeAt")
+ override public fun remove(index: Int): E = js.noImpl
+
+ override public fun indexOf(o: E?): Int = js.noImpl
+}
+
+library
+public open class ArrayList() : AbstractList() {
}
library
public trait Set : Collection {
- override public fun size() : Int
- override public fun isEmpty() : Boolean
- override public fun contains(o : Any?) : Boolean
- override public fun iterator() : java.util.Iterator
- // override public fun toArray() : Array
- // override public fun toArray(a : Array) : Array
- override public fun add(e : E) : Boolean
- override public fun remove(o : Any?) : Boolean
- //override public fun containsAll(c : java.util.Collection<*>) : Boolean
- override public fun addAll(c : java.util.Collection) : Boolean
- //override public fun retainAll(c : java.util.Collection<*>) : Boolean
- //override public fun removeAll(c : java.util.Collection<*>) : Boolean
- override public fun clear() : Unit
}
library
-public open class HashSet() : java.util.Set {
- public override fun iterator() : java.util.Iterator = js.noImpl
- public override fun size() : Int = js.noImpl
- public override fun isEmpty() : Boolean = js.noImpl
- public override fun contains(o : Any?) : Boolean = js.noImpl
- public override fun add(e : E) : Boolean = js.noImpl
- public override fun remove(o : Any?) : Boolean = js.noImpl
- public override fun clear() : Unit = js.noImpl
- override fun addAll(c : java.util.Collection) : Boolean = js.noImpl
+public open class HashSet(): AbstractCollection(), java.util.Set {
}
library
@@ -186,23 +139,23 @@ public trait Map {
open public fun values() : java.util.Collection
open public fun entrySet() : java.util.Set>
-// open public fun equals(o : Any?) : Boolean
-// open public fun hashCode() : Int
+// open public fun equals(o : Any?) : Boolean
+// open public fun hashCode() : Int
trait Entry {
open public fun getKey() : K
open public fun getValue() : V
open public fun setValue(value : V) : V
-// open public fun equals(o : Any?) : Boolean
-// open public fun hashCode() : Int
+// open public fun equals(o : Any?) : Boolean
+// open public fun hashCode() : Int
}
}
library
-public open class HashMap() : java.util.Map {
+public open class HashMap() : Map {
public override fun size() : Int = js.noImpl
public override fun isEmpty() : Boolean = js.noImpl
- public override fun get(key : Any?) : V = js.noImpl
+ public override fun get(key : Any?) : V? = js.noImpl
public override fun containsKey(key : Any?) : Boolean = js.noImpl
public override fun put(key : K, value : V) : V = js.noImpl
public override fun putAll(m : java.util.Map) : Unit = js.noImpl
@@ -215,37 +168,23 @@ public open class HashMap() : java.util.Map {
}
library
-public open class LinkedList() : List {
- public override fun iterator() : java.util.Iterator = js.noImpl
- public override fun isEmpty() : Boolean = js.noImpl
- public override fun contains(o : Any?) : Boolean = js.noImpl
- public override fun size() : Int = js.noImpl
- public override fun add(e : E) : Boolean = js.noImpl
- public override fun remove(o : Any?) : Boolean = js.noImpl
- public override fun addAll(c : java.util.Collection) : Boolean = js.noImpl
- public override fun clear() : Unit = js.noImpl
- public override fun get(index : Int) : E = js.noImpl
- public override fun set(index : Int, element : E) : E = js.noImpl
- public override fun add(index : Int, element : E) : Unit = js.noImpl
- public override fun remove(index : Int) : E = js.noImpl
- public fun poll() : E? = js.noImpl
- public fun peek() : E? = js.noImpl
- public fun offer(e : E) : Boolean = js.noImpl
+public open class LinkedList(): AbstractList() {
+ public override fun get(index: Int): E = js.noImpl
+ public override fun set(index: Int, element: E): E = js.noImpl
+ public override fun add(index: Int, element: E): Unit = js.noImpl
+ public fun poll(): E? = js.noImpl
+ public fun peek(): E? = js.noImpl
+ public fun offer(e: E): Boolean = js.noImpl
}
library
public class StringBuilder() : Appendable {
- override fun append(c: Char): Appendable? = js.noImpl
- override fun append(csq: CharSequence?): Appendable? = js.noImpl
- override fun append(csq: CharSequence?, start: Int, end: Int): Appendable? = js.noImpl
+ override public fun append(c: Char): Appendable? = js.noImpl
+ override public fun append(csq: CharSequence?): Appendable? = js.noImpl
+ override public fun append(csq: CharSequence?, start: Int, end: Int): Appendable? = js.noImpl
public fun append(obj : Any?) : StringBuilder = js.noImpl
public fun toString() : String = js.noImpl
}
library
-public class NoSuchElementException() : Exception() {}
-
-public trait Enumeration {
- open fun hasMoreElements(): Boolean
- open fun nextElement(): E?
-}
+public class NoSuchElementException() : Exception() {}
\ No newline at end of file
diff --git a/js/js.libraries/src/core/json.kt b/js/js.libraries/src/core/json.kt
index 9a60614639c..f61f1904724 100644
--- a/js/js.libraries/src/core/json.kt
+++ b/js/js.libraries/src/core/json.kt
@@ -21,4 +21,13 @@ library("jsonFromTuples")
public fun json2(pairs : Array>) : Json = js.noImpl
library("jsonAddProperties")
-public fun Json.add(other : Json) : Json = js.noImpl
\ No newline at end of file
+public fun Json.add(other : Json) : Json = js.noImpl
+
+native
+public trait JsonClass {
+ public fun stringify(o: Any): String = noImpl
+ public fun parse(text: String): T = noImpl
+}
+
+native
+public val JSON:JsonClass = noImpl
\ No newline at end of file
diff --git a/js/js.tests/test/org/jetbrains/k2js/test/BasicTest.java b/js/js.tests/test/org/jetbrains/k2js/test/BasicTest.java
index 3adf4798ba5..453e3b3e3e3 100644
--- a/js/js.tests/test/org/jetbrains/k2js/test/BasicTest.java
+++ b/js/js.tests/test/org/jetbrains/k2js/test/BasicTest.java
@@ -43,6 +43,8 @@ public abstract class BasicTest extends TestWithEnvironment {
private static final String CASES = "cases/";
private static final String OUT = "out/";
private static final String EXPECTED = "expected/";
+
+ public static final String JSLINT_LIB = pathToTestFilesRoot() + "jslint.js";
@NotNull
private String mainDirectory = "";
diff --git a/js/js.tests/test/org/jetbrains/k2js/test/SingleFileTranslationTest.java b/js/js.tests/test/org/jetbrains/k2js/test/SingleFileTranslationTest.java
index 3f09631dfaf..4d3dc54ca1f 100644
--- a/js/js.tests/test/org/jetbrains/k2js/test/SingleFileTranslationTest.java
+++ b/js/js.tests/test/org/jetbrains/k2js/test/SingleFileTranslationTest.java
@@ -42,7 +42,7 @@ public abstract class SingleFileTranslationTest extends BasicTest {
runFunctionOutputTest(EcmaVersion.all(), kotlinFilename, namespaceName, functionName, expectedResult);
}
- protected void runFunctionOutputTest(@NotNull EnumSet ecmaVersions, @NotNull String kotlinFilename,
+ protected void runFunctionOutputTest(@NotNull Iterable ecmaVersions, @NotNull String kotlinFilename,
@NotNull String namespaceName,
@NotNull String functionName,
@NotNull Object expectedResult) throws Exception {
@@ -50,7 +50,7 @@ public abstract class SingleFileTranslationTest extends BasicTest {
runRhinoTests(kotlinFilename, ecmaVersions, new RhinoFunctionResultChecker(namespaceName, functionName, expectedResult));
}
- public void checkFooBoxIsTrue(@NotNull String filename, @NotNull EnumSet ecmaVersions) throws Exception {
+ public void checkFooBoxIsTrue(@NotNull String filename, @NotNull Iterable ecmaVersions) throws Exception {
runFunctionOutputTest(ecmaVersions, filename, "foo", "box", true);
}
@@ -58,7 +58,7 @@ public abstract class SingleFileTranslationTest extends BasicTest {
checkFooBoxIsTrue(getTestName(true) + ".kt", EcmaVersion.all());
}
- protected void fooBoxTest(@NotNull EnumSet ecmaVersions) throws Exception {
+ protected void fooBoxTest(@NotNull Iterable ecmaVersions) throws Exception {
checkFooBoxIsTrue(getTestName(true) + ".kt", ecmaVersions);
}
@@ -84,7 +84,7 @@ public abstract class SingleFileTranslationTest extends BasicTest {
runRhinoTests(kotlinFilename, ecmaVersions, new RhinoSystemOutputChecker(expectedResult));
}
- protected void performTestWithMain(@NotNull EnumSet ecmaVersions,
+ protected void performTestWithMain(@NotNull Iterable ecmaVersions,
@NotNull String testName,
@NotNull String testId,
@NotNull String... args) throws Exception {
diff --git a/js/js.tests/test/org/jetbrains/k2js/test/config/TestConfig.java b/js/js.tests/test/org/jetbrains/k2js/test/config/TestConfig.java
index f3832533022..bd2db405a78 100644
--- a/js/js.tests/test/org/jetbrains/k2js/test/config/TestConfig.java
+++ b/js/js.tests/test/org/jetbrains/k2js/test/config/TestConfig.java
@@ -28,8 +28,11 @@ import java.util.List;
/**
* @author Pavel Talanov
*/
-public class TestConfig extends Config {
+public final class TestConfig extends Config {
+ //NOTE: hard-coded in kotlin-lib files
+ @NotNull
+ public static final String TEST_MODULE_NAME = "JS_TESTS";
@NotNull
private final List jsLibFiles;
@NotNull
@@ -37,7 +40,7 @@ public class TestConfig extends Config {
public TestConfig(@NotNull Project project, @NotNull EcmaVersion version,
@NotNull List files, @NotNull BindingContext context) {
- super(project, version);
+ super(project, TEST_MODULE_NAME, version);
jsLibFiles = files;
libraryContext = context;
}
diff --git a/js/js.tests/test/org/jetbrains/k2js/test/rhino/FunctionWithScope.java b/js/js.tests/test/org/jetbrains/k2js/test/rhino/FunctionWithScope.java
new file mode 100644
index 00000000000..228c914c824
--- /dev/null
+++ b/js/js.tests/test/org/jetbrains/k2js/test/rhino/FunctionWithScope.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2010-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.jetbrains.k2js.test.rhino;
+
+import org.jetbrains.annotations.NotNull;
+import org.mozilla.javascript.Function;
+import org.mozilla.javascript.Scriptable;
+
+/**
+ * @author Sergey Simonchik
+ */
+class FunctionWithScope {
+ private final Function fun;
+ private final Scriptable scope;
+
+ FunctionWithScope(@NotNull Function function, @NotNull Scriptable scope) {
+ this.fun = function;
+ this.scope = scope;
+ }
+
+ @NotNull
+ public Function getFunction() {
+ return fun;
+ }
+
+ @NotNull
+ public Scriptable getScope() {
+ return scope;
+ }
+}
diff --git a/js/js.tests/test/org/jetbrains/k2js/test/rhino/RhinoFunctionManager.java b/js/js.tests/test/org/jetbrains/k2js/test/rhino/RhinoFunctionManager.java
new file mode 100644
index 00000000000..a4f460b18ab
--- /dev/null
+++ b/js/js.tests/test/org/jetbrains/k2js/test/rhino/RhinoFunctionManager.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2010-2012 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.jetbrains.k2js.test.rhino;
+
+import com.google.common.base.Supplier;
+import com.intellij.openapi.diagnostic.Logger;
+import org.jetbrains.annotations.NotNull;
+import org.mozilla.javascript.Context;
+import org.mozilla.javascript.Function;
+import org.mozilla.javascript.Script;
+import org.mozilla.javascript.Scriptable;
+
+/**
+ * @author Sergey Simonchik
+ */
+class RhinoFunctionManager {
+ private static final Logger LOG = Logger.getInstance(RhinoFunctionManager.class);
+
+ private final ThreadLocal threadLocalFunction = new ThreadLocal() {
+ @Override
+ protected FunctionWithScope initialValue() {
+ if (script == null) {
+ synchronized (threadLocalFunction) {
+ if (script == null) {
+ script = compileScript(9);
+ }
+ }
+ }
+ return extractFunctionWithScope(script);
+ }
+ };
+
+ private volatile Script script;
+
+ private final Supplier scriptSourceProvider;
+ private final String functionName;
+
+ public RhinoFunctionManager(@NotNull Supplier scriptSourceProvider,
+ @NotNull String functionName) {
+ this.scriptSourceProvider = scriptSourceProvider;
+ this.functionName = functionName;
+ }
+
+ private Script compileScript(int optimizationLevel) {
+ long startNano = System.nanoTime();
+ Context context = Context.enter();
+ try {
+ context.setOptimizationLevel(optimizationLevel);
+ String scriptSource = scriptSourceProvider.get();
+ return context.compileString(scriptSource, "<" + functionName + " script>", 1, null);
+ }
+ finally {
+ Context.exit();
+ LOG.info(formatMessage(startNano, functionName + " script rhino compilation"));
+ }
+ }
+
+ @NotNull
+ private FunctionWithScope extractFunctionWithScope(@NotNull Script script) {
+ long startNano = System.nanoTime();
+ Context context = Context.enter();
+ try {
+ Scriptable scope = context.initStandardObjects();
+ script.exec(context, scope);
+ Object jsLintObj = scope.get(functionName, scope);
+ if (jsLintObj instanceof Function) {
+ Function jsLint = (Function) jsLintObj;
+ return new FunctionWithScope(jsLint, scope);
+ }
+ else {
+ throw new RuntimeException(functionName + " is undefined or not a function.");
+ }
+ }
+ finally {
+ Context.exit();
+ LOG.info(formatMessage(startNano, functionName + " function extraction"));
+ }
+ }
+
+ private static String formatMessage(long startTimeNano, @NotNull String actionName) {
+ long nanoDuration = System.nanoTime() - startTimeNano;
+ return String.format("[%s] %s took %.2f ms",
+ Thread.currentThread().getName(),
+ actionName,
+ nanoDuration / 1000000.0);
+ }
+
+ @NotNull
+ public FunctionWithScope getFunctionWithScope() {
+ return threadLocalFunction.get();
+ }
+}
diff --git a/js/js.tests/test/org/jetbrains/k2js/test/rhino/RhinoFunctionNativeObjectResultChecker.java b/js/js.tests/test/org/jetbrains/k2js/test/rhino/RhinoFunctionNativeObjectResultChecker.java
index 59eba9537cc..198f6a5cea8 100644
--- a/js/js.tests/test/org/jetbrains/k2js/test/rhino/RhinoFunctionNativeObjectResultChecker.java
+++ b/js/js.tests/test/org/jetbrains/k2js/test/rhino/RhinoFunctionNativeObjectResultChecker.java
@@ -17,6 +17,7 @@
package org.jetbrains.k2js.test.rhino;
import org.jetbrains.annotations.Nullable;
+import org.mozilla.javascript.Context;
import org.mozilla.javascript.NativeJavaObject;
/**
@@ -33,13 +34,13 @@ public class RhinoFunctionNativeObjectResultChecker extends RhinoFunctionResultC
}
@Override
- protected void assertResultValid(Object result) {
+ protected void assertResultValid(Object result, Context context) {
if (result instanceof NativeJavaObject) {
NativeJavaObject nativeJavaObject = (NativeJavaObject) result;
Object unwrap = nativeJavaObject.unwrap();
- super.assertResultValid(unwrap);
+ super.assertResultValid(unwrap, context);
} else {
- super.assertResultValid(result);
+ super.assertResultValid(result, context);
}
}
}
diff --git a/js/js.tests/test/org/jetbrains/k2js/test/rhino/RhinoFunctionResultChecker.java b/js/js.tests/test/org/jetbrains/k2js/test/rhino/RhinoFunctionResultChecker.java
index 55d4f847bf7..cd9886f9707 100644
--- a/js/js.tests/test/org/jetbrains/k2js/test/rhino/RhinoFunctionResultChecker.java
+++ b/js/js.tests/test/org/jetbrains/k2js/test/rhino/RhinoFunctionResultChecker.java
@@ -17,6 +17,8 @@
package org.jetbrains.k2js.test.rhino;
import org.jetbrains.annotations.Nullable;
+import org.jetbrains.k2js.test.config.TestConfig;
+import org.jetbrains.k2js.translate.context.Namer;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Scriptable;
@@ -46,11 +48,12 @@ public class RhinoFunctionResultChecker implements RhinoResultChecker {
public void runChecks(Context context, Scriptable scope) throws Exception {
Object result = evaluateFunction(context, scope);
flushSystemOut(context, scope);
- assertResultValid(result);
+ assertResultValid(result, context);
}
- protected void assertResultValid(Object result) {
- assertEquals("Result of " + namespaceName + "." + functionName + "() is not what expected!", expectedResult, result);
+ protected void assertResultValid(Object result, Context context) {
+ String ecmaVersion = context.getLanguageVersion() == Context.VERSION_1_8 ? "ecma5" : "ecma3";
+ assertEquals("Result of " + namespaceName + "." + functionName + "() is not what expected (" + ecmaVersion + ")!", expectedResult, result);
String report = namespaceName + "." + functionName + "() = " + Context.toString(result);
System.out.println(report);
}
@@ -60,10 +63,14 @@ public class RhinoFunctionResultChecker implements RhinoResultChecker {
}
private String functionCallString() {
- String result = functionName + "()";
+ StringBuilder sb = new StringBuilder();
if (namespaceName != null) {
- result = "Kotlin.defs." + namespaceName + "." + result;
+ sb.append("Kotlin.modules." + TestConfig.TEST_MODULE_NAME);
+ if (namespaceName != Namer.getRootNamespaceName()) {
+ sb.append('.').append(namespaceName);
+ }
+ sb.append('.');
}
- return result;
+ return sb.append(functionName).append("()").toString();
}
}
diff --git a/js/js.tests/test/org/jetbrains/k2js/test/rhino/RhinoUtils.java b/js/js.tests/test/org/jetbrains/k2js/test/rhino/RhinoUtils.java
index bb2dc39d996..46f9abd6c13 100644
--- a/js/js.tests/test/org/jetbrains/k2js/test/rhino/RhinoUtils.java
+++ b/js/js.tests/test/org/jetbrains/k2js/test/rhino/RhinoUtils.java
@@ -17,15 +17,19 @@
package org.jetbrains.k2js.test.rhino;
import closurecompiler.internal.com.google.common.collect.Maps;
+import com.google.common.base.Supplier;
+import com.google.common.collect.Sets;
+import com.intellij.openapi.util.io.FileUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.k2js.config.EcmaVersion;
import org.jetbrains.k2js.facade.K2JSTranslator;
-import org.mozilla.javascript.Context;
-import org.mozilla.javascript.Scriptable;
-import org.mozilla.javascript.ScriptableObject;
+import org.jetbrains.k2js.test.BasicTest;
+import org.mozilla.javascript.*;
+import java.io.File;
import java.io.FileReader;
+import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -37,6 +41,28 @@ import static org.jetbrains.k2js.test.BasicTest.pathToTestFilesRoot;
* @author Pavel Talanov
*/
public final class RhinoUtils {
+ @NotNull
+ private static final Set IGNORED_JSLINT_WARNINGS = Sets.newHashSet();
+
+ static {
+ // todo dart ast bug
+ IGNORED_JSLINT_WARNINGS.add("Unexpected space between '}' and '('.");
+ // don't read JS, use kotlin and idea debugger ;)
+ IGNORED_JSLINT_WARNINGS
+ .add("Wrap an immediate function invocation in parentheses to assist the reader in understanding that the expression is the result of a function, and not the function itself.");
+ }
+
+ @NotNull
+ private static final RhinoFunctionManager functionManager = new RhinoFunctionManager(
+ new Supplier() {
+ @Override
+ public String get() {
+ return fileToString(BasicTest.JSLINT_LIB);
+ }
+ },
+ "JSLINT"
+ );
+
public static final String KOTLIN_JS_LIB_COMMON = pathToTestFilesRoot() + "kotlin_lib.js";
private static final String KOTLIN_JS_LIB_ECMA_3 = pathToTestFilesRoot() + "kotlin_lib_ecma3.js";
@@ -46,6 +72,15 @@ public final class RhinoUtils {
}
+ private static String fileToString(String file) {
+ try {
+ return FileUtil.loadFile(new File(file));
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
private static void runFileWithRhino(@NotNull String inputFile,
@NotNull Context context,
@NotNull Scriptable scope) throws Exception {
@@ -75,6 +110,8 @@ public final class RhinoUtils {
runFileWithRhino(filename, context, scope);
}
checker.runChecks(context, scope);
+
+ lintIt(context, fileNames.get(fileNames.size() - 1));
}
finally {
Context.exit();
@@ -147,4 +184,61 @@ public final class RhinoUtils {
static void flushSystemOut(@NotNull Context context, @NotNull Scriptable scope) {
context.evaluateString(scope, K2JSTranslator.FLUSH_SYSTEM_OUT, "test", 0, null);
}
+
+ private static void lintIt(Context context, String fileName) throws IOException {
+ if (Boolean.valueOf(System.getProperty("test.lint.skip"))) {
+ return;
+ }
+
+ NativeObject options = new NativeObject();
+ // todo fix dart ast?
+ options.defineProperty("white", true, ScriptableObject.READONLY);
+ // vars, http://uxebu.com/blog/2010/04/02/one-var-statement-for-one-variable/
+ options.defineProperty("vars", true, ScriptableObject.READONLY);
+ NativeArray globals = new NativeArray(new Object[] {"Kotlin"});
+ options.defineProperty("predef", globals, ScriptableObject.READONLY);
+
+ Object[] args = {FileUtil.loadFile(new File(fileName)), options};
+ FunctionWithScope functionWithScope = functionManager.getFunctionWithScope();
+ Function function = functionWithScope.getFunction();
+ Scriptable scope = functionWithScope.getScope();
+ Object status = function.call(context, scope, scope, args);
+ Boolean noErrors = (Boolean) Context.jsToJava(status, Boolean.class);
+ if (!noErrors) {
+ Object errors = function.get("errors", scope);
+ if (errors == null) {
+ return;
+ }
+
+ System.out.println(fileName);
+ for (Object errorObj : ((NativeArray) errors)) {
+ if (!(errorObj instanceof NativeObject)) {
+ continue;
+ }
+
+ NativeObject e = (NativeObject) errorObj;
+ int line = toInt(e.get("line"));
+ int character = toInt(e.get("character"));
+ if (line < 0 || character < 0) {
+ continue;
+ }
+ Object reasonObj = e.get("reason");
+ if (reasonObj instanceof String) {
+ String reason = (String) reasonObj;
+ if (IGNORED_JSLINT_WARNINGS.contains(reason)) {
+ continue;
+ }
+
+ System.out.println(line + ":" + character + " " + reason);
+ }
+ }
+ }
+ }
+
+ private static int toInt(Object obj) {
+ if (obj instanceof Number) {
+ return ((Number) obj).intValue();
+ }
+ return -1;
+ }
}
diff --git a/js/js.tests/test/org/jetbrains/k2js/test/semantics/ArrayListTest.java b/js/js.tests/test/org/jetbrains/k2js/test/semantics/ArrayListTest.java
index 4a2f0b6ff1f..8f8551acee7 100644
--- a/js/js.tests/test/org/jetbrains/k2js/test/semantics/ArrayListTest.java
+++ b/js/js.tests/test/org/jetbrains/k2js/test/semantics/ArrayListTest.java
@@ -51,6 +51,10 @@ public final class ArrayListTest extends JavaClassesTest {
fooBoxTest();
}
+ public void testToArray() throws Exception {
+ fooBoxTest();
+ }
+
public void testIndexOOB() throws Exception {
try {
fooBoxTest();
diff --git a/js/js.tests/test/org/jetbrains/k2js/test/semantics/ExtensionFunctionTest.java b/js/js.tests/test/org/jetbrains/k2js/test/semantics/ExtensionFunctionTest.java
index 643c15cb047..c5bbaa32be5 100644
--- a/js/js.tests/test/org/jetbrains/k2js/test/semantics/ExtensionFunctionTest.java
+++ b/js/js.tests/test/org/jetbrains/k2js/test/semantics/ExtensionFunctionTest.java
@@ -74,4 +74,8 @@ public final class ExtensionFunctionTest extends SingleFileTranslationTest {
public void testExtensionPropertyOnClassWithExplicitAndImplicitReceiver() throws Exception {
fooBoxTest();
}
+
+ public void testExtensionFunctionCalledFromFor() throws Exception {
+ fooBoxTest();
+ }
}
diff --git a/js/js.tests/test/org/jetbrains/k2js/test/semantics/MultiFileTest.java b/js/js.tests/test/org/jetbrains/k2js/test/semantics/MultiFileTest.java
index 5dc8927264a..a7e5d11246f 100644
--- a/js/js.tests/test/org/jetbrains/k2js/test/semantics/MultiFileTest.java
+++ b/js/js.tests/test/org/jetbrains/k2js/test/semantics/MultiFileTest.java
@@ -34,4 +34,8 @@ public final class MultiFileTest extends MultipleFilesTranslationTest {
public void testClassesInheritedFromOtherFile() throws Exception {
checkFooBoxIsTrue("classesInheritedFromOtherFile");
}
+
+ public void testClassOfTheSameNameInAnotherPackage() throws Exception {
+ checkFooBoxIsTrue("classOfTheSameNameInAnotherPackage");
+ }
}
diff --git a/js/js.tests/test/org/jetbrains/k2js/test/semantics/ObjectTest.java b/js/js.tests/test/org/jetbrains/k2js/test/semantics/ObjectTest.java
index 51eed910ebd..141fec3b0b6 100644
--- a/js/js.tests/test/org/jetbrains/k2js/test/semantics/ObjectTest.java
+++ b/js/js.tests/test/org/jetbrains/k2js/test/semantics/ObjectTest.java
@@ -16,8 +16,11 @@
package org.jetbrains.k2js.test.semantics;
+import org.jetbrains.k2js.config.EcmaVersion;
import org.jetbrains.k2js.test.SingleFileTranslationTest;
+import java.util.EnumSet;
+
/**
* @author Pavel Talanov
*/
@@ -41,9 +44,13 @@ public final class ObjectTest extends SingleFileTranslationTest {
fooBoxTest();
}
+ public void testObjectInObject() throws Exception {
+ fooBoxTest(EnumSet.noneOf(EcmaVersion.class));
+ }
+
public void testObjectInheritingFromATrait() throws Exception {
fooBoxTest();
}
-}
\ No newline at end of file
+}
diff --git a/js/js.tests/test/org/jetbrains/k2js/test/semantics/PropertyAccessTest.java b/js/js.tests/test/org/jetbrains/k2js/test/semantics/PropertyAccessTest.java
index 1e01ecba839..5e49b03936b 100644
--- a/js/js.tests/test/org/jetbrains/k2js/test/semantics/PropertyAccessTest.java
+++ b/js/js.tests/test/org/jetbrains/k2js/test/semantics/PropertyAccessTest.java
@@ -16,10 +16,14 @@
package org.jetbrains.k2js.test.semantics;
+import com.google.common.collect.Lists;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.k2js.config.EcmaVersion;
import org.jetbrains.k2js.test.SingleFileTranslationTest;
+import org.jetbrains.k2js.test.utils.JsTestUtils;
import java.util.EnumSet;
+import java.util.List;
/**
* @author Pavel Talanov
@@ -79,4 +83,23 @@ public final class PropertyAccessTest extends SingleFileTranslationTest {
public void testInitInstanceProperties() throws Exception {
fooBoxTest(EnumSet.of(EcmaVersion.v5));
}
+
+ public void testEnumerable() throws Exception {
+ fooBoxTest(JsTestUtils.successOnEcmaV5());
+ }
+
+ public void testOverloadedOverriddenFunctionPropertyName() throws Exception {
+ //fooBoxTest(JsTestUtils.successOnEcmaV5());
+ //fooBoxTest();
+ }
+
+ @Override
+ @NotNull
+ protected List additionalJSFiles(@NotNull EcmaVersion ecmaVersion) {
+ List result = Lists.newArrayList(super.additionalJSFiles(ecmaVersion));
+ if (getName().equals("testEnumerable")) {
+ result.add(pathToTestFiles() + "enumerate.js");
+ }
+ return result;
+ }
}
diff --git a/js/js.tests/test/org/jetbrains/k2js/test/semantics/StdLibTestSupport.java b/js/js.tests/test/org/jetbrains/k2js/test/semantics/StdLibTestSupport.java
index 6c2f14ba2ad..1381212893f 100644
--- a/js/js.tests/test/org/jetbrains/k2js/test/semantics/StdLibTestSupport.java
+++ b/js/js.tests/test/org/jetbrains/k2js/test/semantics/StdLibTestSupport.java
@@ -79,7 +79,7 @@ abstract class StdLibTestSupport extends SingleFileTranslationTest {
K2JSCompiler compiler = new K2JSCompiler();
K2JSCompilerArguments arguments = new K2JSCompilerArguments();
arguments.outputFile = getOutputFilePath(getTestName(false) + ".compiler.kt", version);
- arguments.sourceFiles = files;
+ arguments.sourceFiles = files.toArray(new String[files.size()]);
arguments.verbose = true;
System.out.println("Compiling with version: " + version + " to: " + arguments.outputFile);
ExitCode answer = compiler.exec(System.out, arguments);
diff --git a/js/js.tests/test/org/jetbrains/k2js/test/utils/JsTestUtils.java b/js/js.tests/test/org/jetbrains/k2js/test/utils/JsTestUtils.java
index dd103c1a1b0..2f3165fc4e2 100644
--- a/js/js.tests/test/org/jetbrains/k2js/test/utils/JsTestUtils.java
+++ b/js/js.tests/test/org/jetbrains/k2js/test/utils/JsTestUtils.java
@@ -24,6 +24,7 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.EnumSet;
import java.util.List;
/**
@@ -34,6 +35,11 @@ public final class JsTestUtils {
private JsTestUtils() {
}
+ @NotNull
+ public static EnumSet successOnEcmaV5() {
+ return EnumSet.of(EcmaVersion.v5);
+ }
+
@NotNull
public static String convertFileNameToDotJsFile(@NotNull String filename, @NotNull EcmaVersion ecmaVersion) {
String postFix = "_" + ecmaVersion.toString() + ".js";
diff --git a/js/js.translator/lib/rhino-1.7R3-src.jar b/js/js.translator/lib/rhino-1.7R3-src.jar
deleted file mode 100644
index 6baf004ef6b..00000000000
Binary files a/js/js.translator/lib/rhino-1.7R3-src.jar and /dev/null differ
diff --git a/js/js.translator/lib/rhino-1.7R3.jar b/js/js.translator/lib/rhino-1.7R3.jar
deleted file mode 100644
index 878b0d9422b..00000000000
Binary files a/js/js.translator/lib/rhino-1.7R3.jar and /dev/null differ
diff --git a/js/js.translator/lib/rhino-1.7R4-sources.jar b/js/js.translator/lib/rhino-1.7R4-sources.jar
new file mode 100644
index 00000000000..f9691cf8969
Binary files /dev/null and b/js/js.translator/lib/rhino-1.7R4-sources.jar differ
diff --git a/js/js.translator/lib/rhino-1.7R4.jar b/js/js.translator/lib/rhino-1.7R4.jar
new file mode 100644
index 00000000000..6f0dafbbc78
Binary files /dev/null and b/js/js.translator/lib/rhino-1.7R4.jar differ
diff --git a/js/js.translator/src/org/jetbrains/k2js/analyze/AnalyzerFacadeForJS.java b/js/js.translator/src/org/jetbrains/k2js/analyze/AnalyzerFacadeForJS.java
index 3f956e7c2ec..3b5a10dafb1 100644
--- a/js/js.translator/src/org/jetbrains/k2js/analyze/AnalyzerFacadeForJS.java
+++ b/js/js.translator/src/org/jetbrains/k2js/analyze/AnalyzerFacadeForJS.java
@@ -18,7 +18,6 @@ package org.jetbrains.k2js.analyze;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
-import com.google.common.collect.Sets;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NotNull;
@@ -41,10 +40,10 @@ import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
import org.jetbrains.k2js.config.Config;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
-import java.util.Set;
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.isRootNamespace;
@@ -136,7 +135,7 @@ public final class AnalyzerFacadeForJS {
@NotNull
public static Collection withJsLibAdded(@NotNull Collection files, @NotNull Config config) {
- Set allFiles = Sets.newHashSet();
+ Collection allFiles = new ArrayList();
allFiles.addAll(files);
allFiles.addAll(config.getLibFiles());
return allFiles;
diff --git a/js/js.translator/src/org/jetbrains/k2js/config/ClassPathLibraryDefintionsConfig.java b/js/js.translator/src/org/jetbrains/k2js/config/ClassPathLibraryDefintionsConfig.java
index 41133aebb07..5ed0995de7e 100644
--- a/js/js.translator/src/org/jetbrains/k2js/config/ClassPathLibraryDefintionsConfig.java
+++ b/js/js.translator/src/org/jetbrains/k2js/config/ClassPathLibraryDefintionsConfig.java
@@ -16,11 +16,11 @@
package org.jetbrains.k2js.config;
-import org.jetbrains.annotations.NotNull;
import com.intellij.openapi.project.Project;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetFile;
-import java.util.*;
+import java.util.List;
/**
* A Config implementation which is configured with a directory to find the standard library names from
@@ -28,8 +28,8 @@ import java.util.*;
public class ClassPathLibraryDefintionsConfig extends Config {
public static final String META_INF_SERVICES_FILE = "META-INF/services/org.jetbrains.kotlin.js.libraryDefinitions";
- public ClassPathLibraryDefintionsConfig(@NotNull Project project, @NotNull EcmaVersion version) {
- super(project, version);
+ public ClassPathLibraryDefintionsConfig(@NotNull Project project, @NotNull String moduleId, @NotNull EcmaVersion version) {
+ super(project, moduleId, version);
}
@NotNull
diff --git a/js/js.translator/src/org/jetbrains/k2js/config/Config.java b/js/js.translator/src/org/jetbrains/k2js/config/Config.java
index fd7c43ae621..43e21dcd01c 100644
--- a/js/js.translator/src/org/jetbrains/k2js/config/Config.java
+++ b/js/js.translator/src/org/jetbrains/k2js/config/Config.java
@@ -36,7 +36,7 @@ public abstract class Config {
@NotNull
public static Config getEmptyConfig(@NotNull Project project, @NotNull EcmaVersion ecmaVersion) {
- return new Config(project, ecmaVersion) {
+ return new Config(project, "main", ecmaVersion) {
@NotNull
@Override
protected List generateLibFiles() {
@@ -133,9 +133,13 @@ public abstract class Config {
@NotNull
private final EcmaVersion target;
- public Config(@NotNull Project project, @NotNull EcmaVersion ecmaVersion) {
+ @NotNull
+ private final String moduleId;
+
+ public Config(@NotNull Project project, @NotNull String moduleId, @NotNull EcmaVersion ecmaVersion) {
this.project = project;
this.target = ecmaVersion;
+ this.moduleId = moduleId;
}
@NotNull
@@ -148,6 +152,11 @@ public abstract class Config {
return target;
}
+ @NotNull
+ public String getModuleId() {
+ return moduleId;
+ }
+
@NotNull
protected abstract List generateLibFiles();
diff --git a/js/js.translator/src/org/jetbrains/k2js/config/ZippedLibrarySourcesConfig.java b/js/js.translator/src/org/jetbrains/k2js/config/LibrarySourcesConfig.java
similarity index 54%
rename from js/js.translator/src/org/jetbrains/k2js/config/ZippedLibrarySourcesConfig.java
rename to js/js.translator/src/org/jetbrains/k2js/config/LibrarySourcesConfig.java
index 723e0171ba7..bbf31d8dc8a 100644
--- a/js/js.translator/src/org/jetbrains/k2js/config/ZippedLibrarySourcesConfig.java
+++ b/js/js.translator/src/org/jetbrains/k2js/config/LibrarySourcesConfig.java
@@ -18,6 +18,7 @@ package org.jetbrains.k2js.config;
import com.google.common.collect.Lists;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.io.FileUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -27,6 +28,7 @@ import org.jetbrains.k2js.utils.JetFileUtils;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
@@ -36,33 +38,63 @@ import java.util.zip.ZipFile;
/**
* @author Pavel Talanov
*/
-public class ZippedLibrarySourcesConfig extends Config {
- @Nullable
- protected final String pathToLibZip;
+public class LibrarySourcesConfig extends Config {
+ public static final Key EXTERNAL_MODULE_NAME = new Key("externalModule");
+ public static final String UNKNOWN_EXTERNAL_MODULE_NAME = "";
- public ZippedLibrarySourcesConfig(@NotNull Project project, @Nullable String pathToZip, @NotNull EcmaVersion ecmaVersion) {
- super(project, ecmaVersion);
- pathToLibZip = pathToZip;
+ @Nullable
+ private final String[] files;
+
+ public LibrarySourcesConfig(@NotNull Project project,
+ @NotNull String moduleId,
+ @Nullable String[] files,
+ @NotNull EcmaVersion ecmaVersion) {
+ super(project, moduleId, ecmaVersion);
+ this.files = files;
}
@NotNull
@Override
public List generateLibFiles() {
- if (pathToLibZip == null) {
+ if (files == null) {
return Collections.emptyList();
}
- try {
- File file = new File(pathToLibZip);
- ZipFile zipFile = new ZipFile(file);
+
+ List jetFiles = new ArrayList();
+ String moduleName = UNKNOWN_EXTERNAL_MODULE_NAME;
+ for (String path : files) {
+ File file = new File(path);
try {
- return traverseArchive(zipFile);
+ String name = file.getName();
+ if (path.charAt(0) == '@') {
+ moduleName = path.substring(1);
+ continue;
+ }
+
+ if (name.endsWith(".jar") || name.endsWith(".zip")) {
+ jetFiles.addAll(readZip(file));
+ }
+ else {
+ JetFile psiFile = JetFileUtils.createPsiFile(path, FileUtil.loadFile(file), getProject());
+ psiFile.putUserData(EXTERNAL_MODULE_NAME, moduleName);
+ jetFiles.add(psiFile);
+ }
}
- finally {
- zipFile.close();
+ catch (IOException e) {
+ throw new RuntimeException(e);
}
}
- catch (IOException e) {
- return Collections.emptyList();
+
+ return jetFiles;
+ }
+
+ private List readZip(File file) throws IOException {
+ ZipFile zipFile = new ZipFile(file);
+ try {
+ return traverseArchive(zipFile);
+ }
+ finally {
+ zipFile.close();
}
}
@@ -76,6 +108,7 @@ public class ZippedLibrarySourcesConfig extends Config {
InputStream stream = file.getInputStream(entry);
String text = FileUtil.loadTextAndClose(stream);
JetFile jetFile = JetFileUtils.createPsiFile(entry.getName(), text, getProject());
+ jetFile.putUserData(EXTERNAL_MODULE_NAME, UNKNOWN_EXTERNAL_MODULE_NAME);
result.add(jetFile);
}
}
diff --git a/js/js.translator/src/org/jetbrains/k2js/facade/K2JSTranslator.java b/js/js.translator/src/org/jetbrains/k2js/facade/K2JSTranslator.java
index eac933e6357..88b6a423dcc 100644
--- a/js/js.translator/src/org/jetbrains/k2js/facade/K2JSTranslator.java
+++ b/js/js.translator/src/org/jetbrains/k2js/facade/K2JSTranslator.java
@@ -32,7 +32,6 @@ import org.jetbrains.k2js.utils.JetFileUtils;
import java.io.IOException;
import java.util.Arrays;
-import java.util.Collection;
import java.util.List;
import static org.jetbrains.k2js.facade.FacadeUtils.parseString;
@@ -97,9 +96,7 @@ public final class K2JSTranslator {
throws TranslationException {
JetStandardLibrary.initialize(config.getProject());
BindingContext bindingContext = AnalyzerFacadeForJS.analyzeFilesAndCheckErrors(filesToTranslate, config);
- Collection files = AnalyzerFacadeForJS.withJsLibAdded(filesToTranslate, config);
-
- return Translation.generateAst(bindingContext, Lists.newArrayList(files), mainCallParameters, config.getTarget(), rawStatements);
+ return Translation.generateAst(bindingContext, filesToTranslate, mainCallParameters, config, rawStatements);
}
@NotNull
diff --git a/js/js.translator/src/org/jetbrains/k2js/facade/MainCallParameters.java b/js/js.translator/src/org/jetbrains/k2js/facade/MainCallParameters.java
index d7c5bc8cf73..326d8683868 100644
--- a/js/js.translator/src/org/jetbrains/k2js/facade/MainCallParameters.java
+++ b/js/js.translator/src/org/jetbrains/k2js/facade/MainCallParameters.java
@@ -25,7 +25,6 @@ import java.util.List;
* @author Pavel Talanov
*/
public abstract class MainCallParameters {
-
@NotNull
public static MainCallParameters noCall() {
return new MainCallParameters() {
diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/context/DynamicContext.java b/js/js.translator/src/org/jetbrains/k2js/translate/context/DynamicContext.java
index ed0028287ac..aa1d08c6496 100644
--- a/js/js.translator/src/org/jetbrains/k2js/translate/context/DynamicContext.java
+++ b/js/js.translator/src/org/jetbrains/k2js/translate/context/DynamicContext.java
@@ -53,8 +53,13 @@ public final class DynamicContext {
@NotNull
public TemporaryVariable declareTemporary(@NotNull JsExpression initExpression) {
+ return declareTemporary(initExpression, false);
+ }
+
+ @NotNull
+ public TemporaryVariable declareTemporary(@NotNull JsExpression initExpression, boolean initialize) {
JsName temporaryName = currentScope.declareTemporary();
- JsVars temporaryDeclaration = newVar(temporaryName, /*no init expression in var statement*/ null);
+ JsVars temporaryDeclaration = newVar(temporaryName, initialize ? initExpression : null);
addVarDeclaration(jsBlock(), temporaryDeclaration);
return new TemporaryVariable(temporaryName, initExpression);
}
diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/context/Namer.java b/js/js.translator/src/org/jetbrains/k2js/translate/context/Namer.java
index 52da0995874..871ddbadedd 100644
--- a/js/js.translator/src/org/jetbrains/k2js/translate/context/Namer.java
+++ b/js/js.translator/src/org/jetbrains/k2js/translate/context/Namer.java
@@ -32,14 +32,13 @@ public final class Namer {
private static final String INITIALIZE_METHOD_NAME = "initialize";
private static final String CLASS_OBJECT_NAME = "createClass";
private static final String TRAIT_OBJECT_NAME = "createTrait";
- private static final String NAMESPACE_OBJECT_NAME = "createNamespace";
private static final String OBJECT_OBJECT_NAME = "createObject";
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 SUPER_METHOD_NAME = "super_init";
private static final String KOTLIN_OBJECT_NAME = "Kotlin";
- private static final String ROOT_NAMESPACE = "Root";
+ private static final String ROOT_NAMESPACE = "_";
private static final String RECEIVER_PARAMETER_NAME = "receiver";
private static final String CLASSES_OBJECT_NAME = "classes";
private static final String THROW_NPE_FUN_NAME = "throwNPE";
@@ -112,7 +111,7 @@ public final class Namer {
@NotNull
private final JsName traitName;
@NotNull
- private final JsName namespaceName;
+ private final JsExpression definePackage;
@NotNull
private final JsName objectName;
@@ -122,17 +121,24 @@ public final class Namer {
@NotNull
private final JsPropertyInitializer writablePropertyDescriptorField;
+ @NotNull
+ private final JsPropertyInitializer enumerablePropertyDescriptorField;
+
private Namer(@NotNull JsScope rootScope) {
kotlinName = rootScope.declareName(KOTLIN_OBJECT_NAME);
kotlinScope = new JsScope(rootScope, "Kotlin standard object");
traitName = kotlinScope.declareName(TRAIT_OBJECT_NAME);
- namespaceName = kotlinScope.declareName(NAMESPACE_OBJECT_NAME);
+
+ definePackage = kotlin("definePackage");
+
className = kotlinScope.declareName(CLASS_OBJECT_NAME);
objectName = kotlinScope.declareName(OBJECT_OBJECT_NAME);
isTypeName = kotlinScope.declareName("isType");
- writablePropertyDescriptorField = new JsPropertyInitializer(new JsNameRef("writable"), rootScope.getProgram().getTrueLiteral());
+ JsProgram program = rootScope.getProgram();
+ writablePropertyDescriptorField = new JsPropertyInitializer(program.getStringLiteral("writable"), program.getTrueLiteral());
+ enumerablePropertyDescriptorField = new JsPropertyInitializer(program.getStringLiteral("enumerable"), program.getTrueLiteral());
}
@NotNull
@@ -146,8 +152,8 @@ public final class Namer {
}
@NotNull
- public JsExpression namespaceCreationMethodReference() {
- return kotlin(namespaceName);
+ public JsExpression packageDefinitionMethodReference() {
+ return definePackage;
}
@NotNull
@@ -164,14 +170,17 @@ public final class Namer {
@NotNull
private JsExpression kotlin(@NotNull JsName name) {
- JsNameRef reference = name.makeRef();
- reference.setQualifier(kotlinName.makeRef());
- return reference;
+ return kotlin(name.makeRef());
+ }
+
+ @NotNull
+ public JsExpression kotlin(@NotNull String name) {
+ return kotlin(kotlinScope.declareName(name));
}
@NotNull
private JsExpression kotlin(@NotNull JsExpression reference) {
- setQualifier(reference, kotlinName.makeRef());
+ setQualifier(reference, kotlinObject());
return reference;
}
@@ -190,6 +199,11 @@ public final class Namer {
return writablePropertyDescriptorField;
}
+ @NotNull
+ public JsPropertyInitializer enumerablePropertyDescriptorField() {
+ return enumerablePropertyDescriptorField;
+ }
+
@NotNull
/*package*/ JsScope getKotlinScope() {
return kotlinScope;
diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/context/StaticContext.java b/js/js.translator/src/org/jetbrains/k2js/translate/context/StaticContext.java
index 3027ae32f33..d933bbb2ba0 100644
--- a/js/js.translator/src/org/jetbrains/k2js/translate/context/StaticContext.java
+++ b/js/js.translator/src/org/jetbrains/k2js/translate/context/StaticContext.java
@@ -18,13 +18,17 @@ package org.jetbrains.k2js.translate.context;
import com.google.common.collect.Maps;
import com.google.dart.compiler.backend.js.ast.*;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
+import org.jetbrains.jet.lang.resolve.BindingContextUtils;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
import org.jetbrains.k2js.config.EcmaVersion;
+import org.jetbrains.k2js.config.LibrarySourcesConfig;
import org.jetbrains.k2js.translate.context.generator.Generator;
import org.jetbrains.k2js.translate.context.generator.Rule;
import org.jetbrains.k2js.translate.intrinsic.Intrinsics;
@@ -105,6 +109,11 @@ public final class StaticContext {
return ecmaVersion == EcmaVersion.v5;
}
+ @NotNull
+ public EcmaVersion getEcmaVersion() {
+ return ecmaVersion;
+ }
+
@NotNull
public JsProgram getProgram() {
return program;
@@ -153,6 +162,14 @@ public final class StaticContext {
}
private final class NameGenerator extends Generator {
+ private JsName declareName(DeclarationDescriptor descriptor, String name) {
+ NamingScope scope = getEnclosingScope(descriptor);
+ // ecma 5 property name never declares as obfuscatable:
+ // 1) property cannot be overloaded, so, name collision is not possible
+ // 2) main reason: if property doesn't have any custom accessor, value holder will have the same name as accessor, so, the same name will be declared more than once
+ return isEcma5() ? scope.declareUnobfuscatableName(name) : scope.declareObfuscatableName(name);
+ }
+
public NameGenerator() {
Rule namesForStandardClasses = new Rule() {
@Override
@@ -171,8 +188,16 @@ public final class StaticContext {
if (!(descriptor instanceof NamespaceDescriptor)) {
return null;
}
- String nameForNamespace = getNameForNamespace((NamespaceDescriptor) descriptor);
- return getRootScope().declareUnobfuscatableName(nameForNamespace);
+
+ String name;
+ if (DescriptorUtils.isRootNamespace((NamespaceDescriptor) descriptor)) {
+ name = Namer.getRootNamespaceName();
+ }
+ else {
+ name = descriptor.getName().getName();
+ }
+
+ return getRootScope().declareUnobfuscatableName(name);
}
};
Rule memberDeclarationsInsideParentsScope = new Rule() {
@@ -180,6 +205,9 @@ public final class StaticContext {
@Nullable
public JsName apply(@NotNull DeclarationDescriptor descriptor) {
NamingScope namingScope = getEnclosingScope(descriptor);
+ if (descriptor instanceof ClassDescriptor) {
+ return namingScope.declareUnobfuscatableName(descriptor.getName().getName());
+ }
return namingScope.declareObfuscatableName(descriptor.getName().getName());
}
};
@@ -203,11 +231,9 @@ public final class StaticContext {
boolean isGetter = descriptor instanceof PropertyGetterDescriptor;
PropertyAccessorDescriptor accessorDescriptor = (PropertyAccessorDescriptor) descriptor;
String propertyName = accessorDescriptor.getCorrespondingProperty().getName().getName();
- String accessorName = Namer.getNameForAccessor(propertyName, isGetter, !accessorDescriptor.getReceiverParameter().exists() && isEcma5());
- NamingScope enclosingScope = getEnclosingScope(descriptor);
- return isEcma5()
- ? enclosingScope.declareUnobfuscatableName(accessorName)
- : enclosingScope.declareObfuscatableName(accessorName);
+ String accessorName = Namer.getNameForAccessor(propertyName, isGetter,
+ !accessorDescriptor.getReceiverParameter().exists() && isEcma5());
+ return declareName(descriptor, accessorName);
}
};
@@ -232,19 +258,12 @@ public final class StaticContext {
return null;
}
- //TODO: move somewhere
- NamingScope enclosingScope = getEnclosingScope(descriptor);
- if (isEcma5()) {
- String name = descriptor.getName().getName();
- if (JsDescriptorUtils.isAsPrivate((PropertyDescriptor) descriptor)) {
- name = '_' + name;
- }
+ String name = descriptor.getName().getName();
+ if (!isEcma5() || JsDescriptorUtils.isAsPrivate((PropertyDescriptor) descriptor)) {
+ name = Namer.getKotlinBackingFieldName(name);
+ }
- return enclosingScope.declareUnobfuscatableName(name);
- }
- else {
- return enclosingScope.declareObfuscatableName(Namer.getKotlinBackingFieldName(descriptor.getName().getName()));
- }
+ return declareName(descriptor, name);
}
};
//TODO: hack!
@@ -386,14 +405,50 @@ public final class StaticContext {
Rule namespaceLevelDeclarationsHaveEnclosingNamespacesNamesAsQualifier = new Rule() {
@Override
public JsNameRef apply(@NotNull DeclarationDescriptor descriptor) {
- DeclarationDescriptor containingDeclaration = getContainingDeclaration(descriptor);
- if (!(containingDeclaration instanceof NamespaceDescriptor)) {
+ DeclarationDescriptor containingDescriptor = getContainingDeclaration(descriptor);
+ if (!(containingDescriptor instanceof NamespaceDescriptor)) {
return null;
}
- JsName containingDeclarationName = getNameForDescriptor(containingDeclaration);
- JsNameRef qualifier = containingDeclarationName.makeRef();
- qualifier.setQualifier(getQualifierForDescriptor(containingDeclaration));
- return qualifier;
+
+ final JsNameRef result = new JsNameRef(getNameForDescriptor(containingDescriptor));
+ if (DescriptorUtils.isRootNamespace((NamespaceDescriptor) containingDescriptor)) {
+ return result;
+ }
+
+ JsNameRef qualifier = result;
+ while ((containingDescriptor = getContainingDeclaration(containingDescriptor)) instanceof NamespaceDescriptor &&
+ !DescriptorUtils.isRootNamespace((NamespaceDescriptor) containingDescriptor)) {
+ JsNameRef ref = getNameForDescriptor(containingDescriptor).makeRef();
+ qualifier.setQualifier(ref);
+ qualifier = ref;
+ }
+
+ PsiElement element = BindingContextUtils.descriptorToDeclaration(bindingContext, descriptor);
+ if (element == null && descriptor instanceof PropertyAccessorDescriptor) {
+ element = BindingContextUtils.descriptorToDeclaration(bindingContext, ((PropertyAccessorDescriptor) descriptor)
+ .getCorrespondingProperty());
+ }
+
+ if (element != null) {
+ PsiFile file = element.getContainingFile();
+ String moduleName = file.getUserData(LibrarySourcesConfig.EXTERNAL_MODULE_NAME);
+ if (LibrarySourcesConfig.UNKNOWN_EXTERNAL_MODULE_NAME.equals(moduleName)) {
+ return null;
+ }
+ else if (moduleName != null) {
+ qualifier.setQualifier(new JsArrayAccess(namer.kotlin("modules"), program.getStringLiteral(moduleName)));
+ }
+ else if (result == qualifier && result.getIdent().equals("kotlin")) {
+ // todo WebDemoExamples2Test#testBuilder, package "kotlin" from kotlin/js/js.libraries/src/stdlib/JUMaps.kt must be inlined
+ return qualifier;
+ }
+ }
+
+ if (qualifier.getQualifier() == null) {
+ qualifier.setQualifier(new JsNameRef(Namer.getRootNamespaceName()));
+ }
+
+ return result;
}
};
Rule constructorHaveTheSameQualifierAsTheClass = new Rule() {
@@ -449,10 +504,7 @@ public final class StaticContext {
Rule topLevelNamespaceHaveNoQualifier = new Rule() {
@Override
public Boolean apply(@NotNull DeclarationDescriptor descriptor) {
- if (!(descriptor instanceof NamespaceDescriptor)) {
- return null;
- }
- if (DescriptorUtils.isTopLevelNamespace((NamespaceDescriptor) descriptor)) {
+ if (descriptor instanceof NamespaceDescriptor && DescriptorUtils.isRootNamespace((NamespaceDescriptor) descriptor)) {
return true;
}
return null;
diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/context/TranslationContext.java b/js/js.translator/src/org/jetbrains/k2js/translate/context/TranslationContext.java
index a55a17687e9..26e8f33ec4c 100644
--- a/js/js.translator/src/org/jetbrains/k2js/translate/context/TranslationContext.java
+++ b/js/js.translator/src/org/jetbrains/k2js/translate/context/TranslationContext.java
@@ -24,6 +24,7 @@ import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.resolve.BindingContext;
+import org.jetbrains.k2js.config.EcmaVersion;
import org.jetbrains.k2js.translate.intrinsic.Intrinsics;
import java.util.Map;
@@ -58,6 +59,10 @@ public final class TranslationContext {
return staticContext.isEcma5();
}
+ public boolean isNotEcma3() {
+ return staticContext.getEcmaVersion() != EcmaVersion.v3;
+ }
+
private TranslationContext(@NotNull StaticContext staticContext,
@NotNull DynamicContext dynamicContext,
@NotNull AliasingContext context) {
@@ -152,6 +157,11 @@ public final class TranslationContext {
return dynamicContext.declareTemporary(initExpression);
}
+ @NotNull
+ public TemporaryVariable declareTemporary(@NotNull JsExpression initExpression, boolean initialize) {
+ return dynamicContext.declareTemporary(initExpression, initialize);
+ }
+
@NotNull
public Namer namer() {
return staticContext.getNamer();
diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/declaration/ClassAliasingMap.java b/js/js.translator/src/org/jetbrains/k2js/translate/declaration/ClassAliasingMap.java
new file mode 100644
index 00000000000..c7312044a4b
--- /dev/null
+++ b/js/js.translator/src/org/jetbrains/k2js/translate/declaration/ClassAliasingMap.java
@@ -0,0 +1,10 @@
+package org.jetbrains.k2js.translate.declaration;
+
+import com.google.dart.compiler.backend.js.ast.JsNameRef;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jet.lang.psi.JetClass;
+
+public interface ClassAliasingMap {
+ @Nullable
+ JsNameRef get(JetClass declaration, JetClass referencedDeclaration);
+}
diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/declaration/ClassDeclarationTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/declaration/ClassDeclarationTranslator.java
index 5c90678041e..f00caac0bd9 100644
--- a/js/js.translator/src/org/jetbrains/k2js/translate/declaration/ClassDeclarationTranslator.java
+++ b/js/js.translator/src/org/jetbrains/k2js/translate/declaration/ClassDeclarationTranslator.java
@@ -16,28 +16,29 @@
package org.jetbrains.k2js.translate.declaration;
-import com.google.common.collect.BiMap;
-import com.google.common.collect.HashBiMap;
-import com.google.common.collect.Lists;
import com.google.dart.compiler.backend.js.ast.*;
import com.google.dart.compiler.util.AstUtil;
+import gnu.trove.THashMap;
+import gnu.trove.TLinkable;
+import gnu.trove.TLinkableAdaptor;
+import gnu.trove.TLinkedList;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
-import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
+import org.jetbrains.jet.lang.descriptors.Modality;
import org.jetbrains.jet.lang.psi.JetClass;
import org.jetbrains.k2js.translate.context.Namer;
import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.general.AbstractTranslator;
-import org.jetbrains.k2js.translate.general.Translation;
-import org.jetbrains.k2js.translate.utils.BindingUtils;
-import org.jetbrains.k2js.translate.utils.ClassSortingUtils;
+import org.jetbrains.k2js.translate.utils.JsAstUtils;
import java.util.ArrayList;
import java.util.List;
-import static org.jetbrains.k2js.translate.utils.JsAstUtils.*;
-import static org.jetbrains.k2js.translate.utils.JsDescriptorUtils.getAllClassesDefinedInNamespace;
+import static com.google.dart.compiler.backend.js.ast.JsVars.JsVar;
+import static org.jetbrains.k2js.translate.general.Translation.translateClassDeclaration;
+import static org.jetbrains.k2js.translate.utils.BindingUtils.getClassDescriptor;
+import static org.jetbrains.k2js.translate.utils.JsAstUtils.newBlock;
/**
* @author Pavel Talanov
@@ -45,115 +46,170 @@ import static org.jetbrains.k2js.translate.utils.JsDescriptorUtils.getAllClasses
* Generates a big block where are all the classes(objects representing them) are created.
*/
public final class ClassDeclarationTranslator extends AbstractTranslator {
+ private int localNameCounter;
@NotNull
- private final List descriptors;
- @NotNull
- private final BiMap localToGlobalClassName;
+ private final THashMap openClassToItem = new THashMap();
+
+ private final TLinkedList openList = new TLinkedList();
+ private final List finalList = new ArrayList();
+
@NotNull
private final JsFunction dummyFunction;
- @Nullable
- private JsName declarationsObject = null;
- @Nullable
- private JsStatement declarationsStatement = null;
- public ClassDeclarationTranslator(@NotNull List descriptors,
- @NotNull TranslationContext context) {
+ private final JsName declarationsObject;
+ private final JsVar classesVar;
+
+ public ClassDeclarationTranslator(@NotNull TranslationContext context) {
super(context);
- this.descriptors = descriptors;
- this.localToGlobalClassName = HashBiMap.create();
- this.dummyFunction = new JsFunction(context.jsScope());
+
+ dummyFunction = new JsFunction(context.jsScope());
+ declarationsObject = context().jsScope().declareName(Namer.nameForClassesVariable());
+ classesVar = new JsVars.JsVar(declarationsObject);
+ }
+
+ private final class OpenClassRefProvider implements ClassAliasingMap {
+ @Override
+ @Nullable
+ public JsNameRef get(JetClass declaration, JetClass referencedDeclaration) {
+ ListItem item = openClassToItem.get(declaration);
+ // class declared in library
+ if (item == null) {
+ return null;
+ }
+
+ addAfter(item, openClassToItem.get(referencedDeclaration));
+ return item.label;
+ }
+
+ private void addAfter(@NotNull ListItem item, @NotNull ListItem referencedItem) {
+ for (TLinkable link = item.getNext(); link != null; link = link.getNext()) {
+ if (link == referencedItem) {
+ return;
+ }
+ }
+
+ openList.remove(referencedItem);
+ openList.addBefore((ListItem) item.getNext(), referencedItem);
+ }
+ }
+
+ private final class FinalClassRefProvider implements ClassAliasingMap {
+ @Override
+ public JsNameRef get(JetClass declaration, JetClass referencedDeclaration) {
+ ListItem item = openClassToItem.get(declaration);
+ return item == null ? null : item.label;
+ }
+ }
+
+ private static class ListItem extends TLinkableAdaptor {
+ private final JetClass declaration;
+ private final JsNameRef label;
+
+ private JsExpression translatedDeclaration;
+
+ private ListItem(JetClass declaration, JsNameRef label) {
+ this.declaration = declaration;
+ this.label = label;
+ }
+ }
+
+ @NotNull
+ public JsVars getDeclarationsStatement() {
+ JsVars vars = new JsVars();
+ vars.add(classesVar);
+ return vars;
}
public void generateDeclarations() {
- declarationsObject = context().jsScope().declareName(Namer.nameForClassesVariable());
- assert declarationsObject != null;
- declarationsStatement =
- newVar(declarationsObject, generateDummyFunctionInvocation());
- }
+ JsObjectLiteral valueLiteral = new JsObjectLiteral();
+ JsVars vars = new JsVars();
+ List propertyInitializers = valueLiteral.getPropertyInitializers();
- @NotNull
- public JsName getDeclarationsObjectName() {
- assert declarationsObject != null : "Should run generateDeclarations first";
- return declarationsObject;
- }
+ generateOpenClassDeclarations(vars, propertyInitializers);
+ generateFinalClassDeclarations(vars, propertyInitializers);
- @NotNull
- public JsStatement getDeclarationsStatement() {
- assert declarationsStatement != null : "Should run generateDeclarations first";
- return declarationsStatement;
- }
-
- @NotNull
- private JsInvocation generateDummyFunctionInvocation() {
- List classDeclarations = generateClassDeclarationStatements();
- classDeclarations.add(new JsReturn(generateReturnedObjectLiteral()));
- dummyFunction.setBody(newBlock(classDeclarations));
- return AstUtil.newInvocation(dummyFunction);
- }
-
- @NotNull
- private JsObjectLiteral generateReturnedObjectLiteral() {
- JsObjectLiteral returnedValueLiteral = new JsObjectLiteral();
- for (JsName localName : localToGlobalClassName.keySet()) {
- returnedValueLiteral.getPropertyInitializers().add(classEntry(localName));
+ if (vars.isEmpty()) {
+ classesVar.setInitExpr(valueLiteral);
+ return;
}
- return returnedValueLiteral;
+
+ List result = new ArrayList();
+ result.add(vars);
+ result.add(new JsReturn(valueLiteral));
+ dummyFunction.setBody(newBlock(result));
+ classesVar.setInitExpr(AstUtil.newInvocation(dummyFunction));
}
- @NotNull
- private JsPropertyInitializer classEntry(@NotNull JsName localName) {
- return new JsPropertyInitializer(localToGlobalClassName.get(localName).makeRef(), localName.makeRef());
- }
-
- @NotNull
- private List generateClassDeclarationStatements() {
- List classDeclarations = new ArrayList();
- for (JetClass jetClass : getClassDeclarations()) {
- classDeclarations.add(generateDeclaration(jetClass));
+ private void generateOpenClassDeclarations(@NotNull JsVars vars, @NotNull List propertyInitializers) {
+ ClassAliasingMap classAliasingMap = new OpenClassRefProvider();
+ // first pass: set up list order
+ for (ListItem item : openList) {
+ item.translatedDeclaration = translateClassDeclaration(item.declaration, classAliasingMap, context());
}
- return classDeclarations;
- }
-
-
- @NotNull
- private List getClassDeclarations() {
- List classes = new ArrayList();
- for (ClassDescriptor classDescriptor : descriptors) {
- classes.add(BindingUtils.getClassForDescriptor(bindingContext(), classDescriptor));
+ // second pass: generate
+ for (ListItem item : openList) {
+ generate(item, propertyInitializers, item.translatedDeclaration, vars);
}
- return ClassSortingUtils.sortUsingInheritanceOrder(classes, bindingContext());
}
- @NotNull
- private JsStatement generateDeclaration(@NotNull JetClass declaration) {
- JsName localClassName = generateLocalAlias(declaration);
- JsExpression classDeclarationExpression =
- Translation.translateClassDeclaration(declaration, localToGlobalClassName.inverse(), context());
- return newVar(localClassName, classDeclarationExpression);
- }
-
- @NotNull
- private JsName generateLocalAlias(@NotNull JetClass declaration) {
- JsName globalClassName = context().getNameForElement(declaration);
- JsName localAlias = dummyFunction.getScope().declareTemporary();
- localToGlobalClassName.put(localAlias, globalClassName);
- return localAlias;
- }
-
- @NotNull
- public List classDeclarationsForNamespace(@NotNull NamespaceDescriptor namespaceDescriptor) {
- List result = Lists.newArrayList();
- for (ClassDescriptor classDescriptor : getAllClassesDefinedInNamespace(namespaceDescriptor)) {
- result.add(getClassNameToClassObject(classDescriptor));
+ private void generateFinalClassDeclarations(@NotNull JsVars vars, @NotNull List propertyInitializers) {
+ ClassAliasingMap classAliasingMap = new FinalClassRefProvider();
+ for (ListItem item : finalList) {
+ generate(item, propertyInitializers, translateClassDeclaration(item.declaration, classAliasingMap, context()), vars);
}
- return result;
+ }
+
+ private static void generate(@NotNull ListItem item,
+ @NotNull List propertyInitializers,
+ @NotNull JsExpression definition,
+ @NotNull JsVars vars) {
+ JsExpression value;
+ if (item.label.getName() == null) {
+ value = definition;
+ }
+ else {
+ assert item.label.getName() != null;
+ vars.add(new JsVar(item.label.getName(), definition));
+ value = item.label;
+ }
+
+ propertyInitializers.add(new JsPropertyInitializer(item.label, value));
}
@NotNull
- private JsPropertyInitializer getClassNameToClassObject(@NotNull ClassDescriptor classDescriptor) {
- JsName className = context().getNameForDescriptor(classDescriptor);
- JsNameRef alreadyDefinedClassReference = qualified(className, getDeclarationsObjectName().makeRef());
- return new JsPropertyInitializer(className.makeRef(), alreadyDefinedClassReference);
+ public JsPropertyInitializer translateAndGetClassNameToClassObject(@NotNull JetClass declaration) {
+ ClassDescriptor descriptor = getClassDescriptor(context().bindingContext(), declaration);
+
+ JsNameRef labelRef;
+ String label = 'c' + Integer.toString(localNameCounter++, 36);
+ boolean isFinal = descriptor.getModality() == Modality.FINAL;
+ if (isFinal) {
+ labelRef = new JsNameRef(label);
+ }
+ else {
+ labelRef = dummyFunction.getScope().declareName(label).makeRef();
+ }
+
+ ListItem item = new ListItem(declaration, labelRef);
+ if (isFinal) {
+ finalList.add(item);
+ }
+ else {
+ openList.add(item);
+ openClassToItem.put(declaration, item);
+ }
+
+ JsNameRef qualifiedLabelRef = new JsNameRef(labelRef.getIdent());
+ qualifiedLabelRef.setQualifier(declarationsObject.makeRef());
+ JsExpression value;
+ if (context().isEcma5()) {
+ value = JsAstUtils.createDataDescriptor(qualifiedLabelRef, false, context());
+ }
+ else {
+ value = qualifiedLabelRef;
+ }
+
+ return new JsPropertyInitializer(context().program().getStringLiteral(descriptor.getName().getName()), value);
}
}
diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/declaration/ClassTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/declaration/ClassTranslator.java
index c5ab497e195..0b3167d85af 100644
--- a/js/js.translator/src/org/jetbrains/k2js/translate/declaration/ClassTranslator.java
+++ b/js/js.translator/src/org/jetbrains/k2js/translate/declaration/ClassTranslator.java
@@ -23,6 +23,7 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.ClassKind;
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
+import org.jetbrains.jet.lang.psi.JetClass;
import org.jetbrains.jet.lang.psi.JetClassOrObject;
import org.jetbrains.jet.lang.psi.JetObjectLiteralExpression;
import org.jetbrains.jet.lang.psi.JetParameter;
@@ -31,12 +32,11 @@ import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.general.AbstractTranslator;
import org.jetbrains.k2js.translate.general.Translation;
import org.jetbrains.k2js.translate.initializer.InitializerUtils;
+import org.jetbrains.k2js.translate.utils.BindingUtils;
import org.jetbrains.k2js.translate.utils.JsAstUtils;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.List;
-import java.util.Map;
import static com.google.dart.compiler.util.AstUtil.newSequence;
import static org.jetbrains.k2js.translate.utils.BindingUtils.getClassDescriptor;
@@ -64,8 +64,8 @@ public final class ClassTranslator extends AbstractTranslator {
@NotNull
public static JsExpression generateClassCreationExpression(@NotNull JetClassOrObject classDeclaration,
- @NotNull Map aliasingMap,
- @NotNull TranslationContext context) {
+ @NotNull ClassAliasingMap aliasingMap,
+ @NotNull TranslationContext context) {
return (new ClassTranslator(classDeclaration, aliasingMap, context)).translateClassOrObjectCreation();
}
@@ -73,13 +73,13 @@ public final class ClassTranslator extends AbstractTranslator {
public static JsExpression generateClassCreationExpression(@NotNull JetClassOrObject classDeclaration,
@NotNull TranslationContext context) {
- return (new ClassTranslator(classDeclaration, Collections.emptyMap(), context)).translateClassOrObjectCreation();
+ return (new ClassTranslator(classDeclaration, null, context)).translateClassOrObjectCreation();
}
@NotNull
public static JsExpression generateObjectLiteralExpression(@NotNull JetObjectLiteralExpression objectLiteralExpression,
@NotNull TranslationContext context) {
- return (new ClassTranslator(objectLiteralExpression.getObjectDeclaration(), Collections.emptyMap(), context))
+ return (new ClassTranslator(objectLiteralExpression.getObjectDeclaration(), null, context))
.translateObjectLiteralExpression();
}
@@ -95,12 +95,12 @@ public final class ClassTranslator extends AbstractTranslator {
@NotNull
private final ClassDescriptor descriptor;
- @NotNull
- private final Map aliasingMap;
+ @Nullable
+ private final ClassAliasingMap aliasingMap;
private ClassTranslator(@NotNull JetClassOrObject classDeclaration,
- @NotNull Map aliasingMap,
- @NotNull TranslationContext context) {
+ @Nullable ClassAliasingMap aliasingMap,
+ @NotNull TranslationContext context) {
super(context.newDeclaration(classDeclaration));
this.aliasingMap = aliasingMap;
this.descriptor = getClassDescriptor(context.bindingContext(), classDeclaration);
@@ -160,7 +160,7 @@ public final class ClassTranslator extends AbstractTranslator {
if (!isTrait()) {
JsFunction initializer = Translation.generateClassInitializerMethod(classDeclaration, classDeclarationContext);
if (context().isEcma5()) {
- jsClassDeclaration.getArguments().add(isObject() ? initializer : JsAstUtils.encloseFunction(initializer));
+ jsClassDeclaration.getArguments().add(initializer.getName() == null ? initializer : JsAstUtils.encloseFunction(initializer));
}
else {
propertyList.add(InitializerUtils.generateInitializeMethod(initializer));
@@ -209,8 +209,7 @@ public final class ClassTranslator extends AbstractTranslator {
private void addTraits(@NotNull List superclassReferences,
@NotNull List superclassDescriptors) {
- for (ClassDescriptor superClassDescriptor :
- superclassDescriptors) {
+ for (ClassDescriptor superClassDescriptor : superclassDescriptors) {
assert (superClassDescriptor.getKind() == ClassKind.TRAIT) : "Only traits are expected here";
superclassReferences.add(getClassReference(superClassDescriptor));
}
@@ -227,12 +226,16 @@ public final class ClassTranslator extends AbstractTranslator {
@NotNull
private JsExpression getClassReference(@NotNull ClassDescriptor superClassDescriptor) {
- //NOTE: aliasing here is needed for the declaration generation step
- JsName name = context().getNameForDescriptor(superClassDescriptor);
- JsName alias = aliasingMap.get(name);
- if (alias != null) {
- return alias.makeRef();
+ // aliasing here is needed for the declaration generation step
+ if (aliasingMap != null) {
+ JsNameRef name = aliasingMap.get(BindingUtils.getClassForDescriptor(bindingContext(), superClassDescriptor),
+ (JetClass) classDeclaration);
+ if (name != null) {
+ return name;
+ }
}
+
+ // from library
return getQualifiedReference(context(), superClassDescriptor);
}
diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/declaration/DeclarationBodyVisitor.java b/js/js.translator/src/org/jetbrains/k2js/translate/declaration/DeclarationBodyVisitor.java
index 683b7427ce1..c7e533db00e 100644
--- a/js/js.translator/src/org/jetbrains/k2js/translate/declaration/DeclarationBodyVisitor.java
+++ b/js/js.translator/src/org/jetbrains/k2js/translate/declaration/DeclarationBodyVisitor.java
@@ -19,6 +19,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.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
@@ -39,6 +40,17 @@ import static org.jetbrains.k2js.translate.utils.BindingUtils.*;
* @author Pavel Talanov
*/
public final class DeclarationBodyVisitor extends TranslatorVisitor> {
+ @Nullable
+ private final ClassDeclarationTranslator classDeclarationTranslator;
+
+ public DeclarationBodyVisitor() {
+ classDeclarationTranslator = null;
+ }
+
+ public DeclarationBodyVisitor(ClassDeclarationTranslator classDeclarationTranslator) {
+ this.classDeclarationTranslator = classDeclarationTranslator;
+ }
+
@NotNull
public List traverseClass(@NotNull JetClassOrObject jetClass,
@NotNull TranslationContext context) {
@@ -51,7 +63,7 @@ public final class DeclarationBodyVisitor extends TranslatorVisitor traverseNamespace(@NotNull NamespaceDescriptor namespace,
- @NotNull TranslationContext context) {
+ @NotNull TranslationContext context) {
List properties = new ArrayList();
for (JetDeclaration declaration : getDeclarationsForNamespace(context.bindingContext(), namespace)) {
properties.addAll(declaration.accept(this, context));
@@ -62,7 +74,11 @@ public final class DeclarationBodyVisitor extends TranslatorVisitor visitClass(@NotNull JetClass expression, @NotNull TranslationContext context) {
- return Collections.emptyList();
+ if (classDeclarationTranslator == null) {
+ return Collections.emptyList();
+ }
+
+ return Collections.singletonList(classDeclarationTranslator.translateAndGetClassNameToClassObject(expression));
}
@Override
@@ -71,10 +87,9 @@ public final class DeclarationBodyVisitor extends TranslatorVisitor getAllClasses() {
- List result = Lists.newArrayList();
- for (NamespaceDescriptor namespaceDescriptor : namespaceDescriptors) {
- result.addAll(getAllClassesDefinedInNamespace(namespaceDescriptor));
- }
- return result;
+ classDeclarationTranslator = new ClassDeclarationTranslator(context);
}
@NotNull
private List translate() {
- List result = classesDeclarations();
- result.addAll(namespacesDeclarations());
- return result;
- }
-
- @NotNull
- private List classesDeclarations() {
- List result = Lists.newArrayList();
- classDeclarationTranslator.generateDeclarations();
+ List result = new ArrayList();
result.add(classDeclarationTranslator.getDeclarationsStatement());
+ namespacesDeclarations(result);
+ classDeclarationTranslator.generateDeclarations();
return result;
}
- @NotNull
- private List namespacesDeclarations() {
- List result = Lists.newArrayList();
+ private void namespacesDeclarations(List statements) {
List namespaceTranslators = getTranslatorsForNonEmptyNamespaces();
- result.addAll(declarationStatements(namespaceTranslators, context()));
- result.addAll(initializeStatements(namespaceTranslators));
- return result;
+ declarationStatements(namespaceTranslators, statements);
+ initializeStatements(namespaceTranslators, statements);
}
@NotNull
@@ -102,34 +83,31 @@ public final class NamespaceDeclarationTranslator extends AbstractTranslator {
return namespaceTranslators;
}
- @NotNull
- private static List declarationStatements(@NotNull List namespaceTranslators, TranslationContext context) {
- List result = Lists.newArrayList();
-
- JsNameRef defs = JsAstUtils.qualified(context.jsScope().declareName("defs"), context.namer().kotlinObject());
- for (NamespaceTranslator translator : namespaceTranslators) {
- JsVars vars = translator.getDeclarationAsVar();
-
- JsVars.JsVar var = vars.iterator().next();
- JsNameRef ref = new JsNameRef(var.getName());
- ref.setQualifier(defs);
-
- result.add(vars);
- result.add(JsAstUtils.assignment(ref, new JsNameRef(var.getName())).makeStmt());
+ private void declarationStatements(@NotNull List namespaceTranslators,
+ @NotNull List statements) {
+ JsObjectLiteral objectLiteral = new JsObjectLiteral();
+ JsNameRef packageMapNameRef = context().jsScope().declareName("_").makeRef();
+ JsExpression packageMapValue;
+ if (context().isNotEcma3()) {
+ packageMapValue = AstUtil.newInvocation(JsAstUtils.CREATE_OBJECT, context().program().getNullLiteral(), objectLiteral);
+ }
+ else {
+ packageMapValue = objectLiteral;
+ }
+ statements.add(JsAstUtils.newVar(packageMapNameRef.getName(), packageMapValue));
+
+ for (NamespaceTranslator translator : namespaceTranslators) {
+ translator.addNamespaceDeclaration(objectLiteral.getPropertyInitializers());
}
- return result;
}
- @NotNull
- private List initializeStatements(@NotNull List namespaceTranslators) {
- List result = Lists.newArrayList();
- for (NamespaceDescriptor descriptor : filterNonEmptyNamespaces(namespaceDescriptors)) {
- JsNameRef initializeMethodReference = Namer.initializeMethodReference();
- JsNameRef fqNamespaceNameRef = TranslationUtils.getQualifiedReference(context(), descriptor);
- setQualifier(initializeMethodReference, fqNamespaceNameRef);
- result.add(AstUtil.newInvocation(initializeMethodReference).makeStmt());
+ private static void initializeStatements(@NotNull List namespaceTranslators,
+ @NotNull List statements) {
+ for (NamespaceTranslator translator : namespaceTranslators) {
+ for (JsExpression expression : translator.getInitializers()) {
+ statements.add(expression.makeStmt());
+ }
}
- return result;
}
@NotNull
@@ -144,10 +122,10 @@ public final class NamespaceDeclarationTranslator extends AbstractTranslator {
}
@NotNull
- private static List filterNonEmptyNamespaces(@NotNull List namespaceDescriptors) {
+ private List filterNonEmptyNamespaces(@NotNull List namespaceDescriptors) {
List result = Lists.newArrayList();
for (NamespaceDescriptor descriptor : namespaceDescriptors) {
- if (!JsDescriptorUtils.isNamespaceEmpty(descriptor)) {
+ if (!JsDescriptorUtils.isNamespaceEmpty(descriptor, context().bindingContext())) {
result.add(descriptor);
}
}
diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/declaration/NamespaceTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/declaration/NamespaceTranslator.java
index 3149932a5ec..6a92dd3340b 100644
--- a/js/js.translator/src/org/jetbrains/k2js/translate/declaration/NamespaceTranslator.java
+++ b/js/js.translator/src/org/jetbrains/k2js/translate/declaration/NamespaceTranslator.java
@@ -25,14 +25,14 @@ import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.general.AbstractTranslator;
import org.jetbrains.k2js.translate.general.Translation;
-import org.jetbrains.k2js.translate.initializer.InitializerUtils;
+import org.jetbrains.k2js.translate.utils.JsAstUtils;
import org.jetbrains.k2js.translate.utils.JsDescriptorUtils;
+import org.jetbrains.k2js.translate.utils.TranslationUtils;
import java.util.ArrayList;
import java.util.List;
import static org.jetbrains.k2js.translate.utils.JsAstUtils.newObjectLiteral;
-import static org.jetbrains.k2js.translate.utils.JsAstUtils.newVar;
/**
* @author Pavel.Talanov
@@ -48,6 +48,9 @@ public final class NamespaceTranslator extends AbstractTranslator {
@NotNull
private final ClassDeclarationTranslator classDeclarationTranslator;
+ @NotNull
+ private final List initializers = new ArrayList();
+
/*package*/ NamespaceTranslator(@NotNull NamespaceDescriptor descriptor,
@NotNull ClassDeclarationTranslator classDeclarationTranslator,
@NotNull TranslationContext context) {
@@ -57,82 +60,81 @@ public final class NamespaceTranslator extends AbstractTranslator {
this.classDeclarationTranslator = classDeclarationTranslator;
}
-
@NotNull
- public JsVars getDeclarationAsVar() {
- return newVar(namespaceName, getNamespaceDeclaration());
+ public List getInitializers() {
+ return initializers;
}
@NotNull
public JsPropertyInitializer getDeclarationAsInitializer() {
+ addNamespaceInitializer();
return new JsPropertyInitializer(namespaceName.makeRef(), getNamespaceDeclaration());
}
+ public void addNamespaceDeclaration(List list) {
+ addNamespaceInitializer();
+
+ if (DescriptorUtils.isRootNamespace(descriptor)) {
+ list.addAll(getFunctionsAndClasses());
+ return;
+ }
+
+ JsExpression value = getNamespaceDeclaration();
+ if (context().isNotEcma3()) {
+ value = JsAstUtils.createDataDescriptor(value, false, context());
+ }
+
+ list.add(new JsPropertyInitializer(namespaceName.makeRef(), value));
+ }
+
@NotNull
private JsInvocation getNamespaceDeclaration() {
JsInvocation namespaceDeclaration = namespaceCreateMethodInvocation();
- addNamespaceInitalizersAndProperties(namespaceDeclaration);
- namespaceDeclaration.getArguments().add(getClassesAndNestedNamespaces());
+ addIfNeed(getFunctionsAndClasses(), namespaceDeclaration.getArguments());
+ addIfNeed(getNestedNamespaceDeclarations(), namespaceDeclaration.getArguments());
return namespaceDeclaration;
}
- private void addNamespaceInitalizersAndProperties(@NotNull JsInvocation namespaceDeclaration) {
+ private void addNamespaceInitializer() {
JsFunction initializer = Translation.generateNamespaceInitializerMethod(descriptor, context());
- List properties = new DeclarationBodyVisitor().traverseNamespace(descriptor, context());
- if (context().isEcma5()) {
- addEcma5InitializersAndProperties(namespaceDeclaration, initializer, properties);
- }
- else {
- addEcma3InitializersAndProperties(namespaceDeclaration, initializer, properties);
+ if (!initializer.getBody().getStatements().isEmpty()) {
+ JsNameRef call = new JsNameRef("call");
+ call.setQualifier(initializer);
+ JsInvocation invocation = new JsInvocation();
+ invocation.setQualifier(call);
+ invocation.getArguments().add(TranslationUtils.getQualifiedReference(context(), descriptor));
+ initializers.add(invocation);
}
}
- private static void addEcma3InitializersAndProperties(@NotNull JsInvocation namespaceDeclaration,
- @NotNull JsFunction initializer,
- @NotNull List properties) {
- List propertyList = new ArrayList();
- 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 properties) {
- namespaceDeclaration.getArguments().add(initializer);
- namespaceDeclaration.getArguments().add(newObjectLiteral(properties));
+ private List getFunctionsAndClasses() {
+ return new DeclarationBodyVisitor(classDeclarationTranslator).traverseNamespace(descriptor, context());
}
@NotNull
private JsInvocation namespaceCreateMethodInvocation() {
- return AstUtil.newInvocation(context().namer().namespaceCreationMethodReference());
+ return AstUtil.newInvocation(context().namer().packageDefinitionMethodReference());
}
- @NotNull
- private JsObjectLiteral getClassesAndNestedNamespaces() {
- JsObjectLiteral classesAndNestedNamespaces = new JsObjectLiteral();
- classesAndNestedNamespaces.getPropertyInitializers()
- .addAll(getClassesDefined());
- classesAndNestedNamespaces.getPropertyInitializers()
- .addAll(getNestedNamespaceDeclarations());
- return classesAndNestedNamespaces;
- }
-
- @NotNull
- private List getClassesDefined() {
- return classDeclarationTranslator.classDeclarationsForNamespace(descriptor);
+ private void addIfNeed(@NotNull List declarations, @NotNull List expressions) {
+ // ecma5 expects strict number of arguments, but ecma3 doesn't
+ if (!declarations.isEmpty()) {
+ expressions.add(newObjectLiteral(declarations));
+ }
+ else if (context().isNotEcma3()) {
+ expressions.add(context().program().getNullLiteral());
+ }
}
@NotNull
private List getNestedNamespaceDeclarations() {
- if (DescriptorUtils.isRootNamespace(descriptor)) {
- return Lists.newArrayList();
- }
List result = Lists.newArrayList();
- List nestedNamespaces = JsDescriptorUtils.getNestedNamespaces(descriptor);
+ List nestedNamespaces = JsDescriptorUtils.getNestedNamespaces(descriptor, context().bindingContext());
for (NamespaceDescriptor nestedNamespace : nestedNamespaces) {
NamespaceTranslator nestedNamespaceTranslator = new NamespaceTranslator(nestedNamespace, classDeclarationTranslator, context());
result.add(nestedNamespaceTranslator.getDeclarationAsInitializer());
+
+ initializers.addAll(nestedNamespaceTranslator.getInitializers());
}
return result;
}
diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/expression/WhenTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/expression/WhenTranslator.java
index 3ae42af63d9..06c016582a7 100644
--- a/js/js.translator/src/org/jetbrains/k2js/translate/expression/WhenTranslator.java
+++ b/js/js.translator/src/org/jetbrains/k2js/translate/expression/WhenTranslator.java
@@ -116,12 +116,11 @@ public final class WhenTranslator extends AbstractTranslator {
return statementToExecute;
}
JsExpression condition = translateConditions(entry);
- return new JsIf(condition, addDummyBreak(statementToExecute), null);
+ return new JsIf(condition, addDummyBreakIfNeed(statementToExecute), null);
}
@NotNull
JsStatement withReturnValueCaptured(@NotNull JsNode node) {
-
return convertToStatement(LastExpressionMutator.mutateLastExpression(node,
new AssignToExpressionMutator(result.reference())));
}
@@ -172,8 +171,8 @@ public final class WhenTranslator extends AbstractTranslator {
}
@NotNull
- private static JsBlock addDummyBreak(@NotNull JsStatement statement) {
- return AstUtil.newBlock(statement, new JsBreak());
+ private static JsStatement addDummyBreakIfNeed(@NotNull JsStatement statement) {
+ return statement instanceof JsReturn ? statement : AstUtil.newBlock(statement, new JsBreak());
}
@NotNull
diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/expression/foreach/IteratorForTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/expression/foreach/IteratorForTranslator.java
index d6e28144f7c..8f70fdc5e87 100644
--- a/js/js.translator/src/org/jetbrains/k2js/translate/expression/foreach/IteratorForTranslator.java
+++ b/js/js.translator/src/org/jetbrains/k2js/translate/expression/foreach/IteratorForTranslator.java
@@ -31,9 +31,7 @@ import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.general.Translation;
import org.jetbrains.k2js.translate.reference.CallBuilder;
-import static org.jetbrains.k2js.translate.utils.BindingUtils.getHasNextCallable;
-import static org.jetbrains.k2js.translate.utils.BindingUtils.getIteratorFunction;
-import static org.jetbrains.k2js.translate.utils.BindingUtils.getNextFunction;
+import static org.jetbrains.k2js.translate.utils.BindingUtils.*;
import static org.jetbrains.k2js.translate.utils.JsAstUtils.convertToBlock;
import static org.jetbrains.k2js.translate.utils.JsAstUtils.newVar;
import static org.jetbrains.k2js.translate.utils.PsiUtils.getLoopBody;
@@ -104,7 +102,7 @@ public final class IteratorForTranslator extends ForTranslator {
// kotlin iterator define hasNext as property, but java util as function, our js side expects as property
private static boolean isJavaUtilIterator(CallableDescriptor descriptor) {
- final DeclarationDescriptor declaration = descriptor.getContainingDeclaration();
+ DeclarationDescriptor declaration = descriptor.getContainingDeclaration();
return declaration != null && declaration.getName().getName().equals("Iterator");
}
diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/general/Translation.java b/js/js.translator/src/org/jetbrains/k2js/translate/general/Translation.java
index f784f264771..ea77ec00559 100644
--- a/js/js.translator/src/org/jetbrains/k2js/translate/general/Translation.java
+++ b/js/js.translator/src/org/jetbrains/k2js/translate/general/Translation.java
@@ -19,8 +19,10 @@ 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.util.text.StringUtil;
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;
@@ -28,7 +30,7 @@ import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
-import org.jetbrains.k2js.config.EcmaVersion;
+import org.jetbrains.k2js.config.Config;
import org.jetbrains.k2js.facade.MainCallParameters;
import org.jetbrains.k2js.facade.exceptions.MainFunctionNotFoundException;
import org.jetbrains.k2js.facade.exceptions.TranslationException;
@@ -36,6 +38,7 @@ import org.jetbrains.k2js.facade.exceptions.TranslationInternalException;
import org.jetbrains.k2js.facade.exceptions.UnsupportedFeatureException;
import org.jetbrains.k2js.translate.context.StaticContext;
import org.jetbrains.k2js.translate.context.TranslationContext;
+import org.jetbrains.k2js.translate.declaration.ClassAliasingMap;
import org.jetbrains.k2js.translate.declaration.ClassTranslator;
import org.jetbrains.k2js.translate.declaration.NamespaceDeclarationTranslator;
import org.jetbrains.k2js.translate.expression.ExpressionVisitor;
@@ -52,7 +55,6 @@ import org.jetbrains.k2js.translate.utils.dangerous.DangerousTranslator;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
-import java.util.Map;
import static org.jetbrains.jet.plugin.JetMainDetector.getMainFunction;
import static org.jetbrains.k2js.translate.utils.BindingUtils.getFunctionDescriptor;
@@ -83,9 +85,9 @@ public final class Translation {
@NotNull
public static JsExpression translateClassDeclaration(@NotNull JetClass classDeclaration,
- @NotNull Map aliasingMap,
+ @NotNull ClassAliasingMap classAliasingMap,
@NotNull TranslationContext context) {
- return ClassTranslator.generateClassCreationExpression(classDeclaration, aliasingMap, context);
+ return ClassTranslator.generateClassCreationExpression(classDeclaration, classAliasingMap, context);
}
@NotNull
@@ -148,10 +150,10 @@ public final class Translation {
@NotNull
public static JsProgram generateAst(@NotNull BindingContext bindingContext,
@NotNull List files, @NotNull MainCallParameters mainCallParameters,
- @NotNull EcmaVersion ecmaVersion, List rawStatements)
+ @NotNull Config config, List rawStatements)
throws TranslationException {
try {
- return doGenerateAst(bindingContext, files, mainCallParameters, ecmaVersion, rawStatements);
+ return doGenerateAst(bindingContext, files, mainCallParameters, config, rawStatements);
}
catch (UnsupportedOperationException e) {
throw new UnsupportedFeatureException("Unsupported feature used.", e);
@@ -164,10 +166,10 @@ public final class Translation {
@NotNull
private static JsProgram doGenerateAst(@NotNull BindingContext bindingContext, @NotNull List files,
@NotNull MainCallParameters mainCallParameters,
- @NotNull EcmaVersion ecmaVersion, List rawStatements) throws MainFunctionNotFoundException {
+ @NotNull Config config, List rawStatements) throws MainFunctionNotFoundException {
//TODO: move some of the code somewhere
JetStandardLibrary standardLibrary = JetStandardLibrary.getInstance();
- StaticContext staticContext = StaticContext.generateStaticContext(standardLibrary, bindingContext, ecmaVersion);
+ StaticContext staticContext = StaticContext.generateStaticContext(standardLibrary, bindingContext, config.getTarget());
JsProgram program = staticContext.getProgram();
JsBlock block = program.getGlobalBlock();
@@ -177,8 +179,13 @@ public final class Translation {
TranslationContext context = TranslationContext.rootContext(staticContext);
statements.addAll(translateFiles(files, context));
+ defineModule(statements, context, config);
+
if (mainCallParameters.shouldBeGenerated()) {
- statements.add(generateCallToMain(context, files, mainCallParameters.arguments()));
+ JsStatement statement = generateCallToMain(context, files, mainCallParameters.arguments());
+ if (statement != null) {
+ statements.add(statement);
+ }
}
generateTestCalls(context, files, block, rawStatements);
JsNamer namer = new JsPrettyNamer();
@@ -186,12 +193,20 @@ public final class Translation {
return context.program();
}
- @NotNull
+ private static void defineModule(@NotNull List statements,
+ @NotNull TranslationContext context,
+ @NotNull Config config) {
+ statements.add(AstUtil.newInvocation(context.namer().kotlin("defineModule"),
+ context.program().getStringLiteral(config.getModuleId()),
+ context.jsScope().declareName("_").makeRef()).makeStmt());
+ }
+
+ @Nullable
private static JsStatement generateCallToMain(@NotNull TranslationContext context, @NotNull List files,
@NotNull List arguments) throws MainFunctionNotFoundException {
JetNamedFunction mainFunction = getMainFunction(files);
if (mainFunction == null) {
- throw new MainFunctionNotFoundException("Main function was not found. Please check compiler arguments");
+ return null;
}
JsInvocation translatedCall = generateInvocation(context, mainFunction);
setArguments(context, arguments, translatedCall);
@@ -214,12 +229,12 @@ public final class Translation {
JsAstUtils.setArguments(translatedCall, Collections.singletonList(arrayLiteral));
}
- @NotNull
private static void generateTestCalls(@NotNull TranslationContext context,
@NotNull List files,
@NotNull JsBlock block,
List rawStatements) {
ClassDescriptor lastClassDescriptor = null;
+ boolean declaredVar = false;
List functions = JetTestFunctionDetector.findTestFunctions(context.bindingContext(), files);
for (JetNamedFunction function : functions) {
FunctionDescriptor functionDescriptor = getFunctionDescriptor(context.bindingContext(), function);
@@ -228,9 +243,16 @@ public final class Translation {
if (containingDeclaration instanceof ClassDescriptor) {
ClassDescriptor classDescriptor = (ClassDescriptor) containingDeclaration;
String className = getQualifiedName(classDescriptor);
+ if (lastClassDescriptor != classDescriptor) {
+ lastClassDescriptor = classDescriptor;
+ String prefix = "";
+ if (!declaredVar) {
+ prefix = "var ";
+ declaredVar = true;
+ }
+ rawStatements.add(prefix + "_testCase = new Kotlin.main." + className + "();");
+ }
rawStatements.add("QUnit.test( \"" + className + "." + funName + "()\" , function() {");
- String prefix = " var ";
- rawStatements.add(prefix + "_testCase = new Kotlin.defs." + className + "();");
//rawStatements.add(" expect(0);");
rawStatements.add(" _testCase." + funName + "();");
} else {
diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/operation/UnaryOperationTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/operation/UnaryOperationTranslator.java
index 8d5bba28ff9..8777a23c258 100644
--- a/js/js.translator/src/org/jetbrains/k2js/translate/operation/UnaryOperationTranslator.java
+++ b/js/js.translator/src/org/jetbrains/k2js/translate/operation/UnaryOperationTranslator.java
@@ -19,6 +19,7 @@ package org.jetbrains.k2js.translate.operation;
import com.google.dart.compiler.backend.js.ast.JsBinaryOperation;
import com.google.dart.compiler.backend.js.ast.JsConditional;
import com.google.dart.compiler.backend.js.ast.JsExpression;
+import com.google.dart.compiler.backend.js.ast.JsNameRef;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetUnaryExpression;
import org.jetbrains.jet.lexer.JetTokens;
@@ -62,9 +63,9 @@ public final class UnaryOperationTranslator {
@NotNull
private static JsExpression translateExclExclOperator(@NotNull JetUnaryExpression expression, @NotNull TranslationContext context) {
- JsExpression translatedExpression = translateAsExpression(getBaseExpression(expression), context);
- JsBinaryOperation notNullCheck = notNullCheck(context, translatedExpression);
- return new JsConditional(notNullCheck, translatedExpression, context.namer().throwNPEFunctionCall());
+ JsNameRef cachedValue = context.declareTemporary(translateAsExpression(getBaseExpression(expression), context), true).reference();
+ JsBinaryOperation notNullCheck = notNullCheck(context, cachedValue);
+ return new JsConditional(notNullCheck, cachedValue, context.namer().throwNPEFunctionCall());
}
@NotNull
diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/reference/CallBuilder.java b/js/js.translator/src/org/jetbrains/k2js/translate/reference/CallBuilder.java
index 4e26d07b6b4..4cd670eaf15 100644
--- a/js/js.translator/src/org/jetbrains/k2js/translate/reference/CallBuilder.java
+++ b/js/js.translator/src/org/jetbrains/k2js/translate/reference/CallBuilder.java
@@ -107,8 +107,10 @@ public final class CallBuilder {
private CallTranslator finish() {
if (resolvedCall == null) {
assert descriptor != null;
- resolvedCall = ResolvedCallImpl.create(ResolutionCandidate.create(descriptor, false),
- TemporaryBindingTrace.create(new BindingTraceContext())); //todo
+ resolvedCall = ResolvedCallImpl.create(ResolutionCandidate.create(descriptor, descriptor.getExpectedThisObject(),
+ descriptor.getReceiverParameter(),
+ ExplicitReceiverKind.THIS_OBJECT, false),
+ TemporaryBindingTrace.create(new BindingTraceContext()));
}
if (descriptor == null) {
descriptor = resolvedCall.getCandidateDescriptor().getOriginal();
diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/reference/CallTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/reference/CallTranslator.java
index ca42397faaf..ff97abb9815 100644
--- a/js/js.translator/src/org/jetbrains/k2js/translate/reference/CallTranslator.java
+++ b/js/js.translator/src/org/jetbrains/k2js/translate/reference/CallTranslator.java
@@ -213,7 +213,7 @@ public final class CallTranslator extends AbstractTranslator {
@NotNull
private JsInvocation generateCallMethodInvocation() {
- JsNameRef callMethodNameRef = AstUtil.newQualifiedNameRef("call");
+ JsNameRef callMethodNameRef = new JsNameRef("call");
JsInvocation callMethodInvocation = new JsInvocation();
callMethodInvocation.setQualifier(callMethodNameRef);
setQualifier(callMethodInvocation, callParameters.getFunctionReference());
diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/utils/AnnotationsUtils.java b/js/js.translator/src/org/jetbrains/k2js/translate/utils/AnnotationsUtils.java
index 303ca774236..a6256535d82 100644
--- a/js/js.translator/src/org/jetbrains/k2js/translate/utils/AnnotationsUtils.java
+++ b/js/js.translator/src/org/jetbrains/k2js/translate/utils/AnnotationsUtils.java
@@ -19,6 +19,7 @@ package org.jetbrains.k2js.translate.utils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
+import org.jetbrains.jet.lang.descriptors.ClassKind;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
@@ -31,6 +32,8 @@ import static org.jetbrains.k2js.translate.utils.JsDescriptorUtils.getContaining
*/
public final class AnnotationsUtils {
+ private static final String ENUMERABLE = "js.enumerable";
+
private AnnotationsUtils() {
}
@@ -69,10 +72,14 @@ public final class AnnotationsUtils {
@Nullable
private static AnnotationDescriptor getAnnotationByName(@NotNull DeclarationDescriptor descriptor,
- @NotNull PredefinedAnnotation annotation) {
+ @NotNull PredefinedAnnotation annotation) {
+ return getAnnotationByName(descriptor, annotation.getFQName());
+ }
+
+ @Nullable
+ private static AnnotationDescriptor getAnnotationByName(@NotNull DeclarationDescriptor descriptor, @NotNull String fqn) {
for (AnnotationDescriptor annotationDescriptor : descriptor.getAnnotations()) {
- String annotationClassFQName = getAnnotationClassFQName(annotationDescriptor);
- if (annotationClassFQName.equals(annotation.getFQName())) {
+ if (getAnnotationClassFQName(annotationDescriptor).equals(fqn)) {
return annotationDescriptor;
}
}
@@ -91,6 +98,16 @@ public final class AnnotationsUtils {
return hasAnnotationOrInsideAnnotatedClass(descriptor, PredefinedAnnotation.NATIVE);
}
+ public static boolean isEnumerable(@NotNull DeclarationDescriptor descriptor) {
+ if (getAnnotationByName(descriptor, ENUMERABLE) != null) {
+ return true;
+ }
+ ClassDescriptor containingClass = getContainingClass(descriptor);
+ return containingClass != null &&
+ (getAnnotationByName(containingClass, ENUMERABLE) != null ||
+ (containingClass.getKind().equals(ClassKind.OBJECT) && containingClass.getName().isSpecial()));
+ }
+
public static boolean isLibraryObject(@NotNull DeclarationDescriptor descriptor) {
return hasAnnotationOrInsideAnnotatedClass(descriptor, PredefinedAnnotation.LIBRARY);
}
@@ -105,14 +122,15 @@ public final class AnnotationsUtils {
}
public static boolean hasAnnotationOrInsideAnnotatedClass(@NotNull DeclarationDescriptor descriptor,
- @NotNull PredefinedAnnotation annotation) {
- if (getAnnotationByName(descriptor, annotation) != null) {
+ @NotNull PredefinedAnnotation annotation) {
+ return hasAnnotationOrInsideAnnotatedClass(descriptor, annotation.getFQName());
+ }
+
+ private static boolean hasAnnotationOrInsideAnnotatedClass(@NotNull DeclarationDescriptor descriptor, @NotNull String fqn) {
+ if (getAnnotationByName(descriptor, fqn) != null) {
return true;
}
ClassDescriptor containingClass = getContainingClass(descriptor);
- if (containingClass == null) {
- return false;
- }
- return (getAnnotationByName(containingClass, annotation) != null);
+ return containingClass != null && getAnnotationByName(containingClass, fqn) != null;
}
}
diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/utils/BindingUtils.java b/js/js.translator/src/org/jetbrains/k2js/translate/utils/BindingUtils.java
index 10c0775ab09..9ef7572e550 100644
--- a/js/js.translator/src/org/jetbrains/k2js/translate/utils/BindingUtils.java
+++ b/js/js.translator/src/org/jetbrains/k2js/translate/utils/BindingUtils.java
@@ -16,8 +16,8 @@
package org.jetbrains.k2js.translate.utils;
-import com.google.common.collect.Sets;
import com.intellij.psi.PsiElement;
+import com.intellij.util.containers.OrderedSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
@@ -110,7 +110,7 @@ public final class BindingUtils {
public static List