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

Commit

Permalink
When gotoSymbol.includeGoroot is set, also show symbols from GOROOT (#…
Browse files Browse the repository at this point in the history
…1604)

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

Setting the option to true enables the user to include the standard
library located at GOROOT to be included in the results shown on
"Go To Symbol" - resolves #1567

* Add proper types to empty arrays

* Correctly lookup GOROOT by calling `go env`

* tests

* Move logic for retrieving symbols from goroot a level down
  • Loading branch information
m90 authored and ramya-rao-a committed Apr 5, 2018
1 parent 535ea1b commit c0a489f
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 24 deletions.
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

0 comments on commit c0a489f

Please sign in to comment.