Files
vscode-codeql/extensions/ql-vscode/src/language-support/query-editor.ts

110 lines
3.8 KiB
TypeScript

import { Uri, window } from "vscode";
import { CodeQLCliServer } from "../codeql-cli/cli";
import { QueryRunner } from "../query-server";
import { basename, join } from "path";
import { getErrorMessage } from "../common/helpers-pure";
import { redactableError } from "../common/errors";
import { AppCommandManager, QueryEditorCommands } from "../common/commands";
import { extLogger } from "../common/logging/vscode";
import { showAndLogExceptionWithTelemetry } from "../common/logging";
import { telemetryListener } from "../common/vscode/telemetry";
type QueryEditorOptions = {
commandManager: AppCommandManager;
queryRunner: QueryRunner;
cliServer: CodeQLCliServer;
qhelpTmpDir: string;
};
export function getQueryEditorCommands({
commandManager,
queryRunner,
cliServer,
qhelpTmpDir,
}: QueryEditorOptions): QueryEditorCommands {
const openReferencedFileCommand = async (selectedQuery: Uri) =>
await openReferencedFile(queryRunner, cliServer, selectedQuery);
return {
"codeQL.openReferencedFile": openReferencedFileCommand,
// Since we are tracking extension usage through commands, this command mirrors the "codeQL.openReferencedFile" command
"codeQL.openReferencedFileContextEditor": openReferencedFileCommand,
// Since we are tracking extension usage through commands, this command mirrors the "codeQL.openReferencedFile" command
"codeQL.openReferencedFileContextExplorer": openReferencedFileCommand,
"codeQL.previewQueryHelp": async (selectedQuery: Uri) =>
await previewQueryHelp(
commandManager,
cliServer,
qhelpTmpDir,
selectedQuery,
),
"codeQL.previewQueryHelpContextEditor": async (selectedQuery: Uri) =>
await previewQueryHelp(
commandManager,
cliServer,
qhelpTmpDir,
selectedQuery,
),
"codeQL.previewQueryHelpContextExplorer": async (selectedQuery: Uri) =>
await previewQueryHelp(
commandManager,
cliServer,
qhelpTmpDir,
selectedQuery,
),
};
}
async function previewQueryHelp(
commandManager: AppCommandManager,
cliServer: CodeQLCliServer,
qhelpTmpDir: string,
selectedQuery: Uri,
): Promise<void> {
// selectedQuery is unpopulated when executing through the command palette
const pathToQhelp = selectedQuery
? selectedQuery.fsPath
: window.activeTextEditor?.document.uri.fsPath;
if (pathToQhelp) {
// Create temporary directory
const relativePathToMd = `${basename(pathToQhelp, ".qhelp")}.md`;
const absolutePathToMd = join(qhelpTmpDir, relativePathToMd);
const uri = Uri.file(absolutePathToMd);
try {
await cliServer.generateQueryHelp(pathToQhelp, absolutePathToMd);
await commandManager.execute("markdown.showPreviewToSide", uri);
} catch (e) {
const errorMessage = getErrorMessage(e).includes(
"Generating qhelp in markdown",
)
? redactableError`Could not generate markdown from ${pathToQhelp}: Bad formatting in .qhelp file.`
: redactableError`Could not open a preview of the generated file (${absolutePathToMd}).`;
void showAndLogExceptionWithTelemetry(
extLogger,
telemetryListener,
errorMessage,
{
fullMessage: `${errorMessage}\n${getErrorMessage(e)}`,
},
);
}
}
}
async function openReferencedFile(
qs: QueryRunner,
cliServer: CodeQLCliServer,
selectedQuery: Uri,
): Promise<void> {
// If no file is selected, the path of the file in the editor is selected
const path =
selectedQuery?.fsPath || window.activeTextEditor?.document.uri.fsPath;
if (qs !== undefined && path) {
const resolved = await cliServer.resolveQlref(path);
const uri = Uri.file(resolved.resolvedPath);
await window.showTextDocument(uri, { preview: false });
}
}