diff --git a/extensions/typescript-language-features/src/tsServer/server.ts b/extensions/typescript-language-features/src/tsServer/server.ts index 7faff5b6d71..0ac92ca7a42 100644 --- a/extensions/typescript-language-features/src/tsServer/server.ts +++ b/extensions/typescript-language-features/src/tsServer/server.ts @@ -379,75 +379,6 @@ class RequestRouter { } } - -const syntaxAlwaysCommands: ReadonlySet = new Set([ - 'navtree', - 'getOutliningSpans', - 'jsxClosingTag', - 'selectionRange', - 'format', - 'formatonkey', - 'docCommentTemplate', -]); - -export class SyntaxRoutingTsServer extends Disposable implements ITypeScriptServer { - - private readonly syntaxServer: ITypeScriptServer; - private readonly semanticServer: ITypeScriptServer; - private readonly router: RequestRouter; - - public constructor( - servers: { syntax: ITypeScriptServer, semantic: ITypeScriptServer }, - delegate: TsServerDelegate, - ) { - super(); - - this.syntaxServer = servers.syntax; - this.semanticServer = servers.semantic; - - this.router = new RequestRouter( - [ - { server: this.syntaxServer, canRun: (command) => syntaxAlwaysCommands.has(command) }, - { server: this.semanticServer, canRun: undefined /* gets all other commands */ } - ], - delegate); - - this._register(this.syntaxServer.onEvent(e => this._onEvent.fire(e))); - this._register(this.semanticServer.onEvent(e => this._onEvent.fire(e))); - - this._register(this.semanticServer.onExit(e => { - this._onExit.fire(e); - this.syntaxServer.kill(); - })); - this._register(this.semanticServer.onError(e => this._onError.fire(e))); - } - - private readonly _onEvent = this._register(new vscode.EventEmitter()); - public readonly onEvent = this._onEvent.event; - - private readonly _onExit = this._register(new vscode.EventEmitter()); - public readonly onExit = this._onExit.event; - - private readonly _onError = this._register(new vscode.EventEmitter()); - public readonly onError = this._onError.event; - - public get onReaderError() { return this.semanticServer.onReaderError; } - - public get tsServerLogFile() { return this.semanticServer.tsServerLogFile; } - - public kill(): void { - this.syntaxServer.kill(); - this.semanticServer.kill(); - } - - public executeImpl(command: keyof TypeScriptRequests, args: any, executeInfo: { isAsync: boolean, token?: vscode.CancellationToken, expectsResult: false, lowPriority?: boolean }): undefined; - public executeImpl(command: keyof TypeScriptRequests, args: any, executeInfo: { isAsync: boolean, token?: vscode.CancellationToken, expectsResult: boolean, lowPriority?: boolean }): Promise>; - public executeImpl(command: keyof TypeScriptRequests, args: any, executeInfo: { isAsync: boolean, token?: vscode.CancellationToken, expectsResult: boolean, lowPriority?: boolean }): Promise> | undefined { - return this.router.execute(command, args, executeInfo); - } -} - - export class GetErrRoutingTsServer extends Disposable implements ITypeScriptServer { private static readonly diagnosticEvents = new Set([ @@ -525,7 +456,20 @@ export class GetErrRoutingTsServer extends Disposable implements ITypeScriptServ } -export class ProjectLoadingRoutingSyntaxTsServer extends Disposable implements ITypeScriptServer { +export class SyntaxRoutingTsServer extends Disposable implements ITypeScriptServer { + + /** + * Commands that should always be run on the syntax server. + */ + private static readonly syntaxAlwaysCommands = new Set([ + 'navtree', + 'getOutliningSpans', + 'jsxClosingTag', + 'selectionRange', + 'format', + 'formatonkey', + 'docCommentTemplate', + ]); /** * Commands that should always be run on the semantic server. @@ -539,7 +483,7 @@ export class ProjectLoadingRoutingSyntaxTsServer extends Disposable implements I /** * Commands that can be run on the syntax server but would benefit from being upgraded to the semantic server. */ - private syntaxAllowedCommands = new Set([ + private static readonly syntaxAllowedCommands = new Set([ 'completions', 'completionEntryDetails', 'completionInfo', @@ -563,6 +507,7 @@ export class ProjectLoadingRoutingSyntaxTsServer extends Disposable implements I public constructor( servers: { syntax: ITypeScriptServer, semantic: ITypeScriptServer }, delegate: TsServerDelegate, + enableDynamicRouting: boolean, ) { super(); @@ -574,13 +519,13 @@ export class ProjectLoadingRoutingSyntaxTsServer extends Disposable implements I { server: this.syntaxServer, canRun: (command) => { - if (syntaxAlwaysCommands.has(command)) { + if (SyntaxRoutingTsServer.syntaxAlwaysCommands.has(command)) { return true; } - if (ProjectLoadingRoutingSyntaxTsServer.semanticCommands.has(command)) { + if (SyntaxRoutingTsServer.semanticCommands.has(command)) { return false; } - if (this.projectLoading && this.syntaxAllowedCommands.has(command)) { + if (enableDynamicRouting && this.projectLoading && SyntaxRoutingTsServer.syntaxAllowedCommands.has(command)) { return true; } return false; diff --git a/extensions/typescript-language-features/src/tsServer/spawner.ts b/extensions/typescript-language-features/src/tsServer/spawner.ts index 292e3d42f4b..dcf0ed5a627 100644 --- a/extensions/typescript-language-features/src/tsServer/spawner.ts +++ b/extensions/typescript-language-features/src/tsServer/spawner.ts @@ -9,7 +9,7 @@ import * as stream from 'stream'; import * as vscode from 'vscode'; import type * as Proto from '../protocol'; import API from '../utils/api'; -import { TsServerLogLevel, TypeScriptServiceConfiguration, SeparateSyntaxServerConfigration } from '../utils/configuration'; +import { SeparateSyntaxServerConfiguration, TsServerLogLevel, TypeScriptServiceConfiguration } from '../utils/configuration'; import * as electron from '../utils/electron'; import LogDirectoryProvider from '../utils/logDirectoryProvider'; import Logger from '../utils/logger'; @@ -18,7 +18,7 @@ import { PluginManager } from '../utils/plugins'; import { TelemetryReporter } from '../utils/telemetry'; import Tracer from '../utils/tracer'; import { TypeScriptVersion, TypeScriptVersionProvider } from '../utils/versionProvider'; -import { ITypeScriptServer, PipeRequestCanceller, ProcessBasedTsServer, SyntaxRoutingTsServer, TsServerProcess, TsServerDelegate, GetErrRoutingTsServer, ProjectLoadingRoutingSyntaxTsServer } from './server'; +import { GetErrRoutingTsServer, ITypeScriptServer, PipeRequestCanceller, ProcessBasedTsServer, SyntaxRoutingTsServer, TsServerDelegate, TsServerProcess } from './server'; const enum ServerKind { Main = 'main', @@ -34,7 +34,7 @@ const enum CompositeServerType { /** Run a separate server for syntax commands */ SeparateSyntax, - /** Use a separate suntax server while the project is loading */ + /** Use a separate syntax server while the project is loading */ DynamicSeparateSyntax, } @@ -55,21 +55,16 @@ export class TypeScriptServerSpawner { delegate: TsServerDelegate, ): ITypeScriptServer { let primaryServer: ITypeScriptServer; - switch (this.getCompositeServerType(version, configuration)) { + const serverType = this.getCompositeServerType(version, configuration); + switch (serverType) { case CompositeServerType.SeparateSyntax: + case CompositeServerType.DynamicSeparateSyntax: { + const enableDynamicRouting = serverType === CompositeServerType.DynamicSeparateSyntax; primaryServer = new SyntaxRoutingTsServer({ syntax: this.spawnTsServer(ServerKind.Syntax, version, configuration, pluginManager), semantic: this.spawnTsServer(ServerKind.Semantic, version, configuration, pluginManager) - }, delegate); - break; - } - case CompositeServerType.DynamicSeparateSyntax: - { - primaryServer = new ProjectLoadingRoutingSyntaxTsServer({ - syntax: this.spawnTsServer(ServerKind.Syntax, version, configuration, pluginManager), - semantic: this.spawnTsServer(ServerKind.Semantic, version, configuration, pluginManager) - }, delegate); + }, delegate, enableDynamicRouting); break; } case CompositeServerType.Single: @@ -94,13 +89,13 @@ export class TypeScriptServerSpawner { configuration: TypeScriptServiceConfiguration, ): CompositeServerType { switch (configuration.separateSyntaxServer) { - case SeparateSyntaxServerConfigration.Disabled: + case SeparateSyntaxServerConfiguration.Disabled: return CompositeServerType.Single; - case SeparateSyntaxServerConfigration.Enabled: + case SeparateSyntaxServerConfiguration.Enabled: return version.apiVersion?.gte(API.v340) ? CompositeServerType.SeparateSyntax : CompositeServerType.Single; - case SeparateSyntaxServerConfigration.Dynamic: + case SeparateSyntaxServerConfiguration.Dynamic: return version.apiVersion?.gte(API.v400) ? CompositeServerType.DynamicSeparateSyntax : CompositeServerType.Single; } } diff --git a/extensions/typescript-language-features/src/utils/configuration.ts b/extensions/typescript-language-features/src/utils/configuration.ts index caa38efe842..10290f3ad09 100644 --- a/extensions/typescript-language-features/src/utils/configuration.ts +++ b/extensions/typescript-language-features/src/utils/configuration.ts @@ -46,7 +46,7 @@ export namespace TsServerLogLevel { } } -export const enum SeparateSyntaxServerConfigration { +export const enum SeparateSyntaxServerConfiguration { Disabled, Enabled, Dynamic, @@ -62,7 +62,7 @@ export class TypeScriptServiceConfiguration { public readonly checkJs: boolean; public readonly experimentalDecorators: boolean; public readonly disableAutomaticTypeAcquisition: boolean; - public readonly separateSyntaxServer: SeparateSyntaxServerConfigration; + public readonly separateSyntaxServer: SeparateSyntaxServerConfiguration; public readonly enableProjectDiagnostics: boolean; public readonly maxTsServerMemory: number; public readonly enablePromptUseWorkspaceTsdk: boolean; @@ -163,15 +163,15 @@ export class TypeScriptServiceConfiguration { return configuration.get('typescript.locale', null); } - private static readUseSeparateSyntaxServer(configuration: vscode.WorkspaceConfiguration): SeparateSyntaxServerConfigration { + private static readUseSeparateSyntaxServer(configuration: vscode.WorkspaceConfiguration): SeparateSyntaxServerConfiguration { const value = configuration.get('typescript.tsserver.useSeparateSyntaxServer', true); if (value === true) { - return SeparateSyntaxServerConfigration.Enabled; + return SeparateSyntaxServerConfiguration.Enabled; } if (value === 'dynamic') { - return SeparateSyntaxServerConfigration.Dynamic; + return SeparateSyntaxServerConfiguration.Dynamic; } - return SeparateSyntaxServerConfigration.Disabled; + return SeparateSyntaxServerConfiguration.Disabled; } private static readEnableProjectDiagnostics(configuration: vscode.WorkspaceConfiguration): boolean {