Skip to content

Commit fa7f3e8

Browse files
committed
Adds support for inferred project isolation by projectRootPath
1 parent c969807 commit fa7f3e8

File tree

10 files changed

+278
-67
lines changed

10 files changed

+278
-67
lines changed

src/harness/harnessLanguageService.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -828,6 +828,7 @@ namespace Harness.LanguageService {
828828
host: serverHost,
829829
cancellationToken: ts.server.nullCancellationToken,
830830
useSingleInferredProject: false,
831+
useInferredProjectPerProjectRoot: false,
831832
typingsInstaller: undefined,
832833
byteLength: Utils.byteLength,
833834
hrtime: process.hrtime,

src/harness/unittests/cachingInServerLSHost.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ namespace ts {
6969
logger,
7070
cancellationToken: { isCancellationRequested: () => false },
7171
useSingleInferredProject: false,
72+
useInferredProjectPerProjectRoot: false,
7273
typingsInstaller: undefined
7374
};
7475
const projectService = new server.ProjectService(svcOpts);

src/harness/unittests/compileOnSave.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ namespace ts.projectSystem {
3636
host,
3737
cancellationToken: nullCancellationToken,
3838
useSingleInferredProject: false,
39+
useInferredProjectPerProjectRoot: false,
3940
typingsInstaller: typingsInstaller || server.nullTypingsInstaller,
4041
byteLength: Utils.byteLength,
4142
hrtime: process.hrtime,
@@ -550,7 +551,7 @@ namespace ts.projectSystem {
550551
};
551552
const host = createServerHost([file1, file2, configFile, libFile], { newLine: "\r\n" });
552553
const typingsInstaller = createTestTypingsInstaller(host);
553-
const session = createSession(host, typingsInstaller);
554+
const session = createSession(host, { typingsInstaller });
554555

555556
openFilesForSession([file1, file2], session);
556557
const compileFileRequest = makeSessionRequest<server.protocol.CompileOnSaveEmitFileRequestArgs>(CommandNames.CompileOnSaveEmitFile, { file: file1.path, projectFileName: configFile.path });

src/harness/unittests/session.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ namespace ts.server {
5555
host: mockHost,
5656
cancellationToken: nullCancellationToken,
5757
useSingleInferredProject: false,
58+
useInferredProjectPerProjectRoot: false,
5859
typingsInstaller: undefined,
5960
byteLength: Utils.byteLength,
6061
hrtime: process.hrtime,
@@ -405,6 +406,7 @@ namespace ts.server {
405406
host: mockHost,
406407
cancellationToken: nullCancellationToken,
407408
useSingleInferredProject: false,
409+
useInferredProjectPerProjectRoot: false,
408410
typingsInstaller: undefined,
409411
byteLength: Utils.byteLength,
410412
hrtime: process.hrtime,
@@ -472,6 +474,7 @@ namespace ts.server {
472474
host: mockHost,
473475
cancellationToken: nullCancellationToken,
474476
useSingleInferredProject: false,
477+
useInferredProjectPerProjectRoot: false,
475478
typingsInstaller: undefined,
476479
byteLength: Utils.byteLength,
477480
hrtime: process.hrtime,

src/harness/unittests/tsserverProjectSystem.ts

Lines changed: 151 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -186,23 +186,25 @@ namespace ts.projectSystem {
186186
}
187187
}
188188

189-
export function createSession(host: server.ServerHost, typingsInstaller?: server.ITypingsInstaller, projectServiceEventHandler?: server.ProjectServiceEventHandler, cancellationToken?: server.ServerCancellationToken, throttleWaitMilliseconds?: number) {
190-
if (typingsInstaller === undefined) {
191-
typingsInstaller = new TestTypingsInstaller("/a/data/", /*throttleLimit*/5, host);
189+
export function createSession(host: server.ServerHost, opts: Partial<server.SessionOptions> = {}) {
190+
if (opts.typingsInstaller === undefined) {
191+
opts.typingsInstaller = new TestTypingsInstaller("/a/data/", /*throttleLimit*/5, host);
192192
}
193-
const opts: server.SessionOptions = {
193+
if (opts.eventHandler !== undefined) {
194+
opts.canUseEvents = true;
195+
}
196+
return new TestSession({
194197
host,
195-
cancellationToken: cancellationToken || server.nullCancellationToken,
198+
cancellationToken: server.nullCancellationToken,
196199
useSingleInferredProject: false,
197-
typingsInstaller,
200+
useInferredProjectPerProjectRoot: false,
201+
typingsInstaller: opts.typingsInstaller,
198202
byteLength: Utils.byteLength,
199203
hrtime: process.hrtime,
200204
logger: nullLogger,
201-
canUseEvents: projectServiceEventHandler !== undefined,
202-
eventHandler: projectServiceEventHandler,
203-
throttleWaitMilliseconds
204-
};
205-
return new TestSession(opts);
205+
canUseEvents: false,
206+
...opts
207+
});
206208
}
207209

208210
export interface CreateProjectServiceParameters {
@@ -216,9 +218,16 @@ namespace ts.projectSystem {
216218

217219
export class TestProjectService extends server.ProjectService {
218220
constructor(host: server.ServerHost, logger: server.Logger, cancellationToken: HostCancellationToken, useSingleInferredProject: boolean,
219-
typingsInstaller: server.ITypingsInstaller, eventHandler: server.ProjectServiceEventHandler) {
221+
typingsInstaller: server.ITypingsInstaller, eventHandler: server.ProjectServiceEventHandler, opts: Partial<server.ProjectServiceOptions> = {}) {
220222
super({
221-
host, logger, cancellationToken, useSingleInferredProject, typingsInstaller, eventHandler
223+
host,
224+
logger,
225+
cancellationToken,
226+
useSingleInferredProject,
227+
useInferredProjectPerProjectRoot: false,
228+
typingsInstaller,
229+
eventHandler,
230+
...opts
222231
});
223232
}
224233

@@ -632,7 +641,7 @@ namespace ts.projectSystem {
632641
}
633642
}
634643

635-
describe("tsserver-project-system", () => {
644+
describe("tsserverProjectSystem", () => {
636645
const commonFile1: FileOrFolder = {
637646
path: "/a/b/commonFile1.ts",
638647
content: "let x = 1"
@@ -2231,13 +2240,16 @@ namespace ts.projectSystem {
22312240
filePath === f2.path ? server.maxProgramSizeForNonTsFiles + 1 : originalGetFileSize.call(host, filePath);
22322241

22332242
let lastEvent: server.ProjectLanguageServiceStateEvent;
2234-
const session = createSession(host, /*typingsInstaller*/ undefined, e => {
2235-
if (e.eventName === server.ConfigFileDiagEvent || e.eventName === server.ContextEvent || e.eventName === server.ProjectInfoTelemetryEvent) {
2236-
return;
2243+
const session = createSession(host, {
2244+
canUseEvents: true,
2245+
eventHandler: e => {
2246+
if (e.eventName === server.ConfigFileDiagEvent || e.eventName === server.ContextEvent || e.eventName === server.ProjectInfoTelemetryEvent) {
2247+
return;
2248+
}
2249+
assert.equal(e.eventName, server.ProjectLanguageServiceStateEvent);
2250+
assert.equal(e.data.project.getProjectName(), config.path, "project name");
2251+
lastEvent = <server.ProjectLanguageServiceStateEvent>e;
22372252
}
2238-
assert.equal(e.eventName, server.ProjectLanguageServiceStateEvent);
2239-
assert.equal(e.data.project.getProjectName(), config.path, "project name");
2240-
lastEvent = <server.ProjectLanguageServiceStateEvent>e;
22412253
});
22422254
session.executeCommand(<protocol.OpenRequest>{
22432255
seq: 0,
@@ -2281,12 +2293,15 @@ namespace ts.projectSystem {
22812293
host.getFileSize = (filePath: string) =>
22822294
filePath === f2.path ? server.maxProgramSizeForNonTsFiles + 1 : originalGetFileSize.call(host, filePath);
22832295
let lastEvent: server.ProjectLanguageServiceStateEvent;
2284-
const session = createSession(host, /*typingsInstaller*/ undefined, e => {
2285-
if (e.eventName === server.ConfigFileDiagEvent || e.eventName === server.ProjectInfoTelemetryEvent) {
2286-
return;
2296+
const session = createSession(host, {
2297+
canUseEvents: true,
2298+
eventHandler: e => {
2299+
if (e.eventName === server.ConfigFileDiagEvent || e.eventName === server.ProjectInfoTelemetryEvent) {
2300+
return;
2301+
}
2302+
assert.equal(e.eventName, server.ProjectLanguageServiceStateEvent);
2303+
lastEvent = <server.ProjectLanguageServiceStateEvent>e;
22872304
}
2288-
assert.equal(e.eventName, server.ProjectLanguageServiceStateEvent);
2289-
lastEvent = <server.ProjectLanguageServiceStateEvent>e;
22902305
});
22912306
session.executeCommand(<protocol.OpenRequest>{
22922307
seq: 0,
@@ -3070,7 +3085,10 @@ namespace ts.projectSystem {
30703085
};
30713086

30723087
const host = createServerHost([file, configFile]);
3073-
const session = createSession(host, /*typingsInstaller*/ undefined, serverEventManager.handler);
3088+
const session = createSession(host, {
3089+
canUseEvents: true,
3090+
eventHandler: serverEventManager.handler
3091+
});
30743092
openFilesForSession([file], session);
30753093
serverEventManager.checkEventCountOfType("configFileDiag", 1);
30763094

@@ -3097,7 +3115,10 @@ namespace ts.projectSystem {
30973115
};
30983116

30993117
const host = createServerHost([file, configFile]);
3100-
const session = createSession(host, /*typingsInstaller*/ undefined, serverEventManager.handler);
3118+
const session = createSession(host, {
3119+
canUseEvents: true,
3120+
eventHandler: serverEventManager.handler
3121+
});
31013122
openFilesForSession([file], session);
31023123
serverEventManager.checkEventCountOfType("configFileDiag", 1);
31033124
});
@@ -3116,7 +3137,10 @@ namespace ts.projectSystem {
31163137
};
31173138

31183139
const host = createServerHost([file, configFile]);
3119-
const session = createSession(host, /*typingsInstaller*/ undefined, serverEventManager.handler);
3140+
const session = createSession(host, {
3141+
canUseEvents: true,
3142+
eventHandler: serverEventManager.handler
3143+
});
31203144
openFilesForSession([file], session);
31213145
serverEventManager.checkEventCountOfType("configFileDiag", 1);
31223146

@@ -3505,6 +3529,93 @@ namespace ts.projectSystem {
35053529
checkNumberOfProjects(projectService, { inferredProjects: 1 });
35063530
checkProjectActualFiles(projectService.inferredProjects[0], [f.path]);
35073531
});
3532+
3533+
it("inferred projects per project root", () => {
3534+
const file1 = { path: "/a/file1.ts", content: "let x = 1;", projectRootPath: "/a" };
3535+
const file2 = { path: "/a/file2.ts", content: "let y = 2;", projectRootPath: "/a" };
3536+
const file3 = { path: "/b/file2.ts", content: "let x = 3;", projectRootPath: "/b" };
3537+
const file4 = { path: "/c/file3.ts", content: "let z = 4;" };
3538+
const host = createServerHost([file1, file2, file3, file4]);
3539+
const session = createSession(host, {
3540+
useSingleInferredProject: true,
3541+
useInferredProjectPerProjectRoot: true
3542+
});
3543+
session.executeCommand(<server.protocol.SetCompilerOptionsForInferredProjectsRequest>{
3544+
seq: 1,
3545+
type: "request",
3546+
command: CommandNames.CompilerOptionsForInferredProjects,
3547+
arguments: {
3548+
options: {
3549+
allowJs: true,
3550+
target: ScriptTarget.ESNext
3551+
}
3552+
}
3553+
});
3554+
session.executeCommand(<server.protocol.SetCompilerOptionsForInferredProjectsRequest>{
3555+
seq: 2,
3556+
type: "request",
3557+
command: CommandNames.CompilerOptionsForInferredProjects,
3558+
arguments: {
3559+
options: {
3560+
allowJs: true,
3561+
target: ScriptTarget.ES2015
3562+
},
3563+
projectRootPath: "/b"
3564+
}
3565+
});
3566+
session.executeCommand(<server.protocol.OpenRequest>{
3567+
seq: 3,
3568+
type: "request",
3569+
command: CommandNames.Open,
3570+
arguments: {
3571+
file: file1.path,
3572+
fileContent: file1.content,
3573+
scriptKindName: "JS",
3574+
projectRootPath: file1.projectRootPath
3575+
}
3576+
});
3577+
session.executeCommand(<server.protocol.OpenRequest>{
3578+
seq: 4,
3579+
type: "request",
3580+
command: CommandNames.Open,
3581+
arguments: {
3582+
file: file2.path,
3583+
fileContent: file2.content,
3584+
scriptKindName: "JS",
3585+
projectRootPath: file2.projectRootPath
3586+
}
3587+
});
3588+
session.executeCommand(<server.protocol.OpenRequest>{
3589+
seq: 5,
3590+
type: "request",
3591+
command: CommandNames.Open,
3592+
arguments: {
3593+
file: file3.path,
3594+
fileContent: file3.content,
3595+
scriptKindName: "JS",
3596+
projectRootPath: file3.projectRootPath
3597+
}
3598+
});
3599+
session.executeCommand(<server.protocol.OpenRequest>{
3600+
seq: 6,
3601+
type: "request",
3602+
command: CommandNames.Open,
3603+
arguments: {
3604+
file: file4.path,
3605+
fileContent: file4.content,
3606+
scriptKindName: "JS"
3607+
}
3608+
});
3609+
3610+
const projectService = session.getProjectService();
3611+
checkNumberOfProjects(projectService, { inferredProjects: 3 });
3612+
checkProjectActualFiles(projectService.inferredProjects[0], [file4.path]);
3613+
checkProjectActualFiles(projectService.inferredProjects[1], [file1.path, file2.path]);
3614+
checkProjectActualFiles(projectService.inferredProjects[2], [file3.path]);
3615+
assert.equal(projectService.inferredProjects[0].getCompilerOptions().target, ScriptTarget.ESNext);
3616+
assert.equal(projectService.inferredProjects[1].getCompilerOptions().target, ScriptTarget.ESNext);
3617+
assert.equal(projectService.inferredProjects[2].getCompilerOptions().target, ScriptTarget.ES2015);
3618+
});
35083619
});
35093620

35103621
describe("No overwrite emit error", () => {
@@ -3698,7 +3809,7 @@ namespace ts.projectSystem {
36983809
resetRequest: noop
36993810
};
37003811

3701-
const session = createSession(host, /*typingsInstaller*/ undefined, /*projectServiceEventHandler*/ undefined, cancellationToken);
3812+
const session = createSession(host, { cancellationToken });
37023813

37033814
expectedRequestId = session.getNextSeq();
37043815
session.executeCommandSeq(<server.protocol.OpenRequest>{
@@ -3738,7 +3849,11 @@ namespace ts.projectSystem {
37383849

37393850
const cancellationToken = new TestServerCancellationToken();
37403851
const host = createServerHost([f1, config]);
3741-
const session = createSession(host, /*typingsInstaller*/ undefined, () => { }, cancellationToken);
3852+
const session = createSession(host, {
3853+
canUseEvents: true,
3854+
eventHandler: () => { },
3855+
cancellationToken
3856+
});
37423857
{
37433858
session.executeCommandSeq(<protocol.OpenRequest>{
37443859
command: "open",
@@ -3871,7 +3986,12 @@ namespace ts.projectSystem {
38713986
};
38723987
const cancellationToken = new TestServerCancellationToken(/*cancelAfterRequest*/ 3);
38733988
const host = createServerHost([f1, config]);
3874-
const session = createSession(host, /*typingsInstaller*/ undefined, () => { }, cancellationToken, /*throttleWaitMilliseconds*/ 0);
3989+
const session = createSession(host, {
3990+
canUseEvents: true,
3991+
eventHandler: () => { },
3992+
cancellationToken,
3993+
throttleWaitMilliseconds: 0
3994+
});
38753995
{
38763996
session.executeCommandSeq(<protocol.OpenRequest>{
38773997
command: "open",

0 commit comments

Comments
 (0)