Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,5 @@ tests/*.d.ts
scripts/debug.bat
scripts/run.bat
scripts/word2md.js
scripts/ior.js
coverage/
123 changes: 123 additions & 0 deletions scripts/ior.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
/// <reference path="../src/harness/external/node.d.ts" />

import fs = require('fs');
import path = require('path');

interface IOLog {
filesRead: {
path: string;
result: { contents: string; };
}[];
arguments: string[];
}

module Commands {
export function dir(obj: IOLog) {
obj.filesRead.filter(f => f.result !== undefined).forEach(f => {
console.log(f.path);
});
}
dir['description'] = ': displays a list of files';

export function find(obj: IOLog, str: string) {
obj.filesRead.filter(f => f.result !== undefined).forEach(f => {
var lines = f.result.contents.split('\n');
var printedHeader = false;
lines.forEach(line => {
if (line.indexOf(str) >= 0) {
if (!printedHeader) {
console.log(' === ' + f.path + ' ===');
printedHeader = true;
}
console.log(line);
}
});
});
}
find['description'] = ' string: finds text in files';

export function grab(obj: IOLog, filename: string) {
obj.filesRead.filter(f => f.result !== undefined).forEach(f => {
if (path.basename(f.path) === filename) {
fs.writeFile(filename, f.result.contents);
}
});
}
grab['description'] = ' filename.ts: writes out the specified file to disk';

export function extract(obj: IOLog, outputFolder: string) {
var directorySeparator = "/";
function directoryExists(path: string): boolean {
return fs.existsSync(path) && fs.statSync(path).isDirectory();
}
function getDirectoryPath(path: string) {
return path.substr(0, Math.max(getRootLength(path), path.lastIndexOf(directorySeparator)));
}
function getRootLength(path: string): number {
if (path.charAt(0) === directorySeparator) {
if (path.charAt(1) !== directorySeparator) return 1;
var p1 = path.indexOf(directorySeparator, 2);
if (p1 < 0) return 2;
var p2 = path.indexOf(directorySeparator, p1 + 1);
if (p2 < 0) return p1 + 1;
return p2 + 1;
}
if (path.charAt(1) === ":") {
if (path.charAt(2) === directorySeparator) return 3;
return 2;
}
return 0;
}
function ensureDirectoriesExist(directoryPath: string) {
if (directoryPath.length > getRootLength(directoryPath) && !directoryExists(directoryPath)) {
var parentDirectory = getDirectoryPath(directoryPath);
ensureDirectoriesExist(parentDirectory);
console.log("creating directory: " + directoryPath);
fs.mkdirSync(directoryPath);
}
}
function transalatePath(outputFolder:string, path: string): string {
return outputFolder + directorySeparator + path.replace(":", "");
}
function fileExists(path: string): boolean {
return fs.existsSync(path);
}
obj.filesRead.forEach(f => {
var filename = transalatePath(outputFolder, f.path);
ensureDirectoriesExist(getDirectoryPath(filename));
console.log("writing filename: " + filename);
fs.writeFile(filename, f.result.contents, (err) => { });
});

console.log("Command: tsc ");
obj.arguments.forEach(a => {
if (getRootLength(a) > 0) {
console.log(transalatePath(outputFolder, a));
}
else {
console.log(a);
}
console.log(" ");
});
}
extract['description'] = ' outputFolder: extract all input files to <outputFolder>';
}

var args = process.argv.slice(2);
if (args.length < 2) {
console.log('Usage: node ior.js path_to_file.json [command]');
console.log('List of commands: ');
Object.keys(Commands).forEach(k => console.log(' ' + k + Commands[k]['description']));
} else {
var cmd: Function = Commands[args[1]];
if (cmd === undefined) {
console.log('Unknown command ' + args[1]);
} else {
fs.readFile(args[0], 'utf-8', (err, data) => {
if (err) throw err;
var json = JSON.parse(data);
cmd.apply(undefined, [json].concat(args.slice(2)));
});
}
}

69 changes: 13 additions & 56 deletions src/harness/compilerRunner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,11 @@ class CompilerBaselineRunner extends RunnerBase {
var otherFiles: { unitName: string; content: string }[];
var harnessCompiler: Harness.Compiler.HarnessCompiler;

var declToBeCompiled: { unitName: string; content: string }[] = [];
var declOtherFiles: { unitName: string; content: string }[] = [];
var declResult: Harness.Compiler.CompilerResult;
var declFileCompilationResult: {
declInputFiles: { unitName: string; content: string }[];
declOtherFiles: { unitName: string; content: string }[];
declResult: Harness.Compiler.CompilerResult;
};

var createNewInstance = false;

Expand Down Expand Up @@ -147,9 +149,7 @@ class CompilerBaselineRunner extends RunnerBase {
toBeCompiled = undefined;
otherFiles = undefined;
harnessCompiler = undefined;
declToBeCompiled = undefined;
declOtherFiles = undefined;
declResult = undefined;
declFileCompilationResult = undefined;
});

function getByteOrderMarkText(file: Harness.Compiler.GeneratedFile): string {
Expand All @@ -173,61 +173,18 @@ class CompilerBaselineRunner extends RunnerBase {

// Source maps?
it('Correct sourcemap content for ' + fileName, () => {
if (result.sourceMapRecord) {
if (options.sourceMap) {
Harness.Baseline.runBaseline('Correct sourcemap content for ' + fileName, justName.replace(/\.ts$/, '.sourcemap.txt'), () => {
return result.sourceMapRecord;
return result.getSourceMapRecord();
});
}
});

// Compile .d.ts files
it('Correct compiler generated.d.ts for ' + fileName, () => {
if (options.declaration && result.errors.length === 0 && result.declFilesCode.length !== result.files.length) {
throw new Error('There were no errors and declFiles generated did not match number of js files generated');
}

// if the .d.ts is non-empty, confirm it compiles correctly as well
if (options.declaration && result.errors.length === 0 && result.declFilesCode.length > 0) {
function addDtsFile(file: { unitName: string; content: string }, dtsFiles: { unitName: string; content: string }[]) {
if (Harness.Compiler.isDTS(file.unitName)) {
dtsFiles.push(file);
}
else {
var declFile = findResultCodeFile(file.unitName);
// Look if there is --out file corresponding to this ts file
if (!declFile && options.out) {
declFile = findResultCodeFile(options.out);
if (!declFile || findUnit(declFile.fileName, declToBeCompiled) ||
findUnit(declFile.fileName, declOtherFiles)) {
return;
}
}

if (declFile) {
dtsFiles.push({ unitName: declFile.fileName, content: declFile.code });
return;
}
}

function findResultCodeFile(fileName: string) {
return ts.forEach(result.declFilesCode,
declFile => declFile.fileName === (fileName.substr(0, fileName.length - ".ts".length) + ".d.ts")
? declFile : undefined);
}

function findUnit(fileName: string, units: { unitName: string; content: string }[]) {
return ts.forEach(units, unit => unit.unitName === fileName ? unit : undefined);
}
}

ts.forEach(toBeCompiled, file => addDtsFile(file, declToBeCompiled));
ts.forEach(otherFiles, file => addDtsFile(file, declOtherFiles));
harnessCompiler.compileFiles(declToBeCompiled, declOtherFiles, function (compileResult) {
declResult = compileResult;
}, function (settings) {
harnessCompiler.setCompilerSettings(tcSettings);
});
}
declFileCompilationResult = harnessCompiler.compileDeclarationFiles(toBeCompiled, otherFiles, result, function (settings) {
harnessCompiler.setCompilerSettings(tcSettings);
}, options);
});


Expand Down Expand Up @@ -267,10 +224,10 @@ class CompilerBaselineRunner extends RunnerBase {
}
}

if (declResult && declResult.errors.length) {
if (declFileCompilationResult && declFileCompilationResult.declResult.errors.length) {
jsCode += '\r\n\r\n//// [DtsFileErrors]\r\n';
jsCode += '\r\n\r\n';
jsCode += getErrorBaseline(declToBeCompiled, declOtherFiles, declResult);
jsCode += getErrorBaseline(declFileCompilationResult.declInputFiles, declFileCompilationResult.declOtherFiles, declFileCompilationResult.declResult);
}

if (jsCode.length > 0) {
Expand Down
99 changes: 86 additions & 13 deletions src/harness/harness.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ module Harness {
deleteFile(filename: string): void;
listFiles(path: string, filter: RegExp, options?: { recursive?: boolean }): string[];
log(text: string): void;
getMemoryUsage? (): number;
}

module IOImpl {
Expand Down Expand Up @@ -275,6 +276,13 @@ module Harness {

return filesInFolder(path);
}

export var getMemoryUsage: typeof IO.getMemoryUsage = () => {
if (global.gc) {
global.gc();
}
return process.memoryUsage().heapUsed;
}
}

export module Network {
Expand Down Expand Up @@ -804,15 +812,81 @@ module Harness {
});
this.lastErrors = errors;

var result = new CompilerResult(fileOutputs, errors, []);
// Covert the source Map data into the baseline
result.updateSourceMapRecord(program, emitResult ? emitResult.sourceMaps : undefined);
var result = new CompilerResult(fileOutputs, errors, program, sys.getCurrentDirectory(), emitResult ? emitResult.sourceMaps : undefined);
onComplete(result, checker);

// reset what newline means in case the last test changed it
sys.newLine = '\r\n';
return options;
}

public compileDeclarationFiles(inputFiles: { unitName: string; content: string; }[],
otherFiles: { unitName: string; content: string; }[],
result: CompilerResult,
settingsCallback?: (settings: ts.CompilerOptions) => void,
options?: ts.CompilerOptions) {
if (options.declaration && result.errors.length === 0 && result.declFilesCode.length !== result.files.length) {
throw new Error('There were no errors and declFiles generated did not match number of js files generated');
}

// if the .d.ts is non-empty, confirm it compiles correctly as well
if (options.declaration && result.errors.length === 0 && result.declFilesCode.length > 0) {
var declInputFiles: { unitName: string; content: string }[] = [];
var declOtherFiles: { unitName: string; content: string }[] = [];
var declResult: Harness.Compiler.CompilerResult;

ts.forEach(inputFiles, file => addDtsFile(file, declInputFiles));
ts.forEach(otherFiles, file => addDtsFile(file, declOtherFiles));
this.compileFiles(declInputFiles, declOtherFiles, function (compileResult) {
declResult = compileResult;
}, settingsCallback, options);

return { declInputFiles: declInputFiles, declOtherFiles: declOtherFiles, declResult: declResult };
}

function addDtsFile(file: { unitName: string; content: string }, dtsFiles: { unitName: string; content: string }[]) {
if (isDTS(file.unitName)) {
dtsFiles.push(file);
}
else if (isTS(file.unitName)) {
var declFile = findResultCodeFile(file.unitName);
if (!findUnit(declFile.fileName, declInputFiles) && !findUnit(declFile.fileName, declOtherFiles)) {
dtsFiles.push({ unitName: declFile.fileName, content: declFile.code });
}
}

function findResultCodeFile(fileName: string) {
var dTsFileName = ts.forEach(result.program.getSourceFiles(), sourceFile => {
if (sourceFile.filename === fileName) {
// Is this file going to be emitted separately
var sourceFileName: string;
if (ts.isExternalModule(sourceFile) || !options.out) {
if (options.outDir) {
var sourceFilePath = ts.getNormalizedPathFromPathComponents(ts.getNormalizedPathComponents(sourceFile.filename, result.currentDirectoryForProgram));
sourceFilePath = sourceFilePath.replace(result.program.getCommonSourceDirectory(), "");
sourceFileName = ts.combinePaths(options.outDir, sourceFilePath);
}
else {
sourceFileName = sourceFile.filename;
}
}
else {
// Goes to single --out file
sourceFileName = options.out;
}

return ts.removeFileExtension(sourceFileName) + ".d.ts";
}
});

return ts.forEach(result.declFilesCode, declFile => declFile.fileName === dTsFileName ? declFile : undefined);
}

function findUnit(fileName: string, units: { unitName: string; content: string; }[]) {
return ts.forEach(units, unit => unit.unitName === fileName ? unit : undefined);
}
}
}
}

export function getMinimalDiagnostic(err: ts.Diagnostic): HarnessDiagnostic {
Expand Down Expand Up @@ -948,10 +1022,6 @@ module Harness {
}
*/

