Verify errors more correctly in tsc-watch mode

This commit is contained in:
Sheetal Nandi
2017-10-10 20:19:46 -07:00
parent 9767d77143
commit 993890f06c
2 changed files with 193 additions and 168 deletions

View File

@@ -80,6 +80,92 @@ namespace ts.tscWatch {
checkOutputDoesNotContain(host, expectedNonAffectedFiles);
}
function checkOutputErrors(host: WatchedSystem, errors?: ReadonlyArray<Diagnostic>, isInitial?: true, skipWaiting?: true) {
const outputs = host.getOutput();
const expectedOutputCount = (isInitial ? 0 : 1) + (errors ? errors.length : 0) + (skipWaiting ? 0 : 1);
assert.equal(outputs.length, expectedOutputCount, "Outputs = " + outputs.toString());
let index = 0;
if (!isInitial) {
assertWatchDiagnosticAt(host, index, Diagnostics.File_change_detected_Starting_incremental_compilation);
index++;
}
forEach(errors, error => {
assertDiagnosticAt(host, index, error);
index++;
});
if (!skipWaiting) {
assertWatchDiagnosticAt(host, index, Diagnostics.Compilation_complete_Watching_for_file_changes);
}
host.clearOutput();
}
function assertDiagnosticAt(host: WatchedSystem, outputAt: number, diagnostic: Diagnostic) {
const output = host.getOutput()[outputAt];
assert.equal(output, formatDiagnostic(diagnostic, host), "outputs[" + outputAt + "] is " + output);
}
function assertWatchDiagnosticAt(host: WatchedSystem, outputAt: number, diagnosticMessage: DiagnosticMessage) {
const output = host.getOutput()[outputAt];
assert.isTrue(endsWith(output, getWatchDiagnosticWithoutDate(host, diagnosticMessage)), "outputs[" + outputAt + "] is " + output);
}
function getWatchDiagnosticWithoutDate(host: WatchedSystem, diagnosticMessage: DiagnosticMessage) {
return ` - ${flattenDiagnosticMessageText(getLocaleSpecificMessage(diagnosticMessage), host.newLine)}${host.newLine + host.newLine + host.newLine}`;
}
function getDiagnosticOfFileFrom(file: SourceFile, text: string, start: number, length: number, message: DiagnosticMessage): Diagnostic {
return {
file,
start,
length,
messageText: text,
category: message.category,
code: message.code,
};
}
function getDiagnosticWithoutFile(message: DiagnosticMessage, ..._args: (string | number)[]): Diagnostic {
let text = getLocaleSpecificMessage(message);
if (arguments.length > 1) {
text = formatStringFromArgs(text, arguments, 1);
}
return getDiagnosticOfFileFrom(/*file*/ undefined, text, /*start*/ undefined, /*length*/ undefined, message);
}
function getDiagnosticOfFile(file: SourceFile, start: number, length: number, message: DiagnosticMessage, ..._args: (string | number)[]): Diagnostic {
let text = getLocaleSpecificMessage(message);
if (arguments.length > 4) {
text = formatStringFromArgs(text, arguments, 4);
}
return getDiagnosticOfFileFrom(file, text, start, length, message);
}
function getUnknownCompilerOption(program: Program, configFile: FileOrFolder, option: string) {
const quotedOption = `"${option}"`;
return getDiagnosticOfFile(program.getCompilerOptions().configFile, configFile.content.indexOf(quotedOption), quotedOption.length, Diagnostics.Unknown_compiler_option_0, option);
}
function getDiagnosticOfFileFromProgram(program: Program, filePath: string, start: number, length: number, message: DiagnosticMessage, ..._args: (string | number)[]): Diagnostic {
let text = getLocaleSpecificMessage(message);
if (arguments.length > 5) {
text = formatStringFromArgs(text, arguments, 5);
}
return getDiagnosticOfFileFrom(program.getSourceFileByPath(toPath(filePath, program.getCurrentDirectory(), s => s.toLowerCase())),
text, start, length, message);
}
function getDiagnosticModuleNotFoundOfFile(program: Program, file: FileOrFolder, moduleName: string) {
const quotedModuleName = `"${moduleName}"`;
return getDiagnosticOfFileFromProgram(program, file.path, file.content.indexOf(quotedModuleName), quotedModuleName.length, Diagnostics.Cannot_find_module_0, moduleName);
}
describe("tsc-watch program updates", () => {
const commonFile1: FileOrFolder = {
path: "/a/b/commonFile1.ts",
@@ -233,9 +319,10 @@ namespace ts.tscWatch {
});
it("handles the missing files - that were added to program because they were added with ///<ref", () => {
const commonFile2Name = "commonFile2.ts";
const file1: FileOrFolder = {
path: "/a/b/commonFile1.ts",
content: `/// <reference path="commonFile2.ts"/>
content: `/// <reference path="${commonFile2Name}"/>
let x = y`
};
const host = createWatchedSystem([file1, libFile]);
@@ -243,18 +330,16 @@ namespace ts.tscWatch {
checkProgramRootFiles(watch(), [file1.path]);
checkProgramActualFiles(watch(), [file1.path, libFile.path]);
const errors = [
`a/b/commonFile1.ts(1,22): error TS6053: File '${commonFile2.path}' not found.${host.newLine}`,
`a/b/commonFile1.ts(2,29): error TS2304: Cannot find name 'y'.${host.newLine}`
];
checkOutputContains(host, errors);
host.clearOutput();
checkOutputErrors(host, [
getDiagnosticOfFileFromProgram(watch(), file1.path, file1.content.indexOf(commonFile2Name), commonFile2Name.length, Diagnostics.File_0_not_found, commonFile2.path),
getDiagnosticOfFileFromProgram(watch(), file1.path, file1.content.indexOf("y"), 1, Diagnostics.Cannot_find_name_0, "y")
], /*isInitial*/ true);
host.reloadFS([file1, commonFile2, libFile]);
host.runQueuedTimeoutCallbacks();
checkProgramRootFiles(watch(), [file1.path]);
checkProgramActualFiles(watch(), [file1.path, libFile.path, commonFile2.path]);
checkOutputDoesNotContain(host, errors);
checkOutputErrors(host);
});
it("should reflect change in config file", () => {
@@ -578,17 +663,19 @@ namespace ts.tscWatch {
path: "/a/b/tsconfig.json",
content: JSON.stringify({ compilerOptions: {} })
};
const host = createWatchedSystem([file1, file2, config]);
const host = createWatchedSystem([file1, file2, libFile, config]);
const watch = createWatchModeWithConfigFile(config.path, host);
checkProgramActualFiles(watch(), [file1.path, file2.path]);
checkProgramActualFiles(watch(), [file1.path, file2.path, libFile.path]);
checkOutputErrors(host, emptyArray, /*isInitial*/ true);
host.clearOutput();
host.reloadFS([file1, file2]);
host.reloadFS([file1, file2, libFile]);
host.checkTimeoutQueueLengthAndRun(1);
assert.equal(host.exitCode, ExitStatus.DiagnosticsPresent_OutputsSkipped);
checkOutputContains(host, [`error TS6053: File '${config.path}' not found.${host.newLine}`]);
checkOutputErrors(host, [
getDiagnosticWithoutFile(Diagnostics.File_0_not_found, config.path)
], /*isInitial*/ undefined, /*skipWaiting*/ true);
});
it("Proper errors: document is not contained in project", () => {
@@ -687,25 +774,25 @@ namespace ts.tscWatch {
};
const file1 = {
path: "/a/b/file1.ts",
content: "import * as T from './moduleFile'; T.bar();"
content: 'import * as T from "./moduleFile"; T.bar();'
};
const host = createWatchedSystem([moduleFile, file1, libFile]);
createWatchModeWithoutConfigFile([file1.path], host);
const error = "a/b/file1.ts(1,20): error TS2307: Cannot find module \'./moduleFile\'.\n";
checkOutputDoesNotContain(host, [error]);
const watch = createWatchModeWithoutConfigFile([file1.path], host);
checkOutputErrors(host, emptyArray, /*isInitial*/ true);
const moduleFileOldPath = moduleFile.path;
const moduleFileNewPath = "/a/b/moduleFile1.ts";
moduleFile.path = moduleFileNewPath;
host.reloadFS([moduleFile, file1, libFile]);
host.runQueuedTimeoutCallbacks();
checkOutputContains(host, [error]);
checkOutputErrors(host, [
getDiagnosticModuleNotFoundOfFile(watch(), file1, "./moduleFile")
]);
host.clearOutput();
moduleFile.path = moduleFileOldPath;
host.reloadFS([moduleFile, file1, libFile]);
host.runQueuedTimeoutCallbacks();
checkOutputDoesNotContain(host, [error]);
checkOutputErrors(host);
});
it("rename a module file and rename back should restore the states for configured projects", () => {
@@ -715,31 +802,29 @@ namespace ts.tscWatch {
};
const file1 = {
path: "/a/b/file1.ts",
content: "import * as T from './moduleFile'; T.bar();"
content: 'import * as T from "./moduleFile"; T.bar();'
};
const configFile = {
path: "/a/b/tsconfig.json",
content: `{}`
};
const host = createWatchedSystem([moduleFile, file1, configFile, libFile]);
createWatchModeWithConfigFile(configFile.path, host);
const error = "a/b/file1.ts(1,20): error TS2307: Cannot find module \'./moduleFile\'.\n";
checkOutputDoesNotContain(host, [error]);
const watch = createWatchModeWithConfigFile(configFile.path, host);
checkOutputErrors(host, emptyArray, /*isInitial*/ true);
const moduleFileOldPath = moduleFile.path;
const moduleFileNewPath = "/a/b/moduleFile1.ts";
moduleFile.path = moduleFileNewPath;
host.clearOutput();
host.reloadFS([moduleFile, file1, configFile, libFile]);
host.runQueuedTimeoutCallbacks();
checkOutputContains(host, [error]);
checkOutputErrors(host, [
getDiagnosticModuleNotFoundOfFile(watch(), file1, "./moduleFile")
]);
host.clearOutput();
moduleFile.path = moduleFileOldPath;
host.reloadFS([moduleFile, file1, configFile, libFile]);
host.runQueuedTimeoutCallbacks();
checkOutputDoesNotContain(host, [error]);
checkOutputErrors(host);
});
it("types should load from config file path if config exists", () => {
@@ -771,18 +856,18 @@ namespace ts.tscWatch {
};
const file1 = {
path: "/a/b/file1.ts",
content: "import * as T from './moduleFile'; T.bar();"
content: 'import * as T from "./moduleFile"; T.bar();'
};
const host = createWatchedSystem([file1, libFile]);
createWatchModeWithoutConfigFile([file1.path], host);
const watch = createWatchModeWithoutConfigFile([file1.path], host);
const error = `a/b/file1.ts(1,20): error TS2307: Cannot find module \'./moduleFile\'.${host.newLine}`;
checkOutputContains(host, [error]);
host.clearOutput();
checkOutputErrors(host, [
getDiagnosticModuleNotFoundOfFile(watch(), file1, "./moduleFile")
], /*isInitial*/ true);
host.reloadFS([file1, moduleFile, libFile]);
host.runQueuedTimeoutCallbacks();
checkOutputDoesNotContain(host, [error]);
checkOutputErrors(host);
});
it("Configure file diagnostics events are generated when the config file has errors", () => {
@@ -801,14 +886,14 @@ namespace ts.tscWatch {
};
const host = createWatchedSystem([file, configFile, libFile]);
createWatchModeWithConfigFile(configFile.path, host);
checkOutputContains(host, [
`a/b/tsconfig.json(3,29): error TS5023: Unknown compiler option \'foo\'.${host.newLine}`,
`a/b/tsconfig.json(4,29): error TS5023: Unknown compiler option \'allowJS\'.${host.newLine}`
]);
const watch = createWatchModeWithConfigFile(configFile.path, host);
checkOutputErrors(host, [
getUnknownCompilerOption(watch(), configFile, "foo"),
getUnknownCompilerOption(watch(), configFile, "allowJS")
], /*isInitial*/ true);
});
it("Configure file diagnostics events are generated when the config file doesn't have errors", () => {
it("If config file doesnt have errors, they are not reported", () => {
const file = {
path: "/a/b/app.ts",
content: "let x = 10"
@@ -822,13 +907,10 @@ namespace ts.tscWatch {
const host = createWatchedSystem([file, configFile, libFile]);
createWatchModeWithConfigFile(configFile.path, host);
checkOutputDoesNotContain(host, [
`a/b/tsconfig.json(3,29): error TS5023: Unknown compiler option \'foo\'.${host.newLine}`,
`a/b/tsconfig.json(4,29): error TS5023: Unknown compiler option \'allowJS\'.${host.newLine}`
]);
checkOutputErrors(host, emptyArray, /*isInitial*/ true);
});
it("Configure file diagnostics events are generated when the config file changes", () => {
it("Reports errors when the config file changes", () => {
const file = {
path: "/a/b/app.ts",
content: "let x = 10"
@@ -841,9 +923,8 @@ namespace ts.tscWatch {
};
const host = createWatchedSystem([file, configFile, libFile]);
createWatchModeWithConfigFile(configFile.path, host);
const error = `a/b/tsconfig.json(3,25): error TS5023: Unknown compiler option 'haha'.${host.newLine}`;
checkOutputDoesNotContain(host, [error]);
const watch = createWatchModeWithConfigFile(configFile.path, host);
checkOutputErrors(host, emptyArray, /*isInitial*/ true);
configFile.content = `{
"compilerOptions": {
@@ -852,15 +933,16 @@ namespace ts.tscWatch {
}`;
host.reloadFS([file, configFile, libFile]);
host.runQueuedTimeoutCallbacks();
checkOutputContains(host, [error]);
checkOutputErrors(host, [
getUnknownCompilerOption(watch(), configFile, "haha")
]);
host.clearOutput();
configFile.content = `{
"compilerOptions": {}
}`;
host.reloadFS([file, configFile, libFile]);
host.runQueuedTimeoutCallbacks();
checkOutputDoesNotContain(host, [error]);
checkOutputErrors(host);
});
it("non-existing directories listed in config file input array should be tolerated without crashing the server", () => {
@@ -935,29 +1017,28 @@ namespace ts.tscWatch {
}`;
const configFileContentWithComment = configFileContentBeforeComment + configFileContentComment + configFileContentAfterComment;
const configFileContentWithoutCommentLine = configFileContentBeforeComment + configFileContentAfterComment;
const line = 5;
const errors = (line: number) => [
`a/b/tsconfig.json(${line},25): error TS5053: Option \'allowJs\' cannot be specified with option \'declaration\'.\n`,
`a/b/tsconfig.json(${line + 1},25): error TS5053: Option \'allowJs\' cannot be specified with option \'declaration\'.\n`
];
const configFile = {
path: "/a/b/tsconfig.json",
content: configFileContentWithComment
};
const host = createWatchedSystem([file, libFile, configFile]);
createWatchModeWithConfigFile(configFile.path, host);
checkOutputContains(host, errors(line));
checkOutputDoesNotContain(host, errors(line - 2));
host.clearOutput();
const files = [file, libFile, configFile];
const host = createWatchedSystem(files);
const watch = createWatchModeWithConfigFile(configFile.path, host);
const errors = () => [
getDiagnosticOfFile(watch().getCompilerOptions().configFile, configFile.content.indexOf('"allowJs"'), '"allowJs"'.length, Diagnostics.Option_0_cannot_be_specified_with_option_1, "allowJs", "declaration"),
getDiagnosticOfFile(watch().getCompilerOptions().configFile, configFile.content.indexOf('"declaration"'), '"declaration"'.length, Diagnostics.Option_0_cannot_be_specified_with_option_1, "allowJs", "declaration")
];
const intialErrors = errors();
checkOutputErrors(host, intialErrors, /*isInitial*/ true);
configFile.content = configFileContentWithoutCommentLine;
host.reloadFS([file, configFile]);
host.reloadFS(files);
host.runQueuedTimeoutCallbacks();
checkOutputContains(host, errors(line - 2));
checkOutputDoesNotContain(host, errors(line));
const nowErrors = errors();
checkOutputErrors(host, nowErrors);
assert.equal(nowErrors[0].start, intialErrors[0].start - configFileContentComment.length);
assert.equal(nowErrors[1].start, intialErrors[1].start - configFileContentComment.length);
});
});
@@ -1485,23 +1566,20 @@ namespace ts.tscWatch {
path: "/a/d/f0.ts",
content: `import {x} from "f1"`
};
const imported = {
path: "/a/f1.ts",
content: `foo()`
};
const f1IsNotModule = `a/d/f0.ts(1,17): error TS2306: File '${imported.path}' is not a module.\n`;
const cannotFindFoo = `a/f1.ts(1,1): error TS2304: Cannot find name 'foo'.\n`;
const cannotAssignValue = "a/d/f0.ts(2,21): error TS2322: Type '1' is not assignable to type 'string'.\n";
const files = [root, imported, libFile];
const host = createWatchedSystem(files);
createWatchModeWithoutConfigFile([root.path], host, { module: ModuleKind.AMD });
const watch = createWatchModeWithoutConfigFile([root.path], host, { module: ModuleKind.AMD });
const f1IsNotModule = getDiagnosticOfFileFromProgram(watch(), root.path, root.content.indexOf('"f1"'), '"f1"'.length, Diagnostics.File_0_is_not_a_module, imported.path);
const cannotFindFoo = getDiagnosticOfFileFromProgram(watch(), imported.path, imported.content.indexOf("foo"), "foo".length, Diagnostics.Cannot_find_name_0, "foo");
// ensure that imported file was found
checkOutputContains(host, [f1IsNotModule, cannotFindFoo]);
host.clearOutput();
checkOutputErrors(host, [f1IsNotModule, cannotFindFoo], /*isInitial*/ true);
const originalFileExists = host.fileExists;
{
@@ -1517,8 +1595,11 @@ namespace ts.tscWatch {
host.runQueuedTimeoutCallbacks();
// ensure file has correct number of errors after edit
checkOutputContains(host, [f1IsNotModule, cannotAssignValue]);
host.clearOutput();
checkOutputErrors(host, [
f1IsNotModule,
getDiagnosticOfFileFromProgram(watch(), root.path, newContent.indexOf("var x") + "var ".length, "x".length, Diagnostics.Type_0_is_not_assignable_to_type_1, 1, "string"),
cannotFindFoo
]);
}
{
let fileExistsIsCalled = false;
@@ -1534,13 +1615,13 @@ namespace ts.tscWatch {
root.content = `import {x} from "f2"`;
host.reloadFS(files);
// trigger synchronization to make sure that LSHost will try to find 'f2' module on disk
host.runQueuedTimeoutCallbacks();
// trigger synchronization to make sure that LSHost will try to find 'f2' module on disk
host.runQueuedTimeoutCallbacks();
// ensure file has correct number of errors after edit
const cannotFindModuleF2 = `a/d/f0.ts(1,17): error TS2307: Cannot find module 'f2'.\n`;
checkOutputContains(host, [cannotFindModuleF2]);
host.clearOutput();
// ensure file has correct number of errors after edit
checkOutputErrors(host, [
getDiagnosticModuleNotFoundOfFile(watch(), root, "f2")
]);
assert.isTrue(fileExistsIsCalled);
}
@@ -1561,7 +1642,7 @@ namespace ts.tscWatch {
host.reloadFS(files);
host.runQueuedTimeoutCallbacks();
checkOutputContains(host, [f1IsNotModule, cannotFindFoo]);
checkOutputErrors(host, [f1IsNotModule, cannotFindFoo]);
assert.isTrue(fileExistsCalled);
}
});
@@ -1593,12 +1674,12 @@ namespace ts.tscWatch {
return originalFileExists.call(host, fileName);
};
createWatchModeWithoutConfigFile([root.path], host, { module: ModuleKind.AMD });
const watch = createWatchModeWithoutConfigFile([root.path], host, { module: ModuleKind.AMD });
const barNotFound = `a/foo.ts(1,17): error TS2307: Cannot find module 'bar'.\n`;
assert.isTrue(fileExistsCalledForBar, "'fileExists' should be called");
checkOutputContains(host, [barNotFound]);
host.clearOutput();
checkOutputErrors(host, [
getDiagnosticModuleNotFoundOfFile(watch(), root, "bar")
], /*isInitial*/ true);
fileExistsCalledForBar = false;
root.content = `import {y} from "bar"`;
@@ -1606,7 +1687,7 @@ namespace ts.tscWatch {
host.runQueuedTimeoutCallbacks();
assert.isTrue(fileExistsCalledForBar, "'fileExists' should be called.");
checkOutputDoesNotContain(host, [barNotFound]);
checkOutputErrors(host);
});
it("should compile correctly when resolved module goes missing and then comes back (module is not part of the root)", () => {
@@ -1617,7 +1698,7 @@ namespace ts.tscWatch {
const imported = {
path: `/a/bar.d.ts`,
content: `export const y = 1;`
content: `export const y = 1;export const x = 10;`
};
const files = [root, libFile];
@@ -1635,25 +1716,24 @@ namespace ts.tscWatch {
return originalFileExists.call(host, fileName);
};
createWatchModeWithoutConfigFile([root.path], host, { module: ModuleKind.AMD });
const watch = createWatchModeWithoutConfigFile([root.path], host, { module: ModuleKind.AMD });
const barNotFound = `a/foo.ts(1,17): error TS2307: Cannot find module 'bar'.\n`;
assert.isTrue(fileExistsCalledForBar, "'fileExists' should be called");
checkOutputDoesNotContain(host, [barNotFound]);
host.clearOutput();
checkOutputErrors(host, emptyArray, /*isInitial*/ true);
fileExistsCalledForBar = false;
host.reloadFS(files);
host.runQueuedTimeoutCallbacks();
assert.isTrue(fileExistsCalledForBar, "'fileExists' should be called.");
checkOutputContains(host, [barNotFound]);
host.clearOutput();
checkOutputErrors(host, [
getDiagnosticModuleNotFoundOfFile(watch(), root, "bar")
]);
fileExistsCalledForBar = false;
host.reloadFS(filesWithImported);
host.checkTimeoutQueueLengthAndRun(1);
assert.isTrue(fileExistsCalledForBar, "'fileExists' should be called.");
checkOutputDoesNotContain(host, [barNotFound]);
checkOutputErrors(host);
});
it("works when module resolution changes to ambient module", () => {
@@ -1677,30 +1757,6 @@ namespace ts.tscWatch {
declare module "fs" {
export interface Stats {
isFile(): boolean;
isDirectory(): boolean;
isBlockDevice(): boolean;
isCharacterDevice(): boolean;
isSymbolicLink(): boolean;
isFIFO(): boolean;
isSocket(): boolean;
dev: number;
ino: number;
mode: number;
nlink: number;
uid: number;
gid: number;
rdev: number;
size: number;
blksize: number;
blocks: number;
atimeMs: number;
mtimeMs: number;
ctimeMs: number;
birthtimeMs: number;
atime: Date;
mtime: Date;
ctime: Date;
birthtime: Date;
}
}`
};
@@ -1709,15 +1765,15 @@ declare module "fs" {
const filesWithNodeType = files.concat(packageJson, nodeType);
const host = createWatchedSystem(files, { currentDirectory: "/a/b" });
createWatchModeWithoutConfigFile([root.path], host, { });
const watch = createWatchModeWithoutConfigFile([root.path], host, { });
const fsNotFound = `foo.ts(1,21): error TS2307: Cannot find module 'fs'.\n`;
checkOutputContains(host, [fsNotFound]);
host.clearOutput();
checkOutputErrors(host, [
getDiagnosticModuleNotFoundOfFile(watch(), root, "fs")
], /*isInitial*/ true);
host.reloadFS(filesWithNodeType);
host.runQueuedTimeoutCallbacks();
checkOutputDoesNotContain(host, [fsNotFound]);
checkOutputErrors(host);
});
it("works when included file with ambient module changes", () => {
@@ -1735,17 +1791,6 @@ import * as u from "url";
declare module "url" {
export interface Url {
href?: string;
protocol?: string;
auth?: string;
hostname?: string;
port?: string;
host?: string;
pathname?: string;
search?: string;
query?: string | any;
slashes?: boolean;
hash?: string;
path?: string;
}
}
`
@@ -1755,30 +1800,6 @@ declare module "url" {
declare module "fs" {
export interface Stats {
isFile(): boolean;
isDirectory(): boolean;
isBlockDevice(): boolean;
isCharacterDevice(): boolean;
isSymbolicLink(): boolean;
isFIFO(): boolean;
isSocket(): boolean;
dev: number;
ino: number;
mode: number;
nlink: number;
uid: number;
gid: number;
rdev: number;
size: number;
blksize: number;
blocks: number;
atimeMs: number;
mtimeMs: number;
ctimeMs: number;
birthtimeMs: number;
atime: Date;
mtime: Date;
ctime: Date;
birthtime: Date;
}
}
`;
@@ -1786,16 +1807,16 @@ declare module "fs" {
const files = [root, file, libFile];
const host = createWatchedSystem(files, { currentDirectory: "/a/b" });
createWatchModeWithoutConfigFile([root.path, file.path], host, {});
const watch = createWatchModeWithoutConfigFile([root.path, file.path], host, {});
const fsNotFound = `foo.ts(2,21): error TS2307: Cannot find module 'fs'.\n`;
checkOutputContains(host, [fsNotFound]);
host.clearOutput();
checkOutputErrors(host, [
getDiagnosticModuleNotFoundOfFile(watch(), root, "fs")
], /*isInitial*/ true);
file.content += fileContentWithFS;
host.reloadFS(files);
host.runQueuedTimeoutCallbacks();
checkOutputDoesNotContain(host, [fsNotFound]);
checkOutputErrors(host);
});
});
}

View File

@@ -212,13 +212,13 @@ namespace ts.TestFSWithWatch {
directoryName: string;
}
export class TestServerHost implements server.ServerHost {
export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost {
args: string[] = [];
private readonly output: string[] = [];
private fs: Map<FSEntry> = createMap<FSEntry>();
private getCanonicalFileName: (s: string) => string;
getCanonicalFileName: (s: string) => string;
private toPath: (f: string) => Path;
private timeoutCallbacks = new Callbacks();
private immediateCallbacks = new Callbacks();
@@ -234,6 +234,10 @@ namespace ts.TestFSWithWatch {
this.reloadFS(fileOrFolderList);
}
getNewLine() {
return this.newLine;
}
toNormalizedAbsolutePath(s: string) {
return getNormalizedAbsolutePath(s, this.currentDirectory);
}