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

Add go.toolCommands which specifies alternate command locations #1297

Merged
merged 10 commits into from
Jun 11, 2018
Binary file modified Go-latest.vsix
Binary file not shown.
43 changes: 43 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -1063,6 +1063,49 @@
"default": [],
"description": "Folder names (not paths) to ignore while using Go to Symbol in Workspace feature",
"scope": "resource"
},
"go.alternateTools": {
"type": "object",
"default": {},
"description": "Alternate tools or alternate paths for the same tools used by the Go extension. Provide either absolute path or the name of the binary in GOPATH/bin, GOROOT/bin or PATH. Useful when you want to use wrapper script for the Go tools or versioned tools from https://gopkg.in.",
"scope": "resource",
"properties": {
"go": {
"type": "string",
"default": "go",
"description": "Alternate tool to use instead of the go binary or alternate path to use for the go binary."
},
"gometalinter": {
"type": "string",
"default": "gometalinter",
"description": "Alternate tool to use instead of the gometalinter binary or alternate path to use for the gometalinter binary."
},
"gocode": {
"type": "string",
"default": "gocode",
"description": "Alternate tool to use instead of the gocode binary or alternate path to use for the gocode binary."
},
"gopkgs": {
"type": "string",
"default": "gopkgs",
"description": "Alternate tool to use instead of the gopkgs binary or alternate path to use for the gopkgs binary."
},
"godoc": {
"type": "string",
"default": "godoc",
"description": "Alternate tool to use instead of the godoc binary or alternate path to use for the godoc binary."
},
"go-outline": {
"type": "string",
"default": "go-outline",
"description": "Alternate tool to use instead of the go-outline binary or alternate path to use for the go-outline binary."
},
"guru": {
"type": "string",
"default": "guru",
"description": "Alternate tool to use instead of the guru binary or alternate path to use for the guru binary."
}
}
}
}
},
Expand Down
6 changes: 3 additions & 3 deletions src/debugAdapter/goDebug.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { existsSync, lstatSync } from 'fs';
import { basename, dirname, extname } from 'path';
import { spawn, ChildProcess, execSync, spawnSync } from 'child_process';
import { Client, RPCConnection } from 'json-rpc2';
import { parseEnvFile, getBinPathWithPreferredGopath, resolveHomeDir, getGoRuntimePath, getInferredGopath, getCurrentGoWorkspaceFromGOPATH, envPath, fixDriveCasingInWindows } from '../goPath';
import { parseEnvFile, getBinPathWithPreferredGopath, resolveHomeDir, getInferredGopath, getCurrentGoWorkspaceFromGOPATH, envPath, fixDriveCasingInWindows } from '../goPath';
import * as logger from 'vscode-debug-logger';

