Skip to content

Commit 93b1861

Browse files
committed
goImpl: improvements
Improvements: 1. Now variable and type can be deduced from cursor selection 2. Now you can implement multiple interfaces at once
1 parent b2303c5 commit 93b1861

File tree

1 file changed

+55
-29
lines changed

1 file changed

+55
-29
lines changed

src/goImpl.ts

Lines changed: 55 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,12 @@ import { getBinPath } from './util';
1515
import vscode = require('vscode');
1616
import { CommandFactory } from './commands';
1717

18-
// Supports only passing interface, see TODO in implCursor to finish
19-
const inputRegex = /^(\w+\ \*?\w+\ )?([\w\.\-\/]+)$/;
18+
// Accepts input of the form:
19+
// [f *File] io.Closer [, ...]
20+
// [f *File] io.Closer
21+
// io.Closer (type name will be deduced from variable name from cursor position)
22+
// io.Closer, io.Reader (same as above)
23+
const inputRegex = /^(?<identifier>(?<variable>[\p{Letter}_][\p{Letter}_\p{Number}\d]*) *(?<type>[*]? *[\p{Letter}_][\p{Letter}_\p{Number}\d]*) +)?(?<interfaces>(?:[\p{Letter}_][\p{Letter}_\p{Number}\d\.\-\/]*)+(?: *, *(?:[\p{Letter}_][\p{Letter}_\p{Number}\d\.\-\/]*)+)*)$/u;
2024

2125
export const implCursor: CommandFactory = () => () => {
2226
const editor = vscode.window.activeTextEditor;
@@ -27,50 +31,72 @@ export const implCursor: CommandFactory = () => () => {
2731
const cursor = editor.selection;
2832
return vscode.window
2933
.showInputBox({
30-
placeHolder: 'f *File io.Closer',
34+
placeHolder: '[f *File] io.Closer [, ...]',
3135
prompt: 'Enter receiver and interface to implement.'
3236
})
3337
.then((implInput) => {
3438
if (typeof implInput === 'undefined') {
3539
return;
3640
}
3741
const matches = implInput.match(inputRegex);
38-
if (!matches) {
42+
if (!matches || !matches.groups || !matches.groups.interfaces) {
3943
vscode.window.showInformationMessage(`Not parsable input: ${implInput}`);
4044
return;
4145
}
4246

43-
// TODO: automatically detect type name at cursor
44-
// if matches[1] is undefined then detect receiver type
45-
// take first character and use as receiver name
47+
let identifier = matches.groups?.identifier;
48+
if (!identifier) {
49+
const beforeCursor = new vscode.Range(new vscode.Position(cursor.start.line, 0), cursor.start);
50+
const beforeCursorText = editor.document.getText(beforeCursor);
51+
const typeIndex = beforeCursorText.lastIndexOf('type');
52+
if (typeIndex === -1) {
53+
vscode.window.showInformationMessage('No identifier found at cursor.');
54+
return;
55+
}
4656

47-
runGoImpl([matches[1], matches[2]], cursor.start, editor);
57+
const variable = editor.document.getText(cursor)[0].toLowerCase();
58+
identifier = editor.document.getText(cursor);
59+
identifier = `${variable} *${identifier}`;
60+
61+
let newPosition = cursor.start.with(cursor.start.line + 1, 0);
62+
newPosition = newPosition.translate(1, 0);
63+
editor.selection = new vscode.Selection(newPosition, newPosition);
64+
}
65+
const interfaces = matches.groups?.interfaces.trim().split(',');
66+
interfaces.forEach((iface, i) => {
67+
interfaces[i] = iface.trim();
68+
});
69+
runGoImpl([identifier, interfaces], editor);
4870
});
4971
};
5072

51-
function runGoImpl(args: string[], insertPos: vscode.Position, editor: vscode.TextEditor) {
73+
function runGoImpl(prompt: [string, string[]], editor: vscode.TextEditor) {
5274
const goimpl = getBinPath('impl');
53-
const p = cp.execFile(
54-
goimpl,
55-
args,
56-
{ env: toolExecutionEnvironment(), cwd: dirname(editor.document.fileName) },
57-
(err, stdout, stderr) => {
58-
if (err && (<any>err).code === 'ENOENT') {
59-
promptForMissingTool('impl');
60-
return;
61-
}
75+
prompt[1].forEach((iface) => {
76+
const p = cp.execFile(
77+
goimpl,
78+
[prompt[0], iface],
79+
{ env: toolExecutionEnvironment(), cwd: dirname(editor.document.fileName) },
80+
(err, stdout, stderr) => {
81+
if (err && (<any>err).code === 'ENOENT') {
82+
promptForMissingTool('impl');
83+
return;
84+
}
6285

63-
if (err) {
64-
vscode.window.showInformationMessage(`Cannot stub interface: ${stderr}`);
65-
return;
66-
}
86+
if (err) {
87+
vscode.window.showInformationMessage(`Cannot stub interface: ${stderr}`);
88+
return;
89+
}
6790

68-
editor.edit((editBuilder) => {
69-
editBuilder.insert(insertPos, stdout);
70-
});
91+
(function (out: string) {
92+
editor.edit((editBuilder) => {
93+
editBuilder.insert(editor.selection.start, out);
94+
});
95+
})(stdout);
96+
}
97+
);
98+
if (p.pid) {
99+
p.stdin?.end();
71100
}
72-
);
73-
if (p.pid) {
74-
p.stdin?.end();
75-
}
101+
});
76102
}

0 commit comments

Comments
 (0)