From 880e167158d26cff3984c43977b62de4ef74c743 Mon Sep 17 00:00:00 2001 From: Bart van der Schoor Date: Thu, 27 Feb 2014 19:25:46 +0100 Subject: [PATCH] added reference parser stores as File::references[]:File added source-map-support dependency added glob dependency ditched io env wrapper for regular node fs / glob ditched exec env windows wrapper added extract util cleaned File.ts directory handling added pre-stage to test runner temporary exclude most files (for testing) --- _infrastructure/tests/runner.js | 712 +++++------------- _infrastructure/tests/runner.ts | 57 +- .../tests/src/{indexer.ts => changes.ts} | 0 _infrastructure/tests/src/file.ts | 17 +- _infrastructure/tests/src/host/exec.ts | 31 +- _infrastructure/tests/src/host/io.ts | 548 -------------- _infrastructure/tests/src/references.ts | 80 ++ _infrastructure/tests/src/suite/tscParams.ts | 12 +- _infrastructure/tests/src/timer.ts | 13 +- _infrastructure/tests/src/tsc.ts | 8 +- _infrastructure/tests/src/util.ts | 20 + 11 files changed, 363 insertions(+), 1135 deletions(-) rename _infrastructure/tests/src/{indexer.ts => changes.ts} (100%) delete mode 100644 _infrastructure/tests/src/host/io.ts create mode 100644 _infrastructure/tests/src/references.ts diff --git a/_infrastructure/tests/runner.js b/_infrastructure/tests/runner.js index 37aefb7e5..f73c72a39 100644 --- a/_infrastructure/tests/runner.js +++ b/_infrastructure/tests/runner.js @@ -21,35 +21,6 @@ var ExecResult = (function () { return ExecResult; })(); -var WindowsScriptHostExec = (function () { - function WindowsScriptHostExec() { - } - WindowsScriptHostExec.prototype.exec = function (filename, cmdLineArgs, handleResult) { - var result = new ExecResult(); - var shell = new ActiveXObject('WScript.Shell'); - try { - var process = shell.Exec(filename + ' ' + cmdLineArgs.join(' ')); - } catch (e) { - result.stderr = e.message; - result.exitCode = 1; - handleResult(result); - return; - } - - while (process.Status != 0) { - } - - result.exitCode = process.ExitCode; - if (!process.StdOut.AtEndOfStream) - result.stdout = process.StdOut.ReadAll(); - if (!process.StdErr.AtEndOfStream) - result.stderr = process.StdErr.ReadAll(); - - handleResult(result); - }; - return WindowsScriptHostExec; -})(); - var NodeExec = (function () { function NodeExec() { } @@ -71,492 +42,8 @@ var NodeExec = (function () { })(); var Exec = function () { - var global = Function("return this;").call(null); - if (typeof global.ActiveXObject !== "undefined") { - return new WindowsScriptHostExec(); - } else { - return new NodeExec(); - } + return new NodeExec(); }(); -// -// Copyright (c) Microsoft Corporation. All rights reserved. -// -// 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. -// - -var IOUtils; -(function (IOUtils) { - // Creates the directory including its parent if not already present - function createDirectoryStructure(ioHost, dirName) { - if (ioHost.directoryExists(dirName)) { - return; - } - - var parentDirectory = ioHost.dirName(dirName); - if (parentDirectory != "") { - createDirectoryStructure(ioHost, parentDirectory); - } - ioHost.createDirectory(dirName); - } - - // Creates a file including its directory structure if not already present - function createFileAndFolderStructure(ioHost, fileName, useUTF8) { - var path = ioHost.resolvePath(fileName); - var dirName = ioHost.dirName(path); - createDirectoryStructure(ioHost, dirName); - return ioHost.createFile(path, useUTF8); - } - IOUtils.createFileAndFolderStructure = createFileAndFolderStructure; - - function throwIOError(message, error) { - var errorMessage = message; - if (error && error.message) { - errorMessage += (" " + error.message); - } - throw new Error(errorMessage); - } - IOUtils.throwIOError = throwIOError; -})(IOUtils || (IOUtils = {})); - - - -var IO = (function () { - // Create an IO object for use inside WindowsScriptHost hosts - // Depends on WSCript and FileSystemObject - function getWindowsScriptHostIO() { - var fso = new ActiveXObject("Scripting.FileSystemObject"); - var streamObjectPool = []; - - function getStreamObject() { - if (streamObjectPool.length > 0) { - return streamObjectPool.pop(); - } else { - return new ActiveXObject("ADODB.Stream"); - } - } - - function releaseStreamObject(obj) { - streamObjectPool.push(obj); - } - - var args = []; - for (var i = 0; i < WScript.Arguments.length; i++) { - args[i] = WScript.Arguments.Item(i); - } - - return { - readFile: function (path) { - try { - var streamObj = getStreamObject(); - streamObj.Open(); - streamObj.Type = 2; // Text data - streamObj.Charset = 'x-ansi'; // Assume we are reading ansi text - streamObj.LoadFromFile(path); - var bomChar = streamObj.ReadText(2); - streamObj.Position = 0; // Position has to be at 0 before changing the encoding - if ((bomChar.charCodeAt(0) == 0xFE && bomChar.charCodeAt(1) == 0xFF) || (bomChar.charCodeAt(0) == 0xFF && bomChar.charCodeAt(1) == 0xFE)) { - streamObj.Charset = 'unicode'; - } else if (bomChar.charCodeAt(0) == 0xEF && bomChar.charCodeAt(1) == 0xBB) { - streamObj.Charset = 'utf-8'; - } - - // Read the whole file - var str = streamObj.ReadText(-1); - streamObj.Close(); - releaseStreamObject(streamObj); - return str; - } catch (err) { - IOUtils.throwIOError("Error reading file \"" + path + "\".", err); - } - }, - writeFile: function (path, contents) { - var file = this.createFile(path); - file.Write(contents); - file.Close(); - }, - fileExists: function (path) { - return fso.FileExists(path); - }, - resolvePath: function (path) { - return fso.GetAbsolutePathName(path); - }, - dirName: function (path) { - return fso.GetParentFolderName(path); - }, - findFile: function (rootPath, partialFilePath) { - var path = fso.GetAbsolutePathName(rootPath) + "/" + partialFilePath; - - while (true) { - if (fso.FileExists(path)) { - try { - var content = this.readFile(path); - return { content: content, path: path }; - } catch (err) { - //Tools.CompilerDiagnostics.debugPrint("Could not find " + path + ", trying parent"); - } - } else { - rootPath = fso.GetParentFolderName(fso.GetAbsolutePathName(rootPath)); - - if (rootPath == "") { - return null; - } else { - path = fso.BuildPath(rootPath, partialFilePath); - } - } - } - }, - deleteFile: function (path) { - try { - if (fso.FileExists(path)) { - fso.DeleteFile(path, true); // true: delete read-only files - } - } catch (e) { - IOUtils.throwIOError("Couldn't delete file '" + path + "'.", e); - } - }, - createFile: function (path, useUTF8) { - try { - var streamObj = getStreamObject(); - streamObj.Charset = useUTF8 ? 'utf-8' : 'x-ansi'; - streamObj.Open(); - return { - Write: function (str) { - streamObj.WriteText(str, 0); - }, - WriteLine: function (str) { - streamObj.WriteText(str, 1); - }, - Close: function () { - try { - streamObj.SaveToFile(path, 2); - } catch (saveError) { - IOUtils.throwIOError("Couldn't write to file '" + path + "'.", saveError); - } finally { - if (streamObj.State != 0) { - streamObj.Close(); - } - releaseStreamObject(streamObj); - } - } - }; - } catch (creationError) { - IOUtils.throwIOError("Couldn't write to file '" + path + "'.", creationError); - } - }, - directoryExists: function (path) { - return fso.FolderExists(path); - }, - createDirectory: function (path) { - try { - if (!this.directoryExists(path)) { - fso.CreateFolder(path); - } - } catch (e) { - IOUtils.throwIOError("Couldn't create directory '" + path + "'.", e); - } - }, - dir: function (path, spec, options) { - options = options || {}; - function filesInFolder(folder, root) { - var paths = []; - var fc; - - if (options.recursive) { - fc = new Enumerator(folder.subfolders); - - for (; !fc.atEnd(); fc.moveNext()) { - paths = paths.concat(filesInFolder(fc.item(), root + "/" + fc.item().Name)); - } - } - - fc = new Enumerator(folder.files); - - for (; !fc.atEnd(); fc.moveNext()) { - if (!spec || fc.item().Name.match(spec)) { - paths.push(root + "/" + fc.item().Name); - } - } - - return paths; - } - - var folder = fso.GetFolder(path); - var paths = []; - - return filesInFolder(folder, path); - }, - print: function (str) { - WScript.StdOut.Write(str); - }, - printLine: function (str) { - WScript.Echo(str); - }, - arguments: args, - stderr: WScript.StdErr, - stdout: WScript.StdOut, - watchFile: null, - run: function (source, filename) { - try { - eval(source); - } catch (e) { - IOUtils.throwIOError("Error while executing file '" + filename + "'.", e); - } - }, - getExecutingFilePath: function () { - return WScript.ScriptFullName; - }, - quit: function (exitCode) { - if (typeof exitCode === "undefined") { exitCode = 0; } - try { - WScript.Quit(exitCode); - } catch (e) { - } - } - }; - } - ; - - // Create an IO object for use inside Node.js hosts - // Depends on 'fs' and 'path' modules - function getNodeIO() { - var _fs = require('fs'); - var _path = require('path'); - var _module = require('module'); - - return { - readFile: function (file) { - try { - var buffer = _fs.readFileSync(file); - switch (buffer[0]) { - case 0xFE: - if (buffer[1] == 0xFF) { - // utf16-be. Reading the buffer as big endian is not supported, so convert it to - // Little Endian first - var i = 0; - while ((i + 1) < buffer.length) { - var temp = buffer[i]; - buffer[i] = buffer[i + 1]; - buffer[i + 1] = temp; - i += 2; - } - return buffer.toString("ucs2", 2); - } - break; - case 0xFF: - if (buffer[1] == 0xFE) { - // utf16-le - return buffer.toString("ucs2", 2); - } - break; - case 0xEF: - if (buffer[1] == 0xBB) { - // utf-8 - return buffer.toString("utf8", 3); - } - } - - // Default behaviour - return buffer.toString(); - } catch (e) { - IOUtils.throwIOError("Error reading file \"" + file + "\".", e); - } - }, - writeFile: _fs.writeFileSync, - deleteFile: function (path) { - try { - _fs.unlinkSync(path); - } catch (e) { - IOUtils.throwIOError("Couldn't delete file '" + path + "'.", e); - } - }, - fileExists: function (path) { - return _fs.existsSync(path); - }, - createFile: function (path, useUTF8) { - function mkdirRecursiveSync(path) { - var stats = _fs.statSync(path); - if (stats.isFile()) { - IOUtils.throwIOError("\"" + path + "\" exists but isn't a directory.", null); - } else if (stats.isDirectory()) { - return; - } else { - mkdirRecursiveSync(_path.dirname(path)); - _fs.mkdirSync(path, parseInt('0775', 8)); - } - } - - mkdirRecursiveSync(_path.dirname(path)); - - try { - var fd = _fs.openSync(path, 'w'); - } catch (e) { - IOUtils.throwIOError("Couldn't write to file '" + path + "'.", e); - } - return { - Write: function (str) { - _fs.writeSync(fd, str); - }, - WriteLine: function (str) { - _fs.writeSync(fd, str + '\r\n'); - }, - Close: function () { - _fs.closeSync(fd); - fd = null; - } - }; - }, - dir: function dir(path, spec, options) { - options = options || {}; - - function filesInFolder(folder, deep) { - var paths = []; - - var files = _fs.readdirSync(folder); - for (var i = 0; i < files.length; i++) { - var stat = _fs.statSync(folder + "/" + files[i]); - if (options.recursive && stat.isDirectory()) { - if (deep < (options.deep || 100)) { - paths = paths.concat(filesInFolder(folder + "/" + files[i], 1)); - } - } else if (stat.isFile() && (!spec || files[i].match(spec))) { - paths.push(folder + "/" + files[i]); - } - } - - return paths; - } - - return filesInFolder(path, 0); - }, - createDirectory: function (path) { - try { - if (!this.directoryExists(path)) { - _fs.mkdirSync(path); - } - } catch (e) { - IOUtils.throwIOError("Couldn't create directory '" + path + "'.", e); - } - }, - directoryExists: function (path) { - return _fs.existsSync(path) && _fs.lstatSync(path).isDirectory(); - }, - resolvePath: function (path) { - return _path.resolve(path); - }, - dirName: function (path) { - return _path.dirname(path); - }, - findFile: function (rootPath, partialFilePath) { - var path = rootPath + "/" + partialFilePath; - - while (true) { - if (_fs.existsSync(path)) { - try { - var content = this.readFile(path); - return { content: content, path: path }; - } catch (err) { - //Tools.CompilerDiagnostics.debugPrint(("Could not find " + path) + ", trying parent"); - } - } else { - var parentPath = _path.resolve(rootPath, ".."); - - // Node will just continue to repeat the root path, rather than return null - if (rootPath === parentPath) { - return null; - } else { - rootPath = parentPath; - path = _path.resolve(rootPath, partialFilePath); - } - } - } - }, - print: function (str) { - process.stdout.write(str); - }, - printLine: function (str) { - process.stdout.write(str + '\n'); - }, - arguments: process.argv.slice(2), - stderr: { - Write: function (str) { - process.stderr.write(str); - }, - WriteLine: function (str) { - process.stderr.write(str + '\n'); - }, - Close: function () { - } - }, - stdout: { - Write: function (str) { - process.stdout.write(str); - }, - WriteLine: function (str) { - process.stdout.write(str + '\n'); - }, - Close: function () { - } - }, - watchFile: function (filename, callback) { - var firstRun = true; - var processingChange = false; - - var fileChanged = function (curr, prev) { - if (!firstRun) { - if (curr.mtime < prev.mtime) { - return; - } - - _fs.unwatchFile(filename, fileChanged); - if (!processingChange) { - processingChange = true; - callback(filename); - setTimeout(function () { - processingChange = false; - }, 100); - } - } - firstRun = false; - _fs.watchFile(filename, { persistent: true, interval: 500 }, fileChanged); - }; - - fileChanged(); - return { - filename: filename, - close: function () { - _fs.unwatchFile(filename, fileChanged); - } - }; - }, - run: function (source, filename) { - require.main.filename = filename; - require.main.paths = _module._nodeModulePaths(_path.dirname(_fs.realpathSync(filename))); - require.main._compile(source, filename); - }, - getExecutingFilePath: function () { - return process.mainModule.filename; - }, - quit: process.exit - }; - } - ; - - if (typeof ActiveXObject === "function") - return getWindowsScriptHostIO(); - else if (typeof require === "function") - return getNodeIO(); - else - return null; -})(); var DT; (function (DT) { var path = require('path'); @@ -569,20 +56,31 @@ var DT; function File(baseDir, filePathWithName) { this.baseDir = baseDir; this.filePathWithName = filePathWithName; - var dirName = path.dirname(this.filePathWithName.substr(this.baseDir.length + 1)).replace('\\', '/'); - this.dir = dirName.split('/')[0]; - this.file = path.basename(this.filePathWithName, '.ts'); + this.references = []; this.ext = path.extname(this.filePathWithName); + this.file = path.basename(this.filePathWithName, this.ext); + this.dir = path.dirname(this.filePathWithName); } Object.defineProperty(File.prototype, "formatName", { // From '/complete/path/to/file' to 'specfolder/specfile.d.ts' get: function () { - var dirName = path.dirname(this.filePathWithName.substr(this.baseDir.length + 1)).replace('\\', '/'); - return this.dir + ((dirName.split('/').length > 1) ? '/-/' : '/') + this.file + this.ext; + return path.join(this.dir, this.file + this.ext); }, enumerable: true, configurable: true }); + + Object.defineProperty(File.prototype, "fullPath", { + get: function () { + return path.join(this.baseDir, this.dir, this.file + this.ext); + }, + enumerable: true, + configurable: true + }); + + File.prototype.toString = function () { + return '[File ' + this.filePathWithName + ']'; + }; return File; })(); DT.File = File; @@ -592,6 +90,8 @@ var DT; /// var DT; (function (DT) { + var fs = require('fs'); + var Tsc = (function () { function Tsc() { } @@ -605,16 +105,16 @@ var DT; options.useTscParams = true; } - if (!IO.fileExists(tsfile)) { + if (!fs.existsSync(tsfile)) { throw new Error(tsfile + " not exists"); } var tscPath = './_infrastructure/tests/typescript/' + options.tscVersion + '/tsc.js'; - if (!IO.fileExists(tscPath)) { + if (!fs.existsSync(tscPath)) { throw new Error(tscPath + ' is not exists'); } var command = 'node ' + tscPath + ' --module commonjs '; - if (options.useTscParams && IO.fileExists(tsfile + '.tscparams')) { + if (options.useTscParams && fs.existsSync(tsfile + '.tscparams')) { command += '@' + tsfile + '.tscparams'; } else if (options.checkNoImplicitAny) { command += '--noImplicitAny'; @@ -654,10 +154,12 @@ var DT; }; Timer.prettyDate = function (date1, date2) { - var diff = ((date2 - date1) / 1000), day_diff = Math.floor(diff / 86400); + var diff = ((date2 - date1) / 1000); + var day_diff = Math.floor(diff / 86400); - if (isNaN(day_diff) || day_diff < 0 || day_diff >= 31) - return; + if (isNaN(day_diff) || day_diff < 0 || day_diff >= 31) { + return null; + } return (day_diff == 0 && (diff < 60 && (diff + " seconds") || diff < 120 && "1 minute" || diff < 3600 && Math.floor(diff / 60) + " minutes" || diff < 7200 && "1 hour" || diff < 86400 && Math.floor(diff / 3600) + " hours") || day_diff == 1 && "Yesterday" || day_diff < 7 && day_diff + " days" || day_diff < 31 && Math.ceil(day_diff / 7) + " weeks"); }; @@ -667,10 +169,107 @@ var DT; })(DT || (DT = {})); var DT; (function (DT) { + var referenceTagExp = //g; + function endsWith(str, suffix) { return str.indexOf(suffix, str.length - suffix.length) !== -1; } DT.endsWith = endsWith; + + function extractReferenceTags(source) { + var ret = []; + var match; + + if (!referenceTagExp.global) { + throw new Error('referenceTagExp RegExp must have global flag'); + } + referenceTagExp.lastIndex = 0; + + while ((match = referenceTagExp.exec(source))) { + if (match.length > 0 && match[1].length > 0) { + ret.push(match[1]); + } + } + return ret; + } + DT.extractReferenceTags = extractReferenceTags; +})(DT || (DT = {})); +/// +/// +/// +var DT; +(function (DT) { + var fs = require('fs'); + var path = require('path'); + + var ReferenceIndex = (function () { + function ReferenceIndex(options) { + this.options = options; + } + ReferenceIndex.prototype.collectReferences = function (files, callback) { + var _this = this; + this.fileMap = Object.create(null); + files.forEach(function (file) { + _this.fileMap[file.fullPath] = file; + }); + this.loadReferences(files, function () { + callback(); + }); + }; + + ReferenceIndex.prototype.loadReferences = function (files, callback) { + var _this = this; + var queue = files.slice(0); + var active = []; + var max = 50; + var next = function () { + if (queue.length === 0 && active.length === 0) { + callback(); + return; + } + + while (queue.length > 0 && active.length < max) { + var file = queue.pop(); + active.push(file); + _this.parseFile(file, function (file) { + active.splice(active.indexOf(file), 1); + next(); + }); + } + }; + process.nextTick(next); + }; + + ReferenceIndex.prototype.parseFile = function (file, callback) { + var _this = this; + fs.readFile(file.filePathWithName, { + encoding: 'utf8', + flag: 'r' + }, function (err, content) { + if (err) { + throw err; + } + + // console.log('----'); + // console.log(file.filePathWithName); + file.references = DT.extractReferenceTags(content).map(function (ref) { + return path.resolve(path.dirname(file.fullPath), ref); + }).reduce(function (memo, ref) { + if (ref in _this.fileMap) { + memo.push(_this.fileMap[ref]); + } else { + console.log('not mapped? -> ' + ref); + } + return memo; + }, []); + + // console.log(file.references); + callback(file); + }); + }; + return ReferenceIndex; + })(); + DT.ReferenceIndex = ReferenceIndex; })(DT || (DT = {})); /// /// @@ -951,6 +550,8 @@ var DT; /// var DT; (function (DT) { + var fs = require('fs'); + ///////////////////////////////// // Try compile without .tscparams // It may indicate that it is compatible with --noImplicitAny maybe... @@ -973,14 +574,18 @@ var DT; } FindNotRequiredTscparams.prototype.filterTargetFiles = function (files) { return files.filter(function (file) { - return IO.fileExists(file.filePathWithName + '.tscparams'); + return fs.existsSync(file.filePathWithName + '.tscparams'); }); }; FindNotRequiredTscparams.prototype.runTest = function (targetFile, callback) { var _this = this; this.print.clearCurrentLine().out(targetFile.formatName); - new DT.Test(this, targetFile, { tscVersion: this.options.tscVersion, useTscParams: false, checkNoImplicitAny: true }).run(function (result) { + new DT.Test(this, targetFile, { + tscVersion: this.options.tscVersion, + useTscParams: false, + checkNoImplicitAny: true + }).run(function (result) { _this.testResults.push(result); callback(result); }); @@ -1005,11 +610,11 @@ var DT; })(DT || (DT = {})); /// /// -/// /// /// /// /// +/// /// /// /// @@ -1018,8 +623,11 @@ var DT; /// var DT; (function (DT) { + require('source-map-support'); + var fs = require('fs'); var path = require('path'); + var glob = require('glob'); DT.DEFAULT_TSC_VERSION = "0.9.1.1"; @@ -1075,16 +683,32 @@ var DT; this.suites = []; this.options.findNotRequiredTscparams = !!this.options.findNotRequiredTscparams; - var filesName = IO.dir(dtPath, /.\.ts/g, { recursive: true }).sort(); + // TOD0 remove this after dev! + var testNames = [ + 'async/', + 'jquery/jquery.d', + 'angularjs/angular.d', + 'pixi/' + ]; + if (process.env.TRAVIS) { + testNames = null; + } + // should be async // only includes .d.ts or -tests.ts or -test.ts or .ts + var filesName = glob.sync('**/*.ts', { cwd: dtPath }); this.files = filesName.filter(function (fileName) { - return fileName.indexOf('../_infrastructure') < 0; + return fileName.indexOf('_infrastructure') < 0; }).filter(function (fileName) { - return fileName.indexOf('../node_modules') < 0; + return fileName.indexOf('node_modules/') < 0; }).filter(function (fileName) { - return !DT.endsWith(fileName, ".tscparams"); - }).map(function (fileName) { + // TOD0 remove this after dev! + return !testNames || testNames.some(function (pattern) { + return fileName.indexOf(pattern) > -1; + }); + }).filter(function (fileName) { + return /^[a-z]/i.test(fileName); + }).sort().map(function (fileName) { return new DT.File(dtPath, fileName); }); } @@ -1097,6 +721,19 @@ var DT; this.timer = new DT.Timer(); this.timer.start(); + var index = new DT.ReferenceIndex(this.options); + index.collectReferences(this.files, function () { + _this.files.forEach(function (file) { + console.log(file.filePathWithName); + file.references.forEach(function (file) { + console.log(' - %s', file.filePathWithName); + }); + }); + _this.runTests(); + }); + }; + TestRunner.prototype.runTests = function () { + var _this = this; var syntaxChecking = new DT.SyntaxChecking(this.options); var testEval = new DT.TestEval(this.options); if (!this.options.findNotRequiredTscparams) { @@ -1213,7 +850,7 @@ var DT; })(); DT.TestRunner = TestRunner; - var dtPath = __dirname + '/../..'; + var dtPath = path.resolve(path.dirname((module).filename), '..', '..'); var findNotRequiredTscparams = process.argv.some(function (arg) { return arg == "--try-without-tscparams"; }); @@ -1223,6 +860,13 @@ var DT; tscVersion = process.argv[tscVersionIndex + 1]; } + console.log('--'); + console.log(' dtPath %s', dtPath); + console.log(' tscVersion %s', tscVersion); + console.log(' findNotRequiredTscparams %s', findNotRequiredTscparams); + console.log('--'); + console.log(''); + var runner = new TestRunner(dtPath, { tscVersion: tscVersion, findNotRequiredTscparams: findNotRequiredTscparams diff --git a/_infrastructure/tests/runner.ts b/_infrastructure/tests/runner.ts index 86a4c2caa..bf0502526 100644 --- a/_infrastructure/tests/runner.ts +++ b/_infrastructure/tests/runner.ts @@ -1,12 +1,12 @@ /// /// -/// /// /// /// /// +/// /// /// @@ -17,8 +17,11 @@ /// module DT { + require('source-map-support'); + var fs = require('fs'); var path = require('path'); + var glob = require('glob'); export var DEFAULT_TSC_VERSION = "0.9.1.1"; @@ -74,18 +77,38 @@ module DT { constructor(dtPath: string, public options: ITestRunnerOptions = {tscVersion: DT.DEFAULT_TSC_VERSION}) { this.options.findNotRequiredTscparams = !!this.options.findNotRequiredTscparams; - var filesName = IO.dir(dtPath, /.\.ts/g, { recursive: true }).sort(); + // TOD0 remove this after dev! + var testNames = [ + 'async/', + 'jquery/jquery.d', + 'angularjs/angular.d', + 'pixi/' + ]; + if (process.env.TRAVIS) { + testNames = null; + } + + // should be async // only includes .d.ts or -tests.ts or -test.ts or .ts + var filesName = glob.sync('**/*.ts', { cwd: dtPath }); this.files = filesName .filter((fileName) => { - return fileName.indexOf('../_infrastructure') < 0; + return fileName.indexOf('_infrastructure') < 0; }) .filter((fileName) => { - return fileName.indexOf('../node_modules') < 0; + return fileName.indexOf('node_modules/') < 0; }) .filter((fileName) => { - return !DT.endsWith(fileName, ".tscparams"); - }).map((fileName) => { + // TOD0 remove this after dev! + return !testNames || testNames.some((pattern) => { + return fileName.indexOf(pattern) > -1; + }); + }) + .filter((fileName) => { + return /^[a-z]/i.test(fileName); + }) + .sort() + .map((fileName) => { return new File(dtPath, fileName); }); } @@ -98,6 +121,19 @@ module DT { this.timer = new Timer(); this.timer.start(); + var index = new ReferenceIndex(this.options); + index.collectReferences(this.files, () => { + this.files.forEach((file) => { + console.log(file.filePathWithName); + file.references.forEach((file) => { + console.log(' - %s', file.filePathWithName); + }); + }); + this.runTests(); + }); + } + public runTests() { + var syntaxChecking = new SyntaxChecking(this.options); var testEval = new TestEval(this.options); if (!this.options.findNotRequiredTscparams) { @@ -221,7 +257,7 @@ module DT { } } - var dtPath = __dirname + '/../..'; + var dtPath = path.resolve(path.dirname((module).filename), '..', '..'); var findNotRequiredTscparams = process.argv.some(arg => arg == "--try-without-tscparams"); var tscVersionIndex = process.argv.indexOf("--tsc-version"); var tscVersion = DEFAULT_TSC_VERSION; @@ -229,6 +265,13 @@ module DT { tscVersion = process.argv[tscVersionIndex + 1]; } + console.log('--'); + console.log(' dtPath %s', dtPath); + console.log(' tscVersion %s', tscVersion); + console.log(' findNotRequiredTscparams %s', findNotRequiredTscparams); + console.log('--'); + console.log(''); + var runner = new TestRunner(dtPath, { tscVersion: tscVersion, findNotRequiredTscparams: findNotRequiredTscparams diff --git a/_infrastructure/tests/src/indexer.ts b/_infrastructure/tests/src/changes.ts similarity index 100% rename from _infrastructure/tests/src/indexer.ts rename to _infrastructure/tests/src/changes.ts diff --git a/_infrastructure/tests/src/file.ts b/_infrastructure/tests/src/file.ts index f349a09da..c1a8d1f51 100644 --- a/_infrastructure/tests/src/file.ts +++ b/_infrastructure/tests/src/file.ts @@ -9,18 +9,25 @@ module DT { dir: string; file: string; ext: string; + references: File[] = []; constructor(public baseDir: string, public filePathWithName: string) { - var dirName = path.dirname(this.filePathWithName.substr(this.baseDir.length + 1)).replace('\\', '/'); - this.dir = dirName.split('/')[0]; - this.file = path.basename(this.filePathWithName, '.ts'); this.ext = path.extname(this.filePathWithName); + this.file = path.basename(this.filePathWithName, this.ext); + this.dir = path.dirname(this.filePathWithName); } // From '/complete/path/to/file' to 'specfolder/specfile.d.ts' public get formatName(): string { - var dirName = path.dirname(this.filePathWithName.substr(this.baseDir.length + 1)).replace('\\', '/'); - return this.dir + ((dirName.split('/').length > 1) ? '/-/' : '/') + this.file + this.ext; + return path.join(this.dir, this.file + this.ext); + } + + public get fullPath(): string { + return path.join(this.baseDir, this.dir, this.file + this.ext); + } + + toString() { + return '[File ' + this.filePathWithName + ']'; } } } diff --git a/_infrastructure/tests/src/host/exec.ts b/_infrastructure/tests/src/host/exec.ts index 2bddb0043..9ff896c3f 100644 --- a/_infrastructure/tests/src/host/exec.ts +++ b/_infrastructure/tests/src/host/exec.ts @@ -24,30 +24,6 @@ class ExecResult { public exitCode: number; } -class WindowsScriptHostExec implements IExec { - public exec(filename: string, cmdLineArgs: string[], handleResult: (ExecResult) => void): void { - var result = new ExecResult(); - var shell = new ActiveXObject('WScript.Shell'); - try { - var process = shell.Exec(filename + ' ' + cmdLineArgs.join(' ')); - } catch (e) { - result.stderr = e.message; - result.exitCode = 1 - handleResult(result); - return; - } - // Wait for it to finish running - while (process.Status != 0) { /* todo: sleep? */ - } - - result.exitCode = process.ExitCode; - if (!process.StdOut.AtEndOfStream) result.stdout = process.StdOut.ReadAll(); - if (!process.StdErr.AtEndOfStream) result.stderr = process.StdErr.ReadAll(); - - handleResult(result); - } -} - class NodeExec implements IExec { public exec(filename: string, cmdLineArgs: string[], handleResult: (ExecResult) => void): void { var nodeExec = require('child_process').exec; @@ -66,10 +42,5 @@ class NodeExec implements IExec { } var Exec: IExec = function (): IExec { - var global = Function("return this;").call(null); - if (typeof global.ActiveXObject !== "undefined") { - return new WindowsScriptHostExec(); - } else { - return new NodeExec(); - } + return new NodeExec(); }(); diff --git a/_infrastructure/tests/src/host/io.ts b/_infrastructure/tests/src/host/io.ts deleted file mode 100644 index b308ef13f..000000000 --- a/_infrastructure/tests/src/host/io.ts +++ /dev/null @@ -1,548 +0,0 @@ -// -// Copyright (c) Microsoft Corporation. All rights reserved. -// -// 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. -// - -interface IResolvedFile { - content: string; - path: string; -} - -interface IFileWatcher { - close(): void; -} - -interface IIO { - readFile(path: string): string; - writeFile(path: string, contents: string): void; - createFile(path: string, useUTF8?: boolean): ITextWriter; - deleteFile(path: string): void; - dir(path: string, re?: RegExp, options?: { recursive?: boolean; deep?: number; - }): string[]; - fileExists(path: string): boolean; - directoryExists(path: string): boolean; - createDirectory(path: string): void; - resolvePath(path: string): string; - dirName(path: string): string; - findFile(rootPath: string, partialFilePath: string): IResolvedFile; - print(str: string): void; - printLine(str: string): void; - arguments: string[]; - stderr: ITextWriter; - stdout: ITextWriter; - watchFile(filename: string, callback: (string) => void): IFileWatcher; - run(source: string, filename: string): void; - getExecutingFilePath(): string; - quit(exitCode?: number); -} - -module IOUtils { - // Creates the directory including its parent if not already present - function createDirectoryStructure(ioHost: IIO, dirName: string) { - if (ioHost.directoryExists(dirName)) { - return; - } - - var parentDirectory = ioHost.dirName(dirName); - if (parentDirectory != "") { - createDirectoryStructure(ioHost, parentDirectory); - } - ioHost.createDirectory(dirName); - } - - // Creates a file including its directory structure if not already present - export function createFileAndFolderStructure(ioHost: IIO, fileName: string, useUTF8?: boolean) { - var path = ioHost.resolvePath(fileName); - var dirName = ioHost.dirName(path); - createDirectoryStructure(ioHost, dirName); - return ioHost.createFile(path, useUTF8); - } - - export function throwIOError(message: string, error: Error) { - var errorMessage = message; - if (error && error.message) { - errorMessage += (" " + error.message); - } - throw new Error(errorMessage); - } -} - -// Declare dependencies needed for all supported hosts -declare class Enumerator { - public atEnd(): boolean; - - public moveNext(); - - public item(): any; - - constructor(o: any); -} - -// Missing in node definitions, but called in code below. -interface NodeProcess { - mainModule: { - filename: string; - } -} - -var IO = (function () { - - // Create an IO object for use inside WindowsScriptHost hosts - // Depends on WSCript and FileSystemObject - function getWindowsScriptHostIO(): IIO { - var fso = new ActiveXObject("Scripting.FileSystemObject"); - var streamObjectPool = []; - - function getStreamObject(): any { - if (streamObjectPool.length > 0) { - return streamObjectPool.pop(); - } else { - return new ActiveXObject("ADODB.Stream"); - } - } - - function releaseStreamObject(obj: any) { - streamObjectPool.push(obj); - } - - var args = []; - for (var i = 0; i < WScript.Arguments.length; i++) { - args[i] = WScript.Arguments.Item(i); - } - - return { - readFile: function (path) { - try { - var streamObj = getStreamObject(); - streamObj.Open(); - streamObj.Type = 2; // Text data - streamObj.Charset = 'x-ansi'; // Assume we are reading ansi text - streamObj.LoadFromFile(path); - var bomChar = streamObj.ReadText(2); // Read the BOM char - streamObj.Position = 0; // Position has to be at 0 before changing the encoding - if ((bomChar.charCodeAt(0) == 0xFE && bomChar.charCodeAt(1) == 0xFF) - || (bomChar.charCodeAt(0) == 0xFF && bomChar.charCodeAt(1) == 0xFE)) { - streamObj.Charset = 'unicode'; - } else if (bomChar.charCodeAt(0) == 0xEF && bomChar.charCodeAt(1) == 0xBB) { - streamObj.Charset = 'utf-8'; - } - - // Read the whole file - var str = streamObj.ReadText(-1 /* read from the current position to EOS */); - streamObj.Close(); - releaseStreamObject(streamObj); - return str; - } - catch (err) { - IOUtils.throwIOError("Error reading file \"" + path + "\".", err); - } - }, - - writeFile: function (path, contents) { - var file = this.createFile(path); - file.Write(contents); - file.Close(); - }, - - fileExists: function (path: string): boolean { - return fso.FileExists(path); - }, - - resolvePath: function (path: string): string { - return fso.GetAbsolutePathName(path); - }, - - dirName: function (path: string): string { - return fso.GetParentFolderName(path); - }, - - findFile: function (rootPath: string, partialFilePath: string): IResolvedFile { - var path = fso.GetAbsolutePathName(rootPath) + "/" + partialFilePath; - - while (true) { - if (fso.FileExists(path)) { - try { - var content = this.readFile(path); - return { content: content, path: path }; - } - catch (err) { - //Tools.CompilerDiagnostics.debugPrint("Could not find " + path + ", trying parent"); - } - } - else { - rootPath = fso.GetParentFolderName(fso.GetAbsolutePathName(rootPath)); - - if (rootPath == "") { - return null; - } - else { - path = fso.BuildPath(rootPath, partialFilePath); - } - } - } - }, - - deleteFile: function (path: string): void { - try { - if (fso.FileExists(path)) { - fso.DeleteFile(path, true); // true: delete read-only files - } - } catch (e) { - IOUtils.throwIOError("Couldn't delete file '" + path + "'.", e); - } - }, - - createFile: function (path, useUTF8?) { - try { - var streamObj = getStreamObject(); - streamObj.Charset = useUTF8 ? 'utf-8' : 'x-ansi'; - streamObj.Open(); - return { - Write: function (str) { - streamObj.WriteText(str, 0); - }, - WriteLine: function (str) { - streamObj.WriteText(str, 1); - }, - Close: function () { - try { - streamObj.SaveToFile(path, 2); - } catch (saveError) { - IOUtils.throwIOError("Couldn't write to file '" + path + "'.", saveError); - } - finally { - if (streamObj.State != 0 /*adStateClosed*/) { - streamObj.Close(); - } - releaseStreamObject(streamObj); - } - } - }; - } catch (creationError) { - IOUtils.throwIOError("Couldn't write to file '" + path + "'.", creationError); - } - }, - - directoryExists: function (path) { - return fso.FolderExists(path); - }, - - createDirectory: function (path) { - try { - if (!this.directoryExists(path)) { - fso.CreateFolder(path); - } - } catch (e) { - IOUtils.throwIOError("Couldn't create directory '" + path + "'.", e); - } - }, - - dir: function (path, spec?, options?) { - options = options || <{ recursive?: boolean; deep?: number; - }>{}; - function filesInFolder(folder, root): string[] { - var paths = []; - var fc: Enumerator; - - if (options.recursive) { - fc = new Enumerator(folder.subfolders); - - for (; !fc.atEnd(); fc.moveNext()) { - paths = paths.concat(filesInFolder(fc.item(), root + "/" + fc.item().Name)); - } - } - - fc = new Enumerator(folder.files); - - for (; !fc.atEnd(); fc.moveNext()) { - if (!spec || fc.item().Name.match(spec)) { - paths.push(root + "/" + fc.item().Name); - } - } - - return paths; - } - - var folder = fso.GetFolder(path); - var paths = []; - - return filesInFolder(folder, path); - }, - - print: function (str) { - WScript.StdOut.Write(str); - }, - - printLine: function (str) { - WScript.Echo(str); - }, - - arguments: args, - stderr: WScript.StdErr, - stdout: WScript.StdOut, - watchFile: null, - run: function (source, filename) { - try { - eval(source); - } catch (e) { - IOUtils.throwIOError("Error while executing file '" + filename + "'.", e); - } - }, - getExecutingFilePath: function () { - return WScript.ScriptFullName; - }, - quit: function (exitCode: number = 0) { - try { - WScript.Quit(exitCode); - } catch (e) { - } - } - } - - }; - - // Create an IO object for use inside Node.js hosts - // Depends on 'fs' and 'path' modules - function getNodeIO(): IIO { - - var _fs = require('fs'); - var _path = require('path'); - var _module = require('module'); - - return { - readFile: function (file) { - try { - var buffer = _fs.readFileSync(file); - switch (buffer[0]) { - case 0xFE: - if (buffer[1] == 0xFF) { - // utf16-be. Reading the buffer as big endian is not supported, so convert it to - // Little Endian first - var i = 0; - while ((i + 1) < buffer.length) { - var temp = buffer[i] - buffer[i] = buffer[i + 1]; - buffer[i + 1] = temp; - i += 2; - } - return buffer.toString("ucs2", 2); - } - break; - case 0xFF: - if (buffer[1] == 0xFE) { - // utf16-le - return buffer.toString("ucs2", 2); - } - break; - case 0xEF: - if (buffer[1] == 0xBB) { - // utf-8 - return buffer.toString("utf8", 3); - } - } - // Default behaviour - return buffer.toString(); - } catch (e) { - IOUtils.throwIOError("Error reading file \"" + file + "\".", e); - } - }, - writeFile: <(path: string, contents: string) => void >_fs.writeFileSync, - deleteFile: function (path) { - try { - _fs.unlinkSync(path); - } catch (e) { - IOUtils.throwIOError("Couldn't delete file '" + path + "'.", e); - } - }, - fileExists: function (path): boolean { - return _fs.existsSync(path); - }, - createFile: function (path, useUTF8?) { - function mkdirRecursiveSync(path) { - var stats = _fs.statSync(path); - if (stats.isFile()) { - IOUtils.throwIOError("\"" + path + "\" exists but isn't a directory.", null); - } else if (stats.isDirectory()) { - return; - } else { - mkdirRecursiveSync(_path.dirname(path)); - _fs.mkdirSync(path, parseInt('0775', 8)); - } - } - - mkdirRecursiveSync(_path.dirname(path)); - - try { - var fd = _fs.openSync(path, 'w'); - } catch (e) { - IOUtils.throwIOError("Couldn't write to file '" + path + "'.", e); - } - return { - Write: function (str) { - _fs.writeSync(fd, str); - }, - WriteLine: function (str) { - _fs.writeSync(fd, str + '\r\n'); - }, - Close: function () { - _fs.closeSync(fd); - fd = null; - } - }; - }, - dir: function dir(path, spec?, options?) { - options = options || <{ recursive?: boolean; deep?: number; - }>{}; - - function filesInFolder(folder: string, deep?: number): string[] { - var paths = []; - - var files = _fs.readdirSync(folder); - for (var i = 0; i < files.length; i++) { - var stat = _fs.statSync(folder + "/" + files[i]); - if (options.recursive && stat.isDirectory()) { - if (deep < (options.deep || 100)) { - paths = paths.concat(filesInFolder(folder + "/" + files[i], 1)); - } - } else if (stat.isFile() && (!spec || files[i].match(spec))) { - paths.push(folder + "/" + files[i]); - } - } - - return paths; - } - - return filesInFolder(path, 0); - }, - createDirectory: function (path: string): void { - try { - if (!this.directoryExists(path)) { - _fs.mkdirSync(path); - } - } catch (e) { - IOUtils.throwIOError("Couldn't create directory '" + path + "'.", e); - } - }, - - directoryExists: function (path: string): boolean { - return _fs.existsSync(path) && _fs.lstatSync(path).isDirectory(); - }, - resolvePath: function (path: string): string { - return _path.resolve(path); - }, - dirName: function (path: string): string { - return _path.dirname(path); - }, - findFile: function (rootPath: string, partialFilePath): IResolvedFile { - var path = rootPath + "/" + partialFilePath; - - while (true) { - if (_fs.existsSync(path)) { - try { - var content = this.readFile(path); - return { content: content, path: path }; - } catch (err) { - //Tools.CompilerDiagnostics.debugPrint(("Could not find " + path) + ", trying parent"); - } - } - else { - var parentPath = _path.resolve(rootPath, ".."); - - // Node will just continue to repeat the root path, rather than return null - if (rootPath === parentPath) { - return null; - } - else { - rootPath = parentPath; - path = _path.resolve(rootPath, partialFilePath); - } - } - } - }, - print: function (str) { - process.stdout.write(str) - }, - printLine: function (str) { - process.stdout.write(str + '\n') - }, - arguments: process.argv.slice(2), - stderr: { - Write: function (str) { - process.stderr.write(str); - }, - WriteLine: function (str) { - process.stderr.write(str + '\n'); - }, - Close: function () { - } - }, - stdout: { - Write: function (str) { - process.stdout.write(str); - }, - WriteLine: function (str) { - process.stdout.write(str + '\n'); - }, - Close: function () { - } - }, - watchFile: function (filename: string, callback: (string) => void): IFileWatcher { - var firstRun = true; - var processingChange = false; - - var fileChanged: any = function (curr, prev) { - if (!firstRun) { - if (curr.mtime < prev.mtime) { - return; - } - - _fs.unwatchFile(filename, fileChanged); - if (!processingChange) { - processingChange = true; - callback(filename); - setTimeout(function () { - processingChange = false; - }, 100); - } - } - firstRun = false; - _fs.watchFile(filename, { persistent: true, interval: 500 }, fileChanged); - }; - - fileChanged(); - return { - filename: filename, - close: function () { - _fs.unwatchFile(filename, fileChanged); - } - }; - }, - run: function (source, filename) { - require.main.filename = filename; - require.main.paths = _module._nodeModulePaths(_path.dirname(_fs.realpathSync(filename))); - require.main._compile(source, filename); - }, - getExecutingFilePath: function () { - return process.mainModule.filename; - }, - quit: process.exit - } - }; - - if (typeof ActiveXObject === "function") - return getWindowsScriptHostIO(); - else if (typeof require === "function") - return getNodeIO(); - else - return null; // Unsupported host -})(); diff --git a/_infrastructure/tests/src/references.ts b/_infrastructure/tests/src/references.ts new file mode 100644 index 000000000..c98f947c3 --- /dev/null +++ b/_infrastructure/tests/src/references.ts @@ -0,0 +1,80 @@ +/// +/// + +/// + +module DT { + var fs = require('fs'); + var path = require('path'); + + export class ReferenceIndex { + + fileMap: {[path:string]:File}; + + constructor(public options: ITestRunnerOptions) { + + } + + collectReferences(files: File[], callback: () => void): void { + this.fileMap = Object.create(null); + files.forEach((file) => { + this.fileMap[file.fullPath] = file; + }); + this.loadReferences(files, () => { + callback(); + }); + } + + private loadReferences(files: File[], callback: () => void): void { + var queue = files.slice(0); + var active = []; + var max = 50; + var next = () => { + if (queue.length === 0 && active.length === 0) { + callback(); + return; + } + // queue paralel + while (queue.length > 0 && active.length < max) { + var file = queue.pop(); + active.push(file); + this.parseFile(file, (file) => { + active.splice(active.indexOf(file), 1); + next(); + }); + } + }; + process.nextTick(next); + } + + private parseFile(file: File, callback: (file: File) => void): void { + fs.readFile(file.filePathWithName, { + encoding: 'utf8', + flag: 'r' + }, (err, content) => { + if (err) { + // just blow up? + throw err; + } + // console.log('----'); + // console.log(file.filePathWithName); + + file.references = extractReferenceTags(content).map((ref: string) => { + return path.resolve(path.dirname(file.fullPath), ref); + }).reduce((memo: File[], ref: string) => { + if (ref in this.fileMap) { + memo.push(this.fileMap[ref]); + } + else { + console.log('not mapped? -> ' + ref); + } + return memo; + }, []); + + // console.log(file.references); + + callback(file); + }); + } + } +} diff --git a/_infrastructure/tests/src/suite/tscParams.ts b/_infrastructure/tests/src/suite/tscParams.ts index 65491d30d..510e15ce7 100644 --- a/_infrastructure/tests/src/suite/tscParams.ts +++ b/_infrastructure/tests/src/suite/tscParams.ts @@ -2,6 +2,8 @@ /// module DT { + var fs = require('fs'); + ///////////////////////////////// // Try compile without .tscparams // It may indicate that it is compatible with --noImplicitAny maybe... @@ -25,12 +27,18 @@ module DT { } public filterTargetFiles(files: File[]): File[] { - return files.filter(file=> IO.fileExists(file.filePathWithName + '.tscparams')); + return files.filter((file) => { + return fs.existsSync(file.filePathWithName + '.tscparams'); + }); } public runTest(targetFile: File, callback: (result: TestResult) => void): void { this.print.clearCurrentLine().out(targetFile.formatName); - new Test(this, targetFile, {tscVersion: this.options.tscVersion, useTscParams: false, checkNoImplicitAny: true}).run(result=> { + new Test(this, targetFile, { + tscVersion: this.options.tscVersion, + useTscParams: false, + checkNoImplicitAny: true + }).run(result=> { this.testResults.push(result); callback(result); }); diff --git a/_infrastructure/tests/src/timer.ts b/_infrastructure/tests/src/timer.ts index a92d08faf..e03a94166 100644 --- a/_infrastructure/tests/src/timer.ts +++ b/_infrastructure/tests/src/timer.ts @@ -26,13 +26,14 @@ module DT { } public static prettyDate(date1: number, date2: number): string { - var diff = ((date2 - date1) / 1000), - day_diff = Math.floor(diff / 86400); + var diff = ((date2 - date1) / 1000); + var day_diff = Math.floor(diff / 86400); - if (isNaN(day_diff) || day_diff < 0 || day_diff >= 31) - return; + if (isNaN(day_diff) || day_diff < 0 || day_diff >= 31) { + return null; + } - return (day_diff == 0 && ( + return ( (day_diff == 0 && ( diff < 60 && (diff + " seconds") || diff < 120 && "1 minute" || diff < 3600 && Math.floor(diff / 60) + " minutes" || @@ -40,7 +41,7 @@ module DT { diff < 86400 && Math.floor(diff / 3600) + " hours") || day_diff == 1 && "Yesterday" || day_diff < 7 && day_diff + " days" || - day_diff < 31 && Math.ceil(day_diff / 7) + " weeks"); + day_diff < 31 && Math.ceil(day_diff / 7) + " weeks")); } } } diff --git a/_infrastructure/tests/src/tsc.ts b/_infrastructure/tests/src/tsc.ts index 708f42a91..5a2c803c8 100644 --- a/_infrastructure/tests/src/tsc.ts +++ b/_infrastructure/tests/src/tsc.ts @@ -4,6 +4,8 @@ /// module DT { + var fs = require('fs'); + export interface TscExecOptions { tscVersion?:string; useTscParams?:boolean; @@ -21,16 +23,16 @@ module DT { options.useTscParams = true; } - if (!IO.fileExists(tsfile)) { + if (!fs.existsSync(tsfile)) { throw new Error(tsfile + " not exists"); } var tscPath = './_infrastructure/tests/typescript/' + options.tscVersion + '/tsc.js'; - if (!IO.fileExists(tscPath)) { + if (!fs.existsSync(tscPath)) { throw new Error(tscPath + ' is not exists'); } var command = 'node ' + tscPath + ' --module commonjs '; - if (options.useTscParams && IO.fileExists(tsfile + '.tscparams')) { + if (options.useTscParams && fs.existsSync(tsfile + '.tscparams')) { command += '@' + tsfile + '.tscparams'; } else if (options.checkNoImplicitAny) { command += '--noImplicitAny'; diff --git a/_infrastructure/tests/src/util.ts b/_infrastructure/tests/src/util.ts index d907fe49d..3b441991f 100644 --- a/_infrastructure/tests/src/util.ts +++ b/_infrastructure/tests/src/util.ts @@ -1,5 +1,25 @@ module DT { + + var referenceTagExp = //g; + export function endsWith(str: string, suffix: string) { return str.indexOf(suffix, str.length - suffix.length) !== -1; } + + export function extractReferenceTags(source: string): string[] { + var ret: string[] = []; + var match: RegExpExecArray; + + if (!referenceTagExp.global) { + throw new Error('referenceTagExp RegExp must have global flag'); + } + referenceTagExp.lastIndex = 0; + + while ((match = referenceTagExp.exec(source))) { + if (match.length > 0 && match[1].length > 0) { + ret.push(match[1]); + } + } + return ret; + } }