diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index ba0a80890fe..386aa262964 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -305,6 +305,7 @@ namespace ts.server { useInferredProjectPerProjectRoot: boolean; typingsInstaller: ITypingsInstaller; eventHandler?: ProjectServiceEventHandler; + suppressDiagnosticEvents?: boolean; throttleWaitMilliseconds?: number; globalPlugins?: ReadonlyArray; pluginProbeLocations?: ReadonlyArray; @@ -392,6 +393,7 @@ namespace ts.server { public readonly typingsInstaller: ITypingsInstaller; public readonly throttleWaitMilliseconds?: number; private readonly eventHandler?: ProjectServiceEventHandler; + private readonly suppressDiagnosticEvents?: boolean; public readonly globalPlugins: ReadonlyArray; public readonly pluginProbeLocations: ReadonlyArray; @@ -413,6 +415,7 @@ namespace ts.server { this.typingsInstaller = opts.typingsInstaller || nullTypingsInstaller; this.throttleWaitMilliseconds = opts.throttleWaitMilliseconds; this.eventHandler = opts.eventHandler; + this.suppressDiagnosticEvents = opts.suppressDiagnosticEvents; this.globalPlugins = opts.globalPlugins || emptyArray; this.pluginProbeLocations = opts.pluginProbeLocations || emptyArray; this.allowLocalPluginLoads = !!opts.allowLocalPluginLoads; @@ -1598,7 +1601,7 @@ namespace ts.server { } private sendConfigFileDiagEvent(project: ConfiguredProject, triggerFile: NormalizedPath) { - if (!this.eventHandler) { + if (!this.eventHandler || this.suppressDiagnosticEvents) { return; } diff --git a/src/server/server.ts b/src/server/server.ts index 8fb9bfb64bc..4141a36161f 100644 --- a/src/server/server.ts +++ b/src/server/server.ts @@ -512,6 +512,7 @@ namespace ts.server { hrtime: process.hrtime, logger, canUseEvents: true, + suppressDiagnosticEvents, globalPlugins, pluginProbeLocations, allowLocalPluginLoads, @@ -927,6 +928,7 @@ namespace ts.server { const useSingleInferredProject = hasArgument("--useSingleInferredProject"); const useInferredProjectPerProjectRoot = hasArgument("--useInferredProjectPerProjectRoot"); const disableAutomaticTypingAcquisition = hasArgument("--disableAutomaticTypingAcquisition"); + const suppressDiagnosticEvents = hasArgument("--suppressDiagnosticEvents"); const telemetryEnabled = hasArgument(Arguments.EnableTelemetry); logger.info(`Starting TS Server`); diff --git a/src/server/session.ts b/src/server/session.ts index 1999360e34b..4d9c296f6a9 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -295,6 +295,8 @@ namespace ts.server { */ canUseEvents: boolean; eventHandler?: ProjectServiceEventHandler; + /** Has no effect if eventHandler is also specified. */ + suppressDiagnosticEvents?: boolean; throttleWaitMilliseconds?: number; globalPlugins?: ReadonlyArray; @@ -318,6 +320,7 @@ namespace ts.server { protected logger: Logger; protected canUseEvents: boolean; + private suppressDiagnosticEvents?: boolean; private eventHandler: ProjectServiceEventHandler; constructor(opts: SessionOptions) { @@ -328,6 +331,7 @@ namespace ts.server { this.hrtime = opts.hrtime; this.logger = opts.logger; this.canUseEvents = opts.canUseEvents; + this.suppressDiagnosticEvents = opts.suppressDiagnosticEvents; const { throttleWaitMilliseconds } = opts; @@ -352,6 +356,7 @@ namespace ts.server { typingsInstaller: this.typingsInstaller, throttleWaitMilliseconds, eventHandler: this.eventHandler, + suppressDiagnosticEvents: this.suppressDiagnosticEvents, globalPlugins: opts.globalPlugins, pluginProbeLocations: opts.pluginProbeLocations, allowLocalPluginLoads: opts.allowLocalPluginLoads @@ -401,11 +406,12 @@ namespace ts.server { private projectsUpdatedInBackgroundEvent(openFiles: string[]): void { this.projectService.logger.info(`got projects updated in background, updating diagnostics for ${openFiles}`); if (openFiles.length) { - const checkList = this.createCheckList(openFiles); - - // For now only queue error checking for open files. We can change this to include non open files as well - this.errorCheck.startNew(next => this.updateErrorCheck(next, checkList, 100, /*requireOpen*/ true)); + if (!this.suppressDiagnosticEvents) { + const checkList = this.createCheckList(openFiles); + // For now only queue error checking for open files. We can change this to include non open files as well + this.errorCheck.startNew(next => this.updateErrorCheck(next, checkList, 100, /*requireOpen*/ true)); + } // Send project changed event this.event({ @@ -489,7 +495,10 @@ namespace ts.server { } } + /** It is the caller's responsibility to verify that `!this.suppressDiagnosticEvents`. */ private updateErrorCheck(next: NextStep, checkList: PendingErrorCheck[], ms: number, requireOpen = true) { + Debug.assert(!this.suppressDiagnosticEvents); // Caller's responsibility + const seq = this.changeSeq; const followMs = Math.min(ms, 200); @@ -1379,6 +1388,10 @@ namespace ts.server { } private getDiagnostics(next: NextStep, delay: number, fileNames: string[]): void { + if (this.suppressDiagnosticEvents) { + return; + } + const checkList = this.createCheckList(fileNames); if (checkList.length > 0) { this.updateErrorCheck(next, checkList, delay); @@ -1748,6 +1761,10 @@ namespace ts.server { } private getDiagnosticsForProject(next: NextStep, delay: number, fileName: string): void { + if (this.suppressDiagnosticEvents) { + return; + } + const { fileNames, languageServiceDisabled } = this.getProjectInfoWorker(fileName, /*projectFileName*/ undefined, /*needFileNameList*/ true, /*excludeConfigFiles*/ true); if (languageServiceDisabled) { return;