Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CompletionList.isIncomplete=true results in showing "stale" results when typing quickly due to cancelled requests #147830

Open
DanTup opened this issue Apr 21, 2022 · 2 comments
Assignees
Labels
suggest IntelliSense, Auto Complete under-discussion Issue is under discussion for relevance, priority, approach

Comments

@DanTup
Copy link
Contributor

DanTup commented Apr 21, 2022

I'm trying to move my extension to using isIncomplete=true on Completion results to avoid preloading thousands of items in the first request. However, when I do this, the completion feels sluggish/doesn't update and I suspect it's due to how cancellations are handled.

I made a small completion provider that takes 40ms to return, and a test that types one character every 60ms (this means all requests complete without any cancellation). I include the offset of the request in the results to make it clear when updated results are shown. As expected, the completion list updates on every keystroke:

Apr-21-2022 09-51-20

However, if I increase the completion provider to take 80ms to return (slightly longer than the delay between keystrokes), the completion list doesn't update at all until the typing stops:

Apr-21-2022 09-52-14

My understanding is that when you type a new character, VS Code cancels the previous (in-flight) request and sends a new one. This makes sense. However, if the server returns the results anyway (perhaps it had already computed them), I think it would be a much better experience if VS Code still used those results while waiting for the next one. Otherwise, using isIncomplete=true results in completion feeling sluggish when typing slightly faster than the server is responding (server response times may increase slightly if lots of requests are being sent/cancelled, as there could be synchronous work that means they don't immediately handle the cancellation).

@DanTup
Copy link
Contributor Author

DanTup commented Apr 21, 2022

Here is the code I used for testing. It can be pasted into src/test/suite/extension.test.ts in a project created with yo code:

import * as assert from 'assert';
import * as vs from "vscode";

suite('Extension Test Suite', () => {

	test('Sample test', async function () {
		this.timeout(100000000000);

		registerCompletionProvider();

		const doc = await vs.workspace.openTextDocument({ language: 'plaintext', content: '' });
		const editor = await vs.window.showTextDocument(doc);

		editor.selection = new vs.Selection(new vs.Position(0, 0), new vs.Position(0, 0));
		await delay(5000);
		await vs.commands.executeCommand('editor.action.triggerSuggest');
		await delay(1000);
		await typeSlowly('aaaaaaaaaaaaaaaaaaaa');


		await delay(600000);
	});

	async function typeSlowly(text: string) {
		for (const c of text.split('')) {
			await delay(60);
			await vs.commands.executeCommand('default:type', { text: c });
		}
	}

	function delay(milliseconds: number): Promise<void> {
		return new Promise((resolve) => setTimeout(resolve, milliseconds));
	}

	function registerCompletionProvider() {
		vs.languages.registerCompletionItemProvider({ language: 'plaintext' }, {
			provideCompletionItems: async (document: vs.TextDocument, position: vs.Position, token: vs.CancellationToken, context: vs.CompletionContext): Promise<vs.CompletionList> => {
				console.log(`Request for completions at ${position.character}`);
				await delay(80); // change this between 40 and 80ms
				const res = new vs.CompletionList(
					[
						new vs.CompletionItem(`aaaaaaaaaaaaaaaaaaaa(${position.character})`),
					],
					true,
				);
				return res;
			}
		});
	}
});

@DanTup DanTup changed the title CompletionList.isIncomplete results in showing "stale" results when typing quickly due to cancelled requests CompletionList.isIncomplete=true results in showing "stale" results when typing quickly due to cancelled requests Apr 21, 2022
@DanTup
Copy link
Contributor Author

DanTup commented Apr 22, 2022

Some other things that might be contributing to this feeling slower:

  • The completion dropdown usually moves along on each update - if the second one also moved on each keypress (before waiting for the results), it wouldn't look so different. Although, I wonder if the moving is actually the best behaviour - it seems odd that it keeps getting further and further offset from where it will actually insert the displayed value
  • There's no highlighting of the matched characters after a keystroke until the update arrives - highlighting in the existing results list prior to the update arriving could also make it less obvious something is taking longer

DanTup added a commit to Dart-Code/Dart-Code that referenced this issue Apr 27, 2022
There are some outstanding issues with this, including snippets being truncated (due to low ranking) and some issues noted at microsoft/vscode#147830.
@jrieken jrieken added the suggest IntelliSense, Auto Complete label Oct 3, 2022
@jrieken jrieken added the under-discussion Issue is under discussion for relevance, priority, approach label Dec 6, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
suggest IntelliSense, Auto Complete under-discussion Issue is under discussion for relevance, priority, approach
Projects
None yet
Development

No branches or pull requests

2 participants