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

Commit

Permalink
Merge branch 'master' into separate-gotools-path
Browse files Browse the repository at this point in the history
  • Loading branch information
ramya-rao-a authored Jan 21, 2017
2 parents be6d94b + 4ead817 commit 8cce7d1
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 22 deletions.
44 changes: 27 additions & 17 deletions src/goCheck.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,34 @@ export interface ICheckResult {
severity: string;
}

function runTool(cmd: string, args: string[], cwd: string, severity: string, useStdErr: boolean, toolName: string, notFoundError?: string) {
/**
* Runs given Go tool and returns errors/warnings that can be fed to the Problems Matcher
* @param args Arguments to be passed while running given tool
* @param cwd cwd that will passed in the env object while running given tool
* @param serverity error or warning
* @param useStdErr If true, the stderr of the output of the given tool will be used, else stdout will be used
* @param toolName The name of the Go tool to run. If none is provided, the go runtime itself is used
* @param printUnexpectedOutput If true, then output that doesnt match expected format is printed to the output channel
*/
function runTool(args: string[], cwd: string, severity: string, useStdErr: boolean, toolName: string, printUnexpectedOutput?: boolean): Promise<ICheckResult[]> {
let goRuntimePath = getGoRuntimePath();
let cmd = toolName ? getBinPath(toolName) : goRuntimePath;
return new Promise((resolve, reject) => {
cp.execFile(cmd, args, { cwd: cwd }, (err, stdout, stderr) => {
try {
if (err && (<any>err).code === 'ENOENT') {
if (toolName) {
promptForMissingTool(toolName);
} else {
vscode.window.showInformationMessage(notFoundError);
vscode.window.showInformationMessage(`Cannot find ${goRuntimePath}`);
}
return resolve([]);
}
if (err && stderr && !useStdErr) {
outputChannel.appendLine(['Error while running tool:', cmd, ...args].join(' '));
outputChannel.appendLine(stderr);
return resolve([]);
}
let lines = (useStdErr ? stderr : stdout).toString().split('\n');
outputChannel.appendLine(['Finished running tool:', cmd, ...args].join(' '));

Expand All @@ -45,7 +61,10 @@ function runTool(cmd: string, args: string[], cwd: string, severity: string, use
continue;
}
let match = /^([^:]*: )?((.:)?[^:]*):(\d+)(:(\d+)?)?:(?:\w+:)? (.*)$/.exec(lines[i]);
if (!match) continue;
if (!match) {
if (printUnexpectedOutput) outputChannel.appendLine(lines[i]);
continue;
}
let [_, __, file, ___, lineStr, ____, charStr, msg] = match;
let line = +lineStr;
file = path.resolve(cwd, file);
Expand Down Expand Up @@ -98,48 +117,39 @@ export function check(filename: string, goConfig: vscode.WorkspaceConfiguration)
args = ['test', '-copybinary', '-o', tmppath, '-c', '-tags', buildTags, ...buildFlags, '.'];
}
runTool(
goRuntimePath,
args,
cwd,
'error',
true,
null,
`Cannot find ${goRuntimePath}`
true
).then(result => resolve(result), err => reject(err));
});
});
runningToolsPromises.push(buildPromise);
}
if (!!goConfig['lintOnSave']) {
let lintTool = getBinPath(goConfig['lintTool'] || 'golint');
let lintTool = goConfig['lintTool'] || 'golint';
let lintFlags = goConfig['lintFlags'] || [];
let args = [...lintFlags];

if (lintTool === 'golint') {
args.push(filename);
}

runningToolsPromises.push(runTool(
lintTool,
args,
cwd,
'warning',
lintTool === 'golint',
lintTool === 'golint' ? 'golint' : null,
lintTool === 'golint' ? undefined : 'No "gometalinter" could be found. Install gometalinter to use this option.'
false,
lintTool
));
}

if (!!goConfig['vetOnSave']) {
let vetFlags = goConfig['vetFlags'] || [];
runningToolsPromises.push(runTool(
goRuntimePath,
['tool', 'vet', ...vetFlags, filename],
cwd,
'warning',
true,
null,
`Cannot find ${goRuntimePath}`
null
));
}

Expand Down
34 changes: 29 additions & 5 deletions src/goInstallTools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ function getTools(goVersion: SemVersion): { [key: string]: string } {
tools['golint'] = 'github.com/golang/lint/golint';
tools['gotests'] = 'github.com/cweill/gotests/...';
}

if (goConfig['lintTool'] === 'gometalinter') {
tools['gometalinter'] = 'github.com/alecthomas/gometalinter';
}

return tools;
}

Expand Down Expand Up @@ -121,33 +126,52 @@ function installTools(goVersion: SemVersion, missing?: string[]) {

// http.proxy setting takes precedence over environment variables
let httpProxy = vscode.workspace.getConfiguration('http').get('proxy');
let env = Object.assign({}, process.env);
let envForTools = Object.assign({}, process.env);
if (httpProxy) {
env = Object.assign({}, process.env, {
envForTools = Object.assign({}, process.env, {
http_proxy: httpProxy,
HTTP_PROXY: httpProxy,
https_proxy: httpProxy,
HTTPS_PROXY: httpProxy,
});
}

// If the go.toolsGopath is set, use
// If the go.toolsGopath is set, use
// its value as the GOPATH for the "go get" child process.
let goConfig = vscode.workspace.getConfiguration('go');
let envWithSeparateGoPathForTools = null;
if (goConfig['toolsGopath']) {
env['GOPATH'] = goConfig['toolsGopath'];
envWithSeparateGoPathForTools = Object.assign({}, envForTools, {GOPATH: goConfig['toolsGopath']});
}

missing.reduce((res: Promise<string[]>, tool: string) => {
return res.then(sofar => new Promise<string[]>((resolve, reject) => {
// gometalinter expects its linters to be in the user's GOPATH
// Therefore, cannot use an isolated GOPATH for installing gometalinter
let env = (envWithSeparateGoPathForTools && tool !== 'gometalinter') ? envWithSeparateGoPathForTools : envForTools;
cp.execFile(goRuntimePath, ['get', '-u', '-v', tools[tool]], { env }, (err, stdout, stderr) => {
if (err) {
outputChannel.appendLine('Installing ' + tool + ' FAILED');
let failureReason = tool + ';;' + err + stdout.toString() + stderr.toString();
resolve([...sofar, failureReason]);
} else {
outputChannel.appendLine('Installing ' + tool + ' SUCCEEDED');
resolve([...sofar, null]);
if (tool === 'gometalinter') {
// Gometalinter needs to install all the linters it uses.
outputChannel.appendLine('Installing all linters used by gometalinter....');
let gometalinterBinPath = getBinPath('gometalinter');
cp.execFile(gometalinterBinPath, ['--install'], (err, stdout, stderr) => {
if (!err) {
outputChannel.appendLine('Installing all linters used by gometalinter SUCCEEDED.');
resolve([...sofar, null]);
} else {
let failureReason = `Error while running gometalinter --install;; ${stderr}`;
resolve([...sofar, failureReason]);
}
});
} else {
resolve([...sofar, null]);
}
}
});
}));
Expand Down

0 comments on commit 8cce7d1

Please sign in to comment.