pull https://github.com/develar/kotlin ecma5-iter3 Make most of the tests work.

Thanks to develar.
This commit is contained in:
Pavel V. Talanov
2012-07-03 15:27:37 +04:00
75 changed files with 7964 additions and 1165 deletions
-3
View File
@@ -410,9 +410,6 @@
<inspection_tool class="UtilityClassWithPublicConstructor" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="UtilityClassWithoutPrivateConstructor" enabled="true" level="WARNING" enabled_by_default="true">
<option name="ignoreClassesWithOnlyMain" value="false" />
<option name="ignorableAnnotations">
<value />
</option>
</inspection_tool>
<inspection_tool class="VolatileLongOrDoubleField" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="WaitNotInLoop" enabled="true" level="WARNING" enabled_by_default="true" />
+2 -2
View File
@@ -2,15 +2,15 @@
<library name="js-libs">
<CLASSES>
<root url="jar://$PROJECT_DIR$/js/js.translator/lib/json.jar!/" />
<root url="jar://$PROJECT_DIR$/js/js.translator/lib/rhino-1.7R3.jar!/" />
<root url="jar://$PROJECT_DIR$/js/js.translator/lib/dart-r3300.jar!/" />
<root url="jar://$PROJECT_DIR$/js/js.translator/lib/closure-compiler.jar!/" />
<root url="jar://$PROJECT_DIR$/js/js.translator/lib/rhino-1.7R4.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$PROJECT_DIR$/js/js.translator/lib/rhino-1.7R3-src.jar!/" />
<root url="jar://$PROJECT_DIR$/js/js.translator/lib/dart-r3300-src.jar!/" />
<root url="jar://$PROJECT_DIR$/js/js.translator/lib/closure-compiler.jar!/" />
<root url="jar://$PROJECT_DIR$/js/js.translator/lib/rhino-1.7R4-sources.jar!/" />
</SOURCES>
</library>
</component>
@@ -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<K2JSCompilerArguments, K2JSCompile
@NotNull
@Override
protected ExitCode doExecute(K2JSCompilerArguments arguments, PrintingMessageCollector messageCollector, Disposable rootDisposable) {
if (arguments.srcdir == null && arguments.sourceFiles == null) {
messageCollector.report(CompilerMessageSeverity.ERROR, "Specify sources location via -srcdir", NO_LOCATION);
if (arguments.sourceFiles == null) {
messageCollector.report(CompilerMessageSeverity.ERROR, "Specify sources location via -sourceFiles", NO_LOCATION);
return ExitCode.INTERNAL_ERROR;
}
JetCoreEnvironment environmentForJS = JetCoreEnvironment.getCoreEnvironmentForJS(rootDisposable);
if (arguments.srcdir != null) {
environmentForJS.addSources(arguments.srcdir);
}
if (arguments.sourceFiles != null) {
for (String sourceFile : arguments.sourceFiles) {
environmentForJS.addSources(sourceFile);
}
for (String sourceFile : arguments.sourceFiles) {
environmentForJS.addSources(sourceFile);
}
Project project = environmentForJS.getProject();
@@ -101,7 +97,6 @@ public class K2JSCompiler extends CLICompiler<K2JSCompilerArguments, K2JSCompile
return ExitCode.INTERNAL_ERROR;
}
MainCallParameters mainCallParameters = arguments.createMainCallParameters();
return translateAndGenerateOutputFile(mainCallParameters, messageCollector, environmentForJS, config, outputFile);
}
@@ -151,10 +146,11 @@ public class K2JSCompiler extends CLICompiler<K2JSCompilerArguments, K2JSCompile
@NotNull
private static Config getConfig(@NotNull K2JSCompilerArguments arguments, @NotNull Project project) {
EcmaVersion ecmaVersion = EcmaVersion.fromString(arguments.target);
if (arguments.libzip == null) {
String moduleId = FileUtil.getNameWithoutExtension(new File(arguments.outputFile));
if (arguments.libraryFiles == null) {
// lets discover the JS library definitions on the classpath
return new ClassPathLibraryDefintionsConfig(project, ecmaVersion);
return new ClassPathLibraryDefintionsConfig(project, moduleId, ecmaVersion);
}
return new ZippedLibrarySourcesConfig(project, arguments.libzip, ecmaVersion);
return new LibrarySourcesConfig(project, moduleId, arguments.libraryFiles, ecmaVersion);
}
}
@@ -17,30 +17,28 @@
package org.jetbrains.jet.cli.js;
import com.sampullara.cli.Argument;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.cli.common.CompilerArguments;
import org.jetbrains.k2js.facade.MainCallParameters;
import java.util.ArrayList;
import java.util.List;
/**
* @author Pavel Talanov
*/
/**
* NOTE: for now K2JSCompiler supports only minimal amount of parameters required to launch it from the plugin.
* You can specify only one source folder, path to the file where generated file will be stored, path to zipped library sources.
* You can specify path to the file where generated file will be stored, path to zipped library sources.
*/
public class K2JSCompilerArguments extends CompilerArguments {
@Argument(value = "output", description = "Output file path")
public String outputFile;
//NOTE: may well be a subject to change soon
@Argument(value = "libzip", description = "Path to zipped lib sources")
public String libzip;
@Argument(value = "libraryFiles", description = "Path to zipped lib sources or kotlin files")
public String[] libraryFiles;
@Argument(value = "srcdir", description = "Sources directory")
public String srcdir;
@Argument(value = "sourceFiles", description = "Source files (dir or file)")
public String[] sourceFiles;
@Argument(value = "target", description = "Generate js files for specific ECMA version (3 or 5, default ECMA 3)")
public String target;
@@ -54,14 +52,13 @@ public class K2JSCompilerArguments extends CompilerArguments {
@Argument(value = "version", description = "Display compiler version")
public boolean version;
@Argument(value = "mainCall", description = "Whether a main function should be invoked; either 'main' or 'mainWithArgs'")
public String mainCall;
@Nullable
@Argument(value = "main", description = "Whether a main function should be called; either 'call' or 'noCall', default 'call' (main function will be auto detected)")
public String main;
@Argument(value = "help", alias = "h", description = "Show help")
public boolean help;
public List<String> 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<String>());
}
if ("noCall".equals(main)) {
return MainCallParameters.noCall();
}
else {
// TODO should we pass the arguments to the compiler?
return MainCallParameters.mainWithoutArguments();
}
return MainCallParameters.noCall();
}
}
@@ -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<String> 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<String> args) {
Pair<String, String> 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<Module> 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<String> args) {
Pair<String[], String> libLocationAndTarget = JsModuleDetector.getLibLocationAndTargetForProject(module);
StringBuilder sb = StringBuilderSpinAllocator.alloc();
AccessToken token = ReadAction.start();
try {
THashSet<Module> modules = new THashSet<Module>();
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<String> args, @NotNull VirtualFile srcDir) {
String srcPath = srcDir.getPath();
args.add("-srcdir");
args.add(srcPath);
private static void addPathToSourcesDir(@NotNull VirtualFile[] sourceFiles, @NotNull ArrayList<String> 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<String> args) {
@@ -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());
}
}
@@ -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<String, String> getLibLocationAndTargetForProject(@NotNull Project project) {
public static Pair<String[], String> getLibLocationAndTargetForProject(@NotNull Project project) {
Module module = getJSModule(project);
if (module == null) {
return Pair.empty();
}
else {
return getLibLocationAndTargetForProject(module);
}
}
@NotNull
public static Pair<String[], String> 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
+3 -1
View File
@@ -3,4 +3,6 @@ package js;
native
public annotation class native(name : String = "") {}
native
public annotation class library(name : String = "") {}
public annotation class library(name : String = "") {}
native
public annotation class enumerable() {}
+11 -7
View File
@@ -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
}
val console:Console = noImpl
+69 -130
View File
@@ -12,12 +12,11 @@ public trait Comparator<T> {
library
public trait Iterator<T> {
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<T>(col : Collection<T>, comp : Comparator<T>) : T = js.noImpl
@@ -55,120 +54,74 @@ val Collections = object {
}
library
public open class ArrayList<E>() : java.util.List<E> {
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<E> = 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<Any?> = js.noImpl
// public override fun toArray<T>(a : Array<out T>) : Array<T> = 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<out E>) : Boolean = js.noImpl
// public override fun addAll(index : Int, c : java.util.Collection<out E>) : Boolean = js.noImpl
}
library
public trait Collection<E> : java.lang.Iterable<E> {
open public fun size() : Int
open public fun isEmpty() : Boolean
open public fun contains(o : Any?) : Boolean
override public fun iterator() : java.util.Iterator<E>
// open public fun toArray() : Array<Any?>
// open public fun toArray<T>(a : Array<out T>) : Array<T>
open public fun add(e : E) : Boolean
open public fun remove(o : Any?) : Boolean
public trait Collection<E>: Iterable<E> {
open public fun size(): Int
open public fun isEmpty(): Boolean
open public fun contains(o: Any?): Boolean
override public fun iterator(): Iterator<E>
public fun toArray(): Array<E>
// open public fun toArray<T>(a : Array<out T>) : Array<T>
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<out E>) : Boolean
open public fun addAll(c: Collection<out E>): 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<E>() : Collection<E> {
public abstract class AbstractCollection<E>() : Collection<E> {
override public fun toArray(): Array<E> = js.noImpl
override public fun isEmpty(): Boolean = js.noImpl
override public fun contains(o: Any?): Boolean = js.noImpl
override public fun iterator(): Iterator<E> = 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<out E>): Boolean = js.noImpl
override public fun clear(): Unit = js.noImpl
override public fun size(): Int = js.noImpl
}
library
public abstract open class AbstractList<E>() : AbstractCollection<E>(), List<E> {
public override fun isEmpty() : Boolean = js.noImpl
public override fun contains(o : Any?) : Boolean = js.noImpl
public override fun iterator() : Iterator<E> = 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<Any?> = js.noImpl
// public override fun toArray<T>(a : Array<out T>) : Array<T> = 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<out E>) : Boolean = js.noImpl
// public override fun addAll(index : Int, c : java.util.Collection<out E>) : Boolean = js.noImpl
public trait List<E>: Collection<E> {
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<E> : Collection<E> {
override public fun size() : Int
override public fun isEmpty() : Boolean
override public fun contains(o : Any?) : Boolean
override public fun iterator() : java.util.Iterator<E>
// override public fun toArray() : Array<Any?>
// Simulate Java's array covariance
// override public fun toArray<T>(a : Array<out T>) : Array<T>
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<out E>) : Boolean
// open public fun addAll(index : Int, c : java.util.Collection<out E>) : 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<E>(): AbstractCollection<E>(), List<E> {
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<E>() : AbstractList<E>() {
}
library
public trait Set<E> : Collection<E> {
override public fun size() : Int
override public fun isEmpty() : Boolean
override public fun contains(o : Any?) : Boolean
override public fun iterator() : java.util.Iterator<E>
// override public fun toArray() : Array<Any?>
// override public fun toArray<T>(a : Array<out T>) : Array<T>
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<out E>) : 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<E>() : java.util.Set<E> {
public override fun iterator() : java.util.Iterator<E> = 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<out E>) : Boolean = js.noImpl
public open class HashSet<E>(): AbstractCollection<E>(), java.util.Set<E> {
}
library
@@ -186,23 +139,23 @@ public trait Map<K, V> {
open public fun values() : java.util.Collection<V>
open public fun entrySet() : java.util.Set<Entry<K, 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
trait Entry<K, V> {
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<K, V>() : java.util.Map<K, V> {
public open class HashMap<K, V>() : Map<K, V> {
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<out K, out V>) : Unit = js.noImpl
@@ -215,37 +168,23 @@ public open class HashMap<K, V>() : java.util.Map<K, V> {
}
library
public open class LinkedList<E>() : List<E> {
public override fun iterator() : java.util.Iterator<E> = 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<out E>) : 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<E>(): AbstractList<E>() {
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<E> {
open fun hasMoreElements(): Boolean
open fun nextElement(): E?
}
public class NoSuchElementException() : Exception() {}
+10 -1
View File
@@ -21,4 +21,13 @@ library("jsonFromTuples")
public fun json2(pairs : Array<Tuple2<String, Any?>>) : Json = js.noImpl
library("jsonAddProperties")
public fun Json.add(other : Json) : Json = js.noImpl
public fun Json.add(other : Json) : Json = js.noImpl
native
public trait JsonClass {
public fun stringify(o: Any): String = noImpl
public fun parse<T>(text: String): T = noImpl
}
native
public val JSON:JsonClass = noImpl
@@ -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 = "";
@@ -42,7 +42,7 @@ public abstract class SingleFileTranslationTest extends BasicTest {
runFunctionOutputTest(EcmaVersion.all(), kotlinFilename, namespaceName, functionName, expectedResult);
}
protected void runFunctionOutputTest(@NotNull EnumSet<EcmaVersion> ecmaVersions, @NotNull String kotlinFilename,
protected void runFunctionOutputTest(@NotNull Iterable<EcmaVersion> 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<EcmaVersion> ecmaVersions) throws Exception {
public void checkFooBoxIsTrue(@NotNull String filename, @NotNull Iterable<EcmaVersion> 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<EcmaVersion> ecmaVersions) throws Exception {
protected void fooBoxTest(@NotNull Iterable<EcmaVersion> 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<EcmaVersion> ecmaVersions,
protected void performTestWithMain(@NotNull Iterable<EcmaVersion> ecmaVersions,
@NotNull String testName,
@NotNull String testId,
@NotNull String... args) throws Exception {
@@ -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<JetFile> jsLibFiles;
@NotNull
@@ -37,7 +40,7 @@ public class TestConfig extends Config {
public TestConfig(@NotNull Project project, @NotNull EcmaVersion version,
@NotNull List<JetFile> files, @NotNull BindingContext context) {
super(project, version);
super(project, TEST_MODULE_NAME, version);
jsLibFiles = files;
libraryContext = context;
}
@@ -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;
}
}
@@ -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<FunctionWithScope> threadLocalFunction = new ThreadLocal<FunctionWithScope>() {
@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<String> scriptSourceProvider;
private final String functionName;
public RhinoFunctionManager(@NotNull Supplier<String> 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();
}
}
@@ -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);
}
}
}
@@ -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();
}
}
@@ -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<String> 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<String>() {
@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;
}
}
@@ -51,6 +51,10 @@ public final class ArrayListTest extends JavaClassesTest {
fooBoxTest();
}
public void testToArray() throws Exception {
fooBoxTest();
}
public void testIndexOOB() throws Exception {
try {
fooBoxTest();
@@ -74,4 +74,8 @@ public final class ExtensionFunctionTest extends SingleFileTranslationTest {
public void testExtensionPropertyOnClassWithExplicitAndImplicitReceiver() throws Exception {
fooBoxTest();
}
public void testExtensionFunctionCalledFromFor() throws Exception {
fooBoxTest();
}
}
@@ -34,4 +34,8 @@ public final class MultiFileTest extends MultipleFilesTranslationTest {
public void testClassesInheritedFromOtherFile() throws Exception {
checkFooBoxIsTrue("classesInheritedFromOtherFile");
}
public void testClassOfTheSameNameInAnotherPackage() throws Exception {
checkFooBoxIsTrue("classOfTheSameNameInAnotherPackage");
}
}
@@ -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();
}
}
}
@@ -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<String> additionalJSFiles(@NotNull EcmaVersion ecmaVersion) {
List<String> result = Lists.newArrayList(super.additionalJSFiles(ecmaVersion));
if (getName().equals("testEnumerable")) {
result.add(pathToTestFiles() + "enumerate.js");
}
return result;
}
}
@@ -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);
@@ -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<EcmaVersion> successOnEcmaV5() {
return EnumSet.of(EcmaVersion.v5);
}
@NotNull
public static String convertFileNameToDotJsFile(@NotNull String filename, @NotNull EcmaVersion ecmaVersion) {
String postFix = "_" + ecmaVersion.toString() + ".js";
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -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<JetFile> withJsLibAdded(@NotNull Collection<JetFile> files, @NotNull Config config) {
Set<JetFile> allFiles = Sets.newHashSet();
Collection<JetFile> allFiles = new ArrayList<JetFile>();
allFiles.addAll(files);
allFiles.addAll(config.getLibFiles());
return allFiles;
@@ -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
@@ -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<JetFile> 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<JetFile> generateLibFiles();
@@ -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<String> EXTERNAL_MODULE_NAME = new Key<String>("externalModule");
public static final String UNKNOWN_EXTERNAL_MODULE_NAME = "<unknown>";
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<JetFile> generateLibFiles() {
if (pathToLibZip == null) {
if (files == null) {
return Collections.emptyList();
}
try {
File file = new File(pathToLibZip);
ZipFile zipFile = new ZipFile(file);
List<JetFile> jetFiles = new ArrayList<JetFile>();
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<JetFile> 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);
}
}
@@ -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<JetFile> 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
@@ -25,7 +25,6 @@ import java.util.List;
* @author Pavel Talanov
*/
public abstract class MainCallParameters {
@NotNull
public static MainCallParameters noCall() {
return new MainCallParameters() {
@@ -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);
}
@@ -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;
@@ -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<JsName> {
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<JsName> namesForStandardClasses = new Rule<JsName>() {
@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<JsName> memberDeclarationsInsideParentsScope = new Rule<JsName>() {
@@ -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<JsNameRef> namespaceLevelDeclarationsHaveEnclosingNamespacesNamesAsQualifier = new Rule<JsNameRef>() {
@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<JsNameRef> constructorHaveTheSameQualifierAsTheClass = new Rule<JsNameRef>() {
@@ -449,10 +504,7 @@ public final class StaticContext {
Rule<Boolean> topLevelNamespaceHaveNoQualifier = new Rule<Boolean>() {
@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;
@@ -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();
@@ -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);
}
@@ -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<ClassDescriptor> descriptors;
@NotNull
private final BiMap<JsName, JsName> localToGlobalClassName;
private final THashMap<JetClass, ListItem> openClassToItem = new THashMap<JetClass, ListItem>();
private final TLinkedList<ListItem> openList = new TLinkedList<ListItem>();
private final List<ListItem> finalList = new ArrayList<ListItem>();
@NotNull
private final JsFunction dummyFunction;
@Nullable
private JsName declarationsObject = null;
@Nullable
private JsStatement declarationsStatement = null;
public ClassDeclarationTranslator(@NotNull List<ClassDescriptor> 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<JsPropertyInitializer> 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<JsStatement> 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<JsStatement> result = new ArrayList<JsStatement>();
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<JsStatement> generateClassDeclarationStatements() {
List<JsStatement> classDeclarations = new ArrayList<JsStatement>();
for (JetClass jetClass : getClassDeclarations()) {
classDeclarations.add(generateDeclaration(jetClass));
private void generateOpenClassDeclarations(@NotNull JsVars vars, @NotNull List<JsPropertyInitializer> 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<JetClass> getClassDeclarations() {
List<JetClass> classes = new ArrayList<JetClass>();
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<JsPropertyInitializer> classDeclarationsForNamespace(@NotNull NamespaceDescriptor namespaceDescriptor) {
List<JsPropertyInitializer> result = Lists.newArrayList();
for (ClassDescriptor classDescriptor : getAllClassesDefinedInNamespace(namespaceDescriptor)) {
result.add(getClassNameToClassObject(classDescriptor));
private void generateFinalClassDeclarations(@NotNull JsVars vars, @NotNull List<JsPropertyInitializer> 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<JsPropertyInitializer> 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);
}
}
@@ -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<JsName, JsName> 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.<JsName, JsName>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.<JsName, JsName>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<JsName, JsName> aliasingMap;
@Nullable
private final ClassAliasingMap aliasingMap;
private ClassTranslator(@NotNull JetClassOrObject classDeclaration,
@NotNull Map<JsName, JsName> 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<JsExpression> superclassReferences,
@NotNull List<ClassDescriptor> 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);
}
@@ -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<List<JsPropertyInitializer>> {
@Nullable
private final ClassDeclarationTranslator classDeclarationTranslator;
public DeclarationBodyVisitor() {
classDeclarationTranslator = null;
}
public DeclarationBodyVisitor(ClassDeclarationTranslator classDeclarationTranslator) {
this.classDeclarationTranslator = classDeclarationTranslator;
}
@NotNull
public List<JsPropertyInitializer> traverseClass(@NotNull JetClassOrObject jetClass,
@NotNull TranslationContext context) {
@@ -51,7 +63,7 @@ public final class DeclarationBodyVisitor extends TranslatorVisitor<List<JsPrope
@NotNull
public List<JsPropertyInitializer> traverseNamespace(@NotNull NamespaceDescriptor namespace,
@NotNull TranslationContext context) {
@NotNull TranslationContext context) {
List<JsPropertyInitializer> properties = new ArrayList<JsPropertyInitializer>();
for (JetDeclaration declaration : getDeclarationsForNamespace(context.bindingContext(), namespace)) {
properties.addAll(declaration.accept(this, context));
@@ -62,7 +74,11 @@ public final class DeclarationBodyVisitor extends TranslatorVisitor<List<JsPrope
@Override
@NotNull
public List<JsPropertyInitializer> 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<List<JsPrope
@NotNull TranslationContext context) {
JsPropertyInitializer methodAsPropertyInitializer = Translation.functionTranslator(expression, context).translateAsMethod();
if (context.isEcma5()) {
final FunctionDescriptor descriptor = getFunctionDescriptor(context.bindingContext(), expression);
boolean overridable = descriptor.getModality().isOverridable();
FunctionDescriptor descriptor = getFunctionDescriptor(context.bindingContext(), expression);
JsExpression methodBodyExpression = methodAsPropertyInitializer.getValueExpr();
methodAsPropertyInitializer.setValueExpr(JsAstUtils.createPropertyDataDescriptor(overridable, methodBodyExpression, context));
methodAsPropertyInitializer.setValueExpr(JsAstUtils.createPropertyDataDescriptor(descriptor, methodBodyExpression, context));
}
return Collections.singletonList(methodAsPropertyInitializer);
}
@@ -17,26 +17,25 @@
package org.jetbrains.k2js.translate.declaration;
import com.google.common.collect.Lists;
import com.google.dart.compiler.backend.js.ast.*;
import com.google.dart.compiler.backend.js.ast.JsExpression;
import com.google.dart.compiler.backend.js.ast.JsNameRef;
import com.google.dart.compiler.backend.js.ast.JsObjectLiteral;
import com.google.dart.compiler.backend.js.ast.JsStatement;
import com.google.dart.compiler.util.AstUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
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.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 java.util.Set;
import static org.jetbrains.k2js.translate.utils.BindingUtils.getAllNonNativeNamespaceDescriptors;
import static org.jetbrains.k2js.translate.utils.JsDescriptorUtils.getAllClassesDefinedInNamespace;
import static org.jetbrains.k2js.translate.utils.JsAstUtils.setQualifier;
/**
* @author Pavel Talanov
@@ -57,40 +56,22 @@ public final class NamespaceDeclarationTranslator extends AbstractTranslator {
@NotNull TranslationContext context) {
super(context);
this.namespaceDescriptors = namespaceDescriptors;
this.classDeclarationTranslator = new ClassDeclarationTranslator(getAllClasses(), context);
}
@NotNull
private List<ClassDescriptor> getAllClasses() {
List<ClassDescriptor> result = Lists.newArrayList();
for (NamespaceDescriptor namespaceDescriptor : namespaceDescriptors) {
result.addAll(getAllClassesDefinedInNamespace(namespaceDescriptor));
}
return result;
classDeclarationTranslator = new ClassDeclarationTranslator(context);
}
@NotNull
private List<JsStatement> translate() {
List<JsStatement> result = classesDeclarations();
result.addAll(namespacesDeclarations());
return result;
}
@NotNull
private List<JsStatement> classesDeclarations() {
List<JsStatement> result = Lists.newArrayList();
classDeclarationTranslator.generateDeclarations();
List<JsStatement> result = new ArrayList<JsStatement>();
result.add(classDeclarationTranslator.getDeclarationsStatement());
namespacesDeclarations(result);
classDeclarationTranslator.generateDeclarations();
return result;
}
@NotNull
private List<JsStatement> namespacesDeclarations() {
List<JsStatement> result = Lists.newArrayList();
private void namespacesDeclarations(List<JsStatement> statements) {
List<NamespaceTranslator> 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<JsStatement> declarationStatements(@NotNull List<NamespaceTranslator> namespaceTranslators, TranslationContext context) {
List<JsStatement> 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<NamespaceTranslator> namespaceTranslators,
@NotNull List<JsStatement> 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<JsStatement> initializeStatements(@NotNull List<NamespaceTranslator> namespaceTranslators) {
List<JsStatement> 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<NamespaceTranslator> namespaceTranslators,
@NotNull List<JsStatement> 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<NamespaceDescriptor> filterNonEmptyNamespaces(@NotNull List<NamespaceDescriptor> namespaceDescriptors) {
private List<NamespaceDescriptor> filterNonEmptyNamespaces(@NotNull List<NamespaceDescriptor> namespaceDescriptors) {
List<NamespaceDescriptor> result = Lists.newArrayList();
for (NamespaceDescriptor descriptor : namespaceDescriptors) {
if (!JsDescriptorUtils.isNamespaceEmpty(descriptor)) {
if (!JsDescriptorUtils.isNamespaceEmpty(descriptor, context().bindingContext())) {
result.add(descriptor);
}
}
@@ -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<JsExpression> initializers = new ArrayList<JsExpression>();
/*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<JsExpression> getInitializers() {
return initializers;
}
@NotNull
public JsPropertyInitializer getDeclarationAsInitializer() {
addNamespaceInitializer();
return new JsPropertyInitializer(namespaceName.makeRef(), getNamespaceDeclaration());
}
public void addNamespaceDeclaration(List<JsPropertyInitializer> 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<JsPropertyInitializer> 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<JsPropertyInitializer> properties) {
List<JsPropertyInitializer> propertyList = new ArrayList<JsPropertyInitializer>();
propertyList.add(InitializerUtils.generateInitializeMethod(initializer));
propertyList.addAll(properties);
namespaceDeclaration.getArguments().add(newObjectLiteral(propertyList));
}
private static void addEcma5InitializersAndProperties(@NotNull JsInvocation namespaceDeclaration,
@NotNull JsFunction initializer,
@NotNull List<JsPropertyInitializer> properties) {
namespaceDeclaration.getArguments().add(initializer);
namespaceDeclaration.getArguments().add(newObjectLiteral(properties));
private List<JsPropertyInitializer> 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<JsPropertyInitializer> getClassesDefined() {
return classDeclarationTranslator.classDeclarationsForNamespace(descriptor);
private void addIfNeed(@NotNull List<JsPropertyInitializer> declarations, @NotNull List<JsExpression> 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<JsPropertyInitializer> getNestedNamespaceDeclarations() {
if (DescriptorUtils.isRootNamespace(descriptor)) {
return Lists.newArrayList();
}
List<JsPropertyInitializer> result = Lists.newArrayList();
List<NamespaceDescriptor> nestedNamespaces = JsDescriptorUtils.getNestedNamespaces(descriptor);
List<NamespaceDescriptor> 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;
}
@@ -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
@@ -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");
}
@@ -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<JsName, JsName> 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<JetFile> files, @NotNull MainCallParameters mainCallParameters,
@NotNull EcmaVersion ecmaVersion, List<String> rawStatements)
@NotNull Config config, List<String> 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<JetFile> files,
@NotNull MainCallParameters mainCallParameters,
@NotNull EcmaVersion ecmaVersion, List<String> rawStatements) throws MainFunctionNotFoundException {
@NotNull Config config, List<String> 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<JsStatement> 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<JetFile> files,
@NotNull List<String> 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.<JsExpression>singletonList(arrayLiteral));
}
@NotNull
private static void generateTestCalls(@NotNull TranslationContext context,
@NotNull List<JetFile> files,
@NotNull JsBlock block,
List<String> rawStatements) {
ClassDescriptor lastClassDescriptor = null;
boolean declaredVar = false;
List<JetNamedFunction> 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 {
@@ -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
@@ -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();
@@ -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());
@@ -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;
}
}
@@ -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<JetDeclaration> getDeclarationsForNamespace(@NotNull BindingContext bindingContext,
@NotNull NamespaceDescriptor namespace) {
List<JetDeclaration> declarations = new ArrayList<JetDeclaration>();
for (DeclarationDescriptor descriptor : getContainedDescriptorsWhichAreNotPredefined(namespace)) {
for (DeclarationDescriptor descriptor : getContainedDescriptorsWhichAreNotPredefined(namespace, bindingContext)) {
if (descriptor instanceof NamespaceDescriptor) {
continue;
}
@@ -321,7 +321,7 @@ public final class BindingUtils {
@NotNull
public static Set<NamespaceDescriptor> getAllNonNativeNamespaceDescriptors(@NotNull BindingContext context,
@NotNull List<JetFile> files) {
Set<NamespaceDescriptor> descriptorSet = Sets.newHashSet();
Set<NamespaceDescriptor> descriptorSet = new OrderedSet<NamespaceDescriptor>();
for (JetFile file : files) {
//TODO: can't be
NamespaceDescriptor namespaceDescriptor = getNamespaceDescriptor(context, file);
@@ -1,88 +0,0 @@
/*
* 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.translate.utils;
import com.google.common.collect.Lists;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.psi.JetClass;
import org.jetbrains.jet.lang.resolve.BindingContext;
import java.util.ArrayList;
import java.util.List;
import static org.jetbrains.k2js.translate.utils.JsDescriptorUtils.getSuperclassDescriptors;
//TODO: can optimise using less dumb implementation
//TODO: pass list of descriptors here, not the list of jet classes
/**
* @author Pavel Talanov
*/
public final class ClassSortingUtils {
private ClassSortingUtils() {
}
@NotNull
public static List<JetClass> sortUsingInheritanceOrder(@NotNull List<JetClass> elements,
@NotNull BindingContext bindingContext) {
List<ClassDescriptor> descriptors = descriptorsFromClasses(elements, bindingContext);
PartiallyOrderedSet<ClassDescriptor> partiallyOrderedSet
= new PartiallyOrderedSet<ClassDescriptor>(descriptors, inheritanceOrder());
List<JetClass> sortedClasses = descriptorsToClasses(partiallyOrderedSet.partiallySortedElements(), bindingContext);
assert elements.size() == sortedClasses.size();
return sortedClasses;
}
@NotNull
private static PartiallyOrderedSet.Order<ClassDescriptor> inheritanceOrder() {
return new PartiallyOrderedSet.Order<ClassDescriptor>() {
@Override
public boolean firstDependsOnSecond(@NotNull ClassDescriptor first, @NotNull ClassDescriptor second) {
return isDerivedClass(first, second);
}
};
}
private static boolean isDerivedClass(@NotNull ClassDescriptor ancestor, @NotNull ClassDescriptor derived) {
return (getSuperclassDescriptors(derived).contains(ancestor));
}
@NotNull
private static List<JetClass> descriptorsToClasses(@NotNull List<ClassDescriptor> descriptors,
@NotNull BindingContext bindingContext) {
List<JetClass> sortedClasses = Lists.newArrayList();
for (ClassDescriptor descriptor : descriptors) {
sortedClasses.add(BindingUtils.getClassForDescriptor(bindingContext, descriptor));
}
return sortedClasses;
}
@NotNull
private static List<ClassDescriptor> descriptorsFromClasses(@NotNull List<JetClass> classesToSort,
@NotNull BindingContext bindingContext) {
List<ClassDescriptor> descriptorList = new ArrayList<ClassDescriptor>();
for (JetClass jetClass : classesToSort) {
descriptorList.add(BindingUtils.getClassDescriptor(bindingContext, jetClass));
}
return descriptorList;
}
}
@@ -21,6 +21,8 @@ import com.google.dart.compiler.backend.js.ast.*;
import com.google.dart.compiler.util.AstUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
import org.jetbrains.k2js.translate.context.TranslationContext;
@@ -31,11 +33,13 @@ import java.util.*;
*/
public final class JsAstUtils {
private static final JsNameRef DEFINE_PROPERTY = new JsNameRef("defineProperty");
public static final JsNameRef CREATE_OBJECT = new JsNameRef("create");
private static final JsNameRef EMPTY_REF = new JsNameRef("");
static {
JsNameRef globalObjectReference = new JsNameRef("Object");
DEFINE_PROPERTY.setQualifier(globalObjectReference);
CREATE_OBJECT.setQualifier(globalObjectReference);
}
private JsAstUtils() {
@@ -289,20 +293,36 @@ public final class JsAstUtils {
@NotNull TranslationContext context) {
return AstUtil.newInvocation(DEFINE_PROPERTY, new JsThisRef(),
context.program().getStringLiteral(context.getNameForDescriptor(descriptor).getIdent()),
createPropertyDataDescriptor(descriptor.isVar(), value, context));
createPropertyDataDescriptor(descriptor.isVar(), descriptor, value, context));
}
@NotNull
public static JsObjectLiteral createPropertyDataDescriptor(boolean writable,
public static JsObjectLiteral createPropertyDataDescriptor(@NotNull FunctionDescriptor descriptor,
@NotNull JsExpression value,
@NotNull TranslationContext context) {
JsObjectLiteral jsPropertyDescriptor = new JsObjectLiteral();
List<JsPropertyInitializer> meta = jsPropertyDescriptor.getPropertyInitializers();
meta.add(new JsPropertyInitializer(context.program().getStringLiteral("value"), value));
return createPropertyDataDescriptor(descriptor.getModality().isOverridable(), descriptor, value, context);
}
@NotNull
public static JsObjectLiteral createDataDescriptor(@NotNull JsExpression value, boolean writable, @NotNull TranslationContext context) {
JsObjectLiteral dataDescriptor = new JsObjectLiteral();
dataDescriptor.getPropertyInitializers().add(new JsPropertyInitializer(context.program().getStringLiteral("value"), value));
if (writable) {
meta.add(context.namer().writablePropertyDescriptorField());
dataDescriptor.getPropertyInitializers().add(context.namer().writablePropertyDescriptorField());
}
return jsPropertyDescriptor;
return dataDescriptor;
}
@NotNull
private static JsObjectLiteral createPropertyDataDescriptor(boolean writable,
@NotNull DeclarationDescriptor descriptor,
@NotNull JsExpression value,
@NotNull TranslationContext context) {
JsObjectLiteral dataDescriptor = createDataDescriptor(value, writable, context);
if (AnnotationsUtils.isEnumerable(descriptor)) {
dataDescriptor.getPropertyInitializers().add(context.namer().enumerablePropertyDescriptorField());
}
return dataDescriptor;
}
@NotNull
@@ -17,15 +17,19 @@
package org.jetbrains.k2js.translate.utils;
import com.google.common.collect.Lists;
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.name.Name;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.expressions.OperatorConventions;
import org.jetbrains.k2js.translate.context.Namer;
import org.jetbrains.k2js.config.LibrarySourcesConfig;
import java.util.ArrayList;
import java.util.Collection;
@@ -140,16 +144,6 @@ public final class JsDescriptorUtils {
return (functionDescriptor.getReceiverParameter().exists());
}
@NotNull
public static String getNameForNamespace(@NotNull NamespaceDescriptor descriptor) {
if (descriptor.getContainingDeclaration() instanceof ModuleDescriptor) {
return Namer.getRootNamespaceName();
}
else {
return descriptor.getName().getName();
}
}
//TODO: why callable descriptor
@Nullable
public static DeclarationDescriptor getExpectedThisDescriptor(@NotNull CallableDescriptor callableDescriptor) {
@@ -193,22 +187,12 @@ public final class JsDescriptorUtils {
}
@NotNull
public static List<ClassDescriptor> getAllClassesDefinedInNamespace(@NotNull NamespaceDescriptor namespaceDescriptor) {
List<ClassDescriptor> classDescriptors = Lists.newArrayList();
for (DeclarationDescriptor descriptor : getContainedDescriptorsWhichAreNotPredefined(namespaceDescriptor)) {
if (descriptor instanceof ClassDescriptor) {
classDescriptors.add((ClassDescriptor)descriptor);
}
}
return classDescriptors;
}
@NotNull
public static List<NamespaceDescriptor> getNestedNamespaces(@NotNull NamespaceDescriptor namespaceDescriptor) {
public static List<NamespaceDescriptor> getNestedNamespaces(@NotNull NamespaceDescriptor namespaceDescriptor,
@NotNull BindingContext context) {
List<NamespaceDescriptor> result = Lists.newArrayList();
for (DeclarationDescriptor descriptor : getContainedDescriptorsWhichAreNotPredefined(namespaceDescriptor)) {
for (DeclarationDescriptor descriptor : getContainedDescriptorsWhichAreNotPredefined(namespaceDescriptor, context)) {
if (descriptor instanceof NamespaceDescriptor) {
result.add((NamespaceDescriptor)descriptor);
result.add((NamespaceDescriptor) descriptor);
}
}
return result;
@@ -227,10 +211,22 @@ public final class JsDescriptorUtils {
}
@NotNull
public static List<DeclarationDescriptor> getContainedDescriptorsWhichAreNotPredefined(@NotNull NamespaceDescriptor namespace) {
public static List<DeclarationDescriptor> getContainedDescriptorsWhichAreNotPredefined(@NotNull NamespaceDescriptor namespace,
@NotNull BindingContext context) {
List<DeclarationDescriptor> result = Lists.newArrayList();
for (DeclarationDescriptor descriptor : namespace.getMemberScope().getAllDescriptors()) {
if (!AnnotationsUtils.isPredefinedObject(descriptor)) {
// namespace may be defined in multiple files
if (!(descriptor instanceof NamespaceDescriptor)) {
PsiElement psiElement = BindingContextUtils.descriptorToDeclaration(context, descriptor);
if (psiElement != null) {
PsiFile file = psiElement.getContainingFile();
if (file.getUserData(LibrarySourcesConfig.EXTERNAL_MODULE_NAME) != null) {
continue;
}
}
}
result.add(descriptor);
}
}
@@ -238,11 +234,11 @@ public final class JsDescriptorUtils {
}
//TODO: at the moment this check is very ineffective
public static boolean isNamespaceEmpty(@NotNull NamespaceDescriptor namespace) {
List<DeclarationDescriptor> containedDescriptors = getContainedDescriptorsWhichAreNotPredefined(namespace);
public static boolean isNamespaceEmpty(@NotNull NamespaceDescriptor namespace, @NotNull BindingContext context) {
List<DeclarationDescriptor> containedDescriptors = getContainedDescriptorsWhichAreNotPredefined(namespace, context);
for (DeclarationDescriptor descriptor : containedDescriptors) {
if (descriptor instanceof NamespaceDescriptor) {
if (!isNamespaceEmpty((NamespaceDescriptor)descriptor)) {
if (!isNamespaceEmpty((NamespaceDescriptor) descriptor, context)) {
return false;
}
}
@@ -1,121 +0,0 @@
/*
* 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.translate.utils;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
* @author Pavel Talanov
* <p/>
* This is very inefficient but simple implementation of partially orderered set.
* Feel free to replace with library implementation.
*/
public final class PartiallyOrderedSet<Element> {
private class Arc {
@NotNull
public final Element from;
@NotNull
public final Element to;
private Arc(@NotNull Element from, @NotNull Element to) {
this.from = from;
this.to = to;
}
}
public interface Order<Element> {
boolean firstDependsOnSecond(@NotNull Element first, @NotNull Element second);
}
@NotNull
private final List<Arc> arcs = Lists.newArrayList();
@NotNull
private final Map<Element, Integer> incomingArcs = Maps.newHashMap();
@NotNull
private final List<Element> elementsWithZeroIncoming = Lists.newArrayList();
public PartiallyOrderedSet(@NotNull Collection<Element> elements, @NotNull Order<Element> order) {
elementsWithZeroIncoming.addAll(elements);
for (@NotNull Element first : elements) {
for (@NotNull Element second : elements) {
if (order.firstDependsOnSecond(first, second)) {
arcs.add(new Arc(first, second));
increaseIncomingCount(second);
}
}
}
}
private void increaseIncomingCount(@NotNull Element element) {
if (!incomingArcs.containsKey(element)) {
incomingArcs.put(element, 1);
elementsWithZeroIncoming.remove(element);
}
else {
Integer count = incomingArcs.get(element);
incomingArcs.put(element, count + 1);
}
}
private void decreaseIncomingCount(@NotNull Element element) {
assert incomingArcs.containsKey(element);
Integer count = incomingArcs.get(element);
if (count == 1) {
incomingArcs.remove(element);
elementsWithZeroIncoming.add(element);
}
else {
incomingArcs.put(element, count - 1);
}
}
@NotNull
public List<Element> partiallySortedElements() {
List<Element> result = Lists.newArrayList();
while (!elementsWithZeroIncoming.isEmpty()) {
result.add(getNextElement());
}
return result;
}
@NotNull
private Element getNextElement() {
Element elementWithZeroIncoming = getElementWithZeroIncoming();
for (Arc arc : arcs) {
if (arc.from == elementWithZeroIncoming) {
decreaseIncomingCount(arc.to);
}
}
return elementWithZeroIncoming;
}
@NotNull
private Element getElementWithZeroIncoming() {
int indexOfLast = elementsWithZeroIncoming.size() - 1;
Element element = elementsWithZeroIncoming.get(indexOfLast);
elementsWithZeroIncoming.remove(indexOfLast);
return element;
}
}
@@ -22,8 +22,6 @@ import org.jetbrains.annotations.NotNull;
* @author Pavel Talanov
*/
public enum PredefinedAnnotation {
LIBRARY("js.library"),
NATIVE("js.native");
@@ -23,7 +23,6 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lexer.JetToken;
import org.jetbrains.jet.lexer.JetTokens;
import org.jetbrains.k2js.translate.context.Namer;
import java.util.Collections;
import java.util.List;
@@ -143,17 +142,6 @@ public final class PsiUtils {
return nameAsDeclaration;
}
@NotNull
public static String getNamespaceName(@NotNull JetFile psiFile) {
JetNamespaceHeader namespaceHeader = psiFile.getNamespaceHeader();
String name = namespaceHeader.getName();
assert name != null : "NamespaceHeader must have a name";
if (name.isEmpty()) {
return Namer.getRootNamespaceName();
}
return name;
}
@NotNull
public static JetExpression getLoopRange(@NotNull JetForExpression expression) {
JetExpression rangeExpression = expression.getLoopRange();
@@ -43,7 +43,7 @@ import static org.jetbrains.k2js.translate.utils.JsDescriptorUtils.getExpectedRe
*/
public final class TranslationUtils {
private static JsNameRef UNDEFINED_LITERAL = AstUtil.newQualifiedNameRef("undefined");
private static final JsNameRef UNDEFINED_LITERAL = AstUtil.newQualifiedNameRef("undefined");
private TranslationUtils() {
}
@@ -64,11 +64,7 @@ public final class TranslationUtils {
@NotNull
private static JsPropertyInitializer translateExtensionFunctionAsEcma5PropertyDescriptor(@NotNull JsFunction function,
@NotNull FunctionDescriptor descriptor, @NotNull TranslationContext context) {
JsObjectLiteral meta = new JsObjectLiteral();
meta.getPropertyInitializers().add(new JsPropertyInitializer(context.program().getStringLiteral("value"), function));
if (descriptor.getModality().isOverridable()) {
meta.getPropertyInitializers().add(context.namer().writablePropertyDescriptorField());
}
JsObjectLiteral meta = JsAstUtils.createDataDescriptor(function, descriptor.getModality().isOverridable(), context);
return new JsPropertyInitializer(context.getNameForDescriptor(descriptor).makeRef(), meta);
}
@@ -0,0 +1,33 @@
package foo
class SimpleEnumerator {
private var counter = 0
fun getNext(): String {
counter++;
return counter.toString()
}
fun hasMoreElements(): Boolean = counter < 1
}
class SimpleEnumeratorWrapper(private val enumerator: SimpleEnumerator) {
val hasNext: Boolean
get() = enumerator.hasMoreElements()
fun next() = enumerator.getNext()
}
fun SimpleEnumerator.iterator(): SimpleEnumeratorWrapper {
return SimpleEnumeratorWrapper(this)
}
fun box(): Boolean {
var o = ""
val enumerator = SimpleEnumerator()
for (s in enumerator) {
o += s;
}
return o == "1"
}
@@ -0,0 +1,13 @@
package foo
import java.util.ArrayList
fun box() : Boolean {
var i = 0
val list = ArrayList<Int>()
while (i++ < 3) {
list.add(i)
}
val array = list.toArray()
return array[0] == 1 && array[1] == 2 && array[2] == 3
}
File diff suppressed because it is too large Load Diff
@@ -14,11 +14,7 @@
* limitations under the License.
*/
var foo = Kotlin.createNamespace({initialize:function(){
}
, box:function(){
var foo = Kotlin.definePackage({box:function(){
return !false;
}
});
@@ -46,9 +46,7 @@
return {A:A, B:B, C:C};
}
();
var foo = Kotlin.createNamespace(classes, {initialize:function(){
}
, box:function(){
var foo = Kotlin.definePackage(classes, {box:function(){
return (new foo.C).get_order() === 'ABC' && (new foo.B).get_order() === 'AB' && (new foo.A).get_order() === 'A';
}
});
+164 -192
View File
@@ -14,6 +14,11 @@
* limitations under the License.
*/
// todo org.jetbrains.k2js.test.semantics.WebDemoExamples2Test#testBuilder
var kotlin = {set:function (receiver, key, value) {
return receiver.put(key, value);
}};
(function () {
"use strict";
@@ -23,10 +28,10 @@
return obj1.equals(obj2);
}
}
return (obj1 === obj2);
return obj1 === obj2;
};
Kotlin.defs = {};
Kotlin.modules = {};
Kotlin.Exceptions = {};
Kotlin.Exception = Kotlin.$createClass();
Kotlin.RuntimeException = Kotlin.$createClass(Kotlin.Exception);
@@ -39,121 +44,126 @@
Kotlin.Exceptions.UnsupportedOperationException = Kotlin.$createClass(Kotlin.Exception);
Kotlin.Exceptions.IOException = Kotlin.$createClass(Kotlin.Exception);
Kotlin.throwNPE = function() {
Kotlin.throwNPE = function () {
throw Kotlin.$new(Kotlin.Exceptions.NullPointerException)();
};
Kotlin.AbstractList = Kotlin.$createClass({
set:function (index, value) {
throw Kotlin.$new(Kotlin.Exceptions.UnsupportedOperationException)();
},
iterator:function () {
return Kotlin.$new(Kotlin.ArrayIterator)(this);
},
isEmpty:function () {
return (this.size() === 0);
},
add:function (element) {
throw Kotlin.$new(Kotlin.Exceptions.UnsupportedOperationException)();
},
addAll:function (collection) {
var it = collection.iterator();
while (it.get_hasNext()) {
this.add(it.next());
}
},
remove:function(value) {
for (var i = 0; i < this.$size; ++i) {
if (this.array[i] == value) {
this.removeByIndex(i);
return;
}
}
},
removeByIndex:function (index) {
throw Kotlin.$new(Kotlin.Exceptions.UnsupportedOperationException)();
},
clear:function () {
throw Kotlin.$new(Kotlin.Exceptions.UnsupportedOperationException)();
},
contains:function (obj) {
for (var i = 0; i < this.$size; ++i) {
if (Kotlin.equals(this.array[i], obj)) {
return true;
}
}
return false;
}
});
function throwAbstractFunctionInvocationError() {
throw new TypeError("Function is abstract");
}
Kotlin.ArrayList = Kotlin.$createClass({
initialize:function () {
this.array = [];
this.$size = 0;
Kotlin.Iterator = Kotlin.$createClass({
initialize: function () {
},
get:function (index) {
if ((index < 0) || (index >= this.$size)) {
throw Kotlin.Exceptions.IndexOutOfBounds;
}
return (this.array)[index];
next: throwAbstractFunctionInvocationError,
get_hasNext: throwAbstractFunctionInvocationError
});
var ArrayIterator = Kotlin.$createClass(Kotlin.Iterator, {
initialize: function (array) {
this.array = array;
this.size = array.length;
this.index = 0;
},
set:function (index, value) {
if ((index < 0) || (index >= this.$size)) {
throw Kotlin.Exceptions.IndexOutOfBounds;
}
(this.array)[index] = value;
next: function () {
return this.array[this.index++];
},
size:function () {
return this.$size;
get_hasNext: function () {
return this.index < this.size;
}
});
var ListIterator = Kotlin.$createClass(ArrayIterator, {
initialize: function (list) {
this.list = list;
this.size = list.size();
this.index = 0;
},
iterator:function () {
return Kotlin.$new(Kotlin.ArrayIterator)(this);
next: function () {
return this.list.get(this.index++);
},
isEmpty:function () {
return (this.$size === 0);
get_hasNext: function () {
return this.index < this.size;
}
});
Kotlin.AbstractList = Kotlin.$createClass({
iterator: function () {
return Kotlin.$new(ListIterator)(this);
},
add:function (element) {
this.array[this.$size++] = element;
isEmpty: function () {
return this.size() == 0;
},
addAll:function (collection) {
addAll: function (collection) {
var it = collection.iterator();
while (it.get_hasNext()) {
this.add(it.next());
}
},
remove:function(value) {
for (var i = 0; i < this.$size; ++i) {
if (this.array[i] == value) {
this.removeByIndex(i);
return;
}
remove: function (o) {
var index = this.indexOf(o);
if (index != -1) {
this.removeAt(index);
}
},
removeByIndex:function (index) {
for (var i = index; i < this.$size - 1; ++i) {
this.array[i] = this.array[i + 1];
}
this.$size--;
},
clear:function () {
this.array = [];
this.$size = 0;
},
contains:function (obj) {
for (var i = 0; i < this.$size; ++i) {
if (Kotlin.equals(this.array[i], obj)) {
return true;
}
}
return false;
contains: function (o) {
return this.indexOf(o) != -1;
}
});
Kotlin.ArrayList = Kotlin.$createClass(Kotlin.AbstractList, {
initialize: function () {
this.array = [];
this.$size = 0;
},
get: function (index) {
if (index < 0 || index >= this.$size) {
throw Kotlin.Exceptions.IndexOutOfBounds;
}
return this.array[index];
},
set: function (index, value) {
if (index < 0 || index >= this.$size) {
throw Kotlin.Exceptions.IndexOutOfBounds;
}
this.array[index] = value;
},
toArray: function () {
return this.array.slice(0, this.$size);
},
size: function () {
return this.$size;
},
iterator: function () {
return Kotlin.arrayIterator(this.array);
},
add: function (element) {
this.array[this.$size++] = element;
},
addAt: function (index, element) {
this.array.splice(index, 0, element);
},
removeAt: function (index) {
this.array.splice(index, 1);
this.$size--;
},
clear: function () {
this.array.length = 0;
this.$size = 0;
},
indexOf: function (o) {
for (var i = 0, n = this.$size; i < n; ++i) {
if (Kotlin.equals(this.array[i], o)) {
return i;
}
}
return -1;
}
});
Kotlin.parseInt = function (str) {
return parseInt(str, 10);
}
;
};
Kotlin.safeParseInt = function(str) {
var r = parseInt(str, 10);
@@ -207,57 +217,32 @@
Kotlin.System.out().print(s);
};
Kotlin.AbstractFunctionInvocationError = Kotlin.$createClass();
Kotlin.Iterator = Kotlin.$createClass({
initialize:function () {
},
next:function () {
throw Kotlin.$new(Kotlin.AbstractFunctionInvocationError)();
},
get_hasNext:function () {
throw Kotlin.$new(Kotlin.AbstractFunctionInvocationError)();
}
});
Kotlin.Runnable = Kotlin.$createClass({
run:function () {
throw Kotlin.$new(Kotlin.AbstractFunctionInvocationError)();
}
});
Kotlin.ArrayIterator = Kotlin.$createClass(Kotlin.Iterator, {
initialize: function (array) {
this.array = array;
this.index = 0;
},
next: function () {
return this.array.get(this.index++);
},
get_hasNext: function () {
return this.array.size() > this.index;
}
});
Kotlin.RangeIterator = Kotlin.$createClass(Kotlin.Iterator, {
initialize:function (start, count, reversed) {
initialize: function (start, count, reversed) {
this.$start = start;
this.$count = count;
this.$reversed = reversed;
this.$i = this.get_start();
}, get_start:function () {
},
get_start: function () {
return this.$start;
}, get_count:function () {
},
get_count: function () {
return this.$count;
}, set_count:function (tmp$0) {
},
set_count: function (tmp$0) {
this.$count = tmp$0;
}, get_reversed:function () {
},
get_reversed: function () {
return this.$reversed;
}, get_i:function () {
},
get_i: function () {
return this.$i;
}, set_i:function (tmp$0) {
},
set_i: function (tmp$0) {
this.$i = tmp$0;
}, next:function () {
},
next: function () {
this.set_count(this.get_count() - 1);
if (this.get_reversed()) {
this.set_i(this.get_i() - 1);
@@ -273,44 +258,51 @@
}
});
Kotlin.NumberRange = Kotlin.$createClass({initialize:function (start, size, reversed) {
this.$start = start;
this.$size = size;
this.$reversed = reversed;
}, get_start:function () {
return this.$start;
}, get_size:function () {
return this.$size;
}, get_reversed:function () {
return this.$reversed;
}, get_end:function () {
return this.get_reversed() ? this.get_start() - this.get_size() + 1 : this.get_start() + this.get_size() - 1;
}, contains:function (number) {
if (this.get_reversed()) {
return number <= this.get_start() && number > this.get_start() - this.get_size();
Kotlin.NumberRange = Kotlin.$createClass({
initialize: function (start, size, reversed) {
this.$start = start;
this.$size = size;
this.$reversed = reversed;
},
get_start: function () {
return this.$start;
},
get_size: function () {
return this.$size;
},
get_reversed: function () {
return this.$reversed;
},
get_end: function () {
return this.get_reversed() ? this.get_start() - this.get_size() + 1 : this.get_start() + this.get_size() - 1;
},
contains: function (number) {
if (this.get_reversed()) {
return number <= this.get_start() && number > this.get_start() - this.get_size();
}
else {
return number >= this.get_start() && number < this.get_start() + this.get_size();
}
},
iterator: function () {
return Kotlin.$new(Kotlin.RangeIterator)(this.get_start(), this.get_size(), this.get_reversed());
}
else {
return number >= this.get_start() && number < this.get_start() + this.get_size();
}
}, iterator:function () {
return Kotlin.$new(Kotlin.RangeIterator)(this.get_start(), this.get_size(), this.get_reversed());
}
});
Kotlin.Comparator = Kotlin.$createClass(
{
initialize: function () {
},
compare: function (el1, el2) {
throw Kotlin.$new(Kotlin.AbstractFunctionInvocationError)();
}
Kotlin.Comparator = Kotlin.$createClass({
initialize: function () {
},
compare: throwAbstractFunctionInvocationError
});
var ComparatorImpl = Kotlin.$createClass(Kotlin.Comparator, {
initialize: function (comparator) {
this.compare = comparator;
}
);
});
Kotlin.comparator = function (f) {
var result = Kotlin.$new(Kotlin.Comparator)();
result.compare = f;
return result;
return Kotlin.$new(ComparatorImpl)(f);
};
Kotlin.collectionsMax = function (col, comp) {
@@ -369,25 +361,8 @@
return Kotlin.$new(Kotlin.NumberRange)(0, arr.length);
};
var intrinsicArrayIterator = Kotlin.$createClass(
Kotlin.Iterator,
{
initialize: function (arr) {
this.arr = arr;
this.len = arr.length;
this.i = 0;
},
next: function () {
return this.arr[this.i++];
},
get_hasNext: function () {
return this.i < this.len;
}
}
);
Kotlin.arrayIterator = function (arr) {
return Kotlin.$new(intrinsicArrayIterator)(arr);
Kotlin.arrayIterator = function (array) {
return Kotlin.$new(ArrayIterator)(array);
};
Kotlin.toString = function (obj) {
@@ -796,14 +771,11 @@
Kotlin.HashTable = Hashtable;
})();
Kotlin.HashMap = Kotlin.$createClass(
{
initialize:function () {
Kotlin.HashTable.call(this);
}
}
);
Kotlin.HashMap = Kotlin.$createClass({
initialize: function () {
Kotlin.HashTable.call(this);
}
});
(function () {
function HashSet(hashingFunction, equalityFunction) {
+28 -37
View File
@@ -1,10 +1,10 @@
/* Prototype JavaScript framework, version 1.6.1
* (c) 2005-2009 Sam Stephenson
*
* Prototype is freely distributable under the terms of an MIT-style license.
* For details, see the Prototype web site: http://www.prototypejs.org/
*
*--------------------------------------------------------------------------*/
/* Prototype JavaScript framework, version 1.6.1
* (c) 2005-2009 Sam Stephenson
*
* Prototype is freely distributable under the terms of an MIT-style license.
* For details, see the Prototype web site: http://www.prototypejs.org/
*
*--------------------------------------------------------------------------*/
var Kotlin = {};
(function () {
@@ -12,13 +12,14 @@ var Kotlin = {};
var emptyFunction = function () {
};
function $A(iterable) {
if (!iterable) return [];
if ('toArray' in Object(iterable)) return iterable.toArray();
var length = iterable.length || 0, results = new Array(length);
while (length--) results[length] = iterable[length];
return results;
}
Kotlin.argumentsToArrayLike = function (args) {
var n = args.length;
var result = new Array(n);
while (n--) {
result[n] = args[n];
}
return result;
};
(function () {
function extend(destination, source) {
@@ -62,11 +63,6 @@ var Kotlin = {};
return array;
}
function merge(array, args) {
array = slice.call(array, 0);
return update(array, args);
}
function argumentNames() {
var names = this.toString().match(/^[\s\(]*function[^(]*\(([^)]*)\)/)[1]
.replace(/\/\/.*?[\r\n]|\/\*(?:.|[\r\n])*?\*\//g, '')
@@ -74,15 +70,6 @@ var Kotlin = {};
return names.length == 1 && !names[0] ? [] : names;
}
function bind(context) {
if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this;
var __method = this, args = slice.call(arguments, 1);
return function () {
var a = merge(args, arguments);
return __method.apply(context, a);
};
}
function bindAsEventListener(context) {
var __method = this, args = slice.call(arguments, 1);
return function (event) {
@@ -101,7 +88,6 @@ var Kotlin = {};
return {
argumentNames: argumentNames,
bind: bind,
bindAsEventListener: bindAsEventListener,
wrap: wrap
};
@@ -129,21 +115,18 @@ var Kotlin = {};
var property = properties[i];
object[property] = source[property];
}
return this;
}
return function () {
var result = {};
for (var i = 0, length = arguments.length; i < length; i++) {
var result = arguments[0];
for (var i = 1, n = arguments.length; i < n; i++) {
add(result, arguments[i]);
}
return result;
}
})();
Kotlin.createNamespace = function () {
return Kotlin.createTrait.apply(null, arguments);
};
Kotlin.definePackage = Kotlin.createTrait;
Kotlin.createClass = (function () {
var METHODS = {addMethods: addMethods};
@@ -152,7 +135,7 @@ var Kotlin = {};
}
function create() {
var parent = null, properties = $A(arguments);
var parent = null, properties = Kotlin.argumentsToArrayLike(arguments);
if (typeof (properties[0]) == "function") {
parent = properties.shift();
}
@@ -243,4 +226,12 @@ var Kotlin = {};
var singletonClass = Kotlin.createClass.apply(null, arguments);
return new singletonClass();
};
})();
Kotlin.defineModule = function (id, module) {
if ((id in Kotlin.modules) && (id !== "JS_TESTS")) {
throw Kotlin.$new(Kotlin.Exceptions.IllegalArgumentException)();
}
Kotlin.modules[id] = module;
};
})();
+85 -90
View File
@@ -20,89 +20,75 @@ var Kotlin = {};
return false;
};
// todo compatibility for opera https://raw.github.com/gist/1000718/es5compat-gs.js
// as separated function to reduce scope
function createConstructor(proto, initializer) {
return function () {
var o = Object.create(proto);
if (initializer != null) {
initializer.apply(o, arguments);
}
Object.seal(o);
return o;
};
}
function computeProto(bases, properties) {
var proto = null;
for (var i = 0, n = bases.length; i < n; i++) {
var base = bases[i];
var baseProto = base.proto;
if (baseProto == null || base.properties == null) {
continue;
}
if (!proto) {
proto = Object.create(baseProto, properties || undefined);
continue;
}
Object.defineProperties(proto, base.properties);
// todo test A -> B, C(->D) *properties from D is not yet added to proto*
}
return proto;
}
// proto must be created for class even if it is not needed (requires for is operator)
Kotlin.createClass = (function () {
function create(bases, initializer, properties) {
var proto;
var baseInitializer = null;
var isTrait = initializer == null;
if (!bases) {
proto = !properties && isTrait ? null : Object.create(null, properties || undefined);
Kotlin.createClass = function (bases, initializer, properties) {
var proto;
var baseInitializer = null;
var isTrait = initializer == null;
if (!bases) {
proto = !properties && isTrait ? null : Object.create(null, properties || undefined);
}
else if (!Array.isArray(bases)) {
baseInitializer = bases.initializer;
proto = !properties && isTrait ? bases.proto : Object.create(bases.proto, properties || undefined);
}
else {
proto = computeProto(bases, properties);
// first is superclass, other are traits
baseInitializer = bases[0].initializer;
// all bases are traits without properties
if (proto == null && !isTrait) {
proto = Object.create(null, properties || undefined);
}
else if (!Array.isArray(bases)) {
baseInitializer = bases.initializer;
proto = !properties && isTrait ? bases.proto : Object.create(bases.proto, properties || undefined);
}
else {
proto = computeProto(bases, properties);
// first is superclass, other are traits
baseInitializer = bases[0].initializer;
// all bases are traits without properties
if (proto == null && !isTrait) {
proto = Object.create(null, properties || undefined);
}
}
var constructor = createConstructor(proto, initializer);
Object.defineProperty(constructor, "proto", {value: proto});
Object.defineProperty(constructor, "properties", {value: properties || null});
// null for trait
if (!isTrait) {
Object.defineProperty(constructor, "initializer", {value: initializer});
Object.defineProperty(initializer, "baseInitializer", {value: baseInitializer});
Object.seal(initializer);
}
Object.seal(constructor);
return constructor;
}
// as separate function to reduce scope
function createConstructor(proto, initializer) {
return function () {
var o = Object.create(proto);
if (initializer != null) {
initializer.apply(o, arguments);
}
if (initializer == null || !initializer.hasOwnProperty("skipSeal")) {
Object.seal(o);
}
return o;
};
var constructor = createConstructor(proto, initializer);
Object.defineProperty(constructor, "proto", {value: proto});
Object.defineProperty(constructor, "properties", {value: properties || null});
// null for trait
if (!isTrait) {
Object.defineProperty(constructor, "initializer", {value: initializer});
Object.defineProperty(initializer, "baseInitializer", {value: baseInitializer});
Object.freeze(initializer);
}
function computeProto(bases, properties) {
var proto = null;
for (var i = 0, n = bases.length; i < n; i++) {
var base = bases[i];
var baseProto = base.proto;
if (baseProto == null || base.properties == null) {
continue;
}
if (!proto) {
proto = Object.create(baseProto, properties || undefined);
continue;
}
// chrome bug related to getOwnPropertyDescriptor (sometimes returns undefined), so, we keep properties
//var names = Object.getOwnPropertyNames(baseProto);
//for (var j = 0, k = names.length; j < k; j++) {
// var descriptor = Object.getOwnPropertyDescriptor(baseProto, names[i]);
// Object.defineProperty(proto, names[i], descriptor);
//}
Object.defineProperties(proto, base.properties);
// todo test A -> B, C(->D) *properties from D is not yet added to proto*
}
return proto;
}
return create;
})();
Object.freeze(constructor);
return constructor;
};
Kotlin.createObject = function (initializer, properties) {
var o = Object.create(null, properties || undefined);
@@ -110,15 +96,18 @@ var Kotlin = {};
return o;
};
Kotlin.createNamespace = function (initializer, properties, classesAndNestedNamespaces) {
var o = Object.create(null, properties || undefined);
Object.defineProperty(o, "initialize", {value: initializer});
var keys = Object.keys(classesAndNestedNamespaces);
for (var i = 0, n = keys.length; i < n; i++) {
var name = keys[i];
Object.defineProperty(o, name, {value: classesAndNestedNamespaces[name]});
Kotlin.definePackage = function (functionsAndClasses, nestedNamespaces) {
var p = Object.create(null, functionsAndClasses || undefined);
if (nestedNamespaces) {
var keys = Object.keys(nestedNamespaces);
for (var i = 0, n = keys.length; i < n; i++) {
var name = keys[i];
Object.defineProperty(p, name, {value:nestedNamespaces[name]});
}
}
return o;
return p;
};
Kotlin.$new = function (f) {
@@ -126,7 +115,7 @@ var Kotlin = {};
};
Kotlin.$createClass = function (parent, properties) {
if (typeof (parent) != "function") {
if (parent !== null && typeof (parent) != "function") {
properties = parent;
parent = null;
}
@@ -161,10 +150,16 @@ var Kotlin = {};
}
}
if (initializer) {
Object.defineProperty(initializer, "skipSeal", {value: true});
}
return Kotlin.createClass(parent || null, initializer, descriptors);
};
Kotlin.defineModule = function (id, module) {
var isTestMode = id === "JS_TESTS";
if ((id in Kotlin.modules) && (!isTestMode)) {
throw Kotlin.$new(Kotlin.Exceptions.IllegalArgumentException)();
}
Object.freeze(module);
Object.defineProperty(Kotlin.modules, id, {value: module, writable: isTestMode});
};
})();
@@ -0,0 +1,7 @@
package foo
open class A() {
fun f() = 3
}
fun box() = (A().f() + bar.A().f()) == 9
@@ -0,0 +1,5 @@
package bar
open class A() {
fun f() = 6
}
@@ -0,0 +1,17 @@
package foo
object A {
val query = object {val status = "complete"}
}
object B {
private val ov = "d"
val query = object {val status = "complete" + ov}
}
class C {
val query = object {val status = "complete"}
}
fun box() = A.query.status == "complete" && B.query.status == "completed" && C().query.status == "completed"
@@ -0,0 +1,28 @@
package foo
import js.enumerable
import js.native
native
fun <T> _enumerate(o:T):T = noImpl
native
fun _findFirst<T>(o:Any):T = noImpl
enumerable
class Test() {
val a:Int = 100
val b:String = "s"
}
class P() {
enumerable
val a:Int = 100
val b:String = "s"
}
fun box():Boolean {
val test = _enumerate(Test())
val p = _enumerate(P())
return (100 == test.a && "s" == test.b) && p.a == 100 && _findFirst<Int>(object {val test = 100}) == 100;
}
@@ -0,0 +1,14 @@
package foo
trait I {
fun test():String
}
class P : I {
override fun test():String {return "a" + test("b")}
private fun test(p:String):String {return p}
}
fun box():Boolean {
return P().test() == "ab"
}
@@ -0,0 +1,13 @@
function _enumerate(o) {
var r = {};
for (var p in o) {
r[p] = o[p];
}
return r;
}
function _findFirst(o) {
for (var p in o) {
return o[p];
}
}