diff --git a/package.json b/package.json index 55231ad85..16ca5ad67 100644 --- a/package.json +++ b/package.json @@ -129,6 +129,11 @@ "title": "Go: Generate unit tests for function", "description": "Generates unit tests for the selected function in the current file" }, + { + "command": "go.impl.cursor", + "title": "Go: Generate interface stub", + "description": "Generates and inserts stub methods for implementing the provided interface at the cursor." + }, { "command": "go.import.add", "title": "Go: Add Import", @@ -730,4 +735,4 @@ ] } } -} \ No newline at end of file +} diff --git a/src/goImpl.ts b/src/goImpl.ts new file mode 100644 index 000000000..4f2b0db37 --- /dev/null +++ b/src/goImpl.ts @@ -0,0 +1,69 @@ +/*--------------------------------------------------------- + * 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 vscode = require('vscode'); +import cp = require('child_process'); +import { getBinPath } from './util'; +import { promptForMissingTool } from './goInstallTools'; + +interface GoImplInput { + receiver: string; + interface: string; +} + +// Supports only passing interface, see TODO in implCursor to finish +const inputRegex = /^(\w+\ \*?\w+\ )?([\w.]+)$/; + +export function implCursor() { + let cursor = vscode.window.activeTextEditor.selection; + return vscode.window.showInputBox({ + placeHolder: 'f *File io.Closer', + prompt: 'What interface do you want to implement?' + }).then(implInput => { + if (typeof implInput === 'undefined') { + return; + } + const matches = implInput.match(inputRegex); + if (!matches) { + vscode.window.showInformationMessage(`Not parsable input: ${implInput}`); + return; + } + + // TODO: automatically detect type name at cursor + // if matches[1] is undefined then detect receiver type + // take first character and use as receiver name + + let input: GoImplInput = { + receiver: matches[1], + interface: matches[2] + }; + + runGoImpl(input, cursor.start); + }); +} + +function runGoImpl(input: GoImplInput, insertPos: vscode.Position) { + let goimpl = getBinPath('impl'); + let editor = vscode.window.activeTextEditor; + let p = cp.execFile(goimpl, [input.receiver, input.interface], (err, stdout, stderr) => { + if (err && (err).code === 'ENOENT') { + promptForMissingTool('impl'); + return; + } + + if (err) { + vscode.window.showInformationMessage(`Cannot stub inteface: ${stderr}`); + return; + } + + let output = stdout; + vscode.window.activeTextEditor.edit(editBuilder => { + editBuilder.insert(insertPos, stdout); + }); + }); + p.stdin.end(); +} \ No newline at end of file diff --git a/src/goInstallTools.ts b/src/goInstallTools.ts index 08755db5a..8ba50162e 100644 --- a/src/goInstallTools.ts +++ b/src/goInstallTools.ts @@ -27,7 +27,8 @@ function getTools(goVersion: SemVersion): { [key: string]: string } { 'go-symbols': 'github.com/acroca/go-symbols', 'guru': 'golang.org/x/tools/cmd/guru', 'gorename': 'golang.org/x/tools/cmd/gorename', - 'gomodifytags': 'github.com/fatih/gomodifytags' + 'gomodifytags': 'github.com/fatih/gomodifytags', + 'impl': 'github.com/josharian/impl' }; if (goLiveErrorsEnabled()) { tools['gotype-live'] = 'github.com/tylerb/gotype-live'; diff --git a/src/goMain.ts b/src/goMain.ts index e67ba1359..ed8e94e99 100644 --- a/src/goMain.ts +++ b/src/goMain.ts @@ -34,6 +34,7 @@ import { clearCacheForTools } from './goPath'; import { addTags, removeTags } from './goModifytags'; import { parseLiveFile } from './goLiveErrors'; import { GoCodeLensProvider } from './goCodelens'; +import { implCursor } from './goImpl'; export let errorDiagnosticCollection: vscode.DiagnosticCollection; let warningDiagnosticCollection: vscode.DiagnosticCollection; @@ -117,6 +118,10 @@ export function activate(ctx: vscode.ExtensionContext): void { removeTags(args); })); + ctx.subscriptions.push(vscode.commands.registerCommand('go.impl.cursor', () => { + implCursor(); + })); + ctx.subscriptions.push(vscode.commands.registerCommand('go.test.cursor', (args) => { let goConfig = vscode.workspace.getConfiguration('go'); testAtCursor(goConfig, args);