Skip to content

Commit

Permalink
Refactoring: Move commands into a command_variables.ts (bazel-contr…
Browse files Browse the repository at this point in the history
…ib#348)

* Refactoring: Move commands into a `command_variables.ts`

This commit moves all the commands intended to be used as "comand
variables" from the `extension.ts` into a new `command_variables.ts`
file. This is a precursory refactoring before introducing additional
command variables.

* Correct copyright year
  • Loading branch information
vogelsgesang authored Feb 28, 2024
1 parent 6d3e988 commit 2180a4c
Show file tree
Hide file tree
Showing 2 changed files with 146 additions and 118 deletions.
143 changes: 143 additions & 0 deletions src/extension/command_variables.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
// Copyright 2024 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import * as path from "path";
import * as vscode from "vscode";
import { getDefaultBazelExecutablePath } from "./configuration";
import { BazelWorkspaceInfo } from "../bazel";
import { BazelCQuery } from "../bazel/bazel_cquery";
import { BazelInfo } from "../bazel/bazel_info";

/**
* Get the output of the given target.
*
* If there are multiple outputs, a quick-pick window will be opened asking the
* user to choose one.
*
* The `bazel.getTargetOutput` command can be used in launch configurations to
* obtain the path to an executable built by Bazel. For example, you can set the
* "program" attribute of a launch configuration to an input variable:
*
* ```
* "program": "${input:binaryOutputLocation}"
* ```
*
* Then define a command input variable:
*
* ```
* "inputs": [
* {
* "id": "binaryOutputLocation",
* "type": "command",
* "command": "bazel.getTargetOutput",
* "args": ["//my/binary:target"],
* }
* ]
* ```
*
* Additional Bazel flags can be provided:
*
* ```
* "inputs": [
* {
* "id": "debugOutputLocation",
* "type": "command",
* "command": "bazel.getTargetOutput",
* "args": ["//my/binary:target", ["--compilation_mode", "dbg"]],
* }
* ]
* ```
*/
async function bazelGetTargetOutput(
target: string,
options: string[] = [],
): Promise<string> {
// Workaround for https://github.com/microsoft/vscode/issues/167970
if (Array.isArray(target)) {
options = (target[1] || []) as string[];
target = target[0] as string;
}
const workspaceInfo = await BazelWorkspaceInfo.fromWorkspaceFolders();
if (!workspaceInfo) {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
vscode.window.showInformationMessage(
"Please open a Bazel workspace folder to use this command.",
);

return;
}
const outputPath = await new BazelInfo(
getDefaultBazelExecutablePath(),
workspaceInfo.bazelWorkspacePath,
).run("output_path");
const outputs = await new BazelCQuery(
getDefaultBazelExecutablePath(),
workspaceInfo.bazelWorkspacePath,
).queryOutputs(target, options);
switch (outputs.length) {
case 0:
throw new Error(`Target ${target} has no outputs.`);
case 1:
return path.join(outputPath, "..", outputs[0]);
default:
return await vscode.window.showQuickPick(outputs, {
placeHolder: `Pick an output of ${target}`,
});
}
}

/**
* Get the output of `bazel info` for the given key.
*
* If there are multiple outputs, a quick-pick window will be opened asking the
* user to choose one.
*/
async function bazelInfo(key: string): Promise<string> {
const workspaceInfo = await BazelWorkspaceInfo.fromWorkspaceFolders();
if (!workspaceInfo) {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
vscode.window.showInformationMessage(
"Please open a Bazel workspace folder to use this command.",
);
return;
}
return new BazelInfo(
getDefaultBazelExecutablePath(),
workspaceInfo.bazelWorkspacePath,
).run(key);
}

/**
* Activate all "command variables"
*/
export function activateCommandVariables(): vscode.Disposable[] {
return [
vscode.commands.registerCommand(
"bazel.getTargetOutput",
bazelGetTargetOutput,
),
...[
"bazel-bin",
"bazel-genfiles",
"bazel-testlogs",
"execution_root",
"output_base",
"output_path",
].map((key) =>
vscode.commands.registerCommand(`bazel.info.${key}`, () =>
bazelInfo(key),
),
),
];
}
121 changes: 3 additions & 118 deletions src/extension/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.

import * as path from "path";
import * as vscode from "vscode";
import {
LanguageClient,
Expand All @@ -32,8 +31,6 @@ import {
IBazelCommandAdapter,
parseExitCode,
} from "../bazel";
import { BazelCQuery } from "../bazel/bazel_cquery";
import { BazelInfo } from "../bazel/bazel_info";
import {
BuildifierDiagnosticsManager,
BuildifierFormatProvider,
Expand All @@ -45,6 +42,7 @@ import { BazelGotoDefinitionProvider } from "../definition/bazel_goto_definition
import { BazelTargetSymbolProvider } from "../symbols";
import { BazelWorkspaceTreeProvider } from "../workspace-tree";
import { getDefaultBazelExecutablePath } from "./configuration";
import { activateCommandVariables } from "./command_variables";

/**
* Called when the extension is activated; that is, when its first command is
Expand Down Expand Up @@ -131,22 +129,6 @@ export async function activate(context: vscode.ExtensionContext) {
"bazel.copyTargetToClipboard",
bazelCopyTargetToClipboard,
),
vscode.commands.registerCommand(
"bazel.getTargetOutput",
bazelGetTargetOutput,
),
...[
"bazel-bin",
"bazel-genfiles",
"bazel-testlogs",
"execution_root",
"output_base",
"output_path",
].map((key) =>
vscode.commands.registerCommand(`bazel.info.${key}`, () =>
bazelInfo(key),
),
),
// CodeLens provider for BUILD files
vscode.languages.registerCodeLensProvider(
[{ pattern: "**/BUILD" }, { pattern: "**/BUILD.bazel" }],
Expand All @@ -170,6 +152,8 @@ export async function activate(context: vscode.ExtensionContext) {
vscode.tasks.onDidStartTask(onTaskStart),
vscode.tasks.onDidStartTaskProcess(onTaskProcessStart),
vscode.tasks.onDidEndTaskProcess(onTaskProcessEnd),
// Command variables
...activateCommandVariables(),
);

// Notify the user if buildifier is not available on their path (or where
Expand Down Expand Up @@ -490,105 +474,6 @@ function bazelCopyTargetToClipboard(adapter: IBazelCommandAdapter | undefined) {
vscode.env.clipboard.writeText(target);
}

/**
* Get the output of the given target.
*
* If there are multiple outputs, a quick-pick window will be opened asking the
* user to choose one.
*
* The `bazel.getTargetOutput` command can be used in launch configurations to
* obtain the path to an executable built by Bazel. For example, you can set the
* "program" attribute of a launch configuration to an input variable:
*
* ```
* "program": "${input:binaryOutputLocation}"
* ```
*
* Then define a command input variable:
*
* ```
* "inputs": [
* {
* "id": "binaryOutputLocation",
* "type": "command",
* "command": "bazel.getTargetOutput",
* "args": ["//my/binary:target"],
* }
* ]
* ```
*
* Additional Bazel flags can be provided:
*
* ```
* "inputs": [
* {
* "id": "debugOutputLocation",
* "type": "command",
* "command": "bazel.getTargetOutput",
* "args": ["//my/binary:target", ["--compilation_mode", "dbg"]],
* }
* ]
* ```
*/
async function bazelGetTargetOutput(
target: string,
options: string[] = [],
): Promise<string> {
// Workaround for https://github.com/microsoft/vscode/issues/167970
if (Array.isArray(target)) {
options = (target[1] || []) as string[];
target = target[0] as string;
}
const workspaceInfo = await BazelWorkspaceInfo.fromWorkspaceFolders();
if (!workspaceInfo) {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
vscode.window.showInformationMessage(
"Please open a Bazel workspace folder to use this command.",
);

return;
}
const outputPath = await new BazelInfo(
getDefaultBazelExecutablePath(),
workspaceInfo.bazelWorkspacePath,
).run("output_path");
const outputs = await new BazelCQuery(
getDefaultBazelExecutablePath(),
workspaceInfo.bazelWorkspacePath,
).queryOutputs(target, options);
switch (outputs.length) {
case 0:
throw new Error(`Target ${target} has no outputs.`);
case 1:
return path.join(outputPath, "..", outputs[0]);
default:
return await vscode.window.showQuickPick(outputs, {
placeHolder: `Pick an output of ${target}`,
});
}
}

/**
* Get the output of `bazel info` for the given key.
*
* If there are multiple outputs, a quick-pick window will be opened asking the
* user to choose one.
*/
async function bazelInfo(key: string): Promise<string> {
const workspaceInfo = await BazelWorkspaceInfo.fromWorkspaceFolders();
if (!workspaceInfo) {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
vscode.window.showInformationMessage(
"Please open a Bazel workspace folder to use this command.",
);
return;
}
return new BazelInfo(
getDefaultBazelExecutablePath(),
workspaceInfo.bazelWorkspacePath,
).run(key);
}

function onTaskStart(event: vscode.TaskStartEvent) {
const bazelTaskInfo = getBazelTaskInfo(event.execution.task);
if (bazelTaskInfo) {
Expand Down

0 comments on commit 2180a4c

Please sign in to comment.