This commit is contained in:
Adrian Suwała 2019-02-04 05:29:21 +01:00 коммит произвёл Ramya Rao
Родитель e7b8beafd5
Коммит bcc6407ef6
6 изменённых файлов: 144 добавлений и 94 удалений

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

@ -24,7 +24,7 @@ before_install:
fi
install:
- TRAVIS_NODE_VERSION="6";
- TRAVIS_NODE_VERSION="6"; GOMETALINTER_RELEASE_TAG="v2.0.12"; GOMETALIMTER_INSTALL_SCRIPT_COMMIT="83891259ab664a6d96066685f7f07431375ca8e5";
# Clear out whatever version of NVM Travis has as it is old.
- rm -rf ~/.nvm;
# Grab NVM.
@ -49,7 +49,8 @@ install:
- go get -u -v github.com/cweill/gotests/...
- go get -u -v github.com/haya14busa/goplay/cmd/goplay
- go get -u -v github.com/davidrjenni/reftools/cmd/fillstruct
- curl -fsSL https://git.io/vp6lP | sh -s -- -b $GOPATH/bin
# The latest script at https://git.io/vp6lP seems to have broken us as some checkers have been removed. Locking to previous version.
- curl -fsSL https://raw.githubusercontent.com/alecthomas/gometalinter/$GOMETALIMTER_INSTALL_SCRIPT_COMMIT/scripts/install.sh | sh -s $GOMETALINTER_RELEASE_TAG -- -b $GOPATH/bin
script:
- npm run lint

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

@ -101,6 +101,11 @@
"title": "Go: Benchmark Function At Cursor",
"description": "Runs a benchmark at the cursor."
},
{
"command": "go.debug.cursor",
"title": "Go: Debug Test At Cursor",
"description": "Debug test at the cursor."
},
{
"command": "go.test.file",
"title": "Go: Test File",
@ -1155,6 +1160,11 @@
"type": "boolean",
"default": true,
"description": "If true, adds command to upload the current file or selection to the Go Playground"
},
"debugTestAtCursor": {
"type": "boolean",
"default": true,
"description": "If true, adds command to debug the test under the cursor to the editor context menu"
}
},
"default": {
@ -1169,7 +1179,8 @@
"generateTestForPackage": false,
"addImport": true,
"testCoverage": true,
"playground": true
"playground": true,
"debugTestAtCursor": true
},
"description": "Experimental Feature: Enable/Disable entries from the context menu in the editor.",
"scope": "resource"
@ -1308,6 +1319,11 @@
"command": "go.benchmark.cursor",
"group": "Go group 1"
},
{
"when": "editorTextFocus && config.go.editorContextMenuCommands.debugTestAtCursor && resourceLangId == go && !config.editor.codeLens",
"command": "go.debug.cursor",
"group": "Go group 1"
},
{
"when": "editorTextFocus && config.go.editorContextMenuCommands.testFile && resourceLangId == go",
"command": "go.test.file",
@ -1351,4 +1367,4 @@
]
}
}
}
}

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

