rename suggestions: fix: remove delay that was causing bad UX

fixes https://github.com/microsoft/vscode-copilot/issues/5259
This commit is contained in:
Ulugbek Abdullaev 2024-04-24 00:10:02 +05:00
parent 2d947d1206
commit 2a0715668a
No known key found for this signature in database
GPG key ID: 4F1AB80F62B8E4A4
8 changed files with 41 additions and 16 deletions

View file

@ -1740,6 +1740,7 @@ export interface NewSymbolName {
}
export interface NewSymbolNamesProvider {
supportsAutomaticNewSymbolNamesTriggerKind?: Promise<boolean | undefined>;
provideNewSymbolNames(model: model.ITextModel, range: IRange, triggerKind: NewSymbolNameTriggerKind, token: CancellationToken): ProviderResult<NewSymbolName[]>;
}

View file

@ -231,7 +231,17 @@ class RenameController implements IEditorContribution {
const newSymbolNamesProviders = this._languageFeaturesService.newSymbolNamesProvider.all(model);
const requestRenameSuggestions = (triggerKind: NewSymbolNameTriggerKind, cts: CancellationToken) => newSymbolNamesProviders.map(p => p.provideNewSymbolNames(model, loc.range, triggerKind, cts));
const resolvedNewSymbolnamesProviders = await Promise.all(newSymbolNamesProviders.map(async p => [p, await p.supportsAutomaticNewSymbolNamesTriggerKind ?? false] as const));
const requestRenameSuggestions = (triggerKind: NewSymbolNameTriggerKind, cts: CancellationToken) => {
let providers = resolvedNewSymbolnamesProviders.slice();
if (triggerKind === NewSymbolNameTriggerKind.Automatic) {
providers = providers.filter(([_, supportsAutomatic]) => supportsAutomatic);
}
return providers.map(([p,]) => p.provideNewSymbolNames(model, loc.range, triggerKind, cts));
};
trace('creating rename input field and awaiting its result');
const supportPreview = this._bulkEditService.hasPreviewHandler() && this._configService.getValue<boolean>(this.editor.getModel().uri, 'editor.rename.enablePreview');

View file

@ -520,17 +520,13 @@ export class RenameWidget implements IRenameWidget, IContentWidget, IDisposable
const triggerKind = isManuallyTriggered ? NewSymbolNameTriggerKind.Invoke : NewSymbolNameTriggerKind.Automatic;
const candidates = this._requestRenameCandidatesOnce(triggerKind, this._renameCandidateProvidersCts.token);
const window = dom.getActiveWindow();
let delayHandle: (() => void) | undefined;
if (isManuallyTriggered) {
this._inputWithButton.setStopButton();
} else {
const handle = window.setTimeout(() => this._inputWithButton.setStopButton(), 600);
delayHandle = () => window.clearTimeout(handle);
if (candidates.length === 0) {
return;
}
this._updateRenameCandidates(candidates, currentName, delayHandle, this._renameCts.token);
this._inputWithButton.setStopButton();
this._updateRenameCandidates(candidates, currentName, this._renameCts.token);
}
}
@ -569,7 +565,7 @@ export class RenameWidget implements IRenameWidget, IContentWidget, IDisposable
}, 100);
}
private async _updateRenameCandidates(candidates: ProviderResult<NewSymbolName[]>[], currentName: string, cancelSetStopButton: (() => void) | undefined, token: CancellationToken) {
private async _updateRenameCandidates(candidates: ProviderResult<NewSymbolName[]>[], currentName: string, token: CancellationToken) {
const trace = (...args: any[]) => this._trace('_updateRenameCandidates', ...args);
trace('start');
@ -589,11 +585,6 @@ export class RenameWidget implements IRenameWidget, IContentWidget, IDisposable
);
trace(`received updateRenameCandidates results - total (unfiltered) ${newNames.length} candidates.`);
if (newNames.length < 1) {
cancelSetStopButton?.();
return;
}
// deduplicate and filter out the current value
const distinctNames = arrays.distinct(newNames, v => v.newSymbolName);

1
src/vs/monaco.d.ts vendored
View file

@ -7903,6 +7903,7 @@ declare namespace monaco.languages {
}
export interface NewSymbolNamesProvider {
supportsAutomaticNewSymbolNamesTriggerKind?: Promise<boolean | undefined>;
provideNewSymbolNames(model: editor.ITextModel, range: IRange, triggerKind: NewSymbolNameTriggerKind, token: CancellationToken): ProviderResult<NewSymbolName[]>;
}

View file

@ -505,6 +505,7 @@ export class MainThreadLanguageFeatures extends Disposable implements MainThread
$registerNewSymbolNamesProvider(handle: number, selector: IDocumentFilterDto[]): void {
this._registrations.set(handle, this._languageFeaturesService.newSymbolNamesProvider.register(selector, {
supportsAutomaticNewSymbolNamesTriggerKind: this._proxy.$supportsAutomaticNewSymbolNamesTriggerKind(handle),
provideNewSymbolNames: (model: ITextModel, range: IRange, triggerKind: languages.NewSymbolNameTriggerKind, token: CancellationToken): Promise<languages.NewSymbolName[] | undefined> => {
return this._proxy.$provideNewSymbolNames(handle, model.uri, range, triggerKind, token);
}

View file

@ -2142,6 +2142,7 @@ export interface ExtHostLanguageFeaturesShape {
$releaseWorkspaceSymbols(handle: number, id: number): void;
$provideRenameEdits(handle: number, resource: UriComponents, position: IPosition, newName: string, token: CancellationToken): Promise<IWorkspaceEditDto & { rejectReason?: string } | undefined>;
$resolveRenameLocation(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<languages.RenameLocation | undefined>;
$supportsAutomaticNewSymbolNamesTriggerKind(handle: number): Promise<boolean | undefined>;
$provideNewSymbolNames(handle: number, resource: UriComponents, range: IRange, triggerKind: languages.NewSymbolNameTriggerKind, token: CancellationToken): Promise<languages.NewSymbolName[] | undefined>;
$provideDocumentSemanticTokens(handle: number, resource: UriComponents, previousResultId: number, token: CancellationToken): Promise<VSBuffer | null>;
$releaseDocumentSemanticTokens(handle: number, semanticColoringResultId: number): void;

View file

@ -880,6 +880,10 @@ class NewSymbolNamesAdapter {
private readonly _logService: ILogService
) { }
async supportsAutomaticNewSymbolNamesTriggerKind() {
return this._provider.supportsAutomaticTriggerKind;
}
async provideNewSymbolNames(resource: URI, range: IRange, triggerKind: languages.NewSymbolNameTriggerKind, token: CancellationToken): Promise<languages.NewSymbolName[] | undefined> {
const doc = this._documents.getDocument(resource);
@ -2489,6 +2493,16 @@ export class ExtHostLanguageFeatures implements extHostProtocol.ExtHostLanguageF
return this._createDisposable(handle);
}
$supportsAutomaticNewSymbolNamesTriggerKind(handle: number): Promise<boolean | undefined> {
return this._withAdapter(
handle,
NewSymbolNamesAdapter,
adapter => adapter.supportsAutomaticNewSymbolNamesTriggerKind(),
false,
undefined
);
}
$provideNewSymbolNames(handle: number, resource: UriComponents, range: IRange, triggerKind: languages.NewSymbolNameTriggerKind, token: CancellationToken): Promise<languages.NewSymbolName[] | undefined> {
return this._withAdapter(handle, NewSymbolNamesAdapter, adapter => adapter.provideNewSymbolNames(URI.revive(resource), range, triggerKind, token), undefined, token);
}

View file

@ -24,6 +24,12 @@ declare module 'vscode' {
}
export interface NewSymbolNamesProvider {
/**
* @default false
*/
readonly supportsAutomaticTriggerKind?: Thenable<boolean>;
/**
* Provide possible new names for the symbol at the given range.
*