From 212aeb5e534e0a8109ff70913fca88408b38e5ef Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 3 Mar 2015 22:12:06 -0800 Subject: [PATCH] Revert "Run jake in interactive mode so output isn't lost." --- .travis.yml | 3 +- Jakefile | 112 +++++++++++++++++++++++++++----------------- package.json | 2 +- src/compiler/tsc.ts | 2 +- tests/perfsys.ts | 105 +++++++++++++++++++++++++++++++++++++++++ tests/perftsc.ts | 30 ++++++++++++ 6 files changed, 208 insertions(+), 46 deletions(-) create mode 100644 tests/perfsys.ts create mode 100644 tests/perftsc.ts diff --git a/.travis.yml b/.travis.yml index 50ff61e20f4..305fad1e4a7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,8 +5,7 @@ node_js: sudo: false -before_script: - - npm install -g codeclimate-test-reporter +before_script: npm install -g codeclimate-test-reporter after_script: - cat coverage/lcov.info | codeclimate diff --git a/Jakefile b/Jakefile index 4c971efe0c9..324356a4af5 100644 --- a/Jakefile +++ b/Jakefile @@ -3,6 +3,7 @@ var fs = require("fs"); var os = require("os"); var path = require("path"); +var child_process = require("child_process"); // Variables var compilerDirectory = "src/compiler/"; @@ -25,8 +26,7 @@ var thirdParty = "ThirdPartyNoticeText.txt"; var nodeModulesPathPrefix = path.resolve("./node_modules/.bin/") + path.delimiter; if (process.env.path !== undefined) { process.env.path = nodeModulesPathPrefix + process.env.path; -} -else if (process.env.PATH !== undefined) { +} else if (process.env.PATH !== undefined) { process.env.PATH = nodeModulesPathPrefix + process.env.PATH; } @@ -203,8 +203,7 @@ function concatenateFiles(destinationFile, sourceFiles) { var useDebugMode = true; var host = (process.env.host || process.env.TYPESCRIPT_HOST || "node"); var compilerFilename = "tsc.js"; - - /* Compiles a file from a list of sources +/* Compiles a file from a list of sources * @param outFile: the target file name * @param sources: an array of the names of the source files * @param prereqs: prerequisite tasks to compiling the file @@ -215,9 +214,8 @@ var compilerFilename = "tsc.js"; * @param outDir: true to compile using --outDir * @param keepComments: false to compile using --removeComments * @param callback: a function to execute after the compilation process ends - * @async */ - function compileFile(outFile, sources, prereqs, prefixes, useBuiltCompiler, noOutFile, generateDeclarations, outDir, preserveConstEnums, keepComments, noResolve, stripInternal, callback) { +function compileFile(outFile, sources, prereqs, prefixes, useBuiltCompiler, noOutFile, generateDeclarations, outDir, preserveConstEnums, keepComments, noResolve, stripInternal, callback) { file(outFile, prereqs, function() { var dir = useBuiltCompiler ? builtLocalDirectory : LKGDirectory; var options = "--module commonjs -noImplicitAny"; @@ -256,9 +254,17 @@ var compilerFilename = "tsc.js"; var cmd = host + " " + dir + compilerFilename + " " + options + " "; cmd = cmd + sources.join(" "); + console.log(cmd + "\n"); - exec(cmd, function() { - console.log("") + var ex = jake.createExec([cmd]); + // Add listeners for output and error + ex.addListener("stdout", function(output) { + process.stdout.write(output); + }); + ex.addListener("stderr", function(error) { + process.stderr.write(error); + }); + ex.addListener("cmdEnd", function() { if (!useDebugMode && prefixes && fs.existsSync(outFile)) { for (var i in prefixes) { prependFile(prefixes[i], outFile); @@ -268,14 +274,14 @@ var compilerFilename = "tsc.js"; if (callback) { callback(); } - else { - complete(); - } - }, /* errorHandler */ function() { + + complete(); + }); + ex.addListener("error", function() { fs.unlinkSync(outFile); fail("Compilation of " + outFile + " unsuccessful"); }); - + ex.run(); }, {async: true}); } @@ -318,8 +324,19 @@ compileFile(processDiagnosticMessagesJs, // The generated diagnostics map; built for the compiler and for the 'generate-diagnostics' task file(diagnosticInfoMapTs, [processDiagnosticMessagesJs, diagnosticMessagesJson], function () { var cmd = "node " + processDiagnosticMessagesJs + " " + diagnosticMessagesJson; - - exec(cmd); + console.log(cmd); + var ex = jake.createExec([cmd]); + // Add listeners for output and error + ex.addListener("stdout", function(output) { + process.stdout.write(output); + }); + ex.addListener("stderr", function(error) { + process.stderr.write(error); + }); + ex.addListener("cmdEnd", function() { + complete(); + }); + ex.run(); }, {async: true}) desc("Generates a diagnostic file in TypeScript based on an input JSON file"); @@ -384,7 +401,6 @@ compileFile(nodeDefinitionsFile, servicesSources,[builtLocalDirectory, copyright // Delete the temp dir jake.rmRf(tempDirPath, {silent: true}); - complete(); }); var serverFile = path.join(builtLocalDirectory, "tsserver.js"); @@ -433,8 +449,10 @@ compileFile(word2mdJs, file(specMd, [word2mdJs, specWord], function () { var specWordFullPath = path.resolve(specWord); var cmd = "cscript //nologo " + word2mdJs + ' "' + specWordFullPath + '" ' + specMd; - - exec(cmd); + console.log(cmd); + child_process.exec(cmd, function () { + complete(); + }); }, {async: true}) @@ -485,24 +503,22 @@ var refTest262Baseline = path.join(internalTests, "baselines/test262/reference") desc("Builds the test infrastructure using the built compiler"); task("tests", ["local", run].concat(libraryTargets)); -/* Executes a command - * @param cmd: command to execute - * @param completeHandler?: a function to execute after the command ends - * @param errorHandler?: a function to execute if an error occurs - * @async - */ -function exec(cmd, completeHandler, errorHandler) { - console.log(cmd); - var ex = jake.createExec([cmd], {windowsVerbatimArguments: true, interactive: true}); +function exec(cmd, completeHandler) { + var ex = jake.createExec([cmd], {windowsVerbatimArguments: true}); + // Add listeners for output and error + ex.addListener("stdout", function(output) { + process.stdout.write(output); + }); + ex.addListener("stderr", function(error) { + process.stderr.write(error); + }); ex.addListener("cmdEnd", function() { if (completeHandler) { completeHandler(); } - else { - complete(); - } + complete(); }); - ex.addListener("error", errorHandler || function(e, status) { + ex.addListener("error", function(e, status) { fail("Process exited with code " + status); }) @@ -521,7 +537,7 @@ function cleanTestDirs() { } jake.mkdirP(localRwcBaseline); - jake.mkdirP(localTest262Baseline); + jake.mkdirP(localTest262Baseline); jake.mkdirP(localBaseline); } @@ -532,14 +548,10 @@ function writeTestConfigFile(tests, testConfigFile) { fs.writeFileSync('test.config', testConfigContents); } -/* Removes project output - * @async - */ function deleteTemporaryProjectOutput() { if (fs.existsSync(path.join(localBaseline, "projectOutput/"))) { jake.rmRf(path.join(localBaseline, "projectOutput/")); } - complete(); } var testTimeout = 20000; @@ -568,14 +580,14 @@ task("runtests", ["tests", builtLocalDirectory], function() { // timeout normally isn't necessary but Travis-CI has been timing out on compiler baselines occasionally // default timeout is 2sec which really should be enough, but maybe we just need a small amount longer var cmd = host + " -R " + reporter + tests + colors + ' -t ' + testTimeout + ' ' + run; - + console.log(cmd); exec(cmd, deleteTemporaryProjectOutput); }, {async: true}); desc("Generates code coverage data via instanbul") task("generate-code-coverage", ["tests", builtLocalDirectory], function () { var cmd = 'istanbul cover node_modules/mocha/bin/_mocha -- -R min -t ' + testTimeout + ' ' + run; - + console.log(cmd); exec(cmd); }, { async: true }); @@ -607,6 +619,7 @@ task("runtests-browser", ["tests", "browserify", builtLocalDirectory], function( tests = tests ? tests : ''; var cmd = host + " tests/webTestServer.js " + port + " " + browser + " " + tests + console.log(cmd); exec(cmd); }, {async: true}); @@ -622,12 +635,14 @@ function getDiffTool() { desc("Diffs the compiler baselines using the diff tool specified by the 'DIFF' environment variable"); task('diff', function () { var cmd = '"' + getDiffTool() + '" ' + refBaseline + ' ' + localBaseline; + console.log(cmd) exec(cmd); }, {async: true}); desc("Diffs the RWC baselines using the diff tool specified by the 'DIFF' environment variable"); task('diff-rwc', function () { var cmd = '"' + getDiffTool() + '" ' + refRwcBaseline + ' ' + localRwcBaseline; + console.log(cmd) exec(cmd); }, {async: true}); @@ -674,6 +689,13 @@ task("webhost", [webhostJsPath], function() { jake.cpR(path.join(builtLocalDirectory, "lib.d.ts"), "tests/webhost/", {silent: true}); }); +// Perf compiler +var perftscPath = "tests/perftsc.ts"; +var perftscJsPath = "built/local/perftsc.js"; +compileFile(perftscJsPath, [perftscPath], [tscFile, perftscPath, "tests/perfsys.ts"].concat(libraryTargets), [], /*useBuiltCompiler*/ true); +desc("Builds augmented version of the compiler for perf tests"); +task("perftsc", [perftscJsPath]); + // Instrumented compiler var loggedIOpath = harnessDirectory + 'loggedIO.ts'; var loggedIOJsPath = builtLocalDirectory + 'loggedIO.js'; @@ -682,12 +704,14 @@ file(loggedIOJsPath, [builtLocalDirectory, loggedIOpath], function() { jake.mkdirP(temp); var options = "--outdir " + temp + ' ' + loggedIOpath; var cmd = host + " " + LKGDirectory + compilerFilename + " " + options + " "; - - exec(cmd, function() { + console.log(cmd + "\n"); + var ex = jake.createExec([cmd]); + ex.addListener("cmdEnd", function() { fs.renameSync(temp + '/harness/loggedIO.js', loggedIOJsPath); jake.rmRf(temp); complete(); }); + ex.run(); }, {async: true}); var instrumenterPath = harnessDirectory + 'instrumenter.ts'; @@ -697,6 +721,10 @@ compileFile(instrumenterJsPath, [instrumenterPath], [tscFile, instrumenterPath], desc("Builds an instrumented tsc.js"); task('tsc-instrumented', [loggedIOJsPath, instrumenterJsPath, tscFile], function() { var cmd = host + ' ' + instrumenterJsPath + ' record iocapture ' + builtLocalDirectory + compilerFilename; - - exec(cmd); + console.log(cmd); + var ex = jake.createExec([cmd]); + ex.addListener("cmdEnd", function() { + complete(); + }); + ex.run(); }, { async: true }); diff --git a/package.json b/package.json index b53916b37b3..9261174b68f 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,6 @@ "codeclimate-test-reporter": "latest" }, "scripts": { - "test": "jake --trace generate-code-coverage" + "test": "jake generate-code-coverage" } } diff --git a/src/compiler/tsc.ts b/src/compiler/tsc.ts index 68507b34574..57c2298d3d3 100644 --- a/src/compiler/tsc.ts +++ b/src/compiler/tsc.ts @@ -258,7 +258,7 @@ module ts { reportDiagnostic(createCompilerDiagnostic(Diagnostics.Compilation_complete_Watching_for_file_changes)); } - function getSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void) { + function getSourceFile(fileName: string, languageVersion: ScriptTarget, onError ?: (message: string) => void) { // Return existing SourceFile object if one is available if (cachedProgram) { var sourceFile = cachedProgram.getSourceFile(fileName); diff --git a/tests/perfsys.ts b/tests/perfsys.ts new file mode 100644 index 00000000000..143d0d637d4 --- /dev/null +++ b/tests/perfsys.ts @@ -0,0 +1,105 @@ +/// +/// + +module perftest { + + interface IOLog { + resolvePath: ts.Map; + fileNames: string[]; + } + + export interface IO { + getOut(): string; + } + + export var readFile = ts.sys.readFile; + var writeFile = ts.sys.writeFile; + export var write = ts.sys.write; + var resolvePath = ts.sys.resolvePath; + export var getExecutingFilePath = ts.sys.getExecutingFilePath; + export var getCurrentDirectory = ts.sys.getCurrentDirectory; + var exit = ts.sys.exit; + + var args = ts.sys.args; + + // augment sys so first ts.executeCommandLine call will be finish silently + ts.sys.write = (s: string) => { }; + ts.sys.exit = (code: number) => { }; + ts.sys.args = [] + + export function restoreSys() { + ts.sys.args = args; + ts.sys.write = write; + } + + export function hasLogIOFlag() { + return args.length > 2 && args[0] === "--logio"; + } + + export function getArgsWithoutLogIOFlag() { + return args.slice(2); + } + + export function getArgsWithoutIOLogFile() { + return args.slice(1); + } + + var resolvePathLog: ts.Map = {}; + + export function interceptIO() { + ts.sys.resolvePath = (s) => { + var result = resolvePath(s); + resolvePathLog[s] = result; + return result; + }; + } + + export function writeIOLog(fileNames: string[]) { + var path = args[1]; + var log: IOLog = { + fileNames: fileNames, + resolvePath: resolvePathLog + }; + + writeFile(path, JSON.stringify(log)); + } + + export function prepare(): IO { + var log = JSON.parse(readFile(args[0])); + + var files: ts.Map = {}; + log.fileNames.forEach(f => { files[f] = readFile(f); }) + + ts.sys.createDirectory = (s: string) => { }; + ts.sys.directoryExists = (s: string) => true; + ts.sys.fileExists = (s: string) => true; + + var currentDirectory = ts.sys.getCurrentDirectory(); + ts.sys.getCurrentDirectory = () => currentDirectory; + + var executingFilePath = ts.sys.getExecutingFilePath(); + ts.sys.getExecutingFilePath = () => executingFilePath; + + ts.sys.readFile = (s: string) => { + return files[s]; + } + + ts.sys.resolvePath = (s: string) => { + var path = log.resolvePath[s]; + if (!path) { + throw new Error("Unexpected path '" + s + "'"); + } + return path + } + + ts.sys.writeFile = (path: string, data: string) => { }; + + var out: string = ""; + + ts.sys.write = (s: string) => { out += s; }; + + return { + getOut: () => out, + }; + } +} diff --git a/tests/perftsc.ts b/tests/perftsc.ts new file mode 100644 index 00000000000..e0189896a15 --- /dev/null +++ b/tests/perftsc.ts @@ -0,0 +1,30 @@ +/// +/// + +// resolve all files used in this compilation +if (perftest.hasLogIOFlag()) { + perftest.interceptIO(); + + var compilerHost: ts.CompilerHost = { + getSourceFile: (s, v) => { + var content = perftest.readFile(s); + return content !== undefined ? ts.createSourceFile(s, content, v) : undefined; + }, + getDefaultLibFilename: () => ts.combinePaths(ts.getDirectoryPath(ts.normalizePath(perftest.getExecutingFilePath())), "lib.d.ts"), + writeFile: (f: string, content: string) => { throw new Error("Unexpected operation: writeFile"); }, + getCurrentDirectory: () => perftest.getCurrentDirectory(), + getCanonicalFileName: (f: string) => ts.sys.useCaseSensitiveFileNames ? f : f.toLowerCase(), + useCaseSensitiveFileNames: () => ts.sys.useCaseSensitiveFileNames, + getNewLine: () => ts.sys.newLine + }; + + var commandLine = ts.parseCommandLine(perftest.getArgsWithoutLogIOFlag()); + var program = ts.createProgram(commandLine.filenames, commandLine.options, compilerHost); + var fileNames = program.getSourceFiles().map(f => f.filename); + perftest.writeIOLog(fileNames); +} +else { + var io = perftest.prepare(); + ts.executeCommandLine(perftest.getArgsWithoutIOLogFile()); + perftest.write(io.getOut()); +}