require('console-stamp')(console);
Expand Down Expand Up @@ -309,7 +309,7 @@ class Delve {
if (!!launchArgs.noDebug) {
if (mode === 'debug' && !isProgramDirectory) {
this.noDebug = true;
this.debugProcess = spawn(getGoRuntimePath(), ['run', program], { env });
this.debugProcess = spawn(getBinPathWithPreferredGopath('go', []), ['run', program], { env });
this.debugProcess.stderr.on('data', chunk => {
let str = chunk.toString();
if (this.onstderr) { this.onstderr(str); }
Expand Down Expand Up @@ -350,7 +350,7 @@ class Delve {
return;
}

let dlv = getBinPathWithPreferredGopath('dlv', resolveHomeDir(env['GOPATH']), process.env['GOPATH']);
let dlv = getBinPathWithPreferredGopath('dlv', [resolveHomeDir(env['GOPATH']), process.env['GOPATH']]);

if (!existsSync(dlv)) {
verbose(`Couldnt find dlv at ${process.env['GOPATH']}${env['GOPATH'] ? ', ' + env['GOPATH'] : ''} or ${envPath}`);
Expand Down
5 changes: 2 additions & 3 deletions src/goBrowsePackage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,9 @@

import vscode = require('vscode');
import cp = require('child_process');
import { getGoRuntimePath } from './goPath';
import path = require('path');
import { getAllPackages } from './goPackages';
import { getImportPath, getCurrentGoPath } from './util';
import { getImportPath, getCurrentGoPath, getBinPath } from './util';

export function browsePackages() {
let selectedText = '';
Expand All @@ -31,7 +30,7 @@ export function browsePackages() {
}

function showPackageFiles(pkg: string, showAllPkgsIfPkgNotFound: boolean) {
const goRuntimePath = getGoRuntimePath();
const goRuntimePath = getBinPath('go');
if (!goRuntimePath) {
return vscode.window.showErrorMessage('Could not locate Go path. Make sure you have Go installed');
}
Expand Down
5 changes: 2 additions & 3 deletions src/goCheck.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,10 @@
import vscode = require('vscode');
import path = require('path');
import os = require('os');
import { getGoRuntimePath } from './goPath';
import { getCoverage } from './goCover';
import { outputChannel, diagnosticsStatusBarItem } from './goStatus';
import { goTest } from './testUtils';
import { ICheckResult } from './util';
import { ICheckResult, getBinPath } from './util';
import { goLint } from './goLint';
import { goVet } from './goVet';
import { goBuild } from './goBuild';
Expand Down Expand Up @@ -52,7 +51,7 @@ export function check(fileUri: vscode.Uri, goConfig: vscode.WorkspaceConfigurati
outputChannel.clear();
let runningToolsPromises = [];
let cwd = path.dirname(fileUri.fsPath);
let goRuntimePath = getGoRuntimePath();
let goRuntimePath = getBinPath('go');

if (!goRuntimePath) {
vscode.window.showInformationMessage('Cannot find "go" binary. Update PATH or GOROOT appropriately');
Expand Down
5 changes: 2 additions & 3 deletions src/goGetPackage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@

import vscode = require('vscode');
import cp = require('child_process');
import { getGoRuntimePath } from './goPath';
import { getImportPath, getCurrentGoPath } from './util';
import { getImportPath, getCurrentGoPath, getBinPath } from './util';
import { outputChannel } from './goStatus';

export function goGetPackage() {
Expand All @@ -17,7 +16,7 @@ export function goGetPackage() {
return;
}

const goRuntimePath = getGoRuntimePath();
const goRuntimePath = getBinPath('go');
if (!goRuntimePath) {
return vscode.window.showErrorMessage('Could not locate Go binaries. Make sure you have Go installed');
}
Expand Down
3 changes: 1 addition & 2 deletions src/goImplementations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import path = require('path');
import { byteOffsetAt, getBinPath, canonicalizeGOPATHPrefix, getWorkspaceFolderPath } from './util';
import { promptForMissingTool } from './goInstallTools';
import { getToolsEnvVars } from './util';
import { getGoRuntimePath } from './goPath';

interface GoListOutput {
Dir: string;
Expand Down Expand Up @@ -43,7 +42,7 @@ export class GoImplementationProvider implements vscode.ImplementationProvider {
return resolve(null);
}
let env = getToolsEnvVars();
let listProcess = cp.execFile(getGoRuntimePath(), ['list', '-e', '-json'], { cwd: root, env }, (err, stdout, stderr) => {
let listProcess = cp.execFile(getBinPath('go'), ['list', '-e', '-json'], { cwd: root, env }, (err, stdout, stderr) => {
if (err) {
return reject(err);
}
Expand Down
6 changes: 3 additions & 3 deletions src/goInstall.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import path = require('path');
import vscode = require('vscode');
import { getToolsEnvVars, getCurrentGoPath } from './util';
import { getToolsEnvVars, getCurrentGoPath, getBinPath } from './util';
import { outputChannel } from './goStatus';
import { getCurrentGoWorkspaceFromGOPATH, getGoRuntimePath } from './goPath';
import { getCurrentGoWorkspaceFromGOPATH } from './goPath';
import cp = require('child_process');

export function installCurrentPackage() {
Expand All @@ -16,7 +16,7 @@ export function installCurrentPackage() {
return;
}

let goRuntimePath = getGoRuntimePath();
let goRuntimePath = getBinPath('go');
if (!goRuntimePath) {
vscode.window.showInformationMessage('Cannot find "go" binary. Update PATH or GOROOT appropriately');
return;
Expand Down
8 changes: 3 additions & 5 deletions src/goInstallTools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@ import vscode = require('vscode');
import fs = require('fs');
import path = require('path');
import cp = require('child_process');
import { showGoStatus, hideGoStatus } from './goStatus';
import { getGoRuntimePath } from './goPath';
import { outputChannel } from './goStatus';
import { showGoStatus, hideGoStatus, outputChannel } from './goStatus';
import { getBinPath, getToolsGopath, getGoVersion, SemVersion, isVendorSupported, getCurrentGoPath, resolvePath } from './util';
import { goLiveErrorsEnabled } from './goLiveErrors';

Expand Down Expand Up @@ -201,7 +199,7 @@ export function promptForUpdatingTool(tool: string) {
* @param string[] array of tool names to be installed
*/
function installTools(goVersion: SemVersion, missing?: string[]) {
let goRuntimePath = getGoRuntimePath();
let goRuntimePath = getBinPath('go');
if (!goRuntimePath) {
vscode.window.showInformationMessage('Cannot find "go" binary. Update PATH or GOROOT appropriately');
return;
Expand Down Expand Up @@ -316,7 +314,7 @@ export function updateGoPathGoRootFromConfig(): Promise<void> {
}

// If GOPATH is still not set, then use the one from `go env`
let goRuntimePath = getGoRuntimePath();
let goRuntimePath = getBinPath('go');
if (!goRuntimePath) {
return Promise.reject(new Error('Cannot find "go" binary. Update PATH or GOROOT appropriately'));
}
Expand Down
6 changes: 4 additions & 2 deletions src/goMain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -446,7 +446,8 @@ function sendTelemetryEventForConfig(goConfig: vscode.WorkspaceConfiguration) {
"removeTags": { "classification": "CustomerContent", "purpose": "FeatureInsight" },
"editorContextMenuCommands": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"liveErrors": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"codeLens": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
"codeLens": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"alternateTools": { "classification": "CustomerContent", "purpose": "FeatureInsight" }
}
*/
sendTelemetryEvent('goConfig', {
Expand Down Expand Up @@ -484,7 +485,8 @@ function sendTelemetryEventForConfig(goConfig: vscode.WorkspaceConfiguration) {
removeTags: JSON.stringify(goConfig['removeTags']),
editorContextMenuCommands: JSON.stringify(goConfig['editorContextMenuCommands']),
liveErrors: JSON.stringify(goConfig['liveErrors']),
codeLens: JSON.stringify(goConfig['enableCodeLens'])
codeLens: JSON.stringify(goConfig['enableCodeLens']),
alternateTools: JSON.stringify(goConfig['alternateTools'])
});
}

Expand Down
4 changes: 2 additions & 2 deletions src/goPackages.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import vscode = require('vscode');
import cp = require('child_process');
import path = require('path');
import { getGoRuntimePath, getCurrentGoWorkspaceFromGOPATH, fixDriveCasingInWindows } from './goPath';
import { getCurrentGoWorkspaceFromGOPATH, fixDriveCasingInWindows } from './goPath';
import { isVendorSupported, getCurrentGoPath, getToolsEnvVars, getGoVersion, getBinPath, SemVersion, sendTelemetryEvent } from './util';
import { promptForMissingTool, promptForUpdatingTool } from './goInstallTools';

Expand Down Expand Up @@ -242,7 +242,7 @@ function getRelativePackagePath(currentFileDirPath: string, currentWorkspace: st
* Returns import paths for all packages under given folder (vendor will be excluded)
*/
export function getNonVendorPackages(folderPath: string): Promise<string[]> {
let goRuntimePath = getGoRuntimePath();
let goRuntimePath = getBinPath('go');

if (!goRuntimePath) {
vscode.window.showInformationMessage('Cannot find "go" binary. Update PATH or GOROOT appropriately');
Expand Down
65 changes: 27 additions & 38 deletions src/goPath.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import path = require('path');
import os = require('os');

let binPathCache: { [bin: string]: string; } = {};
let runtimePathCache: string = '';

export const envPath = process.env['PATH'] || (process.platform === 'win32' ? process.env['Path'] : null);

export function getBinPathFromEnvVar(toolName: string, envVarValue: string, appendBinToPath: boolean): string {
Expand All @@ -23,22 +23,28 @@ export function getBinPathFromEnvVar(toolName: string, envVarValue: string, appe
for (let i = 0; i < paths.length; i++) {
let binpath = path.join(paths[i], appendBinToPath ? 'bin' : '', toolName);
if (fileExists(binpath)) {
binPathCache[toolName] = binpath;
return binpath;
}
}
}
return null;
}

export function getBinPathWithPreferredGopath(binname: string, ...preferredGopaths) {
if (binPathCache[correctBinname(binname)]) return binPathCache[correctBinname(binname)];
export function getBinPathWithPreferredGopath(toolName: string, preferredGopaths: string[], alternateTools?: { [key: string]: string; }) {
if (binPathCache[toolName]) return binPathCache[toolName];

if (alternateTools && alternateTools[toolName] && path.isAbsolute(alternateTools[toolName]) && fileExists(alternateTools[toolName])) {
binPathCache[toolName] = alternateTools[toolName];
return alternateTools[toolName];
}

const binname = (alternateTools && alternateTools[toolName] && !path.isAbsolute(alternateTools[toolName])) ? alternateTools[toolName] : toolName;
for (let i = 0; i < preferredGopaths.length; i++) {
if (typeof preferredGopaths[i] === 'string') {
// Search in the preferred GOPATH workspace's bin folder
let pathFrompreferredGoPath = getBinPathFromEnvVar(binname, preferredGopaths[i], true);
if (pathFrompreferredGoPath) {
binPathCache[toolName] = pathFrompreferredGoPath;
return pathFrompreferredGoPath;
}
}
Expand All @@ -47,53 +53,36 @@ export function getBinPathWithPreferredGopath(binname: string, ...preferredGopat
// Then search PATH parts
let pathFromPath = getBinPathFromEnvVar(binname, envPath, false);
if (pathFromPath) {
binPathCache[toolName] = pathFromPath;
return pathFromPath;
}

// Finally check GOROOT just in case
let pathFromGoRoot = getBinPathFromEnvVar(binname, process.env['GOROOT'], true);
if (pathFromGoRoot) {
binPathCache[toolName] = pathFromGoRoot;
return pathFromGoRoot;
}

// Check default path for go
if (toolName === 'go') {
let defaultPathForGo = process.platform === 'win32' ? 'C:\\Go\\bin\\go.exe' : '/usr/local/go/bin/go';
if (fileExists(defaultPathForGo)) {
binPathCache[toolName] = defaultPathForGo;
return defaultPathForGo;
}
return;
}

// Else return the binary name directly (this will likely always fail downstream)
return binname;
return toolName;
}

function correctBinname(binname: string) {
function correctBinname(toolName: string) {
if (process.platform === 'win32')
return binname + '.exe';
return toolName + '.exe';
else
return binname;
}

/**
* Returns Go runtime binary path.
*
* @return the path to the Go binary.
*/
export function getGoRuntimePath(): string {
if (runtimePathCache) return runtimePathCache;
let correctBinNameGo = correctBinname('go');
if (process.env['GOROOT']) {
let runtimePathFromGoRoot = path.join(process.env['GOROOT'], 'bin', correctBinNameGo);
if (fileExists(runtimePathFromGoRoot)) {
runtimePathCache = runtimePathFromGoRoot;
return runtimePathCache;
}
}

if (envPath) {
let pathparts = (<string>envPath).split(path.delimiter);
runtimePathCache = pathparts.map(dir => path.join(dir, correctBinNameGo)).filter(candidate => fileExists(candidate))[0];
}
if (!runtimePathCache) {
let defaultPathForGo = process.platform === 'win32' ? 'C:\\Go\\bin\\go.exe' : '/usr/local/go/bin/go';
if (fileExists(defaultPathForGo)) {
runtimePathCache = defaultPathForGo;
}
}
return runtimePathCache;
return toolName;
}

function fileExists(filePath: string): boolean {
Expand Down Expand Up @@ -185,7 +174,7 @@ export function getCurrentGoWorkspaceFromGOPATH(gopath: string, currentFileDirPa
// both parent & child workspace in the nested workspaces pair can make it inside the above if block
// Therefore, the below check will take longer (more specific to current file) of the two
if (possibleCurrentWorkspace.length > currentWorkspace.length) {
currentWorkspace = currentFileDirPath.substr(0, possibleCurrentWorkspace.length);
currentWorkspace = currentFileDirPath.substr(0, possibleCurrentWorkspace.length);
}
}
}
Expand Down
3 changes: 1 addition & 2 deletions src/goSymbol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
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 @@ -123,7 +122,7 @@ function callGoSymbols(args: string[], token: vscode.CancellationToken): Promise
}

function getGoroot(): Promise<string> {
let goExecutable = getGoRuntimePath();
let goExecutable = getBinPath('go');
if (!goExecutable) {
return Promise.reject(new Error('Cannot find "go" binary. Update PATH or GOROOT appropriately'));
}
Expand Down
6 changes: 3 additions & 3 deletions src/testUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import cp = require('child_process');
import path = require('path');
import vscode = require('vscode');
import util = require('util');
import { parseEnvFile, getGoRuntimePath, getCurrentGoWorkspaceFromGOPATH } from './goPath';
import { getToolsEnvVars, getGoVersion, LineBuffer, SemVersion, resolvePath, getCurrentGoPath } from './util';
import { parseEnvFile, getCurrentGoWorkspaceFromGOPATH } from './goPath';
import { getToolsEnvVars, getGoVersion, LineBuffer, SemVersion, resolvePath, getCurrentGoPath, getBinPath } from './util';
import { GoDocumentSymbolProvider } from './goOutline';
import { getNonVendorPackages } from './goPackages';

Expand Down Expand Up @@ -151,7 +151,7 @@ export function goTest(testconfig: TestConfig): Thenable<boolean> {
}

let testEnvVars = getTestEnvVars(testconfig.goConfig);
let goRuntimePath = getGoRuntimePath();
let goRuntimePath = getBinPath('go');

if (!goRuntimePath) {
vscode.window.showInformationMessage('Cannot find "go" binary. Update PATH or GOROOT appropriately');
Expand Down
Loading