Aggressively cancel code lens requests when the resource changes
For #84185
This commit is contained in:
parent
278b4f8cfa
commit
a8ad448cb0
5 changed files with 63 additions and 8 deletions
|
@ -337,6 +337,9 @@ export default class BufferSyncSupport extends Disposable {
|
|||
private readonly _onDelete = this._register(new vscode.EventEmitter<vscode.Uri>());
|
||||
public readonly onDelete = this._onDelete.event;
|
||||
|
||||
private readonly _onWillChange = this._register(new vscode.EventEmitter<vscode.Uri>());
|
||||
public readonly onWillChange = this._onWillChange.event;
|
||||
|
||||
public listen(): void {
|
||||
if (this.listening) {
|
||||
return;
|
||||
|
@ -456,6 +459,8 @@ export default class BufferSyncSupport extends Disposable {
|
|||
return;
|
||||
}
|
||||
|
||||
this._onWillChange.fire(syncedBuffer.resource);
|
||||
|
||||
syncedBuffer.onContentChanged(e.contentChanges);
|
||||
const didTrigger = this.requestDiagnostic(syncedBuffer);
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ export default class TypeScriptImplementationsCodeLensProvider extends TypeScrip
|
|||
const codeLens = inputCodeLens as ReferencesCodeLens;
|
||||
|
||||
const args = typeConverters.Position.toFileLocationRequestArgs(codeLens.file, codeLens.range.start);
|
||||
const response = await this.client.execute('implementation', args, token, { lowPriority: true });
|
||||
const response = await this.client.execute('implementation', args, token, { lowPriority: true, cancelOnResourceChange: codeLens.document });
|
||||
if (response.type !== 'response' || !response.body) {
|
||||
codeLens.command = response.type === 'cancelled'
|
||||
? TypeScriptBaseCodeLensProvider.cancelledCommand
|
||||
|
|
|
@ -19,7 +19,7 @@ class TypeScriptReferencesCodeLensProvider extends TypeScriptBaseCodeLensProvide
|
|||
public async resolveCodeLens(inputCodeLens: vscode.CodeLens, token: vscode.CancellationToken): Promise<vscode.CodeLens> {
|
||||
const codeLens = inputCodeLens as ReferencesCodeLens;
|
||||
const args = typeConverters.Position.toFileLocationRequestArgs(codeLens.file, codeLens.range.start);
|
||||
const response = await this.client.execute('references', args, token, { lowPriority: true });
|
||||
const response = await this.client.execute('references', args, token, { lowPriority: true, cancelOnResourceChange: codeLens.document });
|
||||
if (response.type !== 'response' || !response.body) {
|
||||
codeLens.command = response.type === 'cancelled'
|
||||
? TypeScriptBaseCodeLensProvider.cancelledCommand
|
||||
|
|
|
@ -78,6 +78,7 @@ export type TypeScriptRequests = StandardTsServerRequests & NoResponseTsServerRe
|
|||
export type ExecConfig = {
|
||||
readonly lowPriority?: boolean;
|
||||
readonly nonRecoverable?: boolean;
|
||||
readonly cancelOnResourceChange?: vscode.Uri
|
||||
};
|
||||
|
||||
export interface ITypeScriptServiceClient {
|
||||
|
|
|
@ -35,6 +35,11 @@ export interface TsDiagnostics {
|
|||
readonly diagnostics: Proto.Diagnostic[];
|
||||
}
|
||||
|
||||
interface ToCancelOnResourceChanged {
|
||||
readonly resource: vscode.Uri;
|
||||
cancel(): void;
|
||||
}
|
||||
|
||||
namespace ServerState {
|
||||
export const enum Type {
|
||||
None,
|
||||
|
@ -60,6 +65,8 @@ namespace ServerState {
|
|||
public tsserverVersion: string | undefined,
|
||||
public langaugeServiceEnabled: boolean,
|
||||
) { }
|
||||
|
||||
public readonly toCancelOnResourceChange = new Set<ToCancelOnResourceChanged>();
|
||||
}
|
||||
|
||||
export class Errored {
|
||||
|
@ -129,9 +136,14 @@ export default class TypeScriptServiceClient extends Disposable implements IType
|
|||
|
||||
this.diagnosticsManager = new DiagnosticsManager('typescript');
|
||||
this.bufferSyncSupport.onDelete(resource => {
|
||||
this.cancelInflightRequestsForResource(resource);
|
||||
this.diagnosticsManager.delete(resource);
|
||||
}, null, this._disposables);
|
||||
|
||||
this.bufferSyncSupport.onWillChange(resource => {
|
||||
this.cancelInflightRequestsForResource(resource);
|
||||
});
|
||||
|
||||
vscode.workspace.onDidChangeConfiguration(() => {
|
||||
const oldConfiguration = this._configuration;
|
||||
this._configuration = TypeScriptServiceConfiguration.loadFromWorkspace();
|
||||
|
@ -173,6 +185,18 @@ export default class TypeScriptServiceClient extends Disposable implements IType
|
|||
}));
|
||||
}
|
||||
|
||||
private cancelInflightRequestsForResource(resource: vscode.Uri): void {
|
||||
if (this.serverState.type !== ServerState.Type.Running) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const request of this.serverState.toCancelOnResourceChange) {
|
||||
if (request.resource.toString() === resource.toString()) {
|
||||
request.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public get configuration() {
|
||||
return this._configuration;
|
||||
}
|
||||
|
@ -609,12 +633,37 @@ 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>> {
|
||||
const execution = this.executeImpl(command, args, {
|
||||
isAsync: false,
|
||||
token,
|
||||
expectsResult: true,
|
||||
lowPriority: config?.lowPriority
|
||||
});
|
||||
let execution: Promise<ServerResponse.Response<Proto.Response>>;
|
||||
|
||||
if (config?.cancelOnResourceChange) {
|
||||
const runningServerState = this.service();
|
||||
|
||||
const source = new vscode.CancellationTokenSource();
|
||||
token.onCancellationRequested(() => source.cancel());
|
||||
|
||||
const inFlight: ToCancelOnResourceChanged = {
|
||||
resource: config.cancelOnResourceChange,
|
||||
cancel: () => source.cancel(),
|
||||
};
|
||||
runningServerState.toCancelOnResourceChange.add(inFlight);
|
||||
|
||||
execution = this.executeImpl(command, args, {
|
||||
isAsync: false,
|
||||
token: source.token,
|
||||
expectsResult: true,
|
||||
...config,
|
||||
}).finally(() => {
|
||||
runningServerState.toCancelOnResourceChange.delete(inFlight);
|
||||
source.dispose();
|
||||
});
|
||||
} else {
|
||||
execution = this.executeImpl(command, args, {
|
||||
isAsync: false,
|
||||
token,
|
||||
expectsResult: true,
|
||||
...config,
|
||||
});
|
||||
}
|
||||
|
||||
if (config?.nonRecoverable) {
|
||||
execution.catch(() => this.fatalError(command));
|
||||
|
|
Loading…
Reference in a new issue