Skip to content

Commit 00afaca

Browse files
committed
feat: go to definition
1 parent 34a8505 commit 00afaca

File tree

6 files changed

+101
-22
lines changed

6 files changed

+101
-22
lines changed

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,17 @@ This extension integrates your Taskfile into Visual Studio Code.
66

77
- View tasks in the activity bar
88
- Run tasks from the activity bar and command palette
9+
- Go to definition
910

1011
## Roadmap
1112

1213
- Run last task command
14+
- Stream output to output channel instead of waiting for command to finish
1315
- Switch between nested/flat task view
1416
- Refresh up-to-date status when a task's sources change
17+
- Status polling to update up-to-date status
1518
- Support global tasks
1619
- Support workspaces
17-
- Go to definitions
18-
- Re run last task
1920
- Install Task via command palette
2021
- Prompt if a Taskfile is detected and Task is not installed
2122
- If no Taskfile is detected, add a button to initialise one

package.json

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,18 @@
5353
"title": "Run Task",
5454
"category": "Task",
5555
"icon": "$(play)"
56+
},
57+
{
58+
"command": "vscode-task.goToDefinition",
59+
"title": "Go to Definition",
60+
"category": "Task",
61+
"icon": "$(go-to-file)"
62+
},
63+
{
64+
"command": "vscode-task.goToDefinitionPicker",
65+
"title": "Go to Definition",
66+
"category": "Task",
67+
"icon": "$(go-to-file)"
5668
}
5769
],
5870
"viewsContainers": {
@@ -77,6 +89,10 @@
7789
{
7890
"command": "vscode-task.runTask",
7991
"when": "false"
92+
},
93+
{
94+
"command": "vscode-task.goToDefinition",
95+
"when": "false"
8096
}
8197
],
8298
"view/title": [
@@ -91,6 +107,11 @@
91107
"command": "vscode-task.runTask",
92108
"when": "view == vscode-task.tasks && viewItem == taskTreeItem",
93109
"group": "inline"
110+
},
111+
{
112+
"command": "vscode-task.goToDefinition",
113+
"when": "view == vscode-task.tasks && viewItem == taskTreeItem",
114+
"group": "inline"
94115
}
95116
]
96117
},

src/models/taskfile.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,11 @@ export interface Task {
77
desc: string;
88
summary: string;
99
up_to_date: boolean;
10+
location: Location;
11+
}
12+
13+
export interface Location {
14+
taskfile: string;
15+
line: number;
16+
column: number;
1017
}

