Skip to content
This repository has been archived by the owner on Jul 15, 2023. It is now read-only.

When gotoSymbol.includeGoroot is set, also show symbols from GOROOT #1604

Merged
merged 5 commits into from
Apr 5, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -689,6 +689,12 @@
"description": "If false, the import statements will be excluded while using the Go to Symbol in File feature",
"scope": "resource"
},
"go.gotoSymbol.includeGoroot": {
"type": "boolean",
"default": false,
"description": "If false, the standard library located at $GOROOT will be excluded while using the Go to Symbol in File feature",
"scope": "resource"
},
"go.enableCodeLens": {
"type": "object",
"properties": {
Expand Down
80 changes: 58 additions & 22 deletions src/goSymbol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import vscode = require('vscode');
import cp = require('child_process');
import { getBinPath, getToolsEnvVars, killProcess } from './util';
import { getGoRuntimePath } from './goPath';
import { promptForMissingTool, promptForUpdatingTool } from './goInstallTools';

// Keep in sync with github.com/acroca/go-symbols'
Expand Down Expand Up @@ -51,12 +52,15 @@ export class GoWorkspaceSymbolProvider implements vscode.WorkspaceSymbolProvider
if (vscode.window.activeTextEditor && vscode.workspace.getWorkspaceFolder(vscode.window.activeTextEditor.document.uri)) {
root = vscode.workspace.getWorkspaceFolder(vscode.window.activeTextEditor.document.uri).uri.fsPath;
}
if (!root) {

let goConfig = vscode.workspace.getConfiguration('go', vscode.window.activeTextEditor ? vscode.window.activeTextEditor.document.uri : null);

if (!root && !goConfig.gotoSymbol.includeGoroot) {
vscode.window.showInformationMessage('No workspace is open to find symbols.');
return;
}

return getWorkspaceSymbols(root, query, token).then(results => {
return getWorkspaceSymbols(root, query, token, goConfig).then(results => {
let symbols: vscode.SymbolInformation[] = [];
convertToCodeSymbols(results, symbols);
return symbols;
Expand All @@ -69,37 +73,69 @@ export function getWorkspaceSymbols(workspacePath: string, query: string, token:
goConfig = vscode.workspace.getConfiguration('go', vscode.window.activeTextEditor ? vscode.window.activeTextEditor.document.uri : null);
}
let gotoSymbolConfig = goConfig['gotoSymbol'];
let calls: Promise<GoSymbolDeclaration[]>[] = [];

let ignoreFolders: string[] = gotoSymbolConfig ? gotoSymbolConfig['ignoreFolders'] : [];
let args = (ignoreFolderFeatureOn && ignoreFolders && ignoreFolders.length > 0) ? ['-ignore', ignoreFolders.join(',')] : [];
args.push(workspacePath);
args.push(query);
let baseArgs = (ignoreFolderFeatureOn && ignoreFolders && ignoreFolders.length > 0) ? ['-ignore', ignoreFolders.join(',')] : [];

calls.push(callGoSymbols([...baseArgs, workspacePath, query], token));

if (gotoSymbolConfig.includeGoroot) {
let gorootCall = getGoroot()
.then(goRoot => callGoSymbols([...baseArgs, goRoot, query], token));
calls.push(gorootCall);
}

return Promise.all(calls)
.then(([...results]) => <GoSymbolDeclaration[]>[].concat(...results))
.catch((err: Error) => {
if (err && (<any>err).code === 'ENOENT') {
promptForMissingTool('go-symbols');
}
if (err.message.startsWith('flag provided but not defined: -ignore')) {
promptForUpdatingTool('go-symbols');
return getWorkspaceSymbols(workspacePath, query, token, goConfig, false);
}
});
}

function callGoSymbols(args: string[], token: vscode.CancellationToken): Promise<GoSymbolDeclaration[]> {
let gosyms = getBinPath('go-symbols');
let env = getToolsEnvVars();
let p: cp.ChildProcess;

if (token) {
token.onCancellationRequested(() => killProcess(p));
}

return new Promise((resolve, reject) => {
p = cp.execFile(gosyms, args, { maxBuffer: 1024 * 1024, env }, (err, stdout, stderr) => {
try {
if (err && (<any>err).code === 'ENOENT') {
promptForMissingTool('go-symbols');
}
if (err && stderr && stderr.startsWith('flag provided but not defined: -ignore')) {
promptForUpdatingTool('go-symbols');
p = null;
return getWorkspaceSymbols(workspacePath, query, token, goConfig, false).then(results => {
return resolve(results);
});
}
if (err) return resolve(null);
let result = stdout.toString();
let decls = <GoSymbolDeclaration[]>JSON.parse(result);
return resolve(decls);
} catch (e) {
reject(e);
if (err && stderr && stderr.startsWith('flag provided but not defined: -ignore')) {
return reject(new Error(stderr));
} else if (err) {
return reject(err);
}
let result = stdout.toString();
let decls = <GoSymbolDeclaration[]>JSON.parse(result);
return resolve(decls);
});
});
}

function getGoroot(): Promise<string> {
let goExecutable = getGoRuntimePath();
if (!goExecutable) {
return Promise.reject(new Error('Cannot find "go" binary. Update PATH or GOROOT appropriately'));
}
return new Promise((resolve, reject) => {
cp.execFile(goExecutable, ['env', 'GOROOT'], (err, stdout) => {
if (err) {
reject(err);
return;
}
let [goRoot] = stdout.split('\n');
resolve(goRoot.trim());
});
});
}

26 changes: 24 additions & 2 deletions test/go.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -681,7 +681,7 @@ It returns the number of bytes written and any write error encountered.
}).then(() => done(), done);
});

test('Workspace Symbols', (done) => {
test('Workspace Symbols', () => {
// This test needs a go project that has vendor folder and vendor packages
// Since the Go extension takes a dependency on the godef tool at github.com/rogpeppe/godef
// which has vendor packages, we are using it here to test the "replace vendor packages with relative path" feature.
Expand All @@ -703,14 +703,36 @@ It returns the number of bytes written and any write error encountered.
}
}
});
let configWithIncludeGoroot = Object.create(vscode.workspace.getConfiguration('go'), {
'gotoSymbol': {
value: {
'includeGoroot': true
}
}
});
let configWithoutIncludeGoroot = Object.create(vscode.workspace.getConfiguration('go'), {
'gotoSymbol': {
value: {
'includeGoroot': false
}
}
});

let withoutIgnoringFolders = getWorkspaceSymbols(workspacePath, 'WinInfo', null, configWithoutIgnoringFolders).then(results => {
assert.equal(results[0].name, 'WinInfo');
assert.equal(results[0].path, path.join(workspacePath, 'vendor/9fans.net/go/acme/acme.go'));
});
let withIgnoringFolders = getWorkspaceSymbols(workspacePath, 'WinInfo', null, configWithIgnoringFolders).then(results => {
assert.equal(results.length, 0);
});
Promise.all([withIgnoringFolders, withoutIgnoringFolders]).then(() => done(), done);
let withoutIncludingGoroot = getWorkspaceSymbols(workspacePath, 'Mutex', null, configWithoutIncludeGoroot).then(results => {
assert.equal(results.length, 0);
});
let withIncludingGoroot = getWorkspaceSymbols(workspacePath, 'Mutex', null, configWithIncludeGoroot).then(results => {
assert(results.some(result => result.name === 'Mutex'));
});

return Promise.all([withIgnoringFolders, withoutIgnoringFolders, withIncludingGoroot, withoutIncludingGoroot]);
});

test('Test Completion', (done) => {
Expand Down