add playground command (#1270)
* add playground command enables the user to upload the current file or selection to the go playground using package goplay - solves #1211 * separate tool execution from command logic, add test * add tests for error case * ensure better separation between tool calling and extension logic * handle no active editor, clear output channel, check for tool availability by stat-ing binary location * move all logic into function body * Add tests back * Fixing linting error
This commit is contained in:
Родитель
12e9d30c42
Коммит
f71af13762
|
@ -52,6 +52,7 @@ install:
|
|||
- go get -u -v github.com/acroca/go-symbols
|
||||
- go get -u -v github.com/alecthomas/gometalinter
|
||||
- go get -u -v github.com/cweill/gotests/...
|
||||
- go get -u -v github.com/haya14busa/goplay/cmd/goplay
|
||||
- GO15VENDOREXPERIMENT=1
|
||||
- if [[ "$(go version)" =~ "go version go1.5" ]]; then echo skipping gometalinter; else gometalinter --install; fi
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@ This extension adds rich language support for the Go language to VS Code, includ
|
|||
- Show code coverage
|
||||
- Generate method stubs for interfaces (using `impl`)
|
||||
- [_partially implemented_] Debugging (using `delve`)
|
||||
- Upload to the Go Playground (using `goplay`)
|
||||
|
||||
### IDE Features
|
||||
![IDE](https://i.giphy.com/xTiTndDHV3GeIy6aNa.gif)
|
||||
|
@ -105,6 +106,7 @@ In addition to integrated editing features, the extension also provides several
|
|||
* `Go: Add Tags` Adds configured tags to selected struct fields.
|
||||
* `Go: Remove Tags` Removes configured tags from selected struct fields.
|
||||
* `Go: Generate Interface Stubs` Generates method stubs for given interface
|
||||
* `Go: Run on Go Playground` Upload the current selection or file to the Go Playground
|
||||
|
||||
You can access all of the above commands from the command pallet (`Cmd+Shift+P` or `Ctrl+Shift+P`).
|
||||
|
||||
|
|
39
package.json
39
package.json
|
@ -177,6 +177,11 @@
|
|||
"command": "go.get.package",
|
||||
"title": "Go: Get Package",
|
||||
"description": "Run `go get -v` on the package on the current line."
|
||||
},
|
||||
{
|
||||
"command": "go.playground",
|
||||
"title": "Go: Run on Go Playground",
|
||||
"description": "Upload the current selection or file to the Go Playground"
|
||||
}
|
||||
],
|
||||
"debuggers": [
|
||||
|
@ -720,6 +725,32 @@
|
|||
"description": "Tags and options configured here will be used by the Remove Tags command to remove tags to struct fields. If promptForTags is true, then user will be prompted for tags and options. By default, all tags and options will be removed.",
|
||||
"scope": "resource"
|
||||
},
|
||||
"go.playground": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"openbrowser": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "Whether to open the created Go Playground in the default browser"
|
||||
},
|
||||
"share": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "Whether to make the created Go Playground shareable"
|
||||
},
|
||||
"run": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "Whether to run the created Go Playground after creation"
|
||||
},
|
||||
"description": "The flags configured here will be passed through to command `goplay`"
|
||||
},
|
||||
"default": {
|
||||
"openbrowser": true,
|
||||
"share": true,
|
||||
"run": true
|
||||
}
|
||||
},
|
||||
"go.editorContextMenuCommands": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
@ -777,6 +808,11 @@
|
|||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "If true, adds command to run test coverage to the editor context menu"
|
||||
},
|
||||
"playground": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "If true, adds command to upload the current file or selection to the Go Playground"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
|
@ -790,7 +826,8 @@
|
|||
"generateTestForFile": false,
|
||||
"generateTestForPackage": false,
|
||||
"addImport": true,
|
||||
"testCoverage": true
|
||||
"testCoverage": true,
|
||||
"playground": true
|
||||
},
|
||||
"description": "Experimental Feature: Enable/Disable entries from the context menu in the editor.",
|
||||
"scope": "resource"
|
||||
|
|
|
@ -26,6 +26,7 @@ const allTools: { [key: string]: string } = {
|
|||
'guru': 'golang.org/x/tools/cmd/guru',
|
||||
'gorename': 'golang.org/x/tools/cmd/gorename',
|
||||
'gomodifytags': 'github.com/fatih/gomodifytags',
|
||||
'goplay': 'github.com/haya14busa/goplay/cmd/goplay',
|
||||
'impl': 'github.com/josharian/impl',
|
||||
'gotype-live': 'github.com/tylerb/gotype-live',
|
||||
'godef': 'github.com/rogpeppe/godef',
|
||||
|
@ -51,6 +52,7 @@ function getTools(goVersion: SemVersion): string[] {
|
|||
'guru',
|
||||
'gorename',
|
||||
'gomodifytags',
|
||||
'goplay',
|
||||
'impl'
|
||||
];
|
||||
|
||||
|
|
|
@ -40,6 +40,7 @@ import { implCursor } from './goImpl';
|
|||
import { browsePackages } from './goBrowsePackage';
|
||||
import { goGetPackage } from './goGetPackage';
|
||||
import { GoDebugConfigurationProvider } from './goDebugConfiguration';
|
||||
import { playgroundCommand } from './goPlayground';
|
||||
|
||||
export let errorDiagnosticCollection: vscode.DiagnosticCollection;
|
||||
let warningDiagnosticCollection: vscode.DiagnosticCollection;
|
||||
|
@ -279,6 +280,8 @@ export function activate(ctx: vscode.ExtensionContext): void {
|
|||
|
||||
ctx.subscriptions.push(vscode.commands.registerCommand('go.get.package', goGetPackage));
|
||||
|
||||
ctx.subscriptions.push(vscode.commands.registerCommand('go.playground', playgroundCommand));
|
||||
|
||||
vscode.languages.setLanguageConfiguration(GO_MODE.language, {
|
||||
indentationRules: {
|
||||
decreaseIndentPattern: /^\s*(\bcase\b.*:|\bdefault\b:|}[),]?|\)[,]?)$/,
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
import vscode = require('vscode');
|
||||
import * as path from 'path';
|
||||
import { execFile } from 'child_process';
|
||||
import { outputChannel } from './goStatus';
|
||||
import { getBinPath } from './util';
|
||||
import { promptForMissingTool } from './goInstallTools';
|
||||
|
||||
const TOOL_CMD_NAME = 'goplay';
|
||||
|
||||
type flags = { [key: string]: Boolean };
|
||||
|
||||
export const playgroundCommand = () => {
|
||||
const editor = vscode.window.activeTextEditor;
|
||||
if (!editor) {
|
||||
vscode.window.showInformationMessage('No editor is active.');
|
||||
return;
|
||||
}
|
||||
|
||||
const binaryLocation = getBinPath(TOOL_CMD_NAME);
|
||||
if (!path.isAbsolute(binaryLocation)) {
|
||||
return promptForMissingTool(TOOL_CMD_NAME);
|
||||
}
|
||||
|
||||
outputChannel.clear();
|
||||
outputChannel.show();
|
||||
outputChannel.appendLine('Upload to the Go Playground in progress...\n');
|
||||
|
||||
const selection = editor.selection;
|
||||
const code = selection.isEmpty
|
||||
? editor.document.getText()
|
||||
: editor.document.getText(selection);
|
||||
goPlay(code, vscode.workspace.getConfiguration('go', editor.document.uri).get('playground')).then(result => {
|
||||
outputChannel.append(result);
|
||||
}, (e: string) => {
|
||||
if (e) {
|
||||
vscode.window.showErrorMessage(e);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export function goPlay(code: string, goConfig: vscode.WorkspaceConfiguration): Thenable<string> {
|
||||
const cliArgs = Object.keys(goConfig).map(key => `-${key}=${goConfig[key]}`);
|
||||
const binaryLocation = getBinPath(TOOL_CMD_NAME);
|
||||
|
||||
return new Promise<string>((resolve, reject) => {
|
||||
execFile(binaryLocation, [...cliArgs, '-'], (err, stdout, stderr) => {
|
||||
if (err && (<any>err).code === 'ENOENT') {
|
||||
promptForMissingTool(TOOL_CMD_NAME);
|
||||
return reject();
|
||||
}
|
||||
if (err) {
|
||||
return reject(`${TOOL_CMD_NAME}: ${stdout || stderr || err.message}`);
|
||||
}
|
||||
return resolve(
|
||||
`Output from the Go Playground:
|
||||
${stdout || stderr}
|
||||
Finished running tool: ${binaryLocation} ${cliArgs.join(' ')} -\n`
|
||||
);
|
||||
}).stdin.end(code);
|
||||
});
|
||||
}
|
|
@ -23,6 +23,7 @@ import { listPackages } from '../src/goImport';
|
|||
import { generateTestCurrentFile, generateTestCurrentPackage, generateTestCurrentFunction } from '../src/goGenerateTests';
|
||||
import { getAllPackages } from '../src/goPackages';
|
||||
import { getImportPath } from '../src/util';
|
||||
import { goPlay } from '../src/goPlayground';
|
||||
|
||||
suite('Go Extension Tests', () => {
|
||||
let gopath = process.env['GOPATH'];
|
||||
|
@ -755,4 +756,75 @@ It returns the number of bytes written and any write error encountered.
|
|||
assert.equal(run[1], getImportPath(run[0]));
|
||||
});
|
||||
});
|
||||
|
||||
test('goPlay - success run', (done) => {
|
||||
const validCode = `
|
||||
package main
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
func main() {
|
||||
for i := 1; i < 4; i++ {
|
||||
fmt.Printf("%v ", i)
|
||||
}
|
||||
fmt.Print("Go!")
|
||||
}`;
|
||||
const goConfig = Object.create(vscode.workspace.getConfiguration('go'), {
|
||||
'playground': { value: { run: true, openbrowser: false, share: false } }
|
||||
});
|
||||
|
||||
goPlay(validCode, goConfig['playground']).then(result => {
|
||||
assert(
|
||||
result.includes('1 2 3 Go!')
|
||||
);
|
||||
}, (e) => {
|
||||
assert.ifError(e);
|
||||
}).then(() => done(), done);
|
||||
});
|
||||
|
||||
|
||||
test('goPlay - success run & share', (done) => {
|
||||
const validCode = `
|
||||
package main
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
func main() {
|
||||
for i := 1; i < 4; i++ {
|
||||
fmt.Printf("%v ", i)
|
||||
}
|
||||
fmt.Print("Go!")
|
||||
}`;
|
||||
const goConfig = Object.create(vscode.workspace.getConfiguration('go'), {
|
||||
'playground': { value: { run: true, openbrowser: false, share: true } }
|
||||
});
|
||||
|
||||
goPlay(validCode, goConfig['playground']).then(result => {
|
||||
assert(result.includes('1 2 3 Go!'));
|
||||
assert(result.includes('https://play.golang.org/'));
|
||||
}, (e) => {
|
||||
assert.ifError(e);
|
||||
}).then(() => done(), done);
|
||||
});
|
||||
|
||||
test('goPlay - fail', (done) => {
|
||||
const invalidCode = `
|
||||
package main
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
func fantasy() {
|
||||
fmt.Print("not a main package, sorry")
|
||||
}`;
|
||||
const goConfig = Object.create(vscode.workspace.getConfiguration('go'), {
|
||||
'playground': { value: { run: true, openbrowser: false, share: false } }
|
||||
});
|
||||
|
||||
goPlay(invalidCode, goConfig['playground']).then(result => {
|
||||
assert.ifError(result);
|
||||
}, (e) => {
|
||||
assert.ok(e);
|
||||
}).then(() => done(), done);
|
||||
});
|
||||
|
||||
});
|
||||
|
|
Загрузка…
Ссылка в новой задаче