@ -326,15 +326,18 @@ export function activate(ctx: vscode.ExtensionContext): void {
}));
ctx.subscriptions.push(vscode.commands.registerCommand('go.test.cursor', (args) => {
let goConfig = vscode.workspace.getConfiguration('go', vscode.window.activeTextEditor ? vscode.window.activeTextEditor.document.uri : null);
let isBenchmark = false;
testAtCursor(goConfig, isBenchmark, args);
const goConfig = vscode.workspace.getConfiguration('go', vscode.window.activeTextEditor ? vscode.window.activeTextEditor.document.uri : null);
testAtCursor(goConfig, 'test', args);
}));
ctx.subscriptions.push(vscode.commands.registerCommand('go.debug.cursor', (args) => {
const goConfig = vscode.workspace.getConfiguration('go', vscode.window.activeTextEditor ? vscode.window.activeTextEditor.document.uri : null);
testAtCursor(goConfig, 'debug', args);
}));
ctx.subscriptions.push(vscode.commands.registerCommand('go.benchmark.cursor', (args) => {
let goConfig = vscode.workspace.getConfiguration('go', vscode.window.activeTextEditor ? vscode.window.activeTextEditor.document.uri : null);
let isBenchmark = true;
testAtCursor(goConfig, isBenchmark, args);
const goConfig = vscode.workspace.getConfiguration('go', vscode.window.activeTextEditor ? vscode.window.activeTextEditor.document.uri : null);
testAtCursor(goConfig, 'benchmark', args);
}));
ctx.subscriptions.push(vscode.commands.registerCommand('go.test.package', (args) => {

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

@ -7,11 +7,11 @@
import vscode = require('vscode');
import path = require('path');
import { TextDocument, CancellationToken, CodeLens, Command } from 'vscode';
import { getTestFunctions, getBenchmarkFunctions, getTestFlags, extractInstanceTestName, findAllTestSuiteRuns } from './testUtils';
import { GoDocumentSymbolProvider } from './goOutline';
import { getCurrentGoPath } from './util';
import { CancellationToken, CodeLens, Command, TextDocument } from 'vscode';
import { GoBaseCodeLensProvider } from './goBaseCodelens';
import { GoDocumentSymbolProvider } from './goOutline';
import { getBenchmarkFunctions, getTestFlags, getTestFunctionDebugArgs, getTestFunctions } from './testUtils';
import { getCurrentGoPath } from './util';
export class GoRunTestCodeLensProvider extends GoBaseCodeLensProvider {
private readonly benchmarkRegex = /^Benchmark.+/;
@ -101,39 +101,26 @@ export class GoRunTestCodeLensProvider extends GoBaseCodeLensProvider {
const testPromise = getTestFunctions(document, token).then(testFunctions => {
testFunctions.forEach(func => {
let runTestCmd: Command = {
const runTestCmd: Command = {
title: 'run test',
command: 'go.test.cursor',
arguments: [{ functionName: func.name }]
};
codelens.push(new CodeLens(func.location.range, runTestCmd));
let args: string[] = [];
let instanceMethod = extractInstanceTestName(func.name);
if (instanceMethod) {
const testFns = findAllTestSuiteRuns(document, testFunctions);
if (testFns && testFns.length > 0) {
args = args.concat('-test.run', `^${testFns.map(t => t.name).join('|')}$`);
}
args = args.concat('-testify.m', `^${instanceMethod}$`);
} else {
args = args.concat('-test.run', `^${func.name}$`);
}
let debugTestCmd: Command = {
const args = getTestFunctionDebugArgs(document, func.name, testFunctions);
const debugTestCmd: Command = {
title: 'debug test',
command: 'go.debug.startSession',
arguments: [Object.assign({}, currentDebugConfig, { args: args })]
arguments: [Object.assign({}, currentDebugConfig, { args })]
};
codelens.push(new CodeLens(func.location.range, debugTestCmd));
});
});
const benchmarkPromise = getBenchmarkFunctions(document, token).then(benchmarkFunctions => {
benchmarkFunctions.forEach(func => {
let runBenchmarkCmd: Command = {
const runBenchmarkCmd: Command = {
title: 'run benchmark',
command: 'go.benchmark.cursor',
arguments: [{ functionName: func.name }]
@ -141,7 +128,7 @@ export class GoRunTestCodeLensProvider extends GoBaseCodeLensProvider {
codelens.push(new CodeLens(func.location.range, runBenchmarkCmd));
let debugTestCmd: Command = {
const debugTestCmd: Command = {
title: 'debug benchmark',
command: 'go.debug.startSession',
arguments: [Object.assign({}, currentDebugConfig, { args: ['-test.bench', '^' + func.name + '$', '-test.run', 'a^'] })]

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

@ -2,29 +2,40 @@
* Copyright (C) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------*/
'use strict';
import path = require('path');
import vscode = require('vscode');
import os = require('os');
import { getTempFilePath } from './util';
import { goTest, TestConfig, getTestFlags, getTestFunctions, getBenchmarkFunctions, extractInstanceTestName, findAllTestSuiteRuns } from './testUtils';
import { applyCodeCoverageToAllEditors } from './goCover';
import { isModSupported } from './goModules';
import {
extractInstanceTestName,
findAllTestSuiteRuns,
getBenchmarkFunctions,
getTestFlags,
getTestFunctionDebugArgs,
getTestFunctions,
goTest,
TestConfig,
} from './testUtils';
import { getTempFilePath } from './util';
// lastTestConfig holds a reference to the last executed TestConfig which allows
// the last test to be easily re-executed.
let lastTestConfig: TestConfig;
export type TestAtCursorCmd = 'debug' | 'test' | 'benchmark';
/**
* Executes the unit test at the primary cursor using `go test`. Output
* is sent to the 'Go' channel.
*
* @param goConfig Configuration for the Go extension.
* @param cmd Whether the command is test , benchmark or debug.
*/
export function testAtCursor(goConfig: vscode.WorkspaceConfiguration, isBenchmark: boolean, args: any) {
let editor = vscode.window.activeTextEditor;
export function testAtCursor(goConfig: vscode.WorkspaceConfiguration, cmd: TestAtCursorCmd, args: any) {
const editor = vscode.window.activeTextEditor;
if (!editor) {
vscode.window.showInformationMessage('No editor is active.');
return;
@ -34,68 +45,82 @@ export function testAtCursor(goConfig: vscode.WorkspaceConfiguration, isBenchmar
return;
}
const getFunctions = isBenchmark ? getBenchmarkFunctions : getTestFunctions;
const { tmpCoverPath, testFlags } = makeCoverData(goConfig, 'coverOnSingleTest', args);
editor.document.save().then(() => {
return getFunctions(editor.document, null).then(testFunctions => {
let testFunctionName: string;
const getFunctions = cmd === 'benchmark' ? getBenchmarkFunctions : getTestFunctions;
editor.document.save().then(async () => {
try {
const testFunctions = await getFunctions(editor.document, null);
// We use functionName if it was provided as argument
// Otherwise find any test function containing the cursor.
if (args && args.functionName) {
testFunctionName = args.functionName;
} else {
for (let func of testFunctions) {
let selection = editor.selection;
if (selection && func.location.range.contains(selection.start)) {
testFunctionName = func.name;
break;
}
}
}
const testFunctionName = args && args.functionName
? args.functionName
: testFunctions.filter(func => func.location.range.contains(editor.selection.start))
.map(el => el.name)[0];
if (!testFunctionName) {
vscode.window.showInformationMessage('No test function found at cursor.');
return;
}
let testConfigFns = [testFunctionName];
if (!isBenchmark && extractInstanceTestName(testFunctionName)) {
// find test function with corresponding suite.Run
const testFns = findAllTestSuiteRuns(editor.document, testFunctions);
if (testFns) {
testConfigFns = testConfigFns.concat(testFns.map(t => t.name));
}
if (cmd === 'debug') {
await debugTestAtCursor(editor, testFunctionName, testFunctions, goConfig);
} else if (cmd === 'benchmark' || cmd === 'test') {
await runTestAtCursor(editor, testFunctionName, testFunctions, goConfig, args, cmd);
} else {
throw 'Unsupported command.';
}
const testConfig: TestConfig = {
goConfig: goConfig,
dir: path.dirname(editor.document.fileName),
flags: testFlags,
functions: testConfigFns,
isBenchmark: isBenchmark,
};
// Remember this config as the last executed test.
lastTestConfig = testConfig;
return isModSupported(editor.document.uri).then(isMod => {
testConfig.isMod = isMod;
return goTest(testConfig).then(success => {
if (success && tmpCoverPath) {
return applyCodeCoverageToAllEditors(tmpCoverPath, testConfig.dir);
}
});
});
});
}).then(null, err => {
console.error(err);
} catch (err) {
console.error(err);
}
});
}
/**
* Runs the test at cursor.
*/
async function runTestAtCursor(editor: vscode.TextEditor, testFunctionName: string, testFunctions: vscode.SymbolInformation[], goConfig: vscode.WorkspaceConfiguration, cmd: TestAtCursorCmd, args: any) {
const { tmpCoverPath, testFlags } = makeCoverData(goConfig, 'coverOnSingleTest', args);
const testConfigFns = cmd !== 'benchmark' && extractInstanceTestName(testFunctionName)
? [testFunctionName, ...findAllTestSuiteRuns(editor.document, testFunctions).map(t => t.name)]
: [testFunctionName];
const isMod = await isModSupported(editor.document.uri);
const testConfig: TestConfig = {
goConfig: goConfig,
dir: path.dirname(editor.document.fileName),
flags: testFlags,
functions: testConfigFns,
isBenchmark: cmd === 'benchmark',
isMod
};
// Remember this config as the last executed test.
lastTestConfig = testConfig;
await goTest(testConfig);
if (tmpCoverPath) {
return applyCodeCoverageToAllEditors(tmpCoverPath, testConfig.dir);
}
}
/**
* Debugs the test at cursor.
*/
async function debugTestAtCursor(editor: vscode.TextEditor, testFunctionName: string, testFunctions: vscode.SymbolInformation[], goConfig: vscode.WorkspaceConfiguration) {
const args = getTestFunctionDebugArgs(editor.document, testFunctionName, testFunctions);
const workspaceFolder = vscode.workspace.getWorkspaceFolder(editor.document.uri);
const debugConfig: vscode.DebugConfiguration = {
name: 'Debug Test',
type: 'go',
request: 'launch',
mode: 'auto',
program: editor.document.fileName,
env: goConfig.get('testEnvVars', {}),
envFile: goConfig.get('testEnvFile'),
args
};
return await vscode.debug.startDebugging(workspaceFolder, debugConfig);
}
/**
* Runs all tests in the package of the source of the active editor.
*

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

@ -2,16 +2,17 @@
* Copyright (C) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------*/
import cp = require('child_process');
import path = require('path');
import vscode = require('vscode');
import util = require('util');
import { parseEnvFile, getCurrentGoWorkspaceFromGOPATH } from './goPath';
import { getToolsEnvVars, getGoVersion, LineBuffer, SemVersion, resolvePath, getCurrentGoPath, getBinPath } from './util';
import vscode = require('vscode');
import { getCurrentPackage } from './goModules';
import { GoDocumentSymbolProvider } from './goOutline';
import { getNonVendorPackages } from './goPackages';
import { getCurrentPackage } from './goModules';
import { getCurrentGoWorkspaceFromGOPATH, parseEnvFile } from './goPath';
import { getBinPath, getCurrentGoPath, getGoVersion, getToolsEnvVars, LineBuffer, resolvePath } from './util';
const sendSignal = 'SIGKILL';
const outputChannel = vscode.window.createOutputChannel('Go Tests');
@ -126,6 +127,23 @@ export function extractInstanceTestName(symbolName: string): string {
return match[2];
}
/**
* Gets the appropriate debug arguments for a debug session on a test function.
* @param document The document containing the tests
* @param testFunctionName The test function to get the debug args
* @param testFunctions The test functions found in the document
*/
export function getTestFunctionDebugArgs(document: vscode.TextDocument, testFunctionName: string, testFunctions: vscode.SymbolInformation[]): string[] {
const instanceMethod = extractInstanceTestName(testFunctionName);
if (instanceMethod) {
const testFns = findAllTestSuiteRuns(document, testFunctions);
const testSuiteRuns = ['-test.run', `^${testFns.map(t => t.name).join('|')}$`];
const testSuiteTests = ['-testify.m', `^${instanceMethod}$`];
return [...testSuiteRuns, ...testSuiteTests];
} else {
return ['-test.run', `^${testFunctionName}$`];
}
}
/**
* Finds test methods containing "suite.Run()" call.
*