Adds support for inferred project isolation by projectRootPath

This commit is contained in:
Ron Buckton
2017-08-03 16:03:24 -07:00
parent c9698072d4
commit fa7f3e85fe
10 changed files with 278 additions and 67 deletions
+1
View File
@@ -828,6 +828,7 @@ namespace Harness.LanguageService {
host: serverHost,
cancellationToken: ts.server.nullCancellationToken,
useSingleInferredProject: false,
useInferredProjectPerProjectRoot: false,
typingsInstaller: undefined,
byteLength: Utils.byteLength,
hrtime: process.hrtime,
@@ -69,6 +69,7 @@ namespace ts {
logger,
cancellationToken: { isCancellationRequested: () => false },
useSingleInferredProject: false,
useInferredProjectPerProjectRoot: false,
typingsInstaller: undefined
};
const projectService = new server.ProjectService(svcOpts);
+2 -1
View File
@@ -36,6 +36,7 @@ namespace ts.projectSystem {
host,
cancellationToken: nullCancellationToken,
useSingleInferredProject: false,
useInferredProjectPerProjectRoot: false,
typingsInstaller: typingsInstaller || server.nullTypingsInstaller,
byteLength: Utils.byteLength,
hrtime: process.hrtime,
@@ -550,7 +551,7 @@ namespace ts.projectSystem {
};
const host = createServerHost([file1, file2, configFile, libFile], { newLine: "\r\n" });
const typingsInstaller = createTestTypingsInstaller(host);
const session = createSession(host, typingsInstaller);
const session = createSession(host, { typingsInstaller });
openFilesForSession([file1, file2], session);
const compileFileRequest = makeSessionRequest<server.protocol.CompileOnSaveEmitFileRequestArgs>(CommandNames.CompileOnSaveEmitFile, { file: file1.path, projectFileName: configFile.path });
+3
View File
@@ -55,6 +55,7 @@ namespace ts.server {
host: mockHost,
cancellationToken: nullCancellationToken,
useSingleInferredProject: false,
useInferredProjectPerProjectRoot: false,
typingsInstaller: undefined,
byteLength: Utils.byteLength,
hrtime: process.hrtime,
@@ -405,6 +406,7 @@ namespace ts.server {
host: mockHost,
cancellationToken: nullCancellationToken,
useSingleInferredProject: false,
useInferredProjectPerProjectRoot: false,
typingsInstaller: undefined,
byteLength: Utils.byteLength,
hrtime: process.hrtime,
@@ -472,6 +474,7 @@ namespace ts.server {
host: mockHost,
cancellationToken: nullCancellationToken,
useSingleInferredProject: false,
useInferredProjectPerProjectRoot: false,
typingsInstaller: undefined,
byteLength: Utils.byteLength,
hrtime: process.hrtime,
+151 -31
View File
@@ -186,23 +186,25 @@ namespace ts.projectSystem {
}
}
export function createSession(host: server.ServerHost, typingsInstaller?: server.ITypingsInstaller, projectServiceEventHandler?: server.ProjectServiceEventHandler, cancellationToken?: server.ServerCancellationToken, throttleWaitMilliseconds?: number) {
if (typingsInstaller === undefined) {
typingsInstaller = new TestTypingsInstaller("/a/data/", /*throttleLimit*/5, host);
export function createSession(host: server.ServerHost, opts: Partial<server.SessionOptions> = {}) {
if (opts.typingsInstaller === undefined) {
opts.typingsInstaller = new TestTypingsInstaller("/a/data/", /*throttleLimit*/5, host);
}
const opts: server.SessionOptions = {
if (opts.eventHandler !== undefined) {
opts.canUseEvents = true;
}
return new TestSession({
host,
cancellationToken: cancellationToken || server.nullCancellationToken,
cancellationToken: server.nullCancellationToken,
useSingleInferredProject: false,
typingsInstaller,
useInferredProjectPerProjectRoot: false,
typingsInstaller: opts.typingsInstaller,
byteLength: Utils.byteLength,
hrtime: process.hrtime,
logger: nullLogger,
canUseEvents: projectServiceEventHandler !== undefined,
eventHandler: projectServiceEventHandler,
throttleWaitMilliseconds
};
return new TestSession(opts);
canUseEvents: false,
...opts
});
}
export interface CreateProjectServiceParameters {
@@ -216,9 +218,16 @@ namespace ts.projectSystem {
export class TestProjectService extends server.ProjectService {
constructor(host: server.ServerHost, logger: server.Logger, cancellationToken: HostCancellationToken, useSingleInferredProject: boolean,
typingsInstaller: server.ITypingsInstaller, eventHandler: server.ProjectServiceEventHandler) {
typingsInstaller: server.ITypingsInstaller, eventHandler: server.ProjectServiceEventHandler, opts: Partial<server.ProjectServiceOptions> = {}) {
super({
host, logger, cancellationToken, useSingleInferredProject, typingsInstaller, eventHandler
host,
logger,
cancellationToken,
useSingleInferredProject,
useInferredProjectPerProjectRoot: false,
typingsInstaller,
eventHandler,
...opts
});
}
@@ -632,7 +641,7 @@ namespace ts.projectSystem {
}
}
describe("tsserver-project-system", () => {
describe("tsserverProjectSystem", () => {
const commonFile1: FileOrFolder = {
path: "/a/b/commonFile1.ts",
content: "let x = 1"
@@ -2231,13 +2240,16 @@ namespace ts.projectSystem {
filePath === f2.path ? server.maxProgramSizeForNonTsFiles + 1 : originalGetFileSize.call(host, filePath);
let lastEvent: server.ProjectLanguageServiceStateEvent;
const session = createSession(host, /*typingsInstaller*/ undefined, e => {
if (e.eventName === server.ConfigFileDiagEvent || e.eventName === server.ContextEvent || e.eventName === server.ProjectInfoTelemetryEvent) {
return;
const session = createSession(host, {
canUseEvents: true,
eventHandler: e => {
if (e.eventName === server.ConfigFileDiagEvent || e.eventName === server.ContextEvent || e.eventName === server.ProjectInfoTelemetryEvent) {
return;
}
assert.equal(e.eventName, server.ProjectLanguageServiceStateEvent);
assert.equal(e.data.project.getProjectName(), config.path, "project name");
lastEvent = <server.ProjectLanguageServiceStateEvent>e;
}
assert.equal(e.eventName, server.ProjectLanguageServiceStateEvent);
assert.equal(e.data.project.getProjectName(), config.path, "project name");
lastEvent = <server.ProjectLanguageServiceStateEvent>e;
});
session.executeCommand(<protocol.OpenRequest>{
seq: 0,
@@ -2281,12 +2293,15 @@ namespace ts.projectSystem {
host.getFileSize = (filePath: string) =>
filePath === f2.path ? server.maxProgramSizeForNonTsFiles + 1 : originalGetFileSize.call(host, filePath);
let lastEvent: server.ProjectLanguageServiceStateEvent;
const session = createSession(host, /*typingsInstaller*/ undefined, e => {
if (e.eventName === server.ConfigFileDiagEvent || e.eventName === server.ProjectInfoTelemetryEvent) {
return;
const session = createSession(host, {
canUseEvents: true,
eventHandler: e => {
if (e.eventName === server.ConfigFileDiagEvent || e.eventName === server.ProjectInfoTelemetryEvent) {
return;
}
assert.equal(e.eventName, server.ProjectLanguageServiceStateEvent);
lastEvent = <server.ProjectLanguageServiceStateEvent>e;
}
assert.equal(e.eventName, server.ProjectLanguageServiceStateEvent);
lastEvent = <server.ProjectLanguageServiceStateEvent>e;
});
session.executeCommand(<protocol.OpenRequest>{
seq: 0,
@@ -3070,7 +3085,10 @@ namespace ts.projectSystem {
};
const host = createServerHost([file, configFile]);
const session = createSession(host, /*typingsInstaller*/ undefined, serverEventManager.handler);
const session = createSession(host, {
canUseEvents: true,
eventHandler: serverEventManager.handler
});
openFilesForSession([file], session);
serverEventManager.checkEventCountOfType("configFileDiag", 1);
@@ -3097,7 +3115,10 @@ namespace ts.projectSystem {
};
const host = createServerHost([file, configFile]);
const session = createSession(host, /*typingsInstaller*/ undefined, serverEventManager.handler);
const session = createSession(host, {
canUseEvents: true,
eventHandler: serverEventManager.handler
});
openFilesForSession([file], session);
serverEventManager.checkEventCountOfType("configFileDiag", 1);
});
@@ -3116,7 +3137,10 @@ namespace ts.projectSystem {
};
const host = createServerHost([file, configFile]);
const session = createSession(host, /*typingsInstaller*/ undefined, serverEventManager.handler);
const session = createSession(host, {
canUseEvents: true,
eventHandler: serverEventManager.handler
});
openFilesForSession([file], session);
serverEventManager.checkEventCountOfType("configFileDiag", 1);
@@ -3505,6 +3529,93 @@ namespace ts.projectSystem {
checkNumberOfProjects(projectService, { inferredProjects: 1 });
checkProjectActualFiles(projectService.inferredProjects[0], [f.path]);
});
it("inferred projects per project root", () => {
const file1 = { path: "/a/file1.ts", content: "let x = 1;", projectRootPath: "/a" };
const file2 = { path: "/a/file2.ts", content: "let y = 2;", projectRootPath: "/a" };
const file3 = { path: "/b/file2.ts", content: "let x = 3;", projectRootPath: "/b" };
const file4 = { path: "/c/file3.ts", content: "let z = 4;" };
const host = createServerHost([file1, file2, file3, file4]);
const session = createSession(host, {
useSingleInferredProject: true,
useInferredProjectPerProjectRoot: true
});
session.executeCommand(<server.protocol.SetCompilerOptionsForInferredProjectsRequest>{
seq: 1,
type: "request",
command: CommandNames.CompilerOptionsForInferredProjects,
arguments: {
options: {
allowJs: true,
target: ScriptTarget.ESNext
}
}
});
session.executeCommand(<server.protocol.SetCompilerOptionsForInferredProjectsRequest>{
seq: 2,
type: "request",
command: CommandNames.CompilerOptionsForInferredProjects,
arguments: {
options: {
allowJs: true,
target: ScriptTarget.ES2015
},
projectRootPath: "/b"
}
});
session.executeCommand(<server.protocol.OpenRequest>{
seq: 3,
type: "request",
command: CommandNames.Open,
arguments: {
file: file1.path,
fileContent: file1.content,
scriptKindName: "JS",
projectRootPath: file1.projectRootPath
}
});
session.executeCommand(<server.protocol.OpenRequest>{
seq: 4,
type: "request",
command: CommandNames.Open,
arguments: {
file: file2.path,
fileContent: file2.content,
scriptKindName: "JS",
projectRootPath: file2.projectRootPath
}
});
session.executeCommand(<server.protocol.OpenRequest>{
seq: 5,
type: "request",
command: CommandNames.Open,
arguments: {
file: file3.path,
fileContent: file3.content,
scriptKindName: "JS",
projectRootPath: file3.projectRootPath
}
});
session.executeCommand(<server.protocol.OpenRequest>{
seq: 6,
type: "request",
command: CommandNames.Open,
arguments: {
file: file4.path,
fileContent: file4.content,
scriptKindName: "JS"
}
});
const projectService = session.getProjectService();
checkNumberOfProjects(projectService, { inferredProjects: 3 });
checkProjectActualFiles(projectService.inferredProjects[0], [file4.path]);
checkProjectActualFiles(projectService.inferredProjects[1], [file1.path, file2.path]);
checkProjectActualFiles(projectService.inferredProjects[2], [file3.path]);
assert.equal(projectService.inferredProjects[0].getCompilerOptions().target, ScriptTarget.ESNext);
assert.equal(projectService.inferredProjects[1].getCompilerOptions().target, ScriptTarget.ESNext);
assert.equal(projectService.inferredProjects[2].getCompilerOptions().target, ScriptTarget.ES2015);
});
});
describe("No overwrite emit error", () => {
@@ -3698,7 +3809,7 @@ namespace ts.projectSystem {
resetRequest: noop
};
const session = createSession(host, /*typingsInstaller*/ undefined, /*projectServiceEventHandler*/ undefined, cancellationToken);
const session = createSession(host, { cancellationToken });
expectedRequestId = session.getNextSeq();
session.executeCommandSeq(<server.protocol.OpenRequest>{
@@ -3738,7 +3849,11 @@ namespace ts.projectSystem {
const cancellationToken = new TestServerCancellationToken();
const host = createServerHost([f1, config]);
const session = createSession(host, /*typingsInstaller*/ undefined, () => { }, cancellationToken);
const session = createSession(host, {
canUseEvents: true,
eventHandler: () => { },
cancellationToken
});
{
session.executeCommandSeq(<protocol.OpenRequest>{
command: "open",
@@ -3871,7 +3986,12 @@ namespace ts.projectSystem {
};
const cancellationToken = new TestServerCancellationToken(/*cancelAfterRequest*/ 3);
const host = createServerHost([f1, config]);
const session = createSession(host, /*typingsInstaller*/ undefined, () => { }, cancellationToken, /*throttleWaitMilliseconds*/ 0);
const session = createSession(host, {
canUseEvents: true,
eventHandler: () => { },
cancellationToken,
throttleWaitMilliseconds: 0
});
{
session.executeCommandSeq(<protocol.OpenRequest>{
command: "open",
+103 -33
View File
@@ -323,6 +323,7 @@ namespace ts.server {
logger: Logger;
cancellationToken: HostCancellationToken;
useSingleInferredProject: boolean;
useInferredProjectPerProjectRoot: boolean;
typingsInstaller: ITypingsInstaller;
eventHandler?: ProjectServiceEventHandler;
throttleWaitMilliseconds?: number;
@@ -364,7 +365,7 @@ namespace ts.server {
readonly openFiles: ScriptInfo[] = [];
private compilerOptionsForInferredProjects: CompilerOptions;
private compileOnSaveForInferredProjects: boolean;
private compilerOptionsForInferredProjectsPerProjectRoot = createMap<CompilerOptions>();
private readonly projectToSizeMap: Map<number> = createMap<number>();
private readonly directoryWatchers: DirectoryWatchers;
private readonly throttledOperations: ThrottledOperations;
@@ -382,6 +383,7 @@ namespace ts.server {
public readonly logger: Logger;
public readonly cancellationToken: HostCancellationToken;
public readonly useSingleInferredProject: boolean;
public readonly useInferredProjectPerProjectRoot: boolean;
public readonly typingsInstaller: ITypingsInstaller;
public readonly throttleWaitMilliseconds?: number;
private readonly eventHandler?: ProjectServiceEventHandler;
@@ -398,6 +400,7 @@ namespace ts.server {
this.logger = opts.logger;
this.cancellationToken = opts.cancellationToken;
this.useSingleInferredProject = opts.useSingleInferredProject;
this.useInferredProjectPerProjectRoot = opts.useInferredProjectPerProjectRoot;
this.typingsInstaller = opts.typingsInstaller || nullTypingsInstaller;
this.throttleWaitMilliseconds = opts.throttleWaitMilliseconds;
this.eventHandler = opts.eventHandler;
@@ -463,17 +466,33 @@ namespace ts.server {
project.updateGraph();
}
setCompilerOptionsForInferredProjects(projectCompilerOptions: protocol.ExternalProjectCompilerOptions): void {
this.compilerOptionsForInferredProjects = convertCompilerOptions(projectCompilerOptions);
setCompilerOptionsForInferredProjects(projectCompilerOptions: protocol.ExternalProjectCompilerOptions, projectRootPath?: string): void {
// ignore this settings if we are not creating inferred projects per project root.
if (projectRootPath && !this.useInferredProjectPerProjectRoot) return;
const compilerOptionsForInferredProjects = convertCompilerOptions(projectCompilerOptions);
// always set 'allowNonTsExtensions' for inferred projects since user cannot configure it from the outside
// previously we did not expose a way for user to change these settings and this option was enabled by default
this.compilerOptionsForInferredProjects.allowNonTsExtensions = true;
this.compileOnSaveForInferredProjects = projectCompilerOptions.compileOnSave;
for (const proj of this.inferredProjects) {
proj.setCompilerOptions(this.compilerOptionsForInferredProjects);
proj.compileOnSaveEnabled = projectCompilerOptions.compileOnSave;
compilerOptionsForInferredProjects.allowNonTsExtensions = true;
if (projectRootPath) {
this.compilerOptionsForInferredProjectsPerProjectRoot.set(projectRootPath, compilerOptionsForInferredProjects);
}
this.updateProjectGraphs(this.inferredProjects);
else {
this.compilerOptionsForInferredProjects = compilerOptionsForInferredProjects;
}
const updatedProjects: Project[] = [];
for (const project of this.inferredProjects) {
if (project.projectRootPath === projectRootPath || (project.projectRootPath && !this.compilerOptionsForInferredProjectsPerProjectRoot.has(project.projectRootPath))) {
project.setCompilerOptions(compilerOptionsForInferredProjects);
project.compileOnSaveEnabled = compilerOptionsForInferredProjects.compileOnSave;
updatedProjects.push(project);
}
}
this.updateProjectGraphs(updatedProjects);
}
stopWatchingDirectory(directory: string) {
@@ -713,7 +732,7 @@ namespace ts.server {
}
}
private assignScriptInfoToInferredProjectIfNecessary(info: ScriptInfo, addToListOfOpenFiles: boolean): void {
private assignScriptInfoToInferredProjectIfNecessary(info: ScriptInfo, addToListOfOpenFiles: boolean, projectRootPath?: string): void {
const externalProject = this.findContainingExternalProject(info.fileName);
if (externalProject) {
// file is already included in some external project - do nothing
@@ -741,30 +760,30 @@ namespace ts.server {
}
if (info.containingProjects.length === 0) {
// create new inferred project p with the newly opened file as root
// or add root to existing inferred project if 'useOneInferredProject' is true
const inferredProject = this.createInferredProjectWithRootFileIfNecessary(info);
if (!this.useSingleInferredProject) {
// if useOneInferredProject is not set then try to fixup ownership of open files
// check 'defaultProject !== inferredProject' is necessary to handle cases
// when creation inferred project for some file has added other open files into this project (i.e. as referenced files)
// we definitely don't want to delete the project that was just created
// get (or create) an inferred project using the newly opened file as a root.
const inferredProject = this.createInferredProjectWithRootFileIfNecessary(info, projectRootPath);
if (!this.useSingleInferredProject && !inferredProject.projectRootPath) {
// if useSingleInferredProject is false and the inferred project is not associated
// with a project root, then try to repair the ownership of open files.
for (const f of this.openFiles) {
if (f.containingProjects.length === 0 || !inferredProject.containsScriptInfo(f)) {
// this is orphaned file that we have not processed yet - skip it
continue;
}
for (const fContainingProject of f.containingProjects) {
if (fContainingProject.projectKind === ProjectKind.Inferred &&
fContainingProject.isRoot(f) &&
fContainingProject !== inferredProject) {
for (const containingProject of f.containingProjects) {
// We verify 'containingProject !== inferredProject' to handle cases
// where the inferred project for some file has added other open files
// into this project (i.e. as referenced files) as we don't want to
// delete the project that was just created
if (containingProject.projectKind === ProjectKind.Inferred &&
containingProject !== inferredProject &&
containingProject.isRoot(f)) {
// open file used to be root in inferred project,
// this inferred project is different from the one we've just created for current file
// and new inferred project references this open file.
// We should delete old inferred project and attach open file to the new one
this.removeProject(fContainingProject);
this.removeProject(containingProject);
f.attachToProject(inferredProject);
}
}
@@ -1285,11 +1304,65 @@ namespace ts.server {
return configFileErrors;
}
createInferredProjectWithRootFileIfNecessary(root: ScriptInfo) {
const useExistingProject = this.useSingleInferredProject && this.inferredProjects.length;
const project = useExistingProject
? this.inferredProjects[0]
: new InferredProject(this, this.documentRegistry, this.compilerOptionsForInferredProjects);
private getOrCreateInferredProjectForProjectRootPathIfEnabled(root: ScriptInfo, projectRootPath: string | undefined): InferredProject | undefined {
if (!this.useInferredProjectPerProjectRoot) {
return undefined;
}
if (projectRootPath) {
// if we have an explicit project root path, find (or create) the matching inferred project.
for (const project of this.inferredProjects) {
if (project.projectRootPath === projectRootPath) {
return project;
}
}
return this.createInferredProject(/*isSingleInferredProject*/ false, projectRootPath);
}
// we don't have an explicit root path, so we should try to find an inferred project that best matches the file.
let bestMatch: InferredProject;
for (const project of this.inferredProjects) {
// ignore single inferred projects (handled elsewhere)
if (!project.projectRootPath) continue;
// ignore inferred projects that don't contain the root's path
if (!containsPath(project.projectRootPath, root.path, this.host.getCurrentDirectory(), !this.host.useCaseSensitiveFileNames)) continue;
// ignore inferred projects that are higher up in the project root.
// TODO(rbuckton): Should we add the file as a root to these as well?
if (bestMatch && bestMatch.projectRootPath.length > project.projectRootPath.length) continue;
bestMatch = project;
}
return bestMatch;
}
private getOrCreateSingleInferredProjectIfEnabled(): InferredProject | undefined {
if (!this.useSingleInferredProject) {
return undefined;
}
if (this.inferredProjects.length > 0 && this.inferredProjects[0].projectRootPath === undefined) {
return this.inferredProjects[0];
}
return this.createInferredProject(/*isSingleInferredProject*/ true);
}
private createInferredProject(isSingleInferredProject?: boolean, projectRootPath?: string): InferredProject {
const compilerOptions = projectRootPath && this.compilerOptionsForInferredProjectsPerProjectRoot.get(projectRootPath) || this.compilerOptionsForInferredProjects;
const project = new InferredProject(this, this.documentRegistry, compilerOptions, projectRootPath);
if (isSingleInferredProject) {
this.inferredProjects.unshift(project);
}
else {
this.inferredProjects.push(project);
}
return project;
}
createInferredProjectWithRootFileIfNecessary(root: ScriptInfo, projectRootPath?: string) {
const project = this.getOrCreateInferredProjectForProjectRootPathIfEnabled(root, projectRootPath) ||
this.getOrCreateSingleInferredProjectIfEnabled() ||
this.createInferredProject();
project.addRoot(root);
@@ -1300,9 +1373,6 @@ namespace ts.server {
project.updateGraph();
if (!useExistingProject) {
this.inferredProjects.push(project);
}
return project;
}
@@ -1476,7 +1546,7 @@ namespace ts.server {
// at this point if file is the part of some configured/external project then this project should be created
const info = this.getOrCreateScriptInfoForNormalizedPath(fileName, /*openedByClient*/ true, fileContent, scriptKind, hasMixedContent);
this.assignScriptInfoToInferredProjectIfNecessary(info, /*addToListOfOpenFiles*/ true);
this.assignScriptInfoToInferredProjectIfNecessary(info, /*addToListOfOpenFiles*/ true, projectRootPath);
// Delete the orphan files here because there might be orphan script infos (which are not part of project)
// when some file/s were closed which resulted in project removal.
// It was then postponed to cleanup these script infos so that they can be reused if
+3 -1
View File
@@ -836,6 +836,7 @@ namespace ts.server {
* the file and its imports/references are put into an InferredProject.
*/
export class InferredProject extends Project {
public readonly projectRootPath: string | undefined;
private static readonly newName = (() => {
let nextId = 1;
@@ -875,7 +876,7 @@ namespace ts.server {
// Used to keep track of what directories are watched for this project
directoriesWatchedForTsconfig: string[] = [];
constructor(projectService: ProjectService, documentRegistry: DocumentRegistry, compilerOptions: CompilerOptions) {
constructor(projectService: ProjectService, documentRegistry: DocumentRegistry, compilerOptions: CompilerOptions, projectRootPath?: string) {
super(InferredProject.newName(),
ProjectKind.Inferred,
projectService,
@@ -884,6 +885,7 @@ namespace ts.server {
/*languageServiceEnabled*/ true,
compilerOptions,
/*compileOnSaveEnabled*/ false);
this.projectRootPath = projectRootPath;
}
addRoot(info: ScriptInfo) {
+7
View File
@@ -1304,6 +1304,13 @@ namespace ts.server.protocol {
* Compiler options to be used with inferred projects.
*/
options: ExternalProjectCompilerOptions;
/**
* Specifies the project root path used to scope commpiler options.
* This message is ignored if this property has been specified and the server is not
* configured to create an inferred project per project root.
*/
projectRootPath?: string;
}
/**
+4
View File
@@ -9,6 +9,7 @@ namespace ts.server {
canUseEvents: boolean;
installerEventPort: number;
useSingleInferredProject: boolean;
useInferredProjectPerProjectRoot: boolean;
disableAutomaticTypingAcquisition: boolean;
globalTypingsCacheLocation: string;
logger: Logger;
@@ -410,6 +411,7 @@ namespace ts.server {
host,
cancellationToken,
useSingleInferredProject,
useInferredProjectPerProjectRoot,
typingsInstaller: typingsInstaller || nullTypingsInstaller,
byteLength: Buffer.byteLength,
hrtime: process.hrtime,
@@ -765,6 +767,7 @@ namespace ts.server {
const allowLocalPluginLoads = hasArgument("--allowLocalPluginLoads");
const useSingleInferredProject = hasArgument("--useSingleInferredProject");
const useInferredProjectPerProjectRoot = hasArgument("--useInferredProjectPerProjectRoot");
const disableAutomaticTypingAcquisition = hasArgument("--disableAutomaticTypingAcquisition");
const telemetryEnabled = hasArgument(Arguments.EnableTelemetry);
@@ -774,6 +777,7 @@ namespace ts.server {
installerEventPort: eventPort,
canUseEvents: eventPort === undefined,
useSingleInferredProject,
useInferredProjectPerProjectRoot,
disableAutomaticTypingAcquisition,
globalTypingsCacheLocation: getGlobalTypingsCacheLocation(),
typingSafeListLocation,
+3 -1
View File
@@ -251,6 +251,7 @@ namespace ts.server {
host: ServerHost;
cancellationToken: ServerCancellationToken;
useSingleInferredProject: boolean;
useInferredProjectPerProjectRoot: boolean;
typingsInstaller: ITypingsInstaller;
byteLength: (buf: string, encoding?: string) => number;
hrtime: (start?: number[]) => number[];
@@ -311,6 +312,7 @@ namespace ts.server {
logger: this.logger,
cancellationToken: this.cancellationToken,
useSingleInferredProject: opts.useSingleInferredProject,
useInferredProjectPerProjectRoot: opts.useInferredProjectPerProjectRoot,
typingsInstaller: this.typingsInstaller,
throttleWaitMilliseconds,
eventHandler: this.eventHandler,
@@ -744,7 +746,7 @@ namespace ts.server {
}
private setCompilerOptionsForInferredProjects(args: protocol.SetCompilerOptionsForInferredProjectsArgs): void {
this.projectService.setCompilerOptionsForInferredProjects(args.options);
this.projectService.setCompilerOptionsForInferredProjects(args.options, args.projectRootPath);
}
private getProjectInfo(args: protocol.ProjectInfoRequestArgs): protocol.ProjectInfo {