/** Recreate the harness compiler instance to its default settings */
export function recreate(options?: { useMinimalDefaultLib: boolean; noImplicitAny: boolean; }) {
}

/** The harness' compiler instance used when tests are actually run. Reseting or changing settings of this compiler instance must be done within a test case (i.e., describe/it) */
var harnessCompiler: HarnessCompiler;

Expand Down Expand Up @@ -991,6 +1061,10 @@ module Harness {
return str.substr(str.length - end.length) === end;
}

export function isTS(fileName: string) {
return stringEndsWith(fileName, '.ts');
}

export function isDTS(fileName: string) {
return stringEndsWith(fileName, '.d.ts');
}
Expand All @@ -1009,10 +1083,10 @@ module Harness {
public errors: HarnessDiagnostic[] = [];
public declFilesCode: GeneratedFile[] = [];
public sourceMaps: GeneratedFile[] = [];
public sourceMapRecord: string;

/** @param fileResults an array of strings for the fileName and an ITextWriter with its code */
constructor(fileResults: GeneratedFile[], errors: HarnessDiagnostic[], sourceMapRecordLines: string[]) {
constructor(fileResults: GeneratedFile[], errors: HarnessDiagnostic[], public program: ts.Program,
public currentDirectoryForProgram: string, private sourceMapData: ts.SourceMapData[]) {
var lines: string[] = [];

fileResults.forEach(emittedFile => {
Expand All @@ -1030,12 +1104,11 @@ module Harness {
});

this.errors = errors;
this.sourceMapRecord = sourceMapRecordLines.join('\r\n');
}

public updateSourceMapRecord(program: ts.Program, sourceMapData: ts.SourceMapData[]) {
if (sourceMapData) {
this.sourceMapRecord = Harness.SourceMapRecoder.getSourceMapRecord(sourceMapData, program, this.files);
public getSourceMapRecord() {
if (this.sourceMapData) {
return Harness.SourceMapRecoder.getSourceMapRecord(this.sourceMapData, this.program, this.files);
}
}

Expand Down
Loading