test for KT-2177 and jslint

This commit is contained in:
develar
2012-06-21 14:12:09 +04:00
parent 39fe690ec8
commit 2108c08b2a
7 changed files with 6635 additions and 3 deletions
@@ -42,6 +42,7 @@ public abstract class BasicTest extends TestWithEnvironment {
private static final String TEST_FILES = "js/js.translator/testFiles/";
private static final String CASES = "cases/";
private static final String OUT = "out/";
public static final String JSLINT_LIB = pathToTestFilesRoot() + "jslint.js";
private static final String KOTLIN_JS_LIB = 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_5 = pathToTestFilesRoot() + "kotlin_lib_ecma5.js";
@@ -0,0 +1,28 @@
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,95 @@
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;
}
@NotNull
public String getFunctionName() {
return 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();
}
}
@@ -16,13 +16,18 @@
package org.jetbrains.k2js.test.rhino;
import com.google.common.base.Supplier;
import com.intellij.openapi.util.io.FileUtil;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.k2js.config.EcmaVersion;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Scriptable;
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;
@@ -31,6 +36,29 @@ import java.util.Set;
* @author Pavel Talanov
*/
public final class RhinoUtils {
private static final Set<String> IGNORED_JSLINT_WARNINGS = new THashSet<String>();
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.");
}
private static final RhinoFunctionManager functionManager = new RhinoFunctionManager(
new Supplier<String>() {
@Override
public String get() {
try {
return FileUtil.loadFile(new File(BasicTest.JSLINT_LIB));
}
catch (IOException e) {
throw new RuntimeException(e);
}
}
},
"JSLINT"
);
private RhinoUtils() {
@@ -76,6 +104,62 @@ public final class RhinoUtils {
runFileWithRhino(filename, context, scope);
}
checker.runChecks(context, scope);
lintIt(context, fileNames.get(fileNames.size() - 1));
Context.exit();
}
private static void lintIt(Context context, String fileName) throws IOException {
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;
}
}
@@ -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();
}
}
}
File diff suppressed because it is too large Load Diff
@@ -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"