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

Build and linting improvements #735

Merged
merged 1 commit into from
Jan 21, 2017
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
46 changes: 28 additions & 18 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 @@ -91,55 +110,46 @@ export function check(filename: string, goConfig: vscode.WorkspaceConfiguration)
let tmppath = path.normalize(path.join(os.tmpdir(), 'go-code-check'));
let args = ['build'];
if (!isMainPkg) {
args.push('- i');
args.push('-i');
};
args = args.concat(['-o', tmppath, '-tags', buildTags, ...buildFlags, '.']);
if (filename.match(/_test.go$/i)) {
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
37 changes: 30 additions & 7 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,51 @@ 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 VSCODE_GOTOOLS environment variable is set, use
// If the VSCODE_GOTOOLS environment variable is set, use
// its value as the GOPATH for the "go get" child precess.
let toolsGoPath = process.env['VSCODE_GOTOOLS'];
if (toolsGoPath) {
env['GOPATH'] = toolsGoPath;
let envWithSeparateGoPathForTools = null;
if (process.env['VSCODE_GOTOOLS']) {
envWithSeparateGoPathForTools = Object.assign({}, envForTools, {GOPATH: process.env['VSCODE_GOTOOLS']});
}

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