Skip to content

Commit 97c9ecd

Browse files
committed
extension/src: add integration test for package symbols outline
Change-Id: I96b93f48a2ee625597ff906e1eab6d39021b53fa Reviewed-on: https://go-review.googlesource.com/c/vscode-go/+/653035 Reviewed-by: Hongxiang Jiang <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]> kokoro-CI: kokoro <[email protected]>
1 parent b1e08da commit 97c9ecd

File tree

5 files changed

+142
-1
lines changed

5 files changed

+142
-1
lines changed

extension/src/goPackageOutline.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ interface PackageSymbolData {
167167
file: number;
168168
}
169169

170-
class PackageSymbol extends vscode.TreeItem {
170+
export class PackageSymbol extends vscode.TreeItem {
171171
constructor(
172172
private readonly data: PackageSymbolData,
173173
private readonly files: string[],
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
/*---------------------------------------------------------
2+
* Copyright 2025 The Go Authors. All rights reserved.
3+
* Licensed under the MIT License. See LICENSE in the project root for license information.
4+
*--------------------------------------------------------*/
5+
6+
import assert from 'assert';
7+
import path from 'path';
8+
import { MockExtensionContext } from '../mocks/MockContext';
9+
import { GoPackageOutlineProvider, PackageSymbol } from '../../src/goPackageOutline';
10+
import { updateGoVarsFromConfig } from '../../src/goInstallTools';
11+
import { window } from 'vscode';
12+
import { Env } from '../gopls/goplsTestEnv.utils';
13+
14+
import { getGoConfig } from '../../src/config';
15+
16+
import vscode = require('vscode');
17+
18+
suite('GoPackageOutlineProvider', function () {
19+
this.timeout(20000);
20+
let provider: GoPackageOutlineProvider;
21+
const fixtureDir = path.join(__dirname, '../../../test/testdata/packageOutlineTest');
22+
const ctx = MockExtensionContext.new();
23+
const env = new Env();
24+
25+
suiteSetup(async () => {
26+
await updateGoVarsFromConfig({});
27+
await env.startGopls(undefined, getGoConfig(), fixtureDir);
28+
provider = GoPackageOutlineProvider.setup(ctx);
29+
});
30+
31+
suiteTeardown(() => {
32+
ctx.teardown();
33+
});
34+
35+
test('opening a document should trigger package outline response', async () => {
36+
const document = await vscode.workspace.openTextDocument(
37+
vscode.Uri.file(path.join(fixtureDir, 'symbols_1.go'))
38+
);
39+
await window.showTextDocument(document);
40+
await sleep(500); // wait for gopls response
41+
const res = provider.result;
42+
assert.strictEqual(res?.PackageName, 'package_outline_test');
43+
assert.strictEqual(res?.Files.length, 2);
44+
assert.strictEqual(res?.Symbols.length, 3);
45+
assert.strictEqual(res?.Symbols[0].name, 'TestReceiver');
46+
assert.strictEqual(res?.Symbols[0].children.length, 6); // 3 fields and 3 receiver methods
47+
});
48+
49+
test('clicking on symbol should navigate to definition', async () => {
50+
const document = await vscode.workspace.openTextDocument(
51+
vscode.Uri.file(path.join(fixtureDir, 'symbols_1.go'))
52+
);
53+
await window.showTextDocument(document);
54+
await sleep(500); // wait for gopls response
55+
await vscode.commands.executeCommand('setContext', 'go.showPackageOutline');
56+
const children = await provider.getChildren();
57+
const receiver = children?.find((symbol) => symbol.label === 'TestReceiver');
58+
assert.ok(receiver, 'receiver symbol not found');
59+
const method1 = receiver.children?.find((symbol) => symbol.label === 'method1');
60+
assert.ok(method1, 'method1 symbol not found');
61+
clickSymbol(method1);
62+
await sleep(500); // wait for editor to navigate to symbol
63+
assert.strictEqual(window.activeTextEditor?.document.uri.fsPath, document.uri.fsPath);
64+
assert.strictEqual(window.activeTextEditor?.selection.active.line, 19);
65+
assert.strictEqual(window.activeTextEditor?.selection.active.character, 0);
66+
});
67+
68+
test('clicking on symbol in different file should open file', async () => {
69+
const document = await vscode.workspace.openTextDocument(
70+
vscode.Uri.file(path.join(fixtureDir, 'symbols_1.go'))
71+
);
72+
await window.showTextDocument(document);
73+
await sleep(500); // wait for gopls response
74+
await vscode.commands.executeCommand('setContext', 'go.showPackageOutline');
75+
const children = await provider.getChildren();
76+
const receiver = children?.find((symbol) => symbol.label === 'TestReceiver');
77+
assert.ok(receiver, 'receiver symbol not found');
78+
const method2 = receiver.children?.find((symbol) => symbol.label === 'method2');
79+
assert.ok(method2, 'method2 symbol not found');
80+
clickSymbol(method2);
81+
await sleep(500); // wait for editor to navigate to symbol
82+
const symbols2 = vscode.workspace.textDocuments.find(
83+
(doc) => doc.uri.fsPath === path.join(fixtureDir, 'symbols_2.go')
84+
);
85+
assert.strictEqual(window.activeTextEditor?.document.uri.fsPath, symbols2?.uri.fsPath);
86+
assert.strictEqual(window.activeTextEditor?.selection.active.line, 2);
87+
assert.strictEqual(window.activeTextEditor?.selection.active.character, 0);
88+
});
89+
90+
test('non-go file does not trigger outline', async () => {
91+
const document = await vscode.workspace.openTextDocument(
92+
vscode.Uri.file(path.join(fixtureDir, 'symbols_3.ts'))
93+
);
94+
await window.showTextDocument(document);
95+
await sleep(500); // wait for gopls response
96+
assert.strictEqual(provider.result, undefined);
97+
});
98+
});
99+
100+
function sleep(ms: number) {
101+
return new Promise((resolve) => setTimeout(resolve, ms));
102+
}
103+
104+
function clickSymbol(symbol: PackageSymbol) {
105+
if (symbol.command) {
106+
vscode.commands.executeCommand(symbol.command.command, ...(symbol.command.arguments || []));
107+
} else {
108+
assert.fail(symbol.label + ' symbol has no command');
109+
}
110+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package package_outline_test
2+
3+
import (
4+
"fmt"
5+
)
6+
7+
func print(txt string) {
8+
fmt.Println(txt)
9+
}
10+
func main() {
11+
print("Hello")
12+
}
13+
14+
type TestReceiver struct {
15+
field1 int
16+
field2 string
17+
field3 bool
18+
}
19+
20+
func (*TestReceiver) method1() {
21+
22+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package package_outline_test
2+
3+
func (*TestReceiver) method2() {
4+
5+
}
6+
7+
func (*TestReceiver) method3() {
8+
9+
}

extension/test/testdata/packageOutlineTest/symbols_3.ts

Whitespace-only changes.

0 commit comments

Comments
 (0)