merge with master

This commit is contained in:
Vladimir Matveev
2015-09-16 12:50:07 -07:00
91 changed files with 3348 additions and 1634 deletions
+4 -1
View File
@@ -14246,7 +14246,10 @@ namespace ts {
let symbols: Symbol[] = [];
let name = symbol.name;
forEach(getSymbolLinks(symbol).containingType.types, t => {
symbols.push(getPropertyOfType(t, name));
let symbol = getPropertyOfType(t, name);
if (symbol) {
symbols.push(symbol);
}
});
return symbols;
}
+4 -3
View File
@@ -243,7 +243,8 @@ namespace ts {
"node": ModuleResolutionKind.NodeJs,
"classic": ModuleResolutionKind.Classic
},
description: Diagnostics.Specifies_module_resolution_strategy_Colon_node_Node_or_classic_TypeScript_pre_1_6
description: Diagnostics.Specifies_module_resolution_strategy_Colon_node_Node_js_or_classic_TypeScript_pre_1_6,
error: Diagnostics.Argument_for_moduleResolution_option_must_be_node_or_classic,
},
{
name: "noUnusedLabels",
@@ -347,7 +348,7 @@ namespace ts {
options[opt.name] = map[key];
}
else {
errors.push(createCompilerDiagnostic(opt.error));
errors.push(createCompilerDiagnostic((<CommandLineOptionOfCustomType>opt).error));
}
}
}
@@ -460,7 +461,7 @@ namespace ts {
value = optType[key];
}
else {
errors.push(createCompilerDiagnostic(opt.error));
errors.push(createCompilerDiagnostic((<CommandLineOptionOfCustomType>opt).error));
value = 0;
}
}
@@ -565,13 +565,14 @@ namespace ts {
Specifies_the_end_of_line_sequence_to_be_used_when_emitting_files_Colon_CRLF_dos_or_LF_unix: { code: 6060, category: DiagnosticCategory.Message, key: "Specifies the end of line sequence to be used when emitting files: 'CRLF' (dos) or 'LF' (unix)." },
NEWLINE: { code: 6061, category: DiagnosticCategory.Message, key: "NEWLINE" },
Argument_for_newLine_option_must_be_CRLF_or_LF: { code: 6062, category: DiagnosticCategory.Error, key: "Argument for '--newLine' option must be 'CRLF' or 'LF'." },
Argument_for_moduleResolution_option_must_be_node_or_classic: { code: 6063, category: DiagnosticCategory.Error, key: "Argument for '--moduleResolution' option must be 'node' or 'classic'." },
Specify_JSX_code_generation_Colon_preserve_or_react: { code: 6080, category: DiagnosticCategory.Message, key: "Specify JSX code generation: 'preserve' or 'react'" },
Argument_for_jsx_must_be_preserve_or_react: { code: 6081, category: DiagnosticCategory.Message, key: "Argument for '--jsx' must be 'preserve' or 'react'." },
Enables_experimental_support_for_ES7_decorators: { code: 6065, category: DiagnosticCategory.Message, key: "Enables experimental support for ES7 decorators." },
Enables_experimental_support_for_emitting_type_metadata_for_decorators: { code: 6066, category: DiagnosticCategory.Message, key: "Enables experimental support for emitting type metadata for decorators." },
Option_experimentalAsyncFunctions_cannot_be_specified_when_targeting_ES5_or_lower: { code: 6067, category: DiagnosticCategory.Message, key: "Option 'experimentalAsyncFunctions' cannot be specified when targeting ES5 or lower." },
Enables_experimental_support_for_ES7_async_functions: { code: 6068, category: DiagnosticCategory.Message, key: "Enables experimental support for ES7 async functions." },
Specifies_module_resolution_strategy_Colon_node_Node_or_classic_TypeScript_pre_1_6: { code: 6069, category: DiagnosticCategory.Message, key: "Specifies module resolution strategy: 'node' (Node) or 'classic' (TypeScript pre 1.6) ." },
Specifies_module_resolution_strategy_Colon_node_Node_js_or_classic_TypeScript_pre_1_6: { code: 6069, category: DiagnosticCategory.Message, key: "Specifies module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6)." },
Initializes_a_TypeScript_project_and_creates_a_tsconfig_json_file: { code: 6070, category: DiagnosticCategory.Message, key: "Initializes a TypeScript project and creates a tsconfig.json file." },
Successfully_created_a_tsconfig_json_file: { code: 6071, category: DiagnosticCategory.Message, key: "Successfully created a tsconfig.json file." },
Suppress_excess_property_checks_for_object_literals: { code: 6072, category: DiagnosticCategory.Message, key: "Suppress excess property checks for object literals." },
+10 -5
View File
@@ -1700,11 +1700,11 @@
"Merged declaration '{0}' cannot include a default export declaration. Consider adding a separate 'export default {0}' declaration instead.": {
"category": "Error",
"code": 2652
},
},
"Non-abstract class expression does not implement inherited abstract member '{0}' from class '{1}'.": {
"category": "Error",
"code": 2653
},
},
"Exported external package typings file cannot contain tripleslash references. Please contact the package author to update the package definition.": {
"category": "Error",
"code": 2654
@@ -1712,11 +1712,11 @@
"Exported external package typings can only be in '.d.ts' files. Please contact the package author to update the package definition.": {
"category": "Error",
"code": 2655
},
},
"Exported external package typings file '{0}' is not a module. Please contact the package author to update the package definition.": {
"category": "Error",
"code": 2656
},
},
"Import declaration '{0}' is using private name '{1}'.": {
"category": "Error",
"code": 4000
@@ -2250,6 +2250,11 @@
"category": "Error",
"code": 6062
},
"Argument for '--moduleResolution' option must be 'node' or 'classic'.": {
"category": "Error",
"code": 6063
},
"Specify JSX code generation: 'preserve' or 'react'": {
"category": "Message",
"code": 6080
@@ -2274,7 +2279,7 @@
"category": "Message",
"code": 6068
},
"Specifies module resolution strategy: 'node' (Node) or 'classic' (TypeScript pre 1.6) .": {
"Specifies module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6).": {
"category": "Message",
"code": 6069
},
+37 -22
View File
@@ -3220,22 +3220,32 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
}
}
function ensureIdentifier(expr: Expression): Expression {
if (expr.kind !== SyntaxKind.Identifier) {
let identifier = createTempVariable(TempFlags.Auto);
if (!canDefineTempVariablesInPlace) {
recordTempDeclaration(identifier);
}
emitAssignment(identifier, expr);
expr = identifier;
/**
* Ensures that there exists a declared identifier whose value holds the given expression.
* This function is useful to ensure that the expression's value can be read from in subsequent expressions.
* Unless 'reuseIdentifierExpressions' is false, 'expr' will be returned if it is just an identifier.
*
* @param expr the expression whose value needs to be bound.
* @param reuseIdentifierExpressions true if identifier expressions can simply be returned;
* false if it is necessary to always emit an identifier.
*/
function ensureIdentifier(expr: Expression, reuseIdentifierExpressions: boolean): Expression {
if (expr.kind === SyntaxKind.Identifier && reuseIdentifierExpressions) {
return expr;
}
return expr;
let identifier = createTempVariable(TempFlags.Auto);
if (!canDefineTempVariablesInPlace) {
recordTempDeclaration(identifier);
}
emitAssignment(identifier, expr);
return identifier;
}
function createDefaultValueCheck(value: Expression, defaultValue: Expression): Expression {
// The value expression will be evaluated twice, so for anything but a simple identifier
// we need to generate a temporary variable
value = ensureIdentifier(value);
value = ensureIdentifier(value, /*reuseIdentifierExpressions*/ true);
// Return the expression 'value === void 0 ? defaultValue : value'
let equals = <BinaryExpression>createSynthesizedNode(SyntaxKind.BinaryExpression);
equals.left = value;
@@ -3286,7 +3296,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
if (properties.length !== 1) {
// For anything but a single element destructuring we need to generate a temporary
// to ensure value is evaluated exactly once.
value = ensureIdentifier(value);
value = ensureIdentifier(value, /*reuseIdentifierExpressions*/ true);
}
for (let p of properties) {
if (p.kind === SyntaxKind.PropertyAssignment || p.kind === SyntaxKind.ShorthandPropertyAssignment) {
@@ -3301,7 +3311,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
if (elements.length !== 1) {
// For anything but a single element destructuring we need to generate a temporary
// to ensure value is evaluated exactly once.
value = ensureIdentifier(value);
value = ensureIdentifier(value, /*reuseIdentifierExpressions*/ true);
}
for (let i = 0; i < elements.length; i++) {
let e = elements[i];
@@ -3346,7 +3356,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
if (root.parent.kind !== SyntaxKind.ParenthesizedExpression) {
write("(");
}
value = ensureIdentifier(value);
value = ensureIdentifier(value, /*reuseIdentifierExpressions*/ true);
emitDestructuringAssignment(target, value);
write(", ");
emit(value);
@@ -3356,7 +3366,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
}
}
function emitBindingElement(target: BindingElement, value: Expression) {
function emitBindingElement(target: BindingElement | VariableDeclaration, value: Expression) {
if (target.initializer) {
// Combine value and initializer
value = value ? createDefaultValueCheck(value, target.initializer) : target.initializer;
@@ -3366,14 +3376,19 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
value = createVoidZero();
}
if (isBindingPattern(target.name)) {
let pattern = <BindingPattern>target.name;
let elements = pattern.elements;
if (elements.length !== 1) {
// For anything but a single element destructuring we need to generate a temporary
// to ensure value is evaluated exactly once.
value = ensureIdentifier(value);
const pattern = <BindingPattern>target.name;
const elements = pattern.elements;
const numElements = elements.length;
if (numElements !== 1) {
// For anything other than a single-element destructuring we need to generate a temporary
// to ensure value is evaluated exactly once. Additionally, if we have zero elements
// we need to emit *something* to ensure that in case a 'var' keyword was already emitted,
// so in that case, we'll intentionally create that temporary.
value = ensureIdentifier(value, /*reuseIdentifierExpressions*/ numElements !== 0);
}
for (let i = 0; i < elements.length; i++) {
for (let i = 0; i < numElements; i++) {
let element = elements[i];
if (pattern.kind === SyntaxKind.ObjectBindingPattern) {
// Rewrite element to a declaration with an initializer that fetches property
@@ -3385,7 +3400,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
// Rewrite element to a declaration that accesses array element at index i
emitBindingElement(element, createElementAccessExpression(value, createNumericLiteral(i)));
}
else if (i === elements.length - 1) {
else if (i === numElements - 1) {
emitBindingElement(element, createSliceCall(value, i));
}
}
+3 -3
View File
@@ -12,7 +12,7 @@ namespace ts {
let emptyArray: any[] = [];
export const version = "1.6.0";
export const version = "1.7.0";
export function findConfigFile(searchPath: string): string {
let fileName = "tsconfig.json";
@@ -862,8 +862,8 @@ namespace ts {
const importedFile = findModuleSourceFile(resolution.resolvedFileName, file.imports[i]);
if (importedFile && resolution.isExternalLibraryImport) {
if (!isExternalModule(importedFile)) {
let start = getTokenPosOfNode(file.imports[i], file)
fileProcessingDiagnostics.add(createFileDiagnostic(file, start, file.imports[i].end - start, Diagnostics.Exported_external_package_typings_file_0_is_not_a_module_Please_contact_the_package_author_to_update_the_package_definition, importedFile.fileName));
let start = getTokenPosOfNode(file.imports[i], file)
fileProcessingDiagnostics.add(createFileDiagnostic(file, start, file.imports[i].end - start, Diagnostics.Exported_external_package_typings_file_0_is_not_a_module_Please_contact_the_package_author_to_update_the_package_definition, importedFile.fileName));
}
else if (!fileExtensionIs(importedFile.fileName, ".d.ts")) {
let start = getTokenPosOfNode(file.imports[i], file)
+15 -2
View File
@@ -2122,17 +2122,30 @@ namespace ts {
}
/* @internal */
export interface CommandLineOption {
export interface CommandLineOptionBase {
name: string;
type: string | Map<number>; // "string", "number", "boolean", or an object literal mapping named values to actual values
isFilePath?: boolean; // True if option value is a path or fileName
shortName?: string; // A short mnemonic for convenience - for instance, 'h' can be used in place of 'help'
description?: DiagnosticMessage; // The message describing what the command line switch does
paramType?: DiagnosticMessage; // The name to be used for a non-boolean option's parameter
error?: DiagnosticMessage; // The error given when the argument does not fit a customized 'type'
experimental?: boolean;
}
/* @internal */
export interface CommandLineOptionOfPrimitiveType extends CommandLineOptionBase {
type: string; // "string" | "number" | "boolean"
}
/* @internal */
export interface CommandLineOptionOfCustomType extends CommandLineOptionBase {
type: Map<number>; // an object literal mapping named values to actual values
error: DiagnosticMessage; // The error given when the argument does not fit a customized 'type'
}
/* @internal */
export type CommandLineOption = CommandLineOptionOfCustomType | CommandLineOptionOfPrimitiveType;
/* @internal */
export const enum CharacterCodes {
nullCharacter = 0,
+8
View File
@@ -428,6 +428,7 @@ module Harness {
args(): string[];
getExecutingFilePath(): string;
exit(exitCode?: number): void;
readDirectory(path: string, extension?: string, exclude?: string[]): string[];
}
export var IO: IO;
@@ -464,6 +465,7 @@ module Harness {
export const directoryExists: typeof IO.directoryExists = fso.FolderExists;
export const fileExists: typeof IO.fileExists = fso.FileExists;
export const log: typeof IO.log = global.WScript && global.WScript.StdOut.WriteLine;
export const readDirectory: typeof IO.readDirectory = (path, extension, exclude) => ts.sys.readDirectory(path, extension, exclude);
export function createDirectory(path: string) {
if (directoryExists(path)) {
@@ -532,6 +534,8 @@ module Harness {
export const fileExists: typeof IO.fileExists = fs.existsSync;
export const log: typeof IO.log = s => console.log(s);
export const readDirectory: typeof IO.readDirectory = (path, extension, exclude) => ts.sys.readDirectory(path, extension, exclude);
export function createDirectory(path: string) {
if (!directoryExists(path)) {
fs.mkdirSync(path);
@@ -730,6 +734,10 @@ module Harness {
export function writeFile(path: string, contents: string) {
Http.writeToServerSync(serverRoot + path, "WRITE", contents);
}
export function readDirectory(path: string, extension?: string, exclude?: string[]) {
return listFiles(path).filter(f => !extension || ts.fileExtensionIs(f, extension));
}
}
}
+6 -2
View File
@@ -3,11 +3,15 @@ var fs: any = require('fs');
var path: any = require('path');
function instrumentForRecording(fn: string, tscPath: string) {
instrument(tscPath, 'ts.sys = Playback.wrapSystem(ts.sys); ts.sys.startRecord("' + fn + '");', 'ts.sys.endRecord();');
instrument(tscPath, `
ts.sys = Playback.wrapSystem(ts.sys);
ts.sys.startRecord("${ fn }");`, `ts.sys.endRecord();`);
}
function instrumentForReplay(logFilename: string, tscPath: string) {
instrument(tscPath, 'ts.sys = Playback.wrapSystem(ts.sys); ts.sys.startReplay("' + logFilename + '");');
instrument(tscPath, `
ts.sys = Playback.wrapSystem(ts.sys);
ts.sys.startReplay("${ logFilename }");`);
}
function instrument(tscPath: string, prepareCode: string, cleanupCode: string = '') {
+120 -91
View File
@@ -59,6 +59,12 @@ interface IOLog {
path: string;
result?: string;
}[];
directoriesRead: {
path: string,
extension: string,
exclude: string[],
result: string[]
}[];
}
interface PlaybackControl {
@@ -95,12 +101,15 @@ module Playback {
export interface PlaybackIO extends Harness.IO, PlaybackControl { }
export interface PlaybackSystem extends ts.System, PlaybackControl { }
function createEmptyLog(): IOLog {
return {
timestamp: (new Date()).toString(),
arguments: [],
currentDirectory: "",
filesRead: [],
directoriesRead: [],
filesWritten: [],
filesDeleted: [],
filesAppended: [],
@@ -114,8 +123,10 @@ module Playback {
};
}
function initWrapper<T>(wrapper: PlaybackControl, underlying: T) {
Object.keys(underlying).forEach(prop => {
function initWrapper(wrapper: PlaybackSystem, underlying: ts.System): void;
function initWrapper(wrapper: PlaybackIO, underlying: Harness.IO): void;
function initWrapper(wrapper: PlaybackSystem | PlaybackIO, underlying: ts.System | Harness.IO): void {
ts.forEach(Object.keys(underlying), prop => {
(<any>wrapper)[prop] = (<any>underlying)[prop];
});
@@ -135,6 +146,93 @@ module Playback {
wrapper.startRecord = (fileNameBase) => {
recordLogFileNameBase = fileNameBase;
recordLog = createEmptyLog();
if (typeof underlying.args !== "function") {
recordLog.arguments = <string[]>underlying.args;
}
};
wrapper.startReplayFromFile = logFn => {
wrapper.startReplayFromString(underlying.readFile(logFn));
};
wrapper.endRecord = () => {
if (recordLog !== undefined) {
let i = 0;
let fn = () => recordLogFileNameBase + i + ".json";
while (underlying.fileExists(fn())) i++;
underlying.writeFile(fn(), JSON.stringify(recordLog));
recordLog = undefined;
}
};
wrapper.fileExists = recordReplay(wrapper.fileExists, underlying)(
path => callAndRecord(underlying.fileExists(path), recordLog.fileExists, { path }),
memoize(path => {
// If we read from the file, it must exist
if (findResultByPath(wrapper, replayLog.filesRead, path, null) !== null) {
return true;
}
else {
return findResultByFields(replayLog.fileExists, { path }, false);
}
})
);
wrapper.getExecutingFilePath = () => {
if (replayLog !== undefined) {
return replayLog.executingPath;
}
else if (recordLog !== undefined) {
return recordLog.executingPath = underlying.getExecutingFilePath();
}
else {
return underlying.getExecutingFilePath();
}
};
wrapper.getCurrentDirectory = () => {
if (replayLog !== undefined) {
return replayLog.currentDirectory || "";
}
else if (recordLog !== undefined) {
return recordLog.currentDirectory = underlying.getCurrentDirectory();
}
else {
return underlying.getCurrentDirectory();
}
};
wrapper.resolvePath = recordReplay(wrapper.resolvePath, underlying)(
path => callAndRecord(underlying.resolvePath(path), recordLog.pathsResolved, { path }),
memoize(path => findResultByFields(replayLog.pathsResolved, { path }, !ts.isRootedDiskPath(ts.normalizeSlashes(path)) && replayLog.currentDirectory ? replayLog.currentDirectory + "/" + path : ts.normalizeSlashes(path))));
wrapper.readFile = recordReplay(wrapper.readFile, underlying)(
path => {
let result = underlying.readFile(path);
let logEntry = { path, codepage: 0, result: { contents: result, codepage: 0 } };
recordLog.filesRead.push(logEntry);
return result;
},
memoize(path => findResultByPath(wrapper, replayLog.filesRead, path).contents));
wrapper.readDirectory = recordReplay(wrapper.readDirectory, underlying)(
(path, extension, exclude) => {
let result = (<ts.System>underlying).readDirectory(path, extension, exclude);
let logEntry = { path, extension, exclude, result };
recordLog.directoriesRead.push(logEntry);
return result;
},
(path, extension, exclude) => findResultByPath(wrapper, replayLog.directoriesRead.filter(d => d.extension === extension && ts.arrayIsEqualTo(d.exclude, exclude)), path));
wrapper.writeFile = recordReplay(wrapper.writeFile, underlying)(
(path, contents) => callAndRecord(underlying.writeFile(path, contents), recordLog.filesWritten, { path, contents, bom: false }),
(path, contents) => noOpReplay("writeFile"));
wrapper.exit = (exitCode) => {
if (recordLog !== undefined) {
wrapper.endRecord();
}
underlying.exit(exitCode);
};
}
@@ -143,9 +241,11 @@ module Playback {
return <any>(function () {
if (replayLog !== undefined) {
return replay.apply(undefined, arguments);
} else if (recordLog !== undefined) {
}
else if (recordLog !== undefined) {
return record.apply(undefined, arguments);
} else {
}
else {
return original.apply(underlying, arguments);
}
});
@@ -169,7 +269,8 @@ module Playback {
if (results.length === 0) {
if (defaultValue !== undefined) {
return defaultValue;
} else {
}
else {
throw new Error("No matching result in log array for: " + JSON.stringify(expectedFields));
}
}
@@ -177,7 +278,7 @@ module Playback {
}
function findResultByPath<T>(wrapper: { resolvePath(s: string): string }, logArray: { path: string; result?: T }[], expectedPath: string, defaultValue?: T): T {
let normalizedName = ts.normalizeSlashes(expectedPath).toLowerCase();
let normalizedName = ts.normalizePath(expectedPath).toLowerCase();
// Try to find the result through normal fileName
for (let i = 0; i < logArray.length; i++) {
if (ts.normalizeSlashes(logArray[i].path).toLowerCase() === normalizedName) {
@@ -193,10 +294,12 @@ module Playback {
}
}
}
// If we got here, we didn't find a match
if (defaultValue === undefined) {
throw new Error("No matching result in log array for path: " + expectedPath);
} else {
}
else {
return defaultValue;
}
}
@@ -214,7 +317,8 @@ module Playback {
}
if (pathEquivCache.hasOwnProperty(key)) {
return pathEquivCache[key];
} else {
}
else {
return pathEquivCache[key] = check();
}
}
@@ -227,93 +331,18 @@ module Playback {
let wrapper: PlaybackIO = <any>{};
initWrapper(wrapper, underlying);
wrapper.startReplayFromFile = logFn => {
wrapper.startReplayFromString(underlying.readFile(logFn));
};
wrapper.endRecord = () => {
if (recordLog !== undefined) {
let i = 0;
let fn = () => recordLogFileNameBase + i + ".json";
while (underlying.fileExists(fn())) i++;
underlying.writeFile(fn(), JSON.stringify(recordLog));
recordLog = undefined;
}
};
wrapper.args = () => {
if (replayLog !== undefined) {
return replayLog.arguments;
} else if (recordLog !== undefined) {
recordLog.arguments = underlying.args();
}
return underlying.args();
}
wrapper.newLine = () => underlying.newLine();
wrapper.useCaseSensitiveFileNames = () => underlying.useCaseSensitiveFileNames();
wrapper.directoryName = (path): string => { throw new Error("NotSupported"); };
wrapper.createDirectory = path => { throw new Error("NotSupported"); };
wrapper.createDirectory = (path): void => { throw new Error("NotSupported"); };
wrapper.directoryExists = (path): boolean => { throw new Error("NotSupported"); };
wrapper.deleteFile = path => { throw new Error("NotSupported"); };
wrapper.deleteFile = (path): void => { throw new Error("NotSupported"); };
wrapper.listFiles = (path, filter, options): string[] => { throw new Error("NotSupported"); };
wrapper.log = text => underlying.log(text);
wrapper.fileExists = recordReplay(wrapper.fileExists, underlying)(
(path) => callAndRecord(underlying.fileExists(path), recordLog.fileExists, { path: path }),
memoize((path) => {
// If we read from the file, it must exist
if (findResultByPath(wrapper, replayLog.filesRead, path, null) !== null) {
return true;
} else {
return findResultByFields(replayLog.fileExists, { path: path }, false);
}
})
);
wrapper.getExecutingFilePath = () => {
if (replayLog !== undefined) {
return replayLog.executingPath;
} else if (recordLog !== undefined) {
return recordLog.executingPath = underlying.getExecutingFilePath();
} else {
return underlying.getExecutingFilePath();
}
};
wrapper.getCurrentDirectory = () => {
if (replayLog !== undefined) {
return replayLog.currentDirectory || "";
} else if (recordLog !== undefined) {
return recordLog.currentDirectory = underlying.getCurrentDirectory();
} else {
return underlying.getCurrentDirectory();
}
};
wrapper.resolvePath = recordReplay(wrapper.resolvePath, underlying)(
(path) => callAndRecord(underlying.resolvePath(path), recordLog.pathsResolved, { path: path }),
memoize((path) => findResultByFields(replayLog.pathsResolved, { path: path }, !ts.isRootedDiskPath(ts.normalizeSlashes(path)) && replayLog.currentDirectory ? replayLog.currentDirectory + "/" + path : ts.normalizeSlashes(path))));
wrapper.readFile = recordReplay(wrapper.readFile, underlying)(
(path) => {
let result = underlying.readFile(path);
let logEntry = { path: path, codepage: 0, result: { contents: result, codepage: 0 } };
recordLog.filesRead.push(logEntry);
return result;
},
memoize((path) => findResultByPath(wrapper, replayLog.filesRead, path).contents));
wrapper.writeFile = recordReplay(wrapper.writeFile, underlying)(
(path, contents) => callAndRecord(underlying.writeFile(path, contents), recordLog.filesWritten, { path: path, contents: contents, bom: false }),
(path, contents) => noOpReplay("writeFile"));
wrapper.exit = (exitCode) => {
if (recordLog !== undefined) {
wrapper.endRecord();
}
underlying.exit(exitCode);
};
return wrapper;
}
export function wrapSystem(underlying: ts.System): PlaybackSystem {
let wrapper: PlaybackSystem = <any>{};
initWrapper(wrapper, underlying);
return wrapper;
}
}
+22 -2
View File
@@ -19,6 +19,11 @@ module RWC {
}
}
function isTsConfigFile(file: { path: string }): boolean {
const tsConfigFileName = "tsconfig.json";
return file.path.substr(file.path.length - tsConfigFileName.length).toLowerCase() === tsConfigFileName;
}
export function runRWCTest(jsonPath: string) {
describe("Testing a RWC project: " + jsonPath, () => {
let inputFiles: { unitName: string; content: string; }[] = [];
@@ -67,10 +72,21 @@ module RWC {
runWithIOLog(ioLog, oldIO => {
harnessCompiler.reset();
let fileNames = opts.fileNames;
let tsconfigFile = ts.forEach(ioLog.filesRead, f => isTsConfigFile(f) ? f : undefined);
if (tsconfigFile) {
let tsconfigFileContents = getHarnessCompilerInputUnit(tsconfigFile.path);
let parsedTsconfigFileContents = ts.parseConfigFileText(tsconfigFile.path, tsconfigFileContents.content);
let configParseResult = ts.parseConfigFile(parsedTsconfigFileContents.config, Harness.IO, ts.getDirectoryPath(tsconfigFile.path));
fileNames = configParseResult.fileNames;
opts.options = ts.extend(opts.options, configParseResult.options);
}
// Load the files
ts.forEach(opts.fileNames, fileName => {
for (let fileName of fileNames) {
inputFiles.push(getHarnessCompilerInputUnit(fileName));
});
}
// Add files to compilation
let isInInputList = (resolvedPath: string) => (inputFile: { unitName: string; content: string; }) => inputFile.unitName === resolvedPath;
@@ -79,6 +95,10 @@ module RWC {
const resolvedPath = ts.normalizeSlashes(Harness.IO.resolvePath(fileRead.path));
let inInputList = ts.forEach(inputFiles, isInInputList(resolvedPath));
if (isTsConfigFile(fileRead)) {
continue;
}
if (!Harness.isLibraryFile(fileRead.path)) {
if (inInputList) {
continue;
+20
View File
@@ -2152,6 +2152,7 @@ namespace ts {
//
// export * from "mod"
// export {a as b} from "mod"
// export import i = require("mod")
while (token !== SyntaxKind.EndOfFileToken) {
if (token === SyntaxKind.DeclareKeyword) {
@@ -2276,6 +2277,25 @@ namespace ts {
}
}
}
else if (token === SyntaxKind.ImportKeyword) {
token = scanner.scan();
if (token === SyntaxKind.Identifier || isKeyword(token)) {
token = scanner.scan();
if (token === SyntaxKind.EqualsToken) {
token = scanner.scan();
if (token === SyntaxKind.RequireKeyword) {
token = scanner.scan();
if (token === SyntaxKind.OpenParenToken) {
token = scanner.scan();
if (token === SyntaxKind.StringLiteral) {
// export import i = require("mod");
recordModuleName();
}
}
}
}
}
}
}
token = scanner.scan();
}