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
@@ -43,6 +43,8 @@ public abstract class BasicTest extends TestWithEnvironment {
private static final String CASES = "cases/";
private static final String OUT = "out/";
private static final String EXPECTED = "expected/";
public static final String JSLINT_LIB = pathToTestFilesRoot() + "jslint.js";
@NotNull
private String mainDirectory = "";
@@ -42,7 +42,7 @@ public abstract class SingleFileTranslationTest extends BasicTest {
runFunctionOutputTest(EcmaVersion.all(), kotlinFilename, namespaceName, functionName, expectedResult);
}
protected void runFunctionOutputTest(@NotNull EnumSet<EcmaVersion> ecmaVersions, @NotNull String kotlinFilename,
protected void runFunctionOutputTest(@NotNull Iterable<EcmaVersion> ecmaVersions, @NotNull String kotlinFilename,
@NotNull String namespaceName,
@NotNull String functionName,
@NotNull Object expectedResult) throws Exception {
@@ -50,7 +50,7 @@ public abstract class SingleFileTranslationTest extends BasicTest {
runRhinoTests(kotlinFilename, ecmaVersions, new RhinoFunctionResultChecker(namespaceName, functionName, expectedResult));
}
public void checkFooBoxIsTrue(@NotNull String filename, @NotNull EnumSet<EcmaVersion> ecmaVersions) throws Exception {
public void checkFooBoxIsTrue(@NotNull String filename, @NotNull Iterable<EcmaVersion> ecmaVersions) throws Exception {
runFunctionOutputTest(ecmaVersions, filename, "foo", "box", true);
}
@@ -58,7 +58,7 @@ public abstract class SingleFileTranslationTest extends BasicTest {
checkFooBoxIsTrue(getTestName(true) + ".kt", EcmaVersion.all());
}
protected void fooBoxTest(@NotNull EnumSet<EcmaVersion> ecmaVersions) throws Exception {
protected void fooBoxTest(@NotNull Iterable<EcmaVersion> ecmaVersions) throws Exception {
checkFooBoxIsTrue(getTestName(true) + ".kt", ecmaVersions);
}
@@ -84,7 +84,7 @@ public abstract class SingleFileTranslationTest extends BasicTest {
runRhinoTests(kotlinFilename, ecmaVersions, new RhinoSystemOutputChecker(expectedResult));
}
protected void performTestWithMain(@NotNull EnumSet<EcmaVersion> ecmaVersions,
protected void performTestWithMain(@NotNull Iterable<EcmaVersion> ecmaVersions,
@NotNull String testName,
@NotNull String testId,
@NotNull String... args) throws Exception {
@@ -28,8 +28,11 @@ import java.util.List;
/**
* @author Pavel Talanov
*/
public class TestConfig extends Config {
public final class TestConfig extends Config {
//NOTE: hard-coded in kotlin-lib files
@NotNull
public static final String TEST_MODULE_NAME = "JS_TESTS";
@NotNull
private final List<JetFile> jsLibFiles;
@NotNull
@@ -37,7 +40,7 @@ public class TestConfig extends Config {
public TestConfig(@NotNull Project project, @NotNull EcmaVersion version,
@NotNull List<JetFile> files, @NotNull BindingContext context) {
super(project, version);
super(project, TEST_MODULE_NAME, version);
jsLibFiles = files;
libraryContext = context;
}
@@ -0,0 +1,44 @@
/*
* Copyright 2010-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.k2js.test.rhino;
import org.jetbrains.annotations.NotNull;
import org.mozilla.javascript.Function;
import org.mozilla.javascript.Scriptable;
/**
* @author Sergey Simonchik
*/
class FunctionWithScope {
private final Function fun;
private final Scriptable scope;
FunctionWithScope(@NotNull Function function, @NotNull Scriptable scope) {
this.fun = function;
this.scope = scope;
}
@NotNull
public Function getFunction() {
return fun;
}
@NotNull
public Scriptable getScope() {
return scope;
}
}
@@ -0,0 +1,106 @@
/*
* Copyright 2010-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.k2js.test.rhino;
import com.google.common.base.Supplier;
import com.intellij.openapi.diagnostic.Logger;
import org.jetbrains.annotations.NotNull;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Function;
import org.mozilla.javascript.Script;
import org.mozilla.javascript.Scriptable;
/**
* @author Sergey Simonchik
*/
class RhinoFunctionManager {
private static final Logger LOG = Logger.getInstance(RhinoFunctionManager.class);
private final ThreadLocal<FunctionWithScope> threadLocalFunction = new ThreadLocal<FunctionWithScope>() {
@Override
protected FunctionWithScope initialValue() {
if (script == null) {
synchronized (threadLocalFunction) {
if (script == null) {
script = compileScript(9);
}
}
}
return extractFunctionWithScope(script);
}
};
private volatile Script script;
private final Supplier<String> scriptSourceProvider;
private final String functionName;
public RhinoFunctionManager(@NotNull Supplier<String> scriptSourceProvider,
@NotNull String functionName) {
this.scriptSourceProvider = scriptSourceProvider;
this.functionName = functionName;
}
private Script compileScript(int optimizationLevel) {
long startNano = System.nanoTime();
Context context = Context.enter();
try {
context.setOptimizationLevel(optimizationLevel);
String scriptSource = scriptSourceProvider.get();
return context.compileString(scriptSource, "<" + functionName + " script>", 1, null);
}
finally {
Context.exit();
LOG.info(formatMessage(startNano, functionName + " script rhino compilation"));
}
}
@NotNull
private FunctionWithScope extractFunctionWithScope(@NotNull Script script) {
long startNano = System.nanoTime();
Context context = Context.enter();
try {
Scriptable scope = context.initStandardObjects();
script.exec(context, scope);
Object jsLintObj = scope.get(functionName, scope);
if (jsLintObj instanceof Function) {
Function jsLint = (Function) jsLintObj;
return new FunctionWithScope(jsLint, scope);
}
else {
throw new RuntimeException(functionName + " is undefined or not a function.");
}
}
finally {
Context.exit();
LOG.info(formatMessage(startNano, functionName + " function extraction"));
}
}
private static String formatMessage(long startTimeNano, @NotNull String actionName) {
long nanoDuration = System.nanoTime() - startTimeNano;
return String.format("[%s] %s took %.2f ms",
Thread.currentThread().getName(),
actionName,
nanoDuration / 1000000.0);
}
@NotNull
public FunctionWithScope getFunctionWithScope() {
return threadLocalFunction.get();
}
}
@@ -17,6 +17,7 @@
package org.jetbrains.k2js.test.rhino;
import org.jetbrains.annotations.Nullable;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.NativeJavaObject;
/**
@@ -33,13 +34,13 @@ public class RhinoFunctionNativeObjectResultChecker extends RhinoFunctionResultC
}
@Override
protected void assertResultValid(Object result) {
protected void assertResultValid(Object result, Context context) {
if (result instanceof NativeJavaObject) {
NativeJavaObject nativeJavaObject = (NativeJavaObject) result;
Object unwrap = nativeJavaObject.unwrap();
super.assertResultValid(unwrap);
super.assertResultValid(unwrap, context);
} else {
super.assertResultValid(result);
super.assertResultValid(result, context);
}
}
}
@@ -17,6 +17,8 @@
package org.jetbrains.k2js.test.rhino;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.k2js.test.config.TestConfig;
import org.jetbrains.k2js.translate.context.Namer;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Scriptable;
@@ -46,11 +48,12 @@ public class RhinoFunctionResultChecker implements RhinoResultChecker {
public void runChecks(Context context, Scriptable scope) throws Exception {
Object result = evaluateFunction(context, scope);
flushSystemOut(context, scope);
assertResultValid(result);
assertResultValid(result, context);
}
protected void assertResultValid(Object result) {
assertEquals("Result of " + namespaceName + "." + functionName + "() is not what expected!", expectedResult, result);
protected void assertResultValid(Object result, Context context) {
String ecmaVersion = context.getLanguageVersion() == Context.VERSION_1_8 ? "ecma5" : "ecma3";
assertEquals("Result of " + namespaceName + "." + functionName + "() is not what expected (" + ecmaVersion + ")!", expectedResult, result);
String report = namespaceName + "." + functionName + "() = " + Context.toString(result);
System.out.println(report);
}
@@ -60,10 +63,14 @@ public class RhinoFunctionResultChecker implements RhinoResultChecker {
}
private String functionCallString() {
String result = functionName + "()";
StringBuilder sb = new StringBuilder();
if (namespaceName != null) {
result = "Kotlin.defs." + namespaceName + "." + result;
sb.append("Kotlin.modules." + TestConfig.TEST_MODULE_NAME);
if (namespaceName != Namer.getRootNamespaceName()) {
sb.append('.').append(namespaceName);
}
sb.append('.');
}
return result;
return sb.append(functionName).append("()").toString();
}
}
@@ -17,15 +17,19 @@
package org.jetbrains.k2js.test.rhino;
import closurecompiler.internal.com.google.common.collect.Maps;
import com.google.common.base.Supplier;
import com.google.common.collect.Sets;
import com.intellij.openapi.util.io.FileUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.k2js.config.EcmaVersion;
import org.jetbrains.k2js.facade.K2JSTranslator;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.ScriptableObject;
import org.jetbrains.k2js.test.BasicTest;
import org.mozilla.javascript.*;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -37,6 +41,28 @@ import static org.jetbrains.k2js.test.BasicTest.pathToTestFilesRoot;
* @author Pavel Talanov
*/
public final class RhinoUtils {
@NotNull
private static final Set<String> IGNORED_JSLINT_WARNINGS = Sets.newHashSet();
static {
// todo dart ast bug
IGNORED_JSLINT_WARNINGS.add("Unexpected space between '}' and '('.");
// don't read JS, use kotlin and idea debugger ;)
IGNORED_JSLINT_WARNINGS
.add("Wrap an immediate function invocation in parentheses to assist the reader in understanding that the expression is the result of a function, and not the function itself.");
}
@NotNull
private static final RhinoFunctionManager functionManager = new RhinoFunctionManager(
new Supplier<String>() {
@Override
public String get() {
return fileToString(BasicTest.JSLINT_LIB);
}
},
"JSLINT"
);
public static final String KOTLIN_JS_LIB_COMMON = pathToTestFilesRoot() + "kotlin_lib.js";
private static final String KOTLIN_JS_LIB_ECMA_3 = pathToTestFilesRoot() + "kotlin_lib_ecma3.js";
@@ -46,6 +72,15 @@ public final class RhinoUtils {
}
private static String fileToString(String file) {
try {
return FileUtil.loadFile(new File(file));
}
catch (IOException e) {
throw new RuntimeException(e);
}
}
private static void runFileWithRhino(@NotNull String inputFile,
@NotNull Context context,
@NotNull Scriptable scope) throws Exception {
@@ -75,6 +110,8 @@ public final class RhinoUtils {
runFileWithRhino(filename, context, scope);
}
checker.runChecks(context, scope);
lintIt(context, fileNames.get(fileNames.size() - 1));
}
finally {
Context.exit();
@@ -147,4 +184,61 @@ public final class RhinoUtils {
static void flushSystemOut(@NotNull Context context, @NotNull Scriptable scope) {
context.evaluateString(scope, K2JSTranslator.FLUSH_SYSTEM_OUT, "test", 0, null);
}
private static void lintIt(Context context, String fileName) throws IOException {
if (Boolean.valueOf(System.getProperty("test.lint.skip"))) {
return;
}
NativeObject options = new NativeObject();
// todo fix dart ast?
options.defineProperty("white", true, ScriptableObject.READONLY);
// vars, http://uxebu.com/blog/2010/04/02/one-var-statement-for-one-variable/
options.defineProperty("vars", true, ScriptableObject.READONLY);
NativeArray globals = new NativeArray(new Object[] {"Kotlin"});
options.defineProperty("predef", globals, ScriptableObject.READONLY);
Object[] args = {FileUtil.loadFile(new File(fileName)), options};
FunctionWithScope functionWithScope = functionManager.getFunctionWithScope();
Function function = functionWithScope.getFunction();
Scriptable scope = functionWithScope.getScope();
Object status = function.call(context, scope, scope, args);
Boolean noErrors = (Boolean) Context.jsToJava(status, Boolean.class);
if (!noErrors) {
Object errors = function.get("errors", scope);
if (errors == null) {
return;
}
System.out.println(fileName);
for (Object errorObj : ((NativeArray) errors)) {
if (!(errorObj instanceof NativeObject)) {
continue;
}
NativeObject e = (NativeObject) errorObj;
int line = toInt(e.get("line"));
int character = toInt(e.get("character"));
if (line < 0 || character < 0) {
continue;
}
Object reasonObj = e.get("reason");
if (reasonObj instanceof String) {
String reason = (String) reasonObj;
if (IGNORED_JSLINT_WARNINGS.contains(reason)) {
continue;
}
System.out.println(line + ":" + character + " " + reason);
}
}
}
}
private static int toInt(Object obj) {
if (obj instanceof Number) {
return ((Number) obj).intValue();
}
return -1;
}
}
@@ -51,6 +51,10 @@ public final class ArrayListTest extends JavaClassesTest {
fooBoxTest();
}
public void testToArray() throws Exception {
fooBoxTest();
}
public void testIndexOOB() throws Exception {
try {
fooBoxTest();
@@ -74,4 +74,8 @@ public final class ExtensionFunctionTest extends SingleFileTranslationTest {
public void testExtensionPropertyOnClassWithExplicitAndImplicitReceiver() throws Exception {
fooBoxTest();
}
public void testExtensionFunctionCalledFromFor() throws Exception {
fooBoxTest();
}
}
@@ -34,4 +34,8 @@ public final class MultiFileTest extends MultipleFilesTranslationTest {
public void testClassesInheritedFromOtherFile() throws Exception {
checkFooBoxIsTrue("classesInheritedFromOtherFile");
}
public void testClassOfTheSameNameInAnotherPackage() throws Exception {
checkFooBoxIsTrue("classOfTheSameNameInAnotherPackage");
}
}
@@ -16,8 +16,11 @@
package org.jetbrains.k2js.test.semantics;
import org.jetbrains.k2js.config.EcmaVersion;
import org.jetbrains.k2js.test.SingleFileTranslationTest;
import java.util.EnumSet;
/**
* @author Pavel Talanov
*/
@@ -41,9 +44,13 @@ public final class ObjectTest extends SingleFileTranslationTest {
fooBoxTest();
}
public void testObjectInObject() throws Exception {
fooBoxTest(EnumSet.noneOf(EcmaVersion.class));
}
public void testObjectInheritingFromATrait() throws Exception {
fooBoxTest();
}
}
}
@@ -16,10 +16,14 @@
package org.jetbrains.k2js.test.semantics;
import com.google.common.collect.Lists;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.k2js.config.EcmaVersion;
import org.jetbrains.k2js.test.SingleFileTranslationTest;
import org.jetbrains.k2js.test.utils.JsTestUtils;
import java.util.EnumSet;
import java.util.List;
/**
* @author Pavel Talanov
@@ -79,4 +83,23 @@ public final class PropertyAccessTest extends SingleFileTranslationTest {
public void testInitInstanceProperties() throws Exception {
fooBoxTest(EnumSet.of(EcmaVersion.v5));
}
public void testEnumerable() throws Exception {
fooBoxTest(JsTestUtils.successOnEcmaV5());
}
public void testOverloadedOverriddenFunctionPropertyName() throws Exception {
//fooBoxTest(JsTestUtils.successOnEcmaV5());
//fooBoxTest();
}
@Override
@NotNull
protected List<String> additionalJSFiles(@NotNull EcmaVersion ecmaVersion) {
List<String> result = Lists.newArrayList(super.additionalJSFiles(ecmaVersion));
if (getName().equals("testEnumerable")) {
result.add(pathToTestFiles() + "enumerate.js");
}
return result;
}
}
@@ -79,7 +79,7 @@ abstract class StdLibTestSupport extends SingleFileTranslationTest {
K2JSCompiler compiler = new K2JSCompiler();
K2JSCompilerArguments arguments = new K2JSCompilerArguments();
arguments.outputFile = getOutputFilePath(getTestName(false) + ".compiler.kt", version);
arguments.sourceFiles = files;
arguments.sourceFiles = files.toArray(new String[files.size()]);
arguments.verbose = true;
System.out.println("Compiling with version: " + version + " to: " + arguments.outputFile);
ExitCode answer = compiler.exec(System.out, arguments);
@@ -24,6 +24,7 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
/**
@@ -34,6 +35,11 @@ public final class JsTestUtils {
private JsTestUtils() {
}
@NotNull
public static EnumSet<EcmaVersion> successOnEcmaV5() {
return EnumSet.of(EcmaVersion.v5);
}
@NotNull
public static String convertFileNameToDotJsFile(@NotNull String filename, @NotNull EcmaVersion ecmaVersion) {
String postFix = "_" + ecmaVersion.toString() + ".js";