test/gopls: retry completion query a couple of times
Sometimes gopls returns an empty result for the completion request
until the internal state is stablized (even when it is ready for
other queries).
Try a couple of times before declaring a test failure.
While we are here, make buildLanguageClient non-async.
It doesn't have to be.
Updates golang/vscode-go#363
Change-Id: I29c80b28bb549d7ac239cc3cf5fe6e56966fc151
Reviewed-on: https://go-review.googlesource.com/c/vscode-go/+/243281
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
diff --git a/src/goLanguageServer.ts b/src/goLanguageServer.ts
index 1a29751..6d8446f 100644
--- a/src/goLanguageServer.ts
+++ b/src/goLanguageServer.ts
@@ -158,7 +158,7 @@
// Track the latest config used to start the language server,
// and rebuild the language client.
latestConfig = config;
- languageClient = await buildLanguageClient(config);
+ languageClient = buildLanguageClient(config);
crashCount = 0;
}
@@ -188,7 +188,7 @@
return true;
}
-async function buildLanguageClient(config: LanguageServerConfig): Promise<LanguageClient> {
+function buildLanguageClient(config: LanguageServerConfig): LanguageClient {
// Reuse the same output channel for each instance of the server.
if (config.enabled) {
if (!serverOutputChannel) {
diff --git a/test/gopls/extension.test.ts b/test/gopls/extension.test.ts
index 64cddfc..7f5104c 100644
--- a/test/gopls/extension.test.ts
+++ b/test/gopls/extension.test.ts
@@ -46,7 +46,10 @@
public async setup() {
await this.reset();
await this.extension.activate();
- await sleep(2000); // allow extension host + gopls to start.
+ await sleep(2000); // allow the language server to start.
+ // TODO(hyangah): find a better way to check the language server's status.
+ // I thought I'd check the languageClient.onReady(),
+ // but couldn't make it working yet.
}
public async reset(fixtureDirName?: string) { // name of the fixtures subdirectory to use.
@@ -89,7 +92,9 @@
const projectDir = path.join(__dirname, '..', '..', '..');
const env = new Env(projectDir);
- suiteSetup(async () => { await env.setup(); });
+ suiteSetup(async () => {
+ await env.setup();
+ });
suiteTeardown(async () => { await env.reset(); });
test('HoverProvider', async () => {
@@ -137,9 +142,23 @@
['fmt.<>', new vscode.Position(19, 5), 'Formatter'],
];
for (const [name, position, wantFilterText] of testCases) {
- const list = await vscode.commands.executeCommand(
- 'vscode.executeCompletionItemProvider', uri, position) as vscode.CompletionList;
-
+ let list: vscode.CompletionList<vscode.CompletionItem>;
+ // Query completion items. We expect the hard coded filter text hack
+ // has been applied and gopls returns an incomplete list by default
+ // to avoid reordering by vscode. But, if the query is made before
+ // gopls is ready, we observed that gopls returns an empty result
+ // as a complete result, and vscode returns a general completion list instead.
+ // Retry a couple of times if we see a complete result as a workaround.
+ // (github.com/golang/vscode-go/issues/363)
+ for (let i = 0; i < 3; i++) {
+ list = await vscode.commands.executeCommand(
+ 'vscode.executeCompletionItemProvider', uri, position) as vscode.CompletionList;
+ if (list.isIncomplete) {
+ break;
+ }
+ await sleep(100);
+ console.log(`${new Date()}: retrying...`);
+ }
// Confirm that the hardcoded filter text hack has been applied.
if (!list.isIncomplete) {
assert.fail(`gopls should provide an incomplete list by default`);
@@ -157,6 +176,5 @@
}
}
}
-
});
});