merge with master

This commit is contained in:
Vladimir Matveev
2015-10-29 09:33:27 -07:00
48 changed files with 8724 additions and 6217 deletions

View File

@@ -57,5 +57,5 @@ function compile(fileNames, options) {
exports.compile = compile;
compile(process.argv.slice(2), {
noEmitOnError: true, noImplicitAny: true,
target: 1 /* ES5 */, module: 1 /* CommonJS */
target: ts.ScriptTarget.ES5, module: ts.ModuleKind.CommonJS
});

View File

@@ -75,28 +75,28 @@ function delint(sourceFile) {
delintNode(sourceFile);
function delintNode(node) {
switch (node.kind) {
case 199 /* ForStatement */:
case 200 /* ForInStatement */:
case 198 /* WhileStatement */:
case 197 /* DoStatement */:
if (node.statement.kind !== 192 /* Block */) {
case ts.SyntaxKind.ForStatement:
case ts.SyntaxKind.ForInStatement:
case ts.SyntaxKind.WhileStatement:
case ts.SyntaxKind.DoStatement:
if (node.statement.kind !== ts.SyntaxKind.Block) {
report(node, "A looping statement's contents should be wrapped in a block body.");
}
break;
case 196 /* IfStatement */:
case ts.SyntaxKind.IfStatement:
var ifStatement = node;
if (ifStatement.thenStatement.kind !== 192 /* Block */) {
if (ifStatement.thenStatement.kind !== ts.SyntaxKind.Block) {
report(ifStatement.thenStatement, "An if statement's contents should be wrapped in a block body.");
}
if (ifStatement.elseStatement &&
ifStatement.elseStatement.kind !== 192 /* Block */ &&
ifStatement.elseStatement.kind !== 196 /* IfStatement */) {
ifStatement.elseStatement.kind !== ts.SyntaxKind.Block &&
ifStatement.elseStatement.kind !== ts.SyntaxKind.IfStatement) {
report(ifStatement.elseStatement, "An else statement's contents should be wrapped in a block body.");
}
break;
case 181 /* BinaryExpression */:
case ts.SyntaxKind.BinaryExpression:
var op = node.operatorToken.kind;
if (op === 30 /* EqualsEqualsToken */ || op == 31 /* ExclamationEqualsToken */) {
if (op === ts.SyntaxKind.EqualsEqualsToken || op == ts.SyntaxKind.ExclamationEqualsToken) {
report(node, "Use '===' and '!=='.");
}
break;
@@ -112,7 +112,7 @@ exports.delint = delint;
var fileNames = process.argv.slice(2);
fileNames.forEach(function (fileName) {
// Parse a file
var sourceFile = ts.createSourceFile(fileName, readFileSync(fileName).toString(), 2 /* ES6 */, /*setParentNodes */ true);
var sourceFile = ts.createSourceFile(fileName, readFileSync(fileName).toString(), ts.ScriptTarget.ES6, /*setParentNodes */ true);
// delint it
delint(sourceFile);
});

View File

@@ -24,5 +24,5 @@ console.log(JSON.stringify(result));
*/
var ts = require("typescript");
var source = "let x: string = 'string'";
var result = ts.transpile(source, { module: 1 /* CommonJS */ });
var result = ts.transpile(source, { module: ts.ModuleKind.CommonJS });
console.log(JSON.stringify(result));

View File

@@ -181,4 +181,4 @@ function watch(rootFileNames, options) {
var currentDirectoryFiles = fs.readdirSync(process.cwd()).
filter(function (fileName) { return fileName.length >= 3 && fileName.substr(fileName.length - 3, 3) === ".ts"; });
// Start the watcher
watch(currentDirectoryFiles, { module: 1 /* CommonJS */ });
watch(currentDirectoryFiles, { module: ts.ModuleKind.CommonJS });

View File

@@ -1,7 +1,7 @@
tests/cases/conformance/async/es6/functionDeclarations/asyncFunctionDeclaration15_es6.ts(6,16): error TS1055: Type '{}' is not a valid async function return type.
tests/cases/conformance/async/es6/functionDeclarations/asyncFunctionDeclaration15_es6.ts(7,16): error TS1055: Type 'any' is not a valid async function return type.
tests/cases/conformance/async/es6/functionDeclarations/asyncFunctionDeclaration15_es6.ts(8,16): error TS1055: Type 'number' is not a valid async function return type.
tests/cases/conformance/async/es6/functionDeclarations/asyncFunctionDeclaration15_es6.ts(9,16): error TS1055: Type 'PromiseLike<void>' is not a valid async function return type.
tests/cases/conformance/async/es6/functionDeclarations/asyncFunctionDeclaration15_es6.ts(9,16): error TS1055: Type 'PromiseLike' is not a valid async function return type.
tests/cases/conformance/async/es6/functionDeclarations/asyncFunctionDeclaration15_es6.ts(10,16): error TS1055: Type 'typeof Thenable' is not a valid async function return type.
Type 'Thenable' is not assignable to type 'PromiseLike<any>'.
Types of property 'then' are incompatible.
@@ -28,7 +28,7 @@ tests/cases/conformance/async/es6/functionDeclarations/asyncFunctionDeclaration1
!!! error TS1055: Type 'number' is not a valid async function return type.
async function fn5(): PromiseLike<void> { } // error
~~~
!!! error TS1055: Type 'PromiseLike<void>' is not a valid async function return type.
!!! error TS1055: Type 'PromiseLike' is not a valid async function return type.
async function fn6(): Thenable { } // error
~~~
!!! error TS1055: Type 'typeof Thenable' is not a valid async function return type.

View File

@@ -0,0 +1,15 @@
tests/cases/compiler/emptyThenWarning.ts(1,6): error TS1313: The body of an 'if' statement cannot be the empty statement.
tests/cases/compiler/emptyThenWarning.ts(4,19): error TS1313: The body of an 'if' statement cannot be the empty statement.
==== tests/cases/compiler/emptyThenWarning.ts (2 errors) ====
if(1);
~
!!! error TS1313: The body of an 'if' statement cannot be the empty statement.
let x = 0;
if (true === true); {
~
!!! error TS1313: The body of an 'if' statement cannot be the empty statement.
x = 1;
}

View File

@@ -0,0 +1,17 @@
//// [emptyThenWarning.ts]
if(1);
let x = 0;
if (true === true); {
x = 1;
}
//// [emptyThenWarning.js]
if (1)
;
var x = 0;
if (true === true)
;
{
x = 1;
}

View File

@@ -0,0 +1,16 @@
//// [emptyThenWithoutWarning.ts]
let a = 4;
if(a === 1 || a === 2 || a === 3) {
}
else {
let message = "Ooops";
}
//// [emptyThenWithoutWarning.js]
var a = 4;
if (a === 1 || a === 2 || a === 3) {
}
else {
var message = "Ooops";
}

View File

@@ -0,0 +1,13 @@
=== tests/cases/compiler/emptyThenWithoutWarning.ts ===
let a = 4;
>a : Symbol(a, Decl(emptyThenWithoutWarning.ts, 0, 3))
if(a === 1 || a === 2 || a === 3) {
>a : Symbol(a, Decl(emptyThenWithoutWarning.ts, 0, 3))
>a : Symbol(a, Decl(emptyThenWithoutWarning.ts, 0, 3))
>a : Symbol(a, Decl(emptyThenWithoutWarning.ts, 0, 3))
}
else {
let message = "Ooops";
>message : Symbol(message, Decl(emptyThenWithoutWarning.ts, 5, 7))
}

View File

@@ -0,0 +1,23 @@
=== tests/cases/compiler/emptyThenWithoutWarning.ts ===
let a = 4;
>a : number
>4 : number
if(a === 1 || a === 2 || a === 3) {
>a === 1 || a === 2 || a === 3 : boolean
>a === 1 || a === 2 : boolean
>a === 1 : boolean
>a : number
>1 : number
>a === 2 : boolean
>a : number
>2 : number
>a === 3 : boolean
>a : number
>3 : number
}
else {
let message = "Ooops";
>message : string
>"Ooops" : string
}

View File

@@ -0,0 +1,27 @@
//// [localClassesInLoop.ts]
declare function use(a: any);
"use strict"
var data = [];
for (let x = 0; x < 2; ++x) {
class C { }
data.push(() => C);
}
use(data[0]() === data[1]());
//// [localClassesInLoop.js]
"use strict";
var data = [];
var _loop_1 = function(x) {
var C = (function () {
function C() {
}
return C;
})();
data.push(function () { return C; });
};
for (var x = 0; x < 2; ++x) {
_loop_1(x);
}
use(data[0]() === data[1]());

View File

@@ -0,0 +1,29 @@
=== tests/cases/compiler/localClassesInLoop.ts ===
declare function use(a: any);
>use : Symbol(use, Decl(localClassesInLoop.ts, 0, 0))
>a : Symbol(a, Decl(localClassesInLoop.ts, 0, 21))
"use strict"
var data = [];
>data : Symbol(data, Decl(localClassesInLoop.ts, 3, 3))
for (let x = 0; x < 2; ++x) {
>x : Symbol(x, Decl(localClassesInLoop.ts, 4, 8))
>x : Symbol(x, Decl(localClassesInLoop.ts, 4, 8))
>x : Symbol(x, Decl(localClassesInLoop.ts, 4, 8))
class C { }
>C : Symbol(C, Decl(localClassesInLoop.ts, 4, 29))
data.push(() => C);
>data.push : Symbol(Array.push, Decl(lib.d.ts, --, --))
>data : Symbol(data, Decl(localClassesInLoop.ts, 3, 3))
>push : Symbol(Array.push, Decl(lib.d.ts, --, --))
>C : Symbol(C, Decl(localClassesInLoop.ts, 4, 29))
}
use(data[0]() === data[1]());
>use : Symbol(use, Decl(localClassesInLoop.ts, 0, 0))
>data : Symbol(data, Decl(localClassesInLoop.ts, 3, 3))
>data : Symbol(data, Decl(localClassesInLoop.ts, 3, 3))

View File

@@ -0,0 +1,46 @@
=== tests/cases/compiler/localClassesInLoop.ts ===
declare function use(a: any);
>use : (a: any) => any
>a : any
"use strict"
>"use strict" : string
var data = [];
>data : any[]
>[] : undefined[]
for (let x = 0; x < 2; ++x) {
>x : number
>0 : number
>x < 2 : boolean
>x : number
>2 : number
>++x : number
>x : number
class C { }
>C : C
data.push(() => C);
>data.push(() => C) : number
>data.push : (...items: any[]) => number
>data : any[]
>push : (...items: any[]) => number
>() => C : () => typeof C
>C : typeof C
}
use(data[0]() === data[1]());
>use(data[0]() === data[1]()) : any
>use : (a: any) => any
>data[0]() === data[1]() : boolean
>data[0]() : any
>data[0] : any
>data : any[]
>0 : number
>data[1]() : any
>data[1] : any
>data : any[]
>1 : number

View File

@@ -0,0 +1,22 @@
//// [localClassesInLoop_ES6.ts]
declare function use(a: any);
"use strict"
var data = [];
for (let x = 0; x < 2; ++x) {
class C { }
data.push(() => C);
}
use(data[0]() === data[1]());
//// [localClassesInLoop_ES6.js]
"use strict";
var data = [];
for (let x = 0; x < 2; ++x) {
class C {
}
data.push(() => C);
}
use(data[0]() === data[1]());

View File

@@ -0,0 +1,30 @@
=== tests/cases/compiler/localClassesInLoop_ES6.ts ===
declare function use(a: any);
>use : Symbol(use, Decl(localClassesInLoop_ES6.ts, 0, 0))
>a : Symbol(a, Decl(localClassesInLoop_ES6.ts, 1, 21))
"use strict"
var data = [];
>data : Symbol(data, Decl(localClassesInLoop_ES6.ts, 4, 3))
for (let x = 0; x < 2; ++x) {
>x : Symbol(x, Decl(localClassesInLoop_ES6.ts, 5, 8))
>x : Symbol(x, Decl(localClassesInLoop_ES6.ts, 5, 8))
>x : Symbol(x, Decl(localClassesInLoop_ES6.ts, 5, 8))
class C { }
>C : Symbol(C, Decl(localClassesInLoop_ES6.ts, 5, 29))
data.push(() => C);
>data.push : Symbol(Array.push, Decl(lib.d.ts, --, --))
>data : Symbol(data, Decl(localClassesInLoop_ES6.ts, 4, 3))
>push : Symbol(Array.push, Decl(lib.d.ts, --, --))
>C : Symbol(C, Decl(localClassesInLoop_ES6.ts, 5, 29))
}
use(data[0]() === data[1]());
>use : Symbol(use, Decl(localClassesInLoop_ES6.ts, 0, 0))
>data : Symbol(data, Decl(localClassesInLoop_ES6.ts, 4, 3))
>data : Symbol(data, Decl(localClassesInLoop_ES6.ts, 4, 3))

View File

@@ -0,0 +1,47 @@
=== tests/cases/compiler/localClassesInLoop_ES6.ts ===
declare function use(a: any);
>use : (a: any) => any
>a : any
"use strict"
>"use strict" : string
var data = [];
>data : any[]
>[] : undefined[]
for (let x = 0; x < 2; ++x) {
>x : number
>0 : number
>x < 2 : boolean
>x : number
>2 : number
>++x : number
>x : number
class C { }
>C : C
data.push(() => C);
>data.push(() => C) : number
>data.push : (...items: any[]) => number
>data : any[]
>push : (...items: any[]) => number
>() => C : () => typeof C
>C : typeof C
}
use(data[0]() === data[1]());
>use(data[0]() === data[1]()) : any
>use : (a: any) => any
>data[0]() === data[1]() : boolean
>data[0]() : any
>data[0] : any
>data : any[]
>0 : number
>data[1]() : any
>data[1] : any
>data : any[]
>1 : number

View File

@@ -0,0 +1,6 @@
if(1);
let x = 0;
if (true === true); {
x = 1;
}

View File

@@ -0,0 +1,7 @@
let a = 4;
if(a === 1 || a === 2 || a === 3) {
}
else {
let message = "Ooops";
}

View File

@@ -0,0 +1,10 @@
declare function use(a: any);
"use strict"
var data = [];
for (let x = 0; x < 2; ++x) {
class C { }
data.push(() => C);
}
use(data[0]() === data[1]());

View File

@@ -0,0 +1,12 @@
// @target: ES6
declare function use(a: any);
"use strict"
var data = [];
for (let x = 0; x < 2; ++x) {
class C { }
data.push(() => C);
}
use(data[0]() === data[1]());

View File

@@ -6,21 +6,35 @@ declare namespace chai.assert {
}
module ts {
function diagnosticToString(diagnostic: Diagnostic) {
let output = "";
if (diagnostic.file) {
let loc = getLineAndCharacterOfPosition(diagnostic.file, diagnostic.start);
output += `${diagnostic.file.fileName}(${loc.line + 1},${loc.character + 1}): `;
}
let category = DiagnosticCategory[diagnostic.category].toLowerCase();
output += `${category} TS${diagnostic.code}: ${flattenDiagnosticMessageText(diagnostic.messageText, sys.newLine)}${sys.newLine}`;
return output;
}
interface File {
name: string
content?: string
content?: string
}
function createModuleResolutionHost(...files: File[]): ModuleResolutionHost {
let map = arrayToMap(files, f => f.name);
return { fileExists, readFile };
function fileExists(path: string): boolean {
return hasProperty(map, path);
}
function readFile(path: string): string {
return hasProperty(map, path) ? map[path].content : undefined;
}
@@ -28,18 +42,18 @@ module ts {
function splitPath(path: string): { dir: string; rel: string } {
let index = path.indexOf(directorySeparator);
return index === -1
return index === -1
? { dir: path, rel: undefined }
: { dir: path.substr(0, index), rel: path.substr(index + 1) };
}
describe("Node module resolution - relative paths", () => {
function testLoadAsFile(containingFileName: string, moduleFileNameNoExt: string, moduleName: string): void {
for (let ext of supportedExtensions) {
let containingFile = { name: containingFileName }
let moduleFile = { name: moduleFileNameNoExt + ext }
let resolution = nodeModuleNameResolver(moduleName, containingFile.name, createModuleResolutionHost(containingFile, moduleFile));
let resolution = nodeModuleNameResolver(moduleName, containingFile.name, createModuleResolutionHost(containingFile, moduleFile));
assert.equal(resolution.resolvedModule.resolvedFileName, moduleFile.name);
assert.equal(!!resolution.resolvedModule.isExternalLibraryImport, false);
@@ -53,11 +67,11 @@ module ts {
failedLookupLocations.push(normalizePath(getRootLength(moduleName) === 0 ? combinePaths(dir, moduleName) : moduleName) + e);
}
}
assert.deepEqual(resolution.failedLookupLocations, failedLookupLocations);
}
}
it("module name that starts with './' resolved as relative file name", () => {
testLoadAsFile("/foo/bar/baz.ts", "/foo/bar/foo", "./foo");
});
@@ -73,7 +87,7 @@ module ts {
it("module name that starts with 'c:/' script extension resolved as relative file name", () => {
testLoadAsFile("c:/foo/bar/baz.ts", "c:/foo", "c:/foo");
});
function testLoadingFromPackageJson(containingFileName: string, packageJsonFileName: string, fieldRef: string, moduleFileName: string, moduleName: string): void {
let containingFile = { name: containingFileName };
let packageJson = { name: packageJsonFileName, content: JSON.stringify({ "typings": fieldRef }) };
@@ -84,17 +98,17 @@ module ts {
// expect three failed lookup location - attempt to load module as file with all supported extensions
assert.equal(resolution.failedLookupLocations.length, 3);
}
it("module name as directory - load from typings", () => {
testLoadingFromPackageJson("/a/b/c/d.ts", "/a/b/c/bar/package.json", "c/d/e.d.ts", "/a/b/c/bar/c/d/e.d.ts", "./bar");
testLoadingFromPackageJson("/a/b/c/d.ts", "/a/bar/package.json", "e.d.ts", "/a/bar/e.d.ts", "../../bar");
testLoadingFromPackageJson("/a/b/c/d.ts", "/bar/package.json", "e.d.ts", "/bar/e.d.ts", "/bar");
testLoadingFromPackageJson("c:/a/b/c/d.ts", "c:/bar/package.json", "e.d.ts", "c:/bar/e.d.ts", "c:/bar");
});
it ("module name as directory - load index.d.ts", () => {
let containingFile = {name: "/a/b/c.ts"};
let packageJson = {name: "/a/b/foo/package.json", content: JSON.stringify({main: "/c/d"})};
it("module name as directory - load index.d.ts", () => {
let containingFile = { name: "/a/b/c.ts" };
let packageJson = { name: "/a/b/foo/package.json", content: JSON.stringify({ main: "/c/d" }) };
let indexFile = { name: "/a/b/foo/index.d.ts" };
let resolution = nodeModuleNameResolver("./foo", containingFile.name, createModuleResolutionHost(containingFile, packageJson, indexFile));
assert.equal(resolution.resolvedModule.resolvedFileName, indexFile.name);
@@ -108,7 +122,7 @@ module ts {
]);
});
});
describe("Node module resolution - non-relative paths", () => {
it("load module as file - ts files not loaded", () => {
let containingFile = { name: "/a/b/c/d/e.ts" };
@@ -140,7 +154,7 @@ module ts {
assert.equal(resolution.resolvedModule.resolvedFileName, moduleFile.name);
assert.equal(resolution.resolvedModule.isExternalLibraryImport, true);
});
it("load module as directory", () => {
let containingFile = { name: "/a/node_modules/b/c/node_modules/d/e.ts" };
let moduleFile = { name: "/a/node_modules/foo/index.d.ts" };
@@ -178,31 +192,15 @@ module ts {
]);
});
});
describe("Module resolution - relative imports", () => {
it("should find all modules", () => {
const options: CompilerOptions = { module: ModuleKind.CommonJS };
const files: Map<string> = {
"/a/b/c/first/shared.ts": `
class A {}
export = A`,
"/a/b/c/first/second/class_a.ts": `
import Shared = require('../shared');
import C = require('../../third/class_c');
class B {}
export = B;`,
"/a/b/c/third/class_c.ts":`
import Shared = require('../first/shared');
class C {}
export = C;
`
};
const currentDirectory = "/a/b/c/first/second";
const host: CompilerHost = {
getSourceFile: (fileName: string, languageVersion: ScriptTarget) => {
let path = normalizePath(combinePaths(currentDirectory, fileName));
return hasProperty(files, path) ? createSourceFile(fileName, files[path], languageVersion) : undefined;
},
function test(files: Map<string>, currentDirectory: string, rootFiles: string[], expectedFilesCount: number, relativeNamesToCheck: string[]) {
const options: CompilerOptions = { module: ModuleKind.CommonJS };
const host: CompilerHost = {
getSourceFile: (fileName: string, languageVersion: ScriptTarget) => {
let path = normalizePath(combinePaths(currentDirectory, fileName));
return hasProperty(files, path) ? createSourceFile(fileName, files[path], languageVersion) : undefined;
},
getDefaultLibFileName: () => "lib.d.ts",
writeFile: (fileName, content): void => { throw new Error("NotImplemented"); },
getCurrentDirectory: () => currentDirectory,
@@ -210,38 +208,150 @@ export = C;
getNewLine: () => "\r\n",
useCaseSensitiveFileNames: () => false,
fileExists: fileName => {
let path = normalizePath(combinePaths(currentDirectory, fileName));
return hasProperty(files, path);
let path = normalizePath(combinePaths(currentDirectory, fileName));
return hasProperty(files, path);
},
readFile: (fileName): string => { throw new Error("NotImplemented"); }
};
};
const program = createProgram(["class_a.ts"], options, host);
const program = createProgram(rootFiles, options, host);
assert.equal(program.getSourceFiles().length, 3);
const syntacticDiagnostics = program.getSyntacticDiagnostics();
assert.equal(syntacticDiagnostics.length, 0, `expect no syntactic diagnostics, got: ${JSON.stringify(syntacticDiagnostics.map(diagnosticToString))}`);
const semanticDiagnostics = program.getSemanticDiagnostics();
assert.equal(semanticDiagnostics.length, 0, `expect no semantic diagnostics, got: ${JSON.stringify(semanticDiagnostics.map(diagnosticToString))}`);
assert.equal(program.getSourceFiles().length, expectedFilesCount);
const syntacticDiagnostics = program.getSyntacticDiagnostics();
assert.equal(syntacticDiagnostics.length, 0, `expect no syntactic diagnostics, got: ${JSON.stringify(syntacticDiagnostics.map(diagnosticToString))}`);
const semanticDiagnostics = program.getSemanticDiagnostics();
assert.equal(semanticDiagnostics.length, 0, `expect no semantic diagnostics, got: ${JSON.stringify(semanticDiagnostics.map(diagnosticToString))}`);
// try to get file using a relative name
const fileC = program.getSourceFile("../../../c/third/class_c.ts");
assert.isTrue(fileC !== undefined, `expected to get file by relative name, got ${fileC}`);
});
function diagnosticToString(diagnostic: Diagnostic) {
let output = "";
if (diagnostic.file) {
let loc = getLineAndCharacterOfPosition(diagnostic.file, diagnostic.start);
output += `${ diagnostic.file.fileName }(${ loc.line + 1 },${ loc.character + 1 }): `;
// try to get file using a relative name
for (const relativeFileName of relativeNamesToCheck) {
assert.isTrue(program.getSourceFile(relativeFileName) !== undefined, `expected to get file by relative name, got undefined`);
}
let category = DiagnosticCategory[diagnostic.category].toLowerCase();
output += `${ category } TS${ diagnostic.code }: ${ flattenDiagnosticMessageText(diagnostic.messageText, sys.newLine) }${ sys.newLine }`;
return output;
}
it("should find all modules", () => {
const files: Map<string> = {
"/a/b/c/first/shared.ts": `
class A {}
export = A`,
"/a/b/c/first/second/class_a.ts": `
import Shared = require('../shared');
import C = require('../../third/class_c');
class B {}
export = B;`,
"/a/b/c/third/class_c.ts": `
import Shared = require('../first/shared');
class C {}
export = C;
`
};
test(files, "/a/b/c/first/second", ["class_a.ts"], 3, ["../../../c/third/class_c.ts"]);
});
it("should find modules in node_modules", () => {
const files: Map<string> = {
"/parent/node_modules/mod/index.d.ts": "export var x",
"/parent/app/myapp.ts": `import {x} from "mod"`
};
test(files, "/parent/app",["myapp.ts"], 2, []);
});
it("should find file referenced via absolute and relative names", () => {
const files: Map<string> = {
"/a/b/c.ts": `/// <reference path="b.ts"/>`,
"/a/b/b.ts": "var x"
};
test(files, "/a/b", ["c.ts", "/a/b/b.ts"], 2, []);
});
});
describe("Files with different casing", () => {
const library = createSourceFile("lib.d.ts", "", ScriptTarget.ES5);
function test(files: Map<string>, options: CompilerOptions, currentDirectory: string, useCaseSensitiveFileNames: boolean, rootFiles: string[], diagnosticCodes: number[]): void {
const getCanonicalFileName = createGetCanonicalFileName(useCaseSensitiveFileNames);
if (!useCaseSensitiveFileNames) {
let f: Map<string> = {};
for (let fileName in files) {
f[getCanonicalFileName(fileName)] = files[fileName];
}
files = f;
}
const host: CompilerHost = {
getSourceFile: (fileName: string, languageVersion: ScriptTarget) => {
if (fileName === "lib.d.ts") {
return library;
}
let path = getCanonicalFileName(normalizePath(combinePaths(currentDirectory, fileName)));
return hasProperty(files, path) ? createSourceFile(fileName, files[path], languageVersion) : undefined;
},
getDefaultLibFileName: () => "lib.d.ts",
writeFile: (fileName, content): void => { throw new Error("NotImplemented"); },
getCurrentDirectory: () => currentDirectory,
getCanonicalFileName,
getNewLine: () => "\r\n",
useCaseSensitiveFileNames: () => useCaseSensitiveFileNames,
fileExists: fileName => {
let path = getCanonicalFileName(normalizePath(combinePaths(currentDirectory, fileName)));
return hasProperty(files, path);
},
readFile: (fileName): string => { throw new Error("NotImplemented"); }
};
const program = createProgram(rootFiles, options, host);
const diagnostics = sortAndDeduplicateDiagnostics(program.getSemanticDiagnostics().concat(program.getOptionsDiagnostics()));
assert.equal(diagnostics.length, diagnosticCodes.length, `Incorrect number of expected diagnostics, expected ${diagnosticCodes.length}, got '${map(diagnostics, diagnosticToString).join("\r\n")}'`);
for (let i = 0; i < diagnosticCodes.length; ++i) {
assert.equal(diagnostics[i].code, diagnosticCodes[i], `Expected diagnostic code ${diagnosticCodes[i]}, got '${diagnostics[i].code}': '${diagnostics[i].messageText}'`);
}
}
it("should succeed when the same file is referenced using absolute and relative names", () => {
const files: Map<string> = {
"/a/b/c.ts": `/// <reference path="d.ts"/>`,
"/a/b/d.ts": "var x"
};
test(files, { module: ts.ModuleKind.AMD }, "/a/b", /* useCaseSensitiveFileNames */ false, ["c.ts", "/a/b/d.ts"], []);
});
it("should fail when two files used in program differ only in casing (tripleslash references)", () => {
const files: Map<string> = {
"/a/b/c.ts": `/// <reference path="D.ts"/>`,
"/a/b/d.ts": "var x"
};
test(files, { module: ts.ModuleKind.AMD, forceConsistentCasingInFileNames: true }, "/a/b", /* useCaseSensitiveFileNames */ false, ["c.ts", "d.ts"], [1149]);
});
it("should fail when two files used in program differ only in casing (imports)", () => {
const files: Map<string> = {
"/a/b/c.ts": `import {x} from "D"`,
"/a/b/d.ts": "export var x"
};
test(files, { module: ts.ModuleKind.AMD, forceConsistentCasingInFileNames: true }, "/a/b", /* useCaseSensitiveFileNames */ false, ["c.ts", "d.ts"], [1149]);
});
it("should fail when two files used in program differ only in casing (imports, relative module names)", () => {
const files: Map<string> = {
"moduleA.ts": `import {x} from "./ModuleB"`,
"moduleB.ts": "export var x"
};
test(files, { module: ts.ModuleKind.CommonJS, forceConsistentCasingInFileNames: true }, "", /* useCaseSensitiveFileNames */ false, ["moduleA.ts", "moduleB.ts"], [1149]);
});
it("should fail when two files exist on disk that differs only in casing", () => {
const files: Map<string> = {
"/a/b/c.ts": `import {x} from "D"`,
"/a/b/D.ts": "export var x",
"/a/b/d.ts": "export var y"
};
test(files, { module: ts.ModuleKind.AMD }, "/a/b", /* useCaseSensitiveFileNames */ true, ["c.ts", "d.ts"], [1149]);
});
it("should fail when module name in 'require' calls has inconsistent casing", () => {
const files: Map<string> = {
"moduleA.ts": `import a = require("./ModuleC")`,
"moduleB.ts": `import a = require("./moduleC")`,
"moduleC.ts": "export var x"
};
test(files, { module: ts.ModuleKind.CommonJS, forceConsistentCasingInFileNames: true }, "", /* useCaseSensitiveFileNames */ false, ["moduleA.ts", "moduleB.ts", "moduleC.ts"], [1149, 1149]);
})
});
}