JsTests speed up: cash the scope with Kotlin library. Refactor CodeGenerator class.
About 10% speed up (not much but still...)
This commit is contained in:
@@ -42,9 +42,6 @@ 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/";
|
||||
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";
|
||||
private static final String EXPECTED = "expected/";
|
||||
|
||||
@NotNull
|
||||
@@ -90,10 +87,7 @@ public abstract class BasicTest extends TestWithEnvironment {
|
||||
|
||||
@NotNull
|
||||
protected List<String> additionalJSFiles(@NotNull EcmaVersion ecmaVersion) {
|
||||
List<String> list = Lists.newArrayList();
|
||||
list.add(ecmaVersion == EcmaVersion.v5 ? KOTLIN_JS_LIB_ECMA_5 : KOTLIN_JS_LIB_ECMA_3);
|
||||
list.add(KOTLIN_JS_LIB);
|
||||
return list;
|
||||
return Lists.newArrayList();
|
||||
}
|
||||
|
||||
protected void generateJavaScriptFiles(@NotNull String kotlinFilename,
|
||||
@@ -141,7 +135,7 @@ public abstract class BasicTest extends TestWithEnvironment {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected static String pathToTestFilesRoot() {
|
||||
public static String pathToTestFilesRoot() {
|
||||
return TEST_FILES;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
import org.mozilla.javascript.Context;
|
||||
import org.mozilla.javascript.Scriptable;
|
||||
|
||||
import static org.jetbrains.k2js.test.rhino.RhinoUtils.flushSystemOut;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
@@ -44,6 +45,7 @@ public class RhinoFunctionResultChecker implements RhinoResultChecker {
|
||||
@Override
|
||||
public void runChecks(Context context, Scriptable scope) throws Exception {
|
||||
Object result = evaluateFunction(context, scope);
|
||||
flushSystemOut(context, scope);
|
||||
assertResultValid(result);
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.jetbrains.k2js.test.rhino;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.k2js.facade.K2JSTranslator;
|
||||
import org.mozilla.javascript.Context;
|
||||
import org.mozilla.javascript.Scriptable;
|
||||
|
||||
@@ -44,12 +45,15 @@ public final class RhinoSystemOutputChecker implements RhinoResultChecker {
|
||||
+ "END_OF_EXPECTED\n", trimmedExpected.equals(trimmedActual));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String getSystemOutput(@NotNull Context context, @NotNull Scriptable scope) {
|
||||
Object output = context.evaluateString(scope, "Kotlin.System.output()", "test", 0, null);
|
||||
Object output = context.evaluateString(scope, K2JSTranslator.GET_SYSTEM_OUT, "test", 0, null);
|
||||
RhinoUtils.flushSystemOut(context, scope);
|
||||
assertTrue("Output should be a string.", output instanceof String);
|
||||
return (String) output;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String trimSpace(@NotNull String s) {
|
||||
String[] choppedUpString = s.trim().split("\\s");
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
@@ -16,66 +16,135 @@
|
||||
|
||||
package org.jetbrains.k2js.test.rhino;
|
||||
|
||||
import closurecompiler.internal.com.google.common.collect.Maps;
|
||||
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 java.io.FileReader;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.jetbrains.jet.utils.ExceptionUtils.rethrow;
|
||||
import static org.jetbrains.k2js.test.BasicTest.pathToTestFilesRoot;
|
||||
|
||||
/**
|
||||
* @author Pavel Talanov
|
||||
*/
|
||||
public final class RhinoUtils {
|
||||
|
||||
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_5 = pathToTestFilesRoot() + "kotlin_lib_ecma5.js";
|
||||
|
||||
private RhinoUtils() {
|
||||
|
||||
}
|
||||
|
||||
private static void runFileWithRhino(@NotNull String inputFile,
|
||||
@NotNull Context context,
|
||||
@NotNull Scriptable scope) throws Exception {
|
||||
@NotNull Context context,
|
||||
@NotNull Scriptable scope) throws Exception {
|
||||
FileReader reader = new FileReader(inputFile);
|
||||
try {
|
||||
context.evaluateReader(scope, reader, inputFile, 1, null);
|
||||
} finally {
|
||||
}
|
||||
finally {
|
||||
reader.close();
|
||||
}
|
||||
}
|
||||
|
||||
public static void runRhinoTest(@NotNull List<String> fileNames,
|
||||
@NotNull RhinoResultChecker checker) throws Exception {
|
||||
|
||||
@NotNull RhinoResultChecker checker) throws Exception {
|
||||
runRhinoTest(fileNames, checker, null, EcmaVersion.defaultVersion());
|
||||
}
|
||||
|
||||
public static void runRhinoTest(@NotNull List<String> fileNames,
|
||||
@NotNull RhinoResultChecker checker,
|
||||
@Nullable Map<String, Object> variables,
|
||||
@NotNull EcmaVersion ecmaVersion) throws Exception {
|
||||
@NotNull RhinoResultChecker checker,
|
||||
@Nullable Map<String, Object> variables,
|
||||
@NotNull EcmaVersion ecmaVersion) throws Exception {
|
||||
Context context = createContext(ecmaVersion);
|
||||
try {
|
||||
Scriptable scope = getScope(ecmaVersion, context);
|
||||
putGlobalVariablesIntoScope(scope, variables);
|
||||
for (String filename : fileNames) {
|
||||
runFileWithRhino(filename, context, scope);
|
||||
}
|
||||
checker.runChecks(context, scope);
|
||||
}
|
||||
finally {
|
||||
Context.exit();
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Scriptable getScope(@NotNull EcmaVersion version, @NotNull Context context) {
|
||||
ScriptableObject scope = context.initStandardObjects(null, false);
|
||||
scope.setParentScope(getParentScope(version, context));
|
||||
return scope;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Scriptable getParentScope(@NotNull EcmaVersion version, @NotNull Context context) {
|
||||
Scriptable parentScope = versionToScope.get(version);
|
||||
if (parentScope == null) {
|
||||
parentScope = initScope(version, context);
|
||||
versionToScope.put(version, parentScope);
|
||||
}
|
||||
return parentScope;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Scriptable initScope(@NotNull EcmaVersion version, @NotNull Context context) {
|
||||
ScriptableObject scope = context.initStandardObjects();
|
||||
try {
|
||||
runFileWithRhino(getKotlinLibFile(version), context, scope);
|
||||
runFileWithRhino(KOTLIN_JS_LIB_COMMON, context, scope);
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw rethrow(e);
|
||||
}
|
||||
scope.sealObject();
|
||||
return scope;
|
||||
}
|
||||
|
||||
|
||||
//TODO:
|
||||
@NotNull
|
||||
private static Context createContext(@NotNull EcmaVersion ecmaVersion) {
|
||||
Context context = Context.enter();
|
||||
if (ecmaVersion == EcmaVersion.v5) {
|
||||
// actually, currently, doesn't matter because dart doesn't produce js 1.8 code (expression closures)
|
||||
context.setLanguageVersion(Context.VERSION_1_8);
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
Scriptable scope = context.initStandardObjects();
|
||||
if (variables != null) {
|
||||
Set<Map.Entry<String,Object>> entries = variables.entrySet();
|
||||
for (Map.Entry<String, Object> entry : entries) {
|
||||
String name = entry.getKey();
|
||||
Object value = entry.getValue();
|
||||
scope.put(name, scope, value);
|
||||
}
|
||||
private static void putGlobalVariablesIntoScope(@NotNull Scriptable scope, @Nullable Map<String, Object> variables) {
|
||||
if (variables == null) {
|
||||
return;
|
||||
}
|
||||
for (String filename : fileNames) {
|
||||
runFileWithRhino(filename, context, scope);
|
||||
Set<Map.Entry<String, Object>> entries = variables.entrySet();
|
||||
for (Map.Entry<String, Object> entry : entries) {
|
||||
String name = entry.getKey();
|
||||
Object value = entry.getValue();
|
||||
scope.put(name, scope, value);
|
||||
}
|
||||
checker.runChecks(context, scope);
|
||||
Context.exit();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static final Map<EcmaVersion, Scriptable> versionToScope = Maps.newHashMap();
|
||||
|
||||
@NotNull
|
||||
public static String getKotlinLibFile(@NotNull EcmaVersion ecmaVersion) {
|
||||
return ecmaVersion == EcmaVersion.v5 ? KOTLIN_JS_LIB_ECMA_5 : KOTLIN_JS_LIB_ECMA_3;
|
||||
}
|
||||
|
||||
static void flushSystemOut(@NotNull Context context, @NotNull Scriptable scope) {
|
||||
context.evaluateString(scope, K2JSTranslator.FLUSH_SYSTEM_OUT, "test", 0, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import closurecompiler.internal.com.google.common.collect.Maps;
|
||||
import com.google.dart.compiler.backend.js.ast.JsProgram;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
import org.jetbrains.k2js.config.EcmaVersion;
|
||||
import org.jetbrains.k2js.facade.K2JSTranslator;
|
||||
@@ -29,7 +30,6 @@ import org.jetbrains.k2js.test.config.TestConfig;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -46,21 +46,16 @@ public final class TranslationUtils {
|
||||
@NotNull
|
||||
private static final Map<EcmaVersion, K2JSTranslator> translators = Maps.newHashMap();
|
||||
|
||||
public static void translateFile(@NotNull Project project, @NotNull String inputFile,
|
||||
@NotNull String outputFile, @NotNull MainCallParameters mainCallParameters, @NotNull EcmaVersion version) throws Exception {
|
||||
translateFiles(project, Collections.singletonList(inputFile), outputFile, mainCallParameters, version, null);
|
||||
}
|
||||
|
||||
public static void translateFiles(@NotNull Project project, @NotNull List<String> inputFiles,
|
||||
@NotNull String outputFile,
|
||||
@NotNull MainCallParameters mainCallParameters,
|
||||
@NotNull EcmaVersion version,
|
||||
List<String> rawStatements) throws Exception {
|
||||
@Nullable List<String> rawStatements) throws Exception {
|
||||
List<JetFile> psiFiles = createPsiFileList(inputFiles, project);
|
||||
JsProgram program = getTranslator(project, version).generateProgram(psiFiles, mainCallParameters, rawStatements);
|
||||
FileWriter writer = new FileWriter(new File(outputFile));
|
||||
try {
|
||||
writer.write(CodeGenerator.toString(program, null));
|
||||
writer.write(CodeGenerator.generateProgramToString(program, null));
|
||||
}
|
||||
finally {
|
||||
writer.close();
|
||||
|
||||
@@ -20,13 +20,13 @@ import com.google.common.collect.Lists;
|
||||
import com.google.dart.compiler.backend.js.ast.JsProgram;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
|
||||
import org.jetbrains.k2js.analyze.AnalyzerFacadeForJS;
|
||||
import org.jetbrains.k2js.config.Config;
|
||||
import org.jetbrains.k2js.facade.exceptions.TranslationException;
|
||||
import org.jetbrains.k2js.generate.CodeGenerator;
|
||||
import org.jetbrains.k2js.translate.general.Translation;
|
||||
import org.jetbrains.k2js.utils.JetFileUtils;
|
||||
|
||||
@@ -37,6 +37,7 @@ import java.util.List;
|
||||
|
||||
import static org.jetbrains.k2js.facade.FacadeUtils.parseString;
|
||||
import static org.jetbrains.k2js.facade.FacadeUtils.writeCodeToFile;
|
||||
import static org.jetbrains.k2js.generate.CodeGenerator.generateProgramToString;
|
||||
|
||||
/**
|
||||
* @author Pavel Talanov
|
||||
@@ -45,6 +46,9 @@ import static org.jetbrains.k2js.facade.FacadeUtils.writeCodeToFile;
|
||||
*/
|
||||
public final class K2JSTranslator {
|
||||
|
||||
public static final String FLUSH_SYSTEM_OUT = "Kotlin.System.flush();\n";
|
||||
public static final String GET_SYSTEM_OUT = "Kotlin.System.output();\n";
|
||||
|
||||
public static void translateWithMainCallParametersAndSaveToFile(@NotNull MainCallParameters mainCall,
|
||||
@NotNull List<JetFile> files,
|
||||
@NotNull String outputPath,
|
||||
@@ -62,22 +66,20 @@ public final class K2JSTranslator {
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
//TODO: web demo related method
|
||||
//NOTE: web demo related method
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
@NotNull
|
||||
public String translateStringWithCallToMain(@NotNull String programText, @NotNull String argumentsString) throws TranslationException {
|
||||
JetFile file = JetFileUtils.createPsiFile("test", programText, getProject());
|
||||
String programCode = generateProgramCode(file, MainCallParameters.mainWithArguments(parseString(argumentsString)), null) + "\n";
|
||||
String flushOutput = "Kotlin.System.flush();\n";
|
||||
String programOutput = "Kotlin.System.output();\n";
|
||||
return flushOutput + programCode + programOutput;
|
||||
return FLUSH_SYSTEM_OUT + programCode + GET_SYSTEM_OUT;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String generateProgramCode(@NotNull JetFile file, @NotNull MainCallParameters mainCallParameters, List<String> rawStatements) throws TranslationException {
|
||||
public String generateProgramCode(@NotNull JetFile file, @NotNull MainCallParameters mainCallParameters,
|
||||
@Nullable List<String> rawStatements) throws TranslationException {
|
||||
JsProgram program = generateProgram(Arrays.asList(file), mainCallParameters, rawStatements);
|
||||
CodeGenerator generator = new CodeGenerator();
|
||||
return generator.generateToString(program, rawStatements);
|
||||
return generateProgramToString(program, rawStatements);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -85,14 +87,13 @@ public final class K2JSTranslator {
|
||||
throws TranslationException {
|
||||
List<String> rawStatements = Lists.newArrayList();
|
||||
JsProgram program = generateProgram(files, mainCallParameters, rawStatements);
|
||||
CodeGenerator generator = new CodeGenerator();
|
||||
return generator.generateToString(program, rawStatements);
|
||||
return generateProgramToString(program, rawStatements);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JsProgram generateProgram(@NotNull List<JetFile> filesToTranslate,
|
||||
@NotNull MainCallParameters mainCallParameters,
|
||||
List<String> rawStatements)
|
||||
@Nullable List<String> rawStatements)
|
||||
throws TranslationException {
|
||||
JetStandardLibrary.initialize(config.getProject());
|
||||
BindingContext bindingContext = AnalyzerFacadeForJS.analyzeFilesAndCheckErrors(filesToTranslate, config);
|
||||
|
||||
@@ -21,10 +21,8 @@ import com.google.dart.compiler.backend.js.ast.JsProgram;
|
||||
import com.google.dart.compiler.util.DefaultTextOutput;
|
||||
import com.google.dart.compiler.util.TextOutput;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -35,31 +33,16 @@ public final class CodeGenerator {
|
||||
@NotNull
|
||||
private final TextOutput output = new DefaultTextOutput(false);
|
||||
|
||||
public CodeGenerator() {
|
||||
}
|
||||
|
||||
public static void toFile(@NotNull String outputFile, @NotNull JsProgram program) throws IOException {
|
||||
CodeGenerator generator = new CodeGenerator();
|
||||
generator.generateToFile(program, new File(outputFile));
|
||||
private CodeGenerator() {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String toString(@NotNull JsProgram program, List<String> rawStatements) {
|
||||
public static String generateProgramToString(@NotNull JsProgram program, @Nullable List<String> rawStatements) {
|
||||
return (new CodeGenerator()).generateToString(program, rawStatements);
|
||||
}
|
||||
|
||||
public void generateToFile(@NotNull JsProgram program, @NotNull File file) throws IOException {
|
||||
generateCode(program);
|
||||
FileWriter writer = new FileWriter(file);
|
||||
try {
|
||||
writer.write(output.toString());
|
||||
} finally {
|
||||
writer.close();
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String generateToString(@NotNull JsProgram program, List<String> rawStatements) {
|
||||
private String generateToString(@NotNull JsProgram program, List<String> rawStatements) {
|
||||
generateCode(program);
|
||||
if (rawStatements != null) {
|
||||
for (String statement : rawStatements) {
|
||||
|
||||
Reference in New Issue
Block a user