Skip to content

Commit

Permalink
fix: support task object notation in sidebar (#1214)
Browse files Browse the repository at this point in the history
  • Loading branch information
nayeemrmn authored Nov 26, 2024
1 parent 556b79b commit 3a7123d
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 56 deletions.
4 changes: 2 additions & 2 deletions client/src/lsp_extensions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ export const registryState = new NotificationType<RegistryStateParams>(

export interface TaskRequestResponse {
name: string;
// TODO(nayeemrmn): `detail` is being renamed to `command`. Eventually update
// the server's serialization of this field to `command` and remove `detail`.
// TODO(nayeemrmn): `detail` is renamed to `command` for Deno > 2.1.1. Remove
// `detail` eventually.
command: string | null;
detail: string;
sourceUri: string;
Expand Down
4 changes: 2 additions & 2 deletions client/src/tasks_sidebar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ export class DenoTasksTreeDataProvider implements TreeDataProvider<TreeItem> {
for (const task of taskDefinitions.tasks) {
if (
anchor.isAfterOrEqual(task.nameRange.start) &&
anchor.isBeforeOrEqual(task.commandRange.end)
anchor.isBeforeOrEqual(task.valueRange.end)
) {
const sourceUri = window.activeTextEditor.document.uri;
const workspaceFolder = (workspace.workspaceFolders ?? []).find((f) =>
Expand Down Expand Up @@ -272,7 +272,7 @@ export class DenoTasksTreeDataProvider implements TreeDataProvider<TreeItem> {
if (!task) return taskDefinitions.location.range.start;

return taskDefinitions.tasks.find((s) => s.name === task.task.name)
?.commandRange.start;
?.valueRange.start;
}

async #openTaskDefinition(selection: DenoJSON | DenoTask) {
Expand Down
117 changes: 65 additions & 52 deletions client/src/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,12 @@ import * as path from "path";
import * as process from "process";
import {
Location,
Position,
Range,
TextDocument,
workspace,
WorkspaceFolder,
} from "vscode";
import { JSONVisitor, visit } from "jsonc-parser/lib/esm/main.js";
import * as jsoncParser from "jsonc-parser/lib/esm/main.js";
import { semver } from "./semver";

/** Assert that the condition is "truthy", otherwise throw. */
Expand Down Expand Up @@ -144,68 +143,82 @@ export interface TaskDefinitionRange {
name: string;
command: string;
nameRange: Range;
commandRange: Range;
valueRange: Range;
}

export function readTaskDefinitions(
document: TextDocument,
content = document.getText(),
) {
let depth = 0;
let start: Position | undefined;
let end: Position | undefined;
let inTasks = false;
let currentTask: { name: string; nameRange: Range } | undefined;

const root = jsoncParser.parseTree(content);
if (!root) {
return undefined;
}
if (root.type != "object" || !root.children) {
return undefined;
}
const tasksProperty = root.children.find((n) =>
n.type == "property" && n.children?.[0]?.value == "tasks"
);
if (!tasksProperty) {
return undefined;
}
const tasksValue = tasksProperty.children?.[1];
if (!tasksValue || tasksValue.type != "object" || !tasksValue.children) {
return undefined;
}
const tasks: TaskDefinitionRange[] = [];
const visitor: JSONVisitor = {
onObjectBegin() {
depth++;
},
onObjectEnd(offset) {
if (inTasks) {
end = document.positionAt(offset);
inTasks = false;
}
depth--;
},
onLiteralValue(value: unknown, offset: number, length: number) {
if (currentTask && typeof value === "string") {
tasks.push({
...currentTask,
command: value,
commandRange: new Range(
document.positionAt(offset),
document.positionAt(offset + length),
),
});
currentTask = undefined;
for (const taskProperty of tasksValue.children) {
const taskKey = taskProperty.children?.[0];
if (
taskProperty.type != "property" || !taskKey || taskKey.type != "string"
) {
continue;
}
const taskValue = taskProperty.children?.[1];
if (!taskValue) {
continue;
}
let command;
if (taskValue.type == "string") {
command = taskValue.value;
} else if (taskValue.type == "object" && taskValue.children) {
const commandProperty = taskValue.children.find((n) =>
n.type == "property" && n.children?.[0]?.value == "command"
);
if (!commandProperty) {
continue;
}
},
onObjectProperty(property: string, offset: number, length: number) {
if (depth === 1 && property === "tasks") {
inTasks = true;
start = document.positionAt(offset);
} else if (inTasks) {
currentTask = {
name: property,
nameRange: new Range(
document.positionAt(offset),
document.positionAt(offset + length),
),
};
const commandValue = commandProperty.children?.[1];
if (!commandValue || commandValue.type != "string") {
continue;
}
},
};

visit(content, visitor);

if (start === undefined) {
return undefined;
command = commandValue.value;
} else {
continue;
}
tasks.push({
name: taskKey.value,
nameRange: new Range(
document.positionAt(taskKey.offset),
document.positionAt(taskKey.offset + taskKey.length),
),
command,
valueRange: new Range(
document.positionAt(taskValue.offset),
document.positionAt(taskValue.offset + taskValue.length),
),
});
}

return {
location: new Location(document.uri, new Range(start, end ?? start)),
location: new Location(
document.uri,
new Range(
document.positionAt(tasksProperty.offset),
document.positionAt(tasksProperty.offset + tasksProperty.length),
),
),
tasks,
};
}

0 comments on commit 3a7123d

Please sign in to comment.