mirror of
https://github.com/microsoft/vscode.git
synced 2025-12-22 19:29:17 +00:00
@@ -591,6 +591,12 @@
|
|||||||
"default": true,
|
"default": true,
|
||||||
"description": "%configuration.surveys.enabled%",
|
"description": "%configuration.surveys.enabled%",
|
||||||
"scope": "window"
|
"scope": "window"
|
||||||
|
},
|
||||||
|
"typescript.experimental.useSeparateSyntaxServer": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": false,
|
||||||
|
"description": "%configuration.experimental.useSeparateSyntaxServer%",
|
||||||
|
"scope": "window"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -49,6 +49,7 @@
|
|||||||
"typescript.problemMatchers.tsc.label": "TypeScript problems",
|
"typescript.problemMatchers.tsc.label": "TypeScript problems",
|
||||||
"typescript.problemMatchers.tscWatch.label": "TypeScript problems (watch mode)",
|
"typescript.problemMatchers.tscWatch.label": "TypeScript problems (watch mode)",
|
||||||
"configuration.suggest.paths": "Enable/disable suggestions for paths in import statements and require calls.",
|
"configuration.suggest.paths": "Enable/disable suggestions for paths in import statements and require calls.",
|
||||||
|
"configuration.experimental.useSeparateSyntaxServer": "Enable/disable spawning a separate TypeScript server that can more quickly respond to syntax related operations, such as calculating folding or computing document symbols. Note that you must restart the TypeScript server after changing this setting. Requires using TypeScript 3.4.0 or newer in the workspace.",
|
||||||
"typescript.locale": "Sets the locale used to report JavaScript and TypeScript errors. Requires using TypeScript 2.6.0 or newer in the workspace. Default of `null` uses VS Code's locale.",
|
"typescript.locale": "Sets the locale used to report JavaScript and TypeScript errors. Requires using TypeScript 2.6.0 or newer in the workspace. Default of `null` uses VS Code's locale.",
|
||||||
"javascript.implicitProjectConfig.experimentalDecorators": "Enable/disable `experimentalDecorators` for JavaScript files that are not part of a project. Existing jsconfig.json or tsconfig.json files override this setting. Requires using TypeScript 2.3.1 or newer in the workspace.",
|
"javascript.implicitProjectConfig.experimentalDecorators": "Enable/disable `experimentalDecorators` for JavaScript files that are not part of a project. Existing jsconfig.json or tsconfig.json files override this setting. Requires using TypeScript 2.3.1 or newer in the workspace.",
|
||||||
"configuration.suggest.autoImports": "Enable/disable auto import suggestions. Requires using TypeScript 2.6.1 or newer in the workspace.",
|
"configuration.suggest.autoImports": "Enable/disable auto import suggestions. Requires using TypeScript 2.6.1 or newer in the workspace.",
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ suite('Server', () => {
|
|||||||
|
|
||||||
test('should send requests with increasing sequence numbers', async () => {
|
test('should send requests with increasing sequence numbers', async () => {
|
||||||
const process = new FakeServerProcess();
|
const process = new FakeServerProcess();
|
||||||
const server = new ProcessBasedTsServer(process, undefined, new PipeRequestCanceller(undefined, tracer), undefined!, NoopTelemetryReporter, tracer);
|
const server = new ProcessBasedTsServer('semantic', process, undefined, new PipeRequestCanceller('semantic', undefined, tracer), undefined!, NoopTelemetryReporter, tracer);
|
||||||
|
|
||||||
const onWrite1 = process.onWrite();
|
const onWrite1 = process.onWrite();
|
||||||
server.executeImpl('geterr', {}, { isAsync: false, token: nulToken, expectsResult: true });
|
server.executeImpl('geterr', {}, { isAsync: false, token: nulToken, expectsResult: true });
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import * as fs from 'fs';
|
|||||||
import * as stream from 'stream';
|
import * as stream from 'stream';
|
||||||
import * as vscode from 'vscode';
|
import * as vscode from 'vscode';
|
||||||
import * as Proto from '../protocol';
|
import * as Proto from '../protocol';
|
||||||
import { ServerResponse } from '../typescriptService';
|
import { ServerResponse, TypeScriptRequests } from '../typescriptService';
|
||||||
import { Disposable } from '../utils/dispose';
|
import { Disposable } from '../utils/dispose';
|
||||||
import TelemetryReporter from '../utils/telemetry';
|
import TelemetryReporter from '../utils/telemetry';
|
||||||
import Tracer from '../utils/tracer';
|
import Tracer from '../utils/tracer';
|
||||||
@@ -23,6 +23,7 @@ export interface OngoingRequestCanceller {
|
|||||||
|
|
||||||
export class PipeRequestCanceller implements OngoingRequestCanceller {
|
export class PipeRequestCanceller implements OngoingRequestCanceller {
|
||||||
public constructor(
|
public constructor(
|
||||||
|
private readonly _serverId: string,
|
||||||
private readonly _cancellationPipeName: string | undefined,
|
private readonly _cancellationPipeName: string | undefined,
|
||||||
private readonly _tracer: Tracer,
|
private readonly _tracer: Tracer,
|
||||||
) { }
|
) { }
|
||||||
@@ -31,7 +32,7 @@ export class PipeRequestCanceller implements OngoingRequestCanceller {
|
|||||||
if (!this._cancellationPipeName) {
|
if (!this._cancellationPipeName) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
this._tracer.logTrace(`TypeScript Server: trying to cancel ongoing request with sequence number ${seq}`);
|
this._tracer.logTrace(this._serverId, `TypeScript Server: trying to cancel ongoing request with sequence number ${seq}`);
|
||||||
try {
|
try {
|
||||||
fs.writeFileSync(this._cancellationPipeName + seq, '');
|
fs.writeFileSync(this._cancellationPipeName + seq, '');
|
||||||
} catch {
|
} catch {
|
||||||
@@ -51,9 +52,9 @@ export interface ITypeScriptServer {
|
|||||||
|
|
||||||
kill(): void;
|
kill(): void;
|
||||||
|
|
||||||
executeImpl(command: string, args: any, executeInfo: { isAsync: boolean, token?: vscode.CancellationToken, expectsResult: false, lowPriority?: boolean }): undefined;
|
executeImpl(command: keyof TypeScriptRequests, args: any, executeInfo: { isAsync: boolean, token?: vscode.CancellationToken, expectsResult: false, lowPriority?: boolean }): undefined;
|
||||||
executeImpl(command: string, args: any, executeInfo: { isAsync: boolean, token?: vscode.CancellationToken, expectsResult: boolean, lowPriority?: boolean }): Promise<ServerResponse.Response<Proto.Response>>;
|
executeImpl(command: keyof TypeScriptRequests, args: any, executeInfo: { isAsync: boolean, token?: vscode.CancellationToken, expectsResult: boolean, lowPriority?: boolean }): Promise<ServerResponse.Response<Proto.Response>>;
|
||||||
executeImpl(command: string, args: any, executeInfo: { isAsync: boolean, token?: vscode.CancellationToken, expectsResult: boolean, lowPriority?: boolean }): Promise<ServerResponse.Response<Proto.Response>> | undefined;
|
executeImpl(command: keyof TypeScriptRequests, args: any, executeInfo: { isAsync: boolean, token?: vscode.CancellationToken, expectsResult: boolean, lowPriority?: boolean }): Promise<ServerResponse.Response<Proto.Response>> | undefined;
|
||||||
|
|
||||||
dispose(): void;
|
dispose(): void;
|
||||||
}
|
}
|
||||||
@@ -75,6 +76,7 @@ export class ProcessBasedTsServer extends Disposable implements ITypeScriptServe
|
|||||||
private readonly _pendingResponses = new Set<number>();
|
private readonly _pendingResponses = new Set<number>();
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
private readonly _serverId: string,
|
||||||
private readonly _process: TsServerProcess,
|
private readonly _process: TsServerProcess,
|
||||||
private readonly _tsServerLogFile: string | undefined,
|
private readonly _tsServerLogFile: string | undefined,
|
||||||
private readonly _requestCanceller: OngoingRequestCanceller,
|
private readonly _requestCanceller: OngoingRequestCanceller,
|
||||||
@@ -136,11 +138,11 @@ export class ProcessBasedTsServer extends Disposable implements ITypeScriptServe
|
|||||||
const seq = (event as Proto.RequestCompletedEvent).body.request_seq;
|
const seq = (event as Proto.RequestCompletedEvent).body.request_seq;
|
||||||
const p = this._callbacks.fetch(seq);
|
const p = this._callbacks.fetch(seq);
|
||||||
if (p) {
|
if (p) {
|
||||||
this._tracer.traceRequestCompleted('requestCompleted', seq, p.startTime);
|
this._tracer.traceRequestCompleted(this._serverId, 'requestCompleted', seq, p.startTime);
|
||||||
p.onSuccess(undefined);
|
p.onSuccess(undefined);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this._tracer.traceEvent(event);
|
this._tracer.traceEvent(this._serverId, event);
|
||||||
this._onEvent.fire(event);
|
this._onEvent.fire(event);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -156,7 +158,7 @@ export class ProcessBasedTsServer extends Disposable implements ITypeScriptServe
|
|||||||
private tryCancelRequest(seq: number, command: string): boolean {
|
private tryCancelRequest(seq: number, command: string): boolean {
|
||||||
try {
|
try {
|
||||||
if (this._requestQueue.tryDeletePendingRequest(seq)) {
|
if (this._requestQueue.tryDeletePendingRequest(seq)) {
|
||||||
this._tracer.logTrace(`TypeScript Server: canceled request with sequence number ${seq}`);
|
this.logTrace(`Canceled request with sequence number ${seq}`);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,7 +166,7 @@ export class ProcessBasedTsServer extends Disposable implements ITypeScriptServe
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
this._tracer.logTrace(`TypeScript Server: tried to cancel request with sequence number ${seq}. But request got already delivered.`);
|
this.logTrace(`Tried to cancel request with sequence number ${seq}. But request got already delivered.`);
|
||||||
return false;
|
return false;
|
||||||
} finally {
|
} finally {
|
||||||
const callback = this.fetchCallback(seq);
|
const callback = this.fetchCallback(seq);
|
||||||
@@ -180,7 +182,7 @@ export class ProcessBasedTsServer extends Disposable implements ITypeScriptServe
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this._tracer.traceResponse(response, callback.startTime);
|
this._tracer.traceResponse(this._serverId, response, callback.startTime);
|
||||||
if (response.success) {
|
if (response.success) {
|
||||||
callback.onSuccess(response);
|
callback.onSuccess(response);
|
||||||
} else if (response.message === 'No content available.') {
|
} else if (response.message === 'No content available.') {
|
||||||
@@ -191,9 +193,9 @@ export class ProcessBasedTsServer extends Disposable implements ITypeScriptServe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public executeImpl(command: string, 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: false, lowPriority?: boolean }): undefined;
|
||||||
public executeImpl(command: string, 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>>;
|
||||||
public executeImpl(command: string, args: any, executeInfo: { isAsync: boolean, token?: vscode.CancellationToken, expectsResult: boolean, lowPriority?: boolean }): Promise<ServerResponse.Response<Proto.Response>> | undefined {
|
public executeImpl(command: keyof TypeScriptRequests, args: any, executeInfo: { isAsync: boolean, token?: vscode.CancellationToken, expectsResult: boolean, lowPriority?: boolean }): Promise<ServerResponse.Response<Proto.Response>> | undefined {
|
||||||
const request = this._requestQueue.createRequest(command, args);
|
const request = this._requestQueue.createRequest(command, args);
|
||||||
const requestInfo: RequestItem = {
|
const requestInfo: RequestItem = {
|
||||||
request,
|
request,
|
||||||
@@ -255,7 +257,7 @@ export class ProcessBasedTsServer extends Disposable implements ITypeScriptServe
|
|||||||
|
|
||||||
private sendRequest(requestItem: RequestItem): void {
|
private sendRequest(requestItem: RequestItem): void {
|
||||||
const serverRequest = requestItem.request;
|
const serverRequest = requestItem.request;
|
||||||
this._tracer.traceRequest(serverRequest, requestItem.expectsResponse, this._requestQueue.length);
|
this._tracer.traceRequest(this._serverId, serverRequest, requestItem.expectsResponse, this._requestQueue.length);
|
||||||
|
|
||||||
if (requestItem.expectsResponse && !requestItem.isAsync) {
|
if (requestItem.expectsResponse && !requestItem.isAsync) {
|
||||||
this._pendingResponses.add(requestItem.request.seq);
|
this._pendingResponses.add(requestItem.request.seq);
|
||||||
@@ -281,6 +283,10 @@ export class ProcessBasedTsServer extends Disposable implements ITypeScriptServe
|
|||||||
return callback;
|
return callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private logTrace(message: string) {
|
||||||
|
this._tracer.logTrace(this._serverId, message);
|
||||||
|
}
|
||||||
|
|
||||||
private static readonly fenceCommands = new Set(['change', 'close', 'open', 'updateOpen']);
|
private static readonly fenceCommands = new Set(['change', 'close', 'open', 'updateOpen']);
|
||||||
|
|
||||||
private static getQueueingType(
|
private static getQueueingType(
|
||||||
@@ -294,3 +300,53 @@ export class ProcessBasedTsServer extends Disposable implements ITypeScriptServe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export class SyntaxRoutingTsServer extends Disposable implements ITypeScriptServer {
|
||||||
|
public constructor(
|
||||||
|
private readonly syntaxServer: ITypeScriptServer,
|
||||||
|
private readonly semanticServer: ITypeScriptServer,
|
||||||
|
) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this._register(syntaxServer.onEvent(e => this._onEvent.fire(e)));
|
||||||
|
this._register(semanticServer.onEvent(e => this._onEvent.fire(e)));
|
||||||
|
|
||||||
|
this._register(semanticServer.onExit(e => this._onExit.fire(e)));
|
||||||
|
this._register(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();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static readonly syntaxCommands = new Set<keyof TypeScriptRequests>(['navtree', 'getOutliningSpans', 'jsxClosingTag', 'selectionRange']);
|
||||||
|
private static readonly sharedCommands = new Set<keyof TypeScriptRequests>(['change', 'close', 'open', 'updateOpen', 'configure', 'configurePlugin']);
|
||||||
|
|
||||||
|
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 {
|
||||||
|
|
||||||
|
if (SyntaxRoutingTsServer.syntaxCommands.has(command)) {
|
||||||
|
return this.syntaxServer.executeImpl(command, args, executeInfo);
|
||||||
|
} else if (SyntaxRoutingTsServer.sharedCommands.has(command)) {
|
||||||
|
this.syntaxServer.executeImpl(command, args, executeInfo);
|
||||||
|
return this.semanticServer.executeImpl(command, args, executeInfo);
|
||||||
|
} else {
|
||||||
|
return this.semanticServer.executeImpl(command, args, executeInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -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, TsServerProcess, ProcessBasedTsServer, PipeRequestCanceller } from './server';
|
import { ITypeScriptServer, PipeRequestCanceller, ProcessBasedTsServer, SyntaxRoutingTsServer, TsServerProcess } from './server';
|
||||||
|
|
||||||
export class TypeScriptServerSpawner {
|
export class TypeScriptServerSpawner {
|
||||||
public constructor(
|
public constructor(
|
||||||
@@ -34,6 +34,30 @@ export class TypeScriptServerSpawner {
|
|||||||
version: TypeScriptVersion,
|
version: TypeScriptVersion,
|
||||||
configuration: TypeScriptServiceConfiguration,
|
configuration: TypeScriptServiceConfiguration,
|
||||||
pluginManager: PluginManager
|
pluginManager: PluginManager
|
||||||
|
): ITypeScriptServer {
|
||||||
|
if (this.shouldUserSeparateSyntaxServer(version)) {
|
||||||
|
const syntaxServer = this.spawnProcessBasedTsServer('syntax', version, configuration, pluginManager, ['--syntaxOnly', '--disableAutomaticTypingAcquisition']);
|
||||||
|
const semanticServer = this.spawnProcessBasedTsServer('semantic', version, configuration, pluginManager, []);
|
||||||
|
return new SyntaxRoutingTsServer(syntaxServer, semanticServer);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.spawnProcessBasedTsServer('main', version, configuration, pluginManager, []);
|
||||||
|
}
|
||||||
|
|
||||||
|
private shouldUserSeparateSyntaxServer(version: TypeScriptVersion): boolean {
|
||||||
|
if (!version.version || version.version.lt(API.v340)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return vscode.workspace.getConfiguration('typescript')
|
||||||
|
.get<boolean>('experimental.useSeparateSyntaxServer', false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private spawnProcessBasedTsServer(
|
||||||
|
serverId: string,
|
||||||
|
version: TypeScriptVersion,
|
||||||
|
configuration: TypeScriptServiceConfiguration,
|
||||||
|
pluginManager: PluginManager,
|
||||||
|
extraForkArgs: readonly string[],
|
||||||
): ITypeScriptServer {
|
): ITypeScriptServer {
|
||||||
const apiVersion = version.version || API.defaultVersion;
|
const apiVersion = version.version || API.defaultVersion;
|
||||||
|
|
||||||
@@ -41,20 +65,21 @@ export class TypeScriptServerSpawner {
|
|||||||
|
|
||||||
if (TypeScriptServerSpawner.isLoggingEnabled(apiVersion, configuration)) {
|
if (TypeScriptServerSpawner.isLoggingEnabled(apiVersion, configuration)) {
|
||||||
if (tsServerLogFile) {
|
if (tsServerLogFile) {
|
||||||
this._logger.info(`TSServer log file: ${tsServerLogFile}`);
|
this._logger.info(`<${serverId}> Log file: ${tsServerLogFile}`);
|
||||||
} else {
|
} else {
|
||||||
this._logger.error('Could not create TSServer log directory');
|
this._logger.error(`<${serverId}> Could not create log directory`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this._logger.info('Forking TSServer');
|
this._logger.info(`<${serverId}> Forking...`);
|
||||||
const childProcess = electron.fork(version.tsServerPath, args, this.getForkOptions());
|
const childProcess = electron.fork(version.tsServerPath, [...args, ...extraForkArgs], this.getForkOptions());
|
||||||
this._logger.info('Started TSServer');
|
this._logger.info(`<${serverId}> Starting...`);
|
||||||
|
|
||||||
return new ProcessBasedTsServer(
|
return new ProcessBasedTsServer(
|
||||||
|
serverId,
|
||||||
new ChildServerProcess(childProcess),
|
new ChildServerProcess(childProcess),
|
||||||
tsServerLogFile,
|
tsServerLogFile,
|
||||||
new PipeRequestCanceller(cancellationPipeName, this._tracer),
|
new PipeRequestCanceller(serverId, cancellationPipeName, this._tracer),
|
||||||
version,
|
version,
|
||||||
this._telemetryReporter,
|
this._telemetryReporter,
|
||||||
this._tracer);
|
this._tracer);
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ export namespace ServerResponse {
|
|||||||
export type Response<T extends Proto.Response> = T | Cancelled | typeof NoContent;
|
export type Response<T extends Proto.Response> = T | Cancelled | typeof NoContent;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TypeScriptRequestTypes {
|
interface StandardTsServerRequests {
|
||||||
'applyCodeActionCommand': [Proto.ApplyCodeActionCommandRequestArgs, Proto.ApplyCodeActionCommandResponse];
|
'applyCodeActionCommand': [Proto.ApplyCodeActionCommandRequestArgs, Proto.ApplyCodeActionCommandResponse];
|
||||||
'completionEntryDetails': [Proto.CompletionDetailsRequestArgs, Proto.CompletionDetailsResponse];
|
'completionEntryDetails': [Proto.CompletionDetailsRequestArgs, Proto.CompletionDetailsResponse];
|
||||||
'completionInfo': [Proto.CompletionsRequestArgs, Proto.CompletionInfoResponse];
|
'completionInfo': [Proto.CompletionsRequestArgs, Proto.CompletionInfoResponse];
|
||||||
@@ -59,6 +59,22 @@ export interface TypeScriptRequestTypes {
|
|||||||
'typeDefinition': [Proto.FileLocationRequestArgs, Proto.TypeDefinitionResponse];
|
'typeDefinition': [Proto.FileLocationRequestArgs, Proto.TypeDefinitionResponse];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface NoResponseTsServerRequests {
|
||||||
|
'open': [Proto.OpenRequestArgs, null];
|
||||||
|
'close': [Proto.FileRequestArgs];
|
||||||
|
'change': [Proto.ChangeRequestArgs, null];
|
||||||
|
'updateOpen': [Proto.UpdateOpenRequestArgs, null];
|
||||||
|
'compilerOptionsForInferredProjects': [Proto.SetCompilerOptionsForInferredProjectsArgs, null];
|
||||||
|
'reloadProjects': [null, null];
|
||||||
|
'configurePlugin': [Proto.ConfigurePluginRequest, Proto.ConfigurePluginResponse];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface AsyncTsServerRequests {
|
||||||
|
'geterr': [Proto.GeterrRequestArgs, Proto.Response];
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TypeScriptRequests = StandardTsServerRequests & NoResponseTsServerRequests & AsyncTsServerRequests;
|
||||||
|
|
||||||
export interface ITypeScriptServiceClient {
|
export interface ITypeScriptServiceClient {
|
||||||
/**
|
/**
|
||||||
* Convert a resource (VS Code) to a normalized path (TypeScript).
|
* Convert a resource (VS Code) to a normalized path (TypeScript).
|
||||||
@@ -100,19 +116,17 @@ export interface ITypeScriptServiceClient {
|
|||||||
readonly logger: Logger;
|
readonly logger: Logger;
|
||||||
readonly bufferSyncSupport: BufferSyncSupport;
|
readonly bufferSyncSupport: BufferSyncSupport;
|
||||||
|
|
||||||
execute<K extends keyof TypeScriptRequestTypes>(
|
execute<K extends keyof StandardTsServerRequests>(
|
||||||
command: K,
|
command: K,
|
||||||
args: TypeScriptRequestTypes[K][0],
|
args: StandardTsServerRequests[K][0],
|
||||||
token: vscode.CancellationToken,
|
token: vscode.CancellationToken,
|
||||||
lowPriority?: boolean
|
lowPriority?: boolean
|
||||||
): Promise<ServerResponse.Response<TypeScriptRequestTypes[K][1]>>;
|
): Promise<ServerResponse.Response<StandardTsServerRequests[K][1]>>;
|
||||||
|
|
||||||
executeWithoutWaitingForResponse(command: 'open', args: Proto.OpenRequestArgs): void;
|
executeWithoutWaitingForResponse<K extends keyof NoResponseTsServerRequests>(
|
||||||
executeWithoutWaitingForResponse(command: 'close', args: Proto.FileRequestArgs): void;
|
command: K,
|
||||||
executeWithoutWaitingForResponse(command: 'change', args: Proto.ChangeRequestArgs): void;
|
args: NoResponseTsServerRequests[K][0]
|
||||||
executeWithoutWaitingForResponse(command: 'updateOpen', args: Proto.UpdateOpenRequestArgs): void;
|
): void;
|
||||||
executeWithoutWaitingForResponse(command: 'compilerOptionsForInferredProjects', args: Proto.SetCompilerOptionsForInferredProjectsArgs): void;
|
|
||||||
executeWithoutWaitingForResponse(command: 'reloadProjects', args: null): void;
|
|
||||||
|
|
||||||
executeAsync(command: 'geterr', args: Proto.GeterrRequestArgs, token: vscode.CancellationToken): Promise<ServerResponse.Response<Proto.Response>>;
|
executeAsync(command: 'geterr', args: Proto.GeterrRequestArgs, token: vscode.CancellationToken): Promise<ServerResponse.Response<Proto.Response>>;
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import BufferSyncSupport from './features/bufferSyncSupport';
|
|||||||
import { DiagnosticKind, DiagnosticsManager } from './features/diagnostics';
|
import { DiagnosticKind, DiagnosticsManager } from './features/diagnostics';
|
||||||
import * as Proto from './protocol';
|
import * as Proto from './protocol';
|
||||||
import { ITypeScriptServer } from './tsServer/server';
|
import { ITypeScriptServer } from './tsServer/server';
|
||||||
import { ITypeScriptServiceClient, ServerResponse } from './typescriptService';
|
import { ITypeScriptServiceClient, ServerResponse, TypeScriptRequests } from './typescriptService';
|
||||||
import API from './utils/api';
|
import API from './utils/api';
|
||||||
import { TsServerLogLevel, TypeScriptServiceConfiguration } from './utils/configuration';
|
import { TsServerLogLevel, TypeScriptServiceConfiguration } from './utils/configuration';
|
||||||
import { Disposable } from './utils/dispose';
|
import { Disposable } from './utils/dispose';
|
||||||
@@ -607,7 +607,7 @@ export default class TypeScriptServiceClient extends Disposable implements IType
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
public execute(command: string, args: any, token: vscode.CancellationToken, lowPriority?: boolean): Promise<ServerResponse.Response<Proto.Response>> {
|
public execute(command: keyof TypeScriptRequests, args: any, token: vscode.CancellationToken, lowPriority?: boolean): Promise<ServerResponse.Response<Proto.Response>> {
|
||||||
return this.executeImpl(command, args, {
|
return this.executeImpl(command, args, {
|
||||||
isAsync: false,
|
isAsync: false,
|
||||||
token,
|
token,
|
||||||
@@ -616,7 +616,7 @@ export default class TypeScriptServiceClient extends Disposable implements IType
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public executeWithoutWaitingForResponse(command: string, args: any): void {
|
public executeWithoutWaitingForResponse(command: keyof TypeScriptRequests, args: any): void {
|
||||||
this.executeImpl(command, args, {
|
this.executeImpl(command, args, {
|
||||||
isAsync: false,
|
isAsync: false,
|
||||||
token: undefined,
|
token: undefined,
|
||||||
@@ -624,7 +624,7 @@ export default class TypeScriptServiceClient extends Disposable implements IType
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public executeAsync(command: string, args: Proto.GeterrRequestArgs, token: vscode.CancellationToken): Promise<ServerResponse.Response<Proto.Response>> {
|
public executeAsync(command: keyof TypeScriptRequests, args: Proto.GeterrRequestArgs, token: vscode.CancellationToken): Promise<ServerResponse.Response<Proto.Response>> {
|
||||||
return this.executeImpl(command, args, {
|
return this.executeImpl(command, args, {
|
||||||
isAsync: true,
|
isAsync: true,
|
||||||
token,
|
token,
|
||||||
@@ -632,9 +632,9 @@ export default class TypeScriptServiceClient extends Disposable implements IType
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private executeImpl(command: string, args: any, executeInfo: { isAsync: boolean, token?: vscode.CancellationToken, expectsResult: false, lowPriority?: boolean }): undefined;
|
private executeImpl(command: keyof TypeScriptRequests, args: any, executeInfo: { isAsync: boolean, token?: vscode.CancellationToken, expectsResult: false, lowPriority?: boolean }): undefined;
|
||||||
private executeImpl(command: string, args: any, executeInfo: { isAsync: boolean, token?: vscode.CancellationToken, expectsResult: boolean, lowPriority?: boolean }): Promise<ServerResponse.Response<Proto.Response>>;
|
private executeImpl(command: keyof TypeScriptRequests, args: any, executeInfo: { isAsync: boolean, token?: vscode.CancellationToken, expectsResult: boolean, lowPriority?: boolean }): Promise<ServerResponse.Response<Proto.Response>>;
|
||||||
private executeImpl(command: string, args: any, executeInfo: { isAsync: boolean, token?: vscode.CancellationToken, expectsResult: boolean, lowPriority?: boolean }): Promise<ServerResponse.Response<Proto.Response>> | undefined {
|
private executeImpl(command: keyof TypeScriptRequests, args: any, executeInfo: { isAsync: boolean, token?: vscode.CancellationToken, expectsResult: boolean, lowPriority?: boolean }): Promise<ServerResponse.Response<Proto.Response>> | undefined {
|
||||||
this.bufferSyncSupport.beforeCommand(command);
|
this.bufferSyncSupport.beforeCommand(command);
|
||||||
const runningServerState = this.service();
|
const runningServerState = this.service();
|
||||||
return runningServerState.server.executeImpl(command, args, executeInfo);
|
return runningServerState.server.executeImpl(command, args, executeInfo);
|
||||||
@@ -769,7 +769,6 @@ export default class TypeScriptServiceClient extends Disposable implements IType
|
|||||||
this.logTelemetry(telemetryData.telemetryEventName, properties);
|
this.logTelemetry(telemetryData.telemetryEventName, properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private configurePlugin(pluginName: string, configuration: {}): any {
|
private configurePlugin(pluginName: string, configuration: {}): any {
|
||||||
if (this.apiVersion.gte(API.v314)) {
|
if (this.apiVersion.gte(API.v314)) {
|
||||||
this.executeWithoutWaitingForResponse('configurePlugin', { pluginName, configuration });
|
this.executeWithoutWaitingForResponse('configurePlugin', { pluginName, configuration });
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ export default class Tracer {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public traceRequest(request: Proto.Request, responseExpected: boolean, queueLength: number): void {
|
public traceRequest(serverId: string, request: Proto.Request, responseExpected: boolean, queueLength: number): void {
|
||||||
if (this.trace === Trace.Off) {
|
if (this.trace === Trace.Off) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -58,10 +58,10 @@ export default class Tracer {
|
|||||||
if (this.trace === Trace.Verbose && request.arguments) {
|
if (this.trace === Trace.Verbose && request.arguments) {
|
||||||
data = `Arguments: ${JSON.stringify(request.arguments, null, 4)}`;
|
data = `Arguments: ${JSON.stringify(request.arguments, null, 4)}`;
|
||||||
}
|
}
|
||||||
this.logTrace(`Sending request: ${request.command} (${request.seq}). Response expected: ${responseExpected ? 'yes' : 'no'}. Current queue length: ${queueLength}`, data);
|
this.logTrace(serverId, `Sending request: ${request.command} (${request.seq}). Response expected: ${responseExpected ? 'yes' : 'no'}. Current queue length: ${queueLength}`, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public traceResponse(response: Proto.Response, startTime: number): void {
|
public traceResponse(serverId: string, response: Proto.Response, startTime: number): void {
|
||||||
if (this.trace === Trace.Off) {
|
if (this.trace === Trace.Off) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -69,17 +69,17 @@ export default class Tracer {
|
|||||||
if (this.trace === Trace.Verbose && response.body) {
|
if (this.trace === Trace.Verbose && response.body) {
|
||||||
data = `Result: ${JSON.stringify(response.body, null, 4)}`;
|
data = `Result: ${JSON.stringify(response.body, null, 4)}`;
|
||||||
}
|
}
|
||||||
this.logTrace(`Response received: ${response.command} (${response.request_seq}). Request took ${Date.now() - startTime} ms. Success: ${response.success} ${!response.success ? '. Message: ' + response.message : ''}`, data);
|
this.logTrace(serverId, `Response received: ${response.command} (${response.request_seq}). Request took ${Date.now() - startTime} ms. Success: ${response.success} ${!response.success ? '. Message: ' + response.message : ''}`, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public traceRequestCompleted(command: string, request_seq: number, startTime: number): any {
|
public traceRequestCompleted(serverId: string, command: string, request_seq: number, startTime: number): any {
|
||||||
if (this.trace === Trace.Off) {
|
if (this.trace === Trace.Off) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.logTrace(`Async response received: ${command} (${request_seq}). Request took ${Date.now() - startTime} ms.`);
|
this.logTrace(serverId, `Async response received: ${command} (${request_seq}). Request took ${Date.now() - startTime} ms.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
public traceEvent(event: Proto.Event): void {
|
public traceEvent(serverId: string, event: Proto.Event): void {
|
||||||
if (this.trace === Trace.Off) {
|
if (this.trace === Trace.Off) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -87,12 +87,12 @@ export default class Tracer {
|
|||||||
if (this.trace === Trace.Verbose && event.body) {
|
if (this.trace === Trace.Verbose && event.body) {
|
||||||
data = `Data: ${JSON.stringify(event.body, null, 4)}`;
|
data = `Data: ${JSON.stringify(event.body, null, 4)}`;
|
||||||
}
|
}
|
||||||
this.logTrace(`Event received: ${event.event} (${event.seq}).`, data);
|
this.logTrace(serverId, `Event received: ${event.event} (${event.seq}).`, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public logTrace(message: string, data?: any): void {
|
public logTrace(serverId: string, message: string, data?: any): void {
|
||||||
if (this.trace !== Trace.Off) {
|
if (this.trace !== Trace.Off) {
|
||||||
this.logger.logLevel('Trace', message, data);
|
this.logger.logLevel('Trace', `<${serverId}> ${message}`, data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user