Fix merge

This commit is contained in:
Ryan Cavanaugh 2017-04-13 16:16:57 -07:00
parent d129199f41
commit 3cc379c3c0
9 changed files with 258 additions and 95 deletions

View file

@ -818,13 +818,17 @@ namespace Harness.LanguageService {
// This host is just a proxy for the clientHost, it uses the client
// host to answer server queries about files on disk
const serverHost = new SessionServerHost(clientHost);
const server = new ts.server.Session(serverHost,
ts.server.nullCancellationToken,
/*useOneInferredProject*/ false,
/*typingsInstaller*/ undefined,
Utils.byteLength,
process.hrtime, serverHost,
/*canUseEvents*/ true);
const opts: ts.server.SessionOptions = {
host: serverHost,
cancellationToken: ts.server.nullCancellationToken,
useSingleInferredProject: false,
typingsInstaller: undefined,
byteLength: Utils.byteLength,
hrtime: process.hrtime,
logger: serverHost,
canUseEvents: true
};
const server = new ts.server.Session(opts);
// Fake the connection between the client and the server
serverHost.writeMessage = client.onMessage.bind(client);

View file

@ -64,8 +64,16 @@ namespace ts {
getLogFileName: (): string => undefined
};
const projectService = new server.ProjectService(serverHost, logger, { isCancellationRequested: () => false }, /*useOneInferredProject*/ false, /*typingsInstaller*/ undefined);
const rootScriptInfo = projectService.getOrCreateScriptInfo(rootFile, /*openedByClient*/ true, /*containingProject*/ undefined);
const svcOpts: server.ProjectServiceOptions = {
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);
project.setCompilerOptions({ module: ts.ModuleKind.AMD } );
return {

View file

@ -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", () => {
let moduleFile1: 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", () => {
const host = createServerHost([moduleFile1, file1Consumer1, file1Consumer2, globalFile3, moduleFile2, configFile, libFile]);
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);
@ -138,7 +152,7 @@ namespace ts.projectSystem {
it("should be up-to-date with the reference map changes", () => {
const host = createServerHost([moduleFile1, file1Consumer1, file1Consumer2, globalFile3, moduleFile2, configFile, libFile]);
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);
@ -185,7 +199,7 @@ namespace ts.projectSystem {
it("should be up-to-date with changes made in non-open files", () => {
const host = createServerHost([moduleFile1, file1Consumer1, file1Consumer2, globalFile3, moduleFile2, configFile, libFile]);
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);
@ -203,7 +217,7 @@ namespace ts.projectSystem {
it("should be up-to-date with deleted files", () => {
const host = createServerHost([moduleFile1, file1Consumer1, file1Consumer2, globalFile3, moduleFile2, configFile, libFile]);
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);
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", () => {
const host = createServerHost([moduleFile1, file1Consumer1, file1Consumer2, globalFile3, moduleFile2, configFile, libFile]);
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);
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 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);
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", () => {
const host = createServerHost([moduleFile1, file1Consumer1, file1Consumer2, globalFile3, moduleFile2, configFile, libFile]);
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);
const changeGlobalFile3ShapeRequest = makeSessionRequest<server.protocol.ChangeRequestArgs>(CommandNames.Change, {
@ -298,7 +312,7 @@ namespace ts.projectSystem {
const host = createServerHost([moduleFile1, file1Consumer1, file1Consumer2, configFile, libFile]);
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);
sendAffectedFileRequestAndCheckResult(session, moduleFile1FileListRequest, []);
});
@ -316,7 +330,7 @@ namespace ts.projectSystem {
const host = createServerHost([moduleFile1, file1Consumer1, configFile, libFile]);
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);
const file1ChangeShapeRequest = makeSessionRequest<server.protocol.ChangeRequestArgs>(CommandNames.Change, {
@ -345,7 +359,7 @@ namespace ts.projectSystem {
const host = createServerHost([moduleFile1, file1Consumer1, configFile, libFile]);
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);
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 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);
sendAffectedFileRequestAndCheckResult(session, moduleFile1FileListRequest, [{ projectFileName: configFile.path, files: [moduleFile1, file1Consumer1, file1Consumer1Consumer1] }]);
@ -400,7 +414,7 @@ namespace ts.projectSystem {
};
const host = createServerHost([file1, file2, configFile]);
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);
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 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);
const compileFileRequest = makeSessionRequest<server.protocol.CompileOnSaveEmitFileRequestArgs>(CommandNames.CompileOnSaveEmitFile, { file: file1.path, projectFileName: configFile.path });

View file

@ -50,8 +50,22 @@ namespace ts.server {
let session: TestSession;
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(() => {
session = new TestSession(mockHost, nullCancellationToken, /*useOneInferredProject*/ false, /*typingsInstaller*/ undefined, Utils.byteLength, process.hrtime, mockLogger, /*canUseEvents*/ true);
session = createSession();
session.send = (msg: protocol.Message) => {
lastSent = msg;
};
@ -318,7 +332,16 @@ namespace ts.server {
lastSent: protocol.Message;
customHandler = "testhandler";
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, () => {
return { response: undefined, responseRequired: true };
});
@ -376,7 +399,16 @@ namespace ts.server {
class InProcSession extends Session {
private queue: protocol.Request[] = [];
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) => ({
response: req.arguments,
responseRequired: true

View file

@ -190,7 +190,19 @@ namespace ts.projectSystem {
if (typingsInstaller === undefined) {
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 {
@ -205,7 +217,9 @@ 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) {
super(host, logger, cancellationToken, useSingleInferredProject, typingsInstaller, eventHandler);
super({
host, logger, cancellationToken, useSingleInferredProject, typingsInstaller, eventHandler
});
}
checkNumberOfProjects(count: { inferredProjects?: number, configuredProjects?: number, externalProjects?: number }) {

View file

@ -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 {
public readonly typingsCache: TypingsCache;
@ -320,19 +332,33 @@ namespace ts.server {
public lastDeletedFile: ScriptInfo;
constructor(public readonly host: ServerHost,
public readonly logger: Logger,
public readonly cancellationToken: HostCancellationToken,
public readonly useSingleInferredProject: boolean,
readonly typingsInstaller: ITypingsInstaller = nullTypingsInstaller,
private readonly eventHandler?: ProjectServiceEventHandler,
public readonly throttleWaitMilliseconds?: number) {
public readonly host: ServerHost;
public readonly logger: Logger;
public readonly cancellationToken: HostCancellationToken;
public readonly useSingleInferredProject: boolean;
public readonly typingsInstaller: ITypingsInstaller;
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.throttledOperations = new ThrottledOperations(host);
this.throttledOperations = new ThrottledOperations(this.host);
this.typingsInstaller.attach(this);
@ -344,7 +370,7 @@ namespace ts.server {
extraFileExtensions: []
};
this.documentRegistry = createDocumentRegistry(host.useCaseSensitiveFileNames, host.getCurrentDirectory());
this.documentRegistry = createDocumentRegistry(this.host.useCaseSensitiveFileNames, this.host.getCurrentDirectory());
}
/* @internal */

View file

@ -843,7 +843,7 @@ namespace ts.server {
/** Used for configured projects which may have multiple open roots */
openRefCount = 0;
constructor(private configFileName: NormalizedPath,
constructor(configFileName: NormalizedPath,
projectService: ProjectService,
documentRegistry: ts.DocumentRegistry,
hasExplicitListOfFiles: boolean,
@ -863,9 +863,6 @@ namespace ts.server {
enablePlugins() {
const host = this.projectService.host;
const options = this.getCompilerOptions();
const log = (message: string) => {
this.projectService.logger.info(message);
};
if (!(options.plugins && options.plugins.length)) {
this.projectService.logger.info("No plugins exist");
@ -878,13 +875,34 @@ namespace ts.server {
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) {
const searchPath = getDirectoryPath(this.configFileName);
const resolvedModule = <PluginModuleFactory>Project.resolveModule(pluginConfigEntry.name, searchPath, host, log);
this.enablePlugin(pluginConfigEntry, searchPaths);
}
// 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) {
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) {

View file

@ -3,6 +3,20 @@
/// <reference path="session.ts" />
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: {
connect(options: { port: number }, onConnect?: () => void): NodeSocket
@ -373,34 +387,25 @@ namespace ts.server {
}
class IOSession extends Session {
constructor(
host: ServerHost,
cancellationToken: ServerCancellationToken,
installerEventPort: number,
canUseEvents: boolean,
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);
constructor(options: IOSessionOptions) {
const { host, installerEventPort, globalTypingsCacheLocation, typingSafeListLocation, canUseEvents } = options;
const typingsInstaller = disableAutomaticTypingAcquisition
? undefined
: new NodeTypingsInstaller(telemetryEnabled, logger, host, installerEventPort, globalTypingsCacheLocation, typingSafeListLocation, host.newLine);
super(
host,
cancellationToken,
useSingleInferredProject,
typingsInstaller || nullTypingsInstaller,
Buffer.byteLength,
process.hrtime,
logger,
canUseEvents);
super({
host,
cancellationToken,
useSingleInferredProject,
typingsInstaller: typingsInstaller || nullTypingsInstaller,
byteLength: Buffer.byteLength,
hrtime: process.hrtime,
logger,
canUseEvents});
if (telemetryEnabled && typingsInstaller) {
typingsInstaller.setTelemetrySender(this);
}
if (telemetryEnabled && typingsInstaller) {
typingsInstaller.setTelemetrySender(this);
}
}
exit() {
@ -735,21 +740,29 @@ namespace ts.server {
const typingSafeListLocation = findArgument("--typingSafeListLocation");
const globalPlugins = (findArgument("--globalPlugins") || "").split(",");
const pluginProbeLocations = (findArgument("--pluginProbeLocations") || "").split(",");
const useSingleInferredProject = hasArgument("--useSingleInferredProject");
const disableAutomaticTypingAcquisition = hasArgument("--disableAutomaticTypingAcquisition");
const telemetryEnabled = hasArgument(Arguments.EnableTelemetry);
const ioSession = new IOSession(
sys,
const options: IOSessionOptions = {
host: sys,
cancellationToken,
eventPort,
/*canUseEvents*/ eventPort === undefined,
installerEventPort: eventPort,
canUseEvents: eventPort === undefined,
useSingleInferredProject,
disableAutomaticTypingAcquisition,
getGlobalTypingsCacheLocation(),
globalTypingsCacheLocation: getGlobalTypingsCacheLocation(),
typingSafeListLocation,
telemetryEnabled,
logger);
logger,
globalPlugins,
pluginProbeLocations
};
const ioSession = new IOSession(options);
process.on("uncaughtException", function (err: Error) {
ioSession.logError(err, "unknown");
});

View file

@ -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 {
private readonly gcTimer: GcTimer;
protected projectService: ProjectService;
@ -327,22 +343,29 @@ namespace ts.server {
private currentRequestId: number;
private errorCheck: MultistepOperation;
private eventHander: ProjectServiceEventHandler;
private eventHandler: ProjectServiceEventHandler;
constructor(
private host: ServerHost,
private readonly cancellationToken: ServerCancellationToken,
useSingleInferredProject: boolean,
protected readonly typingsInstaller: ITypingsInstaller,
private byteLength: (buf: string, encoding?: string) => number,
private hrtime: (start?: number[]) => number[],
protected logger: Logger,
protected readonly canUseEvents: boolean,
eventHandler?: ProjectServiceEventHandler,
private readonly throttleWaitMilliseconds?: number) {
private host: ServerHost;
private readonly cancellationToken: ServerCancellationToken;
protected readonly typingsInstaller: ITypingsInstaller;
private byteLength: (buf: string, encoding?: string) => number;
private hrtime: (start?: number[]) => number[];
protected logger: Logger;
private canUseEvents: boolean;
this.eventHander = canUseEvents
? eventHandler || (event => this.defaultEventHandler(event))
constructor(opts: SessionOptions) {
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;
const multistepOperationHost: MultistepOperationHost = {
@ -351,11 +374,22 @@ namespace ts.server {
getServerHost: () => this.host,
logError: (err, cmd) => this.logError(err, cmd),
sendRequestCompletedEvent: requestId => this.sendRequestCompletedEvent(requestId),
isCancellationRequested: () => cancellationToken.isCancellationRequested()
isCancellationRequested: () => this.cancellationToken.isCancellationRequested()
};
this.errorCheck = new MultistepOperation(multistepOperationHost);
this.projectService = new ProjectService(host, logger, cancellationToken, useSingleInferredProject, typingsInstaller, this.eventHander, this.throttleWaitMilliseconds);
this.gcTimer = new GcTimer(host, /*delay*/ 7000, logger);
const settings: ProjectServiceOptions = {
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 {
@ -947,8 +981,8 @@ namespace ts.server {
*/
private openClientFile(fileName: NormalizedPath, fileContent?: string, scriptKind?: ScriptKind) {
const { configFileName, configFileErrors } = this.projectService.openClientFileWithNormalizedPath(fileName, fileContent, scriptKind);
if (this.eventHander) {
this.eventHander({
if (this.eventHandler) {
this.eventHandler({
eventName: "configFileDiag",
data: { triggerFile: fileName, configFileName, diagnostics: configFileErrors || [] }
});