src/providers/tasks.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,11 @@ export class Tasks implements vscode.TreeDataProvider<TaskTreeItem> {
2626
// If the task's namespace is the same as the parent's namespace
2727
// add the task to the tree
2828
if ((parent && parent.namespace === namespace) || (!parent && namespace === "")) {
29-
taskTreeItems.push(new TaskTreeItem(taskLabel, namespace, task, vscode.TreeItemCollapsibleState.None));
29+
taskTreeItems.push(new TaskTreeItem(taskLabel, namespace, task, vscode.TreeItemCollapsibleState.None, {
30+
command: 'vscode-task.goToDefinition',
31+
title: 'Go to Definition',
32+
arguments: [task, true],
33+
}));
3034
return;
3135
}
3236

@@ -71,7 +75,8 @@ export class TaskTreeItem extends vscode.TreeItem {
7175
readonly label: string,
7276
readonly namespace: string,
7377
readonly task: models.Task | undefined,
74-
public readonly collapsibleState: vscode.TreeItemCollapsibleState
78+
public readonly collapsibleState: vscode.TreeItemCollapsibleState,
79+
public readonly command?: vscode.Command
7580
) {
7681
super(label, collapsibleState);
7782
this.description = this.task?.desc;

src/services/taskfile.ts

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,36 +15,53 @@ class TaskfileService {
1515
}
1616

1717
public async read(): Promise<models.Taskfile> {
18-
return await new Promise((resolve, reject) => {
18+
return await new Promise((resolve) => {
1919
let command = 'task --list-all --json';
20-
cp.exec(command, { cwd: getWorkspaceFolder() }, (err: cp.ExecException | null, stdout: string, stderr: string) => {
21-
if (err) {
22-
console.log('error: ' + err);
23-
reject();
24-
return;
25-
}
20+
cp.exec(command, { cwd: getWorkspaceFolder() }, (_, stdout: string) => {
2621
var taskfile: models.Taskfile = JSON.parse(stdout);
2722
resolve(taskfile);
2823
});
2924
});
3025
}
3126

3227
public async runTask(taskName: string): Promise<void> {
33-
return await new Promise((resolve, reject) => {
28+
return await new Promise((resolve) => {
3429
let command = `task ${taskName}`;
35-
cp.exec(command, { cwd: getWorkspaceFolder() }, (err: cp.ExecException | null, stdout: string, stderr: string) => {
36-
if (err) {
37-
console.log('error: ' + err);
38-
reject();
39-
return;
40-
}
30+
cp.exec(command, { cwd: getWorkspaceFolder() }, (_, stdout: string, stderr: string) => {
4131
TaskfileService.outputChannel.append(stderr);
4232
TaskfileService.outputChannel.append(stdout);
33+
TaskfileService.outputChannel.append("-----");
4334
TaskfileService.outputChannel.show();
4435
resolve();
4536
});
4637
});
4738
}
39+
40+
public goToDefinition(task: models.Task, preview: boolean = false): void {
41+
if (task.location === undefined) {
42+
vscode.window.showErrorMessage(`Go to definition requires Task v3.23.0 or higher.`);
43+
return;
44+
}
45+
46+
let position = new vscode.Position(task.location.line - 1, task.location.column - 1);
47+
let range = new vscode.Range(position, position);
48+
49+
// Create the vscode URI from the Taskfile path
50+
let file = vscode.Uri.file(task.location.taskfile);
51+
52+
// Create the vscode text document show options
53+
let options: vscode.TextDocumentShowOptions = {
54+
selection: range,
55+
preview: preview
56+
};
57+
58+
// Run the vscode open command with the range options
59+
try {
60+
vscode.commands.executeCommand('vscode.open', file, options);
61+
} catch (err) {
62+
console.error(err);
63+
}
64+
}
4865
}
4966

5067
export const taskfile = TaskfileService.Instance;

src/task.ts

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@ export class TaskExtension {
3737

3838
public registerCommands(context: vscode.ExtensionContext): void {
3939

40+
// Refresh tasks
41+
context.subscriptions.push(vscode.commands.registerCommand('vscode-task.refresh', () => {
42+
this.updateAndRefresh();
43+
}));
44+
4045
// Run task
4146
context.subscriptions.push(vscode.commands.registerCommand('vscode-task.runTask', (treeItem?: TaskTreeItem) => {
4247
if (treeItem?.task) {
@@ -46,7 +51,7 @@ export class TaskExtension {
4651

4752
// Run task picker
4853
context.subscriptions.push(vscode.commands.registerCommand('vscode-task.runTaskPicker', () => {
49-
if (!this._taskfile || this._taskfile.tasks.length === 0) {
54+
if (this._taskfile === undefined || this._taskfile.tasks.length === 0) {
5055
vscode.window.showInformationMessage('No tasks found');
5156
return;
5257
}
@@ -57,9 +62,32 @@ export class TaskExtension {
5762
});
5863
}));
5964

60-
// Refresh tasks
61-
context.subscriptions.push(vscode.commands.registerCommand('vscode-task.refresh', () => {
62-
this.updateAndRefresh();
65+
// Go to definition
66+
context.subscriptions.push(vscode.commands.registerCommand('vscode-task.goToDefinition', (task: TaskTreeItem | models.Task, preview: boolean = false) => {
67+
if (task instanceof TaskTreeItem) {
68+
if (task.task === undefined) {
69+
return;
70+
}
71+
task = task.task;
72+
}
73+
services.taskfile.goToDefinition(task, preview);
74+
}));
75+
76+
// Go to definition picker
77+
context.subscriptions.push(vscode.commands.registerCommand('vscode-task.goToDefinitionPicker', () => {
78+
if (this._taskfile === undefined || this._taskfile.tasks.length === 0) {
79+
vscode.window.showInformationMessage('No tasks found');
80+
return;
81+
}
82+
vscode.window.showQuickPick(this._taskfile.tasks.map(t => t.name)).then((taskName) => {
83+
if (taskName) {
84+
let task = this._taskfile?.tasks.find(t => t.name === taskName);
85+
if (task === undefined) {
86+
return;
87+
}
88+
services.taskfile.goToDefinition(task);
89+
}
90+
});
6391
}));
6492
}
6593

0 commit comments

Comments
 (0)