mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-12 04:17:34 -06:00
Lint unit tests via harnessSources in Jakefile.js
This commit is contained in:
parent
92d465d01f
commit
3d841b20a7
@ -974,7 +974,7 @@ var servicesLintTargets = [
|
||||
return path.join(servicesDirectory, s);
|
||||
});
|
||||
var lintTargets = compilerSources
|
||||
.concat(harnessCoreSources)
|
||||
.concat(harnessSources)
|
||||
// Other harness sources
|
||||
.concat(["instrumenter.ts"].map(function(f) { return path.join(harnessDirectory, f) }))
|
||||
.concat(serverCoreSources)
|
||||
|
||||
@ -7,7 +7,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function createDefaultServerHost(fileMap: Map<File>): server.ServerHost {
|
||||
let existingDirectories: Map<boolean> = {};
|
||||
const existingDirectories: Map<boolean> = {};
|
||||
forEachValue(fileMap, v => {
|
||||
let dir = getDirectoryPath(v.name);
|
||||
let previous: string;
|
||||
@ -67,7 +67,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function createProject(rootFile: string, serverHost: server.ServerHost): { project: server.Project, rootScriptInfo: server.ScriptInfo } {
|
||||
let logger: server.Logger = {
|
||||
const logger: server.Logger = {
|
||||
close() { },
|
||||
isVerbose: () => false,
|
||||
loggingEnabled: () => false,
|
||||
@ -78,9 +78,9 @@ namespace ts {
|
||||
msg: (s: string, type?: string) => { }
|
||||
};
|
||||
|
||||
let projectService = new server.ProjectService(serverHost, logger);
|
||||
let rootScriptInfo = projectService.openFile(rootFile, /* openedByClient */true);
|
||||
let project = projectService.createInferredProject(rootScriptInfo);
|
||||
const projectService = new server.ProjectService(serverHost, logger);
|
||||
const rootScriptInfo = projectService.openFile(rootFile, /* openedByClient */true);
|
||||
const project = projectService.createInferredProject(rootScriptInfo);
|
||||
project.setProjectOptions({ files: [rootScriptInfo.fileName], compilerOptions: { module: ts.ModuleKind.AMD } });
|
||||
return {
|
||||
project,
|
||||
@ -90,24 +90,24 @@ namespace ts {
|
||||
|
||||
describe("Caching in LSHost", () => {
|
||||
it("works using legacy resolution logic", () => {
|
||||
let root: File = {
|
||||
const root: File = {
|
||||
name: "c:/d/f0.ts",
|
||||
content: `import {x} from "f1"`
|
||||
};
|
||||
|
||||
let imported: File = {
|
||||
const imported: File = {
|
||||
name: "c:/f1.ts",
|
||||
content: `foo()`
|
||||
};
|
||||
|
||||
let serverHost = createDefaultServerHost({ [root.name]: root, [imported.name]: imported });
|
||||
let { project, rootScriptInfo } = createProject(root.name, serverHost);
|
||||
const serverHost = createDefaultServerHost({ [root.name]: root, [imported.name]: imported });
|
||||
const { project, rootScriptInfo } = createProject(root.name, serverHost);
|
||||
|
||||
// ensure that imported file was found
|
||||
let diags = project.compilerService.languageService.getSemanticDiagnostics(imported.name);
|
||||
assert.equal(diags.length, 1);
|
||||
|
||||
let originalFileExists = serverHost.fileExists;
|
||||
const originalFileExists = serverHost.fileExists;
|
||||
{
|
||||
// patch fileExists to make sure that disk is not touched
|
||||
serverHost.fileExists = (fileName): boolean => {
|
||||
@ -115,7 +115,7 @@ namespace ts {
|
||||
return false;
|
||||
};
|
||||
|
||||
let newContent = `import {x} from "f1"
|
||||
const newContent = `import {x} from "f1"
|
||||
var x: string = 1;`;
|
||||
rootScriptInfo.editContent(0, rootScriptInfo.content.length, newContent);
|
||||
// trigger synchronization to make sure that import will be fetched from the cache
|
||||
@ -133,7 +133,7 @@ namespace ts {
|
||||
assert.isTrue(fileName.indexOf("/f2.") !== -1);
|
||||
return originalFileExists.call(serverHost, fileName);
|
||||
};
|
||||
let newContent = `import {x} from "f2"`;
|
||||
const newContent = `import {x} from "f2"`;
|
||||
rootScriptInfo.editContent(0, rootScriptInfo.content.length, newContent);
|
||||
|
||||
try {
|
||||
@ -157,7 +157,7 @@ namespace ts {
|
||||
return originalFileExists.call(serverHost, fileName);
|
||||
};
|
||||
|
||||
let newContent = `import {x} from "f1"`;
|
||||
const newContent = `import {x} from "f1"`;
|
||||
rootScriptInfo.editContent(0, rootScriptInfo.content.length, newContent);
|
||||
project.compilerService.languageService.getSemanticDiagnostics(imported.name);
|
||||
assert.isTrue(fileExistsCalled);
|
||||
@ -165,7 +165,7 @@ namespace ts {
|
||||
// setting compiler options discards module resolution cache
|
||||
fileExistsCalled = false;
|
||||
|
||||
let opts = ts.clone(project.projectOptions);
|
||||
const opts = ts.clone(project.projectOptions);
|
||||
opts.compilerOptions = ts.clone(opts.compilerOptions);
|
||||
opts.compilerOptions.target = ts.ScriptTarget.ES5;
|
||||
project.setProjectOptions(opts);
|
||||
@ -176,19 +176,19 @@ namespace ts {
|
||||
});
|
||||
|
||||
it("loads missing files from disk", () => {
|
||||
let root: File = {
|
||||
const root: File = {
|
||||
name: `c:/foo.ts`,
|
||||
content: `import {x} from "bar"`
|
||||
};
|
||||
|
||||
let imported: File = {
|
||||
const imported: File = {
|
||||
name: `c:/bar.d.ts`,
|
||||
content: `export var y = 1`
|
||||
};
|
||||
|
||||
let fileMap: Map<File> = { [root.name]: root };
|
||||
let serverHost = createDefaultServerHost(fileMap);
|
||||
let originalFileExists = serverHost.fileExists;
|
||||
const fileMap: Map<File> = { [root.name]: root };
|
||||
const serverHost = createDefaultServerHost(fileMap);
|
||||
const originalFileExists = serverHost.fileExists;
|
||||
|
||||
let fileExistsCalledForBar = false;
|
||||
serverHost.fileExists = fileName => {
|
||||
@ -202,7 +202,7 @@ namespace ts {
|
||||
return originalFileExists.call(serverHost, fileName);
|
||||
};
|
||||
|
||||
let { project, rootScriptInfo } = createProject(root.name, serverHost);
|
||||
const { project, rootScriptInfo } = createProject(root.name, serverHost);
|
||||
|
||||
let diags = project.compilerService.languageService.getSemanticDiagnostics(root.name);
|
||||
assert.isTrue(fileExistsCalledForBar, "'fileExists' should be called");
|
||||
@ -219,4 +219,4 @@ namespace ts {
|
||||
assert.isTrue(diags.length === 0);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
/// <reference path="..\..\..\src\compiler\commandLineParser.ts" />
|
||||
|
||||
namespace ts {
|
||||
describe('parseCommandLine', () => {
|
||||
describe("parseCommandLine", () => {
|
||||
|
||||
function assertParseResult(commandLine: string[], expectedParsedCommandLine: ts.ParsedCommandLine) {
|
||||
const parsed = ts.parseCommandLine(commandLine);
|
||||
@ -13,9 +13,9 @@ namespace ts {
|
||||
const parsedErrors = parsed.errors;
|
||||
const expectedErrors = expectedParsedCommandLine.errors;
|
||||
assert.isTrue(parsedErrors.length === expectedErrors.length, `Expected error: ${JSON.stringify(expectedErrors)}. Actual error: ${JSON.stringify(parsedErrors)}.`);
|
||||
for (let i = 0; i < parsedErrors.length; ++i) {
|
||||
for (let i = 0; i < parsedErrors.length; i++) {
|
||||
const parsedError = parsedErrors[i];
|
||||
const expectedError = expectedErrors[i];
|
||||
const expectedError = expectedErrors[i];
|
||||
assert.equal(parsedError.code, expectedError.code);
|
||||
assert.equal(parsedError.category, expectedError.category);
|
||||
assert.equal(parsedError.messageText, expectedError.messageText);
|
||||
@ -24,9 +24,9 @@ namespace ts {
|
||||
const parsedFileNames = parsed.fileNames;
|
||||
const expectedFileNames = expectedParsedCommandLine.fileNames;
|
||||
assert.isTrue(parsedFileNames.length === expectedFileNames.length, `Expected fileNames: [${JSON.stringify(expectedFileNames)}]. Actual fileNames: [${JSON.stringify(parsedFileNames)}].`);
|
||||
for (let i = 0; i < parsedFileNames.length; ++i) {
|
||||
for (let i = 0; i < parsedFileNames.length; i++) {
|
||||
const parsedFileName = parsedFileNames[i];
|
||||
const expectedFileName = expectedFileNames[i];
|
||||
const expectedFileName = expectedFileNames[i];
|
||||
assert.equal(parsedFileName, expectedFileName);
|
||||
}
|
||||
}
|
||||
@ -113,7 +113,7 @@ namespace ts {
|
||||
start: undefined,
|
||||
length: undefined,
|
||||
}, {
|
||||
messageText: "Argument for '--module' option must be: 'none', 'commonjs', 'amd', 'system', 'umd', 'es6', 'es2015'",
|
||||
messageText: "Argument for '--module' option must be: 'none', 'commonjs', 'amd', 'system', 'umd', 'es6', 'es2015'",
|
||||
category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category,
|
||||
code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
|
||||
|
||||
|
||||
@ -2,25 +2,25 @@
|
||||
/// <reference path="..\..\..\src\compiler\commandLineParser.ts" />
|
||||
|
||||
namespace ts {
|
||||
describe('convertCompilerOptionsFromJson', () => {
|
||||
describe("convertCompilerOptionsFromJson", () => {
|
||||
function assertCompilerOptions(json: any, configFileName: string, expectedResult: { compilerOptions: CompilerOptions, errors: Diagnostic[] }) {
|
||||
const { options: actualCompilerOptions, errors: actualErrors} = convertCompilerOptionsFromJson(json["compilerOptions"], "/apath/", configFileName);
|
||||
|
||||
|
||||
const parsedCompilerOptions = JSON.stringify(actualCompilerOptions);
|
||||
const expectedCompilerOptions = JSON.stringify(expectedResult.compilerOptions);
|
||||
assert.equal(parsedCompilerOptions, expectedCompilerOptions);
|
||||
|
||||
|
||||
const expectedErrors = expectedResult.errors;
|
||||
assert.isTrue(expectedResult.errors.length === actualErrors.length, `Expected error: ${JSON.stringify(expectedResult.errors)}. Actual error: ${JSON.stringify(actualErrors)}.`);
|
||||
for (let i = 0; i < actualErrors.length; ++i) {
|
||||
for (let i = 0; i < actualErrors.length; i++) {
|
||||
const actualError = actualErrors[i];
|
||||
const expectedError = expectedErrors[i];
|
||||
const expectedError = expectedErrors[i];
|
||||
assert.equal(actualError.code, expectedError.code);
|
||||
assert.equal(actualError.category, expectedError.category);
|
||||
assert.equal(actualError.messageText, expectedError.messageText);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// tsconfig.json tests
|
||||
it("Convert correctly format tsconfig.json to compiler-options ", () => {
|
||||
assertCompilerOptions(
|
||||
@ -448,7 +448,7 @@ namespace ts {
|
||||
}
|
||||
}, "jsconfig.json",
|
||||
{
|
||||
compilerOptions:
|
||||
compilerOptions:
|
||||
{
|
||||
allowJs: true
|
||||
},
|
||||
@ -467,7 +467,7 @@ namespace ts {
|
||||
it("Convert default jsconfig.json to compiler-options ", () => {
|
||||
assertCompilerOptions({}, "jsconfig.json",
|
||||
{
|
||||
compilerOptions:
|
||||
compilerOptions:
|
||||
{
|
||||
allowJs: true
|
||||
},
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
/// <reference path="..\..\..\src\harness\harness.ts" />
|
||||
|
||||
module ts {
|
||||
describe('convertToBase64', () => {
|
||||
namespace ts {
|
||||
describe("convertToBase64", () => {
|
||||
function runTest(input: string): void {
|
||||
var actual = ts.convertToBase64(input);
|
||||
var expected = new Buffer(input).toString("base64");
|
||||
const actual = ts.convertToBase64(input);
|
||||
const expected = new Buffer(input).toString("base64");
|
||||
assert.equal(actual, expected, "Encoded string using convertToBase64 does not match buffer.toString('base64')");
|
||||
}
|
||||
|
||||
|
||||
@ -2,18 +2,18 @@
|
||||
/// <reference path="..\..\..\src\compiler\commandLineParser.ts" />
|
||||
|
||||
namespace ts {
|
||||
describe('convertTypingOptionsFromJson', () => {
|
||||
describe("convertTypingOptionsFromJson", () => {
|
||||
function assertTypingOptions(json: any, configFileName: string, expectedResult: { typingOptions: TypingOptions, errors: Diagnostic[] }) {
|
||||
const { options: actualTypingOptions, errors: actualErrors } = convertTypingOptionsFromJson(json["typingOptions"], "/apath/", configFileName);
|
||||
const parsedTypingOptions = JSON.stringify(actualTypingOptions);
|
||||
const expectedTypingOptions = JSON.stringify(expectedResult.typingOptions);
|
||||
assert.equal(parsedTypingOptions, expectedTypingOptions);
|
||||
|
||||
|
||||
const expectedErrors = expectedResult.errors;
|
||||
assert.isTrue(expectedResult.errors.length === actualErrors.length, `Expected error: ${JSON.stringify(expectedResult.errors)}. Actual error: ${JSON.stringify(actualErrors)}.`);
|
||||
for (let i = 0; i < actualErrors.length; ++i) {
|
||||
for (let i = 0; i < actualErrors.length; i++) {
|
||||
const actualError = actualErrors[i];
|
||||
const expectedError = expectedErrors[i];
|
||||
const expectedError = expectedErrors[i];
|
||||
assert.equal(actualError.code, expectedError.code, `Expected error-code: ${JSON.stringify(expectedError.code)}. Actual error-code: ${JSON.stringify(actualError.code)}.`);
|
||||
assert.equal(actualError.category, expectedError.category, `Expected error-category: ${JSON.stringify(expectedError.category)}. Actual error-category: ${JSON.stringify(actualError.category)}.`);
|
||||
}
|
||||
@ -41,7 +41,7 @@ namespace ts {
|
||||
errors: <Diagnostic[]>[]
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it("Convert incorrect format tsconfig.json to typing-options ", () => {
|
||||
assertTypingOptions(
|
||||
{
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -3,20 +3,20 @@
|
||||
/// <reference path="..\..\..\src\compiler\parser.ts" />
|
||||
/// <reference path="..\..\..\src\harness\harness.ts" />
|
||||
|
||||
module ts {
|
||||
namespace ts {
|
||||
describe("JSDocParsing", () => {
|
||||
describe("TypeExpressions", () => {
|
||||
function parsesCorrectly(content: string, expected: string) {
|
||||
let typeAndDiagnostics = ts.parseJSDocTypeExpressionForTests(content);
|
||||
const typeAndDiagnostics = ts.parseJSDocTypeExpressionForTests(content);
|
||||
assert.isTrue(typeAndDiagnostics && typeAndDiagnostics.diagnostics.length === 0);
|
||||
|
||||
let result = Utils.sourceFileToJSON(typeAndDiagnostics.jsDocTypeExpression.type);
|
||||
const result = Utils.sourceFileToJSON(typeAndDiagnostics.jsDocTypeExpression.type);
|
||||
|
||||
assert.equal(result, expected);
|
||||
}
|
||||
|
||||
function parsesIncorrectly(content: string) {
|
||||
let type = ts.parseJSDocTypeExpressionForTests(content);
|
||||
const type = ts.parseJSDocTypeExpressionForTests(content);
|
||||
assert.isTrue(!type || type.diagnostics.length > 0);
|
||||
}
|
||||
|
||||
@ -50,7 +50,7 @@ module ts {
|
||||
"pos": 2,
|
||||
"end": 8
|
||||
}
|
||||
}`)
|
||||
}`);
|
||||
});
|
||||
|
||||
it("nullableType2", () => {
|
||||
@ -64,7 +64,7 @@ module ts {
|
||||
"pos": 1,
|
||||
"end": 7
|
||||
}
|
||||
}`)
|
||||
}`);
|
||||
});
|
||||
|
||||
it("nonNullableType", () => {
|
||||
@ -78,7 +78,7 @@ module ts {
|
||||
"pos": 2,
|
||||
"end": 8
|
||||
}
|
||||
}`)
|
||||
}`);
|
||||
});
|
||||
|
||||
it("nonNullableType2", () => {
|
||||
@ -92,7 +92,7 @@ module ts {
|
||||
"pos": 1,
|
||||
"end": 7
|
||||
}
|
||||
}`)
|
||||
}`);
|
||||
});
|
||||
|
||||
it("recordType1", () => {
|
||||
@ -106,7 +106,7 @@ module ts {
|
||||
"pos": 2,
|
||||
"end": 2
|
||||
}
|
||||
}`)
|
||||
}`);
|
||||
});
|
||||
|
||||
it("recordType2", () => {
|
||||
@ -131,7 +131,7 @@ module ts {
|
||||
"pos": 2,
|
||||
"end": 5
|
||||
}
|
||||
}`)
|
||||
}`);
|
||||
});
|
||||
|
||||
it("recordType3", () => {
|
||||
@ -161,7 +161,7 @@ module ts {
|
||||
"pos": 2,
|
||||
"end": 13
|
||||
}
|
||||
}`)
|
||||
}`);
|
||||
});
|
||||
|
||||
it("recordType4", () => {
|
||||
@ -197,7 +197,7 @@ module ts {
|
||||
"pos": 2,
|
||||
"end": 10
|
||||
}
|
||||
}`)
|
||||
}`);
|
||||
});
|
||||
|
||||
it("recordType5", () => {
|
||||
@ -238,7 +238,7 @@ module ts {
|
||||
"pos": 2,
|
||||
"end": 18
|
||||
}
|
||||
}`)
|
||||
}`);
|
||||
});
|
||||
|
||||
it("recordType6", () => {
|
||||
@ -279,7 +279,7 @@ module ts {
|
||||
"pos": 2,
|
||||
"end": 18
|
||||
}
|
||||
}`)
|
||||
}`);
|
||||
});
|
||||
|
||||
it("recordType7", () => {
|
||||
@ -325,7 +325,7 @@ module ts {
|
||||
"pos": 2,
|
||||
"end": 26
|
||||
}
|
||||
}`)
|
||||
}`);
|
||||
});
|
||||
|
||||
it("recordType8", () => {
|
||||
@ -351,7 +351,7 @@ module ts {
|
||||
"pos": 2,
|
||||
"end": 10
|
||||
}
|
||||
}`)
|
||||
}`);
|
||||
});
|
||||
|
||||
it("unionType", () => {
|
||||
@ -987,15 +987,15 @@ module ts {
|
||||
|
||||
describe("DocComments", () => {
|
||||
function parsesCorrectly(content: string, expected: string) {
|
||||
let comment = parseIsolatedJSDocComment(content);
|
||||
const comment = parseIsolatedJSDocComment(content);
|
||||
if (!comment) {
|
||||
Debug.fail('Comment failed to parse entirely');
|
||||
Debug.fail("Comment failed to parse entirely");
|
||||
}
|
||||
if (comment.diagnostics.length > 0) {
|
||||
Debug.fail('Comment has at least one diagnostic: ' + comment.diagnostics[0].messageText);
|
||||
Debug.fail("Comment has at least one diagnostic: " + comment.diagnostics[0].messageText);
|
||||
}
|
||||
|
||||
let result = JSON.stringify(comment.jsDocComment, (k, v) => {
|
||||
const result = JSON.stringify(comment.jsDocComment, (k, v) => {
|
||||
return v && v.pos !== undefined
|
||||
? JSON.parse(Utils.sourceFileToJSON(v))
|
||||
: v;
|
||||
@ -1003,8 +1003,8 @@ module ts {
|
||||
|
||||
if (result !== expected) {
|
||||
// Turn on a human-readable diff
|
||||
if (typeof require !== 'undefined') {
|
||||
require('chai').config.showDiff = true;
|
||||
if (typeof require !== "undefined") {
|
||||
require("chai").config.showDiff = true;
|
||||
chai.expect(JSON.parse(result)).equal(JSON.parse(expected));
|
||||
}
|
||||
else {
|
||||
@ -1014,7 +1014,7 @@ module ts {
|
||||
}
|
||||
|
||||
function parsesIncorrectly(content: string) {
|
||||
let type = parseIsolatedJSDocComment(content);
|
||||
const type = parseIsolatedJSDocComment(content);
|
||||
assert.isTrue(!type || type.diagnostics.length > 0);
|
||||
}
|
||||
|
||||
@ -1034,7 +1034,7 @@ module ts {
|
||||
it("multipleTypes", () => {
|
||||
parsesIncorrectly(
|
||||
`/**
|
||||
* @type {number}
|
||||
* @type {number}
|
||||
* @type {string}
|
||||
*/`);
|
||||
});
|
||||
@ -1071,7 +1071,7 @@ module ts {
|
||||
it("paramWithoutTypeOrName", () => {
|
||||
parsesIncorrectly(
|
||||
`/**
|
||||
* @param
|
||||
* @param
|
||||
*/`);
|
||||
});
|
||||
});
|
||||
@ -2218,4 +2218,4 @@ module ts {
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,32 +2,34 @@
|
||||
/// <reference path='..\..\..\src\harness\harness.ts' />
|
||||
|
||||
declare namespace chai.assert {
|
||||
/* tslint:disable no-unused-variable */
|
||||
function deepEqual(actual: any, expected: any): void;
|
||||
/* tslint:enable no-unused-variable */
|
||||
}
|
||||
|
||||
module ts {
|
||||
namespace ts {
|
||||
function diagnosticToString(diagnostic: Diagnostic) {
|
||||
let output = "";
|
||||
|
||||
if (diagnostic.file) {
|
||||
let loc = getLineAndCharacterOfPosition(diagnostic.file, diagnostic.start);
|
||||
const loc = getLineAndCharacterOfPosition(diagnostic.file, diagnostic.start);
|
||||
|
||||
output += `${diagnostic.file.fileName}(${loc.line + 1},${loc.character + 1}): `;
|
||||
}
|
||||
|
||||
let category = DiagnosticCategory[diagnostic.category].toLowerCase();
|
||||
const 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
|
||||
name: string;
|
||||
content?: string;
|
||||
}
|
||||
|
||||
function createModuleResolutionHost(hasDirectoryExists: boolean, ...files: File[]): ModuleResolutionHost {
|
||||
let map = arrayToMap(files, f => f.name);
|
||||
const map = arrayToMap(files, f => f.name);
|
||||
|
||||
if (hasDirectoryExists) {
|
||||
const directories: Map<string> = {};
|
||||
@ -35,7 +37,7 @@ module ts {
|
||||
let name = getDirectoryPath(f.name);
|
||||
while (true) {
|
||||
directories[name] = name;
|
||||
let baseName = getDirectoryPath(name);
|
||||
const baseName = getDirectoryPath(name);
|
||||
if (baseName === name) {
|
||||
break;
|
||||
}
|
||||
@ -44,14 +46,14 @@ module ts {
|
||||
}
|
||||
return {
|
||||
readFile,
|
||||
directoryExists: path => {
|
||||
return hasProperty(directories, path);
|
||||
directoryExists: path => {
|
||||
return hasProperty(directories, path);
|
||||
},
|
||||
fileExists: path => {
|
||||
assert.isTrue(hasProperty(directories, getDirectoryPath(path)), `'fileExists' '${path}' request in non-existing directory`);
|
||||
return hasProperty(map, path);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
else {
|
||||
return { readFile, fileExists: path => hasProperty(map, path), };
|
||||
@ -61,31 +63,24 @@ module ts {
|
||||
}
|
||||
}
|
||||
|
||||
function splitPath(path: string): { dir: string; rel: string } {
|
||||
let index = path.indexOf(directorySeparator);
|
||||
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 supportedTypeScriptExtensions) {
|
||||
for (const ext of supportedTypeScriptExtensions) {
|
||||
test(ext, /*hasDirectoryExists*/ false);
|
||||
test(ext, /*hasDirectoryExists*/ true);
|
||||
}
|
||||
|
||||
function test(ext: string, hasDirectoryExists: boolean) {
|
||||
let containingFile = { name: containingFileName }
|
||||
let moduleFile = { name: moduleFileNameNoExt + ext }
|
||||
let resolution = nodeModuleNameResolver(moduleName, containingFile.name, {}, createModuleResolutionHost(hasDirectoryExists, containingFile, moduleFile));
|
||||
const containingFile = { name: containingFileName };
|
||||
const moduleFile = { name: moduleFileNameNoExt + ext };
|
||||
const resolution = nodeModuleNameResolver(moduleName, containingFile.name, {}, createModuleResolutionHost(hasDirectoryExists, containingFile, moduleFile));
|
||||
assert.equal(resolution.resolvedModule.resolvedFileName, moduleFile.name);
|
||||
assert.equal(!!resolution.resolvedModule.isExternalLibraryImport, false);
|
||||
|
||||
let failedLookupLocations: string[] = [];
|
||||
let dir = getDirectoryPath(containingFileName);
|
||||
for (let e of supportedTypeScriptExtensions) {
|
||||
const failedLookupLocations: string[] = [];
|
||||
const dir = getDirectoryPath(containingFileName);
|
||||
for (const e of supportedTypeScriptExtensions) {
|
||||
if (e === ext) {
|
||||
break;
|
||||
}
|
||||
@ -120,10 +115,10 @@ module ts {
|
||||
test(/*hasDirectoryExists*/ true);
|
||||
|
||||
function test(hasDirectoryExists: boolean) {
|
||||
let containingFile = { name: containingFileName };
|
||||
let packageJson = { name: packageJsonFileName, content: JSON.stringify({ "typings": fieldRef }) };
|
||||
let moduleFile = { name: moduleFileName };
|
||||
let resolution = nodeModuleNameResolver(moduleName, containingFile.name, {}, createModuleResolutionHost(hasDirectoryExists, containingFile, packageJson, moduleFile));
|
||||
const containingFile = { name: containingFileName };
|
||||
const packageJson = { name: packageJsonFileName, content: JSON.stringify({ "typings": fieldRef }) };
|
||||
const moduleFile = { name: moduleFileName };
|
||||
const resolution = nodeModuleNameResolver(moduleName, containingFile.name, {}, createModuleResolutionHost(hasDirectoryExists, containingFile, packageJson, moduleFile));
|
||||
assert.equal(resolution.resolvedModule.resolvedFileName, moduleFile.name);
|
||||
assert.equal(!!resolution.resolvedModule.isExternalLibraryImport, false);
|
||||
// expect three failed lookup location - attempt to load module as file with all supported extensions
|
||||
@ -143,14 +138,14 @@ module ts {
|
||||
test(/*hasDirectoryExists*/ true);
|
||||
|
||||
function test(hasDirectoryExists: boolean) {
|
||||
let containingFile = { name: "/a/b.ts" };
|
||||
let packageJson = { name: "/node_modules/b/package.json", content: JSON.stringify({ "typings": typings }) };
|
||||
let moduleFile = { name: "/a/b.d.ts" };
|
||||
const containingFile = { name: "/a/b.ts" };
|
||||
const packageJson = { name: "/node_modules/b/package.json", content: JSON.stringify({ "typings": typings }) };
|
||||
const moduleFile = { name: "/a/b.d.ts" };
|
||||
|
||||
let indexPath = "/node_modules/b/index.d.ts";
|
||||
let indexFile = { name: indexPath }
|
||||
const indexPath = "/node_modules/b/index.d.ts";
|
||||
const indexFile = { name: indexPath };
|
||||
|
||||
let resolution = nodeModuleNameResolver("b", containingFile.name, {}, createModuleResolutionHost(hasDirectoryExists, containingFile, packageJson, moduleFile, indexFile));
|
||||
const resolution = nodeModuleNameResolver("b", containingFile.name, {}, createModuleResolutionHost(hasDirectoryExists, containingFile, packageJson, moduleFile, indexFile));
|
||||
|
||||
assert.equal(resolution.resolvedModule.resolvedFileName, indexPath);
|
||||
}
|
||||
@ -160,7 +155,9 @@ module ts {
|
||||
testTypingsIgnored(["a", "b"]);
|
||||
testTypingsIgnored({ "a": "b" });
|
||||
testTypingsIgnored(true);
|
||||
/* tslint:disable no-null-keyword */
|
||||
testTypingsIgnored(null);
|
||||
/* tslint:enable no-null-keyword */
|
||||
testTypingsIgnored(undefined);
|
||||
});
|
||||
|
||||
@ -169,10 +166,10 @@ module ts {
|
||||
test(/*hasDirectoryExists*/ true);
|
||||
|
||||
function test(hasDirectoryExists: boolean) {
|
||||
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(hasDirectoryExists, containingFile, packageJson, indexFile));
|
||||
const containingFile = { name: "/a/b/c.ts" };
|
||||
const packageJson = { name: "/a/b/foo/package.json", content: JSON.stringify({ main: "/c/d" }) };
|
||||
const indexFile = { name: "/a/b/foo/index.d.ts" };
|
||||
const resolution = nodeModuleNameResolver("./foo", containingFile.name, {}, createModuleResolutionHost(hasDirectoryExists, containingFile, packageJson, indexFile));
|
||||
assert.equal(resolution.resolvedModule.resolvedFileName, indexFile.name);
|
||||
assert.equal(!!resolution.resolvedModule.isExternalLibraryImport, false);
|
||||
assert.deepEqual(resolution.failedLookupLocations, [
|
||||
@ -192,9 +189,9 @@ module ts {
|
||||
test(/*hasDirectoryExists*/ true);
|
||||
|
||||
function test(hasDirectoryExists: boolean) {
|
||||
let containingFile = { name: "/a/b/c/d/e.ts" };
|
||||
let moduleFile = { name: "/a/b/node_modules/foo.ts" };
|
||||
let resolution = nodeModuleNameResolver("foo", containingFile.name, {}, createModuleResolutionHost(hasDirectoryExists, containingFile, moduleFile));
|
||||
const containingFile = { name: "/a/b/c/d/e.ts" };
|
||||
const moduleFile = { name: "/a/b/node_modules/foo.ts" };
|
||||
const resolution = nodeModuleNameResolver("foo", containingFile.name, {}, createModuleResolutionHost(hasDirectoryExists, containingFile, moduleFile));
|
||||
assert.equal(resolution.resolvedModule.resolvedFileName, moduleFile.name);
|
||||
assert.deepEqual(resolution.failedLookupLocations, [
|
||||
"/a/b/c/d/node_modules/foo.ts",
|
||||
@ -225,7 +222,7 @@ module ts {
|
||||
"/a/b/c/node_modules/@types/foo/index.ts",
|
||||
"/a/b/c/node_modules/@types/foo/index.tsx",
|
||||
"/a/b/c/node_modules/@types/foo/index.d.ts",
|
||||
])
|
||||
]);
|
||||
}
|
||||
});
|
||||
|
||||
@ -234,9 +231,9 @@ module ts {
|
||||
test(/*hasDirectoryExists*/ true);
|
||||
|
||||
function test(hasDirectoryExists: boolean) {
|
||||
let containingFile = { name: "/a/b/c/d/e.ts" };
|
||||
let moduleFile = { name: "/a/b/node_modules/foo.d.ts" };
|
||||
let resolution = nodeModuleNameResolver("foo", containingFile.name, {}, createModuleResolutionHost(hasDirectoryExists, containingFile, moduleFile));
|
||||
const containingFile = { name: "/a/b/c/d/e.ts" };
|
||||
const moduleFile = { name: "/a/b/node_modules/foo.d.ts" };
|
||||
const resolution = nodeModuleNameResolver("foo", containingFile.name, {}, createModuleResolutionHost(hasDirectoryExists, containingFile, moduleFile));
|
||||
assert.equal(resolution.resolvedModule.resolvedFileName, moduleFile.name);
|
||||
assert.equal(resolution.resolvedModule.isExternalLibraryImport, true);
|
||||
}
|
||||
@ -247,9 +244,9 @@ module ts {
|
||||
test(/*hasDirectoryExists*/ true);
|
||||
|
||||
function test(hasDirectoryExists: boolean) {
|
||||
let containingFile = { name: "/a/node_modules/b/c/node_modules/d/e.ts" };
|
||||
let moduleFile = { name: "/a/node_modules/foo/index.d.ts" };
|
||||
let resolution = nodeModuleNameResolver("foo", containingFile.name, {}, createModuleResolutionHost(hasDirectoryExists, containingFile, moduleFile));
|
||||
const containingFile = { name: "/a/node_modules/b/c/node_modules/d/e.ts" };
|
||||
const moduleFile = { name: "/a/node_modules/foo/index.d.ts" };
|
||||
const resolution = nodeModuleNameResolver("foo", containingFile.name, {}, createModuleResolutionHost(hasDirectoryExists, containingFile, moduleFile));
|
||||
assert.equal(resolution.resolvedModule.resolvedFileName, moduleFile.name);
|
||||
assert.equal(resolution.resolvedModule.isExternalLibraryImport, true);
|
||||
assert.deepEqual(resolution.failedLookupLocations, [
|
||||
@ -311,7 +308,7 @@ module ts {
|
||||
const options: CompilerOptions = { module: ModuleKind.CommonJS };
|
||||
const host: CompilerHost = {
|
||||
getSourceFile: (fileName: string, languageVersion: ScriptTarget) => {
|
||||
let path = normalizePath(combinePaths(currentDirectory, fileName));
|
||||
const path = normalizePath(combinePaths(currentDirectory, fileName));
|
||||
return hasProperty(files, path) ? createSourceFile(fileName, files[path], languageVersion) : undefined;
|
||||
},
|
||||
getDefaultLibFileName: () => "lib.d.ts",
|
||||
@ -321,7 +318,7 @@ module ts {
|
||||
getNewLine: () => "\r\n",
|
||||
useCaseSensitiveFileNames: () => false,
|
||||
fileExists: fileName => {
|
||||
let path = normalizePath(combinePaths(currentDirectory, fileName));
|
||||
const path = normalizePath(combinePaths(currentDirectory, fileName));
|
||||
return hasProperty(files, path);
|
||||
},
|
||||
readFile: (fileName): string => { throw new Error("NotImplemented"); }
|
||||
@ -359,13 +356,13 @@ 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, []);
|
||||
test(files, "/parent/app", ["myapp.ts"], 2, []);
|
||||
});
|
||||
|
||||
it("should find file referenced via absolute and relative names", () => {
|
||||
@ -376,14 +373,14 @@ export = C;
|
||||
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) {
|
||||
const f: Map<string> = {};
|
||||
for (const fileName in files) {
|
||||
f[getCanonicalFileName(fileName)] = files[fileName];
|
||||
}
|
||||
files = f;
|
||||
@ -394,7 +391,7 @@ export = C;
|
||||
if (fileName === "lib.d.ts") {
|
||||
return library;
|
||||
}
|
||||
let path = getCanonicalFileName(normalizePath(combinePaths(currentDirectory, fileName)));
|
||||
const path = getCanonicalFileName(normalizePath(combinePaths(currentDirectory, fileName)));
|
||||
return hasProperty(files, path) ? createSourceFile(fileName, files[path], languageVersion) : undefined;
|
||||
},
|
||||
getDefaultLibFileName: () => "lib.d.ts",
|
||||
@ -404,7 +401,7 @@ export = C;
|
||||
getNewLine: () => "\r\n",
|
||||
useCaseSensitiveFileNames: () => useCaseSensitiveFileNames,
|
||||
fileExists: fileName => {
|
||||
let path = getCanonicalFileName(normalizePath(combinePaths(currentDirectory, fileName)));
|
||||
const path = getCanonicalFileName(normalizePath(combinePaths(currentDirectory, fileName)));
|
||||
return hasProperty(files, path);
|
||||
},
|
||||
readFile: (fileName): string => { throw new Error("NotImplemented"); }
|
||||
@ -412,7 +409,7 @@ export = C;
|
||||
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) {
|
||||
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}'`);
|
||||
}
|
||||
}
|
||||
@ -422,7 +419,7 @@ export = C;
|
||||
"/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"], []);
|
||||
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)", () => {
|
||||
@ -430,7 +427,7 @@ export = C;
|
||||
"/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]);
|
||||
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)", () => {
|
||||
@ -438,7 +435,7 @@ export = C;
|
||||
"/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]);
|
||||
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)", () => {
|
||||
@ -446,7 +443,7 @@ export = C;
|
||||
"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]);
|
||||
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", () => {
|
||||
@ -455,7 +452,7 @@ export = C;
|
||||
"/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]);
|
||||
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", () => {
|
||||
@ -464,7 +461,7 @@ export = C;
|
||||
"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]);
|
||||
test(files, { module: ts.ModuleKind.CommonJS, forceConsistentCasingInFileNames: true }, "", /*useCaseSensitiveFileNames*/ false, ["moduleA.ts", "moduleB.ts", "moduleC.ts"], [1149, 1149]);
|
||||
});
|
||||
|
||||
it("should fail when module names in 'require' calls has inconsistent casing and current directory has uppercase chars", () => {
|
||||
@ -477,7 +474,7 @@ import a = require("./moduleA.ts");
|
||||
import b = require("./moduleB.ts");
|
||||
`
|
||||
};
|
||||
test(files, { module: ts.ModuleKind.CommonJS, forceConsistentCasingInFileNames: true }, "/a/B/c", /* useCaseSensitiveFileNames */ false, ["moduleD.ts"], [1149]);
|
||||
test(files, { module: ts.ModuleKind.CommonJS, forceConsistentCasingInFileNames: true }, "/a/B/c", /*useCaseSensitiveFileNames*/ false, ["moduleD.ts"], [1149]);
|
||||
});
|
||||
it("should not fail when module names in 'require' calls has consistent casing and current directory has uppercase chars", () => {
|
||||
const files: Map<string> = {
|
||||
@ -489,8 +486,8 @@ import a = require("./moduleA.ts");
|
||||
import b = require("./moduleB.ts");
|
||||
`
|
||||
};
|
||||
test(files, { module: ts.ModuleKind.CommonJS, forceConsistentCasingInFileNames: true }, "/a/B/c", /* useCaseSensitiveFileNames */ false, ["moduleD.ts"], []);
|
||||
})
|
||||
test(files, { module: ts.ModuleKind.CommonJS, forceConsistentCasingInFileNames: true }, "/a/B/c", /*useCaseSensitiveFileNames*/ false, ["moduleD.ts"], []);
|
||||
});
|
||||
});
|
||||
|
||||
describe("baseUrl augmented module resolution", () => {
|
||||
@ -528,7 +525,7 @@ import b = require("./moduleB.ts");
|
||||
}
|
||||
// add failure tests
|
||||
});
|
||||
|
||||
|
||||
it("node + baseUrl", () => {
|
||||
test(/*hasDirectoryExists*/ false);
|
||||
test(/*hasDirectoryExists*/ true);
|
||||
@ -538,7 +535,7 @@ import b = require("./moduleB.ts");
|
||||
const m1: File = { name: "/root/m1.ts" }; // load file as module
|
||||
const m2: File = { name: "/root/m2/index.d.ts" }; // load folder as module
|
||||
const m3: File = { name: "/root/m3/package.json", content: JSON.stringify({ typings: "dist/typings.d.ts" }) };
|
||||
const m3Typings: File = { name: "/root/m3/dist/typings.d.ts" };
|
||||
const m3Typings: File = { name: "/root/m3/dist/typings.d.ts" };
|
||||
const m4: File = { name: "/root/node_modules/m4.ts" }; // fallback to node
|
||||
|
||||
const options: CompilerOptions = { moduleResolution: ModuleResolutionKind.NodeJs, baseUrl: "/root" };
|
||||
@ -548,13 +545,13 @@ import b = require("./moduleB.ts");
|
||||
check("m2", main, m2);
|
||||
check("m3", main, m3Typings);
|
||||
check("m4", main, m4);
|
||||
|
||||
|
||||
function check(name: string, caller: File, expected: File) {
|
||||
const result = resolveModuleName(name, caller.name, options, host);
|
||||
assert.isTrue(result.resolvedModule !== undefined);
|
||||
assert.equal(result.resolvedModule.resolvedFileName, expected.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it("classic + baseUrl", () => {
|
||||
@ -571,14 +568,14 @@ import b = require("./moduleB.ts");
|
||||
|
||||
check("m1", main, m1);
|
||||
check("m2", main, m2);
|
||||
|
||||
|
||||
function check(name: string, caller: File, expected: File) {
|
||||
const result = resolveModuleName(name, caller.name, options, host);
|
||||
assert.isTrue(result.resolvedModule !== undefined);
|
||||
assert.equal(result.resolvedModule.resolvedFileName, expected.name);
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
it("node + baseUrl + path mappings", () => {
|
||||
test(/*hasDirectoryExists*/ false);
|
||||
@ -586,16 +583,16 @@ import b = require("./moduleB.ts");
|
||||
|
||||
function test(hasDirectoryExists: boolean) {
|
||||
const main: File = { name: "/root/folder1/main.ts" };
|
||||
|
||||
|
||||
const file1: File = { name: "/root/folder1/file1.ts" };
|
||||
const file2: File = { name: "/root/generated/folder1/file2.ts" } // load remapped file as module
|
||||
const file3: File = { name: "/root/generated/folder2/file3/index.d.ts" } // load folder a module
|
||||
const file2: File = { name: "/root/generated/folder1/file2.ts" }; // load remapped file as module
|
||||
const file3: File = { name: "/root/generated/folder2/file3/index.d.ts" }; // load folder a module
|
||||
const file4Typings: File = { name: "/root/generated/folder2/file4/package.json", content: JSON.stringify({ typings: "dist/types.d.ts" })};
|
||||
const file4: File = { name: "/root/generated/folder2/file4/dist/types.d.ts" }; // load file pointed by typings
|
||||
const file5: File = { name: "/root/someanotherfolder/file5/index.d.ts" } // load remapped module from folder
|
||||
const file5: File = { name: "/root/someanotherfolder/file5/index.d.ts" }; // load remapped module from folder
|
||||
const file6: File = { name: "/root/node_modules/file6.ts" }; // fallback to node
|
||||
const host = createModuleResolutionHost(hasDirectoryExists, file1, file2, file3, file4, file4Typings, file5, file6);
|
||||
|
||||
|
||||
const options: CompilerOptions = {
|
||||
moduleResolution: ModuleResolutionKind.NodeJs,
|
||||
baseUrl: "/root",
|
||||
@ -723,12 +720,12 @@ import b = require("./moduleB.ts");
|
||||
|
||||
function test(hasDirectoryExists: boolean) {
|
||||
const main: File = { name: "/root/folder1/main.ts" };
|
||||
|
||||
|
||||
const file1: File = { name: "/root/folder1/file1.ts" };
|
||||
const file2: File = { name: "/root/generated/folder1/file2.ts" };
|
||||
const file3: File = { name: "/folder1/file3.ts" }; // fallback to classic
|
||||
const host = createModuleResolutionHost(hasDirectoryExists, file1, file2, file3);
|
||||
|
||||
|
||||
const options: CompilerOptions = {
|
||||
moduleResolution: ModuleResolutionKind.Classic,
|
||||
baseUrl: "/root",
|
||||
@ -776,17 +773,17 @@ import b = require("./moduleB.ts");
|
||||
assert.deepEqual(result.failedLookupLocations, expectedFailedLookups);
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
it ("node + rootDirs", () => {
|
||||
test(/*hasDirectoryExists*/ false);
|
||||
test(/*hasDirectoryExists*/ true);
|
||||
|
||||
function test(hasDirectoryExists: boolean) {
|
||||
let file1: File = { name: "/root/folder1/file1.ts" };
|
||||
let file1_1: File = { name: "/root/folder1/file1_1/index.d.ts" };
|
||||
let file2: File = { name: "/root/generated/folder1/file2.ts" };
|
||||
let file3: File = { name: "/root/generated/folder2/file3.ts" };
|
||||
const file1: File = { name: "/root/folder1/file1.ts" };
|
||||
const file1_1: File = { name: "/root/folder1/file1_1/index.d.ts" };
|
||||
const file2: File = { name: "/root/generated/folder1/file2.ts" };
|
||||
const file3: File = { name: "/root/generated/folder2/file3.ts" };
|
||||
const host = createModuleResolutionHost(hasDirectoryExists, file1, file1_1, file2, file3);
|
||||
const options: CompilerOptions = {
|
||||
moduleResolution: ModuleResolutionKind.NodeJs,
|
||||
@ -848,7 +845,7 @@ import b = require("./moduleB.ts");
|
||||
const result = resolveModuleName(name, container.name, options, host);
|
||||
assert.isTrue(result.resolvedModule !== undefined, "module should be resolved");
|
||||
assert.equal(result.resolvedModule.resolvedFileName, expected.name);
|
||||
assert.deepEqual(result.failedLookupLocations,expectedFailedLookups);
|
||||
assert.deepEqual(result.failedLookupLocations, expectedFailedLookups);
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -857,10 +854,10 @@ import b = require("./moduleB.ts");
|
||||
test(/*hasDirectoryExists*/ false);
|
||||
|
||||
function test(hasDirectoryExists: boolean) {
|
||||
let file1: File = { name: "/root/folder1/file1.ts" };
|
||||
let file2: File = { name: "/root/generated/folder1/file2.ts" };
|
||||
let file3: File = { name: "/root/generated/folder2/file3.ts" };
|
||||
let file4: File = { name: "/folder1/file1_1.ts" };
|
||||
const file1: File = { name: "/root/folder1/file1.ts" };
|
||||
const file2: File = { name: "/root/generated/folder1/file2.ts" };
|
||||
const file3: File = { name: "/root/generated/folder2/file3.ts" };
|
||||
const file4: File = { name: "/folder1/file1_1.ts" };
|
||||
const host = createModuleResolutionHost(hasDirectoryExists, file1, file2, file3, file4);
|
||||
const options: CompilerOptions = {
|
||||
moduleResolution: ModuleResolutionKind.Classic,
|
||||
@ -904,7 +901,7 @@ import b = require("./moduleB.ts");
|
||||
const result = resolveModuleName(name, container.name, options, host);
|
||||
assert.isTrue(result.resolvedModule !== undefined, "module should be resolved");
|
||||
assert.equal(result.resolvedModule.resolvedFileName, expected.name);
|
||||
assert.deepEqual(result.failedLookupLocations,expectedFailedLookups);
|
||||
assert.deepEqual(result.failedLookupLocations, expectedFailedLookups);
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -914,12 +911,12 @@ import b = require("./moduleB.ts");
|
||||
test(/*hasDirectoryExists*/ true);
|
||||
|
||||
function test(hasDirectoryExists: boolean) {
|
||||
const app: File = { name: "/root/src/app.ts" }
|
||||
const app: File = { name: "/root/src/app.ts" };
|
||||
const libsPackage: File = { name: "/root/src/libs/guid/package.json", content: JSON.stringify({ typings: "dist/guid.d.ts" }) };
|
||||
const libsTypings: File = { name: "/root/src/libs/guid/dist/guid.d.ts" };
|
||||
const host = createModuleResolutionHost(hasDirectoryExists, app, libsPackage, libsTypings);
|
||||
const options: CompilerOptions = {
|
||||
moduleResolution: ModuleResolutionKind.NodeJs,
|
||||
const options: CompilerOptions = {
|
||||
moduleResolution: ModuleResolutionKind.NodeJs,
|
||||
baseUrl: "/root",
|
||||
paths: {
|
||||
"libs/guid": [ "src/libs/guid" ]
|
||||
@ -935,7 +932,7 @@ import b = require("./moduleB.ts");
|
||||
"/root/src/libs/guid.d.ts",
|
||||
]);
|
||||
}
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
function notImplemented(name: string): () => any {
|
||||
@ -957,7 +954,7 @@ import b = require("./moduleB.ts");
|
||||
|
||||
describe("Type reference directive resolution: ", () => {
|
||||
function test(typesRoot: string, typeDirective: string, primary: boolean, initialFile: File, targetFile: File, ...otherFiles: File[]) {
|
||||
const host = createModuleResolutionHost(false, ...[initialFile, targetFile].concat(...otherFiles));
|
||||
const host = createModuleResolutionHost(/*hasDirectoryExists*/ false, ...[initialFile, targetFile].concat(...otherFiles));
|
||||
const result = resolveTypeReferenceDirective(typeDirective, initialFile.name, {typesRoot}, host);
|
||||
assert(result.resolvedTypeReferenceDirective.resolvedFileName !== undefined, "expected type directive to be resolved");
|
||||
assert.equal(result.resolvedTypeReferenceDirective.resolvedFileName, targetFile.name, "unexpected result of type reference resolution");
|
||||
@ -966,63 +963,63 @@ import b = require("./moduleB.ts");
|
||||
|
||||
it("Can be resolved from primary location", () => {
|
||||
{
|
||||
const f1 = { name: "/root/src/app.ts" }
|
||||
const f2 = { name: "/root/src/types/lib/index.d.ts" };
|
||||
const f1 = { name: "/root/src/app.ts" };
|
||||
const f2 = { name: "/root/src/types/lib/index.d.ts" };
|
||||
test(/*typesRoot*/"/root/src", /* typeDirective */"lib", /*primary*/ true, f1, f2);
|
||||
}
|
||||
{
|
||||
const f1 = { name: "/root/src/app.ts" }
|
||||
const f1 = { name: "/root/src/app.ts" };
|
||||
const f2 = { name: "/root/src/types/lib/typings/lib.d.ts" };
|
||||
const package = { name: "/root/src/types/lib/package.json", content: JSON.stringify({types: "typings/lib.d.ts"}) };
|
||||
const package = { name: "/root/src/types/lib/package.json", content: JSON.stringify({types: "typings/lib.d.ts"}) };
|
||||
test(/*typesRoot*/"/root/src", /* typeDirective */"lib", /*primary*/ true, f1, f2, package);
|
||||
}
|
||||
{
|
||||
const f1 = { name: "/root/src/app.ts" }
|
||||
const f2 = { name: "/root/src/node_modules/lib/index.d.ts" };
|
||||
const f1 = { name: "/root/src/app.ts" };
|
||||
const f2 = { name: "/root/src/node_modules/lib/index.d.ts" };
|
||||
test(/*typesRoot*/"/root/src", /* typeDirective */"lib", /*primary*/ true, f1, f2);
|
||||
}
|
||||
{
|
||||
const f1 = { name: "/root/src/app.ts" }
|
||||
const f1 = { name: "/root/src/app.ts" };
|
||||
const f2 = { name: "/root/src/node_modules/lib/typings/lib.d.ts" };
|
||||
const package = { name: "/root/src/node_modules/lib/package.json", content: JSON.stringify({types: "typings/lib.d.ts"}) };
|
||||
const package = { name: "/root/src/node_modules/lib/package.json", content: JSON.stringify({types: "typings/lib.d.ts"}) };
|
||||
test(/*typesRoot*/"/root/src", /* typeDirective */"lib", /*primary*/ true, f1, f2, package);
|
||||
}
|
||||
{
|
||||
const f1 = { name: "/root/src/app.ts" }
|
||||
const f2 = { name: "/root/src/node_modules/@types/lib/index.d.ts" };
|
||||
const f1 = { name: "/root/src/app.ts" };
|
||||
const f2 = { name: "/root/src/node_modules/@types/lib/index.d.ts" };
|
||||
test(/*typesRoot*/"/root/src", /* typeDirective */"lib", /*primary*/ true, f1, f2);
|
||||
}
|
||||
{
|
||||
const f1 = { name: "/root/src/app.ts" }
|
||||
const f1 = { name: "/root/src/app.ts" };
|
||||
const f2 = { name: "/root/src/node_modules/@types/lib/typings/lib.d.ts" };
|
||||
const package = { name: "/root/src/node_modules/@types/lib/package.json", content: JSON.stringify({types: "typings/lib.d.ts"}) };
|
||||
const package = { name: "/root/src/node_modules/@types/lib/package.json", content: JSON.stringify({types: "typings/lib.d.ts"}) };
|
||||
test(/*typesRoot*/"/root/src", /* typeDirective */"lib", /*primary*/ true, f1, f2, package);
|
||||
}
|
||||
});
|
||||
it("Can be resolved from secondary location", () => {
|
||||
{
|
||||
const f1 = { name: "/root/src/app.ts" }
|
||||
const f1 = { name: "/root/src/app.ts" };
|
||||
const f2 = { name: "/root/node_modules/lib.d.ts" };
|
||||
test(/*typesRoot*/"/root/src", /* typeDirective */"lib", /*primary*/ false, f1, f2);
|
||||
}
|
||||
{
|
||||
const f1 = { name: "/root/src/app.ts" }
|
||||
const f1 = { name: "/root/src/app.ts" };
|
||||
const f2 = { name: "/root/node_modules/lib/index.d.ts" };
|
||||
test(/*typesRoot*/"/root/src", /* typeDirective */"lib", /*primary*/ false, f1, f2);
|
||||
}
|
||||
{
|
||||
const f1 = { name: "/root/src/app.ts" }
|
||||
const f1 = { name: "/root/src/app.ts" };
|
||||
const f2 = { name: "/root/node_modules/lib/typings/lib.d.ts" };
|
||||
const package = { name: "/root/node_modules/lib/package.json", content: JSON.stringify({typings: "typings/lib.d.ts"}) };
|
||||
test(/*typesRoot*/"/root/src", /* typeDirective */"lib", /*primary*/ false, f1, f2, package);
|
||||
}
|
||||
{
|
||||
const f1 = { name: "/root/src/app.ts" }
|
||||
const f1 = { name: "/root/src/app.ts" };
|
||||
const f2 = { name: "/root/node_modules/@types/lib/index.d.ts" };
|
||||
test(/*typesRoot*/"/root/src", /* typeDirective */"lib", /*primary*/ false, f1, f2);
|
||||
}
|
||||
{
|
||||
const f1 = { name: "/root/src/app.ts" }
|
||||
const f1 = { name: "/root/src/app.ts" };
|
||||
const f2 = { name: "/root/node_modules/@types/lib/typings/lib.d.ts" };
|
||||
const package = { name: "/root/node_modules/@types/lib/package.json", content: JSON.stringify({typings: "typings/lib.d.ts"}) };
|
||||
test(/*typesRoot*/"/root/src", /* typeDirective */"lib", /*primary*/ false, f1, f2, package);
|
||||
@ -1032,17 +1029,17 @@ import b = require("./moduleB.ts");
|
||||
{
|
||||
const f1 = { name: "/root/src/a/b/c/app.ts" };
|
||||
const f2 = { name: "/root/src/types/lib/index.d.ts" };
|
||||
const f3 = { name: "/root/src/a/b/node_modules/lib.d.ts" }
|
||||
const f3 = { name: "/root/src/a/b/node_modules/lib.d.ts" };
|
||||
test(/*typesRoot*/"/root/src", /* typeDirective */"lib", /*primary*/ true, f1, f2, f3);
|
||||
}
|
||||
})
|
||||
});
|
||||
it("Reused program keeps errors", () => {
|
||||
const f1 = { name: "/root/src/a/b/c/d/e/app.ts", content: `/// <reference types="lib"/>` };
|
||||
const f2 = { name: "/root/src/a/b/c/d/node_modules/lib/index.d.ts", content: `declare var x: number;` };
|
||||
const f3 = { name: "/root/src/a/b/c/d/f/g/app.ts", content: `/// <reference types="lib"/>` };
|
||||
const f4 = { name: "/root/src/a/b/c/d/f/node_modules/lib/index.d.ts", content: `declare var x: number;` };
|
||||
const files = [f1, f2, f3, f4];
|
||||
|
||||
|
||||
const names = map(files, f => f.name);
|
||||
const sourceFiles = arrayToMap(map(files, f => createSourceFile(f.name, f.content, ScriptTarget.ES6)), f => f.fileName);
|
||||
const compilerHost: CompilerHost = {
|
||||
@ -1062,11 +1059,13 @@ import b = require("./moduleB.ts");
|
||||
const diagnostics1 = program1.getFileProcessingDiagnostics().getDiagnostics();
|
||||
assert.equal(diagnostics1.length, 1, "expected one diagnostic");
|
||||
|
||||
/* tslint:disable no-unused-variable */
|
||||
const program2 = createProgram(names, {}, compilerHost, program1);
|
||||
/* tslint:enable no-unused-variable */
|
||||
assert.isTrue(program1.structureIsReused);
|
||||
const diagnostics2 = program1.getFileProcessingDiagnostics().getDiagnostics();
|
||||
assert.equal(diagnostics2.length, 1, "expected one diagnostic");
|
||||
assert.equal(diagnostics1[0].messageText, diagnostics2[0].messageText, "expected one diagnostic");
|
||||
})
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
/// <reference path='..\..\..\src\harness\harness.ts' />
|
||||
/// <reference path="..\..\..\src\harness\harnessLanguageService.ts" />
|
||||
|
||||
module ts {
|
||||
namespace ts {
|
||||
|
||||
const enum ChangedPart {
|
||||
references = 1 << 0,
|
||||
@ -10,7 +10,7 @@ module ts {
|
||||
program = 1 << 2
|
||||
}
|
||||
|
||||
let newLine = "\r\n";
|
||||
const newLine = "\r\n";
|
||||
|
||||
interface SourceFileWithText extends SourceFile {
|
||||
sourceText?: SourceText;
|
||||
@ -18,7 +18,7 @@ module ts {
|
||||
|
||||
interface NamedSourceText {
|
||||
name: string;
|
||||
text: SourceText
|
||||
text: SourceText;
|
||||
}
|
||||
|
||||
interface ProgramWithSourceTexts extends Program {
|
||||
@ -72,9 +72,9 @@ module ts {
|
||||
}
|
||||
|
||||
getChangeRange(oldSnapshot: IScriptSnapshot): TextChangeRange {
|
||||
var oldText = <SourceText>oldSnapshot;
|
||||
var oldSpan: TextSpan;
|
||||
var newLength: number;
|
||||
const oldText = <SourceText>oldSnapshot;
|
||||
let oldSpan: TextSpan;
|
||||
let newLength: number;
|
||||
switch (oldText.changedPart ^ this.changedPart) {
|
||||
case ChangedPart.references:
|
||||
oldSpan = createTextSpan(0, oldText.references.length);
|
||||
@ -82,7 +82,7 @@ module ts {
|
||||
break;
|
||||
case ChangedPart.importsAndExports:
|
||||
oldSpan = createTextSpan(oldText.references.length, oldText.importsAndExports.length);
|
||||
newLength = this.importsAndExports.length
|
||||
newLength = this.importsAndExports.length;
|
||||
break;
|
||||
case ChangedPart.program:
|
||||
oldSpan = createTextSpan(oldText.references.length + oldText.importsAndExports.length, oldText.program.length);
|
||||
@ -97,19 +97,19 @@ module ts {
|
||||
}
|
||||
|
||||
function createTestCompilerHost(texts: NamedSourceText[], target: ScriptTarget): CompilerHost {
|
||||
let files: Map<SourceFileWithText> = {};
|
||||
for (let t of texts) {
|
||||
let file = <SourceFileWithText>createSourceFile(t.name, t.text.getFullText(), target);
|
||||
const files: Map<SourceFileWithText> = {};
|
||||
for (const t of texts) {
|
||||
const file = <SourceFileWithText>createSourceFile(t.name, t.text.getFullText(), target);
|
||||
file.sourceText = t.text;
|
||||
files[t.name] = file;
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
getSourceFile(fileName): SourceFile {
|
||||
return files[fileName];
|
||||
},
|
||||
getDefaultLibFileName(): string {
|
||||
return "lib.d.ts"
|
||||
return "lib.d.ts";
|
||||
},
|
||||
writeFile(file, text) {
|
||||
throw new Error("NYI");
|
||||
@ -128,31 +128,31 @@ module ts {
|
||||
},
|
||||
fileExists: fileName => hasProperty(files, fileName),
|
||||
readFile: fileName => {
|
||||
let file = lookUp(files, fileName);
|
||||
const file = lookUp(files, fileName);
|
||||
return file && file.text;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function newProgram(texts: NamedSourceText[], rootNames: string[], options: CompilerOptions): Program {
|
||||
var host = createTestCompilerHost(texts, options.target);
|
||||
let program = <ProgramWithSourceTexts>createProgram(rootNames, options, host);
|
||||
const host = createTestCompilerHost(texts, options.target);
|
||||
const program = <ProgramWithSourceTexts>createProgram(rootNames, options, host);
|
||||
program.sourceTexts = texts;
|
||||
return program;
|
||||
}
|
||||
|
||||
function updateProgram(oldProgram: Program, rootNames: string[], options: CompilerOptions, updater: (files: NamedSourceText[]) => void) {
|
||||
var texts: NamedSourceText[] = (<ProgramWithSourceTexts>oldProgram).sourceTexts.slice(0);
|
||||
const texts: NamedSourceText[] = (<ProgramWithSourceTexts>oldProgram).sourceTexts.slice(0);
|
||||
updater(texts);
|
||||
var host = createTestCompilerHost(texts, options.target);
|
||||
var program = <ProgramWithSourceTexts>createProgram(rootNames, options, host, oldProgram);
|
||||
const host = createTestCompilerHost(texts, options.target);
|
||||
const program = <ProgramWithSourceTexts>createProgram(rootNames, options, host, oldProgram);
|
||||
program.sourceTexts = texts;
|
||||
return program;
|
||||
}
|
||||
|
||||
function getSizeOfMap(map: Map<any>): number {
|
||||
let size = 0;
|
||||
for (let id in map) {
|
||||
for (const id in map) {
|
||||
if (hasProperty(map, id)) {
|
||||
size++;
|
||||
}
|
||||
@ -172,20 +172,20 @@ module ts {
|
||||
assert.isTrue(expected.primary === actual.primary, `'primary': expected '${expected.primary}' to be equal to '${actual.primary}'`);
|
||||
}
|
||||
|
||||
function checkCache<T>(caption: string, program: Program, fileName: string, expectedContent: Map<T>, getCache: (f: SourceFile) => Map<T>, entryChecker: (expected: T, original:T) => void): void {
|
||||
let file = program.getSourceFile(fileName);
|
||||
function checkCache<T>(caption: string, program: Program, fileName: string, expectedContent: Map<T>, getCache: (f: SourceFile) => Map<T>, entryChecker: (expected: T, original: T) => void): void {
|
||||
const file = program.getSourceFile(fileName);
|
||||
assert.isTrue(file !== undefined, `cannot find file ${fileName}`);
|
||||
const cache = getCache(file)
|
||||
const cache = getCache(file);
|
||||
if (expectedContent === undefined) {
|
||||
assert.isTrue(cache === undefined, `expected ${caption} to be undefined`);
|
||||
}
|
||||
else {
|
||||
assert.isTrue(cache !== undefined, `expected ${caption} to be set`);
|
||||
let actualCacheSize = getSizeOfMap(cache);
|
||||
let expectedSize = getSizeOfMap(expectedContent);
|
||||
const actualCacheSize = getSizeOfMap(cache);
|
||||
const expectedSize = getSizeOfMap(expectedContent);
|
||||
assert.isTrue(actualCacheSize === expectedSize, `expected actual size: ${actualCacheSize} to be equal to ${expectedSize}`);
|
||||
|
||||
for (let id in expectedContent) {
|
||||
for (const id in expectedContent) {
|
||||
if (hasProperty(expectedContent, id)) {
|
||||
|
||||
if (expectedContent[id]) {
|
||||
@ -210,45 +210,46 @@ module ts {
|
||||
}
|
||||
|
||||
describe("Reuse program structure", () => {
|
||||
let target = ScriptTarget.Latest;
|
||||
let files = [
|
||||
/* tslint:disable no-unused-variable */
|
||||
const target = ScriptTarget.Latest;
|
||||
const files = [
|
||||
{ name: "a.ts", text: SourceText.New(
|
||||
`
|
||||
/// <reference path='b.ts'/>
|
||||
/// <reference path='non-existing-file.ts'/>
|
||||
/// <reference types="typerefs" />
|
||||
`, "",`var x = 1`) },
|
||||
`, "", `var x = 1`) },
|
||||
{ name: "b.ts", text: SourceText.New(`/// <reference path='c.ts'/>`, "", `var y = 2`) },
|
||||
{ name: "c.ts", text: SourceText.New("", "", `var z = 1;`) },
|
||||
{ name: "types/typerefs/index.d.ts", text: SourceText.New("", "", `declare let z: number;`) },
|
||||
]
|
||||
];
|
||||
|
||||
it("successful if change does not affect imports", () => {
|
||||
var program_1 = newProgram(files, ["a.ts"], { target });
|
||||
var program_2 = updateProgram(program_1, ["a.ts"], { target }, files => {
|
||||
const program_1 = newProgram(files, ["a.ts"], { target });
|
||||
const program_2 = updateProgram(program_1, ["a.ts"], { target }, files => {
|
||||
files[0].text = files[0].text.updateProgram("var x = 100");
|
||||
});
|
||||
assert.isTrue(program_1.structureIsReused);
|
||||
let program1Diagnostics = program_1.getSemanticDiagnostics(program_1.getSourceFile("a.ts"))
|
||||
let program2Diagnostics = program_2.getSemanticDiagnostics(program_1.getSourceFile("a.ts"))
|
||||
const program1Diagnostics = program_1.getSemanticDiagnostics(program_1.getSourceFile("a.ts"));
|
||||
const program2Diagnostics = program_2.getSemanticDiagnostics(program_1.getSourceFile("a.ts"));
|
||||
assert.equal(program1Diagnostics.length, program2Diagnostics.length);
|
||||
});
|
||||
|
||||
it("successful if change does not affect type reference directives", () => {
|
||||
var program_1 = newProgram(files, ["a.ts"], { target });
|
||||
var program_2 = updateProgram(program_1, ["a.ts"], { target }, files => {
|
||||
const program_1 = newProgram(files, ["a.ts"], { target });
|
||||
const program_2 = updateProgram(program_1, ["a.ts"], { target }, files => {
|
||||
files[0].text = files[0].text.updateProgram("var x = 100");
|
||||
});
|
||||
assert.isTrue(program_1.structureIsReused);
|
||||
let program1Diagnostics = program_1.getSemanticDiagnostics(program_1.getSourceFile("a.ts"))
|
||||
let program2Diagnostics = program_2.getSemanticDiagnostics(program_1.getSourceFile("a.ts"))
|
||||
const program1Diagnostics = program_1.getSemanticDiagnostics(program_1.getSourceFile("a.ts"));
|
||||
const program2Diagnostics = program_2.getSemanticDiagnostics(program_1.getSourceFile("a.ts"));
|
||||
assert.equal(program1Diagnostics.length, program2Diagnostics.length);
|
||||
});
|
||||
|
||||
it("fails if change affects tripleslash references", () => {
|
||||
var program_1 = newProgram(files, ["a.ts"], { target });
|
||||
var program_2 = updateProgram(program_1, ["a.ts"], { target }, files => {
|
||||
let newReferences = `/// <reference path='b.ts'/>
|
||||
const program_1 = newProgram(files, ["a.ts"], { target });
|
||||
const program_2 = updateProgram(program_1, ["a.ts"], { target }, files => {
|
||||
const newReferences = `/// <reference path='b.ts'/>
|
||||
/// <reference path='c.ts'/>
|
||||
`;
|
||||
files[0].text = files[0].text.updateReferences(newReferences);
|
||||
@ -257,17 +258,17 @@ module ts {
|
||||
});
|
||||
|
||||
it("fails if change affects imports", () => {
|
||||
var program_1 = newProgram(files, ["a.ts"], { target });
|
||||
var program_2 = updateProgram(program_1, ["a.ts"], { target }, files => {
|
||||
const program_1 = newProgram(files, ["a.ts"], { target });
|
||||
const program_2 = updateProgram(program_1, ["a.ts"], { target }, files => {
|
||||
files[2].text = files[2].text.updateImportsAndExports("import x from 'b'");
|
||||
});
|
||||
assert.isTrue(!program_1.structureIsReused);
|
||||
});
|
||||
|
||||
it("fails if change affects type directives", () => {
|
||||
var program_1 = newProgram(files, ["a.ts"], { target });
|
||||
var program_2 = updateProgram(program_1, ["a.ts"], { target }, files => {
|
||||
let newReferences = `
|
||||
const program_1 = newProgram(files, ["a.ts"], { target });
|
||||
const program_2 = updateProgram(program_1, ["a.ts"], { target }, files => {
|
||||
const newReferences = `
|
||||
/// <reference path='b.ts'/>
|
||||
/// <reference path='non-existing-file.ts'/>
|
||||
/// <reference types="typerefs1" />`;
|
||||
@ -277,35 +278,35 @@ module ts {
|
||||
});
|
||||
|
||||
it("fails if module kind changes", () => {
|
||||
var program_1 = newProgram(files, ["a.ts"], { target, module: ModuleKind.CommonJS });
|
||||
var program_2 = updateProgram(program_1, ["a.ts"], { target, module: ModuleKind.AMD }, files => void 0);
|
||||
const program_1 = newProgram(files, ["a.ts"], { target, module: ModuleKind.CommonJS });
|
||||
const program_2 = updateProgram(program_1, ["a.ts"], { target, module: ModuleKind.AMD }, files => void 0);
|
||||
assert.isTrue(!program_1.structureIsReused);
|
||||
});
|
||||
|
||||
|
||||
it("fails if rootdir changes", () => {
|
||||
var program_1 = newProgram(files, ["a.ts"], { target, module: ModuleKind.CommonJS, rootDir: "/a/b" });
|
||||
var program_2 = updateProgram(program_1, ["a.ts"], { target, module: ModuleKind.CommonJS, rootDir: "/a/c" }, files => void 0);
|
||||
const program_1 = newProgram(files, ["a.ts"], { target, module: ModuleKind.CommonJS, rootDir: "/a/b" });
|
||||
const program_2 = updateProgram(program_1, ["a.ts"], { target, module: ModuleKind.CommonJS, rootDir: "/a/c" }, files => void 0);
|
||||
assert.isTrue(!program_1.structureIsReused);
|
||||
});
|
||||
|
||||
it("fails if config path changes", () => {
|
||||
var program_1 = newProgram(files, ["a.ts"], { target, module: ModuleKind.CommonJS, configFilePath: "/a/b/tsconfig.json" });
|
||||
var program_2 = updateProgram(program_1, ["a.ts"], { target, module: ModuleKind.CommonJS, configFilePath: "/a/c/tsconfig.json" }, files => void 0);
|
||||
const program_1 = newProgram(files, ["a.ts"], { target, module: ModuleKind.CommonJS, configFilePath: "/a/b/tsconfig.json" });
|
||||
const program_2 = updateProgram(program_1, ["a.ts"], { target, module: ModuleKind.CommonJS, configFilePath: "/a/c/tsconfig.json" }, files => void 0);
|
||||
assert.isTrue(!program_1.structureIsReused);
|
||||
});
|
||||
|
||||
it("resolution cache follows imports", () => {
|
||||
let files = [
|
||||
const files = [
|
||||
{ name: "a.ts", text: SourceText.New("", "import {_} from 'b'", "var x = 1") },
|
||||
{ name: "b.ts", text: SourceText.New("", "", "var y = 2") },
|
||||
];
|
||||
var options: CompilerOptions = { target };
|
||||
const options: CompilerOptions = { target };
|
||||
|
||||
var program_1 = newProgram(files, ["a.ts"], options);
|
||||
const program_1 = newProgram(files, ["a.ts"], options);
|
||||
checkResolvedModulesCache(program_1, "a.ts", { "b": { resolvedFileName: "b.ts" } });
|
||||
checkResolvedModulesCache(program_1, "b.ts", undefined);
|
||||
|
||||
var program_2 = updateProgram(program_1, ["a.ts"], options, files => {
|
||||
const program_2 = updateProgram(program_1, ["a.ts"], options, files => {
|
||||
files[0].text = files[0].text.updateProgram("var x = 2");
|
||||
});
|
||||
assert.isTrue(program_1.structureIsReused);
|
||||
@ -315,14 +316,14 @@ module ts {
|
||||
checkResolvedModulesCache(program_1, "b.ts", undefined);
|
||||
|
||||
// imports has changed - program is not reused
|
||||
var program_3 = updateProgram(program_2, ["a.ts"], options, files => {
|
||||
const program_3 = updateProgram(program_2, ["a.ts"], options, files => {
|
||||
files[0].text = files[0].text.updateImportsAndExports("");
|
||||
});
|
||||
assert.isTrue(!program_2.structureIsReused);
|
||||
checkResolvedModulesCache(program_3, "a.ts", undefined);
|
||||
|
||||
var program_4 = updateProgram(program_3, ["a.ts"], options, files => {
|
||||
let newImports = `import x from 'b'
|
||||
const program_4 = updateProgram(program_3, ["a.ts"], options, files => {
|
||||
const newImports = `import x from 'b'
|
||||
import y from 'c'
|
||||
`;
|
||||
files[0].text = files[0].text.updateImportsAndExports(newImports);
|
||||
@ -332,17 +333,17 @@ module ts {
|
||||
});
|
||||
|
||||
it("resolved type directives cache follows type directives", () => {
|
||||
let files = [
|
||||
const files = [
|
||||
{ name: "/a.ts", text: SourceText.New("/// <reference types='typedefs'/>", "", "var x = $") },
|
||||
{ name: "/types/typedefs/index.d.ts", text: SourceText.New("", "", "declare var $: number") },
|
||||
];
|
||||
var options: CompilerOptions = { target, typesRoot: "/" };
|
||||
const options: CompilerOptions = { target, typesRoot: "/" };
|
||||
|
||||
var program_1 = newProgram(files, ["/a.ts"], options);
|
||||
const program_1 = newProgram(files, ["/a.ts"], options);
|
||||
checkResolvedTypeDirectivesCache(program_1, "/a.ts", { "typedefs": { resolvedFileName: "/types/typedefs/index.d.ts", primary: true } });
|
||||
checkResolvedTypeDirectivesCache(program_1, "/types/typedefs/index.d.ts", undefined);
|
||||
|
||||
var program_2 = updateProgram(program_1, ["/a.ts"], options, files => {
|
||||
const program_2 = updateProgram(program_1, ["/a.ts"], options, files => {
|
||||
files[0].text = files[0].text.updateProgram("var x = 2");
|
||||
});
|
||||
assert.isTrue(program_1.structureIsReused);
|
||||
@ -352,15 +353,15 @@ module ts {
|
||||
checkResolvedTypeDirectivesCache(program_1, "/types/typedefs/index.d.ts", undefined);
|
||||
|
||||
// type reference directives has changed - program is not reused
|
||||
var program_3 = updateProgram(program_2, ["/a.ts"], options, files => {
|
||||
const program_3 = updateProgram(program_2, ["/a.ts"], options, files => {
|
||||
files[0].text = files[0].text.updateReferences("");
|
||||
});
|
||||
|
||||
assert.isTrue(!program_2.structureIsReused);
|
||||
checkResolvedTypeDirectivesCache(program_3, "/a.ts", undefined);
|
||||
|
||||
var program_4 = updateProgram(program_3, ["/a.ts"], options, files => {
|
||||
let newReferences = `/// <reference types="typedefs"/>
|
||||
const program_4 = updateProgram(program_3, ["/a.ts"], options, files => {
|
||||
const newReferences = `/// <reference types="typedefs"/>
|
||||
/// <reference types="typedefs2"/>
|
||||
`;
|
||||
files[0].text = files[0].text.updateReferences(newReferences);
|
||||
@ -368,11 +369,12 @@ module ts {
|
||||
assert.isTrue(!program_3.structureIsReused);
|
||||
checkResolvedTypeDirectivesCache(program_1, "/a.ts", { "typedefs": { resolvedFileName: "/types/typedefs/index.d.ts", primary: true } });
|
||||
});
|
||||
/* tslint:enable no-unused-variable */
|
||||
});
|
||||
|
||||
describe("host is optional", () => {
|
||||
it("should work if host is not provided", () => {
|
||||
createProgram([], {});
|
||||
})
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,15 +7,15 @@ interface ClassificationEntry {
|
||||
position?: number;
|
||||
}
|
||||
|
||||
describe('Colorization', function () {
|
||||
describe("Colorization", function () {
|
||||
// Use the shim adapter to ensure test coverage of the shim layer for the classifier
|
||||
var languageServiceAdapter = new Harness.LanguageService.ShimLanguageServiceAdapter(/*preprocessToResolve*/ false);
|
||||
var classifier = languageServiceAdapter.getClassifier();
|
||||
const languageServiceAdapter = new Harness.LanguageService.ShimLanguageServiceAdapter(/*preprocessToResolve*/ false);
|
||||
const classifier = languageServiceAdapter.getClassifier();
|
||||
|
||||
function getEntryAtPosition(result: ts.ClassificationResult, position: number) {
|
||||
var entryPosition = 0;
|
||||
for (var i = 0, n = result.entries.length; i < n; i++) {
|
||||
var entry = result.entries[i];
|
||||
let entryPosition = 0;
|
||||
for (let i = 0, n = result.entries.length; i < n; i++) {
|
||||
const entry = result.entries[i];
|
||||
if (entryPosition === position) {
|
||||
return entry;
|
||||
}
|
||||
@ -32,7 +32,6 @@ describe('Colorization', function () {
|
||||
function identifier(text: string, position?: number) { return createClassification(text, ts.TokenClass.Identifier, position); }
|
||||
function numberLiteral(text: string, position?: number) { return createClassification(text, ts.TokenClass.NumberLiteral, position); }
|
||||
function stringLiteral(text: string, position?: number) { return createClassification(text, ts.TokenClass.StringLiteral, position); }
|
||||
function regExpLiteral(text: string, position?: number) { return createClassification(text, ts.TokenClass.RegExpLiteral, position); }
|
||||
function finalEndOfLineState(value: number): ClassificationEntry { return { value: value, classification: undefined, position: 0 }; }
|
||||
function createClassification(text: string, tokenClass: ts.TokenClass, position?: number): ClassificationEntry {
|
||||
return {
|
||||
@ -43,19 +42,19 @@ describe('Colorization', function () {
|
||||
}
|
||||
|
||||
function testLexicalClassification(text: string, initialEndOfLineState: ts.EndOfLineState, ...expectedEntries: ClassificationEntry[]): void {
|
||||
var result = classifier.getClassificationsForLine(text, initialEndOfLineState, /*syntacticClassifierAbsent*/ false);
|
||||
const result = classifier.getClassificationsForLine(text, initialEndOfLineState, /*syntacticClassifierAbsent*/ false);
|
||||
|
||||
for (var i = 0, n = expectedEntries.length; i < n; i++) {
|
||||
var expectedEntry = expectedEntries[i];
|
||||
for (let i = 0, n = expectedEntries.length; i < n; i++) {
|
||||
const expectedEntry = expectedEntries[i];
|
||||
|
||||
if (expectedEntry.classification === undefined) {
|
||||
assert.equal(result.finalLexState, expectedEntry.value, "final endOfLineState does not match expected.");
|
||||
}
|
||||
else {
|
||||
var actualEntryPosition = expectedEntry.position !== undefined ? expectedEntry.position : text.indexOf(expectedEntry.value);
|
||||
const actualEntryPosition = expectedEntry.position !== undefined ? expectedEntry.position : text.indexOf(expectedEntry.value);
|
||||
assert(actualEntryPosition >= 0, "token: '" + expectedEntry.value + "' does not exit in text: '" + text + "'.");
|
||||
|
||||
var actualEntry = getEntryAtPosition(result, actualEntryPosition);
|
||||
const actualEntry = getEntryAtPosition(result, actualEntryPosition);
|
||||
|
||||
assert(actualEntry, "Could not find classification entry for '" + expectedEntry.value + "' at position: " + actualEntryPosition);
|
||||
assert.equal(actualEntry.classification, expectedEntry.classification, "Classification class does not match expected. Expected: " + ts.TokenClass[expectedEntry.classification] + ", Actual: " + ts.TokenClass[actualEntry.classification]);
|
||||
@ -292,7 +291,7 @@ describe('Colorization', function () {
|
||||
stringLiteral("..."),
|
||||
finalEndOfLineState(ts.EndOfLineState.InTemplateHeadOrNoSubstitutionTemplate));
|
||||
});
|
||||
it("classifies the entire line of an unterminated multiline template middle/end",() => {
|
||||
it("classifies the entire line of an unterminated multiline template middle/end", () => {
|
||||
testLexicalClassification("...",
|
||||
ts.EndOfLineState.InTemplateMiddleOrTail,
|
||||
stringLiteral("..."),
|
||||
@ -320,7 +319,7 @@ describe('Colorization', function () {
|
||||
stringLiteral("}...`"),
|
||||
finalEndOfLineState(ts.EndOfLineState.None));
|
||||
});
|
||||
it("classifies a template middle and propagates the end of line state",() => {
|
||||
it("classifies a template middle and propagates the end of line state", () => {
|
||||
testLexicalClassification("${ 1 + 1 }...`",
|
||||
ts.EndOfLineState.InTemplateHeadOrNoSubstitutionTemplate,
|
||||
stringLiteral("${"),
|
||||
@ -331,8 +330,8 @@ describe('Colorization', function () {
|
||||
finalEndOfLineState(ts.EndOfLineState.None));
|
||||
});
|
||||
it("classifies substitution expressions with curly braces appropriately", () => {
|
||||
var pos = 0;
|
||||
var lastLength = 0;
|
||||
let pos = 0;
|
||||
let lastLength = 0;
|
||||
|
||||
testLexicalClassification("...${ () => { } } ${ { x: `1` } }...`",
|
||||
ts.EndOfLineState.InTemplateHeadOrNoSubstitutionTemplate,
|
||||
@ -354,7 +353,7 @@ describe('Colorization', function () {
|
||||
// Adjusts 'pos' by accounting for the length of each portion of the string,
|
||||
// but only return the last given string
|
||||
function track(...vals: string[]): string {
|
||||
for (var i = 0, n = vals.length; i < n; i++) {
|
||||
for (let i = 0, n = vals.length; i < n; i++) {
|
||||
pos += lastLength;
|
||||
lastLength = vals[i].length;
|
||||
}
|
||||
@ -446,4 +445,4 @@ class D { }\r\n\
|
||||
finalEndOfLineState(ts.EndOfLineState.None));
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,79 +1,81 @@
|
||||
///<reference path='..\..\..\..\src\harness\harness.ts' />
|
||||
|
||||
describe("DocumentRegistry", () => {
|
||||
/* tslint:disable no-unused-variable */
|
||||
it("documents are shared between projects", () => {
|
||||
var documentRegistry = ts.createDocumentRegistry();
|
||||
var defaultCompilerOptions = ts.getDefaultCompilerOptions();
|
||||
const documentRegistry = ts.createDocumentRegistry();
|
||||
const defaultCompilerOptions = ts.getDefaultCompilerOptions();
|
||||
|
||||
var f1 = documentRegistry.acquireDocument("file1.ts", defaultCompilerOptions, ts.ScriptSnapshot.fromString("var x = 1;"), /* version */ "1");
|
||||
var f2 = documentRegistry.acquireDocument("file1.ts", defaultCompilerOptions, ts.ScriptSnapshot.fromString("var x = 1;"), /* version */ "1");
|
||||
const f1 = documentRegistry.acquireDocument("file1.ts", defaultCompilerOptions, ts.ScriptSnapshot.fromString("var x = 1;"), /* version */ "1");
|
||||
const f2 = documentRegistry.acquireDocument("file1.ts", defaultCompilerOptions, ts.ScriptSnapshot.fromString("var x = 1;"), /* version */ "1");
|
||||
|
||||
assert(f1 === f2, "DocumentRegistry should return the same document for the same name");
|
||||
});
|
||||
|
||||
it("documents are refreshed when settings in compilation settings affect syntax", () => {
|
||||
var documentRegistry = ts.createDocumentRegistry();
|
||||
var compilerOptions: ts.CompilerOptions = { target: ts.ScriptTarget.ES5, module: ts.ModuleKind.AMD };
|
||||
const documentRegistry = ts.createDocumentRegistry();
|
||||
const compilerOptions: ts.CompilerOptions = { target: ts.ScriptTarget.ES5, module: ts.ModuleKind.AMD };
|
||||
|
||||
// change compilation setting that doesn't affect parsing - should have the same document
|
||||
compilerOptions.declaration = true;
|
||||
var f1 = documentRegistry.acquireDocument("file1.ts", compilerOptions, ts.ScriptSnapshot.fromString("var x = 1;"), /* version */ "1");
|
||||
const f1 = documentRegistry.acquireDocument("file1.ts", compilerOptions, ts.ScriptSnapshot.fromString("var x = 1;"), /* version */ "1");
|
||||
compilerOptions.declaration = false;
|
||||
var f2 = documentRegistry.acquireDocument("file1.ts", compilerOptions, ts.ScriptSnapshot.fromString("var x = 1;"), /* version */ "1");
|
||||
const f2 = documentRegistry.acquireDocument("file1.ts", compilerOptions, ts.ScriptSnapshot.fromString("var x = 1;"), /* version */ "1");
|
||||
|
||||
assert(f1 === f2, "Expected to have the same document instance");
|
||||
|
||||
|
||||
// change value of compilation setting that is used during production of AST - new document is required
|
||||
compilerOptions.target = ts.ScriptTarget.ES3;
|
||||
var f3 = documentRegistry.acquireDocument("file1.ts", compilerOptions, ts.ScriptSnapshot.fromString("var x = 1;"), /* version */ "1");
|
||||
const f3 = documentRegistry.acquireDocument("file1.ts", compilerOptions, ts.ScriptSnapshot.fromString("var x = 1;"), /* version */ "1");
|
||||
|
||||
assert(f1 !== f3, "Changed target: Expected to have different instances of document");
|
||||
|
||||
compilerOptions.preserveConstEnums = true;
|
||||
var f4 = documentRegistry.acquireDocument("file1.ts", compilerOptions, ts.ScriptSnapshot.fromString("var x = 1;"), /* version */ "1");
|
||||
const f4 = documentRegistry.acquireDocument("file1.ts", compilerOptions, ts.ScriptSnapshot.fromString("var x = 1;"), /* version */ "1");
|
||||
|
||||
assert(f3 === f4, "Changed preserveConstEnums: Expected to have the same instance of the document");
|
||||
|
||||
compilerOptions.module = ts.ModuleKind.System;
|
||||
var f5 = documentRegistry.acquireDocument("file1.ts", compilerOptions, ts.ScriptSnapshot.fromString("var x = 1;"), /* version */ "1");
|
||||
const f5 = documentRegistry.acquireDocument("file1.ts", compilerOptions, ts.ScriptSnapshot.fromString("var x = 1;"), /* version */ "1");
|
||||
|
||||
assert(f4 !== f5, "Changed module: Expected to have different instances of the document");
|
||||
});
|
||||
|
||||
it("Acquiring document gets correct version 1", () => {
|
||||
var documentRegistry = ts.createDocumentRegistry();
|
||||
var defaultCompilerOptions = ts.getDefaultCompilerOptions();
|
||||
const documentRegistry = ts.createDocumentRegistry();
|
||||
const defaultCompilerOptions = ts.getDefaultCompilerOptions();
|
||||
|
||||
// Simulate one LS getting the document.
|
||||
var f1 = documentRegistry.acquireDocument("file1.ts", defaultCompilerOptions, ts.ScriptSnapshot.fromString("var x = 1;"), /* version */ "1");
|
||||
const f1 = documentRegistry.acquireDocument("file1.ts", defaultCompilerOptions, ts.ScriptSnapshot.fromString("var x = 1;"), /* version */ "1");
|
||||
|
||||
// Simulate another LS getting the document at another version.
|
||||
var f2 = documentRegistry.acquireDocument("file1.ts", defaultCompilerOptions, ts.ScriptSnapshot.fromString("var x = 1;"), /* version */ "2");
|
||||
const f2 = documentRegistry.acquireDocument("file1.ts", defaultCompilerOptions, ts.ScriptSnapshot.fromString("var x = 1;"), /* version */ "2");
|
||||
|
||||
assert(f2.version === "2");
|
||||
});
|
||||
|
||||
it("Acquiring document gets correct version 2", () => {
|
||||
var documentRegistry = ts.createDocumentRegistry();
|
||||
var defaultCompilerOptions = ts.getDefaultCompilerOptions();
|
||||
const documentRegistry = ts.createDocumentRegistry();
|
||||
const defaultCompilerOptions = ts.getDefaultCompilerOptions();
|
||||
|
||||
var contents = "var x = 1;"
|
||||
var snapshot = ts.ScriptSnapshot.fromString(contents);
|
||||
const contents = "var x = 1;";
|
||||
const snapshot = ts.ScriptSnapshot.fromString(contents);
|
||||
|
||||
// Always treat any change as a full change.
|
||||
snapshot.getChangeRange = old => ts.createTextChangeRange(ts.createTextSpan(0, contents.length), contents.length);
|
||||
|
||||
// Simulate one LS getting the document.
|
||||
var f1 = documentRegistry.acquireDocument("file1.ts", defaultCompilerOptions, snapshot, /* version */ "1");
|
||||
const f1 = documentRegistry.acquireDocument("file1.ts", defaultCompilerOptions, snapshot, /* version */ "1");
|
||||
|
||||
// Simulate another LS getting that document.
|
||||
var f2 = documentRegistry.acquireDocument("file1.ts", defaultCompilerOptions, snapshot, /* version */ "1");
|
||||
const f2 = documentRegistry.acquireDocument("file1.ts", defaultCompilerOptions, snapshot, /* version */ "1");
|
||||
|
||||
// Now LS1 updates their document.
|
||||
var f3 = documentRegistry.updateDocument("file1.ts", defaultCompilerOptions, snapshot, /* version */ "2");
|
||||
const f3 = documentRegistry.updateDocument("file1.ts", defaultCompilerOptions, snapshot, /* version */ "2");
|
||||
|
||||
// Now LS2 tries to update their document.
|
||||
var f4 = documentRegistry.updateDocument("file1.ts", defaultCompilerOptions, snapshot, /* version */ "3");
|
||||
// Now LS2 tries to update their document.
|
||||
const f4 = documentRegistry.updateDocument("file1.ts", defaultCompilerOptions, snapshot, /* version */ "3");
|
||||
});
|
||||
});
|
||||
/* tslint:enable no-unused-variable */
|
||||
});
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
/// <reference path="..\..\..\..\src\harness\external\mocha.d.ts" />
|
||||
/// <reference path="..\..\..\..\src\services\patternMatcher.ts" />
|
||||
|
||||
describe('PatternMatcher', function () {
|
||||
describe("PatternMatcher", function () {
|
||||
describe("BreakIntoCharacterSpans", function () {
|
||||
it("EmptyIdentifier", () => {
|
||||
verifyBreakIntoCharacterSpans("")
|
||||
verifyBreakIntoCharacterSpans("");
|
||||
});
|
||||
|
||||
it("SimpleIdentifier", () => {
|
||||
@ -96,35 +96,35 @@ describe('PatternMatcher', function () {
|
||||
|
||||
describe("SingleWordPattern", () => {
|
||||
it("PreferCaseSensitiveExact", () => {
|
||||
var match = getFirstMatch("Foo", "Foo");
|
||||
const match = getFirstMatch("Foo", "Foo");
|
||||
|
||||
assert.equal(ts.PatternMatchKind.exact, match.kind);
|
||||
assert.equal(true, match.isCaseSensitive);
|
||||
});
|
||||
|
||||
it("PreferCaseSensitiveExactInsensitive", () => {
|
||||
var match = getFirstMatch("foo", "Foo");
|
||||
const match = getFirstMatch("foo", "Foo");
|
||||
|
||||
assert.equal(ts.PatternMatchKind.exact, match.kind);
|
||||
assert.equal(false, match.isCaseSensitive);
|
||||
});
|
||||
|
||||
it("PreferCaseSensitivePrefix", () => {
|
||||
var match = getFirstMatch("Foo", "Fo");
|
||||
const match = getFirstMatch("Foo", "Fo");
|
||||
|
||||
assert.equal(ts.PatternMatchKind.prefix, match.kind);
|
||||
assert.equal(true, match.isCaseSensitive);
|
||||
});
|
||||
|
||||
it("PreferCaseSensitivePrefixCaseInsensitive", () => {
|
||||
var match = getFirstMatch("Foo", "fo");
|
||||
const match = getFirstMatch("Foo", "fo");
|
||||
|
||||
assert.equal(ts.PatternMatchKind.prefix, match.kind);
|
||||
assert.equal(false, match.isCaseSensitive);
|
||||
});
|
||||
|
||||
it("PreferCaseSensitiveCamelCaseMatchSimple", () => {
|
||||
var match = getFirstMatch("FogBar", "FB");
|
||||
const match = getFirstMatch("FogBar", "FB");
|
||||
|
||||
assert.equal(ts.PatternMatchKind.camelCase, match.kind);
|
||||
assert.equal(true, match.isCaseSensitive);
|
||||
@ -132,156 +132,156 @@ describe('PatternMatcher', function () {
|
||||
});
|
||||
|
||||
it("PreferCaseSensitiveCamelCaseMatchPartialPattern", () => {
|
||||
var match = getFirstMatch("FogBar", "FoB");
|
||||
const match = getFirstMatch("FogBar", "FoB");
|
||||
|
||||
assert.equal(ts.PatternMatchKind.camelCase, match.kind);
|
||||
assert.equal(true, match.isCaseSensitive);
|
||||
});
|
||||
|
||||
it("PreferCaseSensitiveCamelCaseMatchToLongPattern1", () => {
|
||||
var match = getFirstMatch("FogBar", "FBB");
|
||||
const match = getFirstMatch("FogBar", "FBB");
|
||||
|
||||
assert.isTrue(match === undefined);
|
||||
});
|
||||
|
||||
it("PreferCaseSensitiveCamelCaseMatchToLongPattern2", () => {
|
||||
var match = getFirstMatch("FogBar", "FoooB");
|
||||
const match = getFirstMatch("FogBar", "FoooB");
|
||||
|
||||
assert.isTrue(match === undefined);
|
||||
});
|
||||
|
||||
it("CamelCaseMatchPartiallyUnmatched", () => {
|
||||
var match = getFirstMatch("FogBarBaz", "FZ");
|
||||
const match = getFirstMatch("FogBarBaz", "FZ");
|
||||
|
||||
assert.isTrue(match === undefined);
|
||||
});
|
||||
|
||||
it("CamelCaseMatchCompletelyUnmatched", () => {
|
||||
var match = getFirstMatch("FogBarBaz", "ZZ");
|
||||
const match = getFirstMatch("FogBarBaz", "ZZ");
|
||||
|
||||
assert.isTrue(match === undefined);
|
||||
});
|
||||
|
||||
it("TwoUppercaseCharacters", () => {
|
||||
var match = getFirstMatch("SimpleUIElement", "SiUI");
|
||||
const match = getFirstMatch("SimpleUIElement", "SiUI");
|
||||
|
||||
assert.equal(ts.PatternMatchKind.camelCase, match.kind);
|
||||
assert.equal(true, match.isCaseSensitive);
|
||||
});
|
||||
|
||||
it("PreferCaseSensitiveLowercasePattern", () => {
|
||||
var match = getFirstMatch("FogBar", "b");
|
||||
const match = getFirstMatch("FogBar", "b");
|
||||
|
||||
assert.equal(ts.PatternMatchKind.substring, match.kind);
|
||||
assert.equal(false, match.isCaseSensitive);
|
||||
});
|
||||
|
||||
it("PreferCaseSensitiveLowercasePattern2", () => {
|
||||
var match = getFirstMatch("FogBar", "fB");
|
||||
const match = getFirstMatch("FogBar", "fB");
|
||||
|
||||
assert.equal(ts.PatternMatchKind.camelCase, match.kind);
|
||||
assert.equal(false, match.isCaseSensitive);
|
||||
});
|
||||
|
||||
it("PreferCaseSensitiveTryUnderscoredName", () => {
|
||||
var match = getFirstMatch("_fogBar", "_fB");
|
||||
const match = getFirstMatch("_fogBar", "_fB");
|
||||
|
||||
assert.equal(ts.PatternMatchKind.camelCase, match.kind);
|
||||
assert.equal(true, match.isCaseSensitive);
|
||||
});
|
||||
|
||||
it("PreferCaseSensitiveTryUnderscoredName2", () => {
|
||||
var match = getFirstMatch("_fogBar", "fB");
|
||||
const match = getFirstMatch("_fogBar", "fB");
|
||||
|
||||
assert.equal(ts.PatternMatchKind.camelCase, match.kind);
|
||||
assert.equal(true, match.isCaseSensitive);
|
||||
});
|
||||
|
||||
it("PreferCaseSensitiveTryUnderscoredNameInsensitive", () => {
|
||||
var match = getFirstMatch("_FogBar", "_fB");
|
||||
const match = getFirstMatch("_FogBar", "_fB");
|
||||
|
||||
assert.equal(ts.PatternMatchKind.camelCase, match.kind);
|
||||
assert.equal(false, match.isCaseSensitive);
|
||||
});
|
||||
|
||||
it("PreferCaseSensitiveMiddleUnderscore", () => {
|
||||
var match = getFirstMatch("Fog_Bar", "FB");
|
||||
const match = getFirstMatch("Fog_Bar", "FB");
|
||||
|
||||
assert.equal(ts.PatternMatchKind.camelCase, match.kind);
|
||||
assert.equal(true, match.isCaseSensitive);
|
||||
});
|
||||
|
||||
it("PreferCaseSensitiveMiddleUnderscore2", () => {
|
||||
var match = getFirstMatch("Fog_Bar", "F_B");
|
||||
const match = getFirstMatch("Fog_Bar", "F_B");
|
||||
|
||||
assert.equal(ts.PatternMatchKind.camelCase, match.kind);
|
||||
assert.equal(true, match.isCaseSensitive);
|
||||
});
|
||||
|
||||
it("PreferCaseSensitiveMiddleUnderscore3", () => {
|
||||
var match = getFirstMatch("Fog_Bar", "F__B");
|
||||
const match = getFirstMatch("Fog_Bar", "F__B");
|
||||
|
||||
assert.isTrue(undefined === match);
|
||||
});
|
||||
|
||||
it("PreferCaseSensitiveMiddleUnderscore4", () => {
|
||||
var match = getFirstMatch("Fog_Bar", "f_B");
|
||||
const match = getFirstMatch("Fog_Bar", "f_B");
|
||||
|
||||
assert.equal(ts.PatternMatchKind.camelCase, match.kind);
|
||||
assert.equal(false, match.isCaseSensitive);
|
||||
});
|
||||
|
||||
it("PreferCaseSensitiveMiddleUnderscore5", () => {
|
||||
var match = getFirstMatch("Fog_Bar", "F_b");
|
||||
const match = getFirstMatch("Fog_Bar", "F_b");
|
||||
|
||||
assert.equal(ts.PatternMatchKind.camelCase, match.kind);
|
||||
assert.equal(false, match.isCaseSensitive);
|
||||
});
|
||||
|
||||
it("PreferCaseSensitiveRelativeWeights1", () => {
|
||||
var match1 = getFirstMatch("FogBarBaz", "FB");
|
||||
var match2 = getFirstMatch("FooFlobBaz", "FB");
|
||||
|
||||
const match1 = getFirstMatch("FogBarBaz", "FB");
|
||||
const match2 = getFirstMatch("FooFlobBaz", "FB");
|
||||
|
||||
// We should prefer something that starts at the beginning if possible
|
||||
assertInRange(match1.camelCaseWeight, match2.camelCaseWeight + 1, 1 << 30);
|
||||
});
|
||||
|
||||
it("PreferCaseSensitiveRelativeWeights2", () => {
|
||||
var match1 = getFirstMatch("BazBarFooFooFoo", "FFF");
|
||||
var match2 = getFirstMatch("BazFogBarFooFoo", "FFF");
|
||||
const match1 = getFirstMatch("BazBarFooFooFoo", "FFF");
|
||||
const match2 = getFirstMatch("BazFogBarFooFoo", "FFF");
|
||||
|
||||
// Contiguous things should also be preferred
|
||||
assertInRange(match1.camelCaseWeight, match2.camelCaseWeight + 1, 1 << 30);
|
||||
});
|
||||
|
||||
it("PreferCaseSensitiveRelativeWeights3", () => {
|
||||
var match1 = getFirstMatch("FogBarFooFoo", "FFF");
|
||||
var match2 = getFirstMatch("BarFooFooFoo", "FFF");
|
||||
const match1 = getFirstMatch("FogBarFooFoo", "FFF");
|
||||
const match2 = getFirstMatch("BarFooFooFoo", "FFF");
|
||||
|
||||
// The weight of being first should be greater than the weight of being contiguous
|
||||
assertInRange(match1.camelCaseWeight, match2.camelCaseWeight + 1, 1 << 30);
|
||||
});
|
||||
|
||||
it("AllLowerPattern1", () => {
|
||||
var match = getFirstMatch("FogBarChangedEventArgs", "changedeventargs");
|
||||
const match = getFirstMatch("FogBarChangedEventArgs", "changedeventargs");
|
||||
|
||||
assert.isTrue(undefined !== match);
|
||||
});
|
||||
|
||||
it("AllLowerPattern2", () => {
|
||||
var match = getFirstMatch("FogBarChangedEventArgs", "changedeventarrrgh");
|
||||
const match = getFirstMatch("FogBarChangedEventArgs", "changedeventarrrgh");
|
||||
|
||||
assert.isTrue(undefined === match);
|
||||
});
|
||||
|
||||
it("AllLowerPattern3", () => {
|
||||
var match = getFirstMatch("ABCDEFGH", "bcd");
|
||||
const match = getFirstMatch("ABCDEFGH", "bcd");
|
||||
|
||||
assert.isTrue(undefined !== match);
|
||||
});
|
||||
|
||||
it("AllLowerPattern4", () => {
|
||||
var match = getFirstMatch("AbcdefghijEfgHij", "efghij");
|
||||
const match = getFirstMatch("AbcdefghijEfgHij", "efghij");
|
||||
|
||||
assert.isTrue(undefined === match);
|
||||
});
|
||||
@ -289,144 +289,144 @@ describe('PatternMatcher', function () {
|
||||
|
||||
describe("MultiWordPattern", () => {
|
||||
it("ExactWithLowercase", () => {
|
||||
var matches = getAllMatches("AddMetadataReference", "addmetadatareference");
|
||||
const matches = getAllMatches("AddMetadataReference", "addmetadatareference");
|
||||
|
||||
assertContainsKind(ts.PatternMatchKind.exact, matches);
|
||||
});
|
||||
|
||||
it("SingleLowercasedSearchWord1", () => {
|
||||
var matches = getAllMatches("AddMetadataReference", "add");
|
||||
const matches = getAllMatches("AddMetadataReference", "add");
|
||||
|
||||
assertContainsKind(ts.PatternMatchKind.prefix, matches);
|
||||
});
|
||||
|
||||
it("SingleLowercasedSearchWord2", () => {
|
||||
var matches = getAllMatches("AddMetadataReference", "metadata");
|
||||
const matches = getAllMatches("AddMetadataReference", "metadata");
|
||||
|
||||
assertContainsKind(ts.PatternMatchKind.substring, matches);
|
||||
});
|
||||
|
||||
it("SingleUppercaseSearchWord1", () => {
|
||||
var matches = getAllMatches("AddMetadataReference", "Add");
|
||||
const matches = getAllMatches("AddMetadataReference", "Add");
|
||||
|
||||
assertContainsKind(ts.PatternMatchKind.prefix, matches);
|
||||
});
|
||||
|
||||
it("SingleUppercaseSearchWord2", () => {
|
||||
var matches = getAllMatches("AddMetadataReference", "Metadata");
|
||||
const matches = getAllMatches("AddMetadataReference", "Metadata");
|
||||
|
||||
assertContainsKind(ts.PatternMatchKind.substring, matches);
|
||||
});
|
||||
|
||||
it("SingleUppercaseSearchLetter1", () => {
|
||||
var matches = getAllMatches("AddMetadataReference", "A");
|
||||
const matches = getAllMatches("AddMetadataReference", "A");
|
||||
|
||||
assertContainsKind(ts.PatternMatchKind.prefix, matches);
|
||||
});
|
||||
|
||||
it("SingleUppercaseSearchLetter2", () => {
|
||||
var matches = getAllMatches("AddMetadataReference", "M");
|
||||
const matches = getAllMatches("AddMetadataReference", "M");
|
||||
|
||||
assertContainsKind(ts.PatternMatchKind.substring, matches);
|
||||
});
|
||||
|
||||
it("TwoLowercaseWords", () => {
|
||||
var matches = getAllMatches("AddMetadataReference", "add metadata");
|
||||
const matches = getAllMatches("AddMetadataReference", "add metadata");
|
||||
|
||||
assertContainsKind(ts.PatternMatchKind.prefix, matches);
|
||||
assertContainsKind(ts.PatternMatchKind.substring, matches);
|
||||
});
|
||||
|
||||
it("TwoLowercaseWords", () => {
|
||||
var matches = getAllMatches("AddMetadataReference", "A M");
|
||||
const matches = getAllMatches("AddMetadataReference", "A M");
|
||||
|
||||
assertContainsKind(ts.PatternMatchKind.prefix, matches);
|
||||
assertContainsKind(ts.PatternMatchKind.substring, matches);
|
||||
});
|
||||
|
||||
it("TwoLowercaseWords", () => {
|
||||
var matches = getAllMatches("AddMetadataReference", "AM");
|
||||
const matches = getAllMatches("AddMetadataReference", "AM");
|
||||
|
||||
assertContainsKind(ts.PatternMatchKind.camelCase, matches);
|
||||
});
|
||||
|
||||
it("TwoLowercaseWords", () => {
|
||||
var matches = getAllMatches("AddMetadataReference", "ref Metadata")
|
||||
const matches = getAllMatches("AddMetadataReference", "ref Metadata");
|
||||
|
||||
assertArrayEquals(ts.map(matches, m => m.kind), [ts.PatternMatchKind.substring, ts.PatternMatchKind.substring]);
|
||||
});
|
||||
|
||||
it("TwoLowercaseWords", () => {
|
||||
var matches = getAllMatches("AddMetadataReference", "ref M")
|
||||
const matches = getAllMatches("AddMetadataReference", "ref M");
|
||||
|
||||
assertArrayEquals(ts.map(matches, m => m.kind), [ts.PatternMatchKind.substring, ts.PatternMatchKind.substring]);
|
||||
});
|
||||
|
||||
it("MixedCamelCase", () => {
|
||||
var matches = getAllMatches("AddMetadataReference", "AMRe");
|
||||
const matches = getAllMatches("AddMetadataReference", "AMRe");
|
||||
|
||||
assertContainsKind(ts.PatternMatchKind.camelCase, matches);
|
||||
});
|
||||
|
||||
it("BlankPattern", () => {
|
||||
var matches = getAllMatches("AddMetadataReference", "");
|
||||
const matches = getAllMatches("AddMetadataReference", "");
|
||||
|
||||
assert.isTrue(matches === undefined);
|
||||
});
|
||||
|
||||
it("WhitespaceOnlyPattern", () => {
|
||||
var matches = getAllMatches("AddMetadataReference", " ");
|
||||
const matches = getAllMatches("AddMetadataReference", " ");
|
||||
|
||||
assert.isTrue(matches === undefined);
|
||||
});
|
||||
|
||||
it("EachWordSeparately1", () => {
|
||||
var matches = getAllMatches("AddMetadataReference", "add Meta");
|
||||
const matches = getAllMatches("AddMetadataReference", "add Meta");
|
||||
|
||||
assertContainsKind(ts.PatternMatchKind.prefix, matches);
|
||||
assertContainsKind(ts.PatternMatchKind.substring, matches);
|
||||
});
|
||||
|
||||
it("EachWordSeparately2", () => {
|
||||
var matches = getAllMatches("AddMetadataReference", "Add meta");
|
||||
const matches = getAllMatches("AddMetadataReference", "Add meta");
|
||||
|
||||
assertContainsKind(ts.PatternMatchKind.prefix, matches);
|
||||
assertContainsKind(ts.PatternMatchKind.substring, matches);
|
||||
});
|
||||
|
||||
it("EachWordSeparately3", () => {
|
||||
var matches = getAllMatches("AddMetadataReference", "Add Meta");
|
||||
const matches = getAllMatches("AddMetadataReference", "Add Meta");
|
||||
|
||||
assertContainsKind(ts.PatternMatchKind.prefix, matches);
|
||||
assertContainsKind(ts.PatternMatchKind.substring, matches);
|
||||
});
|
||||
|
||||
it("MixedCasing", () => {
|
||||
var matches = getAllMatches("AddMetadataReference", "mEta");
|
||||
const matches = getAllMatches("AddMetadataReference", "mEta");
|
||||
|
||||
assert.isTrue(matches === undefined);
|
||||
});
|
||||
|
||||
it("MixedCasing2", () => {
|
||||
var matches = getAllMatches("AddMetadataReference", "Data");
|
||||
const matches = getAllMatches("AddMetadataReference", "Data");
|
||||
|
||||
assert.isTrue(matches === undefined);
|
||||
});
|
||||
|
||||
it("AsteriskSplit", () => {
|
||||
var matches = getAllMatches("GetKeyWord", "K*W");
|
||||
const matches = getAllMatches("GetKeyWord", "K*W");
|
||||
|
||||
assertArrayEquals(ts.map(matches, m => m.kind), [ts.PatternMatchKind.substring, ts.PatternMatchKind.substring]);
|
||||
});
|
||||
|
||||
it("LowercaseSubstring1", () => {
|
||||
var matches = getAllMatches("Operator", "a");
|
||||
const matches = getAllMatches("Operator", "a");
|
||||
|
||||
assert.isTrue(matches === undefined);
|
||||
});
|
||||
|
||||
it("LowercaseSubstring2", () => {
|
||||
var matches = getAllMatches("FooAttribute", "a");
|
||||
const matches = getAllMatches("FooAttribute", "a");
|
||||
assertContainsKind(ts.PatternMatchKind.substring, matches);
|
||||
assert.isFalse(matches[0].isCaseSensitive);
|
||||
});
|
||||
@ -434,49 +434,49 @@ describe('PatternMatcher', function () {
|
||||
|
||||
describe("DottedPattern", () => {
|
||||
it("DottedPattern1", () => {
|
||||
var match = getFirstMatchForDottedPattern("Foo.Bar.Baz", "Quux", "B.Q");
|
||||
const match = getFirstMatchForDottedPattern("Foo.Bar.Baz", "Quux", "B.Q");
|
||||
|
||||
assert.equal(ts.PatternMatchKind.prefix, match.kind);
|
||||
assert.equal(true, match.isCaseSensitive);
|
||||
});
|
||||
|
||||
it("DottedPattern2", () => {
|
||||
var match = getFirstMatchForDottedPattern("Foo.Bar.Baz", "Quux", "C.Q");
|
||||
const match = getFirstMatchForDottedPattern("Foo.Bar.Baz", "Quux", "C.Q");
|
||||
assert.isTrue(match === undefined);
|
||||
});
|
||||
|
||||
it("DottedPattern3", () => {
|
||||
var match = getFirstMatchForDottedPattern("Foo.Bar.Baz", "Quux", "B.B.Q");
|
||||
const match = getFirstMatchForDottedPattern("Foo.Bar.Baz", "Quux", "B.B.Q");
|
||||
assert.equal(ts.PatternMatchKind.prefix, match.kind);
|
||||
assert.equal(true, match.isCaseSensitive);
|
||||
});
|
||||
|
||||
it("DottedPattern4", () => {
|
||||
var match = getFirstMatchForDottedPattern("Foo.Bar.Baz", "Quux", "Baz.Quux");
|
||||
const match = getFirstMatchForDottedPattern("Foo.Bar.Baz", "Quux", "Baz.Quux");
|
||||
assert.equal(ts.PatternMatchKind.exact, match.kind);
|
||||
assert.equal(true, match.isCaseSensitive);
|
||||
});
|
||||
|
||||
it("DottedPattern5", () => {
|
||||
var match = getFirstMatchForDottedPattern("Foo.Bar.Baz", "Quux", "F.B.B.Quux");
|
||||
const match = getFirstMatchForDottedPattern("Foo.Bar.Baz", "Quux", "F.B.B.Quux");
|
||||
assert.equal(ts.PatternMatchKind.exact, match.kind);
|
||||
assert.equal(true, match.isCaseSensitive);
|
||||
});
|
||||
|
||||
it("DottedPattern6", () => {
|
||||
var match = getFirstMatchForDottedPattern("Foo.Bar.Baz", "Quux", "F.F.B.B.Quux");
|
||||
const match = getFirstMatchForDottedPattern("Foo.Bar.Baz", "Quux", "F.F.B.B.Quux");
|
||||
assert.isTrue(match === undefined);
|
||||
});
|
||||
|
||||
it("DottedPattern7", () => {
|
||||
var match = getFirstMatch("UIElement", "UIElement");
|
||||
var match = getFirstMatch("GetKeyword", "UIElement");
|
||||
let match = getFirstMatch("UIElement", "UIElement");
|
||||
match = getFirstMatch("GetKeyword", "UIElement");
|
||||
assert.isTrue(match === undefined);
|
||||
});
|
||||
});
|
||||
|
||||
function getFirstMatch(candidate: string, pattern: string): ts.PatternMatch {
|
||||
var matches = ts.createPatternMatcher(pattern).getMatchesForLastSegmentOfPattern(candidate);
|
||||
const matches = ts.createPatternMatcher(pattern).getMatchesForLastSegmentOfPattern(candidate);
|
||||
return matches ? matches[0] : undefined;
|
||||
}
|
||||
|
||||
@ -485,7 +485,7 @@ describe('PatternMatcher', function () {
|
||||
}
|
||||
|
||||
function getFirstMatchForDottedPattern(dottedContainer: string, candidate: string, pattern: string): ts.PatternMatch {
|
||||
var matches = ts.createPatternMatcher(pattern).getMatches(dottedContainer.split("."), candidate);
|
||||
const matches = ts.createPatternMatcher(pattern).getMatches(dottedContainer.split("."), candidate);
|
||||
return matches ? matches[0] : undefined;
|
||||
}
|
||||
|
||||
@ -503,7 +503,7 @@ describe('PatternMatcher', function () {
|
||||
function assertArrayEquals<T>(array1: T[], array2: T[]) {
|
||||
assert.equal(array1.length, array2.length);
|
||||
|
||||
for (var i = 0, n = array1.length; i < n; i++) {
|
||||
for (let i = 0, n = array1.length; i < n; i++) {
|
||||
assert.equal(array1[i], array2[i]);
|
||||
}
|
||||
}
|
||||
@ -524,4 +524,4 @@ describe('PatternMatcher', function () {
|
||||
function assertContainsKind(kind: ts.PatternMatchKind, results: ts.PatternMatch[]) {
|
||||
assert.isTrue(ts.forEach(results, r => r.kind === kind));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@ -2,12 +2,14 @@
|
||||
/// <reference path="..\..\..\..\src\harness\harnessLanguageService.ts" />
|
||||
|
||||
declare namespace chai.assert {
|
||||
/* tslint:disable no-unused-variable */
|
||||
function deepEqual(actual: any, expected: any): void;
|
||||
/* tslint:enable no-unused-variable */
|
||||
}
|
||||
|
||||
describe('PreProcessFile:', function () {
|
||||
describe("PreProcessFile:", function () {
|
||||
function test(sourceText: string, readImportFile: boolean, detectJavaScriptImports: boolean, expectedPreProcess: ts.PreProcessedFileInfo): void {
|
||||
var resultPreProcess = ts.preProcessFile(sourceText, readImportFile, detectJavaScriptImports);
|
||||
const resultPreProcess = ts.preProcessFile(sourceText, readImportFile, detectJavaScriptImports);
|
||||
|
||||
assert.equal(resultPreProcess.isLibFile, expectedPreProcess.isLibFile, "Pre-processed file has different value for isLibFile. Expected: " + expectedPreProcess.isLibFile + ". Actual: " + resultPreProcess.isLibFile);
|
||||
|
||||
@ -27,20 +29,20 @@ describe('PreProcessFile:', function () {
|
||||
}
|
||||
assert.equal(actual.length, expected.length, `[${kind}] Actual array's length does not match expected length. Expected files: ${JSON.stringify(expected)}, actual files: ${JSON.stringify(actual)}`);
|
||||
|
||||
for (var i = 0; i < expected.length; ++i) {
|
||||
var actualReference = actual[i];
|
||||
var expectedReference = expected[i];
|
||||
for (let i = 0; i < expected.length; i++) {
|
||||
const actualReference = actual[i];
|
||||
const expectedReference = expected[i];
|
||||
assert.equal(actualReference.fileName, expectedReference.fileName, `[${kind}] actual file path does not match expected. Expected: "${expectedReference.fileName}". Actual: "${actualReference.fileName}".`);
|
||||
assert.equal(actualReference.pos, expectedReference.pos, `[${kind}] actual file start position does not match expected. Expected: "${expectedReference.pos}". Actual: "${actualReference.pos}".`);
|
||||
assert.equal(actualReference.end, expectedReference.end, `[${kind}] actual file end pos does not match expected. Expected: "${expectedReference.end}". Actual: "${actualReference.end}".`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
describe("Test preProcessFiles,", function () {
|
||||
it("Correctly return referenced files from triple slash", function () {
|
||||
test("///<reference path = \"refFile1.ts\" />" + "\n" + "///<reference path =\"refFile2.ts\"/>" + "\n" + "///<reference path=\"refFile3.ts\" />" + "\n" + "///<reference path= \"..\\refFile4d.ts\" />",
|
||||
/* readImports */true,
|
||||
/* detectJavaScriptImports */ false,
|
||||
test("///<reference path = \"refFile1.ts\" />" + "\n" + "///<reference path =\"refFile2.ts\"/>" + "\n" + "///<reference path=\"refFile3.ts\" />" + "\n" + "///<reference path= \"..\\refFile4d.ts\" />",
|
||||
/*readImportFile*/true,
|
||||
/*detectJavaScriptImports*/ false,
|
||||
{
|
||||
referencedFiles: [{ fileName: "refFile1.ts", pos: 0, end: 37 }, { fileName: "refFile2.ts", pos: 38, end: 73 },
|
||||
{ fileName: "refFile3.ts", pos: 74, end: 109 }, { fileName: "..\\refFile4d.ts", pos: 110, end: 150 }],
|
||||
@ -53,8 +55,8 @@ describe('PreProcessFile:', function () {
|
||||
|
||||
it("Do not return reference path because of invalid triple-slash syntax", function () {
|
||||
test("///<reference path\"refFile1.ts\" />" + "\n" + "///<reference path =\"refFile2.ts\">" + "\n" + "///<referencepath=\"refFile3.ts\" />" + "\n" + "///<reference pat= \"refFile4d.ts\" />",
|
||||
/* readImports */true,
|
||||
/* detectJavaScriptImports */ false,
|
||||
/*readImportFile*/true,
|
||||
/*detectJavaScriptImports*/ false,
|
||||
{
|
||||
referencedFiles: <ts.FileReference[]>[],
|
||||
importedFiles: <ts.FileReference[]>[],
|
||||
@ -66,8 +68,8 @@ describe('PreProcessFile:', function () {
|
||||
|
||||
it("Correctly return imported files", function () {
|
||||
test("import i1 = require(\"r1.ts\"); import i2 =require(\"r2.ts\"); import i3= require(\"r3.ts\"); import i4=require(\"r4.ts\"); import i5 = require (\"r5.ts\");",
|
||||
/* readImports */true,
|
||||
/* detectJavaScriptImports */ false,
|
||||
/*readImportFile*/true,
|
||||
/*detectJavaScriptImports*/ false,
|
||||
{
|
||||
referencedFiles: <ts.FileReference[]>[],
|
||||
typeReferenceDirectives: [],
|
||||
@ -80,8 +82,8 @@ describe('PreProcessFile:', function () {
|
||||
|
||||
it("Do not return imported files if readImportFiles argument is false", function () {
|
||||
test("import i1 = require(\"r1.ts\"); import i2 =require(\"r2.ts\"); import i3= require(\"r3.ts\"); import i4=require(\"r4.ts\"); import i5 = require (\"r5.ts\");",
|
||||
/* readImports */ false,
|
||||
/* detectJavaScriptImports */ false,
|
||||
/*readImportFile*/ false,
|
||||
/*detectJavaScriptImports*/ false,
|
||||
{
|
||||
referencedFiles: <ts.FileReference[]>[],
|
||||
typeReferenceDirectives: [],
|
||||
@ -93,8 +95,8 @@ describe('PreProcessFile:', function () {
|
||||
|
||||
it("Do not return import path because of invalid import syntax", function () {
|
||||
test("import i1 require(\"r1.ts\"); import = require(\"r2.ts\") import i3= require(\"r3.ts\"); import i5",
|
||||
/* readImports */true,
|
||||
/* detectJavaScriptImports */ false,
|
||||
/*readImportFile*/true,
|
||||
/*detectJavaScriptImports*/ false,
|
||||
{
|
||||
referencedFiles: <ts.FileReference[]>[],
|
||||
typeReferenceDirectives: [],
|
||||
@ -106,8 +108,8 @@ describe('PreProcessFile:', function () {
|
||||
|
||||
it("Correctly return referenced files and import files", function () {
|
||||
test("///<reference path=\"refFile1.ts\" />" + "\n" + "///<reference path =\"refFile2.ts\"/>" + "\n" + "import i1 = require(\"r1.ts\"); import i2 =require(\"r2.ts\");",
|
||||
/* readImports */true,
|
||||
/* detectJavaScriptImports */ false,
|
||||
/*readImportFile*/true,
|
||||
/*detectJavaScriptImports*/ false,
|
||||
{
|
||||
referencedFiles: [{ fileName: "refFile1.ts", pos: 0, end: 35 }, { fileName: "refFile2.ts", pos: 36, end: 71 }],
|
||||
typeReferenceDirectives: [],
|
||||
@ -119,15 +121,15 @@ describe('PreProcessFile:', function () {
|
||||
|
||||
it("Correctly return referenced files and import files even with some invalid syntax", function () {
|
||||
test("///<reference path=\"refFile1.ts\" />" + "\n" + "///<reference path \"refFile2.ts\"/>" + "\n" + "import i1 = require(\"r1.ts\"); import = require(\"r2.ts\"); import i2 = require(\"r3.ts\");",
|
||||
/* readImports */true,
|
||||
/* detectJavaScriptImports */ false,
|
||||
/*readImportFile*/true,
|
||||
/*detectJavaScriptImports*/ false,
|
||||
{
|
||||
referencedFiles: [{ fileName: "refFile1.ts", pos: 0, end: 35 }],
|
||||
typeReferenceDirectives: [],
|
||||
importedFiles: [{ fileName: "r1.ts", pos: 91, end: 96 }, { fileName: "r3.ts", pos: 148, end: 153 }],
|
||||
ambientExternalModules: undefined,
|
||||
isLibFile: false
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
it("Correctly return ES6 imports", function () {
|
||||
@ -138,8 +140,8 @@ describe('PreProcessFile:', function () {
|
||||
"import {a as A} from \"m5\";" + "\n" +
|
||||
"import {a as A, b, c as C} from \"m6\";" + "\n" +
|
||||
"import def , {a, b, c as C} from \"m7\";" + "\n",
|
||||
/* readImports */true,
|
||||
/* detectJavaScriptImports */ false,
|
||||
/*readImportFile*/true,
|
||||
/*detectJavaScriptImports*/ false,
|
||||
{
|
||||
referencedFiles: [],
|
||||
typeReferenceDirectives: [],
|
||||
@ -154,7 +156,7 @@ describe('PreProcessFile:', function () {
|
||||
],
|
||||
ambientExternalModules: undefined,
|
||||
isLibFile: false
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
it("Correctly return ES6 exports", function () {
|
||||
@ -162,8 +164,8 @@ describe('PreProcessFile:', function () {
|
||||
"export {a} from \"m2\";" + "\n" +
|
||||
"export {a as A} from \"m3\";" + "\n" +
|
||||
"export {a as A, b, c as C} from \"m4\";" + "\n",
|
||||
/* readImports */true,
|
||||
/* detectJavaScriptImports */ false,
|
||||
/*readImportFile*/true,
|
||||
/*detectJavaScriptImports*/ false,
|
||||
{
|
||||
referencedFiles: [],
|
||||
typeReferenceDirectives: [],
|
||||
@ -175,32 +177,32 @@ describe('PreProcessFile:', function () {
|
||||
],
|
||||
ambientExternalModules: undefined,
|
||||
isLibFile: false
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it("Correctly return ambient external modules", () => {
|
||||
test(`
|
||||
declare module A {}
|
||||
declare module "B" {}
|
||||
function foo() {
|
||||
}
|
||||
`,
|
||||
/* readImports */ true,
|
||||
/* detectJavaScriptImports */ false,
|
||||
|
||||
`,
|
||||
/*readImportFile*/ true,
|
||||
/*detectJavaScriptImports*/ false,
|
||||
|
||||
{
|
||||
referencedFiles: [],
|
||||
typeReferenceDirectives: [],
|
||||
importedFiles: [],
|
||||
ambientExternalModules: ["B"],
|
||||
isLibFile: false
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
it("Correctly handles export import declarations", function () {
|
||||
test("export import a = require(\"m1\");",
|
||||
/* readImports */true,
|
||||
/* detectJavaScriptImports */ false,
|
||||
/*readImportFile*/true,
|
||||
/*detectJavaScriptImports*/ false,
|
||||
{
|
||||
referencedFiles: [],
|
||||
typeReferenceDirectives: [],
|
||||
@ -209,7 +211,7 @@ describe('PreProcessFile:', function () {
|
||||
],
|
||||
ambientExternalModules: undefined,
|
||||
isLibFile: false
|
||||
})
|
||||
});
|
||||
});
|
||||
it("Correctly handles export require calls in JavaScript files", function () {
|
||||
test(`
|
||||
@ -218,8 +220,8 @@ describe('PreProcessFile:', function () {
|
||||
foo(require('m3'));
|
||||
var z = { f: require('m4') }
|
||||
`,
|
||||
/* readImports */true,
|
||||
/* detectJavaScriptImports */ true,
|
||||
/*readImportFile*/true,
|
||||
/*detectJavaScriptImports*/ true,
|
||||
{
|
||||
referencedFiles: [],
|
||||
typeReferenceDirectives: [],
|
||||
@ -231,15 +233,15 @@ describe('PreProcessFile:', function () {
|
||||
],
|
||||
ambientExternalModules: undefined,
|
||||
isLibFile: false
|
||||
})
|
||||
});
|
||||
});
|
||||
it("Correctly handles dependency lists in define([deplist]) calls in JavaScript files", function () {
|
||||
test(`
|
||||
define(["mod1", "mod2"], (m1, m2) => {
|
||||
});
|
||||
`,
|
||||
/* readImports */true,
|
||||
/* detectJavaScriptImports */ true,
|
||||
/*readImportFile*/true,
|
||||
/*detectJavaScriptImports*/ true,
|
||||
{
|
||||
referencedFiles: [],
|
||||
typeReferenceDirectives: [],
|
||||
@ -249,15 +251,15 @@ describe('PreProcessFile:', function () {
|
||||
],
|
||||
ambientExternalModules: undefined,
|
||||
isLibFile: false
|
||||
})
|
||||
});
|
||||
});
|
||||
it("Correctly handles dependency lists in define(modName, [deplist]) calls in JavaScript files", function () {
|
||||
test(`
|
||||
define("mod", ["mod1", "mod2"], (m1, m2) => {
|
||||
});
|
||||
`,
|
||||
/* readImports */true,
|
||||
/* detectJavaScriptImports */ true,
|
||||
/*readImportFile*/true,
|
||||
/*detectJavaScriptImports*/ true,
|
||||
{
|
||||
referencedFiles: [],
|
||||
typeReferenceDirectives: [],
|
||||
@ -267,16 +269,16 @@ describe('PreProcessFile:', function () {
|
||||
],
|
||||
ambientExternalModules: undefined,
|
||||
isLibFile: false
|
||||
})
|
||||
});
|
||||
});
|
||||
it("correctly handles augmentations in external modules - 1", () => {
|
||||
test(`
|
||||
declare module "../Observable" {
|
||||
interface I {}
|
||||
}
|
||||
|
||||
|
||||
export {}
|
||||
`,
|
||||
`,
|
||||
/*readImportFile*/ true,
|
||||
/*detectJavaScriptImports*/ false,
|
||||
{
|
||||
@ -287,49 +289,49 @@ describe('PreProcessFile:', function () {
|
||||
],
|
||||
ambientExternalModules: undefined,
|
||||
isLibFile: false
|
||||
})
|
||||
});
|
||||
});
|
||||
it("correctly handles augmentations in external modules - 2", () => {
|
||||
test(`
|
||||
declare module "../Observable" {
|
||||
interface I {}
|
||||
}
|
||||
|
||||
|
||||
import * as x from "m";
|
||||
`,
|
||||
`,
|
||||
/*readImportFile*/ true,
|
||||
/*detectJavaScriptImports*/ false,
|
||||
{
|
||||
referencedFiles: [],
|
||||
typeReferenceDirectives: [],
|
||||
importedFiles: [
|
||||
{ "fileName": "m", "pos": 135, "end": 136 },
|
||||
{ "fileName": "m", "pos": 123, "end": 124 },
|
||||
{ "fileName": "../Observable", "pos": 28, "end": 41 }
|
||||
],
|
||||
ambientExternalModules: undefined,
|
||||
isLibFile: false
|
||||
})
|
||||
});
|
||||
});
|
||||
it("correctly handles augmentations in external modules - 3", () => {
|
||||
test(`
|
||||
declare module "../Observable" {
|
||||
interface I {}
|
||||
}
|
||||
|
||||
|
||||
import m = require("m");
|
||||
`,
|
||||
`,
|
||||
/*readImportFile*/ true,
|
||||
/*detectJavaScriptImports*/ false,
|
||||
{
|
||||
referencedFiles: [],
|
||||
typeReferenceDirectives: [],
|
||||
importedFiles: [
|
||||
{ "fileName": "m", "pos": 135, "end": 136 },
|
||||
{ "fileName": "m", "pos": 123, "end": 124 },
|
||||
{ "fileName": "../Observable", "pos": 28, "end": 41 }
|
||||
],
|
||||
ambientExternalModules: undefined,
|
||||
isLibFile: false
|
||||
})
|
||||
});
|
||||
});
|
||||
it("correctly handles augmentations in external modules - 4", () => {
|
||||
test(`
|
||||
@ -338,7 +340,7 @@ describe('PreProcessFile:', function () {
|
||||
}
|
||||
namespace N {}
|
||||
export = N;
|
||||
`,
|
||||
`,
|
||||
/*readImportFile*/ true,
|
||||
/*detectJavaScriptImports*/ false,
|
||||
{
|
||||
@ -349,7 +351,7 @@ describe('PreProcessFile:', function () {
|
||||
],
|
||||
ambientExternalModules: undefined,
|
||||
isLibFile: false
|
||||
})
|
||||
});
|
||||
});
|
||||
it("correctly handles augmentations in external modules - 5", () => {
|
||||
test(`
|
||||
@ -358,7 +360,7 @@ describe('PreProcessFile:', function () {
|
||||
}
|
||||
namespace N {}
|
||||
export import IN = N;
|
||||
`,
|
||||
`,
|
||||
/*readImportFile*/ true,
|
||||
/*detectJavaScriptImports*/ false,
|
||||
{
|
||||
@ -369,7 +371,7 @@ describe('PreProcessFile:', function () {
|
||||
],
|
||||
ambientExternalModules: undefined,
|
||||
isLibFile: false
|
||||
})
|
||||
});
|
||||
});
|
||||
it("correctly handles augmentations in external modules - 6", () => {
|
||||
test(`
|
||||
@ -377,7 +379,7 @@ describe('PreProcessFile:', function () {
|
||||
interface I {}
|
||||
}
|
||||
export let x = 1;
|
||||
`,
|
||||
`,
|
||||
/*readImportFile*/ true,
|
||||
/*detectJavaScriptImports*/ false,
|
||||
{
|
||||
@ -388,7 +390,7 @@ describe('PreProcessFile:', function () {
|
||||
],
|
||||
ambientExternalModules: undefined,
|
||||
isLibFile: false
|
||||
})
|
||||
});
|
||||
});
|
||||
it ("correctly handles augmentations in ambient external modules - 1", () => {
|
||||
test(`
|
||||
@ -398,7 +400,7 @@ describe('PreProcessFile:', function () {
|
||||
interface I {}
|
||||
}
|
||||
}
|
||||
`,
|
||||
`,
|
||||
/*readImportFile*/ true,
|
||||
/*detectJavaScriptImports*/ false,
|
||||
{
|
||||
@ -422,7 +424,7 @@ describe('PreProcessFile:', function () {
|
||||
interface I {}
|
||||
}
|
||||
}
|
||||
`,
|
||||
`,
|
||||
/*readImportFile*/ true,
|
||||
/*detectJavaScriptImports*/ false,
|
||||
{
|
||||
@ -458,7 +460,7 @@ describe('PreProcessFile:', function () {
|
||||
ambientExternalModules: undefined,
|
||||
isLibFile: false
|
||||
});
|
||||
})
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@ -111,23 +111,31 @@ namespace ts.server {
|
||||
}
|
||||
const req: protocol.Request = {
|
||||
command: name,
|
||||
seq: i++,
|
||||
seq: i,
|
||||
type: "command"
|
||||
};
|
||||
i++;
|
||||
session.onMessage(JSON.stringify(req));
|
||||
req.seq = i++;
|
||||
req.seq = i;
|
||||
i++;
|
||||
req.arguments = {};
|
||||
session.onMessage(JSON.stringify(req));
|
||||
req.seq = i++;
|
||||
req.seq = i;
|
||||
i++;
|
||||
/* tslint:disable no-null-keyword */
|
||||
req.arguments = null;
|
||||
/* tslint:enable no-null-keyword */
|
||||
session.onMessage(JSON.stringify(req));
|
||||
req.seq = i++;
|
||||
req.seq = i;
|
||||
i++;
|
||||
req.arguments = "";
|
||||
session.onMessage(JSON.stringify(req));
|
||||
req.seq = i++;
|
||||
req.seq = i;
|
||||
i++;
|
||||
req.arguments = 0;
|
||||
session.onMessage(JSON.stringify(req));
|
||||
req.seq = i++;
|
||||
req.seq = i;
|
||||
i++;
|
||||
req.arguments = [];
|
||||
session.onMessage(JSON.stringify(req));
|
||||
}
|
||||
@ -448,4 +456,4 @@ namespace ts.server {
|
||||
session.consumeQueue();
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,90 +1,90 @@
|
||||
/// <reference path="..\..\..\src\harness\harness.ts" />
|
||||
|
||||
module ts {
|
||||
namespace ts {
|
||||
describe("Transpile", () => {
|
||||
|
||||
|
||||
interface TranspileTestSettings {
|
||||
options?: TranspileOptions;
|
||||
expectedOutput?: string;
|
||||
expectedDiagnosticCodes?: number[];
|
||||
}
|
||||
|
||||
|
||||
function checkDiagnostics(diagnostics: Diagnostic[], expectedDiagnosticCodes?: number[]) {
|
||||
if(!expectedDiagnosticCodes) {
|
||||
if (!expectedDiagnosticCodes) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
for (let i = 0; i < expectedDiagnosticCodes.length; i++) {
|
||||
assert.equal(expectedDiagnosticCodes[i], diagnostics[i] && diagnostics[i].code, `Could not find expeced diagnostic.`);
|
||||
}
|
||||
assert.equal(diagnostics.length, expectedDiagnosticCodes.length, "Resuting diagnostics count does not match expected");
|
||||
assert.equal(diagnostics.length, expectedDiagnosticCodes.length, "Resuting diagnostics count does not match expected");
|
||||
}
|
||||
|
||||
|
||||
function test(input: string, testSettings: TranspileTestSettings): void {
|
||||
|
||||
let transpileOptions: TranspileOptions = testSettings.options || {};
|
||||
|
||||
const transpileOptions: TranspileOptions = testSettings.options || {};
|
||||
if (!transpileOptions.compilerOptions) {
|
||||
transpileOptions.compilerOptions = {};
|
||||
}
|
||||
if(transpileOptions.compilerOptions.newLine === undefined) {
|
||||
if (transpileOptions.compilerOptions.newLine === undefined) { //
|
||||
// use \r\n as default new line
|
||||
transpileOptions.compilerOptions.newLine = ts.NewLineKind.CarriageReturnLineFeed;
|
||||
}
|
||||
|
||||
let canUseOldTranspile = !transpileOptions.renamedDependencies;
|
||||
|
||||
|
||||
const canUseOldTranspile = !transpileOptions.renamedDependencies;
|
||||
|
||||
transpileOptions.reportDiagnostics = true;
|
||||
let transpileModuleResult = transpileModule(input, transpileOptions);
|
||||
|
||||
const transpileModuleResult = transpileModule(input, transpileOptions);
|
||||
|
||||
checkDiagnostics(transpileModuleResult.diagnostics, testSettings.expectedDiagnosticCodes);
|
||||
|
||||
|
||||
if (testSettings.expectedOutput !== undefined) {
|
||||
assert.equal(transpileModuleResult.outputText, testSettings.expectedOutput);
|
||||
}
|
||||
|
||||
|
||||
if (canUseOldTranspile) {
|
||||
let diagnostics: Diagnostic[] = [];
|
||||
let transpileResult = transpile(input, transpileOptions.compilerOptions, transpileOptions.fileName, diagnostics, transpileOptions.moduleName);
|
||||
const diagnostics: Diagnostic[] = [];
|
||||
const transpileResult = transpile(input, transpileOptions.compilerOptions, transpileOptions.fileName, diagnostics, transpileOptions.moduleName);
|
||||
checkDiagnostics(diagnostics, testSettings.expectedDiagnosticCodes);
|
||||
if (testSettings.expectedOutput) {
|
||||
assert.equal(transpileResult, testSettings.expectedOutput);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// check source maps
|
||||
if (!transpileOptions.compilerOptions) {
|
||||
transpileOptions.compilerOptions = {};
|
||||
}
|
||||
|
||||
|
||||
if (!transpileOptions.fileName) {
|
||||
transpileOptions.fileName = transpileOptions.compilerOptions.jsx ? "file.tsx" : "file.ts";
|
||||
}
|
||||
|
||||
|
||||
transpileOptions.compilerOptions.sourceMap = true;
|
||||
let transpileModuleResultWithSourceMap = transpileModule(input, transpileOptions);
|
||||
const transpileModuleResultWithSourceMap = transpileModule(input, transpileOptions);
|
||||
assert.isTrue(transpileModuleResultWithSourceMap.sourceMapText !== undefined);
|
||||
|
||||
let expectedSourceMapFileName = removeFileExtension(getBaseFileName(normalizeSlashes(transpileOptions.fileName))) + ".js.map";
|
||||
let expectedSourceMappingUrlLine = `//# sourceMappingURL=${expectedSourceMapFileName}`;
|
||||
|
||||
|
||||
const expectedSourceMapFileName = removeFileExtension(getBaseFileName(normalizeSlashes(transpileOptions.fileName))) + ".js.map";
|
||||
const expectedSourceMappingUrlLine = `//# sourceMappingURL=${expectedSourceMapFileName}`;
|
||||
|
||||
if (testSettings.expectedOutput !== undefined) {
|
||||
assert.equal(transpileModuleResultWithSourceMap.outputText, testSettings.expectedOutput + expectedSourceMappingUrlLine);
|
||||
}
|
||||
else {
|
||||
// expected output is not set, just verify that output text has sourceMappingURL as a last line
|
||||
let output = transpileModuleResultWithSourceMap.outputText;
|
||||
const output = transpileModuleResultWithSourceMap.outputText;
|
||||
assert.isTrue(output.length >= expectedSourceMappingUrlLine.length);
|
||||
if (output.length === expectedSourceMappingUrlLine.length) {
|
||||
assert.equal(output, expectedSourceMappingUrlLine);
|
||||
}
|
||||
else {
|
||||
let suffix = getNewLineCharacter(transpileOptions.compilerOptions) + expectedSourceMappingUrlLine
|
||||
const suffix = getNewLineCharacter(transpileOptions.compilerOptions) + expectedSourceMappingUrlLine;
|
||||
assert.isTrue(output.indexOf(suffix, output.length - suffix.length) !== -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
it("Generates no diagnostics with valid inputs", () => {
|
||||
// No errors
|
||||
test(`var x = 0;`, { options: { compilerOptions: { module: ModuleKind.CommonJS } } });
|
||||
@ -92,7 +92,7 @@ module ts {
|
||||
|
||||
it("Generates no diagnostics for missing file references", () => {
|
||||
test(`/// <reference path="file2.ts" />
|
||||
var x = 0;`,
|
||||
var x = 0;`,
|
||||
{ options: { compilerOptions: { module: ModuleKind.CommonJS } } });
|
||||
});
|
||||
|
||||
@ -112,23 +112,23 @@ var x = 0;`,
|
||||
});
|
||||
|
||||
it("Generates module output", () => {
|
||||
test(`var x = 0;`,
|
||||
{
|
||||
options: { compilerOptions: { module: ModuleKind.AMD } },
|
||||
test(`var x = 0;`,
|
||||
{
|
||||
options: { compilerOptions: { module: ModuleKind.AMD } },
|
||||
expectedOutput: `define(["require", "exports"], function (require, exports) {\r\n "use strict";\r\n var x = 0;\r\n});\r\n`
|
||||
});
|
||||
});
|
||||
|
||||
it("Uses correct newLine character", () => {
|
||||
test(`var x = 0;`,
|
||||
{
|
||||
options: { compilerOptions: { module: ModuleKind.CommonJS, newLine: NewLineKind.LineFeed } },
|
||||
test(`var x = 0;`,
|
||||
{
|
||||
options: { compilerOptions: { module: ModuleKind.CommonJS, newLine: NewLineKind.LineFeed } },
|
||||
expectedOutput: `"use strict";\nvar x = 0;\n`
|
||||
});
|
||||
});
|
||||
|
||||
it("Sets module name", () => {
|
||||
let output =
|
||||
const output =
|
||||
`System.register("NamedModule", [], function(exports_1, context_1) {\n` +
|
||||
` "use strict";\n` +
|
||||
` var __moduleName = context_1 && context_1.id;\n` +
|
||||
@ -140,11 +140,11 @@ var x = 0;`,
|
||||
` }\n` +
|
||||
` }\n` +
|
||||
`});\n`;
|
||||
test("var x = 1;",
|
||||
{
|
||||
options: { compilerOptions: { module: ModuleKind.System, newLine: NewLineKind.LineFeed }, moduleName: "NamedModule" },
|
||||
test("var x = 1;",
|
||||
{
|
||||
options: { compilerOptions: { module: ModuleKind.System, newLine: NewLineKind.LineFeed }, moduleName: "NamedModule" },
|
||||
expectedOutput: output
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
it("No extra errors for file without extension", () => {
|
||||
@ -152,11 +152,11 @@ var x = 0;`,
|
||||
});
|
||||
|
||||
it("Rename dependencies - System", () => {
|
||||
let input =
|
||||
const input =
|
||||
`import {foo} from "SomeName";\n` +
|
||||
`declare function use(a: any);\n` +
|
||||
`use(foo);`
|
||||
let output =
|
||||
`use(foo);`;
|
||||
const output =
|
||||
`System.register(["SomeOtherName"], function(exports_1, context_1) {\n` +
|
||||
` "use strict";\n` +
|
||||
` var __moduleName = context_1 && context_1.id;\n` +
|
||||
@ -170,39 +170,39 @@ var x = 0;`,
|
||||
` use(SomeName_1.foo);\n` +
|
||||
` }\n` +
|
||||
` }\n` +
|
||||
`});\n`
|
||||
`});\n`;
|
||||
|
||||
test(input,
|
||||
{
|
||||
options: { compilerOptions: { module: ModuleKind.System, newLine: NewLineKind.LineFeed }, renamedDependencies: { "SomeName": "SomeOtherName" } },
|
||||
test(input,
|
||||
{
|
||||
options: { compilerOptions: { module: ModuleKind.System, newLine: NewLineKind.LineFeed }, renamedDependencies: { "SomeName": "SomeOtherName" } },
|
||||
expectedOutput: output
|
||||
});
|
||||
});
|
||||
|
||||
it("Rename dependencies - AMD", () => {
|
||||
let input =
|
||||
const input =
|
||||
`import {foo} from "SomeName";\n` +
|
||||
`declare function use(a: any);\n` +
|
||||
`use(foo);`
|
||||
let output =
|
||||
`use(foo);`;
|
||||
const output =
|
||||
`define(["require", "exports", "SomeOtherName"], function (require, exports, SomeName_1) {\n` +
|
||||
` "use strict";\n` +
|
||||
` use(SomeName_1.foo);\n` +
|
||||
`});\n`;
|
||||
|
||||
test(input,
|
||||
{
|
||||
options: { compilerOptions: { module: ModuleKind.AMD, newLine: NewLineKind.LineFeed }, renamedDependencies: { "SomeName": "SomeOtherName" } },
|
||||
test(input,
|
||||
{
|
||||
options: { compilerOptions: { module: ModuleKind.AMD, newLine: NewLineKind.LineFeed }, renamedDependencies: { "SomeName": "SomeOtherName" } },
|
||||
expectedOutput: output
|
||||
});
|
||||
});
|
||||
|
||||
it("Rename dependencies - UMD", () => {
|
||||
let input =
|
||||
const input =
|
||||
`import {foo} from "SomeName";\n` +
|
||||
`declare function use(a: any);\n` +
|
||||
`use(foo);`
|
||||
let output =
|
||||
`use(foo);`;
|
||||
const output =
|
||||
`(function (factory) {\n` +
|
||||
` if (typeof module === 'object' && typeof module.exports === 'object') {\n` +
|
||||
` var v = factory(require, exports); if (v !== undefined) module.exports = v;\n` +
|
||||
@ -216,15 +216,15 @@ var x = 0;`,
|
||||
` use(SomeName_1.foo);\n` +
|
||||
`});\n`;
|
||||
|
||||
test(input,
|
||||
{
|
||||
options: { compilerOptions: { module: ModuleKind.UMD, newLine: NewLineKind.LineFeed }, renamedDependencies: { "SomeName": "SomeOtherName" } },
|
||||
test(input,
|
||||
{
|
||||
options: { compilerOptions: { module: ModuleKind.UMD, newLine: NewLineKind.LineFeed }, renamedDependencies: { "SomeName": "SomeOtherName" } },
|
||||
expectedOutput: output
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it("Transpile with emit decorators and emit metadata", () => {
|
||||
let input =
|
||||
const input =
|
||||
`import {db} from './db';\n` +
|
||||
`function someDecorator(target) {\n` +
|
||||
` return target;\n` +
|
||||
@ -237,29 +237,29 @@ var x = 0;`,
|
||||
` this.db.doSomething(); \n` +
|
||||
` }\n` +
|
||||
`}\n` +
|
||||
`export {MyClass}; \n`
|
||||
let output =
|
||||
`export {MyClass}; \n`;
|
||||
const output =
|
||||
`"use strict";\n` +
|
||||
`var db_1 = require(\'./db\');\n` +
|
||||
`var db_1 = require(\'./db\');\n` +
|
||||
`function someDecorator(target) {\n` +
|
||||
` return target;\n` +
|
||||
`}\n` +
|
||||
`var MyClass = (function () {\n` +
|
||||
` function MyClass(db) {\n` +
|
||||
` this.db = db;\n` +
|
||||
` this.db.doSomething();\n` +
|
||||
` }\n` +
|
||||
` MyClass = __decorate([\n` +
|
||||
` someDecorator, \n` +
|
||||
` __metadata(\'design:paramtypes\', [(typeof (_a = typeof db_1.db !== \'undefined\' && db_1.db) === \'function\' && _a) || Object])\n` +
|
||||
` ], MyClass);\n` +
|
||||
` return MyClass;\n` +
|
||||
` var _a;\n` +
|
||||
`}());\n` +
|
||||
`}\n` +
|
||||
`var MyClass = (function () {\n` +
|
||||
` function MyClass(db) {\n` +
|
||||
` this.db = db;\n` +
|
||||
` this.db.doSomething();\n` +
|
||||
` }\n` +
|
||||
` MyClass = __decorate([\n` +
|
||||
` someDecorator, \n` +
|
||||
` __metadata(\'design:paramtypes\', [(typeof (_a = typeof db_1.db !== \'undefined\' && db_1.db) === \'function\' && _a) || Object])\n` +
|
||||
` ], MyClass);\n` +
|
||||
` return MyClass;\n` +
|
||||
` var _a;\n` +
|
||||
`}());\n` +
|
||||
`exports.MyClass = MyClass;\n`;
|
||||
|
||||
test(input,
|
||||
{
|
||||
test(input,
|
||||
{
|
||||
options: {
|
||||
compilerOptions: {
|
||||
module: ModuleKind.CommonJS,
|
||||
@ -269,7 +269,7 @@ var x = 0;`,
|
||||
experimentalDecorators: true,
|
||||
target: ScriptTarget.ES5,
|
||||
}
|
||||
},
|
||||
},
|
||||
expectedOutput: output
|
||||
});
|
||||
});
|
||||
@ -279,12 +279,12 @@ var x = 0;`,
|
||||
});
|
||||
|
||||
it("transpile file as 'tsx' if 'jsx' is specified", () => {
|
||||
let input = `var x = <div/>`;
|
||||
let output = `"use strict";\nvar x = React.createElement("div", null);\n`;
|
||||
const input = `var x = <div/>`;
|
||||
const output = `"use strict";\nvar x = React.createElement("div", null);\n`;
|
||||
test(input, {
|
||||
expectedOutput: output,
|
||||
options: { compilerOptions: { jsx: JsxEmit.React, newLine: NewLineKind.LineFeed } }
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
it("transpile .js files", () => {
|
||||
@ -295,7 +295,7 @@ var x = 0;`,
|
||||
options: { compilerOptions: { newLine: NewLineKind.LineFeed, module: ModuleKind.CommonJS }, fileName: "input.js", reportDiagnostics: true },
|
||||
expectedDiagnosticCodes: []
|
||||
});
|
||||
})
|
||||
});
|
||||
|
||||
it("Supports urls in file name", () => {
|
||||
test("var x", { expectedOutput: `"use strict";\r\nvar x;\r\n`, options: { fileName: "http://somewhere/directory//directory2/file.ts" } });
|
||||
|
||||
@ -2,21 +2,21 @@
|
||||
/// <reference path="..\..\..\src\compiler\commandLineParser.ts" />
|
||||
|
||||
namespace ts {
|
||||
describe('parseConfigFileTextToJson', () => {
|
||||
describe("parseConfigFileTextToJson", () => {
|
||||
function assertParseResult(jsonText: string, expectedConfigObject: { config?: any; error?: Diagnostic }) {
|
||||
let parsed = ts.parseConfigFileTextToJson("/apath/tsconfig.json", jsonText);
|
||||
const parsed = ts.parseConfigFileTextToJson("/apath/tsconfig.json", jsonText);
|
||||
assert.equal(JSON.stringify(parsed), JSON.stringify(expectedConfigObject));
|
||||
}
|
||||
|
||||
function assertParseError(jsonText: string) {
|
||||
let parsed = ts.parseConfigFileTextToJson("/apath/tsconfig.json", jsonText);
|
||||
const parsed = ts.parseConfigFileTextToJson("/apath/tsconfig.json", jsonText);
|
||||
assert.isTrue(undefined === parsed.config);
|
||||
assert.isTrue(undefined !== parsed.error);
|
||||
}
|
||||
|
||||
function assertParseErrorWithExcludesKeyword(jsonText: string) {
|
||||
let parsed = ts.parseConfigFileTextToJson("/apath/tsconfig.json", jsonText);
|
||||
let parsedCommand = ts.parseJsonConfigFileContent(parsed, ts.sys, "tests/cases/unittests");
|
||||
const parsed = ts.parseConfigFileTextToJson("/apath/tsconfig.json", jsonText);
|
||||
const parsedCommand = ts.parseJsonConfigFileContent(parsed, ts.sys, "tests/cases/unittests");
|
||||
assert.isTrue(undefined !== parsedCommand.errors);
|
||||
}
|
||||
|
||||
@ -156,7 +156,7 @@ namespace ts {
|
||||
"/apath",
|
||||
["/apath/test.ts", "/apath/.git/a.ts", "/apath/.b.ts", "/apath/..c.ts"],
|
||||
["/apath/test.ts"]
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
it("allow dotted files and folders when explicitly requested", () => {
|
||||
@ -168,7 +168,7 @@ namespace ts {
|
||||
"/apath",
|
||||
["/apath/test.ts", "/apath/.git/a.ts", "/apath/.b.ts", "/apath/..c.ts"],
|
||||
["/apath/.git/a.ts", "/apath/.b.ts", "/apath/..c.ts"]
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
it("always exclude outDir", () => {
|
||||
@ -190,7 +190,7 @@ namespace ts {
|
||||
const expectedFiles = ["/b.ts"];
|
||||
assertParseFileList(tsconfigWithoutExclude, "tsconfig.json", rootDir, allFiles, expectedFiles);
|
||||
assertParseFileList(tsconfigWithExclude, "tsconfig.json", rootDir, allFiles, expectedFiles);
|
||||
})
|
||||
});
|
||||
|
||||
it("implicitly exclude common package folders", () => {
|
||||
assertParseFileList(
|
||||
@ -199,7 +199,7 @@ namespace ts {
|
||||
"/",
|
||||
["/node_modules/a.ts", "/bower_components/b.ts", "/jspm_packages/c.ts", "/d.ts", "/folder/e.ts"],
|
||||
["/d.ts", "/folder/e.ts"]
|
||||
)
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@ -12,9 +12,9 @@ namespace ts {
|
||||
}
|
||||
|
||||
function validateEdit(lineIndex: server.LineIndex, sourceText: string, position: number, deleteLength: number, insertString: string): void {
|
||||
let checkText = editFlat(position, deleteLength, insertString, sourceText);
|
||||
let snapshot = lineIndex.edit(position, deleteLength, insertString);
|
||||
let editedText = snapshot.getText(0, snapshot.getLength());
|
||||
const checkText = editFlat(position, deleteLength, insertString, sourceText);
|
||||
const snapshot = lineIndex.edit(position, deleteLength, insertString);
|
||||
const editedText = snapshot.getText(0, snapshot.getLength());
|
||||
|
||||
assert.equal(editedText, checkText);
|
||||
}
|
||||
@ -23,7 +23,7 @@ namespace ts {
|
||||
let validateEditAtLineCharIndex: (line: number, char: number, deleteLength: number, insertString: string) => void;
|
||||
|
||||
before(() => {
|
||||
let testContent = `/// <reference path="z.ts" />
|
||||
const testContent = `/// <reference path="z.ts" />
|
||||
var x = 10;
|
||||
var y = { zebra: 12, giraffe: "ell" };
|
||||
z.a;
|
||||
@ -34,14 +34,14 @@ k=y;
|
||||
var p:Point=new Point();
|
||||
var q:Point=<Point>p;`;
|
||||
|
||||
let { lines } = server.LineIndex.linesFromText(testContent);
|
||||
const { lines } = server.LineIndex.linesFromText(testContent);
|
||||
assert.isTrue(lines.length > 0, "Failed to initialize test text. Expected text to have at least one line");
|
||||
|
||||
let lineIndex = new server.LineIndex();
|
||||
const lineIndex = new server.LineIndex();
|
||||
lineIndex.load(lines);
|
||||
|
||||
validateEditAtLineCharIndex = (line: number, char: number, deleteLength: number, insertString: string) => {
|
||||
let position = lineColToPosition(lineIndex, line, char);
|
||||
const position = lineColToPosition(lineIndex, line, char);
|
||||
validateEdit(lineIndex, testContent, position, deleteLength, insertString);
|
||||
};
|
||||
});
|
||||
@ -91,7 +91,7 @@ and grew 1cm per day`;
|
||||
({ lines, lineMap } = server.LineIndex.linesFromText(testContent));
|
||||
assert.isTrue(lines.length > 0, "Failed to initialize test text. Expected text to have at least one line");
|
||||
|
||||
let lineIndex = new server.LineIndex();
|
||||
const lineIndex = new server.LineIndex();
|
||||
lineIndex.load(lines);
|
||||
|
||||
validateEditAtPosition = (position: number, deleteLength: number, insertString: string) => {
|
||||
@ -195,9 +195,9 @@ and grew 1cm per day`;
|
||||
|
||||
before(() => {
|
||||
// Use scanner.ts, decent size, does not change frequently
|
||||
let testFileName = "src/compiler/scanner.ts";
|
||||
const testFileName = "src/compiler/scanner.ts";
|
||||
testContent = Harness.IO.readFile(testFileName);
|
||||
let totalChars = testContent.length;
|
||||
const totalChars = testContent.length;
|
||||
assert.isTrue(totalChars > 0, "Failed to read test file.");
|
||||
|
||||
({ lines, lineMap } = server.LineIndex.linesFromText(testContent));
|
||||
@ -246,41 +246,41 @@ and grew 1cm per day`;
|
||||
|
||||
it("Range (average length 1/4 file size)", () => {
|
||||
for (let i = 0; i < iterationCount; i++) {
|
||||
let s2 = lineIndex.getText(rsa[i], la[i]);
|
||||
let s1 = testContent.substring(rsa[i], rsa[i] + la[i]);
|
||||
const s2 = lineIndex.getText(rsa[i], la[i]);
|
||||
const s1 = testContent.substring(rsa[i], rsa[i] + la[i]);
|
||||
assert.equal(s1, s2);
|
||||
}
|
||||
});
|
||||
|
||||
it("Range (average length 4 chars)", () => {
|
||||
for (let j = 0; j < iterationCount; j++) {
|
||||
let s2 = lineIndex.getText(rsa[j], las[j]);
|
||||
let s1 = testContent.substring(rsa[j], rsa[j] + las[j]);
|
||||
const s2 = lineIndex.getText(rsa[j], las[j]);
|
||||
const s1 = testContent.substring(rsa[j], rsa[j] + las[j]);
|
||||
assert.equal(s1, s2);
|
||||
}
|
||||
});
|
||||
|
||||
it("Edit (average length 4)", () => {
|
||||
for (let i = 0; i < iterationCount; i++) {
|
||||
let insertString = testContent.substring(rsa[100000 - i], rsa[100000 - i] + las[100000 - i]);
|
||||
let snapshot = lineIndex.edit(rsa[i], las[i], insertString);
|
||||
let checkText = editFlat(rsa[i], las[i], insertString, testContent);
|
||||
let snapText = snapshot.getText(0, checkText.length);
|
||||
const insertString = testContent.substring(rsa[100000 - i], rsa[100000 - i] + las[100000 - i]);
|
||||
const snapshot = lineIndex.edit(rsa[i], las[i], insertString);
|
||||
const checkText = editFlat(rsa[i], las[i], insertString, testContent);
|
||||
const snapText = snapshot.getText(0, checkText.length);
|
||||
assert.equal(checkText, snapText);
|
||||
}
|
||||
});
|
||||
|
||||
it("Edit ScriptVersionCache ", () => {
|
||||
let svc = server.ScriptVersionCache.fromString(<server.ServerHost>ts.sys, testContent);
|
||||
const svc = server.ScriptVersionCache.fromString(<server.ServerHost>ts.sys, testContent);
|
||||
let checkText = testContent;
|
||||
|
||||
for (let i = 0; i < iterationCount; i++) {
|
||||
let insertString = testContent.substring(rsa[i], rsa[i] + las[i]);
|
||||
const insertString = testContent.substring(rsa[i], rsa[i] + las[i]);
|
||||
svc.edit(ersa[i], elas[i], insertString);
|
||||
checkText = editFlat(ersa[i], elas[i], insertString, checkText);
|
||||
if (0 == (i % 4)) {
|
||||
let snap = svc.getSnapshot();
|
||||
let snapText = snap.getText(0, checkText.length);
|
||||
const snap = svc.getSnapshot();
|
||||
const snapText = snap.getText(0, checkText.length);
|
||||
assert.equal(checkText, snapText);
|
||||
}
|
||||
}
|
||||
@ -288,18 +288,18 @@ and grew 1cm per day`;
|
||||
|
||||
it("Edit (average length 1/4th file size)", () => {
|
||||
for (let i = 0; i < iterationCount; i++) {
|
||||
let insertString = testContent.substring(rsa[100000 - i], rsa[100000 - i] + la[100000 - i]);
|
||||
let snapshot = lineIndex.edit(rsa[i], la[i], insertString);
|
||||
let checkText = editFlat(rsa[i], la[i], insertString, testContent);
|
||||
let snapText = snapshot.getText(0, checkText.length);
|
||||
const insertString = testContent.substring(rsa[100000 - i], rsa[100000 - i] + la[100000 - i]);
|
||||
const snapshot = lineIndex.edit(rsa[i], la[i], insertString);
|
||||
const checkText = editFlat(rsa[i], la[i], insertString, testContent);
|
||||
const snapText = snapshot.getText(0, checkText.length);
|
||||
assert.equal(checkText, snapText);
|
||||
}
|
||||
});
|
||||
|
||||
it("Line/offset from pos", () => {
|
||||
for (let i = 0; i < iterationCount; i++) {
|
||||
let lp = lineIndex.charOffsetToLineNumberAndPos(rsa[i]);
|
||||
let lac = ts.computeLineAndCharacterOfPosition(lineMap, rsa[i]);
|
||||
const lp = lineIndex.charOffsetToLineNumberAndPos(rsa[i]);
|
||||
const lac = ts.computeLineAndCharacterOfPosition(lineMap, rsa[i]);
|
||||
assert.equal(lac.line + 1, lp.line, "Line number mismatch " + (lac.line + 1) + " " + lp.line + " " + i);
|
||||
assert.equal(lac.character, (lp.offset), "Charachter offset mismatch " + lac.character + " " + lp.offset + " " + i);
|
||||
}
|
||||
@ -308,12 +308,12 @@ and grew 1cm per day`;
|
||||
it("Start pos from line", () => {
|
||||
for (let i = 0; i < iterationCount; i++) {
|
||||
for (let j = 0, llen = lines.length; j < llen; j++) {
|
||||
let lineInfo = lineIndex.lineNumberToInfo(j + 1);
|
||||
let lineIndexOffset = lineInfo.offset;
|
||||
let lineMapOffset = lineMap[j];
|
||||
const lineInfo = lineIndex.lineNumberToInfo(j + 1);
|
||||
const lineIndexOffset = lineInfo.offset;
|
||||
const lineMapOffset = lineMap[j];
|
||||
assert.equal(lineIndexOffset, lineMapOffset);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user