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

Update installTools logic to support optional tools #509

Merged
merged 5 commits into from
Oct 6, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ install:
- npm run vscode:prepublish
- go get -u -v github.com/nsf/gocode
- go get -u -v github.com/rogpeppe/godef
- go get -u -v github.com/golang/lint/golint
- if [[ "$(go version)" =~ "go version go1.5" ]]; then echo cannot get golint; else go get -u -v github.com/golang/lint/golint; fi
- go get -u -v github.com/lukehoban/go-outline
- go get -u -v sourcegraph.com/sqs/goreturns
- go get -u -v golang.org/x/tools/cmd/gorename
Expand Down
116 changes: 87 additions & 29 deletions src/goInstallTools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,38 +11,76 @@ import path = require('path');
import os = require('os');
import cp = require('child_process');
import { showGoStatus, hideGoStatus } from './goStatus';
import { getBinPath } from './goPath';
import { getBinPath, getGoRuntimePath } from './goPath';
import { outputChannel } from './goStatus';

let tools: { [key: string]: string } = {
'gocode': 'github.com/nsf/gocode',
'goreturns': 'sourcegraph.com/sqs/goreturns',
'gopkgs': 'github.com/tpng/gopkgs',
'godef': 'github.com/rogpeppe/godef',
'golint': 'github.com/golang/lint/golint',
'go-outline': 'github.com/lukehoban/go-outline',
'go-symbols': 'github.com/newhook/go-symbols',
'guru': 'golang.org/x/tools/cmd/guru',
'gorename': 'golang.org/x/tools/cmd/gorename',
'goimports': 'golang.org/x/tools/cmd/goimports'
};
interface SemVersion {
major: number;
minor: number;
}

let goVersion: SemVersion = null;

function getTools(): { [key: string]: string } {
let goConfig = vscode.workspace.getConfiguration('go');
let tools: { [key: string]: string } = {
'gocode': 'github.com/nsf/gocode',
'gopkgs': 'github.com/tpng/gopkgs',
'godef': 'github.com/rogpeppe/godef',
'go-outline': 'github.com/lukehoban/go-outline',
'go-symbols': 'github.com/newhook/go-symbols',
'guru': 'golang.org/x/tools/cmd/guru',
'gorename': 'golang.org/x/tools/cmd/gorename'
};

// Install the formattool that was chosen by the user
if (goConfig['formatTool'] === 'goimports') {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is gofmt included with Go?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes

tools['goimports'] = 'golang.org/x/tools/cmd/goimports';
} else if (goConfig['formatTool'] === 'goreturns') {
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))) {
tools['golint'] = 'github.com/golang/lint/golint';
}
return tools;
}

export function installAllTools() {
installTools(Object.keys(tools));
getGoVersion().then(() => installTools());
}

export function promptForMissingTool(tool: string) {
vscode.window.showInformationMessage(`The "${tool}" command is not available. Use "go get -v ${tools[tool]}" to install.`, 'Install All', 'Install').then(selected => {
if (selected === 'Install') {
installTools([tool]);
} else if (selected === 'Install All') {
getMissingTools().then(installTools);
hideGoStatus();

getGoVersion().then(() => {
if (tool === 'golint' && goVersion.major === 1 && goVersion.minor < 6) {
vscode.window.showInformationMessage('golint no longer supports go1.5, update your settings to use gometalinter as go.lintTool and install gometalinter');
return;
}

vscode.window.showInformationMessage(`The "${tool}" command is not available. Use "go get -v ${getTools()[tool]}" to install.`, 'Install All', 'Install').then(selected => {
if (selected === 'Install') {
installTools([tool]);
} else if (selected === 'Install All') {
getMissingTools().then(installTools);
hideGoStatus();
}
});
});

}

export function installTools(missing: string[]) {
/**
* Installs given array of missing tools. If no input is given, the all tools are installed
*
* @param string[] array of tool names to be installed
*/
function installTools(missing?: string[]) {
let tools = getTools();
if (!missing) {
missing = Object.keys(tools);
}
outputChannel.show();
outputChannel.clear();
outputChannel.appendLine('Installing ' + missing.length + ' tools');
Expand Down Expand Up @@ -134,14 +172,34 @@ export function setupGoPathAndOfferToInstallTools() {
}

function getMissingTools(): Promise<string[]> {
let keys = Object.keys(tools);
return Promise.all<string>(keys.map(tool => new Promise<string>((resolve, reject) => {
let toolPath = getBinPath(tool);
fs.exists(toolPath, exists => {
resolve(exists ? null : tool);
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;
});
}))).then(res => {
let missing = res.filter(x => x != null);
return missing;
});
}

export function getGoVersion(): Promise<SemVersion> {
if (goVersion) {
return Promise.resolve(goVersion);
}
return new Promise<SemVersion>((resolve, reject) => {
cp.execFile(getGoRuntimePath(), ['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);
});
});
}
23 changes: 16 additions & 7 deletions test/go.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ 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';

suite('Go Extension Tests', () => {
let gopath = process.env['GOPATH'];
Expand Down Expand Up @@ -122,15 +123,23 @@ encountered.
// { line: 7, severity: 'warning', msg: 'no formatting directive in Printf call' },
{ line: 11, severity: 'error', msg: 'undefined: prin' },
];
check(path.join(fixturePath, 'errorsTest', 'errors.go'), config).then(diagnostics => {
let sortedDiagnostics = diagnostics.sort((a, b) => a.line - b.line);
for (let i in expected) {
assert.equal(sortedDiagnostics[i].line, expected[i].line);
assert.equal(sortedDiagnostics[i].severity, expected[i].severity);
assert.equal(sortedDiagnostics[i].msg, expected[i].msg);
getGoVersion().then(version => {
if (version.major === 1 && version.minor === 5) {
// golint is not supported in Go 1.5, so skip the test
return Promise.resolve();
}
assert.equal(sortedDiagnostics.length, expected.length, `too many errors ${JSON.stringify(sortedDiagnostics)}`);
return check(path.join(fixturePath, 'errorsTest', 'errors.go'), config).then(diagnostics => {
let sortedDiagnostics = diagnostics.sort((a, b) => a.line - b.line);
for (let i in expected) {
assert.equal(sortedDiagnostics[i].line, expected[i].line);
assert.equal(sortedDiagnostics[i].severity, expected[i].severity);
assert.equal(sortedDiagnostics[i].msg, expected[i].msg);
}
assert.equal(sortedDiagnostics.length, expected.length, `too many errors ${JSON.stringify(sortedDiagnostics)}`);
});

}).then(() => done(), done);

});

test('Gometalinter error checking', (done) => {
Expand Down