mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-15 03:23:08 -06:00
add support for single inferred project
This commit is contained in:
parent
15f825b6b3
commit
96a867a52e
@ -681,6 +681,7 @@ namespace Harness.LanguageService {
|
||||
const serverHost = new SessionServerHost(clientHost);
|
||||
const server = new ts.server.Session(serverHost,
|
||||
{ isCancellationRequested: () => false },
|
||||
/*useOneInferredProject*/ false,
|
||||
Buffer ? Buffer.byteLength : (string: string, encoding?: string) => string.length,
|
||||
process.hrtime, serverHost);
|
||||
|
||||
|
||||
@ -137,26 +137,25 @@ namespace ts.server {
|
||||
|
||||
private readonly directoryWatchers: DirectoryWatchers;
|
||||
|
||||
private hostConfiguration: HostConfiguration;
|
||||
private readonly hostConfiguration: HostConfiguration;
|
||||
|
||||
private timerForDetectingProjectFileListChanges: Map<any> = {};
|
||||
|
||||
constructor(public readonly host: ServerHost,
|
||||
public readonly logger: Logger,
|
||||
public readonly cancellationToken: HostCancellationToken,
|
||||
private readonly useOneInferredProject: boolean,
|
||||
private readonly eventHandler?: ProjectServiceEventHandler) {
|
||||
|
||||
this.directoryWatchers = new DirectoryWatchers(this);
|
||||
// ts.disableIncrementalParsing = true;
|
||||
this.setDefaultHostConfiguration();
|
||||
this.documentRegistry = createDocumentRegistry(host.useCaseSensitiveFileNames, host.getCurrentDirectory());
|
||||
}
|
||||
|
||||
private setDefaultHostConfiguration() {
|
||||
this.hostConfiguration = {
|
||||
formatCodeOptions: getDefaultFormatCodeSettings(this.host),
|
||||
hostInfo: "Unknown host"
|
||||
};
|
||||
|
||||
this.documentRegistry = createDocumentRegistry(host.useCaseSensitiveFileNames, host.getCurrentDirectory());
|
||||
}
|
||||
|
||||
stopWatchingDirectory(directory: string) {
|
||||
@ -378,31 +377,36 @@ namespace ts.server {
|
||||
}
|
||||
if (info.containingProjects.length === 0) {
|
||||
// create new inferred project p with the newly opened file as root
|
||||
const inferredProject = this.createAndAddInferredProject(info);
|
||||
const openFileRoots: ScriptInfo[] = [];
|
||||
// for each inferred project root r
|
||||
for (const rootFile of this.openFileRoots) {
|
||||
// if r referenced by the new project
|
||||
if (inferredProject.containsScriptInfo(rootFile)) {
|
||||
// remove inferred project that was initially created for rootFile
|
||||
const defaultProject = rootFile.getDefaultProject();
|
||||
if (defaultProject === inferredProject) {
|
||||
continue;
|
||||
}
|
||||
Debug.assert(defaultProject.projectKind === ProjectKind.Inferred);
|
||||
// or add root to existing inferred project if 'useOneInferredProject' is true
|
||||
const inferredProject = this.addFileToInferredProject(info);
|
||||
if (!this.useOneInferredProject) {
|
||||
|
||||
this.removeProject(defaultProject);
|
||||
// put r in referenced open file list
|
||||
this.openFilesReferenced.push(rootFile);
|
||||
// set default project of r to the new project
|
||||
rootFile.attachToProject(inferredProject);
|
||||
}
|
||||
else {
|
||||
// otherwise, keep r as root of inferred project
|
||||
openFileRoots.push(rootFile);
|
||||
// if useOneInferredProject is not set then try to fixup ownership of open files
|
||||
const openFileRoots: ScriptInfo[] = [];
|
||||
// for each inferred project root r
|
||||
for (const rootFile of this.openFileRoots) {
|
||||
// if r referenced by the new project
|
||||
if (inferredProject.containsScriptInfo(rootFile)) {
|
||||
// remove inferred project that was initially created for rootFile
|
||||
const defaultProject = rootFile.getDefaultProject();
|
||||
if (defaultProject === inferredProject) {
|
||||
continue;
|
||||
}
|
||||
Debug.assert(defaultProject.projectKind === ProjectKind.Inferred);
|
||||
|
||||
this.removeProject(defaultProject);
|
||||
// put r in referenced open file list
|
||||
this.openFilesReferenced.push(rootFile);
|
||||
// set default project of r to the new project
|
||||
rootFile.attachToProject(inferredProject);
|
||||
}
|
||||
else {
|
||||
// otherwise, keep r as root of inferred project
|
||||
openFileRoots.push(rootFile);
|
||||
}
|
||||
}
|
||||
this.openFileRoots = openFileRoots;
|
||||
}
|
||||
this.openFileRoots = openFileRoots;
|
||||
}
|
||||
|
||||
this.openFileRoots.push(info);
|
||||
@ -736,6 +740,8 @@ namespace ts.server {
|
||||
|
||||
// delete inferred project
|
||||
let toRemove: Project[];
|
||||
|
||||
// TODO: unify logic
|
||||
for (const p of info.containingProjects) {
|
||||
if (p.projectKind === ProjectKind.Inferred && p.isRoot(info)) {
|
||||
(toRemove || (toRemove = [])).push(p);
|
||||
@ -743,7 +749,10 @@ namespace ts.server {
|
||||
}
|
||||
if (toRemove) {
|
||||
for (const p of toRemove) {
|
||||
this.removeProject(p);
|
||||
p.removeFile(info);
|
||||
if (!p.hasRoots()) {
|
||||
this.removeProject(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -792,8 +801,12 @@ namespace ts.server {
|
||||
}
|
||||
}
|
||||
|
||||
createAndAddInferredProject(root: ScriptInfo) {
|
||||
const project = new InferredProject(this, this.documentRegistry, /*languageServiceEnabled*/ true);
|
||||
addFileToInferredProject(root: ScriptInfo) {
|
||||
const useExistingProject = this.useOneInferredProject && this.inferredProjects.length;
|
||||
const project = useExistingProject
|
||||
? this.inferredProjects[0]
|
||||
: new InferredProject(this, this.documentRegistry, /*languageServiceEnabled*/ true);
|
||||
|
||||
project.addRoot(root);
|
||||
|
||||
this.directoryWatchers.startWatchingContainingDirectoriesForFile(
|
||||
@ -802,7 +815,10 @@ namespace ts.server {
|
||||
fileName => this.onConfigFileAddedForInferredProject(fileName));
|
||||
|
||||
project.updateGraph();
|
||||
this.inferredProjects.push(project);
|
||||
|
||||
if (!useExistingProject) {
|
||||
this.inferredProjects.push(project);
|
||||
}
|
||||
return project;
|
||||
}
|
||||
|
||||
@ -966,7 +982,10 @@ namespace ts.server {
|
||||
if (inConfiguredProject || inExternalProject) {
|
||||
const inferredProjects = rootFile.containingProjects.filter(p => p.projectKind === ProjectKind.Inferred);
|
||||
for (const p of inferredProjects) {
|
||||
this.removeProject(p);
|
||||
p.removeFile(rootFile, /*detachFromProject*/ true);
|
||||
if (!p.hasRoots()) {
|
||||
this.removeProject(p);
|
||||
}
|
||||
}
|
||||
if (inConfiguredProject) {
|
||||
this.openFileRootsConfigured.push(rootFile);
|
||||
@ -1033,6 +1052,9 @@ namespace ts.server {
|
||||
for (const f of unattachedOpenFiles) {
|
||||
this.addOpenFile(f);
|
||||
}
|
||||
for (const p of this.inferredProjects) {
|
||||
p.updateGraph();
|
||||
}
|
||||
this.printProjects();
|
||||
}
|
||||
|
||||
|
||||
@ -108,6 +108,10 @@ namespace ts.server {
|
||||
return this.compilerOptions;
|
||||
}
|
||||
|
||||
hasRoots() {
|
||||
return this.rootFiles.length > 0;
|
||||
}
|
||||
|
||||
getRootFiles() {
|
||||
return this.rootFiles.map(info => info.fileName);
|
||||
}
|
||||
|
||||
5
src/server/protocol.d.ts
vendored
5
src/server/protocol.d.ts
vendored
@ -606,6 +606,11 @@ declare namespace ts.server.protocol {
|
||||
* The format options to use during formatting and other code editing features.
|
||||
*/
|
||||
formatOptions?: FormatOptions;
|
||||
|
||||
/**
|
||||
* If set to true - then all loose files will land into one inferred project
|
||||
*/
|
||||
useOneInferredProject?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -91,8 +91,8 @@ namespace ts.server {
|
||||
}
|
||||
|
||||
class IOSession extends Session {
|
||||
constructor(host: ServerHost, cancellationToken: HostCancellationToken, logger: ts.server.Logger) {
|
||||
super(host, cancellationToken, Buffer.byteLength, process.hrtime, logger);
|
||||
constructor(host: ServerHost, cancellationToken: HostCancellationToken, useOneInferredProject: boolean, logger: ts.server.Logger) {
|
||||
super(host, cancellationToken, useOneInferredProject, Buffer.byteLength, process.hrtime, logger);
|
||||
}
|
||||
|
||||
exit() {
|
||||
@ -304,7 +304,8 @@ namespace ts.server {
|
||||
};
|
||||
};
|
||||
|
||||
const ioSession = new IOSession(sys, cancellationToken, logger);
|
||||
const useOneInferredProject = sys.args.some(arg => arg === "--useOneInferredProject");
|
||||
const ioSession = new IOSession(sys, cancellationToken, useOneInferredProject, logger);
|
||||
process.on("uncaughtException", function(err: Error) {
|
||||
ioSession.logError(err, "unknown");
|
||||
});
|
||||
|
||||
@ -178,12 +178,13 @@ namespace ts.server {
|
||||
|
||||
constructor(
|
||||
private host: ServerHost,
|
||||
private cancellationToken: HostCancellationToken,
|
||||
cancellationToken: HostCancellationToken,
|
||||
useOneInferredProject: boolean,
|
||||
private byteLength: (buf: string, encoding?: string) => number,
|
||||
private hrtime: (start?: number[]) => number[],
|
||||
private logger: Logger) {
|
||||
this.projectService =
|
||||
new ProjectService(host, logger, cancellationToken, (eventName, project, fileName) => {
|
||||
new ProjectService(host, logger, cancellationToken, useOneInferredProject, (eventName, project, fileName) => {
|
||||
this.handleEvent(eventName, project, fileName);
|
||||
});
|
||||
}
|
||||
@ -1380,10 +1381,10 @@ namespace ts.server {
|
||||
this.cleanup();
|
||||
return this.requiredResponse(true);
|
||||
},
|
||||
[CommandNames.SemanticDiagnosticsSync]: (request: protocol.FileRequest) => {
|
||||
[CommandNames.SemanticDiagnosticsSync]: (request: protocol.SemanticDiagnosticsSyncRequest) => {
|
||||
return this.requiredResponse(this.getSemanticDiagnosticsSync(request.arguments));
|
||||
},
|
||||
[CommandNames.SyntacticDiagnosticsSync]: (request: protocol.FileRequest) => {
|
||||
[CommandNames.SyntacticDiagnosticsSync]: (request: protocol.SyntacticDiagnosticsSyncRequest) => {
|
||||
return this.requiredResponse(this.getSyntacticDiagnosticsSync(request.arguments));
|
||||
},
|
||||
[CommandNames.Geterr]: (request: protocol.Request) => {
|
||||
@ -1398,9 +1399,8 @@ namespace ts.server {
|
||||
this.change(request.arguments);
|
||||
return this.notRequired();
|
||||
},
|
||||
[CommandNames.Configure]: (request: protocol.Request) => {
|
||||
const configureArgs = <protocol.ConfigureRequestArguments>request.arguments;
|
||||
this.projectService.setHostConfiguration(configureArgs);
|
||||
[CommandNames.Configure]: (request: protocol.ConfigureRequest) => {
|
||||
this.projectService.setHostConfiguration(request.arguments);
|
||||
this.output(undefined, CommandNames.Configure, request.seq);
|
||||
return this.notRequired();
|
||||
},
|
||||
|
||||
@ -79,9 +79,9 @@ namespace ts {
|
||||
msg: (s: string, type?: string) => { }
|
||||
};
|
||||
|
||||
const projectService = new server.ProjectService(serverHost, logger, { isCancellationRequested: () => false });
|
||||
const projectService = new server.ProjectService(serverHost, logger, { isCancellationRequested: () => false }, /*useOneInferredProject*/ false);
|
||||
const rootScriptInfo = projectService.getOrCreateScriptInfo(rootFile, /* openedByClient */true, /*containingProject*/ undefined);
|
||||
const project = projectService.createAndAddInferredProject(rootScriptInfo);
|
||||
const project = projectService.addFileToInferredProject(rootScriptInfo);
|
||||
project.setCompilerOptions({ module: ts.ModuleKind.AMD } );
|
||||
return {
|
||||
project,
|
||||
|
||||
@ -40,7 +40,7 @@ namespace ts.server {
|
||||
let lastSent: protocol.Message;
|
||||
|
||||
beforeEach(() => {
|
||||
session = new Session(mockHost, nullCancellationToken, Utils.byteLength, process.hrtime, mockLogger);
|
||||
session = new Session(mockHost, nullCancellationToken, /*useOneInferredProject*/ false, Utils.byteLength, process.hrtime, mockLogger);
|
||||
session.send = (msg: protocol.Message) => {
|
||||
lastSent = msg;
|
||||
};
|
||||
@ -265,7 +265,7 @@ namespace ts.server {
|
||||
lastSent: protocol.Message;
|
||||
customHandler = "testhandler";
|
||||
constructor() {
|
||||
super(mockHost, nullCancellationToken, Utils.byteLength, process.hrtime, mockLogger);
|
||||
super(mockHost, nullCancellationToken, /*useOneInferredProject*/ false, Utils.byteLength, process.hrtime, mockLogger);
|
||||
this.addProtocolHandler(this.customHandler, () => {
|
||||
return { response: undefined, responseRequired: true };
|
||||
});
|
||||
@ -323,7 +323,7 @@ namespace ts.server {
|
||||
class InProcSession extends Session {
|
||||
private queue: protocol.Request[] = [];
|
||||
constructor(private client: InProcClient) {
|
||||
super(mockHost, nullCancellationToken, Utils.byteLength, process.hrtime, mockLogger);
|
||||
super(mockHost, nullCancellationToken, /*useOneInferredProject*/ false, Utils.byteLength, process.hrtime, mockLogger);
|
||||
this.addProtocolHandler("echo", (req: protocol.Request) => ({
|
||||
response: req.arguments,
|
||||
responseRequired: true
|
||||
|
||||
@ -26,6 +26,22 @@ namespace ts {
|
||||
return combinePaths(getDirectoryPath(libFile.path), "tsc.js");
|
||||
}
|
||||
|
||||
interface TestServerHostCreationParameters {
|
||||
fileOrFolderList: FileOrFolder[];
|
||||
useCaseSensitiveFileNames?: boolean;
|
||||
executingFilePath?: string;
|
||||
libFile?: FileOrFolder;
|
||||
currentDirectory?: string;
|
||||
}
|
||||
|
||||
function createServerHost(params: TestServerHostCreationParameters): TestServerHost {
|
||||
return new TestServerHost(
|
||||
params.useCaseSensitiveFileNames !== undefined ? params.useCaseSensitiveFileNames : false,
|
||||
params.executingFilePath || getExecutingFilePathFromLibFile(params.libFile),
|
||||
params.currentDirectory || "/",
|
||||
params.fileOrFolderList);
|
||||
}
|
||||
|
||||
interface FileOrFolder {
|
||||
path: string;
|
||||
content?: string;
|
||||
@ -112,12 +128,12 @@ namespace ts {
|
||||
checkMapKeys("watchedDirectories", host.watchedDirectories, expectedDirectories);
|
||||
}
|
||||
|
||||
function checkConfiguredProjectActualFiles(project: server.Project, expectedFiles: string[]) {
|
||||
checkFileNames("configuredProjects project, actualFileNames", project.getFileNames(), expectedFiles);
|
||||
function checkProjectActualFiles(project: server.Project, expectedFiles: string[]) {
|
||||
checkFileNames(`${server.ProjectKind[project.projectKind]} project, actual files`, project.getFileNames(), expectedFiles);
|
||||
}
|
||||
|
||||
function checkConfiguredProjectRootFiles(project: server.Project, expectedFiles: string[]) {
|
||||
checkFileNames("configuredProjects project, rootFileNames", project.getRootFiles(), expectedFiles);
|
||||
function checkProjectRootFiles(project: server.Project, expectedFiles: string[]) {
|
||||
checkFileNames(`${server.ProjectKind[project.projectKind]} project, rootFileNames`, project.getRootFiles(), expectedFiles);
|
||||
}
|
||||
|
||||
type TimeOutCallback = () => any;
|
||||
@ -193,7 +209,7 @@ namespace ts {
|
||||
return ts.matchFiles(path, extensions, exclude, include, this.useCaseSensitiveFileNames, this.getCurrentDirectory(), (dir) => {
|
||||
const result: FileSystemEntries = {
|
||||
directories: [],
|
||||
files : []
|
||||
files: []
|
||||
};
|
||||
const dirEntry = that.fs.get(that.toPath(dir));
|
||||
if (isFolder(dirEntry)) {
|
||||
@ -325,8 +341,8 @@ namespace ts {
|
||||
path: "/a/b/c/module.d.ts",
|
||||
content: `export let x: number`
|
||||
};
|
||||
const host = new TestServerHost(/*useCaseSensitiveFileNames*/ false, getExecutingFilePathFromLibFile(libFile), "/", [appFile, moduleFile, libFile]);
|
||||
const projectService = new server.ProjectService(host, nullLogger, nullCancellationToken);
|
||||
const host = createServerHost({ fileOrFolderList: [appFile, moduleFile, libFile], libFile });
|
||||
const projectService = new server.ProjectService(host, nullLogger, nullCancellationToken, /*useOneInferredProject*/ false);
|
||||
const { configFileName } = projectService.openClientFile(appFile.path);
|
||||
|
||||
assert(!configFileName, `should not find config, got: '${configFileName}`);
|
||||
@ -363,8 +379,9 @@ namespace 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, nullCancellationToken);
|
||||
|
||||
const host = createServerHost({ fileOrFolderList: [configFile, libFile, file1, file2, file3], libFile });
|
||||
const projectService = new server.ProjectService(host, nullLogger, nullCancellationToken, /*useOneInferredProject*/ false);
|
||||
const { configFileName, configFileErrors } = projectService.openClientFile(file1.path);
|
||||
|
||||
assert(configFileName, "should find config file");
|
||||
@ -373,8 +390,8 @@ namespace ts {
|
||||
checkNumberOfConfiguredProjects(projectService, 1);
|
||||
|
||||
const project = projectService.configuredProjects[0];
|
||||
checkConfiguredProjectActualFiles(project, [file1.path, libFile.path, file2.path]);
|
||||
checkConfiguredProjectRootFiles(project, [file1.path, file2.path]);
|
||||
checkProjectActualFiles(project, [file1.path, libFile.path, file2.path]);
|
||||
checkProjectRootFiles(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)]);
|
||||
@ -387,10 +404,11 @@ namespace ts {
|
||||
"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, nullCancellationToken);
|
||||
const filesWithoutConfig = [libFile, commonFile1, commonFile2];
|
||||
const host = createServerHost({ fileOrFolderList: filesWithoutConfig, libFile });
|
||||
|
||||
const filesWithConfig = [libFile, commonFile1, commonFile2, configFile];
|
||||
const projectService = new server.ProjectService(host, nullLogger, nullCancellationToken, /*useOneInferredProject*/ false);
|
||||
projectService.openClientFile(commonFile1.path);
|
||||
projectService.openClientFile(commonFile2.path);
|
||||
|
||||
@ -420,21 +438,21 @@ namespace ts {
|
||||
path: "/a/b/tsconfig.json",
|
||||
content: `{}`
|
||||
};
|
||||
const host = new TestServerHost(/*useCaseSensitiveFileNames*/ false, getExecutingFilePathFromLibFile(libFile), "/", [commonFile1, libFile, configFile]);
|
||||
const projectService = new server.ProjectService(host, nullLogger, nullCancellationToken);
|
||||
const host = createServerHost({ fileOrFolderList: [commonFile1, libFile, configFile], libFile });
|
||||
const projectService = new server.ProjectService(host, nullLogger, nullCancellationToken, /*useOneInferredProject*/ false);
|
||||
projectService.openClientFile(commonFile1.path);
|
||||
checkWatchedDirectories(host, ["/a/b"]);
|
||||
checkNumberOfConfiguredProjects(projectService, 1);
|
||||
|
||||
const project = projectService.configuredProjects[0];
|
||||
checkConfiguredProjectRootFiles(project, [commonFile1.path]);
|
||||
checkProjectRootFiles(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]);
|
||||
checkProjectRootFiles(project, [commonFile1.path, commonFile2.path]);
|
||||
});
|
||||
|
||||
it("should ignore non-existing files specified in the config file", () => {
|
||||
@ -448,14 +466,14 @@ namespace ts {
|
||||
]
|
||||
}`
|
||||
};
|
||||
const host = new TestServerHost(/*useCaseSensitiveFileNames*/ false, getExecutingFilePathFromLibFile(libFile), "/", [commonFile1, commonFile2, configFile]);
|
||||
const projectService = new server.ProjectService(host, nullLogger, nullCancellationToken);
|
||||
const host = createServerHost({ fileOrFolderList: [commonFile1, commonFile2, configFile], libFile });
|
||||
const projectService = new server.ProjectService(host, nullLogger, nullCancellationToken, /*useOneInferredProject*/ false);
|
||||
projectService.openClientFile(commonFile1.path);
|
||||
projectService.openClientFile(commonFile2.path);
|
||||
|
||||
checkNumberOfConfiguredProjects(projectService, 1);
|
||||
const project = projectService.configuredProjects[0];
|
||||
checkConfiguredProjectRootFiles(project, [commonFile1.path]);
|
||||
checkProjectRootFiles(project, [commonFile1.path]);
|
||||
checkNumberOfInferredProjects(projectService, 1);
|
||||
});
|
||||
|
||||
@ -464,25 +482,25 @@ namespace ts {
|
||||
path: "/a/b/tsconfig.json",
|
||||
content: `{}`
|
||||
};
|
||||
const host = new TestServerHost(/*useCaseSensitiveFileNames*/ false, getExecutingFilePathFromLibFile(libFile), "/", [commonFile1, commonFile2, configFile]);
|
||||
const projectService = new server.ProjectService(host, nullLogger, nullCancellationToken);
|
||||
const host = createServerHost({ fileOrFolderList: [commonFile1, commonFile2, configFile], libFile });
|
||||
const projectService = new server.ProjectService(host, nullLogger, nullCancellationToken, /*useOneInferredProject*/ false);
|
||||
projectService.openClientFile(commonFile1.path);
|
||||
|
||||
checkNumberOfConfiguredProjects(projectService, 1);
|
||||
const project = projectService.configuredProjects[0];
|
||||
checkConfiguredProjectRootFiles(project, [commonFile1.path, commonFile2.path]);
|
||||
checkProjectRootFiles(project, [commonFile1.path, commonFile2.path]);
|
||||
|
||||
// delete commonFile2
|
||||
host.reloadFS([commonFile1, configFile]);
|
||||
host.triggerDirectoryWatcherCallback("/a/b", commonFile2.path);
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
checkConfiguredProjectRootFiles(project, [commonFile1.path]);
|
||||
checkProjectRootFiles(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]);
|
||||
checkProjectRootFiles(project, [commonFile1.path, commonFile2.path]);
|
||||
});
|
||||
|
||||
it("should create new inferred projects for files excluded from a configured project", () => {
|
||||
@ -494,12 +512,12 @@ namespace ts {
|
||||
}`
|
||||
};
|
||||
const files = [commonFile1, commonFile2, configFile];
|
||||
const host = new TestServerHost(/*useCaseSensitiveFileNames*/ false, getExecutingFilePathFromLibFile(libFile), "/", files);
|
||||
const projectService = new server.ProjectService(host, nullLogger, nullCancellationToken);
|
||||
const host = createServerHost({ fileOrFolderList: files, libFile });
|
||||
const projectService = new server.ProjectService(host, nullLogger, nullCancellationToken, /*useOneInferredProject*/ false);
|
||||
projectService.openClientFile(commonFile1.path);
|
||||
|
||||
const project = projectService.configuredProjects[0];
|
||||
checkConfiguredProjectRootFiles(project, [commonFile1.path, commonFile2.path]);
|
||||
checkProjectRootFiles(project, [commonFile1.path, commonFile2.path]);
|
||||
configFile.content = `{
|
||||
"compilerOptions": {},
|
||||
"files": ["${commonFile1.path}"]
|
||||
@ -508,7 +526,7 @@ namespace ts {
|
||||
host.triggerFileWatcherCallback(configFile.path);
|
||||
|
||||
checkNumberOfConfiguredProjects(projectService, 1);
|
||||
checkConfiguredProjectRootFiles(project, [commonFile1.path]);
|
||||
checkProjectRootFiles(project, [commonFile1.path]);
|
||||
|
||||
projectService.openClientFile(commonFile2.path);
|
||||
checkNumberOfInferredProjects(projectService, 1);
|
||||
@ -527,13 +545,13 @@ namespace ts {
|
||||
content: `let t = 1;`
|
||||
};
|
||||
|
||||
const host = new TestServerHost(/*useCaseSensitiveFileNames*/ false, getExecutingFilePathFromLibFile(libFile), "/", [commonFile1, commonFile2, excludedFile1, configFile]);
|
||||
const projectService = new server.ProjectService(host, nullLogger, nullCancellationToken);
|
||||
const host = createServerHost({ fileOrFolderList: [commonFile1, commonFile2, excludedFile1, configFile], libFile });
|
||||
const projectService = new server.ProjectService(host, nullLogger, nullCancellationToken, /*useOneInferredProject*/ false);
|
||||
|
||||
projectService.openClientFile(commonFile1.path);
|
||||
checkNumberOfConfiguredProjects(projectService, 1);
|
||||
const project = projectService.configuredProjects[0];
|
||||
checkConfiguredProjectRootFiles(project, [commonFile1.path, commonFile2.path]);
|
||||
checkProjectRootFiles(project, [commonFile1.path, commonFile2.path]);
|
||||
projectService.openClientFile(excludedFile1.path);
|
||||
checkNumberOfInferredProjects(projectService, 1);
|
||||
});
|
||||
@ -561,15 +579,15 @@ namespace ts {
|
||||
}`
|
||||
};
|
||||
const files = [file1, nodeModuleFile, classicModuleFile, configFile];
|
||||
const host = new TestServerHost(/*useCaseSensitiveFileNames*/ false, getExecutingFilePathFromLibFile(libFile), "/", files);
|
||||
const projectService = new server.ProjectService(host, nullLogger, nullCancellationToken);
|
||||
const host = createServerHost({ fileOrFolderList: files, libFile });
|
||||
const projectService = new server.ProjectService(host, nullLogger, nullCancellationToken, /*useOneInferredProject*/ false);
|
||||
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]);
|
||||
checkProjectActualFiles(project, [file1.path, nodeModuleFile.path]);
|
||||
checkNumberOfInferredProjects(projectService, 1);
|
||||
|
||||
configFile.content = `{
|
||||
@ -580,7 +598,7 @@ namespace ts {
|
||||
}`;
|
||||
host.reloadFS(files);
|
||||
host.triggerFileWatcherCallback(configFile.path);
|
||||
checkConfiguredProjectActualFiles(project, [file1.path, classicModuleFile.path]);
|
||||
checkProjectActualFiles(project, [file1.path, classicModuleFile.path]);
|
||||
checkNumberOfInferredProjects(projectService, 1);
|
||||
});
|
||||
|
||||
@ -602,8 +620,8 @@ namespace ts {
|
||||
"files": [ "main.ts" ]
|
||||
}`
|
||||
};
|
||||
const host = new TestServerHost(/*useCaseSensitiveFileNames*/ false, getExecutingFilePathFromLibFile(libFile), "/", [file1, file2, configFile]);
|
||||
const projectService = new server.ProjectService(host, nullLogger, nullCancellationToken);
|
||||
const host = createServerHost({ fileOrFolderList: [file1, file2, configFile], libFile });
|
||||
const projectService = new server.ProjectService(host, nullLogger, nullCancellationToken, /*useOneInferredProject*/ false);
|
||||
projectService.openClientFile(file1.path);
|
||||
projectService.closeClientFile(file1.path);
|
||||
projectService.openClientFile(file2.path);
|
||||
@ -629,13 +647,56 @@ namespace ts {
|
||||
"files": [ "main.ts" ]
|
||||
}`
|
||||
};
|
||||
const host = new TestServerHost(/*useCaseSensitiveFileNames*/ false, getExecutingFilePathFromLibFile(libFile), "/", [file1, file2, configFile]);
|
||||
const projectService = new server.ProjectService(host, nullLogger, nullCancellationToken);
|
||||
const host = createServerHost({ fileOrFolderList: [file1, file2, configFile], libFile });
|
||||
const projectService = new server.ProjectService(host, nullLogger, nullCancellationToken, /*useOneInferredProject*/ false);
|
||||
projectService.openClientFile(file1.path);
|
||||
projectService.closeClientFile(file1.path);
|
||||
projectService.openClientFile(file2.path);
|
||||
checkNumberOfConfiguredProjects(projectService, 1);
|
||||
checkNumberOfInferredProjects(projectService, 0);
|
||||
});
|
||||
|
||||
it("should use only one inferred project if 'useOneInferredProject' is set", () => {
|
||||
const file1 = {
|
||||
path: "/a/b/main.ts",
|
||||
content: "let x =1;"
|
||||
};
|
||||
const configFile: FileOrFolder = {
|
||||
path: "/a/b/tsconfig.json",
|
||||
content: `{
|
||||
"compilerOptions": {
|
||||
"target": "es6"
|
||||
},
|
||||
"files": [ "main.ts" ]
|
||||
}`
|
||||
};
|
||||
const file2 = {
|
||||
path: "/a/c/main.ts",
|
||||
content: "let x =1;"
|
||||
};
|
||||
|
||||
const file3 = {
|
||||
path: "/a/d/main.ts",
|
||||
content: "let x =1;"
|
||||
};
|
||||
|
||||
const host = createServerHost({ fileOrFolderList: [file1, file2, file3, libFile], libFile });
|
||||
const projectService = new server.ProjectService(host, nullLogger, nullCancellationToken, /*useOneInferredProject*/ true);
|
||||
projectService.openClientFile(file1.path);
|
||||
projectService.openClientFile(file2.path);
|
||||
projectService.openClientFile(file3.path);
|
||||
|
||||
checkNumberOfConfiguredProjects(projectService, 0);
|
||||
checkNumberOfInferredProjects(projectService, 1);
|
||||
checkProjectActualFiles(projectService.inferredProjects[0], [file1.path, file2.path, file3.path, libFile.path]);
|
||||
|
||||
|
||||
host.reloadFS([file1, configFile, file2, file3, libFile]);
|
||||
host.triggerDirectoryWatcherCallback(getDirectoryPath(configFile.path), configFile.path);
|
||||
|
||||
checkNumberOfConfiguredProjects(projectService, 1);
|
||||
checkNumberOfInferredProjects(projectService, 1);
|
||||
checkProjectActualFiles(projectService.inferredProjects[0], [file2.path, file3.path, libFile.path]);
|
||||
});
|
||||
});
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user