Fix merge
This commit is contained in:
parent
d129199f41
commit
3cc379c3c0
|
@ -818,13 +818,17 @@ namespace Harness.LanguageService {
|
||||||
// This host is just a proxy for the clientHost, it uses the client
|
// This host is just a proxy for the clientHost, it uses the client
|
||||||
// host to answer server queries about files on disk
|
// host to answer server queries about files on disk
|
||||||
const serverHost = new SessionServerHost(clientHost);
|
const serverHost = new SessionServerHost(clientHost);
|
||||||
const server = new ts.server.Session(serverHost,
|
const opts: ts.server.SessionOptions = {
|
||||||
ts.server.nullCancellationToken,
|
host: serverHost,
|
||||||
/*useOneInferredProject*/ false,
|
cancellationToken: ts.server.nullCancellationToken,
|
||||||
/*typingsInstaller*/ undefined,
|
useSingleInferredProject: false,
|
||||||
Utils.byteLength,
|
typingsInstaller: undefined,
|
||||||
process.hrtime, serverHost,
|
byteLength: Utils.byteLength,
|
||||||
/*canUseEvents*/ true);
|
hrtime: process.hrtime,
|
||||||
|
logger: serverHost,
|
||||||
|
canUseEvents: true
|
||||||
|
};
|
||||||
|
const server = new ts.server.Session(opts);
|
||||||
|
|
||||||
// Fake the connection between the client and the server
|
// Fake the connection between the client and the server
|
||||||
serverHost.writeMessage = client.onMessage.bind(client);
|
serverHost.writeMessage = client.onMessage.bind(client);
|
||||||
|
|
|
@ -64,8 +64,16 @@ namespace ts {
|
||||||
getLogFileName: (): string => undefined
|
getLogFileName: (): string => undefined
|
||||||
};
|
};
|
||||||
|
|
||||||
const projectService = new server.ProjectService(serverHost, logger, { isCancellationRequested: () => false }, /*useOneInferredProject*/ false, /*typingsInstaller*/ undefined);
|
const svcOpts: server.ProjectServiceOptions = {
|
||||||
const rootScriptInfo = projectService.getOrCreateScriptInfo(rootFile, /*openedByClient*/ true, /*containingProject*/ undefined);
|
host: serverHost,
|
||||||
|
logger,
|
||||||
|
cancellationToken: { isCancellationRequested: () => false },
|
||||||
|
useSingleInferredProject: false,
|
||||||
|
typingsInstaller: undefined
|
||||||
|
};
|
||||||
|
const projectService = new server.ProjectService(svcOpts);
|
||||||
|
const rootScriptInfo = projectService.getOrCreateScriptInfo(rootFile, /* openedByClient */true, /*containingProject*/ undefined);
|
||||||
|
|
||||||
const project = projectService.createInferredProjectWithRootFileIfNecessary(rootScriptInfo);
|
const project = projectService.createInferredProjectWithRootFileIfNecessary(rootScriptInfo);
|
||||||
project.setCompilerOptions({ module: ts.ModuleKind.AMD } );
|
project.setCompilerOptions({ module: ts.ModuleKind.AMD } );
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -31,6 +31,20 @@ namespace ts.projectSystem {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function createSession(host: server.ServerHost, typingsInstaller?: server.ITypingsInstaller): server.Session {
|
||||||
|
const opts: server.SessionOptions = {
|
||||||
|
host,
|
||||||
|
cancellationToken: nullCancellationToken,
|
||||||
|
useSingleInferredProject: false,
|
||||||
|
typingsInstaller: typingsInstaller || server.nullTypingsInstaller,
|
||||||
|
byteLength: Utils.byteLength,
|
||||||
|
hrtime: process.hrtime,
|
||||||
|
logger: nullLogger,
|
||||||
|
canUseEvents: false
|
||||||
|
};
|
||||||
|
return new server.Session(opts);
|
||||||
|
}
|
||||||
|
|
||||||
describe("for configured projects", () => {
|
describe("for configured projects", () => {
|
||||||
let moduleFile1: FileOrFolder;
|
let moduleFile1: FileOrFolder;
|
||||||
let file1Consumer1: FileOrFolder;
|
let file1Consumer1: FileOrFolder;
|
||||||
|
@ -113,7 +127,7 @@ namespace ts.projectSystem {
|
||||||
it("should contains only itself if a module file's shape didn't change, and all files referencing it if its shape changed", () => {
|
it("should contains only itself if a module file's shape didn't change, and all files referencing it if its shape changed", () => {
|
||||||
const host = createServerHost([moduleFile1, file1Consumer1, file1Consumer2, globalFile3, moduleFile2, configFile, libFile]);
|
const host = createServerHost([moduleFile1, file1Consumer1, file1Consumer2, globalFile3, moduleFile2, configFile, libFile]);
|
||||||
const typingsInstaller = createTestTypingsInstaller(host);
|
const typingsInstaller = createTestTypingsInstaller(host);
|
||||||
const session = new server.Session(host, nullCancellationToken, /*useSingleInferredProject*/ false, typingsInstaller, Utils.byteLength, process.hrtime, nullLogger, /*canUseEvents*/ false);
|
const session = createSession(host, typingsInstaller);
|
||||||
|
|
||||||
openFilesForSession([moduleFile1, file1Consumer1], session);
|
openFilesForSession([moduleFile1, file1Consumer1], session);
|
||||||
|
|
||||||
|
@ -138,7 +152,7 @@ namespace ts.projectSystem {
|
||||||
it("should be up-to-date with the reference map changes", () => {
|
it("should be up-to-date with the reference map changes", () => {
|
||||||
const host = createServerHost([moduleFile1, file1Consumer1, file1Consumer2, globalFile3, moduleFile2, configFile, libFile]);
|
const host = createServerHost([moduleFile1, file1Consumer1, file1Consumer2, globalFile3, moduleFile2, configFile, libFile]);
|
||||||
const typingsInstaller = createTestTypingsInstaller(host);
|
const typingsInstaller = createTestTypingsInstaller(host);
|
||||||
const session = new server.Session(host, nullCancellationToken, /*useSingleInferredProject*/ false, typingsInstaller, Utils.byteLength, process.hrtime, nullLogger, /*canUseEvents*/ false);
|
const session = createSession(host, typingsInstaller);
|
||||||
|
|
||||||
openFilesForSession([moduleFile1, file1Consumer1], session);
|
openFilesForSession([moduleFile1, file1Consumer1], session);
|
||||||
|
|
||||||
|
@ -185,7 +199,7 @@ namespace ts.projectSystem {
|
||||||
it("should be up-to-date with changes made in non-open files", () => {
|
it("should be up-to-date with changes made in non-open files", () => {
|
||||||
const host = createServerHost([moduleFile1, file1Consumer1, file1Consumer2, globalFile3, moduleFile2, configFile, libFile]);
|
const host = createServerHost([moduleFile1, file1Consumer1, file1Consumer2, globalFile3, moduleFile2, configFile, libFile]);
|
||||||
const typingsInstaller = createTestTypingsInstaller(host);
|
const typingsInstaller = createTestTypingsInstaller(host);
|
||||||
const session = new server.Session(host, nullCancellationToken, /*useSingleInferredProject*/ false, typingsInstaller, Utils.byteLength, process.hrtime, nullLogger, /*canUseEvents*/ false);
|
const session = createSession(host, typingsInstaller);
|
||||||
|
|
||||||
openFilesForSession([moduleFile1], session);
|
openFilesForSession([moduleFile1], session);
|
||||||
|
|
||||||
|
@ -203,7 +217,7 @@ namespace ts.projectSystem {
|
||||||
it("should be up-to-date with deleted files", () => {
|
it("should be up-to-date with deleted files", () => {
|
||||||
const host = createServerHost([moduleFile1, file1Consumer1, file1Consumer2, globalFile3, moduleFile2, configFile, libFile]);
|
const host = createServerHost([moduleFile1, file1Consumer1, file1Consumer2, globalFile3, moduleFile2, configFile, libFile]);
|
||||||
const typingsInstaller = createTestTypingsInstaller(host);
|
const typingsInstaller = createTestTypingsInstaller(host);
|
||||||
const session = new server.Session(host, nullCancellationToken, /*useSingleInferredProject*/ false, typingsInstaller, Utils.byteLength, process.hrtime, nullLogger, /*canUseEvents*/ false);
|
const session = createSession(host, typingsInstaller);
|
||||||
|
|
||||||
openFilesForSession([moduleFile1], session);
|
openFilesForSession([moduleFile1], session);
|
||||||
sendAffectedFileRequestAndCheckResult(session, moduleFile1FileListRequest, [{ projectFileName: configFile.path, files: [moduleFile1, file1Consumer1, file1Consumer2] }]);
|
sendAffectedFileRequestAndCheckResult(session, moduleFile1FileListRequest, [{ projectFileName: configFile.path, files: [moduleFile1, file1Consumer1, file1Consumer2] }]);
|
||||||
|
@ -218,7 +232,7 @@ namespace ts.projectSystem {
|
||||||
it("should be up-to-date with newly created files", () => {
|
it("should be up-to-date with newly created files", () => {
|
||||||
const host = createServerHost([moduleFile1, file1Consumer1, file1Consumer2, globalFile3, moduleFile2, configFile, libFile]);
|
const host = createServerHost([moduleFile1, file1Consumer1, file1Consumer2, globalFile3, moduleFile2, configFile, libFile]);
|
||||||
const typingsInstaller = createTestTypingsInstaller(host);
|
const typingsInstaller = createTestTypingsInstaller(host);
|
||||||
const session = new server.Session(host, nullCancellationToken, /*useSingleInferredProject*/ false, typingsInstaller, Utils.byteLength, process.hrtime, nullLogger, /*canUseEvents*/ false);
|
const session = createSession(host, typingsInstaller);
|
||||||
|
|
||||||
openFilesForSession([moduleFile1], session);
|
openFilesForSession([moduleFile1], session);
|
||||||
sendAffectedFileRequestAndCheckResult(session, moduleFile1FileListRequest, [{ projectFileName: configFile.path, files: [moduleFile1, file1Consumer1, file1Consumer2] }]);
|
sendAffectedFileRequestAndCheckResult(session, moduleFile1FileListRequest, [{ projectFileName: configFile.path, files: [moduleFile1, file1Consumer1, file1Consumer2] }]);
|
||||||
|
@ -255,7 +269,7 @@ namespace ts.projectSystem {
|
||||||
|
|
||||||
const host = createServerHost([moduleFile1, file1Consumer1, configFile, libFile]);
|
const host = createServerHost([moduleFile1, file1Consumer1, configFile, libFile]);
|
||||||
const typingsInstaller = createTestTypingsInstaller(host);
|
const typingsInstaller = createTestTypingsInstaller(host);
|
||||||
const session = new server.Session(host, nullCancellationToken, /*useSingleInferredProject*/ false, typingsInstaller, Utils.byteLength, process.hrtime, nullLogger, /*canUseEvents*/ false);
|
const session = createSession(host, typingsInstaller);
|
||||||
|
|
||||||
openFilesForSession([moduleFile1, file1Consumer1], session);
|
openFilesForSession([moduleFile1, file1Consumer1], session);
|
||||||
sendAffectedFileRequestAndCheckResult(session, moduleFile1FileListRequest, [{ projectFileName: configFile.path, files: [moduleFile1, file1Consumer1] }]);
|
sendAffectedFileRequestAndCheckResult(session, moduleFile1FileListRequest, [{ projectFileName: configFile.path, files: [moduleFile1, file1Consumer1] }]);
|
||||||
|
@ -272,7 +286,7 @@ namespace ts.projectSystem {
|
||||||
it("should return all files if a global file changed shape", () => {
|
it("should return all files if a global file changed shape", () => {
|
||||||
const host = createServerHost([moduleFile1, file1Consumer1, file1Consumer2, globalFile3, moduleFile2, configFile, libFile]);
|
const host = createServerHost([moduleFile1, file1Consumer1, file1Consumer2, globalFile3, moduleFile2, configFile, libFile]);
|
||||||
const typingsInstaller = createTestTypingsInstaller(host);
|
const typingsInstaller = createTestTypingsInstaller(host);
|
||||||
const session = new server.Session(host, nullCancellationToken, /*useSingleInferredProject*/ false, typingsInstaller, Utils.byteLength, process.hrtime, nullLogger, /*canUseEvents*/ false);
|
const session = createSession(host, typingsInstaller);
|
||||||
|
|
||||||
openFilesForSession([globalFile3], session);
|
openFilesForSession([globalFile3], session);
|
||||||
const changeGlobalFile3ShapeRequest = makeSessionRequest<server.protocol.ChangeRequestArgs>(CommandNames.Change, {
|
const changeGlobalFile3ShapeRequest = makeSessionRequest<server.protocol.ChangeRequestArgs>(CommandNames.Change, {
|
||||||
|
@ -298,7 +312,7 @@ namespace ts.projectSystem {
|
||||||
|
|
||||||
const host = createServerHost([moduleFile1, file1Consumer1, file1Consumer2, configFile, libFile]);
|
const host = createServerHost([moduleFile1, file1Consumer1, file1Consumer2, configFile, libFile]);
|
||||||
const typingsInstaller = createTestTypingsInstaller(host);
|
const typingsInstaller = createTestTypingsInstaller(host);
|
||||||
const session = new server.Session(host, nullCancellationToken, /*useSingleInferredProject*/ false, typingsInstaller, Utils.byteLength, process.hrtime, nullLogger, /*canUseEvents*/ false);
|
const session = createSession(host, typingsInstaller);
|
||||||
openFilesForSession([moduleFile1], session);
|
openFilesForSession([moduleFile1], session);
|
||||||
sendAffectedFileRequestAndCheckResult(session, moduleFile1FileListRequest, []);
|
sendAffectedFileRequestAndCheckResult(session, moduleFile1FileListRequest, []);
|
||||||
});
|
});
|
||||||
|
@ -316,7 +330,7 @@ namespace ts.projectSystem {
|
||||||
|
|
||||||
const host = createServerHost([moduleFile1, file1Consumer1, configFile, libFile]);
|
const host = createServerHost([moduleFile1, file1Consumer1, configFile, libFile]);
|
||||||
const typingsInstaller = createTestTypingsInstaller(host);
|
const typingsInstaller = createTestTypingsInstaller(host);
|
||||||
const session = new server.Session(host, nullCancellationToken, /*useSingleInferredProject*/ false, typingsInstaller, Utils.byteLength, process.hrtime, nullLogger, /*canUseEvents*/ false);
|
const session = createSession(host, typingsInstaller);
|
||||||
openFilesForSession([moduleFile1], session);
|
openFilesForSession([moduleFile1], session);
|
||||||
|
|
||||||
const file1ChangeShapeRequest = makeSessionRequest<server.protocol.ChangeRequestArgs>(CommandNames.Change, {
|
const file1ChangeShapeRequest = makeSessionRequest<server.protocol.ChangeRequestArgs>(CommandNames.Change, {
|
||||||
|
@ -345,7 +359,7 @@ namespace ts.projectSystem {
|
||||||
|
|
||||||
const host = createServerHost([moduleFile1, file1Consumer1, configFile, libFile]);
|
const host = createServerHost([moduleFile1, file1Consumer1, configFile, libFile]);
|
||||||
const typingsInstaller = createTestTypingsInstaller(host);
|
const typingsInstaller = createTestTypingsInstaller(host);
|
||||||
const session = new server.Session(host, nullCancellationToken, /*useSingleInferredProject*/ false, typingsInstaller, Utils.byteLength, process.hrtime, nullLogger, /*canUseEvents*/ false);
|
const session = createSession(host, typingsInstaller);
|
||||||
openFilesForSession([moduleFile1], session);
|
openFilesForSession([moduleFile1], session);
|
||||||
|
|
||||||
const file1ChangeShapeRequest = makeSessionRequest<server.protocol.ChangeRequestArgs>(CommandNames.Change, {
|
const file1ChangeShapeRequest = makeSessionRequest<server.protocol.ChangeRequestArgs>(CommandNames.Change, {
|
||||||
|
@ -367,7 +381,7 @@ namespace ts.projectSystem {
|
||||||
};
|
};
|
||||||
const host = createServerHost([moduleFile1, file1Consumer1, file1Consumer1Consumer1, globalFile3, configFile, libFile]);
|
const host = createServerHost([moduleFile1, file1Consumer1, file1Consumer1Consumer1, globalFile3, configFile, libFile]);
|
||||||
const typingsInstaller = createTestTypingsInstaller(host);
|
const typingsInstaller = createTestTypingsInstaller(host);
|
||||||
const session = new server.Session(host, nullCancellationToken, /*useSingleInferredProject*/ false, typingsInstaller, Utils.byteLength, process.hrtime, nullLogger, /*canUseEvents*/ false);
|
const session = createSession(host, typingsInstaller);
|
||||||
|
|
||||||
openFilesForSession([moduleFile1, file1Consumer1], session);
|
openFilesForSession([moduleFile1, file1Consumer1], session);
|
||||||
sendAffectedFileRequestAndCheckResult(session, moduleFile1FileListRequest, [{ projectFileName: configFile.path, files: [moduleFile1, file1Consumer1, file1Consumer1Consumer1] }]);
|
sendAffectedFileRequestAndCheckResult(session, moduleFile1FileListRequest, [{ projectFileName: configFile.path, files: [moduleFile1, file1Consumer1, file1Consumer1Consumer1] }]);
|
||||||
|
@ -400,7 +414,7 @@ namespace ts.projectSystem {
|
||||||
};
|
};
|
||||||
const host = createServerHost([file1, file2, configFile]);
|
const host = createServerHost([file1, file2, configFile]);
|
||||||
const typingsInstaller = createTestTypingsInstaller(host);
|
const typingsInstaller = createTestTypingsInstaller(host);
|
||||||
const session = new server.Session(host, nullCancellationToken, /*useSingleInferredProject*/ false, typingsInstaller, Utils.byteLength, process.hrtime, nullLogger, /*canUseEvents*/ false);
|
const session = createSession(host, typingsInstaller);
|
||||||
|
|
||||||
openFilesForSession([file1, file2], session);
|
openFilesForSession([file1, file2], session);
|
||||||
const file1AffectedListRequest = makeSessionRequest<server.protocol.FileRequestArgs>(CommandNames.CompileOnSaveAffectedFileList, { file: file1.path });
|
const file1AffectedListRequest = makeSessionRequest<server.protocol.FileRequestArgs>(CommandNames.CompileOnSaveAffectedFileList, { file: file1.path });
|
||||||
|
@ -513,7 +527,7 @@ namespace ts.projectSystem {
|
||||||
};
|
};
|
||||||
const host = createServerHost([file1, file2, configFile, libFile], { newLine: "\r\n" });
|
const host = createServerHost([file1, file2, configFile, libFile], { newLine: "\r\n" });
|
||||||
const typingsInstaller = createTestTypingsInstaller(host);
|
const typingsInstaller = createTestTypingsInstaller(host);
|
||||||
const session = new server.Session(host, nullCancellationToken, /*useSingleInferredProject*/ false, typingsInstaller, Utils.byteLength, process.hrtime, nullLogger, /*canUseEvents*/ false);
|
const session = createSession(host, typingsInstaller);
|
||||||
|
|
||||||
openFilesForSession([file1, file2], session);
|
openFilesForSession([file1, file2], session);
|
||||||
const compileFileRequest = makeSessionRequest<server.protocol.CompileOnSaveEmitFileRequestArgs>(CommandNames.CompileOnSaveEmitFile, { file: file1.path, projectFileName: configFile.path });
|
const compileFileRequest = makeSessionRequest<server.protocol.CompileOnSaveEmitFileRequestArgs>(CommandNames.CompileOnSaveEmitFile, { file: file1.path, projectFileName: configFile.path });
|
||||||
|
|
|
@ -50,8 +50,22 @@ namespace ts.server {
|
||||||
let session: TestSession;
|
let session: TestSession;
|
||||||
let lastSent: protocol.Message;
|
let lastSent: protocol.Message;
|
||||||
|
|
||||||
|
function createSession(): TestSession {
|
||||||
|
const opts: server.SessionOptions = {
|
||||||
|
host: mockHost,
|
||||||
|
cancellationToken: nullCancellationToken,
|
||||||
|
useSingleInferredProject: false,
|
||||||
|
typingsInstaller: undefined,
|
||||||
|
byteLength: Utils.byteLength,
|
||||||
|
hrtime: process.hrtime,
|
||||||
|
logger: mockLogger,
|
||||||
|
canUseEvents: true
|
||||||
|
};
|
||||||
|
return new TestSession(opts);
|
||||||
|
}
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
session = new TestSession(mockHost, nullCancellationToken, /*useOneInferredProject*/ false, /*typingsInstaller*/ undefined, Utils.byteLength, process.hrtime, mockLogger, /*canUseEvents*/ true);
|
session = createSession();
|
||||||
session.send = (msg: protocol.Message) => {
|
session.send = (msg: protocol.Message) => {
|
||||||
lastSent = msg;
|
lastSent = msg;
|
||||||
};
|
};
|
||||||
|
@ -318,7 +332,16 @@ namespace ts.server {
|
||||||
lastSent: protocol.Message;
|
lastSent: protocol.Message;
|
||||||
customHandler = "testhandler";
|
customHandler = "testhandler";
|
||||||
constructor() {
|
constructor() {
|
||||||
super(mockHost, nullCancellationToken, /*useOneInferredProject*/ false, /*typingsInstaller*/ undefined, Utils.byteLength, process.hrtime, mockLogger, /*canUseEvents*/ true);
|
super({
|
||||||
|
host: mockHost,
|
||||||
|
cancellationToken: nullCancellationToken,
|
||||||
|
useSingleInferredProject: false,
|
||||||
|
typingsInstaller: undefined,
|
||||||
|
byteLength: Utils.byteLength,
|
||||||
|
hrtime: process.hrtime,
|
||||||
|
logger: mockLogger,
|
||||||
|
canUseEvents: true
|
||||||
|
});
|
||||||
this.addProtocolHandler(this.customHandler, () => {
|
this.addProtocolHandler(this.customHandler, () => {
|
||||||
return { response: undefined, responseRequired: true };
|
return { response: undefined, responseRequired: true };
|
||||||
});
|
});
|
||||||
|
@ -376,7 +399,16 @@ namespace ts.server {
|
||||||
class InProcSession extends Session {
|
class InProcSession extends Session {
|
||||||
private queue: protocol.Request[] = [];
|
private queue: protocol.Request[] = [];
|
||||||
constructor(private client: InProcClient) {
|
constructor(private client: InProcClient) {
|
||||||
super(mockHost, nullCancellationToken, /*useOneInferredProject*/ false, /*typingsInstaller*/ undefined, Utils.byteLength, process.hrtime, mockLogger, /*canUseEvents*/ true);
|
super({
|
||||||
|
host: mockHost,
|
||||||
|
cancellationToken: nullCancellationToken,
|
||||||
|
useSingleInferredProject: false,
|
||||||
|
typingsInstaller: undefined,
|
||||||
|
byteLength: Utils.byteLength,
|
||||||
|
hrtime: process.hrtime,
|
||||||
|
logger: mockLogger,
|
||||||
|
canUseEvents: true
|
||||||
|
});
|
||||||
this.addProtocolHandler("echo", (req: protocol.Request) => ({
|
this.addProtocolHandler("echo", (req: protocol.Request) => ({
|
||||||
response: req.arguments,
|
response: req.arguments,
|
||||||
responseRequired: true
|
responseRequired: true
|
||||||
|
|
|
@ -190,7 +190,19 @@ namespace ts.projectSystem {
|
||||||
if (typingsInstaller === undefined) {
|
if (typingsInstaller === undefined) {
|
||||||
typingsInstaller = new TestTypingsInstaller("/a/data/", /*throttleLimit*/5, host);
|
typingsInstaller = new TestTypingsInstaller("/a/data/", /*throttleLimit*/5, host);
|
||||||
}
|
}
|
||||||
return new TestSession(host, cancellationToken || server.nullCancellationToken, /*useSingleInferredProject*/ false, typingsInstaller, Utils.byteLength, process.hrtime, nullLogger, /*canUseEvents*/ projectServiceEventHandler !== undefined, projectServiceEventHandler, throttleWaitMilliseconds);
|
const opts: server.SessionOptions = {
|
||||||
|
host,
|
||||||
|
cancellationToken: cancellationToken || server.nullCancellationToken,
|
||||||
|
useSingleInferredProject: false,
|
||||||
|
typingsInstaller,
|
||||||
|
byteLength: Utils.byteLength,
|
||||||
|
hrtime: process.hrtime,
|
||||||
|
logger: nullLogger,
|
||||||
|
canUseEvents: projectServiceEventHandler !== undefined,
|
||||||
|
eventHandler: projectServiceEventHandler,
|
||||||
|
throttleWaitMilliseconds
|
||||||
|
};
|
||||||
|
return new TestSession(opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CreateProjectServiceParameters {
|
export interface CreateProjectServiceParameters {
|
||||||
|
@ -205,7 +217,9 @@ namespace ts.projectSystem {
|
||||||
export class TestProjectService extends server.ProjectService {
|
export class TestProjectService extends server.ProjectService {
|
||||||
constructor(host: server.ServerHost, logger: server.Logger, cancellationToken: HostCancellationToken, useSingleInferredProject: boolean,
|
constructor(host: server.ServerHost, logger: server.Logger, cancellationToken: HostCancellationToken, useSingleInferredProject: boolean,
|
||||||
typingsInstaller: server.ITypingsInstaller, eventHandler: server.ProjectServiceEventHandler) {
|
typingsInstaller: server.ITypingsInstaller, eventHandler: server.ProjectServiceEventHandler) {
|
||||||
super(host, logger, cancellationToken, useSingleInferredProject, typingsInstaller, eventHandler);
|
super({
|
||||||
|
host, logger, cancellationToken, useSingleInferredProject, typingsInstaller, eventHandler
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
checkNumberOfProjects(count: { inferredProjects?: number, configuredProjects?: number, externalProjects?: number }) {
|
checkNumberOfProjects(count: { inferredProjects?: number, configuredProjects?: number, externalProjects?: number }) {
|
||||||
|
|
|
@ -273,6 +273,18 @@ namespace ts.server {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ProjectServiceOptions {
|
||||||
|
host: ServerHost;
|
||||||
|
logger: Logger;
|
||||||
|
cancellationToken: HostCancellationToken;
|
||||||
|
useSingleInferredProject: boolean;
|
||||||
|
typingsInstaller: ITypingsInstaller;
|
||||||
|
eventHandler?: ProjectServiceEventHandler;
|
||||||
|
throttleWaitMilliseconds?: number;
|
||||||
|
globalPlugins?: string[];
|
||||||
|
pluginProbeLocations?: string[];
|
||||||
|
}
|
||||||
|
|
||||||
export class ProjectService {
|
export class ProjectService {
|
||||||
|
|
||||||
public readonly typingsCache: TypingsCache;
|
public readonly typingsCache: TypingsCache;
|
||||||
|
@ -320,19 +332,33 @@ namespace ts.server {
|
||||||
|
|
||||||
public lastDeletedFile: ScriptInfo;
|
public lastDeletedFile: ScriptInfo;
|
||||||
|
|
||||||
constructor(public readonly host: ServerHost,
|
public readonly host: ServerHost;
|
||||||
public readonly logger: Logger,
|
public readonly logger: Logger;
|
||||||
public readonly cancellationToken: HostCancellationToken,
|
public readonly cancellationToken: HostCancellationToken;
|
||||||
public readonly useSingleInferredProject: boolean,
|
public readonly useSingleInferredProject: boolean;
|
||||||
readonly typingsInstaller: ITypingsInstaller = nullTypingsInstaller,
|
public readonly typingsInstaller: ITypingsInstaller;
|
||||||
private readonly eventHandler?: ProjectServiceEventHandler,
|
public readonly throttleWaitMilliseconds?: number;
|
||||||
public readonly throttleWaitMilliseconds?: number) {
|
private readonly eventHandler?: ProjectServiceEventHandler;
|
||||||
|
|
||||||
Debug.assert(!!host.createHash, "'ServerHost.createHash' is required for ProjectService");
|
public readonly globalPlugins: ReadonlyArray<string>;
|
||||||
|
public readonly pluginProbeLocations: ReadonlyArray<string>;
|
||||||
|
|
||||||
this.toCanonicalFileName = createGetCanonicalFileName(host.useCaseSensitiveFileNames);
|
constructor(opts: ProjectServiceOptions) {
|
||||||
|
this.host = opts.host;
|
||||||
|
this.logger = opts.logger;
|
||||||
|
this.cancellationToken = opts.cancellationToken;
|
||||||
|
this.useSingleInferredProject = opts.useSingleInferredProject;
|
||||||
|
this.typingsInstaller = opts.typingsInstaller || nullTypingsInstaller;
|
||||||
|
this.throttleWaitMilliseconds = opts.throttleWaitMilliseconds;
|
||||||
|
this.eventHandler = opts.eventHandler;
|
||||||
|
this.globalPlugins = opts.globalPlugins || emptyArray;
|
||||||
|
this.pluginProbeLocations = opts.pluginProbeLocations || emptyArray;
|
||||||
|
|
||||||
|
Debug.assert(!!this.host.createHash, "'ServerHost.createHash' is required for ProjectService");
|
||||||
|
|
||||||
|
this.toCanonicalFileName = createGetCanonicalFileName(this.host.useCaseSensitiveFileNames);
|
||||||
this.directoryWatchers = new DirectoryWatchers(this);
|
this.directoryWatchers = new DirectoryWatchers(this);
|
||||||
this.throttledOperations = new ThrottledOperations(host);
|
this.throttledOperations = new ThrottledOperations(this.host);
|
||||||
|
|
||||||
this.typingsInstaller.attach(this);
|
this.typingsInstaller.attach(this);
|
||||||
|
|
||||||
|
@ -344,7 +370,7 @@ namespace ts.server {
|
||||||
extraFileExtensions: []
|
extraFileExtensions: []
|
||||||
};
|
};
|
||||||
|
|
||||||
this.documentRegistry = createDocumentRegistry(host.useCaseSensitiveFileNames, host.getCurrentDirectory());
|
this.documentRegistry = createDocumentRegistry(this.host.useCaseSensitiveFileNames, this.host.getCurrentDirectory());
|
||||||
}
|
}
|
||||||
|
|
||||||
/* @internal */
|
/* @internal */
|
||||||
|
|
|
@ -843,7 +843,7 @@ namespace ts.server {
|
||||||
/** Used for configured projects which may have multiple open roots */
|
/** Used for configured projects which may have multiple open roots */
|
||||||
openRefCount = 0;
|
openRefCount = 0;
|
||||||
|
|
||||||
constructor(private configFileName: NormalizedPath,
|
constructor(configFileName: NormalizedPath,
|
||||||
projectService: ProjectService,
|
projectService: ProjectService,
|
||||||
documentRegistry: ts.DocumentRegistry,
|
documentRegistry: ts.DocumentRegistry,
|
||||||
hasExplicitListOfFiles: boolean,
|
hasExplicitListOfFiles: boolean,
|
||||||
|
@ -863,9 +863,6 @@ namespace ts.server {
|
||||||
enablePlugins() {
|
enablePlugins() {
|
||||||
const host = this.projectService.host;
|
const host = this.projectService.host;
|
||||||
const options = this.getCompilerOptions();
|
const options = this.getCompilerOptions();
|
||||||
const log = (message: string) => {
|
|
||||||
this.projectService.logger.info(message);
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!(options.plugins && options.plugins.length)) {
|
if (!(options.plugins && options.plugins.length)) {
|
||||||
this.projectService.logger.info("No plugins exist");
|
this.projectService.logger.info("No plugins exist");
|
||||||
|
@ -878,13 +875,34 @@ namespace ts.server {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Search our peer node_modules, then any globally-specified probe paths
|
||||||
|
// ../../.. to walk from X/node_modules/typescript/lib/tsserver.js to X/node_modules/
|
||||||
|
const searchPaths = [combinePaths(host.getExecutingFilePath(), "../../.."), ...this.projectService.pluginProbeLocations];
|
||||||
|
|
||||||
|
// Enable tsconfig-specified plugins
|
||||||
for (const pluginConfigEntry of options.plugins) {
|
for (const pluginConfigEntry of options.plugins) {
|
||||||
const searchPath = getDirectoryPath(this.configFileName);
|
this.enablePlugin(pluginConfigEntry, searchPaths);
|
||||||
const resolvedModule = <PluginModuleFactory>Project.resolveModule(pluginConfigEntry.name, searchPath, host, log);
|
}
|
||||||
|
// Enable global plugins with synthetic configuration entries
|
||||||
|
for (const globalPluginName of this.projectService.globalPlugins) {
|
||||||
|
// Provide global: true so plugins can detect why they can't find their config
|
||||||
|
this.enablePlugin({ name: globalPluginName, global: true } as PluginImport, searchPaths);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private enablePlugin(pluginConfigEntry: PluginImport, searchPaths: string[]) {
|
||||||
|
const log = (message: string) => {
|
||||||
|
this.projectService.logger.info(message);
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const searchPath of searchPaths) {
|
||||||
|
const resolvedModule = <PluginModuleFactory>Project.resolveModule(pluginConfigEntry.name, searchPath, this.projectService.host, log);
|
||||||
if (resolvedModule) {
|
if (resolvedModule) {
|
||||||
this.enableProxy(resolvedModule, pluginConfigEntry);
|
this.enableProxy(resolvedModule, pluginConfigEntry);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
this.projectService.logger.info(`Couldn't find ${pluginConfigEntry.name} anywhere in paths: ${searchPaths.join(",")}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
private enableProxy(pluginModuleFactory: PluginModuleFactory, configEntry: PluginImport) {
|
private enableProxy(pluginModuleFactory: PluginModuleFactory, configEntry: PluginImport) {
|
||||||
|
|
|
@ -3,6 +3,20 @@
|
||||||
/// <reference path="session.ts" />
|
/// <reference path="session.ts" />
|
||||||
|
|
||||||
namespace ts.server {
|
namespace ts.server {
|
||||||
|
interface IOSessionOptions {
|
||||||
|
host: ServerHost;
|
||||||
|
cancellationToken: ServerCancellationToken;
|
||||||
|
canUseEvents: boolean;
|
||||||
|
installerEventPort: number;
|
||||||
|
useSingleInferredProject: boolean;
|
||||||
|
disableAutomaticTypingAcquisition: boolean;
|
||||||
|
globalTypingsCacheLocation: string;
|
||||||
|
logger: Logger;
|
||||||
|
typingSafeListLocation: string;
|
||||||
|
telemetryEnabled: boolean;
|
||||||
|
globalPlugins: string[];
|
||||||
|
pluginProbeLocations: string[];
|
||||||
|
}
|
||||||
|
|
||||||
const net: {
|
const net: {
|
||||||
connect(options: { port: number }, onConnect?: () => void): NodeSocket
|
connect(options: { port: number }, onConnect?: () => void): NodeSocket
|
||||||
|
@ -373,34 +387,25 @@ namespace ts.server {
|
||||||
}
|
}
|
||||||
|
|
||||||
class IOSession extends Session {
|
class IOSession extends Session {
|
||||||
constructor(
|
constructor(options: IOSessionOptions) {
|
||||||
host: ServerHost,
|
const { host, installerEventPort, globalTypingsCacheLocation, typingSafeListLocation, canUseEvents } = options;
|
||||||
cancellationToken: ServerCancellationToken,
|
const typingsInstaller = disableAutomaticTypingAcquisition
|
||||||
installerEventPort: number,
|
? undefined
|
||||||
canUseEvents: boolean,
|
: new NodeTypingsInstaller(telemetryEnabled, logger, host, installerEventPort, globalTypingsCacheLocation, typingSafeListLocation, host.newLine);
|
||||||
useSingleInferredProject: boolean,
|
|
||||||
disableAutomaticTypingAcquisition: boolean,
|
|
||||||
globalTypingsCacheLocation: string,
|
|
||||||
typingSafeListLocation: string,
|
|
||||||
telemetryEnabled: boolean,
|
|
||||||
logger: server.Logger) {
|
|
||||||
const typingsInstaller = disableAutomaticTypingAcquisition
|
|
||||||
? undefined
|
|
||||||
: new NodeTypingsInstaller(telemetryEnabled, logger, host, installerEventPort, globalTypingsCacheLocation, typingSafeListLocation, host.newLine);
|
|
||||||
|
|
||||||
super(
|
super({
|
||||||
host,
|
host,
|
||||||
cancellationToken,
|
cancellationToken,
|
||||||
useSingleInferredProject,
|
useSingleInferredProject,
|
||||||
typingsInstaller || nullTypingsInstaller,
|
typingsInstaller: typingsInstaller || nullTypingsInstaller,
|
||||||
Buffer.byteLength,
|
byteLength: Buffer.byteLength,
|
||||||
process.hrtime,
|
hrtime: process.hrtime,
|
||||||
logger,
|
logger,
|
||||||
canUseEvents);
|
canUseEvents});
|
||||||
|
|
||||||
if (telemetryEnabled && typingsInstaller) {
|
if (telemetryEnabled && typingsInstaller) {
|
||||||
typingsInstaller.setTelemetrySender(this);
|
typingsInstaller.setTelemetrySender(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exit() {
|
exit() {
|
||||||
|
@ -735,21 +740,29 @@ namespace ts.server {
|
||||||
|
|
||||||
const typingSafeListLocation = findArgument("--typingSafeListLocation");
|
const typingSafeListLocation = findArgument("--typingSafeListLocation");
|
||||||
|
|
||||||
|
const globalPlugins = (findArgument("--globalPlugins") || "").split(",");
|
||||||
|
const pluginProbeLocations = (findArgument("--pluginProbeLocations") || "").split(",");
|
||||||
|
|
||||||
const useSingleInferredProject = hasArgument("--useSingleInferredProject");
|
const useSingleInferredProject = hasArgument("--useSingleInferredProject");
|
||||||
const disableAutomaticTypingAcquisition = hasArgument("--disableAutomaticTypingAcquisition");
|
const disableAutomaticTypingAcquisition = hasArgument("--disableAutomaticTypingAcquisition");
|
||||||
const telemetryEnabled = hasArgument(Arguments.EnableTelemetry);
|
const telemetryEnabled = hasArgument(Arguments.EnableTelemetry);
|
||||||
|
|
||||||
const ioSession = new IOSession(
|
const options: IOSessionOptions = {
|
||||||
sys,
|
host: sys,
|
||||||
cancellationToken,
|
cancellationToken,
|
||||||
eventPort,
|
installerEventPort: eventPort,
|
||||||
/*canUseEvents*/ eventPort === undefined,
|
canUseEvents: eventPort === undefined,
|
||||||
useSingleInferredProject,
|
useSingleInferredProject,
|
||||||
disableAutomaticTypingAcquisition,
|
disableAutomaticTypingAcquisition,
|
||||||
getGlobalTypingsCacheLocation(),
|
globalTypingsCacheLocation: getGlobalTypingsCacheLocation(),
|
||||||
typingSafeListLocation,
|
typingSafeListLocation,
|
||||||
telemetryEnabled,
|
telemetryEnabled,
|
||||||
logger);
|
logger,
|
||||||
|
globalPlugins,
|
||||||
|
pluginProbeLocations
|
||||||
|
};
|
||||||
|
|
||||||
|
const ioSession = new IOSession(options);
|
||||||
process.on("uncaughtException", function (err: Error) {
|
process.on("uncaughtException", function (err: Error) {
|
||||||
ioSession.logError(err, "unknown");
|
ioSession.logError(err, "unknown");
|
||||||
});
|
});
|
||||||
|
|
|
@ -319,6 +319,22 @@ namespace ts.server {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface SessionOptions {
|
||||||
|
host: ServerHost;
|
||||||
|
cancellationToken: ServerCancellationToken;
|
||||||
|
useSingleInferredProject: boolean;
|
||||||
|
typingsInstaller: ITypingsInstaller;
|
||||||
|
byteLength: (buf: string, encoding?: string) => number;
|
||||||
|
hrtime: (start?: number[]) => number[];
|
||||||
|
logger: Logger;
|
||||||
|
canUseEvents: boolean;
|
||||||
|
eventHandler?: ProjectServiceEventHandler;
|
||||||
|
throttleWaitMilliseconds?: number;
|
||||||
|
|
||||||
|
globalPlugins?: string[];
|
||||||
|
pluginProbeLocations?: string[];
|
||||||
|
}
|
||||||
|
|
||||||
export class Session implements EventSender {
|
export class Session implements EventSender {
|
||||||
private readonly gcTimer: GcTimer;
|
private readonly gcTimer: GcTimer;
|
||||||
protected projectService: ProjectService;
|
protected projectService: ProjectService;
|
||||||
|
@ -327,22 +343,29 @@ namespace ts.server {
|
||||||
private currentRequestId: number;
|
private currentRequestId: number;
|
||||||
private errorCheck: MultistepOperation;
|
private errorCheck: MultistepOperation;
|
||||||
|
|
||||||
private eventHander: ProjectServiceEventHandler;
|
private eventHandler: ProjectServiceEventHandler;
|
||||||
|
|
||||||
constructor(
|
private host: ServerHost;
|
||||||
private host: ServerHost,
|
private readonly cancellationToken: ServerCancellationToken;
|
||||||
private readonly cancellationToken: ServerCancellationToken,
|
protected readonly typingsInstaller: ITypingsInstaller;
|
||||||
useSingleInferredProject: boolean,
|
private byteLength: (buf: string, encoding?: string) => number;
|
||||||
protected readonly typingsInstaller: ITypingsInstaller,
|
private hrtime: (start?: number[]) => number[];
|
||||||
private byteLength: (buf: string, encoding?: string) => number,
|
protected logger: Logger;
|
||||||
private hrtime: (start?: number[]) => number[],
|
private canUseEvents: boolean;
|
||||||
protected logger: Logger,
|
|
||||||
protected readonly canUseEvents: boolean,
|
|
||||||
eventHandler?: ProjectServiceEventHandler,
|
|
||||||
private readonly throttleWaitMilliseconds?: number) {
|
|
||||||
|
|
||||||
this.eventHander = canUseEvents
|
constructor(opts: SessionOptions) {
|
||||||
? eventHandler || (event => this.defaultEventHandler(event))
|
this.host = opts.host;
|
||||||
|
this.cancellationToken = opts.cancellationToken;
|
||||||
|
this.typingsInstaller = opts.typingsInstaller;
|
||||||
|
this.byteLength = opts.byteLength;
|
||||||
|
this.hrtime = opts.hrtime;
|
||||||
|
this.logger = opts.logger;
|
||||||
|
this.canUseEvents = opts.canUseEvents;
|
||||||
|
|
||||||
|
const { throttleWaitMilliseconds } = opts;
|
||||||
|
|
||||||
|
this.eventHandler = this.canUseEvents
|
||||||
|
? opts.eventHandler || (event => this.defaultEventHandler(event))
|
||||||
: undefined;
|
: undefined;
|
||||||
|
|
||||||
const multistepOperationHost: MultistepOperationHost = {
|
const multistepOperationHost: MultistepOperationHost = {
|
||||||
|
@ -351,11 +374,22 @@ namespace ts.server {
|
||||||
getServerHost: () => this.host,
|
getServerHost: () => this.host,
|
||||||
logError: (err, cmd) => this.logError(err, cmd),
|
logError: (err, cmd) => this.logError(err, cmd),
|
||||||
sendRequestCompletedEvent: requestId => this.sendRequestCompletedEvent(requestId),
|
sendRequestCompletedEvent: requestId => this.sendRequestCompletedEvent(requestId),
|
||||||
isCancellationRequested: () => cancellationToken.isCancellationRequested()
|
isCancellationRequested: () => this.cancellationToken.isCancellationRequested()
|
||||||
};
|
};
|
||||||
this.errorCheck = new MultistepOperation(multistepOperationHost);
|
this.errorCheck = new MultistepOperation(multistepOperationHost);
|
||||||
this.projectService = new ProjectService(host, logger, cancellationToken, useSingleInferredProject, typingsInstaller, this.eventHander, this.throttleWaitMilliseconds);
|
const settings: ProjectServiceOptions = {
|
||||||
this.gcTimer = new GcTimer(host, /*delay*/ 7000, logger);
|
host: this.host,
|
||||||
|
logger: this.logger,
|
||||||
|
cancellationToken: this.cancellationToken,
|
||||||
|
useSingleInferredProject: opts.useSingleInferredProject,
|
||||||
|
typingsInstaller: this.typingsInstaller,
|
||||||
|
throttleWaitMilliseconds,
|
||||||
|
eventHandler: this.eventHandler,
|
||||||
|
globalPlugins: opts.globalPlugins,
|
||||||
|
pluginProbeLocations: opts.pluginProbeLocations
|
||||||
|
};
|
||||||
|
this.projectService = new ProjectService(settings);
|
||||||
|
this.gcTimer = new GcTimer(this.host, /*delay*/ 7000, this.logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
private sendRequestCompletedEvent(requestId: number): void {
|
private sendRequestCompletedEvent(requestId: number): void {
|
||||||
|
@ -947,8 +981,8 @@ namespace ts.server {
|
||||||
*/
|
*/
|
||||||
private openClientFile(fileName: NormalizedPath, fileContent?: string, scriptKind?: ScriptKind) {
|
private openClientFile(fileName: NormalizedPath, fileContent?: string, scriptKind?: ScriptKind) {
|
||||||
const { configFileName, configFileErrors } = this.projectService.openClientFileWithNormalizedPath(fileName, fileContent, scriptKind);
|
const { configFileName, configFileErrors } = this.projectService.openClientFileWithNormalizedPath(fileName, fileContent, scriptKind);
|
||||||
if (this.eventHander) {
|
if (this.eventHandler) {
|
||||||
this.eventHander({
|
this.eventHandler({
|
||||||
eventName: "configFileDiag",
|
eventName: "configFileDiag",
|
||||||
data: { triggerFile: fileName, configFileName, diagnostics: configFileErrors || [] }
|
data: { triggerFile: fileName, configFileName, diagnostics: configFileErrors || [] }
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue