Fix for when Go is used from source without release tag (#549)
* Fix for when Go is used from source without release tag * vendoring can be disabled in 1.6
This commit is contained in:
Родитель
708b2ad96c
Коммит
c35b419585
|
@ -8,9 +8,9 @@
|
|||
import vscode = require('vscode');
|
||||
import cp = require('child_process');
|
||||
import { getBinPath } from './goPath';
|
||||
import { parseFilePrelude } from './util';
|
||||
import { parseFilePrelude, isVendorSupported } from './util';
|
||||
import { documentSymbols } from './goOutline';
|
||||
import { promptForMissingTool, isVendorSupported } from './goInstallTools';
|
||||
import { promptForMissingTool } from './goInstallTools';
|
||||
import path = require('path');
|
||||
|
||||
export function listPackages(excludeImportedPkgs: boolean = false): Thenable<string[]> {
|
||||
|
|
|
@ -11,19 +11,13 @@ import path = require('path');
|
|||
import os = require('os');
|
||||
import cp = require('child_process');
|
||||
import { showGoStatus, hideGoStatus } from './goStatus';
|
||||
import { getBinPath, getGoRuntimePath } from './goPath';
|
||||
import { getBinPath } from './goPath';
|
||||
import { outputChannel } from './goStatus';
|
||||
import { getGoVersion, SemVersion, isVendorSupported } from './util';
|
||||
|
||||
interface SemVersion {
|
||||
major: number;
|
||||
minor: number;
|
||||
}
|
||||
|
||||
let goVersion: SemVersion = null;
|
||||
let vendorSupport: boolean = null;
|
||||
let updatesDeclinedTools: string[] = [];
|
||||
|
||||
function getTools(): { [key: string]: string } {
|
||||
function getTools(goVersion: SemVersion): { [key: string]: string } {
|
||||
let goConfig = vscode.workspace.getConfiguration('go');
|
||||
let tools: { [key: string]: string } = {
|
||||
'gocode': 'github.com/nsf/gocode',
|
||||
|
@ -42,8 +36,8 @@ function getTools(): { [key: string]: string } {
|
|||
tools['goreturns'] = 'sourcegraph.com/sqs/goreturns';
|
||||
}
|
||||
|
||||
// golint is no longer supported in go1.5
|
||||
if (goVersion && (goVersion.major > 1 || (goVersion.major === 1 && goVersion.minor > 5))) {
|
||||
// golint and gotests are not supported in go1.5
|
||||
if (!goVersion || (goVersion.major > 1 || (goVersion.major === 1 && goVersion.minor > 5))) {
|
||||
tools['golint'] = 'github.com/golang/lint/golint';
|
||||
tools['gotests'] = 'github.com/cweill/gotests/...';
|
||||
}
|
||||
|
@ -51,13 +45,13 @@ function getTools(): { [key: string]: string } {
|
|||
}
|
||||
|
||||
export function installAllTools() {
|
||||
getGoVersion().then(() => installTools());
|
||||
getGoVersion().then((goVersion) => installTools(goVersion));
|
||||
}
|
||||
|
||||
export function promptForMissingTool(tool: string) {
|
||||
|
||||
getGoVersion().then(() => {
|
||||
if (goVersion.major === 1 && goVersion.minor < 6) {
|
||||
getGoVersion().then((goVersion) => {
|
||||
if (goVersion && goVersion.major === 1 && goVersion.minor < 6) {
|
||||
if (tool === 'golint') {
|
||||
vscode.window.showInformationMessage('golint no longer supports go1.5, update your settings to use gometalinter as go.lintTool and install gometalinter');
|
||||
return;
|
||||
|
@ -68,11 +62,11 @@ export function promptForMissingTool(tool: string) {
|
|||
}
|
||||
}
|
||||
|
||||
vscode.window.showInformationMessage(`The "${tool}" command is not available. Use "go get -v ${getTools()[tool]}" to install.`, 'Install All', 'Install').then(selected => {
|
||||
vscode.window.showInformationMessage(`The "${tool}" command is not available. Use "go get -v ${getTools(goVersion)[tool]}" to install.`, 'Install All', 'Install').then(selected => {
|
||||
if (selected === 'Install') {
|
||||
installTools([tool]);
|
||||
installTools(goVersion, [tool]);
|
||||
} else if (selected === 'Install All') {
|
||||
getMissingTools().then(installTools);
|
||||
getMissingTools(goVersion).then((missing) => installTools(goVersion, missing));
|
||||
hideGoStatus();
|
||||
}
|
||||
});
|
||||
|
@ -84,12 +78,14 @@ export function promptForUpdatingTool(tool: string) {
|
|||
if (updatesDeclinedTools.indexOf(tool) > -1) {
|
||||
return;
|
||||
}
|
||||
vscode.window.showInformationMessage(`The Go extension is better with the latest version of "${tool}". Use "go get -u -v ${getTools()[tool]}" to update`, 'Update').then(selected => {
|
||||
if (selected === 'Update') {
|
||||
installTools([tool]);
|
||||
} else {
|
||||
updatesDeclinedTools.push(tool);
|
||||
}
|
||||
getGoVersion().then((goVersion) => {
|
||||
vscode.window.showInformationMessage(`The Go extension is better with the latest version of "${tool}". Use "go get -u -v ${getTools(goVersion)[tool]}" to update`, 'Update').then(selected => {
|
||||
if (selected === 'Update') {
|
||||
installTools(goVersion, [tool]);
|
||||
} else {
|
||||
updatesDeclinedTools.push(tool);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -98,8 +94,8 @@ export function promptForUpdatingTool(tool: string) {
|
|||
*
|
||||
* @param string[] array of tool names to be installed
|
||||
*/
|
||||
function installTools(missing?: string[]) {
|
||||
let tools = getTools();
|
||||
function installTools(goVersion: SemVersion, missing?: string[]) {
|
||||
let tools = getTools(goVersion);
|
||||
if (!missing) {
|
||||
missing = Object.keys(tools);
|
||||
}
|
||||
|
@ -169,21 +165,24 @@ export function setupGoPathAndOfferToInstallTools() {
|
|||
return;
|
||||
}
|
||||
|
||||
getMissingTools().then(missing => {
|
||||
if (missing.length > 0) {
|
||||
showGoStatus('Analysis Tools Missing', 'go.promptforinstall', 'Not all Go tools are available on the GOPATH');
|
||||
vscode.commands.registerCommand('go.promptforinstall', () => {
|
||||
promptForInstall(missing);
|
||||
hideGoStatus();
|
||||
});
|
||||
}
|
||||
getGoVersion().then(goVersion => {
|
||||
getMissingTools(goVersion).then(missing => {
|
||||
if (missing.length > 0) {
|
||||
showGoStatus('Analysis Tools Missing', 'go.promptforinstall', 'Not all Go tools are available on the GOPATH');
|
||||
vscode.commands.registerCommand('go.promptforinstall', () => {
|
||||
promptForInstall(goVersion, missing);
|
||||
hideGoStatus();
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
function promptForInstall(missing: string[]) {
|
||||
|
||||
function promptForInstall(goVersion: SemVersion, missing: string[]) {
|
||||
let item = {
|
||||
title: 'Install',
|
||||
command() {
|
||||
installTools(missing);
|
||||
installTools(goVersion, missing);
|
||||
}
|
||||
};
|
||||
vscode.window.showInformationMessage('Some Go analysis tools are missing from your GOPATH. Would you like to install them?', item).then(selection => {
|
||||
|
@ -194,65 +193,22 @@ export function setupGoPathAndOfferToInstallTools() {
|
|||
}
|
||||
}
|
||||
|
||||
function getMissingTools(): Promise<string[]> {
|
||||
return getGoVersion().then(() => {
|
||||
let keys = Object.keys(getTools());
|
||||
return Promise.all<string>(keys.map(tool => new Promise<string>((resolve, reject) => {
|
||||
let toolPath = getBinPath(tool);
|
||||
fs.exists(toolPath, exists => {
|
||||
resolve(exists ? null : tool);
|
||||
});
|
||||
}))).then(res => {
|
||||
let missing = res.filter(x => x != null);
|
||||
return missing;
|
||||
function getMissingTools(goVersion: SemVersion): Promise<string[]> {
|
||||
let keys = Object.keys(getTools(goVersion));
|
||||
return Promise.all<string>(keys.map(tool => new Promise<string>((resolve, reject) => {
|
||||
let toolPath = getBinPath(tool);
|
||||
fs.exists(toolPath, exists => {
|
||||
resolve(exists ? null : tool);
|
||||
});
|
||||
}))).then(res => {
|
||||
let missing = res.filter(x => x != null);
|
||||
return missing;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
export function getGoVersion(): Promise<SemVersion> {
|
||||
let goRuntimePath = getGoRuntimePath();
|
||||
|
||||
if (!goRuntimePath) {
|
||||
vscode.window.showInformationMessage('Cannot find "go" binary. Update PATH or GOROOT appropriately');
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
|
||||
if (goVersion) {
|
||||
return Promise.resolve(goVersion);
|
||||
}
|
||||
return new Promise<SemVersion>((resolve, reject) => {
|
||||
cp.execFile(goRuntimePath, ['version'], {}, (err, stdout, stderr) => {
|
||||
let matches = /go version go(\d).(\d).*/.exec(stdout);
|
||||
if (matches) {
|
||||
goVersion = {
|
||||
major: parseInt(matches[1]),
|
||||
minor: parseInt(matches[2])
|
||||
};
|
||||
}
|
||||
return resolve(goVersion);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export function isVendorSupported(): Promise<boolean> {
|
||||
if (vendorSupport != null) {
|
||||
return Promise.resolve(vendorSupport);
|
||||
}
|
||||
return getGoVersion().then(version => {
|
||||
switch (version.major) {
|
||||
case 0:
|
||||
vendorSupport = false;
|
||||
break;
|
||||
case 1:
|
||||
vendorSupport = (version.minor > 5 || (version.minor === 5 && process.env['GO15VENDOREXPERIMENT'] === '1')) ? true : false;
|
||||
break;
|
||||
default:
|
||||
vendorSupport = true;
|
||||
break;
|
||||
}
|
||||
return vendorSupport;
|
||||
});
|
||||
}
|
||||
|
||||
|
|
68
src/util.ts
68
src/util.ts
|
@ -3,8 +3,18 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------*/
|
||||
|
||||
import { TextDocument, Position } from 'vscode';
|
||||
import { TextDocument, Position, window } from 'vscode';
|
||||
import path = require('path');
|
||||
import { getGoRuntimePath } from './goPath';
|
||||
import cp = require('child_process');
|
||||
|
||||
export interface SemVersion {
|
||||
major: number;
|
||||
minor: number;
|
||||
}
|
||||
|
||||
let goVersion: SemVersion = null;
|
||||
let vendorSupport: boolean = null;
|
||||
|
||||
export function byteOffsetAt(document: TextDocument, position: Position): number {
|
||||
let offset = document.offsetAt(position);
|
||||
|
@ -96,6 +106,62 @@ export function canonicalizeGOPATHPrefix(filename: string): string {
|
|||
return filename;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets version of Go based on the output of the command `go version`.
|
||||
* Returns null if go is being used from source/tip in which case `go version` will not return release tag like go1.6.3
|
||||
*/
|
||||
export function getGoVersion(): Promise<SemVersion> {
|
||||
let goRuntimePath = getGoRuntimePath();
|
||||
|
||||
if (!goRuntimePath) {
|
||||
window.showInformationMessage('Cannot find "go" binary. Update PATH or GOROOT appropriately');
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
|
||||
if (goVersion) {
|
||||
return Promise.resolve(goVersion);
|
||||
}
|
||||
return new Promise<SemVersion>((resolve, reject) => {
|
||||
cp.execFile(goRuntimePath, ['version'], {}, (err, stdout, stderr) => {
|
||||
let matches = /go version go(\d).(\d).*/.exec(stdout);
|
||||
if (matches) {
|
||||
goVersion = {
|
||||
major: parseInt(matches[1]),
|
||||
minor: parseInt(matches[2])
|
||||
};
|
||||
}
|
||||
return resolve(goVersion);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns boolean denoting if current version of Go supports vendoring
|
||||
*/
|
||||
export function isVendorSupported(): Promise<boolean> {
|
||||
if (vendorSupport != null) {
|
||||
return Promise.resolve(vendorSupport);
|
||||
}
|
||||
return getGoVersion().then(version => {
|
||||
if (!version) {
|
||||
return process.env['GO15VENDOREXPERIMENT'] === '0' ? false : true;
|
||||
}
|
||||
|
||||
switch (version.major) {
|
||||
case 0:
|
||||
vendorSupport = false;
|
||||
break;
|
||||
case 1:
|
||||
vendorSupport = (version.minor > 6 || ((version.minor === 5 || version.minor === 6) && process.env['GO15VENDOREXPERIMENT'] === '1')) ? true : false;
|
||||
break;
|
||||
default:
|
||||
vendorSupport = true;
|
||||
break;
|
||||
}
|
||||
return vendorSupport;
|
||||
});
|
||||
}
|
||||
|
||||
export function random(low: number, high: number): number {
|
||||
return Math.floor(Math.random() * (high - low) + low);
|
||||
}
|
||||
|
|
|
@ -15,12 +15,11 @@ import cp = require('child_process');
|
|||
import { getEditsFromUnifiedDiffStr, getEdits } from '../src/diffUtils';
|
||||
import jsDiff = require('diff');
|
||||
import { testCurrentFile } from '../src/goTest';
|
||||
import { getGoVersion } from '../src/goInstallTools';
|
||||
import { getGoVersion, isVendorSupported } from '../src/util';
|
||||
import { documentSymbols } from '../src/goOutline';
|
||||
import { listPackages } from '../src/goImport';
|
||||
import { generateTestCurrentFile, generateTestCurrentPackage } from '../src/goGenerateTests';
|
||||
import { getBinPath } from '../src/goPath';
|
||||
import { isVendorSupported } from '../src/goInstallTools';
|
||||
|
||||
suite('Go Extension Tests', () => {
|
||||
let gopath = process.env['GOPATH'];
|
||||
|
|
Загрузка…
Ссылка в новой задаче