Make geterr async

This commit is contained in:
Matt Bierner
2018-05-08 14:28:08 -07:00
parent faec3b58b7
commit 3fc493a0e4
4 changed files with 42 additions and 13 deletions

View File

@@ -310,7 +310,7 @@ export default class BufferSyncSupport {
const token = new CancellationTokenSource();
const getErr = this.pendingGetErr = {
request: this.client.execute('geterr', args, token.token)
request: this.client.executeAsync('geterr', args, token.token)
.then(undefined, () => { })
.then(() => {
if (this.pendingGetErr === getErr) {

View File

@@ -30,7 +30,6 @@ export interface ITypeScriptServiceClient {
execute(command: 'open', args: Proto.OpenRequestArgs, expectedResult: boolean, token?: CancellationToken): Promise<any>;
execute(command: 'close', args: Proto.FileRequestArgs, expectedResult: boolean, token?: CancellationToken): Promise<any>;
execute(command: 'change', args: Proto.ChangeRequestArgs, expectedResult: boolean, token?: CancellationToken): Promise<any>;
execute(command: 'geterr', args: Proto.GeterrRequestArgs, expectedResult: boolean, token?: CancellationToken): Promise<any>;
execute(command: 'quickinfo', args: Proto.FileLocationRequestArgs, token?: CancellationToken): Promise<Proto.QuickInfoResponse>;
execute(command: 'completions', args: Proto.CompletionsRequestArgs, token?: CancellationToken): Promise<Proto.CompletionsResponse>;
execute(command: 'completionEntryDetails', args: Proto.CompletionDetailsRequestArgs, token?: CancellationToken): Promise<Proto.CompletionDetailsResponse>;
@@ -60,4 +59,6 @@ export interface ITypeScriptServiceClient {
execute(command: 'organizeImports', args: Proto.OrganizeImportsRequestArgs, token?: CancellationToken): Promise<Proto.OrganizeImportsResponse>;
execute(command: 'getOutliningSpans', args: Proto.FileRequestArgs, token: CancellationToken): Promise<Proto.OutliningSpansResponse>;
execute(command: string, args: any, expectedResult: boolean | CancellationToken, token?: CancellationToken): Promise<any>;
executeAsync(command: 'geterr', args: Proto.GeterrRequestArgs, token: CancellationToken): Promise<any>;
}

View File

@@ -42,23 +42,31 @@ interface CallbackItem {
class CallbackMap {
private readonly callbacks: Map<number, CallbackItem> = new Map();
private readonly asyncCallbacks: Map<number, CallbackItem> = new Map();
public pendingResponses: number = 0;
public destroy(e: any): void {
for (const callback of this.callbacks.values()) {
callback.e(e);
}
for (const callback of this.asyncCallbacks.values()) {
callback.e(e);
}
this.callbacks.clear();
this.pendingResponses = 0;
}
public add(seq: number, callback: CallbackItem) {
this.callbacks.set(seq, callback);
++this.pendingResponses;
public add(seq: number, callback: CallbackItem, isAsync: boolean) {
if (isAsync) {
this.asyncCallbacks.set(seq, callback);
} else {
this.callbacks.set(seq, callback);
++this.pendingResponses;
}
}
public fetch(seq: number): CallbackItem | undefined {
const callback = this.callbacks.get(seq);
const callback = this.callbacks.get(seq) || this.asyncCallbacks.get(seq);
this.delete(seq);
return callback;
}
@@ -66,13 +74,16 @@ class CallbackMap {
private delete(seq: number) {
if (this.callbacks.delete(seq)) {
--this.pendingResponses;
} else {
this.asyncCallbacks.delete(seq);
}
}
}
interface RequestItem {
request: Proto.Request;
readonly request: Proto.Request;
callbacks: CallbackItem | null;
readonly isAsync: boolean;
}
class RequestQueue {
@@ -672,6 +683,10 @@ export default class TypeScriptServiceClient implements ITypeScriptServiceClient
return undefined;
}
public executeAsync(command: string, args: Proto.GeterrRequestArgs, token: CancellationToken): Promise<any> {
return this.executeImpl(command, args, { isAsync: true, token, expectsResult: true });
}
public execute(command: string, args: any, expectsResultOrToken?: boolean | CancellationToken): Promise<any> {
let token: CancellationToken | undefined = undefined;
let expectsResult = true;
@@ -680,19 +695,23 @@ export default class TypeScriptServiceClient implements ITypeScriptServiceClient
} else {
token = expectsResultOrToken;
}
return this.executeImpl(command, args, { isAsync: false, token, expectsResult });
}
private executeImpl(command: string, args: any, executeInfo: { isAsync: boolean, token?: CancellationToken, expectsResult: boolean }): Promise<any> {
const request = this.requestQueue.createRequest(command, args);
const requestInfo: RequestItem = {
request: request,
callbacks: null
callbacks: null,
isAsync: executeInfo.isAsync
};
let result: Promise<any>;
if (expectsResult) {
if (executeInfo.expectsResult) {
let wasCancelled = false;
result = new Promise<any>((resolve, reject) => {
requestInfo.callbacks = { c: resolve, e: reject, start: Date.now() };
if (token) {
token.onCancellationRequested(() => {
if (executeInfo.token) {
executeInfo.token.onCancellationRequested(() => {
wasCancelled = true;
this.tryCancelRequest(request.seq);
});
@@ -751,7 +770,7 @@ export default class TypeScriptServiceClient implements ITypeScriptServiceClient
const serverRequest = requestItem.request;
this.tracer.traceRequest(serverRequest, !!requestItem.callbacks, this.requestQueue.length);
if (requestItem.callbacks) {
this.callbacks.add(serverRequest.seq, requestItem.callbacks);
this.callbacks.add(serverRequest.seq, requestItem.callbacks, requestItem.isAsync);
}
this.service()
.then((childProcess) => {
@@ -820,8 +839,10 @@ export default class TypeScriptServiceClient implements ITypeScriptServiceClient
private dispatchEvent(event: Proto.Event) {
switch (event.event) {
case 'requestCompleted':
const p = this.callbacks.fetch((event as Proto.RequestCompletedEvent).body.request_seq);
const seq = (event as Proto.RequestCompletedEvent).body.request_seq;
const p = this.callbacks.fetch(seq);
if (p) {
this.tracer.traceRequestCompleted('requestCompleted', seq, p.start);
p.c(undefined);
}
break;

View File

@@ -74,6 +74,13 @@ export default class Tracer {
this.logTrace(`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 {
if (this.trace === Trace.Off) {
return;
}
this.logTrace(`Async response received: ${command} (${request_seq}). Request took ${Date.now() - startTime} ms.`);
}
public traceEvent(event: Proto.Event): void {
if (this.trace === Trace.Off) {
return;