Merge remote-tracking branch 'origin/master' into tsserverVS-WIP

This commit is contained in:
Vladimir Matveev 2016-06-07 23:10:11 -07:00
commit 82715e22a2
9 changed files with 512 additions and 31 deletions

View File

@ -2613,11 +2613,21 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
return isSourceFileLevelDeclarationInSystemJsModule(targetDeclaration, /*isExported*/ true);
}
function isNameOfExportedDeclarationInNonES6Module(node: Node): boolean {
if (modulekind === ModuleKind.System || node.kind !== SyntaxKind.Identifier || nodeIsSynthesized(node)) {
return false;
}
return !exportEquals && exportSpecifiers && hasProperty(exportSpecifiers, (<Identifier>node).text);
}
function emitPrefixUnaryExpression(node: PrefixUnaryExpression) {
const exportChanged = (node.operator === SyntaxKind.PlusPlusToken || node.operator === SyntaxKind.MinusMinusToken) &&
const isPlusPlusOrMinusMinus = (node.operator === SyntaxKind.PlusPlusToken
|| node.operator === SyntaxKind.MinusMinusToken);
const externalExportChanged = isPlusPlusOrMinusMinus &&
isNameOfExportedSourceLevelDeclarationInSystemExternalModule(node.operand);
if (exportChanged) {
if (externalExportChanged) {
// emit
// ++x
// as
@ -2626,6 +2636,12 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
emitNodeWithoutSourceMap(node.operand);
write(`", `);
}
const internalExportChanged = isPlusPlusOrMinusMinus &&
isNameOfExportedDeclarationInNonES6Module(node.operand);
if (internalExportChanged) {
emitAliasEqual(<Identifier> node.operand);
}
write(tokenToString(node.operator));
// In some cases, we need to emit a space between the operator and the operand. One obvious case
@ -2651,14 +2667,16 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
}
emit(node.operand);
if (exportChanged) {
if (externalExportChanged) {
write(")");
}
}
function emitPostfixUnaryExpression(node: PostfixUnaryExpression) {
const exportChanged = isNameOfExportedSourceLevelDeclarationInSystemExternalModule(node.operand);
if (exportChanged) {
const externalExportChanged = isNameOfExportedSourceLevelDeclarationInSystemExternalModule(node.operand);
const internalExportChanged = isNameOfExportedDeclarationInNonES6Module(node.operand);
if (externalExportChanged) {
// export function returns the value that was passes as the second argument
// however for postfix unary expressions result value should be the value before modification.
// emit 'x++' as '(export('x', ++x) - 1)' and 'x--' as '(export('x', --x) + 1)'
@ -2676,6 +2694,16 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
write(") + 1)");
}
}
else if (internalExportChanged) {
emitAliasEqual(<Identifier> node.operand);
emit(node.operand);
if (node.operator === SyntaxKind.PlusPlusToken) {
write(" += 1");
}
else {
write(" -= 1");
}
}
else {
emit(node.operand);
write(tokenToString(node.operator));
@ -2777,24 +2805,50 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
}
}
function emitAliasEqual(name: Identifier): boolean {
for (const specifier of exportSpecifiers[name.text]) {
emitStart(specifier.name);
emitContainingModuleName(specifier);
if (languageVersion === ScriptTarget.ES3 && name.text === "default") {
write('["default"]');
}
else {
write(".");
emitNodeWithCommentsAndWithoutSourcemap(specifier.name);
}
emitEnd(specifier.name);
write(" = ");
}
return true;
}
function emitBinaryExpression(node: BinaryExpression) {
if (languageVersion < ScriptTarget.ES6 && node.operatorToken.kind === SyntaxKind.EqualsToken &&
(node.left.kind === SyntaxKind.ObjectLiteralExpression || node.left.kind === SyntaxKind.ArrayLiteralExpression)) {
emitDestructuring(node, node.parent.kind === SyntaxKind.ExpressionStatement);
}
else {
const exportChanged =
node.operatorToken.kind >= SyntaxKind.FirstAssignment &&
node.operatorToken.kind <= SyntaxKind.LastAssignment &&
const isAssignment = isAssignmentOperator(node.operatorToken.kind);
const externalExportChanged = isAssignment &&
isNameOfExportedSourceLevelDeclarationInSystemExternalModule(node.left);
if (exportChanged) {
if (externalExportChanged) {
// emit assignment 'x <op> y' as 'exports("x", x <op> y)'
write(`${exportFunctionForFile}("`);
emitNodeWithoutSourceMap(node.left);
write(`", `);
}
const internalExportChanged = isAssignment &&
isNameOfExportedDeclarationInNonES6Module(node.left);
if (internalExportChanged) {
// export { foo }
// emit foo = 2 as exports.foo = foo = 2
emitAliasEqual(<Identifier>node.left);
}
if (node.operatorToken.kind === SyntaxKind.AsteriskAsteriskToken || node.operatorToken.kind === SyntaxKind.AsteriskAsteriskEqualsToken) {
// Downleveled emit exponentiation operator using Math.pow
emitExponentiationOperator(node);
@ -2815,7 +2869,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
decreaseIndentIf(indentedBeforeOperator, indentedAfterOperator);
}
if (exportChanged) {
if (externalExportChanged) {
write(")");
}
}

View File

@ -1143,6 +1143,7 @@ namespace ts {
// if any of these properties has changed - structure cannot be reused
const oldOptions = oldProgram.getCompilerOptions();
if ((oldOptions.module !== options.module) ||
(oldOptions.moduleResolution !== options.moduleResolution) ||
(oldOptions.noResolve !== options.noResolve) ||
(oldOptions.target !== options.target) ||
(oldOptions.noLib !== options.noLib) ||

View File

@ -2,7 +2,7 @@
namespace ts {
export type FileWatcherCallback = (fileName: string, removed?: boolean) => void;
export type DirectoryWatcherCallback = (directoryName: string) => void;
export type DirectoryWatcherCallback = (fileName: string) => void;
export interface WatchedFile {
fileName: string;
callback: FileWatcherCallback;

View File

@ -2919,6 +2919,7 @@ namespace ts {
const changesInCompilationSettingsAffectSyntax = oldSettings &&
(oldSettings.target !== newSettings.target ||
oldSettings.module !== newSettings.module ||
oldSettings.moduleResolution !== newSettings.moduleResolution ||
oldSettings.noResolve !== newSettings.noResolve ||
oldSettings.jsx !== newSettings.jsx ||
oldSettings.allowJs !== newSettings.allowJs);

View File

@ -0,0 +1,36 @@
//// [server.ts]
var foo = 2;
foo = 3;
var baz = 3;
baz = 4;
var buzz = 10;
buzz += 3;
var bizz = 8;
bizz++; // compiles to exports.bizz = bizz += 1
bizz--; // similarly
++bizz; // compiles to exports.bizz = ++bizz
export { foo, baz, baz as quux, buzz, bizz };
//// [server.js]
"use strict";
var foo = 2;
exports.foo = foo;
exports.foo = foo = 3;
var baz = 3;
exports.baz = baz;
exports.quux = baz;
exports.baz = exports.quux = baz = 4;
var buzz = 10;
exports.buzz = buzz;
exports.buzz = buzz += 3;
var bizz = 8;
exports.bizz = bizz;
exports.bizz = bizz += 1; // compiles to exports.bizz = bizz += 1
exports.bizz = bizz -= 1; // similarly
exports.bizz = ++bizz; // compiles to exports.bizz = ++bizz

View File

@ -0,0 +1,40 @@
=== tests/cases/compiler/server.ts ===
var foo = 2;
>foo : Symbol(foo, Decl(server.ts, 1, 3))
foo = 3;
>foo : Symbol(foo, Decl(server.ts, 1, 3))
var baz = 3;
>baz : Symbol(baz, Decl(server.ts, 4, 3))
baz = 4;
>baz : Symbol(baz, Decl(server.ts, 4, 3))
var buzz = 10;
>buzz : Symbol(buzz, Decl(server.ts, 7, 3))
buzz += 3;
>buzz : Symbol(buzz, Decl(server.ts, 7, 3))
var bizz = 8;
>bizz : Symbol(bizz, Decl(server.ts, 10, 3))
bizz++; // compiles to exports.bizz = bizz += 1
>bizz : Symbol(bizz, Decl(server.ts, 10, 3))
bizz--; // similarly
>bizz : Symbol(bizz, Decl(server.ts, 10, 3))
++bizz; // compiles to exports.bizz = ++bizz
>bizz : Symbol(bizz, Decl(server.ts, 10, 3))
export { foo, baz, baz as quux, buzz, bizz };
>foo : Symbol(foo, Decl(server.ts, 15, 8))
>baz : Symbol(baz, Decl(server.ts, 15, 13))
>baz : Symbol(quux, Decl(server.ts, 15, 18))
>quux : Symbol(quux, Decl(server.ts, 15, 18))
>buzz : Symbol(buzz, Decl(server.ts, 15, 31))
>bizz : Symbol(bizz, Decl(server.ts, 15, 37))

View File

@ -0,0 +1,53 @@
=== tests/cases/compiler/server.ts ===
var foo = 2;
>foo : number
>2 : number
foo = 3;
>foo = 3 : number
>foo : number
>3 : number
var baz = 3;
>baz : number
>3 : number
baz = 4;
>baz = 4 : number
>baz : number
>4 : number
var buzz = 10;
>buzz : number
>10 : number
buzz += 3;
>buzz += 3 : number
>buzz : number
>3 : number
var bizz = 8;
>bizz : number
>8 : number
bizz++; // compiles to exports.bizz = bizz += 1
>bizz++ : number
>bizz : number
bizz--; // similarly
>bizz-- : number
>bizz : number
++bizz; // compiles to exports.bizz = ++bizz
>++bizz : number
>bizz : number
export { foo, baz, baz as quux, buzz, bizz };
>foo : number
>baz : number
>baz : number
>quux : number
>buzz : number
>bizz : number

View File

@ -0,0 +1,19 @@
// @target: es5
// @module: commonjs
// @filename: server.ts
var foo = 2;
foo = 3;
var baz = 3;
baz = 4;
var buzz = 10;
buzz += 3;
var bizz = 8;
bizz++; // compiles to exports.bizz = bizz += 1
bizz--; // similarly
++bizz; // compiles to exports.bizz = ++bizz
export { foo, baz, baz as quux, buzz, bizz };

View File

@ -107,6 +107,32 @@ namespace ts {
}
}
function checkNumberOfConfiguredProjects(projectService: server.ProjectService, expected: number) {
assert.equal(projectService.configuredProjects.length, expected, `expected ${expected} configured project(s)`);
}
function checkNumberOfInferredProjects(projectService: server.ProjectService, expected: number) {
assert.equal(projectService.inferredProjects.length, expected, `expected ${expected} inferred project(s)`);
}
function checkWatchedFiles(host: TestServerHost, expectedFiles: string[]) {
checkMapKeys("watchedFiles", host.watchedFiles, expectedFiles);
}
function checkWatchedDirectories(host: TestServerHost, expectedDirectories: string[]) {
checkMapKeys("watchedDirectories", host.watchedDirectories, expectedDirectories);
}
function checkConfiguredProjectActualFiles(project: server.Project, expectedFiles: string[]) {
checkFileNames("configuredProjects project, actualFileNames", project.getFileNames(), expectedFiles);
}
function checkConfiguredProjectRootFiles(project: server.Project, expectedFiles: string[]) {
checkFileNames("configuredProjects project, rootFileNames", project.getRootFiles(), expectedFiles);
}
type TimeOutCallback = () => any;
class TestServerHost implements server.ServerHost {
args: string[] = [];
newLine: "\n";
@ -114,6 +140,7 @@ namespace ts {
private fs: ts.FileMap<FSEntry>;
private getCanonicalFileName: (s: string) => string;
private toPath: (f: string) => Path;
private callbackQueue: TimeOutCallback[] = [];
readonly watchedDirectories: Map<{ cb: DirectoryWatcherCallback, recursive: boolean }[]> = {};
readonly watchedFiles: Map<FileWatcherCallback[]> = {};
@ -188,6 +215,26 @@ namespace ts {
};
}
triggerDirectoryWatcherCallback(directoryName: string, fileName: string): void {
const path = this.toPath(directoryName);
const callbacks = lookUp(this.watchedDirectories, path);
if (callbacks) {
for (const callback of callbacks) {
callback.cb(fileName);
}
}
}
triggerFileWatcherCallback(fileName: string, removed?: boolean): void {
const path = this.toPath(fileName);
const callbacks = lookUp(this.watchedFiles, path);
if (callbacks) {
for (const callback of callbacks) {
callback(path, removed);
}
}
}
watchFile(fileName: string, callback: FileWatcherCallback) {
const path = this.toPath(fileName);
const callbacks = lookUp(this.watchedFiles, path) || (this.watchedFiles[path] = []);
@ -204,8 +251,27 @@ namespace ts {
}
// TOOD: record and invoke callbacks to simulate timer events
readonly setTimeout = (callback: (...args: any[]) => void, ms: number, ...args: any[]): any => void 0;
readonly clearTimeout = (timeoutId: any): void => void 0;
readonly setTimeout = (callback: TimeOutCallback, time: number) => {
this.callbackQueue.push(callback);
return this.callbackQueue.length - 1;
};
readonly clearTimeout = (timeoutId: any): void => {
if (typeof timeoutId === "number") {
this.callbackQueue.splice(timeoutId, 1);
}
};
checkTimeoutQueueLength(expected: number) {
assert.equal(this.callbackQueue.length, expected, `expected ${expected} timeout callbacks queued but found ${this.callbackQueue.length}.`);
}
runQueuedTimeoutCallbacks() {
for (const callback of this.callbackQueue) {
callback();
}
this.callbackQueue = [];
}
readonly readFile = (s: string) => (<File>this.fs.get(this.toPath(s))).content;
readonly resolvePath = (s: string) => s;
readonly getExecutingFilePath = () => this.executingFilePath;
@ -216,7 +282,20 @@ namespace ts {
readonly exit = () => notImplemented();
}
describe("tsserver project system:", () => {
describe("tsserver-project-system", () => {
const commonFile1: FileOrFolder = {
path: "/a/b/commonFile1.ts",
content: "let x = 1"
};
const commonFile2: FileOrFolder = {
path: "/a/b/commonFile2.ts",
content: "let y = 1"
};
const libFile: FileOrFolder = {
path: "/a/lib/lib.d.ts",
content: libFileContent
};
it("create inferred project", () => {
const appFile: FileOrFolder = {
path: "/a/b/c/app.ts",
@ -225,10 +304,7 @@ namespace ts {
console.log(f)
`
};
const libFile: FileOrFolder = {
path: "/a/lib/lib.d.ts",
content: libFileContent
};
const moduleFile: FileOrFolder = {
path: "/a/b/c/module.d.ts",
content: `export let x: number`
@ -238,13 +314,13 @@ namespace ts {
const { configFileName } = projectService.openClientFile(appFile.path);
assert(!configFileName, `should not find config, got: '${configFileName}`);
assert.equal(projectService.inferredProjects.length, 1, "expected one inferred project");
assert.equal(projectService.configuredProjects.length, 0, "expected no configured project");
checkNumberOfConfiguredProjects(projectService, 0);
checkNumberOfInferredProjects(projectService, 1);
const project = projectService.inferredProjects[0];
checkFileNames("inferred project", project.getFileNames(), [appFile.path, libFile.path, moduleFile.path]);
checkMapKeys("watchedDirectories", host.watchedDirectories, ["/a/b/c", "/a/b", "/a"]);
checkWatchedDirectories(host, ["/a/b/c", "/a/b", "/a"]);
});
it("create configured project without file list", () => {
@ -258,10 +334,6 @@ namespace ts {
]
}`
};
const libFile: FileOrFolder = {
path: "/a/lib/lib.d.ts",
content: libFileContent
};
const file1: FileOrFolder = {
path: "/a/b/c/f1.ts",
content: "let x = 1"
@ -274,21 +346,226 @@ namespace ts {
path: "/a/b/e/f3.ts",
content: "let z = 1"
};
const host = new TestServerHost(/*useCaseSensitiveFileNames*/ false, getExecutingFilePathFromLibFile(libFile), "/", [ configFile, libFile, file1, file2, file3 ]);
const projectService = new server.ProjectService(host, nullLogger);
const { configFileName, configFileErrors } = projectService.openClientFile(file1.path);
assert(configFileName, "should find config file");
assert.isTrue(!configFileErrors, `expect no errors in config file, got ${JSON.stringify(configFileErrors)}`);
assert.equal(projectService.inferredProjects.length, 0, "expected no inferred project");
assert.equal(projectService.configuredProjects.length, 1, "expected one configured project");
checkNumberOfInferredProjects(projectService, 0);
checkNumberOfConfiguredProjects(projectService, 1);
const project = projectService.configuredProjects[0];
checkFileNames("configuredProjects project, actualFileNames", project.getFileNames(), [file1.path, libFile.path, file2.path]);
checkFileNames("configuredProjects project, rootFileNames", project.getRootFiles(), [file1.path, file2.path]);
checkConfiguredProjectActualFiles(project, [file1.path, libFile.path, file2.path]);
checkConfiguredProjectRootFiles(project, [file1.path, file2.path]);
// watching all files except one that was open
checkWatchedFiles(host, [configFile.path, file2.path, libFile.path]);
checkWatchedDirectories(host, [getDirectoryPath(configFile.path)]);
});
checkMapKeys("watchedFiles", host.watchedFiles, [configFile.path, file2.path, libFile.path]); // watching all files except one that was open
checkMapKeys("watchedDirectories", host.watchedDirectories, [getDirectoryPath(configFile.path)]);
it("add and then remove a config file in a folder with loose files", () => {
const configFile: FileOrFolder = {
path: "/a/b/tsconfig.json",
content: `{
"files": ["commonFile1.ts"]
}`
};
const filesWithoutConfig = [ libFile, commonFile1, commonFile2 ];
const filesWithConfig = [ libFile, commonFile1, commonFile2, configFile ];
const host = new TestServerHost(/*useCaseSensitiveFileNames*/ false, getExecutingFilePathFromLibFile(libFile), "/", filesWithoutConfig);
const projectService = new server.ProjectService(host, nullLogger);
projectService.openClientFile(commonFile1.path);
projectService.openClientFile(commonFile2.path);
checkNumberOfInferredProjects(projectService, 2);
checkWatchedDirectories(host, ["/a/b", "/a"]);
// Add a tsconfig file
host.reloadFS(filesWithConfig);
host.triggerDirectoryWatcherCallback("/a/b", configFile.path);
checkNumberOfInferredProjects(projectService, 1);
checkNumberOfConfiguredProjects(projectService, 1);
// watching all files except one that was open
checkWatchedFiles(host, [libFile.path, configFile.path]);
// remove the tsconfig file
host.reloadFS(filesWithoutConfig);
host.triggerFileWatcherCallback(configFile.path);
checkNumberOfInferredProjects(projectService, 2);
checkNumberOfConfiguredProjects(projectService, 0);
checkWatchedDirectories(host, ["/a/b", "/a"]);
});
it("add new files to a configured project without file list", () => {
const configFile: FileOrFolder = {
path: "/a/b/tsconfig.json",
content: `{}`
};
const host = new TestServerHost(/*useCaseSensitiveFileNames*/ false, getExecutingFilePathFromLibFile(libFile), "/", [commonFile1, libFile, configFile]);
const projectService = new server.ProjectService(host, nullLogger);
projectService.openClientFile(commonFile1.path);
checkWatchedDirectories(host, ["/a/b"]);
checkNumberOfConfiguredProjects(projectService, 1);
const project = projectService.configuredProjects[0];
checkConfiguredProjectRootFiles(project, [commonFile1.path]);
// add a new ts file
host.reloadFS([commonFile1, commonFile2, libFile, configFile]);
host.triggerDirectoryWatcherCallback("/a/b", commonFile2.path);
host.runQueuedTimeoutCallbacks();
// project service waits for 250ms to update the project structure, therefore the assertion needs to wait longer.
checkConfiguredProjectRootFiles(project, [commonFile1.path, commonFile2.path]);
});
it("should ignore non-existing files specified in the config file", () => {
const configFile: FileOrFolder = {
path: "/a/b/tsconfig.json",
content: `{
"compilerOptions": {},
"files": [
"commonFile1.ts",
"commonFile3.ts"
]
}`
};
const host = new TestServerHost(/*useCaseSensitiveFileNames*/ false, getExecutingFilePathFromLibFile(libFile), "/", [commonFile1, commonFile2, configFile]);
const projectService = new server.ProjectService(host, nullLogger);
projectService.openClientFile(commonFile1.path);
projectService.openClientFile(commonFile2.path);
checkNumberOfConfiguredProjects(projectService, 1);
const project = projectService.configuredProjects[0];
checkConfiguredProjectRootFiles(project, [commonFile1.path]);
checkNumberOfInferredProjects(projectService, 1);
});
it("handle recreated files correctly", () => {
const configFile: FileOrFolder = {
path: "/a/b/tsconfig.json",
content: `{}`
};
const host = new TestServerHost(/*useCaseSensitiveFileNames*/ false, getExecutingFilePathFromLibFile(libFile), "/", [commonFile1, commonFile2, configFile]);
const projectService = new server.ProjectService(host, nullLogger);
projectService.openClientFile(commonFile1.path);
checkNumberOfConfiguredProjects(projectService, 1);
const project = projectService.configuredProjects[0];
checkConfiguredProjectRootFiles(project, [commonFile1.path, commonFile2.path]);
// delete commonFile2
host.reloadFS([commonFile1, configFile]);
host.triggerDirectoryWatcherCallback("/a/b", commonFile2.path);
host.runQueuedTimeoutCallbacks();
checkConfiguredProjectRootFiles(project, [commonFile1.path]);
// re-add commonFile2
host.reloadFS([commonFile1, commonFile2, configFile]);
host.triggerDirectoryWatcherCallback("/a/b", commonFile2.path);
host.runQueuedTimeoutCallbacks();
checkConfiguredProjectRootFiles(project, [commonFile1.path, commonFile2.path]);
});
it("should create new inferred projects for files excluded from a configured project", () => {
const configFile: FileOrFolder = {
path: "/a/b/tsconfig.json",
content: `{
"compilerOptions": {},
"files": ["${commonFile1.path}", "${commonFile2.path}"]
}`
};
const files = [commonFile1, commonFile2, configFile];
const host = new TestServerHost(/*useCaseSensitiveFileNames*/ false, getExecutingFilePathFromLibFile(libFile), "/", files);
const projectService = new server.ProjectService(host, nullLogger);
projectService.openClientFile(commonFile1.path);
const project = projectService.configuredProjects[0];
checkConfiguredProjectRootFiles(project, [commonFile1.path, commonFile2.path]);
configFile.content = `{
"compilerOptions": {},
"files": ["${commonFile1.path}"]
}`;
host.reloadFS(files);
host.triggerFileWatcherCallback(configFile.path);
checkNumberOfConfiguredProjects(projectService, 1);
checkConfiguredProjectRootFiles(project, [commonFile1.path]);
projectService.openClientFile(commonFile2.path);
checkNumberOfInferredProjects(projectService, 1);
});
it("files explicitly excluded in config file", () => {
const configFile: FileOrFolder = {
path: "/a/b/tsconfig.json",
content: `{
"compilerOptions": {},
"exclude": ["/a/c"]
}`
};
const excludedFile1: FileOrFolder = {
path: "/a/c/excluedFile1.ts",
content: `let t = 1;`
};
const host = new TestServerHost(/*useCaseSensitiveFileNames*/ false, getExecutingFilePathFromLibFile(libFile), "/", [commonFile1, commonFile2, excludedFile1, configFile]);
const projectService = new server.ProjectService(host, nullLogger);
projectService.openClientFile(commonFile1.path);
checkNumberOfConfiguredProjects(projectService, 1);
const project = projectService.configuredProjects[0];
checkConfiguredProjectRootFiles(project, [commonFile1.path, commonFile2.path]);
projectService.openClientFile(excludedFile1.path);
checkNumberOfInferredProjects(projectService, 1);
});
it("should properly handle module resolution changes in config file", () => {
const file1: FileOrFolder = {
path: "/a/b/file1.ts",
content: `import { T } from "module1";`
};
const nodeModuleFile: FileOrFolder = {
path: "/a/b/node_modules/module1.ts",
content: `export interface T {}`
};
const classicModuleFile: FileOrFolder = {
path: "/a/module1.ts",
content: `export interface T {}`
};
const configFile: FileOrFolder = {
path: "/a/b/tsconfig.json",
content: `{
"compilerOptions": {
"moduleResolution": "node"
},
"files": ["${file1.path}"]
}`
};
const files = [file1, nodeModuleFile, classicModuleFile, configFile];
const host = new TestServerHost(/*useCaseSensitiveFileNames*/ false, getExecutingFilePathFromLibFile(libFile), "/", files);
const projectService = new server.ProjectService(host, nullLogger);
projectService.openClientFile(file1.path);
projectService.openClientFile(nodeModuleFile.path);
projectService.openClientFile(classicModuleFile.path);
checkNumberOfConfiguredProjects(projectService, 1);
const project = projectService.configuredProjects[0];
checkConfiguredProjectActualFiles(project, [file1.path, nodeModuleFile.path]);
checkNumberOfInferredProjects(projectService, 1);
configFile.content = `{
"compilerOptions": {
"moduleResolution": "classic"
},
"files": ["${file1.path}"]
}`;
host.reloadFS(files);
host.triggerFileWatcherCallback(configFile.path);
checkConfiguredProjectActualFiles(project, [file1.path, classicModuleFile.path]);
checkNumberOfInferredProjects(projectService, 1);
});
});
}