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:
Ramya Rao 2016-10-26 00:54:18 -05:00 коммит произвёл GitHub
Родитель 708b2ad96c
Коммит c35b419585
4 изменённых файлов: 113 добавлений и 92 удалений

Просмотреть файл

@ -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;
});
}

Просмотреть файл

@ -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'];