Reduce duplicate code

Merge the `SyntaxRoutingTsServer` and `ProjectLoadingRoutingSyntaxTsServer` classes since these only differ routing to the syntax server while a project is loading
This commit is contained in:
Matt Bierner 2020-06-26 16:11:07 -07:00
parent d0c1d2ed94
commit 9d59cb9813
3 changed files with 36 additions and 96 deletions

View file

@ -379,75 +379,6 @@ class RequestRouter {
} }
} }
const syntaxAlwaysCommands: ReadonlySet<keyof TypeScriptRequests> = new Set<keyof TypeScriptRequests>([
'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<Proto.Event>());
public readonly onEvent = this._onEvent.event;
private readonly _onExit = this._register(new vscode.EventEmitter<any>());
public readonly onExit = this._onExit.event;
private readonly _onError = this._register(new vscode.EventEmitter<any>());
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<ServerResponse.Response<Proto.Response>>;
public executeImpl(command: keyof TypeScriptRequests, args: any, executeInfo: { isAsync: boolean, token?: vscode.CancellationToken, expectsResult: boolean, lowPriority?: boolean }): Promise<ServerResponse.Response<Proto.Response>> | undefined {
return this.router.execute(command, args, executeInfo);
}
}
export class GetErrRoutingTsServer extends Disposable implements ITypeScriptServer { export class GetErrRoutingTsServer extends Disposable implements ITypeScriptServer {
private static readonly diagnosticEvents = new Set<string>([ private static readonly diagnosticEvents = new Set<string>([
@ -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<keyof TypeScriptRequests>([
'navtree',
'getOutliningSpans',
'jsxClosingTag',
'selectionRange',
'format',
'formatonkey',
'docCommentTemplate',
]);
/** /**
* Commands that should always be run on the semantic server. * 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. * Commands that can be run on the syntax server but would benefit from being upgraded to the semantic server.
*/ */
private syntaxAllowedCommands = new Set<keyof TypeScriptRequests>([ private static readonly syntaxAllowedCommands = new Set<keyof TypeScriptRequests>([
'completions', 'completions',
'completionEntryDetails', 'completionEntryDetails',
'completionInfo', 'completionInfo',
@ -563,6 +507,7 @@ export class ProjectLoadingRoutingSyntaxTsServer extends Disposable implements I
public constructor( public constructor(
servers: { syntax: ITypeScriptServer, semantic: ITypeScriptServer }, servers: { syntax: ITypeScriptServer, semantic: ITypeScriptServer },
delegate: TsServerDelegate, delegate: TsServerDelegate,
enableDynamicRouting: boolean,
) { ) {
super(); super();
@ -574,13 +519,13 @@ export class ProjectLoadingRoutingSyntaxTsServer extends Disposable implements I
{ {
server: this.syntaxServer, server: this.syntaxServer,
canRun: (command) => { canRun: (command) => {
if (syntaxAlwaysCommands.has(command)) { if (SyntaxRoutingTsServer.syntaxAlwaysCommands.has(command)) {
return true; return true;
} }
if (ProjectLoadingRoutingSyntaxTsServer.semanticCommands.has(command)) { if (SyntaxRoutingTsServer.semanticCommands.has(command)) {
return false; return false;
} }
if (this.projectLoading && this.syntaxAllowedCommands.has(command)) { if (enableDynamicRouting && this.projectLoading && SyntaxRoutingTsServer.syntaxAllowedCommands.has(command)) {
return true; return true;
} }
return false; return false;

View file

@ -9,7 +9,7 @@ import * as stream from 'stream';
import * as vscode from 'vscode'; import * as vscode from 'vscode';
import type * as Proto from '../protocol'; import type * as Proto from '../protocol';
import API from '../utils/api'; 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 * as electron from '../utils/electron';
import LogDirectoryProvider from '../utils/logDirectoryProvider'; import LogDirectoryProvider from '../utils/logDirectoryProvider';
import Logger from '../utils/logger'; import Logger from '../utils/logger';
@ -18,7 +18,7 @@ import { PluginManager } from '../utils/plugins';
import { TelemetryReporter } from '../utils/telemetry'; import { TelemetryReporter } from '../utils/telemetry';
import Tracer from '../utils/tracer'; import Tracer from '../utils/tracer';
import { TypeScriptVersion, TypeScriptVersionProvider } from '../utils/versionProvider'; 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 { const enum ServerKind {
Main = 'main', Main = 'main',
@ -34,7 +34,7 @@ const enum CompositeServerType {
/** Run a separate server for syntax commands */ /** Run a separate server for syntax commands */
SeparateSyntax, SeparateSyntax,
/** Use a separate suntax server while the project is loading */ /** Use a separate syntax server while the project is loading */
DynamicSeparateSyntax, DynamicSeparateSyntax,
} }
@ -55,21 +55,16 @@ export class TypeScriptServerSpawner {
delegate: TsServerDelegate, delegate: TsServerDelegate,
): ITypeScriptServer { ): ITypeScriptServer {
let primaryServer: ITypeScriptServer; let primaryServer: ITypeScriptServer;
switch (this.getCompositeServerType(version, configuration)) { const serverType = this.getCompositeServerType(version, configuration);
switch (serverType) {
case CompositeServerType.SeparateSyntax: case CompositeServerType.SeparateSyntax:
case CompositeServerType.DynamicSeparateSyntax:
{ {
const enableDynamicRouting = serverType === CompositeServerType.DynamicSeparateSyntax;
primaryServer = new SyntaxRoutingTsServer({ primaryServer = new SyntaxRoutingTsServer({
syntax: this.spawnTsServer(ServerKind.Syntax, version, configuration, pluginManager), syntax: this.spawnTsServer(ServerKind.Syntax, version, configuration, pluginManager),
semantic: this.spawnTsServer(ServerKind.Semantic, version, configuration, pluginManager) semantic: this.spawnTsServer(ServerKind.Semantic, version, configuration, pluginManager)
}, delegate); }, delegate, enableDynamicRouting);
break;
}
case CompositeServerType.DynamicSeparateSyntax:
{
primaryServer = new ProjectLoadingRoutingSyntaxTsServer({
syntax: this.spawnTsServer(ServerKind.Syntax, version, configuration, pluginManager),
semantic: this.spawnTsServer(ServerKind.Semantic, version, configuration, pluginManager)
}, delegate);
break; break;
} }
case CompositeServerType.Single: case CompositeServerType.Single:
@ -94,13 +89,13 @@ export class TypeScriptServerSpawner {
configuration: TypeScriptServiceConfiguration, configuration: TypeScriptServiceConfiguration,
): CompositeServerType { ): CompositeServerType {
switch (configuration.separateSyntaxServer) { switch (configuration.separateSyntaxServer) {
case SeparateSyntaxServerConfigration.Disabled: case SeparateSyntaxServerConfiguration.Disabled:
return CompositeServerType.Single; return CompositeServerType.Single;
case SeparateSyntaxServerConfigration.Enabled: case SeparateSyntaxServerConfiguration.Enabled:
return version.apiVersion?.gte(API.v340) ? CompositeServerType.SeparateSyntax : CompositeServerType.Single; 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; return version.apiVersion?.gte(API.v400) ? CompositeServerType.DynamicSeparateSyntax : CompositeServerType.Single;
} }
} }

View file

@ -46,7 +46,7 @@ export namespace TsServerLogLevel {
} }
} }
export const enum SeparateSyntaxServerConfigration { export const enum SeparateSyntaxServerConfiguration {
Disabled, Disabled,
Enabled, Enabled,
Dynamic, Dynamic,
@ -62,7 +62,7 @@ export class TypeScriptServiceConfiguration {
public readonly checkJs: boolean; public readonly checkJs: boolean;
public readonly experimentalDecorators: boolean; public readonly experimentalDecorators: boolean;
public readonly disableAutomaticTypeAcquisition: boolean; public readonly disableAutomaticTypeAcquisition: boolean;
public readonly separateSyntaxServer: SeparateSyntaxServerConfigration; public readonly separateSyntaxServer: SeparateSyntaxServerConfiguration;
public readonly enableProjectDiagnostics: boolean; public readonly enableProjectDiagnostics: boolean;
public readonly maxTsServerMemory: number; public readonly maxTsServerMemory: number;
public readonly enablePromptUseWorkspaceTsdk: boolean; public readonly enablePromptUseWorkspaceTsdk: boolean;
@ -163,15 +163,15 @@ export class TypeScriptServiceConfiguration {
return configuration.get<string | null>('typescript.locale', null); return configuration.get<string | null>('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); const value = configuration.get('typescript.tsserver.useSeparateSyntaxServer', true);
if (value === true) { if (value === true) {
return SeparateSyntaxServerConfigration.Enabled; return SeparateSyntaxServerConfiguration.Enabled;
} }
if (value === 'dynamic') { if (value === 'dynamic') {
return SeparateSyntaxServerConfigration.Dynamic; return SeparateSyntaxServerConfiguration.Dynamic;
} }
return SeparateSyntaxServerConfigration.Disabled; return SeparateSyntaxServerConfiguration.Disabled;
} }
private static readEnableProjectDiagnostics(configuration: vscode.WorkspaceConfiguration): boolean { private static readEnableProjectDiagnostics(configuration: vscode.WorkspaceConfiguration): boolean {