Fix stopping load indicator when updateOpen completes

Fixes #122979

We can consider the project loaded when `updateOpen` completes for all servers. Previously we were only waiting on the first one
This commit is contained in:
Matt Bierner 2021-05-06 14:54:40 -07:00
parent 5f7422b6bb
commit f25ffb76ed
No known key found for this signature in database
GPG key ID: 099C331567E11888
2 changed files with 38 additions and 41 deletions

View file

@ -32,9 +32,11 @@ export interface ITypeScriptServer {
kill(): void;
executeImpl(command: keyof TypeScriptRequests, args: any, executeInfo: { isAsync: boolean, token?: vscode.CancellationToken, expectsResult: false, lowPriority?: boolean, executionTarget?: ExecutionTarget }): undefined;
executeImpl(command: keyof TypeScriptRequests, args: any, executeInfo: { isAsync: boolean, token?: vscode.CancellationToken, expectsResult: boolean, lowPriority?: boolean, executionTarget?: ExecutionTarget }): Promise<ServerResponse.Response<Proto.Response>>;
executeImpl(command: keyof TypeScriptRequests, args: any, executeInfo: { isAsync: boolean, token?: vscode.CancellationToken, expectsResult: boolean, lowPriority?: boolean, executionTarget?: ExecutionTarget }): Promise<ServerResponse.Response<Proto.Response>> | undefined;
/**
* @return A list of all execute requests. If there are multiple entries, the first item is the primary
* request while the rest are secondary ones.
*/
executeImpl(command: keyof TypeScriptRequests, args: any, executeInfo: { isAsync: boolean, token?: vscode.CancellationToken, expectsResult: boolean, lowPriority?: boolean, executionTarget?: ExecutionTarget }): Array<Promise<ServerResponse.Response<Proto.Response>> | undefined>;
dispose(): void;
}
@ -202,9 +204,7 @@ export class ProcessBasedTsServer extends Disposable implements ITypeScriptServe
}
}
public executeImpl(command: keyof TypeScriptRequests, args: any, executeInfo: { isAsync: boolean, token?: vscode.CancellationToken, expectsResult: false, lowPriority?: boolean, executionTarget?: ExecutionTarget }): undefined;
public executeImpl(command: keyof TypeScriptRequests, args: any, executeInfo: { isAsync: boolean, token?: vscode.CancellationToken, expectsResult: boolean, lowPriority?: boolean, executionTarget?: ExecutionTarget }): Promise<ServerResponse.Response<Proto.Response>>;
public executeImpl(command: keyof TypeScriptRequests, args: any, executeInfo: { isAsync: boolean, token?: vscode.CancellationToken, expectsResult: boolean, lowPriority?: boolean, executionTarget?: ExecutionTarget }): Promise<ServerResponse.Response<Proto.Response>> | undefined {
public executeImpl(command: keyof TypeScriptRequests, args: any, executeInfo: { isAsync: boolean, token?: vscode.CancellationToken, expectsResult: boolean, lowPriority?: boolean, executionTarget?: ExecutionTarget }): Array<Promise<ServerResponse.Response<Proto.Response>> | undefined> {
const request = this._requestQueue.createRequest(command, args);
const requestInfo: RequestItem = {
request,
@ -244,7 +244,7 @@ export class ProcessBasedTsServer extends Disposable implements ITypeScriptServe
this._requestQueue.enqueue(requestInfo);
this.sendNextRequests();
return result;
return [result];
}
private sendNextRequests(): void {
@ -328,9 +328,13 @@ class RequestRouter {
private readonly delegate: TsServerDelegate,
) { }
public execute(command: keyof TypeScriptRequests, args: any, executeInfo: ExecuteInfo): Promise<ServerResponse.Response<Proto.Response>> | undefined {
public execute(
command: keyof TypeScriptRequests,
args: any,
executeInfo: ExecuteInfo,
): Array<Promise<ServerResponse.Response<Proto.Response>> | undefined> {
if (RequestRouter.sharedCommands.has(command) && typeof executeInfo.executionTarget === 'undefined') {
// Dispatch shared commands to all servers but only return from first one
// Dispatch shared commands to all servers but use first one as the primary response
const requestStates: RequestState.State[] = this.servers.map(() => RequestState.Unresolved);
@ -350,15 +354,13 @@ class RequestRouter {
token = source.token;
}
let firstRequest: Promise<ServerResponse.Response<Proto.Response>> | undefined;
const allRequests: Array<Promise<ServerResponse.Response<Proto.Response>> | undefined> = [];
for (let serverIndex = 0; serverIndex < this.servers.length; ++serverIndex) {
const server = this.servers[serverIndex].server;
const request = server.executeImpl(command, args, { ...executeInfo, token }) as Promise<ServerResponse.Response<Proto.Response>> | undefined;
if (serverIndex === 0) {
firstRequest = request;
}
const request = server.executeImpl(command, args, { ...executeInfo, token })[0];
allRequests.push(request);
if (request) {
request
.then(result => {
@ -380,7 +382,7 @@ class RequestRouter {
}
}
return firstRequest;
return allRequests;
}
for (const { canRun, server } of this.servers) {
@ -460,9 +462,7 @@ export class GetErrRoutingTsServer extends Disposable implements ITypeScriptServ
this.mainServer.kill();
}
public executeImpl(command: keyof TypeScriptRequests, args: any, executeInfo: { isAsync: boolean, token?: vscode.CancellationToken, expectsResult: false, lowPriority?: boolean, executionTarget?: ExecutionTarget }): undefined;
public executeImpl(command: keyof TypeScriptRequests, args: any, executeInfo: { isAsync: boolean, token?: vscode.CancellationToken, expectsResult: boolean, lowPriority?: boolean, executionTarget?: ExecutionTarget }): Promise<ServerResponse.Response<Proto.Response>>;
public executeImpl(command: keyof TypeScriptRequests, args: any, executeInfo: { isAsync: boolean, token?: vscode.CancellationToken, expectsResult: boolean, lowPriority?: boolean, executionTarget?: ExecutionTarget }): Promise<ServerResponse.Response<Proto.Response>> | undefined {
public executeImpl(command: keyof TypeScriptRequests, args: any, executeInfo: { isAsync: boolean, token?: vscode.CancellationToken, expectsResult: boolean, lowPriority?: boolean, executionTarget?: ExecutionTarget }): Array<Promise<ServerResponse.Response<Proto.Response>> | undefined> {
return this.router.execute(command, args, executeInfo);
}
}
@ -602,9 +602,7 @@ export class SyntaxRoutingTsServer extends Disposable implements ITypeScriptServ
this.semanticServer.kill();
}
public executeImpl(command: keyof TypeScriptRequests, args: any, executeInfo: { isAsync: boolean, token?: vscode.CancellationToken, expectsResult: false, lowPriority?: boolean, executionTarget?: ExecutionTarget }): undefined;
public executeImpl(command: keyof TypeScriptRequests, args: any, executeInfo: { isAsync: boolean, token?: vscode.CancellationToken, expectsResult: boolean, lowPriority?: boolean, executionTarget?: ExecutionTarget }): Promise<ServerResponse.Response<Proto.Response>>;
public executeImpl(command: keyof TypeScriptRequests, args: any, executeInfo: { isAsync: boolean, token?: vscode.CancellationToken, expectsResult: boolean, lowPriority?: boolean, executionTarget?: ExecutionTarget }): Promise<ServerResponse.Response<Proto.Response>> | undefined {
public executeImpl(command: keyof TypeScriptRequests, args: any, executeInfo: { isAsync: boolean, token?: vscode.CancellationToken, expectsResult: boolean, lowPriority?: boolean, executionTarget?: ExecutionTarget }): Array<Promise<ServerResponse.Response<Proto.Response>> | undefined> {
return this.router.execute(command, args, executeInfo);
}
}

View file

@ -727,7 +727,7 @@ export default class TypeScriptServiceClient extends Disposable implements IType
}
public execute(command: keyof TypeScriptRequests, args: any, token: vscode.CancellationToken, config?: ExecConfig): Promise<ServerResponse.Response<Proto.Response>> {
let execution: Promise<ServerResponse.Response<Proto.Response>>;
let executions: Array<Promise<ServerResponse.Response<Proto.Response>> | undefined>;
if (config?.cancelOnResourceChange) {
const runningServerState = this.service();
@ -741,17 +741,18 @@ export default class TypeScriptServiceClient extends Disposable implements IType
};
runningServerState.toCancelOnResourceChange.add(inFlight);
execution = this.executeImpl(command, args, {
executions = this.executeImpl(command, args, {
isAsync: false,
token: source.token,
expectsResult: true,
...config,
}).finally(() => {
});
executions[0]!.finally(() => {
runningServerState.toCancelOnResourceChange.delete(inFlight);
source.dispose();
});
} else {
execution = this.executeImpl(command, args, {
executions = this.executeImpl(command, args, {
isAsync: false,
token,
expectsResult: true,
@ -760,25 +761,25 @@ export default class TypeScriptServiceClient extends Disposable implements IType
}
if (config?.nonRecoverable) {
execution.catch(err => this.fatalError(command, err));
executions[0]!.catch(err => this.fatalError(command, err));
}
return execution;
}
public executeWithoutWaitingForResponse(command: keyof TypeScriptRequests, args: any): void {
const promise = this.executeImpl(command, args, {
isAsync: false,
token: undefined,
expectsResult: command === 'updateOpen'
});
if (command === 'updateOpen') {
// If update open has completed, consider that the project has loaded
promise.then(() => {
Promise.all(executions).then(() => {
this.loadingIndicator.reset();
});
}
return executions[0]!;
}
public executeWithoutWaitingForResponse(command: keyof TypeScriptRequests, args: any): void {
this.executeImpl(command, args, {
isAsync: false,
token: undefined,
expectsResult: false
});
}
public executeAsync(command: keyof TypeScriptRequests, args: Proto.GeterrRequestArgs, token: vscode.CancellationToken): Promise<ServerResponse.Response<Proto.Response>> {
@ -786,12 +787,10 @@ export default class TypeScriptServiceClient extends Disposable implements IType
isAsync: true,
token,
expectsResult: true
});
})[0]!;
}
private executeImpl(command: keyof TypeScriptRequests, args: any, executeInfo: { isAsync: boolean, token?: vscode.CancellationToken, expectsResult: false, lowPriority?: boolean, requireSemantic?: boolean }): undefined;
private executeImpl(command: keyof TypeScriptRequests, args: any, executeInfo: { isAsync: boolean, token?: vscode.CancellationToken, expectsResult: boolean, lowPriority?: boolean, requireSemantic?: boolean }): Promise<ServerResponse.Response<Proto.Response>>;
private executeImpl(command: keyof TypeScriptRequests, args: any, executeInfo: { isAsync: boolean, token?: vscode.CancellationToken, expectsResult: boolean, lowPriority?: boolean, requireSemantic?: boolean }): Promise<ServerResponse.Response<Proto.Response>> | undefined {
private executeImpl(command: keyof TypeScriptRequests, args: any, executeInfo: { isAsync: boolean, token?: vscode.CancellationToken, expectsResult: boolean, lowPriority?: boolean, requireSemantic?: boolean }): Array<Promise<ServerResponse.Response<Proto.Response>> | undefined> {
this.bufferSyncSupport.beforeCommand(command);
const runningServerState = this.service();
return runningServerState.server.executeImpl(command, args, executeInfo);