blob: 79097a358e3dbfdf884a48b9c9af5e599d021fb2 [file] [log] [blame]
/*---------------------------------------------------------
* Copyright (C) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See LICENSE in the project root for license information.
*--------------------------------------------------------*/
'use strict';
import cp = require('child_process');
import path = require('path');
import vscode = require('vscode');
import { getAllPackages } from './goPackages';
import { getBinPath, getCurrentGoPath, getImportPath } from './util';
import { envPath, getCurrentGoRoot } from './utils/goPath';
export function browsePackages() {
let workDir = '';
let selectedText = '';
const editor = vscode.window.activeTextEditor;
if (editor) {
const currentUri = editor.document.uri;
workDir = path.dirname(currentUri.fsPath);
const selection = editor.selection;
if (!selection.isEmpty) {
// get selected text
selectedText = editor.document.getText(selection);
} else {
// if selection is empty, then get the whole line the cursor is currently on.
selectedText = editor.document.lineAt(selection.active.line).text;
}
selectedText = getImportPath(selectedText) || selectedText.trim();
} else if (vscode.workspace.workspaceFolders && vscode.workspace.workspaceFolders.length === 1) {
const currentUri = vscode.workspace.workspaceFolders[0].uri;
workDir = currentUri.fsPath;
}
showPackageFiles(selectedText, true, workDir);
}
function showPackageFiles(pkg: string, showAllPkgsIfPkgNotFound: boolean, workDir: string) {
const goRuntimePath = getBinPath('go');
if (!goRuntimePath) {
return vscode.window.showErrorMessage(
`Failed to run "go list" to fetch packages as the "go" binary cannot be found in either GOROOT(${getCurrentGoRoot()}) or PATH(${envPath})`
);
}
if (!pkg && showAllPkgsIfPkgNotFound) {
return showPackageList(workDir);
}
const options: { [key: string]: any } = {
env: Object.assign({}, process.env, { GOPATH: getCurrentGoPath() })
};
if (workDir) {
options['cwd'] = workDir;
}
cp.execFile(
goRuntimePath,
['list', '-f', '{{.Dir}}:{{.GoFiles}}:{{.TestGoFiles}}:{{.XTestGoFiles}}', pkg],
options,
(err, stdout, stderr) => {
if (!stdout || stdout.indexOf(':') === -1) {
if (showAllPkgsIfPkgNotFound) {
return showPackageList(workDir);
}
return;
}
const matches = stdout && stdout.match(/(.*):\[(.*)\]:\[(.*)\]:\[(.*)\]/);
if (matches) {
const dir = matches[1];
let files = matches[2] ? matches[2].split(' ') : [];
const testfiles = matches[3] ? matches[3].split(' ') : [];
const xtestfiles = matches[4] ? matches[4].split(' ') : [];
files = files.concat(testfiles);
files = files.concat(xtestfiles);
vscode.window.showQuickPick(files, { placeHolder: `Below are Go files from ${pkg}` }).then((file) => {
// if user abandoned list, file will be null and path.join will error out.
// therefore return.
if (!file) {
return;
}
vscode.workspace.openTextDocument(path.join(dir, file)).then((document) => {
vscode.window.showTextDocument(document);
});
});
}
}
);
}
function showPackageList(workDir: string) {
return getAllPackages(workDir).then((pkgMap) => {
const pkgs: string[] = Array.from(pkgMap.keys());
if (pkgs.length === 0) {
return vscode.window.showErrorMessage(
'Could not find packages. Ensure `gopkgs -format {{.Name}};{{.ImportPath}}` runs successfully.'
);
}
vscode.window
.showQuickPick(pkgs.sort(), { placeHolder: 'Select a package to browse' })
.then((pkgFromDropdown) => {
if (!pkgFromDropdown) {
return;
}
showPackageFiles(pkgFromDropdown, false, workDir);
});
});
}