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="UtilityClassWithPublicConstructor" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="UtilityClassWithoutPrivateConstructor" 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="ignoreClassesWithOnlyMain" value="false" />
<option name="ignorableAnnotations">
<value />
</option>
</inspection_tool> </inspection_tool>
<inspection_tool class="VolatileLongOrDoubleField" enabled="true" level="WARNING" enabled_by_default="true" /> <inspection_tool class="VolatileLongOrDoubleField" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="WaitNotInLoop" 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"> <library name="js-libs">
<CLASSES> <CLASSES>
<root url="jar://$PROJECT_DIR$/js/js.translator/lib/json.jar!/" /> <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/dart-r3300.jar!/" />
<root url="jar://$PROJECT_DIR$/js/js.translator/lib/closure-compiler.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> </CLASSES>
<JAVADOC /> <JAVADOC />
<SOURCES> <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/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/closure-compiler.jar!/" />
<root url="jar://$PROJECT_DIR$/js/js.translator/lib/rhino-1.7R4-sources.jar!/" />
</SOURCES> </SOURCES>
</library> </library>
</component> </component>
@@ -22,6 +22,7 @@ import com.google.common.base.Predicates;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.intellij.openapi.Disposable; import com.intellij.openapi.Disposable;
import com.intellij.openapi.project.Project; import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.psi.PsiFile; import com.intellij.psi.PsiFile;
import jet.Function0; import jet.Function0;
import org.jetbrains.annotations.NotNull; 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.K2JSTranslator;
import org.jetbrains.k2js.facade.MainCallParameters; import org.jetbrains.k2js.facade.MainCallParameters;
import java.io.File;
import java.util.List; import java.util.List;
import static org.jetbrains.jet.cli.common.messages.CompilerMessageLocation.NO_LOCATION; import static org.jetbrains.jet.cli.common.messages.CompilerMessageLocation.NO_LOCATION;
@@ -63,21 +65,15 @@ public class K2JSCompiler extends CLICompiler<K2JSCompilerArguments, K2JSCompile
@NotNull @NotNull
@Override @Override
protected ExitCode doExecute(K2JSCompilerArguments arguments, PrintingMessageCollector messageCollector, Disposable rootDisposable) { protected ExitCode doExecute(K2JSCompilerArguments arguments, PrintingMessageCollector messageCollector, Disposable rootDisposable) {
if (arguments.sourceFiles == null) {
if (arguments.srcdir == null && arguments.sourceFiles == null) { messageCollector.report(CompilerMessageSeverity.ERROR, "Specify sources location via -sourceFiles", NO_LOCATION);
messageCollector.report(CompilerMessageSeverity.ERROR, "Specify sources location via -srcdir", NO_LOCATION);
return ExitCode.INTERNAL_ERROR; return ExitCode.INTERNAL_ERROR;
} }
JetCoreEnvironment environmentForJS = JetCoreEnvironment.getCoreEnvironmentForJS(rootDisposable); JetCoreEnvironment environmentForJS = JetCoreEnvironment.getCoreEnvironmentForJS(rootDisposable);
if (arguments.srcdir != null) { for (String sourceFile : arguments.sourceFiles) {
environmentForJS.addSources(arguments.srcdir); environmentForJS.addSources(sourceFile);
}
if (arguments.sourceFiles != null) {
for (String sourceFile : arguments.sourceFiles) {
environmentForJS.addSources(sourceFile);
}
} }
Project project = environmentForJS.getProject(); Project project = environmentForJS.getProject();
@@ -101,7 +97,6 @@ public class K2JSCompiler extends CLICompiler<K2JSCompilerArguments, K2JSCompile
return ExitCode.INTERNAL_ERROR; return ExitCode.INTERNAL_ERROR;
} }
MainCallParameters mainCallParameters = arguments.createMainCallParameters(); MainCallParameters mainCallParameters = arguments.createMainCallParameters();
return translateAndGenerateOutputFile(mainCallParameters, messageCollector, environmentForJS, config, outputFile); return translateAndGenerateOutputFile(mainCallParameters, messageCollector, environmentForJS, config, outputFile);
} }
@@ -151,10 +146,11 @@ public class K2JSCompiler extends CLICompiler<K2JSCompilerArguments, K2JSCompile
@NotNull @NotNull
private static Config getConfig(@NotNull K2JSCompilerArguments arguments, @NotNull Project project) { private static Config getConfig(@NotNull K2JSCompilerArguments arguments, @NotNull Project project) {
EcmaVersion ecmaVersion = EcmaVersion.fromString(arguments.target); 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 // 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; package org.jetbrains.jet.cli.js;
import com.sampullara.cli.Argument; import com.sampullara.cli.Argument;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.cli.common.CompilerArguments; import org.jetbrains.jet.cli.common.CompilerArguments;
import org.jetbrains.k2js.facade.MainCallParameters; import org.jetbrains.k2js.facade.MainCallParameters;
import java.util.ArrayList;
import java.util.List;
/** /**
* @author Pavel Talanov * @author Pavel Talanov
*/ */
/** /**
* NOTE: for now K2JSCompiler supports only minimal amount of parameters required to launch it from the plugin. * 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 { public class K2JSCompilerArguments extends CompilerArguments {
@Argument(value = "output", description = "Output file path") @Argument(value = "output", description = "Output file path")
public String outputFile; public String outputFile;
//NOTE: may well be a subject to change soon //NOTE: may well be a subject to change soon
@Argument(value = "libzip", description = "Path to zipped lib sources") @Argument(value = "libraryFiles", description = "Path to zipped lib sources or kotlin files")
public String libzip; public String[] libraryFiles;
@Argument(value = "srcdir", description = "Sources directory") @Argument(value = "sourceFiles", description = "Source files (dir or file)")
public String srcdir; public String[] sourceFiles;
@Argument(value = "target", description = "Generate js files for specific ECMA version (3 or 5, default ECMA 3)") @Argument(value = "target", description = "Generate js files for specific ECMA version (3 or 5, default ECMA 3)")
public String target; public String target;
@@ -54,14 +52,13 @@ public class K2JSCompilerArguments extends CompilerArguments {
@Argument(value = "version", description = "Display compiler version") @Argument(value = "version", description = "Display compiler version")
public boolean version; public boolean version;
@Argument(value = "mainCall", description = "Whether a main function should be invoked; either 'main' or 'mainWithArgs'") @Nullable
public String mainCall; @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") @Argument(value = "help", alias = "h", description = "Show help")
public boolean help; public boolean help;
public List<String> sourceFiles;
@Override @Override
public boolean isHelp() { public boolean isHelp() {
return help; return help;
@@ -84,22 +81,16 @@ public class K2JSCompilerArguments extends CompilerArguments {
@Override @Override
public String getSrc() { public String getSrc() {
if (sourceFiles != null) { throw new IllegalStateException();
return sourceFiles.toString();
}
return srcdir;
} }
public MainCallParameters createMainCallParameters() { public MainCallParameters createMainCallParameters() {
if (mainCall != null) { if ("noCall".equals(main)) {
if (mainCall.equals("main")) { return MainCallParameters.noCall();
return MainCallParameters.mainWithoutArguments(); }
} else {
if (mainCall.equals("mainWithArgs")) { // TODO should we pass the arguments to the compiler?
// TODO should we pass the arguments to the compiler? return MainCallParameters.mainWithoutArguments();
return MainCallParameters.mainWithArguments(new ArrayList<String>());
}
} }
return MainCallParameters.noCall();
} }
} }
@@ -17,27 +17,29 @@
package org.jetbrains.jet.plugin.compiler; package org.jetbrains.jet.plugin.compiler;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.intellij.openapi.application.AccessToken;
import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.compiler.CompileContext; import com.intellij.openapi.application.ReadAction;
import com.intellij.openapi.compiler.CompileScope; import com.intellij.openapi.compiler.*;
import com.intellij.openapi.compiler.CompilerMessageCategory;
import com.intellij.openapi.compiler.TranslatingCompiler;
import com.intellij.openapi.module.Module; 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.ModuleRootManager;
import com.intellij.openapi.roots.OrderEntry;
import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.Pair;
import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.ArrayUtil; import com.intellij.util.ArrayUtil;
import com.intellij.util.Chunk; import com.intellij.util.Chunk;
import com.intellij.util.StringBuilderSpinAllocator;
import gnu.trove.THashSet;
import jet.Function1; import jet.Function1;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.plugin.JetFileType; import org.jetbrains.jet.plugin.JetFileType;
import org.jetbrains.jet.plugin.k2jsrun.K2JSRunnerUtils;
import org.jetbrains.jet.plugin.project.JsModuleDetector; import org.jetbrains.jet.plugin.project.JsModuleDetector;
import java.io.PrintStream; import java.io.PrintStream;
import java.util.ArrayList; 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.invokeExecMethod;
import static org.jetbrains.jet.plugin.compiler.CompilerUtils.outputCompilerMessagesAndHandleExitCode; 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 * @author Pavel Talanov
*/ */
public final class K2JSCompiler implements TranslatingCompiler { public final class K2JSCompiler implements TranslatingCompiler {
@Override @Override
public boolean isCompilableFile(VirtualFile file, CompileContext context) { public boolean isCompilableFile(VirtualFile file, CompileContext context) {
if (!(file.getFileType() instanceof JetFileType)) { if (!(file.getFileType() instanceof JetFileType)) {
@@ -115,16 +116,9 @@ public final class K2JSCompiler implements TranslatingCompiler {
@NotNull @NotNull
private static Integer doExec(@NotNull CompileContext context, @NotNull CompilerEnvironment environment, @NotNull PrintStream out, private static Integer doExec(@NotNull CompileContext context, @NotNull CompilerEnvironment environment, @NotNull PrintStream out,
@NotNull Module module) throws Exception { @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); VirtualFile outDir = context.getModuleOutputDirectory(module);
String outFile = outDir == null ? null : K2JSRunnerUtils.constructPathToGeneratedFile(context.getProject(), outDir.getPath()); String outFile = outDir == null ? null : outDir.getPath() + "/" + module.getName() + ".js";
String[] commandLineArgs = constructArguments(module, outFile);
String[] commandLineArgs = constructArguments(context.getProject(), outFile, roots[0]);
Object rc = invokeExecMethod(environment, out, context, commandLineArgs, "org.jetbrains.jet.cli.js.K2JSCompiler"); Object rc = invokeExecMethod(environment, out, context, commandLineArgs, "org.jetbrains.jet.cli.js.K2JSCompiler");
if (outDir != null && !ApplicationManager.getApplication().isUnitTestMode()) { if (outDir != null && !ApplicationManager.getApplication().isUnitTestMode()) {
@@ -134,30 +128,96 @@ public final class K2JSCompiler implements TranslatingCompiler {
} }
@NotNull @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"); ArrayList<String> args = Lists.newArrayList("-tags", "-verbose", "-version");
addPathToSourcesDir(args, srcDir); addPathToSourcesDir(sourceFiles, args);
addOutputPath(outFile, args); addOutputPath(outFile, args);
addLibLocationAndTarget(project, args); addLibLocationAndTarget(module, args);
return ArrayUtil.toStringArray(args); return ArrayUtil.toStringArray(args);
} }
private static void addLibLocationAndTarget(@NotNull Project project, @NotNull ArrayList<String> args) { // we cannot use OrderEnumerator because it has critical bug — try https://gist.github.com/2953261, processor will never be called for module dependency
Pair<String, String> libLocationAndTarget = JsModuleDetector.getLibLocationAndTargetForProject(project); // we don't use context.getCompileScope().getAffectedModules() because we want to know about linkage type (well, we ignore scope right now, but in future...)
if (libLocationAndTarget.first != null) { private static void collectModuleDependencies(Module dependentModule, Set<Module> modules) {
args.add("-libzip"); for (OrderEntry entry : ModuleRootManager.getInstance(dependentModule).getOrderEntries()) {
args.add(libLocationAndTarget.first); 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) { if (libLocationAndTarget.second != null) {
args.add("-target"); args.add("-target");
args.add(libLocationAndTarget.second); args.add(libLocationAndTarget.second);
} }
} }
private static void addPathToSourcesDir(@NotNull ArrayList<String> args, @NotNull VirtualFile srcDir) { private static void addPathToSourcesDir(@NotNull VirtualFile[] sourceFiles, @NotNull ArrayList<String> args) {
String srcPath = srcDir.getPath(); args.add("-sourceFiles");
args.add("-srcdir");
args.add(srcPath); 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) { 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 com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.k2js.config.EcmaVersion; 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; import static org.jetbrains.jet.plugin.project.JsModuleDetector.getLibLocationAndTargetForProject;
/** /**
* @author Pavel Talanov * @author Pavel Talanov
*/ */
public final class IDEAConfig extends ZippedLibrarySourcesConfig { public final class IDEAConfig extends LibrarySourcesConfig {
public IDEAConfig(@NotNull Project project) { 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() { private JsModuleDetector() {
} }
public static boolean isJsProject(@NotNull Project project) {
return getJSModule(project) != null;
}
public static boolean isJsModule(@NotNull Module module) { public static boolean isJsModule(@NotNull Module module) {
return K2JSModuleComponent.getInstance(module).isJavaScriptModule(); return K2JSModuleComponent.getInstance(module).isJavaScriptModule();
} }
@@ -57,15 +53,22 @@ public final class JsModuleDetector {
} }
@NotNull @NotNull
public static Pair<String, String> getLibLocationAndTargetForProject(@NotNull Project project) { public static Pair<String[], String> getLibLocationAndTargetForProject(@NotNull Project project) {
Module module = getJSModule(project); Module module = getJSModule(project);
if (module == null) { if (module == null) {
return Pair.empty(); return Pair.empty();
} }
else {
return getLibLocationAndTargetForProject(module);
}
}
@NotNull
public static Pair<String[], String> getLibLocationAndTargetForProject(@NotNull Module module) {
K2JSModuleComponent jsModuleComponent = K2JSModuleComponent.getInstance(module); K2JSModuleComponent jsModuleComponent = K2JSModuleComponent.getInstance(module);
String pathToJavaScriptLibrary = jsModuleComponent.getPathToJavaScriptLibrary(); String pathToJavaScriptLibrary = jsModuleComponent.getPathToJavaScriptLibrary();
String basePath = ModuleRootManager.getInstance(module).getContentRoots()[0].getPath(); 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 @Nullable
+3 -1
View File
@@ -3,4 +3,6 @@ package js;
native native
public annotation class native(name : String = "") {} public annotation class native(name : String = "") {}
native 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 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 native
val console : consoleClass = js.noImpl val console:Console = noImpl
native
class consoleClass() {
fun log(message : Any?) : Unit = js.noImpl
}
+69 -130
View File
@@ -12,12 +12,11 @@ public trait Comparator<T> {
library library
public trait Iterator<T> { public trait Iterator<T> {
open fun next() : T = js.noImpl open public fun next() : T = js.noImpl
open fun hasNext() : Boolean = js.noImpl open public fun hasNext() : Boolean = js.noImpl
open fun remove() : Unit = js.noImpl open public fun remove() : Unit = js.noImpl
} }
val Collections = object { val Collections = object {
library("collectionsMax") library("collectionsMax")
public fun max<T>(col : Collection<T>, comp : Comparator<T>) : T = js.noImpl public fun max<T>(col : Collection<T>, comp : Comparator<T>) : T = js.noImpl
@@ -55,120 +54,74 @@ val Collections = object {
} }
library library
public open class ArrayList<E>() : java.util.List<E> { public trait Collection<E>: Iterable<E> {
public override fun size() : Int = js.noImpl open public fun size(): Int
public override fun isEmpty() : Boolean = js.noImpl open public fun isEmpty(): Boolean
public override fun contains(o : Any?) : Boolean = js.noImpl open public fun contains(o: Any?): Boolean
public override fun iterator() : Iterator<E> = js.noImpl override public fun iterator(): Iterator<E>
// public override fun indexOf(o : Any?) : Int = js.noImpl public fun toArray(): Array<E>
// public override fun lastIndexOf(o : Any?) : Int = js.noImpl // open public fun toArray<T>(a : Array<out T>) : Array<T>
// public override fun toArray() : Array<Any?> = js.noImpl open public fun add(e: E): Boolean
// public override fun toArray<T>(a : Array<out T>) : Array<T> = js.noImpl open public fun remove(o: Any?): Boolean
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
//open public fun containsAll(c : java.util.Collection<*>) : 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 removeAll(c : java.util.Collection<*>) : Boolean
//open public fun retainAll(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 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 library
public abstract open class AbstractList<E>() : AbstractCollection<E>(), List<E> { public trait List<E>: Collection<E> {
public override fun isEmpty() : Boolean = js.noImpl public fun get(index: Int): E
public override fun contains(o : Any?) : Boolean = js.noImpl public fun set(index: Int, element: E): E
public override fun iterator() : Iterator<E> = js.noImpl
// public override fun indexOf(o : Any?) : Int = js.noImpl public fun add(index: Int, element: E): Unit
// public override fun lastIndexOf(o : Any?) : Int = js.noImpl public fun remove(index: Int): E
// public override fun toArray() : Array<Any?> = js.noImpl
// public override fun toArray<T>(a : Array<out T>) : Array<T> = js.noImpl public fun indexOf(o: E?): Int
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 library
public trait List<E> : Collection<E> { public abstract class AbstractList<E>(): AbstractCollection<E>(), List<E> {
override public fun size() : Int override public fun get(index: Int): E = js.noImpl
override public fun isEmpty() : Boolean override public fun set(index: Int, element: E): E = js.noImpl
override public fun contains(o : Any?) : Boolean
override public fun iterator() : java.util.Iterator<E> library("addAt")
// override public fun toArray() : Array<Any?> override public public fun add(index: Int, element: E): Unit = js.noImpl
// Simulate Java's array covariance
// override public fun toArray<T>(a : Array<out T>) : Array<T> library("removeAt")
override public fun add(e : E) : Boolean override public fun remove(index: Int): E = js.noImpl
override public fun remove(o : Any?) : Boolean
// override public fun containsAll(c : java.util.Collection<*>) : Boolean override public fun indexOf(o: E?): Int = js.noImpl
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 library
// override public fun retainAll(c : java.util.Collection<*>) : Boolean public open class ArrayList<E>() : AbstractList<E>() {
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
} }
library library
public trait Set<E> : Collection<E> { 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 library
public open class HashSet<E>() : java.util.Set<E> { public open class HashSet<E>(): AbstractCollection<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
} }
library library
@@ -186,23 +139,23 @@ public trait Map<K, V> {
open public fun values() : java.util.Collection<V> open public fun values() : java.util.Collection<V>
open public fun entrySet() : java.util.Set<Entry<K, V>> open public fun entrySet() : java.util.Set<Entry<K, V>>
// open public fun equals(o : Any?) : Boolean // open public fun equals(o : Any?) : Boolean
// open public fun hashCode() : Int // open public fun hashCode() : Int
trait Entry<K, V> { trait Entry<K, V> {
open public fun getKey() : K open public fun getKey() : K
open public fun getValue() : V open public fun getValue() : V
open public fun setValue(value : V) : V open public fun setValue(value : V) : V
// open public fun equals(o : Any?) : Boolean // open public fun equals(o : Any?) : Boolean
// open public fun hashCode() : Int // open public fun hashCode() : Int
} }
} }
library 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 size() : Int = js.noImpl
public override fun isEmpty() : Boolean = 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 containsKey(key : Any?) : Boolean = js.noImpl
public override fun put(key : K, value : V) : V = 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 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 library
public open class LinkedList<E>() : List<E> { public open class LinkedList<E>(): AbstractList<E>() {
public override fun iterator() : java.util.Iterator<E> = js.noImpl public override fun get(index: Int): E = js.noImpl
public override fun isEmpty() : Boolean = js.noImpl public override fun set(index: Int, element: E): E = js.noImpl
public override fun contains(o : Any?) : Boolean = js.noImpl public override fun add(index: Int, element: E): Unit = js.noImpl
public override fun size() : Int = js.noImpl public fun poll(): E? = js.noImpl
public override fun add(e : E) : Boolean = js.noImpl public fun peek(): E? = js.noImpl
public override fun remove(o : Any?) : Boolean = js.noImpl public fun offer(e: E): 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
} }
library library
public class StringBuilder() : Appendable { public class StringBuilder() : Appendable {
override fun append(c: Char): Appendable? = js.noImpl override public fun append(c: Char): Appendable? = js.noImpl
override fun append(csq: CharSequence?): Appendable? = js.noImpl override public fun append(csq: CharSequence?): Appendable? = js.noImpl
override fun append(csq: CharSequence?, start: Int, end: Int): 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 append(obj : Any?) : StringBuilder = js.noImpl
public fun toString() : String = js.noImpl public fun toString() : String = js.noImpl
} }
library library
public class NoSuchElementException() : Exception() {} public class NoSuchElementException() : Exception() {}
public trait Enumeration<E> {
open fun hasMoreElements(): Boolean
open fun nextElement(): E?
}
+10 -1
View File
@@ -21,4 +21,13 @@ library("jsonFromTuples")
public fun json2(pairs : Array<Tuple2<String, Any?>>) : Json = js.noImpl public fun json2(pairs : Array<Tuple2<String, Any?>>) : Json = js.noImpl
library("jsonAddProperties") 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 CASES = "cases/";
private static final String OUT = "out/"; private static final String OUT = "out/";
private static final String EXPECTED = "expected/"; private static final String EXPECTED = "expected/";
public static final String JSLINT_LIB = pathToTestFilesRoot() + "jslint.js";
@NotNull @NotNull
private String mainDirectory = ""; private String mainDirectory = "";
@@ -42,7 +42,7 @@ public abstract class SingleFileTranslationTest extends BasicTest {
runFunctionOutputTest(EcmaVersion.all(), kotlinFilename, namespaceName, functionName, expectedResult); 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 namespaceName,
@NotNull String functionName, @NotNull String functionName,
@NotNull Object expectedResult) throws Exception { @NotNull Object expectedResult) throws Exception {
@@ -50,7 +50,7 @@ public abstract class SingleFileTranslationTest extends BasicTest {
runRhinoTests(kotlinFilename, ecmaVersions, new RhinoFunctionResultChecker(namespaceName, functionName, expectedResult)); 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); runFunctionOutputTest(ecmaVersions, filename, "foo", "box", true);
} }
@@ -58,7 +58,7 @@ public abstract class SingleFileTranslationTest extends BasicTest {
checkFooBoxIsTrue(getTestName(true) + ".kt", EcmaVersion.all()); 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); checkFooBoxIsTrue(getTestName(true) + ".kt", ecmaVersions);
} }
@@ -84,7 +84,7 @@ public abstract class SingleFileTranslationTest extends BasicTest {
runRhinoTests(kotlinFilename, ecmaVersions, new RhinoSystemOutputChecker(expectedResult)); 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 testName,
@NotNull String testId, @NotNull String testId,
@NotNull String... args) throws Exception { @NotNull String... args) throws Exception {
@@ -28,8 +28,11 @@ import java.util.List;
/** /**
* @author Pavel Talanov * @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 @NotNull
private final List<JetFile> jsLibFiles; private final List<JetFile> jsLibFiles;
@NotNull @NotNull
@@ -37,7 +40,7 @@ public class TestConfig extends Config {
public TestConfig(@NotNull Project project, @NotNull EcmaVersion version, public TestConfig(@NotNull Project project, @NotNull EcmaVersion version,
@NotNull List<JetFile> files, @NotNull BindingContext context) { @NotNull List<JetFile> files, @NotNull BindingContext context) {
super(project, version); super(project, TEST_MODULE_NAME, version);
jsLibFiles = files; jsLibFiles = files;
libraryContext = context; 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; package org.jetbrains.k2js.test.rhino;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.NativeJavaObject; import org.mozilla.javascript.NativeJavaObject;
/** /**
@@ -33,13 +34,13 @@ public class RhinoFunctionNativeObjectResultChecker extends RhinoFunctionResultC
} }
@Override @Override
protected void assertResultValid(Object result) { protected void assertResultValid(Object result, Context context) {
if (result instanceof NativeJavaObject) { if (result instanceof NativeJavaObject) {
NativeJavaObject nativeJavaObject = (NativeJavaObject) result; NativeJavaObject nativeJavaObject = (NativeJavaObject) result;
Object unwrap = nativeJavaObject.unwrap(); Object unwrap = nativeJavaObject.unwrap();
super.assertResultValid(unwrap); super.assertResultValid(unwrap, context);
} else { } else {
super.assertResultValid(result); super.assertResultValid(result, context);
} }
} }
} }
@@ -17,6 +17,8 @@
package org.jetbrains.k2js.test.rhino; package org.jetbrains.k2js.test.rhino;
import org.jetbrains.annotations.Nullable; 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.Context;
import org.mozilla.javascript.Scriptable; import org.mozilla.javascript.Scriptable;
@@ -46,11 +48,12 @@ public class RhinoFunctionResultChecker implements RhinoResultChecker {
public void runChecks(Context context, Scriptable scope) throws Exception { public void runChecks(Context context, Scriptable scope) throws Exception {
Object result = evaluateFunction(context, scope); Object result = evaluateFunction(context, scope);
flushSystemOut(context, scope); flushSystemOut(context, scope);
assertResultValid(result); assertResultValid(result, context);
} }
protected void assertResultValid(Object result) { protected void assertResultValid(Object result, Context context) {
assertEquals("Result of " + namespaceName + "." + functionName + "() is not what expected!", expectedResult, result); 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); String report = namespaceName + "." + functionName + "() = " + Context.toString(result);
System.out.println(report); System.out.println(report);
} }
@@ -60,10 +63,14 @@ public class RhinoFunctionResultChecker implements RhinoResultChecker {
} }
private String functionCallString() { private String functionCallString() {
String result = functionName + "()"; StringBuilder sb = new StringBuilder();
if (namespaceName != null) { 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; package org.jetbrains.k2js.test.rhino;
import closurecompiler.internal.com.google.common.collect.Maps; 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.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.k2js.config.EcmaVersion; import org.jetbrains.k2js.config.EcmaVersion;
import org.jetbrains.k2js.facade.K2JSTranslator; import org.jetbrains.k2js.facade.K2JSTranslator;
import org.mozilla.javascript.Context; import org.jetbrains.k2js.test.BasicTest;
import org.mozilla.javascript.Scriptable; import org.mozilla.javascript.*;
import org.mozilla.javascript.ScriptableObject;
import java.io.File;
import java.io.FileReader; import java.io.FileReader;
import java.io.IOException;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@@ -37,6 +41,28 @@ import static org.jetbrains.k2js.test.BasicTest.pathToTestFilesRoot;
* @author Pavel Talanov * @author Pavel Talanov
*/ */
public final class RhinoUtils { 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"; 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"; 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, private static void runFileWithRhino(@NotNull String inputFile,
@NotNull Context context, @NotNull Context context,
@NotNull Scriptable scope) throws Exception { @NotNull Scriptable scope) throws Exception {
@@ -75,6 +110,8 @@ public final class RhinoUtils {
runFileWithRhino(filename, context, scope); runFileWithRhino(filename, context, scope);
} }
checker.runChecks(context, scope); checker.runChecks(context, scope);
lintIt(context, fileNames.get(fileNames.size() - 1));
} }
finally { finally {
Context.exit(); Context.exit();
@@ -147,4 +184,61 @@ public final class RhinoUtils {
static void flushSystemOut(@NotNull Context context, @NotNull Scriptable scope) { static void flushSystemOut(@NotNull Context context, @NotNull Scriptable scope) {
context.evaluateString(scope, K2JSTranslator.FLUSH_SYSTEM_OUT, "test", 0, null); 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(); fooBoxTest();
} }
public void testToArray() throws Exception {
fooBoxTest();
}
public void testIndexOOB() throws Exception { public void testIndexOOB() throws Exception {
try { try {
fooBoxTest(); fooBoxTest();
@@ -74,4 +74,8 @@ public final class ExtensionFunctionTest extends SingleFileTranslationTest {
public void testExtensionPropertyOnClassWithExplicitAndImplicitReceiver() throws Exception { public void testExtensionPropertyOnClassWithExplicitAndImplicitReceiver() throws Exception {
fooBoxTest(); fooBoxTest();
} }
public void testExtensionFunctionCalledFromFor() throws Exception {
fooBoxTest();
}
} }
@@ -34,4 +34,8 @@ public final class MultiFileTest extends MultipleFilesTranslationTest {
public void testClassesInheritedFromOtherFile() throws Exception { public void testClassesInheritedFromOtherFile() throws Exception {
checkFooBoxIsTrue("classesInheritedFromOtherFile"); checkFooBoxIsTrue("classesInheritedFromOtherFile");
} }
public void testClassOfTheSameNameInAnotherPackage() throws Exception {
checkFooBoxIsTrue("classOfTheSameNameInAnotherPackage");
}
} }
@@ -16,8 +16,11 @@
package org.jetbrains.k2js.test.semantics; package org.jetbrains.k2js.test.semantics;
import org.jetbrains.k2js.config.EcmaVersion;
import org.jetbrains.k2js.test.SingleFileTranslationTest; import org.jetbrains.k2js.test.SingleFileTranslationTest;
import java.util.EnumSet;
/** /**
* @author Pavel Talanov * @author Pavel Talanov
*/ */
@@ -41,9 +44,13 @@ public final class ObjectTest extends SingleFileTranslationTest {
fooBoxTest(); fooBoxTest();
} }
public void testObjectInObject() throws Exception {
fooBoxTest(EnumSet.noneOf(EcmaVersion.class));
}
public void testObjectInheritingFromATrait() throws Exception { public void testObjectInheritingFromATrait() throws Exception {
fooBoxTest(); fooBoxTest();
} }
} }
@@ -16,10 +16,14 @@
package org.jetbrains.k2js.test.semantics; 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.config.EcmaVersion;
import org.jetbrains.k2js.test.SingleFileTranslationTest; import org.jetbrains.k2js.test.SingleFileTranslationTest;
import org.jetbrains.k2js.test.utils.JsTestUtils;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.List;
/** /**
* @author Pavel Talanov * @author Pavel Talanov
@@ -79,4 +83,23 @@ public final class PropertyAccessTest extends SingleFileTranslationTest {
public void testInitInstanceProperties() throws Exception { public void testInitInstanceProperties() throws Exception {
fooBoxTest(EnumSet.of(EcmaVersion.v5)); 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(); K2JSCompiler compiler = new K2JSCompiler();
K2JSCompilerArguments arguments = new K2JSCompilerArguments(); K2JSCompilerArguments arguments = new K2JSCompilerArguments();
arguments.outputFile = getOutputFilePath(getTestName(false) + ".compiler.kt", version); arguments.outputFile = getOutputFilePath(getTestName(false) + ".compiler.kt", version);
arguments.sourceFiles = files; arguments.sourceFiles = files.toArray(new String[files.size()]);
arguments.verbose = true; arguments.verbose = true;
System.out.println("Compiling with version: " + version + " to: " + arguments.outputFile); System.out.println("Compiling with version: " + version + " to: " + arguments.outputFile);
ExitCode answer = compiler.exec(System.out, arguments); ExitCode answer = compiler.exec(System.out, arguments);
@@ -24,6 +24,7 @@ import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List; import java.util.List;
/** /**
@@ -34,6 +35,11 @@ public final class JsTestUtils {
private JsTestUtils() { private JsTestUtils() {
} }
@NotNull
public static EnumSet<EcmaVersion> successOnEcmaV5() {
return EnumSet.of(EcmaVersion.v5);
}
@NotNull @NotNull
public static String convertFileNameToDotJsFile(@NotNull String filename, @NotNull EcmaVersion ecmaVersion) { public static String convertFileNameToDotJsFile(@NotNull String filename, @NotNull EcmaVersion ecmaVersion) {
String postFix = "_" + ecmaVersion.toString() + ".js"; 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.Predicate;
import com.google.common.base.Predicates; import com.google.common.base.Predicates;
import com.google.common.collect.Sets;
import com.intellij.openapi.project.Project; import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiFile; import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NotNull; 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.jet.lang.types.lang.JetStandardClasses;
import org.jetbrains.k2js.config.Config; import org.jetbrains.k2js.config.Config;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Set;
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.isRootNamespace; import static org.jetbrains.jet.lang.resolve.DescriptorUtils.isRootNamespace;
@@ -136,7 +135,7 @@ public final class AnalyzerFacadeForJS {
@NotNull @NotNull
public static Collection<JetFile> withJsLibAdded(@NotNull Collection<JetFile> files, @NotNull Config config) { 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(files);
allFiles.addAll(config.getLibFiles()); allFiles.addAll(config.getLibFiles());
return allFiles; return allFiles;
@@ -16,11 +16,11 @@
package org.jetbrains.k2js.config; package org.jetbrains.k2js.config;
import org.jetbrains.annotations.NotNull;
import com.intellij.openapi.project.Project; import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetFile; 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 * 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 class ClassPathLibraryDefintionsConfig extends Config {
public static final String META_INF_SERVICES_FILE = "META-INF/services/org.jetbrains.kotlin.js.libraryDefinitions"; public static final String META_INF_SERVICES_FILE = "META-INF/services/org.jetbrains.kotlin.js.libraryDefinitions";
public ClassPathLibraryDefintionsConfig(@NotNull Project project, @NotNull EcmaVersion version) { public ClassPathLibraryDefintionsConfig(@NotNull Project project, @NotNull String moduleId, @NotNull EcmaVersion version) {
super(project, version); super(project, moduleId, version);
} }
@NotNull @NotNull
@@ -36,7 +36,7 @@ public abstract class Config {
@NotNull @NotNull
public static Config getEmptyConfig(@NotNull Project project, @NotNull EcmaVersion ecmaVersion) { public static Config getEmptyConfig(@NotNull Project project, @NotNull EcmaVersion ecmaVersion) {
return new Config(project, ecmaVersion) { return new Config(project, "main", ecmaVersion) {
@NotNull @NotNull
@Override @Override
protected List<JetFile> generateLibFiles() { protected List<JetFile> generateLibFiles() {
@@ -133,9 +133,13 @@ public abstract class Config {
@NotNull @NotNull
private final EcmaVersion target; 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.project = project;
this.target = ecmaVersion; this.target = ecmaVersion;
this.moduleId = moduleId;
} }
@NotNull @NotNull
@@ -148,6 +152,11 @@ public abstract class Config {
return target; return target;
} }
@NotNull
public String getModuleId() {
return moduleId;
}
@NotNull @NotNull
protected abstract List<JetFile> generateLibFiles(); protected abstract List<JetFile> generateLibFiles();
@@ -18,6 +18,7 @@ package org.jetbrains.k2js.config;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.intellij.openapi.project.Project; import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.io.FileUtil;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@@ -27,6 +28,7 @@ import org.jetbrains.k2js.utils.JetFileUtils;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.List; import java.util.List;
@@ -36,33 +38,63 @@ import java.util.zip.ZipFile;
/** /**
* @author Pavel Talanov * @author Pavel Talanov
*/ */
public class ZippedLibrarySourcesConfig extends Config { public class LibrarySourcesConfig extends Config {
@Nullable public static final Key<String> EXTERNAL_MODULE_NAME = new Key<String>("externalModule");
protected final String pathToLibZip; public static final String UNKNOWN_EXTERNAL_MODULE_NAME = "<unknown>";
public ZippedLibrarySourcesConfig(@NotNull Project project, @Nullable String pathToZip, @NotNull EcmaVersion ecmaVersion) { @Nullable
super(project, ecmaVersion); private final String[] files;
pathToLibZip = pathToZip;
public LibrarySourcesConfig(@NotNull Project project,
@NotNull String moduleId,
@Nullable String[] files,
@NotNull EcmaVersion ecmaVersion) {
super(project, moduleId, ecmaVersion);
this.files = files;
} }
@NotNull @NotNull
@Override @Override
public List<JetFile> generateLibFiles() { public List<JetFile> generateLibFiles() {
if (pathToLibZip == null) { if (files == null) {
return Collections.emptyList(); return Collections.emptyList();
} }
try {
File file = new File(pathToLibZip); List<JetFile> jetFiles = new ArrayList<JetFile>();
ZipFile zipFile = new ZipFile(file); String moduleName = UNKNOWN_EXTERNAL_MODULE_NAME;
for (String path : files) {
File file = new File(path);
try { 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 { catch (IOException e) {
zipFile.close(); 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); InputStream stream = file.getInputStream(entry);
String text = FileUtil.loadTextAndClose(stream); String text = FileUtil.loadTextAndClose(stream);
JetFile jetFile = JetFileUtils.createPsiFile(entry.getName(), text, getProject()); JetFile jetFile = JetFileUtils.createPsiFile(entry.getName(), text, getProject());
jetFile.putUserData(EXTERNAL_MODULE_NAME, UNKNOWN_EXTERNAL_MODULE_NAME);
result.add(jetFile); result.add(jetFile);
} }
} }
@@ -32,7 +32,6 @@ import org.jetbrains.k2js.utils.JetFileUtils;
import java.io.IOException; import java.io.IOException;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection;
import java.util.List; import java.util.List;
import static org.jetbrains.k2js.facade.FacadeUtils.parseString; import static org.jetbrains.k2js.facade.FacadeUtils.parseString;
@@ -97,9 +96,7 @@ public final class K2JSTranslator {
throws TranslationException { throws TranslationException {
JetStandardLibrary.initialize(config.getProject()); JetStandardLibrary.initialize(config.getProject());
BindingContext bindingContext = AnalyzerFacadeForJS.analyzeFilesAndCheckErrors(filesToTranslate, config); BindingContext bindingContext = AnalyzerFacadeForJS.analyzeFilesAndCheckErrors(filesToTranslate, config);
Collection<JetFile> files = AnalyzerFacadeForJS.withJsLibAdded(filesToTranslate, config); return Translation.generateAst(bindingContext, filesToTranslate, mainCallParameters, config, rawStatements);
return Translation.generateAst(bindingContext, Lists.newArrayList(files), mainCallParameters, config.getTarget(), rawStatements);
} }
@NotNull @NotNull
@@ -25,7 +25,6 @@ import java.util.List;
* @author Pavel Talanov * @author Pavel Talanov
*/ */
public abstract class MainCallParameters { public abstract class MainCallParameters {
@NotNull @NotNull
public static MainCallParameters noCall() { public static MainCallParameters noCall() {
return new MainCallParameters() { return new MainCallParameters() {
@@ -53,8 +53,13 @@ public final class DynamicContext {
@NotNull @NotNull
public TemporaryVariable declareTemporary(@NotNull JsExpression initExpression) { public TemporaryVariable declareTemporary(@NotNull JsExpression initExpression) {
return declareTemporary(initExpression, false);
}
@NotNull
public TemporaryVariable declareTemporary(@NotNull JsExpression initExpression, boolean initialize) {
JsName temporaryName = currentScope.declareTemporary(); 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); addVarDeclaration(jsBlock(), temporaryDeclaration);
return new TemporaryVariable(temporaryName, initExpression); 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 INITIALIZE_METHOD_NAME = "initialize";
private static final String CLASS_OBJECT_NAME = "createClass"; private static final String CLASS_OBJECT_NAME = "createClass";
private static final String TRAIT_OBJECT_NAME = "createTrait"; 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 OBJECT_OBJECT_NAME = "createObject";
private static final String SETTER_PREFIX = "set_"; private static final String SETTER_PREFIX = "set_";
private static final String GETTER_PREFIX = "get_"; private static final String GETTER_PREFIX = "get_";
private static final String BACKING_FIELD_PREFIX = "$"; private static final String BACKING_FIELD_PREFIX = "$";
private static final String SUPER_METHOD_NAME = "super_init"; private static final String SUPER_METHOD_NAME = "super_init";
private static final String KOTLIN_OBJECT_NAME = "Kotlin"; 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 RECEIVER_PARAMETER_NAME = "receiver";
private static final String CLASSES_OBJECT_NAME = "classes"; private static final String CLASSES_OBJECT_NAME = "classes";
private static final String THROW_NPE_FUN_NAME = "throwNPE"; private static final String THROW_NPE_FUN_NAME = "throwNPE";
@@ -112,7 +111,7 @@ public final class Namer {
@NotNull @NotNull
private final JsName traitName; private final JsName traitName;
@NotNull @NotNull
private final JsName namespaceName; private final JsExpression definePackage;
@NotNull @NotNull
private final JsName objectName; private final JsName objectName;
@@ -122,17 +121,24 @@ public final class Namer {
@NotNull @NotNull
private final JsPropertyInitializer writablePropertyDescriptorField; private final JsPropertyInitializer writablePropertyDescriptorField;
@NotNull
private final JsPropertyInitializer enumerablePropertyDescriptorField;
private Namer(@NotNull JsScope rootScope) { private Namer(@NotNull JsScope rootScope) {
kotlinName = rootScope.declareName(KOTLIN_OBJECT_NAME); kotlinName = rootScope.declareName(KOTLIN_OBJECT_NAME);
kotlinScope = new JsScope(rootScope, "Kotlin standard object"); kotlinScope = new JsScope(rootScope, "Kotlin standard object");
traitName = kotlinScope.declareName(TRAIT_OBJECT_NAME); traitName = kotlinScope.declareName(TRAIT_OBJECT_NAME);
namespaceName = kotlinScope.declareName(NAMESPACE_OBJECT_NAME);
definePackage = kotlin("definePackage");
className = kotlinScope.declareName(CLASS_OBJECT_NAME); className = kotlinScope.declareName(CLASS_OBJECT_NAME);
objectName = kotlinScope.declareName(OBJECT_OBJECT_NAME); objectName = kotlinScope.declareName(OBJECT_OBJECT_NAME);
isTypeName = kotlinScope.declareName("isType"); 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 @NotNull
@@ -146,8 +152,8 @@ public final class Namer {
} }
@NotNull @NotNull
public JsExpression namespaceCreationMethodReference() { public JsExpression packageDefinitionMethodReference() {
return kotlin(namespaceName); return definePackage;
} }
@NotNull @NotNull
@@ -164,14 +170,17 @@ public final class Namer {
@NotNull @NotNull
private JsExpression kotlin(@NotNull JsName name) { private JsExpression kotlin(@NotNull JsName name) {
JsNameRef reference = name.makeRef(); return kotlin(name.makeRef());
reference.setQualifier(kotlinName.makeRef()); }
return reference;
@NotNull
public JsExpression kotlin(@NotNull String name) {
return kotlin(kotlinScope.declareName(name));
} }
@NotNull @NotNull
private JsExpression kotlin(@NotNull JsExpression reference) { private JsExpression kotlin(@NotNull JsExpression reference) {
setQualifier(reference, kotlinName.makeRef()); setQualifier(reference, kotlinObject());
return reference; return reference;
} }
@@ -190,6 +199,11 @@ public final class Namer {
return writablePropertyDescriptorField; return writablePropertyDescriptorField;
} }
@NotNull
public JsPropertyInitializer enumerablePropertyDescriptorField() {
return enumerablePropertyDescriptorField;
}
@NotNull @NotNull
/*package*/ JsScope getKotlinScope() { /*package*/ JsScope getKotlinScope() {
return kotlinScope; return kotlinScope;
@@ -18,13 +18,17 @@ package org.jetbrains.k2js.translate.context;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.dart.compiler.backend.js.ast.*; 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.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.resolve.BindingContext; 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.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.types.lang.JetStandardLibrary; import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
import org.jetbrains.k2js.config.EcmaVersion; 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.Generator;
import org.jetbrains.k2js.translate.context.generator.Rule; import org.jetbrains.k2js.translate.context.generator.Rule;
import org.jetbrains.k2js.translate.intrinsic.Intrinsics; import org.jetbrains.k2js.translate.intrinsic.Intrinsics;
@@ -105,6 +109,11 @@ public final class StaticContext {
return ecmaVersion == EcmaVersion.v5; return ecmaVersion == EcmaVersion.v5;
} }
@NotNull
public EcmaVersion getEcmaVersion() {
return ecmaVersion;
}
@NotNull @NotNull
public JsProgram getProgram() { public JsProgram getProgram() {
return program; return program;
@@ -153,6 +162,14 @@ public final class StaticContext {
} }
private final class NameGenerator extends Generator<JsName> { 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() { public NameGenerator() {
Rule<JsName> namesForStandardClasses = new Rule<JsName>() { Rule<JsName> namesForStandardClasses = new Rule<JsName>() {
@Override @Override
@@ -171,8 +188,16 @@ public final class StaticContext {
if (!(descriptor instanceof NamespaceDescriptor)) { if (!(descriptor instanceof NamespaceDescriptor)) {
return null; 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>() { Rule<JsName> memberDeclarationsInsideParentsScope = new Rule<JsName>() {
@@ -180,6 +205,9 @@ public final class StaticContext {
@Nullable @Nullable
public JsName apply(@NotNull DeclarationDescriptor descriptor) { public JsName apply(@NotNull DeclarationDescriptor descriptor) {
NamingScope namingScope = getEnclosingScope(descriptor); NamingScope namingScope = getEnclosingScope(descriptor);
if (descriptor instanceof ClassDescriptor) {
return namingScope.declareUnobfuscatableName(descriptor.getName().getName());
}
return namingScope.declareObfuscatableName(descriptor.getName().getName()); return namingScope.declareObfuscatableName(descriptor.getName().getName());
} }
}; };
@@ -203,11 +231,9 @@ public final class StaticContext {
boolean isGetter = descriptor instanceof PropertyGetterDescriptor; boolean isGetter = descriptor instanceof PropertyGetterDescriptor;
PropertyAccessorDescriptor accessorDescriptor = (PropertyAccessorDescriptor) descriptor; PropertyAccessorDescriptor accessorDescriptor = (PropertyAccessorDescriptor) descriptor;
String propertyName = accessorDescriptor.getCorrespondingProperty().getName().getName(); String propertyName = accessorDescriptor.getCorrespondingProperty().getName().getName();
String accessorName = Namer.getNameForAccessor(propertyName, isGetter, !accessorDescriptor.getReceiverParameter().exists() && isEcma5()); String accessorName = Namer.getNameForAccessor(propertyName, isGetter,
NamingScope enclosingScope = getEnclosingScope(descriptor); !accessorDescriptor.getReceiverParameter().exists() && isEcma5());
return isEcma5() return declareName(descriptor, accessorName);
? enclosingScope.declareUnobfuscatableName(accessorName)
: enclosingScope.declareObfuscatableName(accessorName);
} }
}; };
@@ -232,19 +258,12 @@ public final class StaticContext {
return null; return null;
} }
//TODO: move somewhere String name = descriptor.getName().getName();
NamingScope enclosingScope = getEnclosingScope(descriptor); if (!isEcma5() || JsDescriptorUtils.isAsPrivate((PropertyDescriptor) descriptor)) {
if (isEcma5()) { name = Namer.getKotlinBackingFieldName(name);
String name = descriptor.getName().getName(); }
if (JsDescriptorUtils.isAsPrivate((PropertyDescriptor) descriptor)) {
name = '_' + name;
}
return enclosingScope.declareUnobfuscatableName(name); return declareName(descriptor, name);
}
else {
return enclosingScope.declareObfuscatableName(Namer.getKotlinBackingFieldName(descriptor.getName().getName()));
}
} }
}; };
//TODO: hack! //TODO: hack!
@@ -386,14 +405,50 @@ public final class StaticContext {
Rule<JsNameRef> namespaceLevelDeclarationsHaveEnclosingNamespacesNamesAsQualifier = new Rule<JsNameRef>() { Rule<JsNameRef> namespaceLevelDeclarationsHaveEnclosingNamespacesNamesAsQualifier = new Rule<JsNameRef>() {
@Override @Override
public JsNameRef apply(@NotNull DeclarationDescriptor descriptor) { public JsNameRef apply(@NotNull DeclarationDescriptor descriptor) {
DeclarationDescriptor containingDeclaration = getContainingDeclaration(descriptor); DeclarationDescriptor containingDescriptor = getContainingDeclaration(descriptor);
if (!(containingDeclaration instanceof NamespaceDescriptor)) { if (!(containingDescriptor instanceof NamespaceDescriptor)) {
return null; return null;
} }
JsName containingDeclarationName = getNameForDescriptor(containingDeclaration);
JsNameRef qualifier = containingDeclarationName.makeRef(); final JsNameRef result = new JsNameRef(getNameForDescriptor(containingDescriptor));
qualifier.setQualifier(getQualifierForDescriptor(containingDeclaration)); if (DescriptorUtils.isRootNamespace((NamespaceDescriptor) containingDescriptor)) {
return qualifier; 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>() { Rule<JsNameRef> constructorHaveTheSameQualifierAsTheClass = new Rule<JsNameRef>() {
@@ -449,10 +504,7 @@ public final class StaticContext {
Rule<Boolean> topLevelNamespaceHaveNoQualifier = new Rule<Boolean>() { Rule<Boolean> topLevelNamespaceHaveNoQualifier = new Rule<Boolean>() {
@Override @Override
public Boolean apply(@NotNull DeclarationDescriptor descriptor) { public Boolean apply(@NotNull DeclarationDescriptor descriptor) {
if (!(descriptor instanceof NamespaceDescriptor)) { if (descriptor instanceof NamespaceDescriptor && DescriptorUtils.isRootNamespace((NamespaceDescriptor) descriptor)) {
return null;
}
if (DescriptorUtils.isTopLevelNamespace((NamespaceDescriptor) descriptor)) {
return true; return true;
} }
return null; 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.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.psi.JetExpression; import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.k2js.config.EcmaVersion;
import org.jetbrains.k2js.translate.intrinsic.Intrinsics; import org.jetbrains.k2js.translate.intrinsic.Intrinsics;
import java.util.Map; import java.util.Map;
@@ -58,6 +59,10 @@ public final class TranslationContext {
return staticContext.isEcma5(); return staticContext.isEcma5();
} }
public boolean isNotEcma3() {
return staticContext.getEcmaVersion() != EcmaVersion.v3;
}
private TranslationContext(@NotNull StaticContext staticContext, private TranslationContext(@NotNull StaticContext staticContext,
@NotNull DynamicContext dynamicContext, @NotNull DynamicContext dynamicContext,
@NotNull AliasingContext context) { @NotNull AliasingContext context) {
@@ -152,6 +157,11 @@ public final class TranslationContext {
return dynamicContext.declareTemporary(initExpression); return dynamicContext.declareTemporary(initExpression);
} }
@NotNull
public TemporaryVariable declareTemporary(@NotNull JsExpression initExpression, boolean initialize) {
return dynamicContext.declareTemporary(initExpression, initialize);
}
@NotNull @NotNull
public Namer namer() { public Namer namer() {
return staticContext.getNamer(); 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; 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.backend.js.ast.*;
import com.google.dart.compiler.util.AstUtil; 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.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor; 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.jet.lang.psi.JetClass;
import org.jetbrains.k2js.translate.context.Namer; import org.jetbrains.k2js.translate.context.Namer;
import org.jetbrains.k2js.translate.context.TranslationContext; import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.general.AbstractTranslator; import org.jetbrains.k2js.translate.general.AbstractTranslator;
import org.jetbrains.k2js.translate.general.Translation; import org.jetbrains.k2js.translate.utils.JsAstUtils;
import org.jetbrains.k2js.translate.utils.BindingUtils;
import org.jetbrains.k2js.translate.utils.ClassSortingUtils;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import static org.jetbrains.k2js.translate.utils.JsAstUtils.*; import static com.google.dart.compiler.backend.js.ast.JsVars.JsVar;
import static org.jetbrains.k2js.translate.utils.JsDescriptorUtils.getAllClassesDefinedInNamespace; 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 * @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. * Generates a big block where are all the classes(objects representing them) are created.
*/ */
public final class ClassDeclarationTranslator extends AbstractTranslator { public final class ClassDeclarationTranslator extends AbstractTranslator {
private int localNameCounter;
@NotNull @NotNull
private final List<ClassDescriptor> descriptors; private final THashMap<JetClass, ListItem> openClassToItem = new THashMap<JetClass, ListItem>();
@NotNull
private final BiMap<JsName, JsName> localToGlobalClassName; private final TLinkedList<ListItem> openList = new TLinkedList<ListItem>();
private final List<ListItem> finalList = new ArrayList<ListItem>();
@NotNull @NotNull
private final JsFunction dummyFunction; private final JsFunction dummyFunction;
@Nullable
private JsName declarationsObject = null;
@Nullable
private JsStatement declarationsStatement = null;
public ClassDeclarationTranslator(@NotNull List<ClassDescriptor> descriptors, private final JsName declarationsObject;
@NotNull TranslationContext context) { private final JsVar classesVar;
public ClassDeclarationTranslator(@NotNull TranslationContext context) {
super(context); super(context);
this.descriptors = descriptors;
this.localToGlobalClassName = HashBiMap.create(); dummyFunction = new JsFunction(context.jsScope());
this.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() { public void generateDeclarations() {
declarationsObject = context().jsScope().declareName(Namer.nameForClassesVariable()); JsObjectLiteral valueLiteral = new JsObjectLiteral();
assert declarationsObject != null; JsVars vars = new JsVars();
declarationsStatement = List<JsPropertyInitializer> propertyInitializers = valueLiteral.getPropertyInitializers();
newVar(declarationsObject, generateDummyFunctionInvocation());
}
@NotNull generateOpenClassDeclarations(vars, propertyInitializers);
public JsName getDeclarationsObjectName() { generateFinalClassDeclarations(vars, propertyInitializers);
assert declarationsObject != null : "Should run generateDeclarations first";
return declarationsObject;
}
@NotNull if (vars.isEmpty()) {
public JsStatement getDeclarationsStatement() { classesVar.setInitExpr(valueLiteral);
assert declarationsStatement != null : "Should run generateDeclarations first"; return;
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));
} }
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 void generateOpenClassDeclarations(@NotNull JsVars vars, @NotNull List<JsPropertyInitializer> propertyInitializers) {
private JsPropertyInitializer classEntry(@NotNull JsName localName) { ClassAliasingMap classAliasingMap = new OpenClassRefProvider();
return new JsPropertyInitializer(localToGlobalClassName.get(localName).makeRef(), localName.makeRef()); // first pass: set up list order
} for (ListItem item : openList) {
item.translatedDeclaration = translateClassDeclaration(item.declaration, classAliasingMap, context());
@NotNull
private List<JsStatement> generateClassDeclarationStatements() {
List<JsStatement> classDeclarations = new ArrayList<JsStatement>();
for (JetClass jetClass : getClassDeclarations()) {
classDeclarations.add(generateDeclaration(jetClass));
} }
return classDeclarations; // second pass: generate
} for (ListItem item : openList) {
generate(item, propertyInitializers, item.translatedDeclaration, vars);
@NotNull
private List<JetClass> getClassDeclarations() {
List<JetClass> classes = new ArrayList<JetClass>();
for (ClassDescriptor classDescriptor : descriptors) {
classes.add(BindingUtils.getClassForDescriptor(bindingContext(), classDescriptor));
} }
return ClassSortingUtils.sortUsingInheritanceOrder(classes, bindingContext());
} }
@NotNull private void generateFinalClassDeclarations(@NotNull JsVars vars, @NotNull List<JsPropertyInitializer> propertyInitializers) {
private JsStatement generateDeclaration(@NotNull JetClass declaration) { ClassAliasingMap classAliasingMap = new FinalClassRefProvider();
JsName localClassName = generateLocalAlias(declaration); for (ListItem item : finalList) {
JsExpression classDeclarationExpression = generate(item, propertyInitializers, translateClassDeclaration(item.declaration, classAliasingMap, context()), vars);
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));
} }
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 @NotNull
private JsPropertyInitializer getClassNameToClassObject(@NotNull ClassDescriptor classDescriptor) { public JsPropertyInitializer translateAndGetClassNameToClassObject(@NotNull JetClass declaration) {
JsName className = context().getNameForDescriptor(classDescriptor); ClassDescriptor descriptor = getClassDescriptor(context().bindingContext(), declaration);
JsNameRef alreadyDefinedClassReference = qualified(className, getDeclarationsObjectName().makeRef());
return new JsPropertyInitializer(className.makeRef(), alreadyDefinedClassReference); 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.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.ClassKind; import org.jetbrains.jet.lang.descriptors.ClassKind;
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; 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.JetClassOrObject;
import org.jetbrains.jet.lang.psi.JetObjectLiteralExpression; import org.jetbrains.jet.lang.psi.JetObjectLiteralExpression;
import org.jetbrains.jet.lang.psi.JetParameter; 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.AbstractTranslator;
import org.jetbrains.k2js.translate.general.Translation; import org.jetbrains.k2js.translate.general.Translation;
import org.jetbrains.k2js.translate.initializer.InitializerUtils; import org.jetbrains.k2js.translate.initializer.InitializerUtils;
import org.jetbrains.k2js.translate.utils.BindingUtils;
import org.jetbrains.k2js.translate.utils.JsAstUtils; import org.jetbrains.k2js.translate.utils.JsAstUtils;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map;
import static com.google.dart.compiler.util.AstUtil.newSequence; import static com.google.dart.compiler.util.AstUtil.newSequence;
import static org.jetbrains.k2js.translate.utils.BindingUtils.getClassDescriptor; import static org.jetbrains.k2js.translate.utils.BindingUtils.getClassDescriptor;
@@ -64,8 +64,8 @@ public final class ClassTranslator extends AbstractTranslator {
@NotNull @NotNull
public static JsExpression generateClassCreationExpression(@NotNull JetClassOrObject classDeclaration, public static JsExpression generateClassCreationExpression(@NotNull JetClassOrObject classDeclaration,
@NotNull Map<JsName, JsName> aliasingMap, @NotNull ClassAliasingMap aliasingMap,
@NotNull TranslationContext context) { @NotNull TranslationContext context) {
return (new ClassTranslator(classDeclaration, aliasingMap, context)).translateClassOrObjectCreation(); return (new ClassTranslator(classDeclaration, aliasingMap, context)).translateClassOrObjectCreation();
} }
@@ -73,13 +73,13 @@ public final class ClassTranslator extends AbstractTranslator {
public static JsExpression generateClassCreationExpression(@NotNull JetClassOrObject classDeclaration, public static JsExpression generateClassCreationExpression(@NotNull JetClassOrObject classDeclaration,
@NotNull TranslationContext context) { @NotNull TranslationContext context) {
return (new ClassTranslator(classDeclaration, Collections.<JsName, JsName>emptyMap(), context)).translateClassOrObjectCreation(); return (new ClassTranslator(classDeclaration, null, context)).translateClassOrObjectCreation();
} }
@NotNull @NotNull
public static JsExpression generateObjectLiteralExpression(@NotNull JetObjectLiteralExpression objectLiteralExpression, public static JsExpression generateObjectLiteralExpression(@NotNull JetObjectLiteralExpression objectLiteralExpression,
@NotNull TranslationContext context) { @NotNull TranslationContext context) {
return (new ClassTranslator(objectLiteralExpression.getObjectDeclaration(), Collections.<JsName, JsName>emptyMap(), context)) return (new ClassTranslator(objectLiteralExpression.getObjectDeclaration(), null, context))
.translateObjectLiteralExpression(); .translateObjectLiteralExpression();
} }
@@ -95,12 +95,12 @@ public final class ClassTranslator extends AbstractTranslator {
@NotNull @NotNull
private final ClassDescriptor descriptor; private final ClassDescriptor descriptor;
@NotNull @Nullable
private final Map<JsName, JsName> aliasingMap; private final ClassAliasingMap aliasingMap;
private ClassTranslator(@NotNull JetClassOrObject classDeclaration, private ClassTranslator(@NotNull JetClassOrObject classDeclaration,
@NotNull Map<JsName, JsName> aliasingMap, @Nullable ClassAliasingMap aliasingMap,
@NotNull TranslationContext context) { @NotNull TranslationContext context) {
super(context.newDeclaration(classDeclaration)); super(context.newDeclaration(classDeclaration));
this.aliasingMap = aliasingMap; this.aliasingMap = aliasingMap;
this.descriptor = getClassDescriptor(context.bindingContext(), classDeclaration); this.descriptor = getClassDescriptor(context.bindingContext(), classDeclaration);
@@ -160,7 +160,7 @@ public final class ClassTranslator extends AbstractTranslator {
if (!isTrait()) { if (!isTrait()) {
JsFunction initializer = Translation.generateClassInitializerMethod(classDeclaration, classDeclarationContext); JsFunction initializer = Translation.generateClassInitializerMethod(classDeclaration, classDeclarationContext);
if (context().isEcma5()) { if (context().isEcma5()) {
jsClassDeclaration.getArguments().add(isObject() ? initializer : JsAstUtils.encloseFunction(initializer)); jsClassDeclaration.getArguments().add(initializer.getName() == null ? initializer : JsAstUtils.encloseFunction(initializer));
} }
else { else {
propertyList.add(InitializerUtils.generateInitializeMethod(initializer)); propertyList.add(InitializerUtils.generateInitializeMethod(initializer));
@@ -209,8 +209,7 @@ public final class ClassTranslator extends AbstractTranslator {
private void addTraits(@NotNull List<JsExpression> superclassReferences, private void addTraits(@NotNull List<JsExpression> superclassReferences,
@NotNull List<ClassDescriptor> superclassDescriptors) { @NotNull List<ClassDescriptor> superclassDescriptors) {
for (ClassDescriptor superClassDescriptor : for (ClassDescriptor superClassDescriptor : superclassDescriptors) {
superclassDescriptors) {
assert (superClassDescriptor.getKind() == ClassKind.TRAIT) : "Only traits are expected here"; assert (superClassDescriptor.getKind() == ClassKind.TRAIT) : "Only traits are expected here";
superclassReferences.add(getClassReference(superClassDescriptor)); superclassReferences.add(getClassReference(superClassDescriptor));
} }
@@ -227,12 +226,16 @@ public final class ClassTranslator extends AbstractTranslator {
@NotNull @NotNull
private JsExpression getClassReference(@NotNull ClassDescriptor superClassDescriptor) { private JsExpression getClassReference(@NotNull ClassDescriptor superClassDescriptor) {
//NOTE: aliasing here is needed for the declaration generation step // aliasing here is needed for the declaration generation step
JsName name = context().getNameForDescriptor(superClassDescriptor); if (aliasingMap != null) {
JsName alias = aliasingMap.get(name); JsNameRef name = aliasingMap.get(BindingUtils.getClassForDescriptor(bindingContext(), superClassDescriptor),
if (alias != null) { (JetClass) classDeclaration);
return alias.makeRef(); if (name != null) {
return name;
}
} }
// from library
return getQualifiedReference(context(), superClassDescriptor); 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.JsExpression;
import com.google.dart.compiler.backend.js.ast.JsPropertyInitializer; import com.google.dart.compiler.backend.js.ast.JsPropertyInitializer;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
@@ -39,6 +40,17 @@ import static org.jetbrains.k2js.translate.utils.BindingUtils.*;
* @author Pavel Talanov * @author Pavel Talanov
*/ */
public final class DeclarationBodyVisitor extends TranslatorVisitor<List<JsPropertyInitializer>> { 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 @NotNull
public List<JsPropertyInitializer> traverseClass(@NotNull JetClassOrObject jetClass, public List<JsPropertyInitializer> traverseClass(@NotNull JetClassOrObject jetClass,
@NotNull TranslationContext context) { @NotNull TranslationContext context) {
@@ -51,7 +63,7 @@ public final class DeclarationBodyVisitor extends TranslatorVisitor<List<JsPrope
@NotNull @NotNull
public List<JsPropertyInitializer> traverseNamespace(@NotNull NamespaceDescriptor namespace, public List<JsPropertyInitializer> traverseNamespace(@NotNull NamespaceDescriptor namespace,
@NotNull TranslationContext context) { @NotNull TranslationContext context) {
List<JsPropertyInitializer> properties = new ArrayList<JsPropertyInitializer>(); List<JsPropertyInitializer> properties = new ArrayList<JsPropertyInitializer>();
for (JetDeclaration declaration : getDeclarationsForNamespace(context.bindingContext(), namespace)) { for (JetDeclaration declaration : getDeclarationsForNamespace(context.bindingContext(), namespace)) {
properties.addAll(declaration.accept(this, context)); properties.addAll(declaration.accept(this, context));
@@ -62,7 +74,11 @@ public final class DeclarationBodyVisitor extends TranslatorVisitor<List<JsPrope
@Override @Override
@NotNull @NotNull
public List<JsPropertyInitializer> visitClass(@NotNull JetClass expression, @NotNull TranslationContext context) { 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 @Override
@@ -71,10 +87,9 @@ public final class DeclarationBodyVisitor extends TranslatorVisitor<List<JsPrope
@NotNull TranslationContext context) { @NotNull TranslationContext context) {
JsPropertyInitializer methodAsPropertyInitializer = Translation.functionTranslator(expression, context).translateAsMethod(); JsPropertyInitializer methodAsPropertyInitializer = Translation.functionTranslator(expression, context).translateAsMethod();
if (context.isEcma5()) { if (context.isEcma5()) {
final FunctionDescriptor descriptor = getFunctionDescriptor(context.bindingContext(), expression); FunctionDescriptor descriptor = getFunctionDescriptor(context.bindingContext(), expression);
boolean overridable = descriptor.getModality().isOverridable();
JsExpression methodBodyExpression = methodAsPropertyInitializer.getValueExpr(); JsExpression methodBodyExpression = methodAsPropertyInitializer.getValueExpr();
methodAsPropertyInitializer.setValueExpr(JsAstUtils.createPropertyDataDescriptor(overridable, methodBodyExpression, context)); methodAsPropertyInitializer.setValueExpr(JsAstUtils.createPropertyDataDescriptor(descriptor, methodBodyExpression, context));
} }
return Collections.singletonList(methodAsPropertyInitializer); return Collections.singletonList(methodAsPropertyInitializer);
} }
@@ -17,26 +17,25 @@
package org.jetbrains.k2js.translate.declaration; package org.jetbrains.k2js.translate.declaration;
import com.google.common.collect.Lists; 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 com.google.dart.compiler.util.AstUtil;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.resolve.DescriptorUtils; 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.context.TranslationContext;
import org.jetbrains.k2js.translate.general.AbstractTranslator; import org.jetbrains.k2js.translate.general.AbstractTranslator;
import org.jetbrains.k2js.translate.utils.JsAstUtils; import org.jetbrains.k2js.translate.utils.JsAstUtils;
import org.jetbrains.k2js.translate.utils.JsDescriptorUtils; 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.List;
import java.util.Set; import java.util.Set;
import static org.jetbrains.k2js.translate.utils.BindingUtils.getAllNonNativeNamespaceDescriptors; 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 * @author Pavel Talanov
@@ -57,40 +56,22 @@ public final class NamespaceDeclarationTranslator extends AbstractTranslator {
@NotNull TranslationContext context) { @NotNull TranslationContext context) {
super(context); super(context);
this.namespaceDescriptors = namespaceDescriptors; this.namespaceDescriptors = namespaceDescriptors;
this.classDeclarationTranslator = new ClassDeclarationTranslator(getAllClasses(), context); classDeclarationTranslator = new ClassDeclarationTranslator(context);
}
@NotNull
private List<ClassDescriptor> getAllClasses() {
List<ClassDescriptor> result = Lists.newArrayList();
for (NamespaceDescriptor namespaceDescriptor : namespaceDescriptors) {
result.addAll(getAllClassesDefinedInNamespace(namespaceDescriptor));
}
return result;
} }
@NotNull @NotNull
private List<JsStatement> translate() { private List<JsStatement> translate() {
List<JsStatement> result = classesDeclarations(); List<JsStatement> result = new ArrayList<JsStatement>();
result.addAll(namespacesDeclarations());
return result;
}
@NotNull
private List<JsStatement> classesDeclarations() {
List<JsStatement> result = Lists.newArrayList();
classDeclarationTranslator.generateDeclarations();
result.add(classDeclarationTranslator.getDeclarationsStatement()); result.add(classDeclarationTranslator.getDeclarationsStatement());
namespacesDeclarations(result);
classDeclarationTranslator.generateDeclarations();
return result; return result;
} }
@NotNull private void namespacesDeclarations(List<JsStatement> statements) {
private List<JsStatement> namespacesDeclarations() {
List<JsStatement> result = Lists.newArrayList();
List<NamespaceTranslator> namespaceTranslators = getTranslatorsForNonEmptyNamespaces(); List<NamespaceTranslator> namespaceTranslators = getTranslatorsForNonEmptyNamespaces();
result.addAll(declarationStatements(namespaceTranslators, context())); declarationStatements(namespaceTranslators, statements);
result.addAll(initializeStatements(namespaceTranslators)); initializeStatements(namespaceTranslators, statements);
return result;
} }
@NotNull @NotNull
@@ -102,34 +83,31 @@ public final class NamespaceDeclarationTranslator extends AbstractTranslator {
return namespaceTranslators; return namespaceTranslators;
} }
@NotNull private void declarationStatements(@NotNull List<NamespaceTranslator> namespaceTranslators,
private static List<JsStatement> declarationStatements(@NotNull List<NamespaceTranslator> namespaceTranslators, TranslationContext context) { @NotNull List<JsStatement> statements) {
List<JsStatement> result = Lists.newArrayList(); JsObjectLiteral objectLiteral = new JsObjectLiteral();
JsNameRef packageMapNameRef = context().jsScope().declareName("_").makeRef();
JsNameRef defs = JsAstUtils.qualified(context.jsScope().declareName("defs"), context.namer().kotlinObject()); JsExpression packageMapValue;
for (NamespaceTranslator translator : namespaceTranslators) { if (context().isNotEcma3()) {
JsVars vars = translator.getDeclarationAsVar(); packageMapValue = AstUtil.newInvocation(JsAstUtils.CREATE_OBJECT, context().program().getNullLiteral(), objectLiteral);
}
JsVars.JsVar var = vars.iterator().next(); else {
JsNameRef ref = new JsNameRef(var.getName()); packageMapValue = objectLiteral;
ref.setQualifier(defs); }
statements.add(JsAstUtils.newVar(packageMapNameRef.getName(), packageMapValue));
result.add(vars);
result.add(JsAstUtils.assignment(ref, new JsNameRef(var.getName())).makeStmt()); for (NamespaceTranslator translator : namespaceTranslators) {
translator.addNamespaceDeclaration(objectLiteral.getPropertyInitializers());
} }
return result;
} }
@NotNull private static void initializeStatements(@NotNull List<NamespaceTranslator> namespaceTranslators,
private List<JsStatement> initializeStatements(@NotNull List<NamespaceTranslator> namespaceTranslators) { @NotNull List<JsStatement> statements) {
List<JsStatement> result = Lists.newArrayList(); for (NamespaceTranslator translator : namespaceTranslators) {
for (NamespaceDescriptor descriptor : filterNonEmptyNamespaces(namespaceDescriptors)) { for (JsExpression expression : translator.getInitializers()) {
JsNameRef initializeMethodReference = Namer.initializeMethodReference(); statements.add(expression.makeStmt());
JsNameRef fqNamespaceNameRef = TranslationUtils.getQualifiedReference(context(), descriptor); }
setQualifier(initializeMethodReference, fqNamespaceNameRef);
result.add(AstUtil.newInvocation(initializeMethodReference).makeStmt());
} }
return result;
} }
@NotNull @NotNull
@@ -144,10 +122,10 @@ public final class NamespaceDeclarationTranslator extends AbstractTranslator {
} }
@NotNull @NotNull
private static List<NamespaceDescriptor> filterNonEmptyNamespaces(@NotNull List<NamespaceDescriptor> namespaceDescriptors) { private List<NamespaceDescriptor> filterNonEmptyNamespaces(@NotNull List<NamespaceDescriptor> namespaceDescriptors) {
List<NamespaceDescriptor> result = Lists.newArrayList(); List<NamespaceDescriptor> result = Lists.newArrayList();
for (NamespaceDescriptor descriptor : namespaceDescriptors) { for (NamespaceDescriptor descriptor : namespaceDescriptors) {
if (!JsDescriptorUtils.isNamespaceEmpty(descriptor)) { if (!JsDescriptorUtils.isNamespaceEmpty(descriptor, context().bindingContext())) {
result.add(descriptor); 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.context.TranslationContext;
import org.jetbrains.k2js.translate.general.AbstractTranslator; import org.jetbrains.k2js.translate.general.AbstractTranslator;
import org.jetbrains.k2js.translate.general.Translation; 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.JsDescriptorUtils;
import org.jetbrains.k2js.translate.utils.TranslationUtils;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import static org.jetbrains.k2js.translate.utils.JsAstUtils.newObjectLiteral; import static org.jetbrains.k2js.translate.utils.JsAstUtils.newObjectLiteral;
import static org.jetbrains.k2js.translate.utils.JsAstUtils.newVar;
/** /**
* @author Pavel.Talanov * @author Pavel.Talanov
@@ -48,6 +48,9 @@ public final class NamespaceTranslator extends AbstractTranslator {
@NotNull @NotNull
private final ClassDeclarationTranslator classDeclarationTranslator; private final ClassDeclarationTranslator classDeclarationTranslator;
@NotNull
private final List<JsExpression> initializers = new ArrayList<JsExpression>();
/*package*/ NamespaceTranslator(@NotNull NamespaceDescriptor descriptor, /*package*/ NamespaceTranslator(@NotNull NamespaceDescriptor descriptor,
@NotNull ClassDeclarationTranslator classDeclarationTranslator, @NotNull ClassDeclarationTranslator classDeclarationTranslator,
@NotNull TranslationContext context) { @NotNull TranslationContext context) {
@@ -57,82 +60,81 @@ public final class NamespaceTranslator extends AbstractTranslator {
this.classDeclarationTranslator = classDeclarationTranslator; this.classDeclarationTranslator = classDeclarationTranslator;
} }
@NotNull @NotNull
public JsVars getDeclarationAsVar() { public List<JsExpression> getInitializers() {
return newVar(namespaceName, getNamespaceDeclaration()); return initializers;
} }
@NotNull @NotNull
public JsPropertyInitializer getDeclarationAsInitializer() { public JsPropertyInitializer getDeclarationAsInitializer() {
addNamespaceInitializer();
return new JsPropertyInitializer(namespaceName.makeRef(), getNamespaceDeclaration()); 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 @NotNull
private JsInvocation getNamespaceDeclaration() { private JsInvocation getNamespaceDeclaration() {
JsInvocation namespaceDeclaration = namespaceCreateMethodInvocation(); JsInvocation namespaceDeclaration = namespaceCreateMethodInvocation();
addNamespaceInitalizersAndProperties(namespaceDeclaration); addIfNeed(getFunctionsAndClasses(), namespaceDeclaration.getArguments());
namespaceDeclaration.getArguments().add(getClassesAndNestedNamespaces()); addIfNeed(getNestedNamespaceDeclarations(), namespaceDeclaration.getArguments());
return namespaceDeclaration; return namespaceDeclaration;
} }
private void addNamespaceInitalizersAndProperties(@NotNull JsInvocation namespaceDeclaration) { private void addNamespaceInitializer() {
JsFunction initializer = Translation.generateNamespaceInitializerMethod(descriptor, context()); JsFunction initializer = Translation.generateNamespaceInitializerMethod(descriptor, context());
List<JsPropertyInitializer> properties = new DeclarationBodyVisitor().traverseNamespace(descriptor, context()); if (!initializer.getBody().getStatements().isEmpty()) {
if (context().isEcma5()) { JsNameRef call = new JsNameRef("call");
addEcma5InitializersAndProperties(namespaceDeclaration, initializer, properties); call.setQualifier(initializer);
} JsInvocation invocation = new JsInvocation();
else { invocation.setQualifier(call);
addEcma3InitializersAndProperties(namespaceDeclaration, initializer, properties); invocation.getArguments().add(TranslationUtils.getQualifiedReference(context(), descriptor));
initializers.add(invocation);
} }
} }
private static void addEcma3InitializersAndProperties(@NotNull JsInvocation namespaceDeclaration, private List<JsPropertyInitializer> getFunctionsAndClasses() {
@NotNull JsFunction initializer, return new DeclarationBodyVisitor(classDeclarationTranslator).traverseNamespace(descriptor, context());
@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));
} }
@NotNull @NotNull
private JsInvocation namespaceCreateMethodInvocation() { private JsInvocation namespaceCreateMethodInvocation() {
return AstUtil.newInvocation(context().namer().namespaceCreationMethodReference()); return AstUtil.newInvocation(context().namer().packageDefinitionMethodReference());
} }
@NotNull private void addIfNeed(@NotNull List<JsPropertyInitializer> declarations, @NotNull List<JsExpression> expressions) {
private JsObjectLiteral getClassesAndNestedNamespaces() { // ecma5 expects strict number of arguments, but ecma3 doesn't
JsObjectLiteral classesAndNestedNamespaces = new JsObjectLiteral(); if (!declarations.isEmpty()) {
classesAndNestedNamespaces.getPropertyInitializers() expressions.add(newObjectLiteral(declarations));
.addAll(getClassesDefined()); }
classesAndNestedNamespaces.getPropertyInitializers() else if (context().isNotEcma3()) {
.addAll(getNestedNamespaceDeclarations()); expressions.add(context().program().getNullLiteral());
return classesAndNestedNamespaces; }
}
@NotNull
private List<JsPropertyInitializer> getClassesDefined() {
return classDeclarationTranslator.classDeclarationsForNamespace(descriptor);
} }
@NotNull @NotNull
private List<JsPropertyInitializer> getNestedNamespaceDeclarations() { private List<JsPropertyInitializer> getNestedNamespaceDeclarations() {
if (DescriptorUtils.isRootNamespace(descriptor)) {
return Lists.newArrayList();
}
List<JsPropertyInitializer> result = 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) { for (NamespaceDescriptor nestedNamespace : nestedNamespaces) {
NamespaceTranslator nestedNamespaceTranslator = new NamespaceTranslator(nestedNamespace, classDeclarationTranslator, context()); NamespaceTranslator nestedNamespaceTranslator = new NamespaceTranslator(nestedNamespace, classDeclarationTranslator, context());
result.add(nestedNamespaceTranslator.getDeclarationAsInitializer()); result.add(nestedNamespaceTranslator.getDeclarationAsInitializer());
initializers.addAll(nestedNamespaceTranslator.getInitializers());
} }
return result; return result;
} }
@@ -116,12 +116,11 @@ public final class WhenTranslator extends AbstractTranslator {
return statementToExecute; return statementToExecute;
} }
JsExpression condition = translateConditions(entry); JsExpression condition = translateConditions(entry);
return new JsIf(condition, addDummyBreak(statementToExecute), null); return new JsIf(condition, addDummyBreakIfNeed(statementToExecute), null);
} }
@NotNull @NotNull
JsStatement withReturnValueCaptured(@NotNull JsNode node) { JsStatement withReturnValueCaptured(@NotNull JsNode node) {
return convertToStatement(LastExpressionMutator.mutateLastExpression(node, return convertToStatement(LastExpressionMutator.mutateLastExpression(node,
new AssignToExpressionMutator(result.reference()))); new AssignToExpressionMutator(result.reference())));
} }
@@ -172,8 +171,8 @@ public final class WhenTranslator extends AbstractTranslator {
} }
@NotNull @NotNull
private static JsBlock addDummyBreak(@NotNull JsStatement statement) { private static JsStatement addDummyBreakIfNeed(@NotNull JsStatement statement) {
return AstUtil.newBlock(statement, new JsBreak()); return statement instanceof JsReturn ? statement : AstUtil.newBlock(statement, new JsBreak());
} }
@NotNull @NotNull
@@ -31,9 +31,7 @@ import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.general.Translation; import org.jetbrains.k2js.translate.general.Translation;
import org.jetbrains.k2js.translate.reference.CallBuilder; import org.jetbrains.k2js.translate.reference.CallBuilder;
import static org.jetbrains.k2js.translate.utils.BindingUtils.getHasNextCallable; import static org.jetbrains.k2js.translate.utils.BindingUtils.*;
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.JsAstUtils.convertToBlock; 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.JsAstUtils.newVar;
import static org.jetbrains.k2js.translate.utils.PsiUtils.getLoopBody; 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 // kotlin iterator define hasNext as property, but java util as function, our js side expects as property
private static boolean isJavaUtilIterator(CallableDescriptor descriptor) { private static boolean isJavaUtilIterator(CallableDescriptor descriptor) {
final DeclarationDescriptor declaration = descriptor.getContainingDeclaration(); DeclarationDescriptor declaration = descriptor.getContainingDeclaration();
return declaration != null && declaration.getName().getName().equals("Iterator"); 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.JsNamer;
import com.google.dart.compiler.backend.js.JsPrettyNamer; import com.google.dart.compiler.backend.js.JsPrettyNamer;
import com.google.dart.compiler.backend.js.ast.*; import com.google.dart.compiler.backend.js.ast.*;
import com.google.dart.compiler.util.AstUtil;
import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.util.text.StringUtil;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; 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.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.types.lang.JetStandardLibrary; 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.MainCallParameters;
import org.jetbrains.k2js.facade.exceptions.MainFunctionNotFoundException; import org.jetbrains.k2js.facade.exceptions.MainFunctionNotFoundException;
import org.jetbrains.k2js.facade.exceptions.TranslationException; 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.facade.exceptions.UnsupportedFeatureException;
import org.jetbrains.k2js.translate.context.StaticContext; import org.jetbrains.k2js.translate.context.StaticContext;
import org.jetbrains.k2js.translate.context.TranslationContext; 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.ClassTranslator;
import org.jetbrains.k2js.translate.declaration.NamespaceDeclarationTranslator; import org.jetbrains.k2js.translate.declaration.NamespaceDeclarationTranslator;
import org.jetbrains.k2js.translate.expression.ExpressionVisitor; 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.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map;
import static org.jetbrains.jet.plugin.JetMainDetector.getMainFunction; import static org.jetbrains.jet.plugin.JetMainDetector.getMainFunction;
import static org.jetbrains.k2js.translate.utils.BindingUtils.getFunctionDescriptor; import static org.jetbrains.k2js.translate.utils.BindingUtils.getFunctionDescriptor;
@@ -83,9 +85,9 @@ public final class Translation {
@NotNull @NotNull
public static JsExpression translateClassDeclaration(@NotNull JetClass classDeclaration, public static JsExpression translateClassDeclaration(@NotNull JetClass classDeclaration,
@NotNull Map<JsName, JsName> aliasingMap, @NotNull ClassAliasingMap classAliasingMap,
@NotNull TranslationContext context) { @NotNull TranslationContext context) {
return ClassTranslator.generateClassCreationExpression(classDeclaration, aliasingMap, context); return ClassTranslator.generateClassCreationExpression(classDeclaration, classAliasingMap, context);
} }
@NotNull @NotNull
@@ -148,10 +150,10 @@ public final class Translation {
@NotNull @NotNull
public static JsProgram generateAst(@NotNull BindingContext bindingContext, public static JsProgram generateAst(@NotNull BindingContext bindingContext,
@NotNull List<JetFile> files, @NotNull MainCallParameters mainCallParameters, @NotNull List<JetFile> files, @NotNull MainCallParameters mainCallParameters,
@NotNull EcmaVersion ecmaVersion, List<String> rawStatements) @NotNull Config config, List<String> rawStatements)
throws TranslationException { throws TranslationException {
try { try {
return doGenerateAst(bindingContext, files, mainCallParameters, ecmaVersion, rawStatements); return doGenerateAst(bindingContext, files, mainCallParameters, config, rawStatements);
} }
catch (UnsupportedOperationException e) { catch (UnsupportedOperationException e) {
throw new UnsupportedFeatureException("Unsupported feature used.", e); throw new UnsupportedFeatureException("Unsupported feature used.", e);
@@ -164,10 +166,10 @@ public final class Translation {
@NotNull @NotNull
private static JsProgram doGenerateAst(@NotNull BindingContext bindingContext, @NotNull List<JetFile> files, private static JsProgram doGenerateAst(@NotNull BindingContext bindingContext, @NotNull List<JetFile> files,
@NotNull MainCallParameters mainCallParameters, @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 //TODO: move some of the code somewhere
JetStandardLibrary standardLibrary = JetStandardLibrary.getInstance(); JetStandardLibrary standardLibrary = JetStandardLibrary.getInstance();
StaticContext staticContext = StaticContext.generateStaticContext(standardLibrary, bindingContext, ecmaVersion); StaticContext staticContext = StaticContext.generateStaticContext(standardLibrary, bindingContext, config.getTarget());
JsProgram program = staticContext.getProgram(); JsProgram program = staticContext.getProgram();
JsBlock block = program.getGlobalBlock(); JsBlock block = program.getGlobalBlock();
@@ -177,8 +179,13 @@ public final class Translation {
TranslationContext context = TranslationContext.rootContext(staticContext); TranslationContext context = TranslationContext.rootContext(staticContext);
statements.addAll(translateFiles(files, context)); statements.addAll(translateFiles(files, context));
defineModule(statements, context, config);
if (mainCallParameters.shouldBeGenerated()) { 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); generateTestCalls(context, files, block, rawStatements);
JsNamer namer = new JsPrettyNamer(); JsNamer namer = new JsPrettyNamer();
@@ -186,12 +193,20 @@ public final class Translation {
return context.program(); 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, private static JsStatement generateCallToMain(@NotNull TranslationContext context, @NotNull List<JetFile> files,
@NotNull List<String> arguments) throws MainFunctionNotFoundException { @NotNull List<String> arguments) throws MainFunctionNotFoundException {
JetNamedFunction mainFunction = getMainFunction(files); JetNamedFunction mainFunction = getMainFunction(files);
if (mainFunction == null) { if (mainFunction == null) {
throw new MainFunctionNotFoundException("Main function was not found. Please check compiler arguments"); return null;
} }
JsInvocation translatedCall = generateInvocation(context, mainFunction); JsInvocation translatedCall = generateInvocation(context, mainFunction);
setArguments(context, arguments, translatedCall); setArguments(context, arguments, translatedCall);
@@ -214,12 +229,12 @@ public final class Translation {
JsAstUtils.setArguments(translatedCall, Collections.<JsExpression>singletonList(arrayLiteral)); JsAstUtils.setArguments(translatedCall, Collections.<JsExpression>singletonList(arrayLiteral));
} }
@NotNull
private static void generateTestCalls(@NotNull TranslationContext context, private static void generateTestCalls(@NotNull TranslationContext context,
@NotNull List<JetFile> files, @NotNull List<JetFile> files,
@NotNull JsBlock block, @NotNull JsBlock block,
List<String> rawStatements) { List<String> rawStatements) {
ClassDescriptor lastClassDescriptor = null; ClassDescriptor lastClassDescriptor = null;
boolean declaredVar = false;
List<JetNamedFunction> functions = JetTestFunctionDetector.findTestFunctions(context.bindingContext(), files); List<JetNamedFunction> functions = JetTestFunctionDetector.findTestFunctions(context.bindingContext(), files);
for (JetNamedFunction function : functions) { for (JetNamedFunction function : functions) {
FunctionDescriptor functionDescriptor = getFunctionDescriptor(context.bindingContext(), function); FunctionDescriptor functionDescriptor = getFunctionDescriptor(context.bindingContext(), function);
@@ -228,9 +243,16 @@ public final class Translation {
if (containingDeclaration instanceof ClassDescriptor) { if (containingDeclaration instanceof ClassDescriptor) {
ClassDescriptor classDescriptor = (ClassDescriptor) containingDeclaration; ClassDescriptor classDescriptor = (ClassDescriptor) containingDeclaration;
String className = getQualifiedName(classDescriptor); 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() {"); rawStatements.add("QUnit.test( \"" + className + "." + funName + "()\" , function() {");
String prefix = " var ";
rawStatements.add(prefix + "_testCase = new Kotlin.defs." + className + "();");
//rawStatements.add(" expect(0);"); //rawStatements.add(" expect(0);");
rawStatements.add(" _testCase." + funName + "();"); rawStatements.add(" _testCase." + funName + "();");
} else { } 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.JsBinaryOperation;
import com.google.dart.compiler.backend.js.ast.JsConditional; 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.JsExpression;
import com.google.dart.compiler.backend.js.ast.JsNameRef;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetUnaryExpression; import org.jetbrains.jet.lang.psi.JetUnaryExpression;
import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.jet.lexer.JetTokens;
@@ -62,9 +63,9 @@ public final class UnaryOperationTranslator {
@NotNull @NotNull
private static JsExpression translateExclExclOperator(@NotNull JetUnaryExpression expression, @NotNull TranslationContext context) { private static JsExpression translateExclExclOperator(@NotNull JetUnaryExpression expression, @NotNull TranslationContext context) {
JsExpression translatedExpression = translateAsExpression(getBaseExpression(expression), context); JsNameRef cachedValue = context.declareTemporary(translateAsExpression(getBaseExpression(expression), context), true).reference();
JsBinaryOperation notNullCheck = notNullCheck(context, translatedExpression); JsBinaryOperation notNullCheck = notNullCheck(context, cachedValue);
return new JsConditional(notNullCheck, translatedExpression, context.namer().throwNPEFunctionCall()); return new JsConditional(notNullCheck, cachedValue, context.namer().throwNPEFunctionCall());
} }
@NotNull @NotNull
@@ -107,8 +107,10 @@ public final class CallBuilder {
private CallTranslator finish() { private CallTranslator finish() {
if (resolvedCall == null) { if (resolvedCall == null) {
assert descriptor != null; assert descriptor != null;
resolvedCall = ResolvedCallImpl.create(ResolutionCandidate.create(descriptor, false), resolvedCall = ResolvedCallImpl.create(ResolutionCandidate.create(descriptor, descriptor.getExpectedThisObject(),
TemporaryBindingTrace.create(new BindingTraceContext())); //todo descriptor.getReceiverParameter(),
ExplicitReceiverKind.THIS_OBJECT, false),
TemporaryBindingTrace.create(new BindingTraceContext()));
} }
if (descriptor == null) { if (descriptor == null) {
descriptor = resolvedCall.getCandidateDescriptor().getOriginal(); descriptor = resolvedCall.getCandidateDescriptor().getOriginal();
@@ -213,7 +213,7 @@ public final class CallTranslator extends AbstractTranslator {
@NotNull @NotNull
private JsInvocation generateCallMethodInvocation() { private JsInvocation generateCallMethodInvocation() {
JsNameRef callMethodNameRef = AstUtil.newQualifiedNameRef("call"); JsNameRef callMethodNameRef = new JsNameRef("call");
JsInvocation callMethodInvocation = new JsInvocation(); JsInvocation callMethodInvocation = new JsInvocation();
callMethodInvocation.setQualifier(callMethodNameRef); callMethodInvocation.setQualifier(callMethodNameRef);
setQualifier(callMethodInvocation, callParameters.getFunctionReference()); setQualifier(callMethodInvocation, callParameters.getFunctionReference());
@@ -19,6 +19,7 @@ package org.jetbrains.k2js.translate.utils;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor; 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.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.DescriptorUtils;
@@ -31,6 +32,8 @@ import static org.jetbrains.k2js.translate.utils.JsDescriptorUtils.getContaining
*/ */
public final class AnnotationsUtils { public final class AnnotationsUtils {
private static final String ENUMERABLE = "js.enumerable";
private AnnotationsUtils() { private AnnotationsUtils() {
} }
@@ -69,10 +72,14 @@ public final class AnnotationsUtils {
@Nullable @Nullable
private static AnnotationDescriptor getAnnotationByName(@NotNull DeclarationDescriptor descriptor, 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()) { for (AnnotationDescriptor annotationDescriptor : descriptor.getAnnotations()) {
String annotationClassFQName = getAnnotationClassFQName(annotationDescriptor); if (getAnnotationClassFQName(annotationDescriptor).equals(fqn)) {
if (annotationClassFQName.equals(annotation.getFQName())) {
return annotationDescriptor; return annotationDescriptor;
} }
} }
@@ -91,6 +98,16 @@ public final class AnnotationsUtils {
return hasAnnotationOrInsideAnnotatedClass(descriptor, PredefinedAnnotation.NATIVE); 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) { public static boolean isLibraryObject(@NotNull DeclarationDescriptor descriptor) {
return hasAnnotationOrInsideAnnotatedClass(descriptor, PredefinedAnnotation.LIBRARY); return hasAnnotationOrInsideAnnotatedClass(descriptor, PredefinedAnnotation.LIBRARY);
} }
@@ -105,14 +122,15 @@ public final class AnnotationsUtils {
} }
public static boolean hasAnnotationOrInsideAnnotatedClass(@NotNull DeclarationDescriptor descriptor, public static boolean hasAnnotationOrInsideAnnotatedClass(@NotNull DeclarationDescriptor descriptor,
@NotNull PredefinedAnnotation annotation) { @NotNull PredefinedAnnotation annotation) {
if (getAnnotationByName(descriptor, annotation) != null) { return hasAnnotationOrInsideAnnotatedClass(descriptor, annotation.getFQName());
}
private static boolean hasAnnotationOrInsideAnnotatedClass(@NotNull DeclarationDescriptor descriptor, @NotNull String fqn) {
if (getAnnotationByName(descriptor, fqn) != null) {
return true; return true;
} }
ClassDescriptor containingClass = getContainingClass(descriptor); ClassDescriptor containingClass = getContainingClass(descriptor);
if (containingClass == null) { return containingClass != null && getAnnotationByName(containingClass, fqn) != null;
return false;
}
return (getAnnotationByName(containingClass, annotation) != null);
} }
} }
@@ -16,8 +16,8 @@
package org.jetbrains.k2js.translate.utils; package org.jetbrains.k2js.translate.utils;
import com.google.common.collect.Sets;
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement;
import com.intellij.util.containers.OrderedSet;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.*;
@@ -110,7 +110,7 @@ public final class BindingUtils {
public static List<JetDeclaration> getDeclarationsForNamespace(@NotNull BindingContext bindingContext, public static List<JetDeclaration> getDeclarationsForNamespace(@NotNull BindingContext bindingContext,
@NotNull NamespaceDescriptor namespace) { @NotNull NamespaceDescriptor namespace) {
List<JetDeclaration> declarations = new ArrayList<JetDeclaration>(); List<JetDeclaration> declarations = new ArrayList<JetDeclaration>();
for (DeclarationDescriptor descriptor : getContainedDescriptorsWhichAreNotPredefined(namespace)) { for (DeclarationDescriptor descriptor : getContainedDescriptorsWhichAreNotPredefined(namespace, bindingContext)) {
if (descriptor instanceof NamespaceDescriptor) { if (descriptor instanceof NamespaceDescriptor) {
continue; continue;
} }
@@ -321,7 +321,7 @@ public final class BindingUtils {
@NotNull @NotNull
public static Set<NamespaceDescriptor> getAllNonNativeNamespaceDescriptors(@NotNull BindingContext context, public static Set<NamespaceDescriptor> getAllNonNativeNamespaceDescriptors(@NotNull BindingContext context,
@NotNull List<JetFile> files) { @NotNull List<JetFile> files) {
Set<NamespaceDescriptor> descriptorSet = Sets.newHashSet(); Set<NamespaceDescriptor> descriptorSet = new OrderedSet<NamespaceDescriptor>();
for (JetFile file : files) { for (JetFile file : files) {
//TODO: can't be //TODO: can't be
NamespaceDescriptor namespaceDescriptor = getNamespaceDescriptor(context, file); 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 com.google.dart.compiler.util.AstUtil;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; 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.jet.lang.descriptors.PropertyDescriptor;
import org.jetbrains.k2js.translate.context.TranslationContext; import org.jetbrains.k2js.translate.context.TranslationContext;
@@ -31,11 +33,13 @@ import java.util.*;
*/ */
public final class JsAstUtils { public final class JsAstUtils {
private static final JsNameRef DEFINE_PROPERTY = new JsNameRef("defineProperty"); 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(""); private static final JsNameRef EMPTY_REF = new JsNameRef("");
static { static {
JsNameRef globalObjectReference = new JsNameRef("Object"); JsNameRef globalObjectReference = new JsNameRef("Object");
DEFINE_PROPERTY.setQualifier(globalObjectReference); DEFINE_PROPERTY.setQualifier(globalObjectReference);
CREATE_OBJECT.setQualifier(globalObjectReference);
} }
private JsAstUtils() { private JsAstUtils() {
@@ -289,20 +293,36 @@ public final class JsAstUtils {
@NotNull TranslationContext context) { @NotNull TranslationContext context) {
return AstUtil.newInvocation(DEFINE_PROPERTY, new JsThisRef(), return AstUtil.newInvocation(DEFINE_PROPERTY, new JsThisRef(),
context.program().getStringLiteral(context.getNameForDescriptor(descriptor).getIdent()), context.program().getStringLiteral(context.getNameForDescriptor(descriptor).getIdent()),
createPropertyDataDescriptor(descriptor.isVar(), value, context)); createPropertyDataDescriptor(descriptor.isVar(), descriptor, value, context));
} }
@NotNull @NotNull
public static JsObjectLiteral createPropertyDataDescriptor(boolean writable, public static JsObjectLiteral createPropertyDataDescriptor(@NotNull FunctionDescriptor descriptor,
@NotNull JsExpression value, @NotNull JsExpression value,
@NotNull TranslationContext context) { @NotNull TranslationContext context) {
JsObjectLiteral jsPropertyDescriptor = new JsObjectLiteral(); return createPropertyDataDescriptor(descriptor.getModality().isOverridable(), descriptor, value, context);
List<JsPropertyInitializer> meta = jsPropertyDescriptor.getPropertyInitializers(); }
meta.add(new JsPropertyInitializer(context.program().getStringLiteral("value"), value));
@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) { 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 @NotNull
@@ -17,15 +17,19 @@
package org.jetbrains.k2js.translate.utils; package org.jetbrains.k2js.translate.utils;
import com.google.common.collect.Lists; 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.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*; 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.name.Name;
import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.expressions.OperatorConventions; 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.ArrayList;
import java.util.Collection; import java.util.Collection;
@@ -140,16 +144,6 @@ public final class JsDescriptorUtils {
return (functionDescriptor.getReceiverParameter().exists()); 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 //TODO: why callable descriptor
@Nullable @Nullable
public static DeclarationDescriptor getExpectedThisDescriptor(@NotNull CallableDescriptor callableDescriptor) { public static DeclarationDescriptor getExpectedThisDescriptor(@NotNull CallableDescriptor callableDescriptor) {
@@ -193,22 +187,12 @@ public final class JsDescriptorUtils {
} }
@NotNull @NotNull
public static List<ClassDescriptor> getAllClassesDefinedInNamespace(@NotNull NamespaceDescriptor namespaceDescriptor) { public static List<NamespaceDescriptor> getNestedNamespaces(@NotNull NamespaceDescriptor namespaceDescriptor,
List<ClassDescriptor> classDescriptors = Lists.newArrayList(); @NotNull BindingContext context) {
for (DeclarationDescriptor descriptor : getContainedDescriptorsWhichAreNotPredefined(namespaceDescriptor)) {
if (descriptor instanceof ClassDescriptor) {
classDescriptors.add((ClassDescriptor)descriptor);
}
}
return classDescriptors;
}
@NotNull
public static List<NamespaceDescriptor> getNestedNamespaces(@NotNull NamespaceDescriptor namespaceDescriptor) {
List<NamespaceDescriptor> result = Lists.newArrayList(); List<NamespaceDescriptor> result = Lists.newArrayList();
for (DeclarationDescriptor descriptor : getContainedDescriptorsWhichAreNotPredefined(namespaceDescriptor)) { for (DeclarationDescriptor descriptor : getContainedDescriptorsWhichAreNotPredefined(namespaceDescriptor, context)) {
if (descriptor instanceof NamespaceDescriptor) { if (descriptor instanceof NamespaceDescriptor) {
result.add((NamespaceDescriptor)descriptor); result.add((NamespaceDescriptor) descriptor);
} }
} }
return result; return result;
@@ -227,10 +211,22 @@ public final class JsDescriptorUtils {
} }
@NotNull @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(); List<DeclarationDescriptor> result = Lists.newArrayList();
for (DeclarationDescriptor descriptor : namespace.getMemberScope().getAllDescriptors()) { for (DeclarationDescriptor descriptor : namespace.getMemberScope().getAllDescriptors()) {
if (!AnnotationsUtils.isPredefinedObject(descriptor)) { 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); result.add(descriptor);
} }
} }
@@ -238,11 +234,11 @@ public final class JsDescriptorUtils {
} }
//TODO: at the moment this check is very ineffective //TODO: at the moment this check is very ineffective
public static boolean isNamespaceEmpty(@NotNull NamespaceDescriptor namespace) { public static boolean isNamespaceEmpty(@NotNull NamespaceDescriptor namespace, @NotNull BindingContext context) {
List<DeclarationDescriptor> containedDescriptors = getContainedDescriptorsWhichAreNotPredefined(namespace); List<DeclarationDescriptor> containedDescriptors = getContainedDescriptorsWhichAreNotPredefined(namespace, context);
for (DeclarationDescriptor descriptor : containedDescriptors) { for (DeclarationDescriptor descriptor : containedDescriptors) {
if (descriptor instanceof NamespaceDescriptor) { if (descriptor instanceof NamespaceDescriptor) {
if (!isNamespaceEmpty((NamespaceDescriptor)descriptor)) { if (!isNamespaceEmpty((NamespaceDescriptor) descriptor, context)) {
return false; 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 * @author Pavel Talanov
*/ */
public enum PredefinedAnnotation { public enum PredefinedAnnotation {
LIBRARY("js.library"), LIBRARY("js.library"),
NATIVE("js.native"); NATIVE("js.native");
@@ -23,7 +23,6 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lexer.JetToken; import org.jetbrains.jet.lexer.JetToken;
import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.jet.lexer.JetTokens;
import org.jetbrains.k2js.translate.context.Namer;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@@ -143,17 +142,6 @@ public final class PsiUtils {
return nameAsDeclaration; 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 @NotNull
public static JetExpression getLoopRange(@NotNull JetForExpression expression) { public static JetExpression getLoopRange(@NotNull JetForExpression expression) {
JetExpression rangeExpression = expression.getLoopRange(); JetExpression rangeExpression = expression.getLoopRange();
@@ -43,7 +43,7 @@ import static org.jetbrains.k2js.translate.utils.JsDescriptorUtils.getExpectedRe
*/ */
public final class TranslationUtils { public final class TranslationUtils {
private static JsNameRef UNDEFINED_LITERAL = AstUtil.newQualifiedNameRef("undefined"); private static final JsNameRef UNDEFINED_LITERAL = AstUtil.newQualifiedNameRef("undefined");
private TranslationUtils() { private TranslationUtils() {
} }
@@ -64,11 +64,7 @@ public final class TranslationUtils {
@NotNull @NotNull
private static JsPropertyInitializer translateExtensionFunctionAsEcma5PropertyDescriptor(@NotNull JsFunction function, private static JsPropertyInitializer translateExtensionFunctionAsEcma5PropertyDescriptor(@NotNull JsFunction function,
@NotNull FunctionDescriptor descriptor, @NotNull TranslationContext context) { @NotNull FunctionDescriptor descriptor, @NotNull TranslationContext context) {
JsObjectLiteral meta = new JsObjectLiteral(); JsObjectLiteral meta = JsAstUtils.createDataDescriptor(function, descriptor.getModality().isOverridable(), context);
meta.getPropertyInitializers().add(new JsPropertyInitializer(context.program().getStringLiteral("value"), function));
if (descriptor.getModality().isOverridable()) {
meta.getPropertyInitializers().add(context.namer().writablePropertyDescriptorField());
}
return new JsPropertyInitializer(context.getNameForDescriptor(descriptor).makeRef(), meta); 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. * limitations under the License.
*/ */
var foo = Kotlin.definePackage({box:function(){
var foo = Kotlin.createNamespace({initialize:function(){
}
, box:function(){
return !false; return !false;
} }
}); });
@@ -46,9 +46,7 @@
return {A:A, B:B, C:C}; return {A:A, B:B, C:C};
} }
(); ();
var foo = Kotlin.createNamespace(classes, {initialize:function(){ var foo = Kotlin.definePackage(classes, {box:function(){
}
, box:function(){
return (new foo.C).get_order() === 'ABC' && (new foo.B).get_order() === 'AB' && (new foo.A).get_order() === 'A'; 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. * 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 () { (function () {
"use strict"; "use strict";
@@ -23,10 +28,10 @@
return obj1.equals(obj2); return obj1.equals(obj2);
} }
} }
return (obj1 === obj2); return obj1 === obj2;
}; };
Kotlin.defs = {}; Kotlin.modules = {};
Kotlin.Exceptions = {}; Kotlin.Exceptions = {};
Kotlin.Exception = Kotlin.$createClass(); Kotlin.Exception = Kotlin.$createClass();
Kotlin.RuntimeException = Kotlin.$createClass(Kotlin.Exception); Kotlin.RuntimeException = Kotlin.$createClass(Kotlin.Exception);
@@ -39,121 +44,126 @@
Kotlin.Exceptions.UnsupportedOperationException = Kotlin.$createClass(Kotlin.Exception); Kotlin.Exceptions.UnsupportedOperationException = Kotlin.$createClass(Kotlin.Exception);
Kotlin.Exceptions.IOException = Kotlin.$createClass(Kotlin.Exception); Kotlin.Exceptions.IOException = Kotlin.$createClass(Kotlin.Exception);
Kotlin.throwNPE = function() { Kotlin.throwNPE = function () {
throw Kotlin.$new(Kotlin.Exceptions.NullPointerException)(); throw Kotlin.$new(Kotlin.Exceptions.NullPointerException)();
}; };
Kotlin.AbstractList = Kotlin.$createClass({ function throwAbstractFunctionInvocationError() {
set:function (index, value) { throw new TypeError("Function is abstract");
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;
}
});
Kotlin.ArrayList = Kotlin.$createClass({ Kotlin.Iterator = Kotlin.$createClass({
initialize:function () { initialize: function () {
this.array = [];
this.$size = 0;
}, },
get:function (index) { next: throwAbstractFunctionInvocationError,
if ((index < 0) || (index >= this.$size)) { get_hasNext: throwAbstractFunctionInvocationError
throw Kotlin.Exceptions.IndexOutOfBounds; });
}
return (this.array)[index]; var ArrayIterator = Kotlin.$createClass(Kotlin.Iterator, {
initialize: function (array) {
this.array = array;
this.size = array.length;
this.index = 0;
}, },
set:function (index, value) { next: function () {
if ((index < 0) || (index >= this.$size)) { return this.array[this.index++];
throw Kotlin.Exceptions.IndexOutOfBounds;
}
(this.array)[index] = value;
}, },
size:function () { get_hasNext: function () {
return this.$size; 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 () { next: function () {
return Kotlin.$new(Kotlin.ArrayIterator)(this); return this.list.get(this.index++);
}, },
isEmpty:function () { get_hasNext: function () {
return (this.$size === 0); return this.index < this.size;
}
});
Kotlin.AbstractList = Kotlin.$createClass({
iterator: function () {
return Kotlin.$new(ListIterator)(this);
}, },
add:function (element) { isEmpty: function () {
this.array[this.$size++] = element; return this.size() == 0;
}, },
addAll:function (collection) { addAll: function (collection) {
var it = collection.iterator(); var it = collection.iterator();
while (it.get_hasNext()) { while (it.get_hasNext()) {
this.add(it.next()); this.add(it.next());
} }
}, },
remove:function(value) { remove: function (o) {
for (var i = 0; i < this.$size; ++i) { var index = this.indexOf(o);
if (this.array[i] == value) { if (index != -1) {
this.removeByIndex(i); this.removeAt(index);
return;
}
} }
}, },
removeByIndex:function (index) { contains: function (o) {
for (var i = index; i < this.$size - 1; ++i) { return this.indexOf(o) != -1;
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;
} }
}); });
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) { Kotlin.parseInt = function (str) {
return parseInt(str, 10); return parseInt(str, 10);
} };
;
Kotlin.safeParseInt = function(str) { Kotlin.safeParseInt = function(str) {
var r = parseInt(str, 10); var r = parseInt(str, 10);
@@ -207,57 +217,32 @@
Kotlin.System.out().print(s); 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, { Kotlin.RangeIterator = Kotlin.$createClass(Kotlin.Iterator, {
initialize:function (start, count, reversed) { initialize: function (start, count, reversed) {
this.$start = start; this.$start = start;
this.$count = count; this.$count = count;
this.$reversed = reversed; this.$reversed = reversed;
this.$i = this.get_start(); this.$i = this.get_start();
}, get_start:function () { },
get_start: function () {
return this.$start; return this.$start;
}, get_count:function () { },
get_count: function () {
return this.$count; return this.$count;
}, set_count:function (tmp$0) { },
set_count: function (tmp$0) {
this.$count = tmp$0; this.$count = tmp$0;
}, get_reversed:function () { },
get_reversed: function () {
return this.$reversed; return this.$reversed;
}, get_i:function () { },
get_i: function () {
return this.$i; return this.$i;
}, set_i:function (tmp$0) { },
set_i: function (tmp$0) {
this.$i = tmp$0; this.$i = tmp$0;
}, next:function () { },
next: function () {
this.set_count(this.get_count() - 1); this.set_count(this.get_count() - 1);
if (this.get_reversed()) { if (this.get_reversed()) {
this.set_i(this.get_i() - 1); this.set_i(this.get_i() - 1);
@@ -273,44 +258,51 @@
} }
}); });
Kotlin.NumberRange = Kotlin.$createClass({initialize:function (start, size, reversed) { Kotlin.NumberRange = Kotlin.$createClass({
this.$start = start; initialize: function (start, size, reversed) {
this.$size = size; this.$start = start;
this.$reversed = reversed; this.$size = size;
}, get_start:function () { this.$reversed = reversed;
return this.$start; },
}, get_size:function () { get_start: function () {
return this.$size; return this.$start;
}, get_reversed:function () { },
return this.$reversed; get_size: function () {
}, get_end:function () { return this.$size;
return this.get_reversed() ? this.get_start() - this.get_size() + 1 : this.get_start() + this.get_size() - 1; },
}, contains:function (number) { get_reversed: function () {
if (this.get_reversed()) { return this.$reversed;
return number <= this.get_start() && number > this.get_start() - this.get_size(); },
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( Kotlin.Comparator = Kotlin.$createClass({
{ initialize: function () {
initialize: function () { },
}, compare: throwAbstractFunctionInvocationError
compare: function (el1, el2) { });
throw Kotlin.$new(Kotlin.AbstractFunctionInvocationError)();
} var ComparatorImpl = Kotlin.$createClass(Kotlin.Comparator, {
initialize: function (comparator) {
this.compare = comparator;
} }
); });
Kotlin.comparator = function (f) { Kotlin.comparator = function (f) {
var result = Kotlin.$new(Kotlin.Comparator)(); return Kotlin.$new(ComparatorImpl)(f);
result.compare = f;
return result;
}; };
Kotlin.collectionsMax = function (col, comp) { Kotlin.collectionsMax = function (col, comp) {
@@ -369,25 +361,8 @@
return Kotlin.$new(Kotlin.NumberRange)(0, arr.length); return Kotlin.$new(Kotlin.NumberRange)(0, arr.length);
}; };
var intrinsicArrayIterator = Kotlin.$createClass( Kotlin.arrayIterator = function (array) {
Kotlin.Iterator, return Kotlin.$new(ArrayIterator)(array);
{
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.toString = function (obj) { Kotlin.toString = function (obj) {
@@ -796,14 +771,11 @@
Kotlin.HashTable = Hashtable; Kotlin.HashTable = Hashtable;
})(); })();
Kotlin.HashMap = Kotlin.$createClass( Kotlin.HashMap = Kotlin.$createClass({
{ initialize: function () {
initialize:function () { Kotlin.HashTable.call(this);
Kotlin.HashTable.call(this); }
} });
}
);
(function () { (function () {
function HashSet(hashingFunction, equalityFunction) { function HashSet(hashingFunction, equalityFunction) {
+28 -37
View File
@@ -1,10 +1,10 @@
/* Prototype JavaScript framework, version 1.6.1 /* Prototype JavaScript framework, version 1.6.1
* (c) 2005-2009 Sam Stephenson * (c) 2005-2009 Sam Stephenson
* *
* Prototype is freely distributable under the terms of an MIT-style license. * Prototype is freely distributable under the terms of an MIT-style license.
* For details, see the Prototype web site: http://www.prototypejs.org/ * For details, see the Prototype web site: http://www.prototypejs.org/
* *
*--------------------------------------------------------------------------*/ *--------------------------------------------------------------------------*/
var Kotlin = {}; var Kotlin = {};
(function () { (function () {
@@ -12,13 +12,14 @@ var Kotlin = {};
var emptyFunction = function () { var emptyFunction = function () {
}; };
function $A(iterable) { Kotlin.argumentsToArrayLike = function (args) {
if (!iterable) return []; var n = args.length;
if ('toArray' in Object(iterable)) return iterable.toArray(); var result = new Array(n);
var length = iterable.length || 0, results = new Array(length); while (n--) {
while (length--) results[length] = iterable[length]; result[n] = args[n];
return results; }
} return result;
};
(function () { (function () {
function extend(destination, source) { function extend(destination, source) {
@@ -62,11 +63,6 @@ var Kotlin = {};
return array; return array;
} }
function merge(array, args) {
array = slice.call(array, 0);
return update(array, args);
}
function argumentNames() { function argumentNames() {
var names = this.toString().match(/^[\s\(]*function[^(]*\(([^)]*)\)/)[1] var names = this.toString().match(/^[\s\(]*function[^(]*\(([^)]*)\)/)[1]
.replace(/\/\/.*?[\r\n]|\/\*(?:.|[\r\n])*?\*\//g, '') .replace(/\/\/.*?[\r\n]|\/\*(?:.|[\r\n])*?\*\//g, '')
@@ -74,15 +70,6 @@ var Kotlin = {};
return names.length == 1 && !names[0] ? [] : names; 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) { function bindAsEventListener(context) {
var __method = this, args = slice.call(arguments, 1); var __method = this, args = slice.call(arguments, 1);
return function (event) { return function (event) {
@@ -101,7 +88,6 @@ var Kotlin = {};
return { return {
argumentNames: argumentNames, argumentNames: argumentNames,
bind: bind,
bindAsEventListener: bindAsEventListener, bindAsEventListener: bindAsEventListener,
wrap: wrap wrap: wrap
}; };
@@ -129,21 +115,18 @@ var Kotlin = {};
var property = properties[i]; var property = properties[i];
object[property] = source[property]; object[property] = source[property];
} }
return this;
} }
return function () { return function () {
var result = {}; var result = arguments[0];
for (var i = 0, length = arguments.length; i < length; i++) { for (var i = 1, n = arguments.length; i < n; i++) {
add(result, arguments[i]); add(result, arguments[i]);
} }
return result; return result;
} }
})(); })();
Kotlin.createNamespace = function () { Kotlin.definePackage = Kotlin.createTrait;
return Kotlin.createTrait.apply(null, arguments);
};
Kotlin.createClass = (function () { Kotlin.createClass = (function () {
var METHODS = {addMethods: addMethods}; var METHODS = {addMethods: addMethods};
@@ -152,7 +135,7 @@ var Kotlin = {};
} }
function create() { function create() {
var parent = null, properties = $A(arguments); var parent = null, properties = Kotlin.argumentsToArrayLike(arguments);
if (typeof (properties[0]) == "function") { if (typeof (properties[0]) == "function") {
parent = properties.shift(); parent = properties.shift();
} }
@@ -243,4 +226,12 @@ var Kotlin = {};
var singletonClass = Kotlin.createClass.apply(null, arguments); var singletonClass = Kotlin.createClass.apply(null, arguments);
return new singletonClass(); 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; 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) // proto must be created for class even if it is not needed (requires for is operator)
Kotlin.createClass = (function () { Kotlin.createClass = function (bases, initializer, properties) {
function create(bases, initializer, properties) { var proto;
var proto; var baseInitializer = null;
var baseInitializer = null; var isTrait = initializer == null;
var isTrait = initializer == null; if (!bases) {
if (!bases) { proto = !properties && isTrait ? null : Object.create(null, properties || undefined);
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 var constructor = createConstructor(proto, initializer);
function createConstructor(proto, initializer) { Object.defineProperty(constructor, "proto", {value: proto});
return function () { Object.defineProperty(constructor, "properties", {value: properties || null});
var o = Object.create(proto); // null for trait
if (initializer != null) { if (!isTrait) {
initializer.apply(o, arguments); Object.defineProperty(constructor, "initializer", {value: initializer});
}
if (initializer == null || !initializer.hasOwnProperty("skipSeal")) { Object.defineProperty(initializer, "baseInitializer", {value: baseInitializer});
Object.seal(o); Object.freeze(initializer);
}
return o;
};
} }
function computeProto(bases, properties) { Object.freeze(constructor);
var proto = null; return constructor;
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;
})();
Kotlin.createObject = function (initializer, properties) { Kotlin.createObject = function (initializer, properties) {
var o = Object.create(null, properties || undefined); var o = Object.create(null, properties || undefined);
@@ -110,15 +96,18 @@ var Kotlin = {};
return o; return o;
}; };
Kotlin.createNamespace = function (initializer, properties, classesAndNestedNamespaces) {
var o = Object.create(null, properties || undefined); Kotlin.definePackage = function (functionsAndClasses, nestedNamespaces) {
Object.defineProperty(o, "initialize", {value: initializer}); var p = Object.create(null, functionsAndClasses || undefined);
var keys = Object.keys(classesAndNestedNamespaces); if (nestedNamespaces) {
for (var i = 0, n = keys.length; i < n; i++) { var keys = Object.keys(nestedNamespaces);
var name = keys[i]; for (var i = 0, n = keys.length; i < n; i++) {
Object.defineProperty(o, name, {value: classesAndNestedNamespaces[name]}); var name = keys[i];
Object.defineProperty(p, name, {value:nestedNamespaces[name]});
}
} }
return o;
return p;
}; };
Kotlin.$new = function (f) { Kotlin.$new = function (f) {
@@ -126,7 +115,7 @@ var Kotlin = {};
}; };
Kotlin.$createClass = function (parent, properties) { Kotlin.$createClass = function (parent, properties) {
if (typeof (parent) != "function") { if (parent !== null && typeof (parent) != "function") {
properties = parent; properties = parent;
parent = null; parent = null;
} }
@@ -161,10 +150,16 @@ var Kotlin = {};
} }
} }
if (initializer) {
Object.defineProperty(initializer, "skipSeal", {value: true});
}
return Kotlin.createClass(parent || null, initializer, descriptors); 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];
}
}