| /*--------------------------------------------------------- |
| * Copyright (C) Microsoft Corporation. All rights reserved. |
| * Licensed under the MIT License. See LICENSE in the project root for license information. |
| *--------------------------------------------------------*/ |
| |
| import path = require('path'); |
| import vscode = require('vscode'); |
| import { toolExecutionEnvironment } from './goEnv'; |
| import { vetDiagnosticCollection } from './goMain'; |
| import { diagnosticsStatusBarItem, outputChannel } from './goStatus'; |
| import { |
| getGoConfig, |
| getGoVersion, |
| getWorkspaceFolderPath, |
| handleDiagnosticErrors, |
| ICheckResult, |
| resolvePath, |
| runTool |
| } from './util'; |
| |
| /** |
| * Runs go vet in the current package or workspace. |
| */ |
| export function vetCode(vetWorkspace?: boolean) { |
| const editor = vscode.window.activeTextEditor; |
| if (!editor && !vetWorkspace) { |
| vscode.window.showInformationMessage('No editor is active, cannot find current package to vet'); |
| return; |
| } |
| if (editor.document.languageId !== 'go' && !vetWorkspace) { |
| vscode.window.showInformationMessage( |
| 'File in the active editor is not a Go file, cannot find current package to vet' |
| ); |
| return; |
| } |
| |
| const documentUri = editor ? editor.document.uri : null; |
| const goConfig = getGoConfig(documentUri); |
| |
| outputChannel.clear(); // Ensures stale output from vet on save is cleared |
| diagnosticsStatusBarItem.show(); |
| diagnosticsStatusBarItem.text = 'Vetting...'; |
| |
| goVet(documentUri, goConfig, vetWorkspace) |
| .then((warnings) => { |
| handleDiagnosticErrors(editor ? editor.document : null, warnings, vetDiagnosticCollection); |
| diagnosticsStatusBarItem.hide(); |
| }) |
| .catch((err) => { |
| vscode.window.showInformationMessage('Error: ' + err); |
| diagnosticsStatusBarItem.text = 'Vetting Failed'; |
| }); |
| } |
| |
| /** |
| * Runs go vet or go tool vet and presents the output in the 'Go' channel and in the diagnostic collections. |
| * |
| * @param fileUri Document uri. |
| * @param goConfig Configuration for the Go extension. |
| * @param vetWorkspace If true vets code in all workspace. |
| */ |
| export async function goVet( |
| fileUri: vscode.Uri, |
| goConfig: vscode.WorkspaceConfiguration, |
| vetWorkspace?: boolean |
| ): Promise<ICheckResult[]> { |
| epoch++; |
| const closureEpoch = epoch; |
| if (tokenSource) { |
| if (running) { |
| tokenSource.cancel(); |
| } |
| tokenSource.dispose(); |
| } |
| tokenSource = new vscode.CancellationTokenSource(); |
| |
| const currentWorkspace = getWorkspaceFolderPath(fileUri); |
| const cwd = vetWorkspace && currentWorkspace ? currentWorkspace : path.dirname(fileUri.fsPath); |
| if (!path.isAbsolute(cwd)) { |
| return Promise.resolve([]); |
| } |
| |
| const vetFlags: string[] = goConfig['vetFlags'] || []; |
| const vetEnv = toolExecutionEnvironment(); |
| const args: string[] = []; |
| |
| vetFlags.forEach((flag) => { |
| if (flag.startsWith('--vettool=') || flag.startsWith('-vettool=')) { |
| let vetToolPath = flag.substr(flag.indexOf('=') + 1).trim(); |
| if (!vetToolPath) { |
| return; |
| } |
| vetToolPath = resolvePath(vetToolPath); |
| args.push(`${flag.substr(0, flag.indexOf('=') + 1)}${vetToolPath}`); |
| return; |
| } |
| args.push(flag); |
| }); |
| |
| const goVersion = await getGoVersion(); |
| const tagsArg = []; |
| if (goConfig['buildTags'] && vetFlags.indexOf('-tags') === -1) { |
| tagsArg.push('-tags'); |
| tagsArg.push(goConfig['buildTags']); |
| } |
| |
| let vetArgs = ['vet', ...args, ...tagsArg, vetWorkspace ? './...' : '.']; |
| if (goVersion.lt('1.10') && args.length) { |
| vetArgs = ['tool', 'vet', ...args, ...tagsArg, '.']; |
| } |
| |
| outputChannel.appendLine(`Starting "go vet" under the folder ${cwd}`); |
| |
| running = true; |
| return runTool(vetArgs, cwd, 'warning', true, null, vetEnv, false, tokenSource.token).then((result) => { |
| if (closureEpoch === epoch) { |
| running = false; |
| } |
| return result; |
| }); |
| } |
| |
| let epoch = 0; |
| let tokenSource: vscode.CancellationTokenSource; |
| let running = false; |