Merge pull request #2511 from github/koesie10/show-and-log-without-vscode

Make the showAndLog family of functions usable without the `vscode` module
This commit is contained in:
Koen Vlaswinkel
2023-06-15 09:29:18 +02:00
committed by GitHub
56 changed files with 547 additions and 343 deletions

View File

@@ -25,7 +25,7 @@ import {
import {
showAndLogErrorMessage,
showAndLogWarningMessage,
} from "../common/vscode/log";
} from "../common/logging";
/**
* distribution.ts
@@ -160,6 +160,7 @@ export class DistributionManager implements DistributionProvider {
if (this.config.customCodeQlPath) {
if (!(await pathExists(this.config.customCodeQlPath))) {
void showAndLogErrorMessage(
extLogger,
`The CodeQL executable path is specified as "${this.config.customCodeQlPath}" ` +
"by a configuration setting, but a CodeQL executable could not be found at that path. Please check " +
"that a CodeQL executable exists at the specified path or remove the setting.",
@@ -852,6 +853,7 @@ export async function getExecutableFromDirectory(
function warnDeprecatedLauncher() {
void showAndLogWarningMessage(
extLogger,
`The "${deprecatedCodeQlLauncherName()!}" launcher has been deprecated and will be removed in a future version. ` +
`Please use "${codeQlLauncherName()}" instead. It is recommended to update to the latest CodeQL binaries.`,
);

View File

@@ -4,7 +4,7 @@ import { isQueryLanguage, QueryLanguage } from "../common/query-language";
import { getOnDiskWorkspaceFolders } from "../common/vscode/workspace-folders";
import { extLogger } from "../common";
import { UserCancellationException } from "../common/vscode/progress";
import { showAndLogErrorMessage } from "../common/vscode/log";
import { showAndLogErrorMessage } from "../common/logging";
/**
* Finds the language that a query targets.
@@ -59,6 +59,7 @@ export async function askForLanguage(
throw new UserCancellationException("Cancelled.");
} else {
void showAndLogErrorMessage(
extLogger,
"Language not found. Language must be specified manually.",
);
}
@@ -67,6 +68,7 @@ export async function askForLanguage(
if (!isQueryLanguage(language)) {
void showAndLogErrorMessage(
extLogger,
`Language '${language}' is not supported. Only languages ${Object.values(
QueryLanguage,
).join(", ")} are supported.`,

View File

@@ -1,14 +1,14 @@
import { Credentials } from "./authentication";
import { Disposable } from "../pure/disposable-object";
import { AppEventEmitter } from "./events";
import { Logger } from "./logging";
import { NotificationLogger } from "./logging";
import { Memento } from "./memento";
import { AppCommandManager } from "./commands";
export interface App {
createEventEmitter<T>(): AppEventEmitter<T>;
readonly mode: AppMode;
readonly logger: Logger;
readonly logger: NotificationLogger;
readonly subscriptions: Disposable[];
readonly extensionPath: string;
readonly globalStoragePath: string;

View File

@@ -1,4 +1,6 @@
export * from "./logger";
export * from "./notification-logger";
export * from "./notifications";
export * from "./tee-logger";
export * from "./vscode/loggers";
export * from "./vscode/output-channel-logger";

View File

@@ -0,0 +1,7 @@
import { Logger } from "./logger";
export interface NotificationLogger extends Logger {
showErrorMessage(message: string): Promise<void>;
showWarningMessage(message: string): Promise<void>;
showInformationMessage(message: string): Promise<void>;
}

View File

@@ -0,0 +1,89 @@
import { NotificationLogger } from "./notification-logger";
export interface ShowAndLogOptions {
/**
* An alternate message that is added to the log, but not displayed in the popup.
* This is useful for adding extra detail to the logs that would be too noisy for the popup.
*/
fullMessage?: string;
}
/**
* Show an error message and log it to the console
*
* @param logger The logger that will receive the message.
* @param message The message to show.
* @param options? See individual fields on `ShowAndLogOptions` type.
*
* @return A promise that resolves to the selected item or undefined when being dismissed.
*/
export async function showAndLogErrorMessage(
logger: NotificationLogger,
message: string,
options?: ShowAndLogOptions,
): Promise<void> {
return internalShowAndLog(
logger,
dropLinesExceptInitial(message),
logger.showErrorMessage,
{ fullMessage: message, ...options },
);
}
function dropLinesExceptInitial(message: string, n = 2) {
return message.toString().split(/\r?\n/).slice(0, n).join("\n");
}
/**
* Show a warning message and log it to the console
*
* @param logger The logger that will receive the message.
* @param message The message to show.
* @param options? See individual fields on `ShowAndLogOptions` type.
*
* @return A promise that resolves to the selected item or undefined when being dismissed.
*/
export async function showAndLogWarningMessage(
logger: NotificationLogger,
message: string,
options?: ShowAndLogOptions,
): Promise<void> {
return internalShowAndLog(
logger,
message,
logger.showWarningMessage,
options,
);
}
/**
* Show an information message and log it to the console
*
* @param logger The logger that will receive the message.
* @param message The message to show.
* @param options? See individual fields on `ShowAndLogOptions` type.
*
* @return A promise that resolves to the selected item or undefined when being dismissed.
*/
export async function showAndLogInformationMessage(
logger: NotificationLogger,
message: string,
options?: ShowAndLogOptions,
): Promise<void> {
return internalShowAndLog(
logger,
message,
logger.showInformationMessage,
options,
);
}
async function internalShowAndLog(
logger: NotificationLogger,
message: string,
fn: (message: string) => Promise<void>,
{ fullMessage }: ShowAndLogOptions = {},
): Promise<void> {
void logger.log(fullMessage || message);
await fn.bind(logger)(message);
}

View File

@@ -1,11 +1,15 @@
import { window as Window, OutputChannel, Progress } from "vscode";
import { Logger, LogOptions } from "../logger";
import { DisposableObject } from "../../../pure/disposable-object";
import { NotificationLogger } from "../notification-logger";
/**
* A logger that writes messages to an output channel in the VS Code Output tab.
*/
export class OutputChannelLogger extends DisposableObject implements Logger {
export class OutputChannelLogger
extends DisposableObject
implements Logger, NotificationLogger
{
public readonly outputChannel: OutputChannel;
isCustomLogDirectory: boolean;
@@ -42,6 +46,30 @@ export class OutputChannelLogger extends DisposableObject implements Logger {
show(preserveFocus?: boolean): void {
this.outputChannel.show(preserveFocus);
}
async showErrorMessage(message: string): Promise<void> {
await this.showMessage(message, Window.showErrorMessage);
}
async showInformationMessage(message: string): Promise<void> {
await this.showMessage(message, Window.showInformationMessage);
}
async showWarningMessage(message: string): Promise<void> {
await this.showMessage(message, Window.showWarningMessage);
}
private async showMessage(
message: string,
show: (message: string, ...items: string[]) => Thenable<string | undefined>,
): Promise<void> {
const label = "Show Log";
const result = await show(message, label);
if (result === label) {
this.show();
}
}
}
export type ProgressReporter = Progress<{ message: string }>;

View File

@@ -1,6 +1,10 @@
import { commands, Disposable } from "vscode";
import { CommandFunction, CommandManager } from "../../packages/commands";
import { extLogger, OutputChannelLogger } from "../logging";
import {
extLogger,
NotificationLogger,
showAndLogWarningMessage,
} from "../logging";
import {
asError,
getErrorMessage,
@@ -9,10 +13,7 @@ import {
import { redactableError } from "../../pure/errors";
import { UserCancellationException } from "./progress";
import { telemetryListener } from "../../telemetry";
import {
showAndLogExceptionWithTelemetry,
showAndLogWarningMessage,
} from "./log";
import { showAndLogExceptionWithTelemetry } from "./logging";
/**
* Create a command manager for VSCode, wrapping registerCommandWithErrorHandling
@@ -20,9 +21,9 @@ import {
*/
export function createVSCodeCommandManager<
Commands extends Record<string, CommandFunction>,
>(outputLogger?: OutputChannelLogger): CommandManager<Commands> {
>(logger?: NotificationLogger): CommandManager<Commands> {
return new CommandManager((commandId, task) => {
return registerCommandWithErrorHandling(commandId, task, outputLogger);
return registerCommandWithErrorHandling(commandId, task, logger);
}, wrapExecuteCommand);
}
@@ -32,11 +33,12 @@ export function createVSCodeCommandManager<
* @param commandId The ID of the command to register.
* @param task The task to run. It is passed directly to `commands.registerCommand`. Any
* arguments to the command handler are passed on to the task.
* @param logger The logger to use for error reporting.
*/
export function registerCommandWithErrorHandling(
commandId: string,
task: (...args: any[]) => Promise<any>,
outputLogger = extLogger,
logger: NotificationLogger = extLogger,
): Disposable {
return commands.registerCommand(commandId, async (...args: any[]) => {
const startTime = Date.now();
@@ -52,11 +54,9 @@ export function registerCommandWithErrorHandling(
if (e instanceof UserCancellationException) {
// User has cancelled this action manually
if (e.silent) {
void outputLogger.log(errorMessage.fullMessage);
void logger.log(errorMessage.fullMessage);
} else {
void showAndLogWarningMessage(errorMessage.fullMessage, {
outputLogger,
});
void showAndLogWarningMessage(logger, errorMessage.fullMessage);
}
} else {
// Include the full stack in the error log only.
@@ -64,8 +64,7 @@ export function registerCommandWithErrorHandling(
const fullMessage = errorStack
? `${errorMessage.fullMessage}\n${errorStack}`
: errorMessage.fullMessage;
void showAndLogExceptionWithTelemetry(errorMessage, {
outputLogger,
void showAndLogExceptionWithTelemetry(logger, errorMessage, {
fullMessage,
extraTelemetryProperties: {
command: commandId,

View File

@@ -7,7 +7,8 @@ import {
getErrorMessage,
getErrorStack,
} from "../../pure/helpers-pure";
import { showAndLogExceptionWithTelemetry } from "./log";
import { extLogger } from "../logging";
import { showAndLogExceptionWithTelemetry } from "./logging";
export async function tryOpenExternalFile(
commandManager: AppCommandManager,
@@ -34,6 +35,7 @@ the file in the file explorer and dragging it into the workspace.`,
await commandManager.execute("revealFileInOS", uri);
} catch (e) {
void showAndLogExceptionWithTelemetry(
extLogger,
redactableError(
asError(e),
)`Failed to reveal file in OS: ${getErrorMessage(e)}`,
@@ -42,6 +44,7 @@ the file in the file explorer and dragging it into the workspace.`,
}
} else {
void showAndLogExceptionWithTelemetry(
extLogger,
redactableError(asError(e))`Could not open file ${fileLocation}`,
{
fullMessage: `${getErrorMessage(e)}\n${getErrorStack(e)}`,

View File

@@ -1,109 +0,0 @@
import { window } from "vscode";
import { RedactableError } from "../../pure/errors";
import { telemetryListener } from "../../telemetry";
import { extLogger, OutputChannelLogger } from "../logging";
interface ShowAndLogExceptionOptions extends ShowAndLogOptions {
/** Custom properties to include in the telemetry report. */
extraTelemetryProperties?: { [key: string]: string };
}
interface ShowAndLogOptions {
/** The output logger that will receive the message. */
outputLogger?: OutputChannelLogger;
/** A set of items that will be rendered as actions in the message. */
items?: string[];
/**
* An alternate message that is added to the log, but not displayed in the popup.
* This is useful for adding extra detail to the logs that would be too noisy for the popup.
*/
fullMessage?: string;
}
/**
* Show an error message, log it to the console, and emit redacted information as telemetry
*
* @param error The error to show. Only redacted information will be included in the telemetry.
* @param options See individual fields on `ShowAndLogExceptionOptions` type.
*
* @return A promise that resolves to the selected item or undefined when being dismissed.
*/
export async function showAndLogExceptionWithTelemetry(
error: RedactableError,
options: ShowAndLogExceptionOptions = {},
): Promise<string | undefined> {
telemetryListener?.sendError(error, options.extraTelemetryProperties);
return showAndLogErrorMessage(error.fullMessage, options);
}
/**
* Show an error message and log it to the console
*
* @param message The message to show.
* @param options See individual fields on `ShowAndLogOptions` type.
*
* @return A promise that resolves to the selected item or undefined when being dismissed.
*/
export async function showAndLogErrorMessage(
message: string,
options?: ShowAndLogOptions,
): Promise<string | undefined> {
return internalShowAndLog(
dropLinesExceptInitial(message),
window.showErrorMessage,
{ fullMessage: message, ...options },
);
}
function dropLinesExceptInitial(message: string, n = 2) {
return message.toString().split(/\r?\n/).slice(0, n).join("\n");
}
/**
* Show a warning message and log it to the console
*
* @param message The message to show.
* @param options See individual fields on `ShowAndLogOptions` type.
*
* @return A promise that resolves to the selected item or undefined when being dismissed.
*/
export async function showAndLogWarningMessage(
message: string,
options?: ShowAndLogOptions,
): Promise<string | undefined> {
return internalShowAndLog(message, window.showWarningMessage, options);
}
/**
* Show an information message and log it to the console
*
* @param message The message to show.
* @param options See individual fields on `ShowAndLogOptions` type.
*
* @return A promise that resolves to the selected item or undefined when being dismissed.
*/
export async function showAndLogInformationMessage(
message: string,
options?: ShowAndLogOptions,
): Promise<string | undefined> {
return internalShowAndLog(message, window.showInformationMessage, options);
}
type ShowMessageFn = (
message: string,
...items: string[]
) => Thenable<string | undefined>;
async function internalShowAndLog(
message: string,
fn: ShowMessageFn,
{ items = [], outputLogger = extLogger, fullMessage }: ShowAndLogOptions = {},
): Promise<string | undefined> {
const label = "Show Log";
void outputLogger.log(fullMessage || message);
const result = await fn(message, label, ...items);
if (result === label) {
outputLogger.show();
}
return result;
}

View File

@@ -0,0 +1,30 @@
import {
NotificationLogger,
showAndLogErrorMessage,
ShowAndLogOptions,
} from "../logging";
import { RedactableError } from "../../pure/errors";
import { telemetryListener } from "../../telemetry";
interface ShowAndLogExceptionOptions extends ShowAndLogOptions {
/** Custom properties to include in the telemetry report. */
extraTelemetryProperties?: { [key: string]: string };
}
/**
* Show an error message, log it to the console, and emit redacted information as telemetry
*
* @param logger The logger that will receive the message.
* @param error The error to show. Only redacted information will be included in the telemetry.
* @param options See individual fields on `ShowAndLogExceptionOptions` type.
*
* @return A promise that resolves to the selected item or undefined when being dismissed.
*/
export async function showAndLogExceptionWithTelemetry(
logger: NotificationLogger,
error: RedactableError,
options: ShowAndLogExceptionOptions = {},
): Promise<void> {
telemetryListener?.sendError(error, options.extraTelemetryProperties);
return showAndLogErrorMessage(logger, error.fullMessage, options);
}

View File

@@ -3,7 +3,7 @@ import {
TreeViewContextMultiSelectionCommandFunction,
TreeViewContextSingleSelectionCommandFunction,
} from "../commands";
import { showAndLogErrorMessage } from "./log";
import { showAndLogErrorMessage, NotificationLogger } from "../logging";
// A hack to match types that are not an array, which is useful to help avoid
// misusing createSingleSelectionCommand, e.g. where T accidentally gets instantiated
@@ -25,6 +25,7 @@ type SelectionCommand<T extends NotArray> = CreateSupertypeOf<
>;
export function createSingleSelectionCommand<T extends NotArray>(
logger: NotificationLogger,
f: (argument: T) => Promise<void>,
itemName: string,
): SelectionCommand<T> {
@@ -32,7 +33,10 @@ export function createSingleSelectionCommand<T extends NotArray>(
if (multiSelect === undefined || multiSelect.length === 1) {
return f(singleItem);
} else {
void showAndLogErrorMessage(`Please select a single ${itemName}.`);
void showAndLogErrorMessage(
logger,
`Please select a single ${itemName}.`,
);
return;
}
};

View File

@@ -3,7 +3,7 @@ import { VSCodeCredentials } from "./authentication";
import { Disposable } from "../../pure/disposable-object";
import { App, AppMode, EnvironmentContext } from "../app";
import { AppEventEmitter } from "../events";
import { extLogger, Logger, queryServerLogger } from "../logging";
import { extLogger, NotificationLogger, queryServerLogger } from "../logging";
import { Memento } from "../memento";
import { VSCodeAppEventEmitter } from "./events";
import { AppCommandManager, QueryServerCommandManager } from "../commands";
@@ -55,7 +55,7 @@ export class ExtensionApp implements App {
}
}
public get logger(): Logger {
public get logger(): NotificationLogger {
return extLogger;
}

View File

@@ -5,7 +5,8 @@ import {
ToCompareViewMessage,
QueryCompareResult,
} from "../pure/interface-types";
import { Logger } from "../common";
import { extLogger, Logger } from "../common";
import { showAndLogExceptionWithTelemetry } from "../common/vscode/logging";
import { CodeQLCliServer } from "../codeql-cli/cli";
import { DatabaseManager } from "../databases/local-databases";
import { jumpToLocation } from "../databases/local-databases/locations";
@@ -25,8 +26,6 @@ import {
import { telemetryListener } from "../telemetry";
import { redactableError } from "../pure/errors";
import { showAndLogExceptionWithTelemetry } from "../common/vscode/log";
interface ComparePair {
from: CompletedLocalQueryInfo;
to: CompletedLocalQueryInfo;
@@ -152,6 +151,7 @@ export class CompareView extends AbstractWebview<
case "unhandledError":
void showAndLogExceptionWithTelemetry(
extLogger,
redactableError(
msg.error,
)`Unhandled error in result comparison view: ${msg.error.message}`,

View File

@@ -9,7 +9,7 @@ import { join } from "path";
import { App } from "../common/app";
import { withProgress } from "../common/vscode/progress";
import { pickExtensionPackModelFile } from "./extension-pack-picker";
import { showAndLogErrorMessage } from "../common/vscode/log";
import { showAndLogErrorMessage } from "../common/logging";
const SUPPORTED_LANGUAGES: string[] = ["java", "csharp"];
@@ -56,12 +56,13 @@ export class DataExtensionsEditorModule {
"codeQL.openDataExtensionsEditor": async () => {
const db = this.databaseManager.currentDatabaseItem;
if (!db) {
void showAndLogErrorMessage("No database selected");
void showAndLogErrorMessage(this.app.logger, "No database selected");
return;
}
if (!SUPPORTED_LANGUAGES.includes(db.language)) {
void showAndLogErrorMessage(
this.app.logger,
`The data extensions editor is not supported for ${db.language} databases.`,
);
return;
@@ -71,6 +72,7 @@ export class DataExtensionsEditorModule {
async (progress, token) => {
if (!(await this.cliServer.cliConstraints.supportsQlpacksKind())) {
void showAndLogErrorMessage(
this.app.logger,
`This feature requires CodeQL CLI version ${CliVersionConstraint.CLI_VERSION_WITH_QLPACKS_KIND.format()} or later.`,
);
return;
@@ -79,6 +81,7 @@ export class DataExtensionsEditorModule {
const modelFile = await pickExtensionPackModelFile(
this.cliServer,
db,
this.app.logger,
progress,
token,
);

View File

@@ -17,7 +17,7 @@ import {
} from "../pure/interface-types";
import { ProgressUpdate } from "../common/vscode/progress";
import { QueryRunner } from "../query-server";
import { extLogger } from "../common";
import { showAndLogExceptionWithTelemetry } from "../common/vscode/logging";
import { outputFile, pathExists, readFile } from "fs-extra";
import { load as loadYaml } from "js-yaml";
import { DatabaseItem, DatabaseManager } from "../databases/local-databases";
@@ -42,10 +42,7 @@ import {
} from "./auto-model";
import { showLlmGeneration } from "../config";
import { getAutoModelUsages } from "./auto-model-usages-query";
import {
showAndLogErrorMessage,
showAndLogExceptionWithTelemetry,
} from "../common/vscode/log";
import { showAndLogErrorMessage } from "../common/logging";
export class DataExtensionsEditorView extends AbstractWebview<
ToDataExtensionsEditorMessage,
@@ -167,10 +164,10 @@ export class DataExtensionsEditorView extends AbstractWebview<
"Original file of this result is not in the database's source archive.",
);
} else {
void extLogger.log(`Unable to handleMsgFromView: ${e.message}`);
void this.app.logger.log(`Unable to handleMsgFromView: ${e.message}`);
}
} else {
void extLogger.log(`Unable to handleMsgFromView: ${e}`);
void this.app.logger.log(`Unable to handleMsgFromView: ${e}`);
}
}
}
@@ -187,7 +184,7 @@ export class DataExtensionsEditorView extends AbstractWebview<
await outputFile(this.modelFile.filename, yaml);
void extLogger.log(
void this.app.logger.log(
`Saved data extension YAML to ${this.modelFile.filename}`,
);
}
@@ -208,6 +205,7 @@ export class DataExtensionsEditorView extends AbstractWebview<
if (!existingModeledMethods) {
void showAndLogErrorMessage(
this.app.logger,
`Failed to parse data extension YAML ${this.modelFile.filename}.`,
);
return;
@@ -219,6 +217,7 @@ export class DataExtensionsEditorView extends AbstractWebview<
});
} catch (e: unknown) {
void showAndLogErrorMessage(
this.app.logger,
`Unable to read data extension YAML ${
this.modelFile.filename
}: ${getErrorMessage(e)}`,
@@ -276,6 +275,7 @@ export class DataExtensionsEditorView extends AbstractWebview<
await this.clearProgress();
} catch (err) {
void showAndLogExceptionWithTelemetry(
this.app.logger,
redactableError(
asError(err),
)`Failed to load external API usages: ${getErrorMessage(err)}`,
@@ -302,7 +302,7 @@ export class DataExtensionsEditorView extends AbstractWebview<
);
if (!database) {
await this.clearProgress();
void extLogger.log("No database chosen");
void this.app.logger.log("No database chosen");
return;
}
@@ -341,6 +341,7 @@ export class DataExtensionsEditorView extends AbstractWebview<
});
} catch (e: unknown) {
void showAndLogExceptionWithTelemetry(
this.app.logger,
redactableError(
asError(e),
)`Failed to generate flow model: ${getErrorMessage(e)}`,
@@ -474,6 +475,7 @@ export class DataExtensionsEditorView extends AbstractWebview<
if (e instanceof RequestError && e.status === 429) {
void showAndLogExceptionWithTelemetry(
this.app.logger,
redactableError(e)`Rate limit hit, please try again soon.`,
);
return null;

View File

@@ -13,7 +13,7 @@ import { DatabaseItem } from "../databases/local-databases";
import { getQlPackPath, QLPACK_FILENAMES } from "../pure/ql";
import { getErrorMessage } from "../pure/helpers-pure";
import { ExtensionPack, ExtensionPackModelFile } from "./shared/extension-pack";
import { showAndLogErrorMessage } from "../common/vscode/log";
import { NotificationLogger, showAndLogErrorMessage } from "../common/logging";
import { containsPath } from "../pure/files";
const maxStep = 3;
@@ -27,12 +27,14 @@ const packNameLength = 128;
export async function pickExtensionPackModelFile(
cliServer: Pick<CodeQLCliServer, "resolveQlpacks" | "resolveExtensions">,
databaseItem: Pick<DatabaseItem, "name" | "language">,
logger: NotificationLogger,
progress: ProgressCallback,
token: CancellationToken,
): Promise<ExtensionPackModelFile | undefined> {
const extensionPack = await pickExtensionPack(
cliServer,
databaseItem,
logger,
progress,
token,
);
@@ -60,6 +62,7 @@ export async function pickExtensionPackModelFile(
async function pickExtensionPack(
cliServer: Pick<CodeQLCliServer, "resolveQlpacks">,
databaseItem: Pick<DatabaseItem, "name" | "language">,
logger: NotificationLogger,
progress: ProgressCallback,
token: CancellationToken,
): Promise<ExtensionPack | undefined> {
@@ -85,6 +88,7 @@ async function pickExtensionPack(
Object.entries(extensionPacksInfo).map(async ([name, paths]) => {
if (paths.length !== 1) {
void showAndLogErrorMessage(
logger,
`Extension pack ${name} resolves to multiple paths`,
{
fullMessage: `Extension pack ${name} resolves to multiple paths: ${paths.join(
@@ -102,11 +106,15 @@ async function pickExtensionPack(
try {
extensionPack = await readExtensionPack(path);
} catch (e: unknown) {
void showAndLogErrorMessage(`Could not read extension pack ${name}`, {
fullMessage: `Could not read extension pack ${name} at ${path}: ${getErrorMessage(
e,
)}`,
});
void showAndLogErrorMessage(
logger,
`Could not read extension pack ${name}`,
{
fullMessage: `Could not read extension pack ${name} at ${path}: ${getErrorMessage(
e,
)}`,
},
);
return undefined;
}

View File

@@ -3,7 +3,8 @@ import { dir } from "tmp-promise";
import { writeFile } from "fs-extra";
import { dump as dumpYaml } from "js-yaml";
import { getOnDiskWorkspaceFolders } from "../common/vscode/workspace-folders";
import { TeeLogger } from "../common";
import { extLogger, TeeLogger } from "../common";
import { showAndLogExceptionWithTelemetry } from "../common/vscode/logging";
import { isQueryLanguage } from "../common/query-language";
import { CancellationToken } from "vscode";
import { CodeQLCliServer } from "../codeql-cli/cli";
@@ -13,7 +14,6 @@ import { fetchExternalApiQueries } from "./queries";
import { QueryResultType } from "../pure/new-messages";
import { join } from "path";
import { redactableError } from "../pure/errors";
import { showAndLogExceptionWithTelemetry } from "../common/vscode/log";
export type RunQueryOptions = {
cliServer: Pick<CodeQLCliServer, "resolveQlpacks">;
@@ -41,6 +41,7 @@ export async function runQuery({
if (!isQueryLanguage(databaseItem.language)) {
void showAndLogExceptionWithTelemetry(
extLogger,
redactableError`Unsupported database language ${databaseItem.language}`,
);
return;
@@ -49,6 +50,7 @@ export async function runQuery({
const query = fetchExternalApiQueries[databaseItem.language];
if (!query) {
void showAndLogExceptionWithTelemetry(
extLogger,
redactableError`No external API usage query found for language ${databaseItem.language}`,
);
return;
@@ -104,6 +106,7 @@ export async function runQuery({
if (completedQuery.resultType !== QueryResultType.SUCCESS) {
void showAndLogExceptionWithTelemetry(
extLogger,
redactableError`External API usage query failed: ${
completedQuery.message ?? "No message"
}`,
@@ -126,6 +129,7 @@ export async function readQueryResults({
const bqrsInfo = await cliServer.bqrsInfo(bqrsPath);
if (bqrsInfo["result-sets"].length !== 1) {
void showAndLogExceptionWithTelemetry(
extLogger,
redactableError`Expected exactly one result set, got ${bqrsInfo["result-sets"].length}`,
);
return undefined;

View File

@@ -3,7 +3,8 @@ import { DatabaseItem } from "../databases/local-databases";
import { basename } from "path";
import { QueryRunner } from "../query-server";
import { CodeQLCliServer } from "../codeql-cli/cli";
import { TeeLogger } from "../common";
import { extLogger, TeeLogger } from "../common";
import { showAndLogExceptionWithTelemetry } from "../common/vscode/logging";
import { extensiblePredicateDefinitions } from "./predicates";
import { ProgressCallback } from "../common/vscode/progress";
import { getOnDiskWorkspaceFolders } from "../common/vscode/workspace-folders";
@@ -17,7 +18,6 @@ import { file } from "tmp-promise";
import { writeFile } from "fs-extra";
import { dump } from "js-yaml";
import { qlpackOfDatabase } from "../language-support";
import { showAndLogExceptionWithTelemetry } from "../common/vscode/log";
type FlowModelOptions = {
cliServer: CodeQLCliServer;
@@ -81,6 +81,7 @@ async function getModeledMethodsFromFlow(
): Promise<ModeledMethodWithSignature[]> {
if (queryPath === undefined) {
void showAndLogExceptionWithTelemetry(
extLogger,
redactableError`Failed to find ${type} query`,
);
return [];
@@ -115,6 +116,7 @@ async function getModeledMethodsFromFlow(
);
if (queryResult.resultType !== QueryResultType.SUCCESS) {
void showAndLogExceptionWithTelemetry(
extLogger,
redactableError`Failed to run ${basename(queryPath)} query: ${
queryResult.message ?? "No message"
}`,
@@ -127,6 +129,7 @@ async function getModeledMethodsFromFlow(
const bqrsInfo = await cliServer.bqrsInfo(bqrsPath);
if (bqrsInfo["result-sets"].length !== 1) {
void showAndLogExceptionWithTelemetry(
extLogger,
redactableError`Expected exactly one result set, got ${
bqrsInfo["result-sets"].length
} for ${basename(queryPath)}`,

View File

@@ -3,7 +3,10 @@ import { throttling } from "@octokit/plugin-throttling";
import { Octokit } from "@octokit/rest";
import { Progress, CancellationToken } from "vscode";
import { Credentials } from "../common/authentication";
import { showAndLogWarningMessage } from "../common/vscode/log";
import {
NotificationLogger,
showAndLogWarningMessage,
} from "../common/logging";
export async function getCodeSearchRepositories(
query: string,
@@ -13,9 +16,10 @@ export async function getCodeSearchRepositories(
}>,
token: CancellationToken,
credentials: Credentials,
logger: NotificationLogger,
): Promise<string[]> {
let nwos: string[] = [];
const octokit = await provideOctokitWithThrottling(credentials);
const octokit = await provideOctokitWithThrottling(credentials, logger);
for await (const response of octokit.paginate.iterator(
octokit.rest.search.code,
@@ -43,6 +47,7 @@ export async function getCodeSearchRepositories(
async function provideOctokitWithThrottling(
credentials: Credentials,
logger: NotificationLogger,
): Promise<Octokit> {
const MyOctokit = Octokit.plugin(throttling);
const auth = await credentials.getAccessToken();
@@ -53,6 +58,7 @@ async function provideOctokitWithThrottling(
throttle: {
onRateLimit: (retryAfter: number, options: any): boolean => {
void showAndLogWarningMessage(
logger,
`Rate Limit detected for request ${options.method} ${options.url}. Retrying after ${retryAfter} seconds!`,
);
@@ -60,6 +66,7 @@ async function provideOctokitWithThrottling(
},
onSecondaryRateLimit: (_retryAfter: number, options: any): void => {
void showAndLogWarningMessage(
logger,
`Secondary Rate Limit detected for request ${options.method} ${options.url}`,
);
},

View File

@@ -31,7 +31,7 @@ import {
import { Credentials } from "../common/authentication";
import { AppCommandManager } from "../common/commands";
import { ALLOW_HTTP_SETTING } from "../config";
import { showAndLogInformationMessage } from "../common/vscode/log";
import { showAndLogInformationMessage } from "../common/logging";
/**
* Prompts a user to fetch a database from a remote location. Database is assumed to be an archive file.
@@ -70,6 +70,7 @@ export async function promptImportInternetDatabase(
if (item) {
await commandManager.execute("codeQLDatabases.focus");
void showAndLogInformationMessage(
extLogger,
"Database downloaded and imported successfully.",
);
}
@@ -115,6 +116,7 @@ export async function promptImportGithubDatabase(
if (databaseItem) {
await commandManager.execute("codeQLDatabases.focus");
void showAndLogInformationMessage(
extLogger,
"Database downloaded and imported successfully.",
);
return databaseItem;
@@ -246,6 +248,7 @@ export async function importArchiveDatabase(
if (item) {
await commandManager.execute("codeQLDatabases.focus");
void showAndLogInformationMessage(
extLogger,
"Database unzipped and imported successfully.",
);
}

View File

@@ -32,7 +32,7 @@ import {
isLikelyDatabaseRoot,
isLikelyDbLanguageFolder,
} from "./local-databases/db-contents-heuristics";
import { extLogger } from "../common";
import { showAndLogExceptionWithTelemetry } from "../common/vscode/logging";
import {
importArchiveDatabase,
promptImportGithubDatabase,
@@ -48,10 +48,7 @@ import {
createMultiSelectionCommand,
createSingleSelectionCommand,
} from "../common/vscode/selection-commands";
import {
showAndLogErrorMessage,
showAndLogExceptionWithTelemetry,
} from "../common/vscode/log";
import { showAndLogErrorMessage } from "../common/logging";
enum SortOrder {
NameAsc = "NameAsc",
@@ -253,6 +250,7 @@ export class DatabaseUI extends DisposableObject {
this.handleUpgradeDatabase.bind(this),
),
"codeQLDatabases.renameDatabase": createSingleSelectionCommand(
this.app.logger,
this.handleRenameDatabase.bind(this),
"database",
),
@@ -281,6 +279,7 @@ export class DatabaseUI extends DisposableObject {
await this.chooseAndSetDatabase(true, { progress, token });
} catch (e) {
void showAndLogExceptionWithTelemetry(
this.app.logger,
redactableError(
asError(e),
)`Failed to choose and set database: ${getErrorMessage(e)}`,
@@ -373,14 +372,16 @@ export class DatabaseUI extends DisposableObject {
// Public because it's used in tests
public async handleRemoveOrphanedDatabases(): Promise<void> {
void extLogger.log("Removing orphaned databases from workspace storage.");
void this.app.logger.log(
"Removing orphaned databases from workspace storage.",
);
let dbDirs = undefined;
if (
!(await pathExists(this.storagePath)) ||
!(await stat(this.storagePath)).isDirectory()
) {
void extLogger.log(
void this.app.logger.log(
"Missing or invalid storage directory. Not trying to remove orphaned databases.",
);
return;
@@ -405,7 +406,7 @@ export class DatabaseUI extends DisposableObject {
dbDirs = await asyncFilter(dbDirs, isLikelyDatabaseRoot);
if (!dbDirs.length) {
void extLogger.log("No orphaned databases found.");
void this.app.logger.log("No orphaned databases found.");
return;
}
@@ -414,10 +415,11 @@ export class DatabaseUI extends DisposableObject {
await Promise.all(
dbDirs.map(async (dbDir) => {
try {
void extLogger.log(`Deleting orphaned database '${dbDir}'.`);
void this.app.logger.log(`Deleting orphaned database '${dbDir}'.`);
await remove(dbDir);
} catch (e) {
void showAndLogExceptionWithTelemetry(
this.app.logger,
redactableError(
asError(e),
)`Failed to delete orphaned database: ${getErrorMessage(e)}`,
@@ -430,6 +432,7 @@ export class DatabaseUI extends DisposableObject {
if (failures.length) {
const dirname = path_dirname(failures[0]);
void showAndLogErrorMessage(
this.app.logger,
`Failed to delete unused databases (${failures.join(
", ",
)}).\nTo delete unused databases, please remove them manually from the storage folder ${dirname}.`,
@@ -445,6 +448,7 @@ export class DatabaseUI extends DisposableObject {
await this.chooseAndSetDatabase(false, { progress, token });
} catch (e: unknown) {
void showAndLogExceptionWithTelemetry(
this.app.logger,
redactableError(
asError(e),
)`Failed to choose and set database: ${getErrorMessage(e)}`,

View File

@@ -1,5 +1,6 @@
import vscode, { ExtensionContext } from "vscode";
import { extLogger, Logger } from "../../common";
import { showAndLogExceptionWithTelemetry } from "../../common/vscode/logging";
import { DisposableObject } from "../../pure/disposable-object";
import { App } from "../../common/app";
import { QueryRunner } from "../../query-server";
@@ -28,7 +29,6 @@ import { remove } from "fs-extra";
import { containsPath } from "../../pure/files";
import { DatabaseChangedEvent, DatabaseEventKind } from "./database-events";
import { DatabaseResolver } from "./database-resolver";
import { showAndLogExceptionWithTelemetry } from "../../common/vscode/log";
/**
* The name of the key in the workspaceState dictionary in which we
@@ -412,6 +412,7 @@ export class DatabaseManager extends DisposableObject {
} catch (e) {
// database list had an unexpected type - nothing to be done?
void showAndLogExceptionWithTelemetry(
extLogger,
redactableError(
asError(e),
)`Database list loading failed: ${getErrorMessage(e)}`,

View File

@@ -11,7 +11,8 @@ import { encodeArchiveBasePath } from "../../common/vscode/archive-filesystem-pr
import {
showAndLogInformationMessage,
showAndLogWarningMessage,
} from "../../common/vscode/log";
} from "../../common/logging";
import { extLogger } from "../../common";
export class DatabaseResolver {
public static async resolveDatabaseContents(
@@ -107,6 +108,7 @@ async function findDataset(parentDirectory: string): Promise<vscode.Uri> {
const dbAbsolutePath = join(parentDirectory, dbRelativePaths[0]);
if (dbRelativePaths.length > 1) {
void showAndLogWarningMessage(
extLogger,
`Found multiple dataset directories in database, using '${dbAbsolutePath}'.`,
);
}
@@ -138,6 +140,7 @@ export async function findSourceArchive(
}
void showAndLogInformationMessage(
extLogger,
`Could not find source archive for database '${databasePath}'. Assuming paths are absolute.`,
);
return undefined;

View File

@@ -37,7 +37,7 @@ import { getCodeSearchRepositories } from "../code-search-api";
import {
showAndLogErrorMessage,
showAndLogInformationMessage,
} from "../../common/vscode/log";
} from "../../common/logging";
export interface RemoteDatabaseQuickPickItem extends QuickPickItem {
remoteDatabaseKind: string;
@@ -174,12 +174,18 @@ export class DbPanel extends DisposableObject {
const nwo = getNwoFromGitHubUrl(repoName) || repoName;
if (!isValidGitHubNwo(nwo)) {
void showAndLogErrorMessage(`Invalid GitHub repository: ${repoName}`);
void showAndLogErrorMessage(
this.app.logger,
`Invalid GitHub repository: ${repoName}`,
);
return;
}
if (this.dbManager.doesRemoteRepoExist(nwo, parentList)) {
void showAndLogErrorMessage(`The repository '${nwo}' already exists`);
void showAndLogErrorMessage(
this.app.logger,
`The repository '${nwo}' already exists`,
);
return;
}
@@ -199,12 +205,18 @@ export class DbPanel extends DisposableObject {
const owner = getOwnerFromGitHubUrl(ownerName) || ownerName;
if (!isValidGitHubOwner(owner)) {
void showAndLogErrorMessage(`Invalid user or organization: ${owner}`);
void showAndLogErrorMessage(
this.app.logger,
`Invalid user or organization: ${owner}`,
);
return;
}
if (this.dbManager.doesRemoteOwnerExist(owner)) {
void showAndLogErrorMessage(`The owner '${owner}' already exists`);
void showAndLogErrorMessage(
this.app.logger,
`The owner '${owner}' already exists`,
);
return;
}
@@ -223,7 +235,10 @@ export class DbPanel extends DisposableObject {
}
if (this.dbManager.doesListExist(listKind, listName)) {
void showAndLogErrorMessage(`The list '${listName}' already exists`);
void showAndLogErrorMessage(
this.app.logger,
`The list '${listName}' already exists`,
);
return;
}
@@ -287,7 +302,10 @@ export class DbPanel extends DisposableObject {
}
if (this.dbManager.doesListExist(DbListKind.Local, newName)) {
void showAndLogErrorMessage(`The list '${newName}' already exists`);
void showAndLogErrorMessage(
this.app.logger,
`The list '${newName}' already exists`,
);
return;
}
@@ -303,7 +321,10 @@ export class DbPanel extends DisposableObject {
}
if (this.dbManager.doesLocalDbExist(newName, dbItem.parentListName)) {
void showAndLogErrorMessage(`The database '${newName}' already exists`);
void showAndLogErrorMessage(
this.app.logger,
`The database '${newName}' already exists`,
);
return;
}
@@ -319,7 +340,10 @@ export class DbPanel extends DisposableObject {
}
if (this.dbManager.doesListExist(DbListKind.Remote, newName)) {
void showAndLogErrorMessage(`The list '${newName}' already exists`);
void showAndLogErrorMessage(
this.app.logger,
`The list '${newName}' already exists`,
);
return;
}
@@ -399,10 +423,14 @@ export class DbPanel extends DisposableObject {
progress,
token,
this.app.credentials,
this.app.logger,
);
token.onCancellationRequested(() => {
void showAndLogInformationMessage("Code search cancelled");
void showAndLogInformationMessage(
this.app.logger,
"Code search cancelled",
);
return;
});
@@ -471,6 +499,7 @@ export class DbPanel extends DisposableObject {
}
void showAndLogErrorMessage(
this.app.logger,
`An error occurred while setting up the controller repository: ${getErrorMessage(
e,
)}`,

View File

@@ -9,7 +9,8 @@ import { LocalQueries } from "../local-queries";
import { getQuickEvalContext, validateQueryPath } from "../run-queries-shared";
import * as CodeQLProtocol from "./debug-protocol";
import { getErrorMessage } from "../pure/helpers-pure";
import { showAndLogErrorMessage } from "../common/vscode/log";
import { showAndLogErrorMessage } from "../common/logging";
import { extLogger } from "../common";
/**
* The CodeQL launch arguments, as specified in "launch.json".
@@ -126,7 +127,7 @@ export class QLDebugConfigurationProvider
// Any unhandled exception will result in an OS-native error message box, which seems ugly.
// We'll just show a real VS Code error message, then return null to prevent the debug session
// from starting.
void showAndLogErrorMessage(getErrorMessage(e));
void showAndLogErrorMessage(extLogger, getErrorMessage(e));
return null;
}
}

View File

@@ -74,11 +74,13 @@ import {
QuickEvalCodeLensProvider,
} from "./local-queries";
import {
BaseLogger,
extLogger,
ideServerLogger,
ProgressReporter,
queryServerLogger,
} from "./common";
import { showAndLogExceptionWithTelemetry } from "./common/vscode/logging";
import { QueryHistoryManager } from "./query-history/query-history-manager";
import { CompletedLocalQueryInfo } from "./query-results";
import {
@@ -126,10 +128,9 @@ import { NewQueryRunner, QueryRunner, QueryServerClient } from "./query-server";
import { QueriesModule } from "./queries-panel/queries-module";
import {
showAndLogErrorMessage,
showAndLogExceptionWithTelemetry,
showAndLogInformationMessage,
showAndLogWarningMessage,
} from "./common/vscode/log";
} from "./common/logging";
/**
* extension.ts
@@ -193,9 +194,10 @@ function getCommands(
}
},
]);
void showAndLogInformationMessage("CodeQL Query Server restarted.", {
outputLogger: queryServerLogger,
});
void showAndLogInformationMessage(
queryServerLogger,
"CodeQL Query Server restarted.",
);
},
{
title: "Restarting Query Server",
@@ -215,7 +217,7 @@ function getCommands(
extension?.packageJSON.version
} \nCodeQL CLI version: ${await getCliVersion()} \nPlatform: ${platform()} ${arch()}`;
await env.clipboard.writeText(text);
void showAndLogInformationMessage(text);
void showAndLogInformationMessage(extLogger, text);
},
"codeQL.authenticateToGitHub": async () => {
/**
@@ -225,6 +227,7 @@ function getCommands(
const octokit = await app.credentials.getOctokit();
const userInfo = await octokit.users.getAuthenticated();
void showAndLogInformationMessage(
extLogger,
`Authenticated to GitHub as user: ${userInfo.data.login}`,
);
},
@@ -341,6 +344,7 @@ export async function activate(
registerErrorStubs([checkForUpdatesCommand], (command) => async () => {
void showAndLogErrorMessage(
extLogger,
`Can't execute ${command}: waiting to finish loading CodeQL CLI.`,
);
});
@@ -428,6 +432,7 @@ export async function activate(
}
void showAndLogWarningMessage(
extLogger,
`You are using an unsupported version of the CodeQL CLI (${ver}). ` +
`The minimum supported version is ${CliVersionConstraint.OLDEST_SUPPORTED_CLI_VERSION}. ` +
`Please upgrade to a newer version of the CodeQL CLI.`,
@@ -449,7 +454,7 @@ async function installOrUpdateDistributionWithProgressTitle(
const minSecondsSinceLastUpdateCheck = config.isUserInitiated ? 0 : 86400;
const noUpdatesLoggingFunc = config.shouldDisplayMessageWhenNoUpdates
? showAndLogInformationMessage
: async (message: string) => void extLogger.log(message);
: async (logger: BaseLogger, message: string) => void logger.log(message);
const result =
await distributionManager.checkForUpdatesToExtensionManagedDistribution(
minSecondsSinceLastUpdateCheck,
@@ -467,10 +472,11 @@ async function installOrUpdateDistributionWithProgressTitle(
);
break;
case DistributionUpdateCheckResultKind.AlreadyUpToDate:
await noUpdatesLoggingFunc("CodeQL CLI already up to date.");
await noUpdatesLoggingFunc(extLogger, "CodeQL CLI already up to date.");
break;
case DistributionUpdateCheckResultKind.InvalidLocation:
await noUpdatesLoggingFunc(
extLogger,
"CodeQL CLI is installed externally so could not be updated.",
);
break;
@@ -502,6 +508,7 @@ async function installOrUpdateDistributionWithProgressTitle(
await ctx.globalState.update(shouldUpdateOnNextActivationKey, false);
void showAndLogInformationMessage(
extLogger,
`CodeQL CLI updated to version "${result.updatedRelease.name}".`,
);
}
@@ -556,6 +563,7 @@ async function installOrUpdateDistribution(
if (e instanceof GithubRateLimitedError) {
void alertFunction(
extLogger,
`Rate limited while trying to ${taskDescription}. Please try again after ` +
`your rate limit window resets at ${e.rateLimitResetDate.toLocaleString(
env.language,
@@ -563,10 +571,11 @@ async function installOrUpdateDistribution(
);
} else if (e instanceof GithubApiError) {
void alertFunction(
extLogger,
`Encountered GitHub API error while trying to ${taskDescription}. ${e}`,
);
}
void alertFunction(`Unable to ${taskDescription}. ${e}`);
void alertFunction(extLogger, `Unable to ${taskDescription}. ${e}`);
} finally {
isInstallingOrUpdatingDistribution = false;
}
@@ -598,6 +607,7 @@ async function getDistributionDisplayingDistributionWarnings(
})();
void showAndLogWarningMessage(
extLogger,
`The current version of the CodeQL CLI (${result.version.raw}) ` +
`is incompatible with this extension. ${fixGuidanceMessage}`,
);
@@ -605,12 +615,16 @@ async function getDistributionDisplayingDistributionWarnings(
}
case FindDistributionResultKind.UnknownCompatibilityDistribution:
void showAndLogWarningMessage(
extLogger,
"Compatibility with the configured CodeQL CLI could not be determined. " +
"You may experience problems using the extension.",
);
break;
case FindDistributionResultKind.NoDistribution:
void showAndLogErrorMessage("The CodeQL CLI could not be found.");
void showAndLogErrorMessage(
extLogger,
"The CodeQL CLI could not be found.",
);
break;
default:
assertNever(result);
@@ -652,14 +666,17 @@ async function installOrUpdateThenTryActivate(
if (distributionResult.kind === FindDistributionResultKind.NoDistribution) {
registerErrorStubs([checkForUpdatesCommand], (command) => async () => {
void extLogger.log(`Can't execute ${command}: missing CodeQL CLI.`);
const showLogName = "Show Log";
const installActionName = "Install CodeQL CLI";
const chosenAction = await showAndLogErrorMessage(
const chosenAction = await Window.showErrorMessage(
`Can't execute ${command}: missing CodeQL CLI.`,
{
items: [installActionName],
},
showLogName,
installActionName,
);
if (chosenAction === installActionName) {
if (chosenAction === showLogName) {
extLogger.show();
} else if (chosenAction === installActionName) {
await installOrUpdateThenTryActivate(
ctx,
app,
@@ -1116,6 +1133,7 @@ async function showResultsForComparison(
await compareView.showResults(from, to);
} catch (e) {
void showAndLogExceptionWithTelemetry(
extLogger,
redactableError(asError(e))`Failed to show results: ${getErrorMessage(
e,
)}`,
@@ -1141,7 +1159,7 @@ function addUnhandledRejectionListener() {
)`Unhandled error: ${getErrorMessage(error)}`;
// Add a catch so that showAndLogExceptionWithTelemetry fails, we avoid
// triggering "unhandledRejection" and avoid an infinite loop
showAndLogExceptionWithTelemetry(message).catch(
showAndLogExceptionWithTelemetry(extLogger, message).catch(
(telemetryError: unknown) => {
void extLogger.log(
`Failed to send error telemetry: ${getErrorMessage(
@@ -1250,6 +1268,7 @@ async function assertVSCodeVersionGreaterThan(
const parsedMinVersion = parse(minVersion);
if (!parsedVersion || !parsedMinVersion) {
void showAndLogWarningMessage(
extLogger,
`Could not do a version check of vscode because could not parse version number: actual vscode version ${vscodeVersion} or minimum supported vscode version ${minVersion}.`,
);
return;
@@ -1269,6 +1288,7 @@ async function assertVSCodeVersionGreaterThan(
}
} catch (e) {
void showAndLogWarningMessage(
extLogger,
`Could not do a version check because of an error: ${getErrorMessage(e)}`,
);
}

View File

@@ -27,7 +27,8 @@ import { DisposableObject } from "../../pure/disposable-object";
import { asError, getErrorMessage } from "../../pure/helpers-pure";
import { redactableError } from "../../pure/errors";
import { AstViewerCommands } from "../../common/commands";
import { showAndLogExceptionWithTelemetry } from "../../common/vscode/log";
import { extLogger } from "../../common";
import { showAndLogExceptionWithTelemetry } from "../../common/vscode/logging";
export interface AstItem {
id: BqrsId;
@@ -145,6 +146,7 @@ export class AstViewer extends DisposableObject {
},
(error: unknown) =>
showAndLogExceptionWithTelemetry(
extLogger,
redactableError(
asError(error),
)`Failed to reveal AST: ${getErrorMessage(error)}`,
@@ -208,6 +210,7 @@ export class AstViewer extends DisposableObject {
},
(error: unknown) =>
showAndLogExceptionWithTelemetry(
extLogger,
redactableError(
asError(error),
)`Failed to reveal AST: ${getErrorMessage(error)}`,

View File

@@ -18,12 +18,12 @@ import {
import { CodeQLCliServer } from "../../codeql-cli/cli";
import { DatabaseItem } from "../../databases/local-databases";
import { extLogger, TeeLogger } from "../../common";
import { showAndLogExceptionWithTelemetry } from "../../common/vscode/logging";
import { CancellationToken } from "vscode";
import { ProgressCallback } from "../../common/vscode/progress";
import { CoreCompletedQuery, QueryRunner } from "../../query-server";
import { redactableError } from "../../pure/errors";
import { QLPACK_FILENAMES } from "../../pure/ql";
import { showAndLogExceptionWithTelemetry } from "../../common/vscode/log";
export async function qlpackOfDatabase(
cli: Pick<CodeQLCliServer, "resolveQlpacks">,
@@ -102,7 +102,7 @@ current library path (tried searching the following packs: ${joinedPacksToSearch
Try upgrading the CodeQL libraries. If that doesn't work, then ${keyTypeName} queries are not yet available \
for this language.`;
void showAndLogExceptionWithTelemetry(error);
void showAndLogExceptionWithTelemetry(extLogger, error);
throw error;
}

View File

@@ -5,7 +5,8 @@ import { basename, join } from "path";
import { getErrorMessage } from "../pure/helpers-pure";
import { redactableError } from "../pure/errors";
import { AppCommandManager, QueryEditorCommands } from "../common/commands";
import { showAndLogExceptionWithTelemetry } from "../common/vscode/log";
import { extLogger } from "../common";
import { showAndLogExceptionWithTelemetry } from "../common/vscode/logging";
type QueryEditorOptions = {
commandManager: AppCommandManager;
@@ -79,7 +80,7 @@ async function previewQueryHelp(
)
? 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(errorMessage, {
void showAndLogExceptionWithTelemetry(extLogger, errorMessage, {
fullMessage: `${errorMessage}\n${getErrorMessage(e)}`,
});
}

View File

@@ -12,7 +12,7 @@ import {
window,
workspace,
} from "vscode";
import { extLogger, TeeLogger } from "../common";
import { TeeLogger } from "../common";
import { isCanary, MAX_QUERIES } from "../config";
import { gatherQlFiles } from "../pure/files";
import { basename } from "path";
@@ -46,7 +46,7 @@ import { createMultiSelectionCommand } from "../common/vscode/selection-commands
import {
showAndLogErrorMessage,
showAndLogWarningMessage,
} from "../common/vscode/log";
} from "../common/logging";
import { findLanguage } from "../codeql-cli/query-language";
interface DatabaseQuickPickItem extends QuickPickItem {
@@ -292,7 +292,7 @@ export class LocalQueries extends DisposableObject {
this.cliServer,
progress,
credentials,
extLogger,
this.app.logger,
this.databaseManager,
token,
contextStoragePath,
@@ -323,6 +323,7 @@ export class LocalQueries extends DisposableObject {
if (this.queryRunner.customLogDirectory) {
void showAndLogWarningMessage(
this.app.logger,
`Custom log directories are no longer supported. The "codeQL.runningQueries.customLogDirectory" setting is deprecated. Unset the setting to stop seeing this message. Query logs saved to ${outputDir.logPath}`,
);
}
@@ -469,6 +470,7 @@ export class LocalQueries extends DisposableObject {
let filteredDBs = this.databaseManager.databaseItems;
if (filteredDBs.length === 0) {
void showAndLogErrorMessage(
this.app.logger,
"No databases found. Please add a suitable database to your workspace.",
);
return;
@@ -481,6 +483,7 @@ export class LocalQueries extends DisposableObject {
);
if (filteredDBs.length === 0) {
void showAndLogErrorMessage(
this.app.logger,
`No databases found for language ${queryLanguage}. Please add a suitable database to your workspace.`,
);
return;
@@ -517,15 +520,16 @@ export class LocalQueries extends DisposableObject {
}
}
if (skippedDatabases.length > 0) {
void extLogger.log(`Errors:\n${errors.join("\n")}`);
void this.app.logger.log(`Errors:\n${errors.join("\n")}`);
void showAndLogWarningMessage(
this.app.logger,
`The following databases were skipped:\n${skippedDatabases.join(
"\n",
)}.\nFor details about the errors, see the logs.`,
);
}
} else {
void showAndLogErrorMessage("No databases selected.");
void showAndLogErrorMessage(this.app.logger, "No databases selected.");
}
}

View File

@@ -1,4 +1,5 @@
import { BaseLogger, Logger } from "../common";
import { BaseLogger, extLogger, Logger } from "../common";
import { showAndLogExceptionWithTelemetry } from "../common/vscode/logging";
import { CoreQueryResults } from "../query-server";
import { QueryHistoryManager } from "../query-history/query-history-manager";
import { DatabaseItem } from "../databases/local-databases";
@@ -16,10 +17,7 @@ import { CodeQLCliServer } from "../codeql-cli/cli";
import { QueryResultType } from "../pure/new-messages";
import { redactableError } from "../pure/errors";
import { LocalQueries } from "./local-queries";
import {
showAndLogExceptionWithTelemetry,
showAndLogWarningMessage,
} from "../common/vscode/log";
import { showAndLogWarningMessage } from "../common/logging";
import { tryGetQueryMetadata } from "../codeql-cli/query-metadata";
function formatResultMessage(result: CoreQueryResults): string {
@@ -119,6 +117,7 @@ export class LocalQueryRun {
// Raw evaluator log was not found. Notify the user, unless we know why it wasn't found.
if (resultType === QueryResultType.SUCCESS) {
void showAndLogWarningMessage(
extLogger,
`Failed to write structured evaluator log to ${outputDir.evalLogPath}.`,
);
} else {
@@ -155,7 +154,7 @@ export class LocalQueryRun {
const message = results.message
? redactableError`Failed to run query: ${results.message}`
: redactableError`Failed to run query`;
void showAndLogExceptionWithTelemetry(message);
void showAndLogExceptionWithTelemetry(extLogger, message);
}
const message = formatResultMessage(results);
const successful = results.resultType === QueryResultType.SUCCESS;

View File

@@ -40,7 +40,8 @@ import {
getDefaultResultSetName,
ParsedResultSets,
} from "../pure/interface-types";
import { Logger } from "../common";
import { extLogger, Logger } from "../common";
import { showAndLogExceptionWithTelemetry } from "../common/vscode/logging";
import {
CompletedQueryInfo,
interpretResultsSarif,
@@ -73,7 +74,6 @@ import { HistoryItemLabelProvider } from "../query-history/history-item-label-pr
import { telemetryListener } from "../telemetry";
import { redactableError } from "../pure/errors";
import { ResultsViewCommands } from "../common/commands";
import { showAndLogExceptionWithTelemetry } from "../common/vscode/log";
/**
* results-view.ts
@@ -319,6 +319,7 @@ export class ResultsView extends AbstractWebview<
break;
case "unhandledError":
void showAndLogExceptionWithTelemetry(
extLogger,
redactableError(
msg.error,
)`Unhandled error in results view: ${msg.error.message}`,
@@ -329,6 +330,7 @@ export class ResultsView extends AbstractWebview<
}
} catch (e) {
void showAndLogExceptionWithTelemetry(
extLogger,
redactableError(
asError(e),
)`Error handling message from results view: ${getErrorMessage(e)}`,
@@ -378,6 +380,7 @@ export class ResultsView extends AbstractWebview<
): Promise<void> {
if (this._displayedQuery === undefined) {
void showAndLogExceptionWithTelemetry(
extLogger,
redactableError`Failed to sort results since evaluation info was unknown.`,
);
return;
@@ -396,6 +399,7 @@ export class ResultsView extends AbstractWebview<
): Promise<void> {
if (this._displayedQuery === undefined) {
void showAndLogExceptionWithTelemetry(
extLogger,
redactableError`Failed to sort results since evaluation info was unknown.`,
);
return;
@@ -806,6 +810,7 @@ export class ResultsView extends AbstractWebview<
// If interpretation fails, accept the error and continue
// trying to render uninterpreted results anyway.
void showAndLogExceptionWithTelemetry(
extLogger,
redactableError(
asError(e),
)`Showing raw results instead of interpreted ones due to an error. ${getErrorMessage(

View File

@@ -7,14 +7,12 @@ import {
withProgress,
} from "../common/vscode/progress";
import { extLogger } from "../common";
import { showAndLogExceptionWithTelemetry } from "../common/vscode/logging";
import { asError, getErrorStack } from "../pure/helpers-pure";
import { redactableError } from "../pure/errors";
import { PACKS_BY_QUERY_LANGUAGE } from "../common/query-language";
import { PackagingCommands } from "../common/commands";
import {
showAndLogExceptionWithTelemetry,
showAndLogInformationMessage,
} from "../common/vscode/log";
import { showAndLogInformationMessage } from "../common/logging";
type PackagingOptions = {
cliServer: CodeQLCliServer;
@@ -87,9 +85,13 @@ export async function handleDownloadPacks(
});
try {
await cliServer.packDownload(packsToDownload);
void showAndLogInformationMessage("Finished downloading packs.");
void showAndLogInformationMessage(
extLogger,
"Finished downloading packs.",
);
} catch (error) {
void showAndLogExceptionWithTelemetry(
extLogger,
redactableError(
asError(error),
)`Unable to download all packs. See log for more details.`,
@@ -165,6 +167,7 @@ export async function handleInstallPackDependencies(
);
} else {
void showAndLogInformationMessage(
extLogger,
"Finished installing pack dependencies.",
);
}

View File

@@ -12,7 +12,8 @@ import { DisposableObject } from "../pure/disposable-object";
import { asError, getErrorMessage } from "../pure/helpers-pure";
import { redactableError } from "../pure/errors";
import { EvalLogViewerCommands } from "../common/commands";
import { showAndLogExceptionWithTelemetry } from "../common/vscode/log";
import { extLogger } from "../common";
import { showAndLogExceptionWithTelemetry } from "../common/vscode/logging";
export interface EvalLogTreeItem {
label?: string;
@@ -109,6 +110,7 @@ export class EvalLogViewer extends DisposableObject {
},
(err: unknown) =>
showAndLogExceptionWithTelemetry(
extLogger,
redactableError(
asError(err),
)`Failed to reveal tree view: ${getErrorMessage(err)}`,

View File

@@ -17,7 +17,6 @@ import {
showBinaryChoiceDialog,
showInformationMessageWithAction,
} from "../common/vscode/dialog";
import { extLogger } from "../common";
import { URLSearchParams } from "url";
import { DisposableObject } from "../pure/disposable-object";
import { ONE_HOUR_IN_MS, TWO_HOURS_IN_MS } from "../pure/time";
@@ -60,7 +59,7 @@ import {
showAndLogErrorMessage,
showAndLogInformationMessage,
showAndLogWarningMessage,
} from "../common/vscode/log";
} from "../common/logging";
/**
* query-history-manager.ts
@@ -238,6 +237,7 @@ export class QueryHistoryManager extends DisposableObject {
"codeQLQueryHistory.sortByCount": this.handleSortByCount.bind(this),
"codeQLQueryHistory.openQueryContextMenu": createSingleSelectionCommand(
this.app.logger,
this.handleOpenQuery.bind(this),
"query",
),
@@ -246,31 +246,38 @@ export class QueryHistoryManager extends DisposableObject {
"codeQLQueryHistory.removeHistoryItemContextInline":
createMultiSelectionCommand(this.handleRemoveHistoryItem.bind(this)),
"codeQLQueryHistory.renameItem": createSingleSelectionCommand(
this.app.logger,
this.handleRenameItem.bind(this),
"query",
),
"codeQLQueryHistory.compareWith": this.handleCompareWith.bind(this),
"codeQLQueryHistory.showEvalLog": createSingleSelectionCommand(
this.app.logger,
this.handleShowEvalLog.bind(this),
"query",
),
"codeQLQueryHistory.showEvalLogSummary": createSingleSelectionCommand(
this.app.logger,
this.handleShowEvalLogSummary.bind(this),
"query",
),
"codeQLQueryHistory.showEvalLogViewer": createSingleSelectionCommand(
this.app.logger,
this.handleShowEvalLogViewer.bind(this),
"query",
),
"codeQLQueryHistory.showQueryLog": createSingleSelectionCommand(
this.app.logger,
this.handleShowQueryLog.bind(this),
"query",
),
"codeQLQueryHistory.showQueryText": createSingleSelectionCommand(
this.app.logger,
this.handleShowQueryText.bind(this),
"query",
),
"codeQLQueryHistory.openQueryDirectory": createSingleSelectionCommand(
this.app.logger,
this.handleOpenQueryDirectory.bind(this),
"query",
),
@@ -278,34 +285,42 @@ export class QueryHistoryManager extends DisposableObject {
this.handleCancel.bind(this),
),
"codeQLQueryHistory.exportResults": createSingleSelectionCommand(
this.app.logger,
this.handleExportResults.bind(this),
"query",
),
"codeQLQueryHistory.viewCsvResults": createSingleSelectionCommand(
this.app.logger,
this.handleViewCsvResults.bind(this),
"query",
),
"codeQLQueryHistory.viewCsvAlerts": createSingleSelectionCommand(
this.app.logger,
this.handleViewCsvAlerts.bind(this),
"query",
),
"codeQLQueryHistory.viewSarifAlerts": createSingleSelectionCommand(
this.app.logger,
this.handleViewSarifAlerts.bind(this),
"query",
),
"codeQLQueryHistory.viewDil": createSingleSelectionCommand(
this.app.logger,
this.handleViewDil.bind(this),
"query",
),
"codeQLQueryHistory.itemClicked": createSingleSelectionCommand(
this.app.logger,
this.handleItemClicked.bind(this),
"query",
),
"codeQLQueryHistory.openOnGithub": createSingleSelectionCommand(
this.app.logger,
this.handleOpenOnGithub.bind(this),
"query",
),
"codeQLQueryHistory.copyRepoList": createSingleSelectionCommand(
this.app.logger,
this.handleCopyRepoList.bind(this),
"query",
),
@@ -386,7 +401,7 @@ export class QueryHistoryManager extends DisposableObject {
});
await this.refreshTreeView();
} else {
void extLogger.log(
void this.app.logger.log(
"Variant analysis status update event received for unknown variant analysis",
);
}
@@ -417,7 +432,7 @@ export class QueryHistoryManager extends DisposableObject {
}
async readQueryHistory(): Promise<void> {
void extLogger.log(
void this.app.logger.log(
`Reading cached query history from '${this.queryMetadataStorageLocation}'.`,
);
const history = await readQueryHistoryFromFile(
@@ -535,7 +550,7 @@ export class QueryHistoryManager extends DisposableObject {
}
this.treeDataProvider.remove(item);
void extLogger.log(`Deleted ${this.labelProvider.getLabel(item)}.`);
void this.app.logger.log(`Deleted ${this.labelProvider.getLabel(item)}.`);
if (item.status === QueryStatus.InProgress) {
await this.showToastWithWorkflowRunLink(item);
@@ -628,6 +643,7 @@ export class QueryHistoryManager extends DisposableObject {
toItem = await this.findOtherQueryToCompare(fromItem, multiSelect);
} catch (e) {
void showAndLogErrorMessage(
this.app.logger,
`Failed to compare queries: ${getErrorMessage(e)}`,
);
}
@@ -672,7 +688,7 @@ export class QueryHistoryManager extends DisposableObject {
item.completedQuery.logFileLocation,
);
} else {
void showAndLogWarningMessage("No log file available");
void showAndLogWarningMessage(this.app.logger, "No log file available");
}
}
@@ -740,18 +756,21 @@ export class QueryHistoryManager extends DisposableObject {
private warnNoEvalLogs() {
void showAndLogWarningMessage(
this.app.logger,
`Evaluator log, summary, and viewer are not available for this run. Perhaps it failed before evaluation, or you are running with a version of CodeQL before ' + ${CliVersionConstraint.CLI_VERSION_WITH_PER_QUERY_EVAL_LOG}?`,
);
}
private warnInProgressEvalLogSummary() {
void showAndLogWarningMessage(
this.app.logger,
'The evaluator log summary is still being generated for this run. Please try again later. The summary generation process is tracked in the "CodeQL Extension Log" view.',
);
}
private warnInProgressEvalLogViewer() {
void showAndLogWarningMessage(
this.app.logger,
"The viewer's data is still being generated for this run. Please try again or re-run the query.",
);
}
@@ -868,6 +887,7 @@ export class QueryHistoryManager extends DisposableObject {
} else {
const label = this.labelProvider.getLabel(item);
void showAndLogInformationMessage(
this.app.logger,
`Query ${label} has no interpreted results.`,
);
}

View File

@@ -12,7 +12,8 @@ import { redactableError } from "../../pure/errors";
import { QueryHistoryDto, QueryHistoryItemDto } from "./query-history-dto";
import { mapQueryHistoryToDomainModel } from "./query-history-dto-mapper";
import { mapQueryHistoryToDto } from "./query-history-domain-mapper";
import { showAndLogExceptionWithTelemetry } from "../../common/vscode/log";
import { extLogger } from "../../common";
import { showAndLogExceptionWithTelemetry } from "../../common/vscode/logging";
const ALLOWED_QUERY_HISTORY_VERSIONS = [1, 2];
@@ -30,6 +31,7 @@ export async function readQueryHistoryFromFile(
if (!ALLOWED_QUERY_HISTORY_VERSIONS.includes(obj.version)) {
void showAndLogExceptionWithTelemetry(
extLogger,
redactableError`Can't parse query history. Unsupported query history format: v${obj.version}.`,
);
return [];
@@ -65,6 +67,7 @@ export async function readQueryHistoryFromFile(
return filteredDomainModels;
} catch (e) {
void showAndLogExceptionWithTelemetry(
extLogger,
redactableError(asError(e))`Error loading query history.`,
{
fullMessage: `Error loading query history.\n${getErrorStack(e)}`,

View File

@@ -13,6 +13,7 @@ import { tmpDir } from "../../tmp-dir";
import { ProgressCallback } from "../../common/vscode/progress";
import { QueryMetadata } from "../../pure/interface-types";
import { extLogger, Logger } from "../../common";
import { showAndLogExceptionWithTelemetry } from "../../common/vscode/logging";
import * as messages from "../../pure/legacy-messages";
import * as newMessages from "../../pure/new-messages";
import * as qsClient from "./query-server-client";
@@ -22,10 +23,7 @@ import { QueryEvaluationInfo, QueryOutputDir } from "../../run-queries-shared";
import { redactableError } from "../../pure/errors";
import { CoreQueryResults, CoreQueryTarget } from "../query-runner";
import { Position } from "../../pure/messages-shared";
import {
showAndLogExceptionWithTelemetry,
showAndLogWarningMessage,
} from "../../common/vscode/log";
import { showAndLogWarningMessage } from "../../common/logging";
import { ensureDirSync } from "fs-extra";
const upgradesTmpDir = join(tmpDir.name, "upgrades");
@@ -321,6 +319,7 @@ export async function compileAndRunQueryAgainstDatabaseCore(
): Promise<CoreQueryResults> {
if (extensionPacks !== undefined && extensionPacks.length > 0) {
void showAndLogWarningMessage(
extLogger,
"Legacy query server does not support extension packs.",
);
}
@@ -386,6 +385,7 @@ export async function compileAndRunQueryAgainstDatabaseCore(
}
} catch (e) {
void showAndLogExceptionWithTelemetry(
extLogger,
redactableError(
asError(e),
)`Couldn't resolve available ML models for ${qlProgram.queryPath}. Running the query without any ML models: ${e}.`,
@@ -444,7 +444,7 @@ export async function compileAndRunQueryAgainstDatabaseCore(
? redactableError`${result.message}`
: redactableError`Failed to run query`;
void extLogger.log(error.fullMessage);
void showAndLogExceptionWithTelemetry(error);
void showAndLogExceptionWithTelemetry(extLogger, error);
}
return translateLegacyResult(result);

View File

@@ -6,6 +6,7 @@ import {
UserCancellationException,
} from "../../common/vscode/progress";
import { extLogger } from "../../common";
import { showAndLogExceptionWithTelemetry } from "../../common/vscode/logging";
import * as messages from "../../pure/legacy-messages";
import * as qsClient from "./query-server-client";
import * as tmp from "tmp-promise";
@@ -13,7 +14,6 @@ import { dirname } from "path";
import { DatabaseItem } from "../../databases/local-databases";
import { asError, getErrorMessage } from "../../pure/helpers-pure";
import { redactableError } from "../../pure/errors";
import { showAndLogExceptionWithTelemetry } from "../../common/vscode/log";
/**
* Maximum number of lines to include from database upgrade message,
@@ -206,6 +206,7 @@ export async function upgradeDatabaseExplicit(
);
} catch (e) {
void showAndLogExceptionWithTelemetry(
extLogger,
redactableError(
asError(e),
)`Compilation of database upgrades failed: ${getErrorMessage(e)}`,
@@ -220,6 +221,7 @@ export async function upgradeDatabaseExplicit(
? redactableError`${compileUpgradeResult.error}`
: redactableError`[no error message available]`;
void showAndLogExceptionWithTelemetry(
extLogger,
redactableError`Compilation of database upgrades failed: ${error}`,
);
return;
@@ -253,6 +255,7 @@ export async function upgradeDatabaseExplicit(
return result;
} catch (e) {
void showAndLogExceptionWithTelemetry(
extLogger,
redactableError(asError(e))`Database upgrade failed: ${getErrorMessage(
e,
)}`,

View File

@@ -5,7 +5,7 @@ import { CancellationToken } from "vscode";
import { createMessageConnection, RequestType } from "vscode-jsonrpc/node";
import * as cli from "../codeql-cli/cli";
import { QueryServerConfig } from "../config";
import { Logger, ProgressReporter } from "../common";
import { extLogger, Logger, ProgressReporter } from "../common";
import {
progress,
ProgressMessage,
@@ -19,7 +19,7 @@ import {
import { ServerProcess } from "./server-process";
import { App } from "../common/app";
import { showAndLogErrorMessage } from "../common/vscode/log";
import { showAndLogErrorMessage } from "../common/logging";
type ServerOpts = {
logger: Logger;
@@ -131,6 +131,7 @@ export class QueryServerClient extends DisposableObject {
);
} else {
void showAndLogErrorMessage(
extLogger,
"The CodeQL query server has unexpectedly terminated too many times. Please check the logs for errors. You can manually restart the query server using the command 'CodeQL: Restart query server'.",
);
// Make sure we dispose anyway to reject all pending requests.

View File

@@ -5,12 +5,10 @@ import { getOnDiskWorkspaceFolders } from "../common/vscode/workspace-folders";
import { asError, getErrorMessage } from "../pure/helpers-pure";
import { redactableError } from "../pure/errors";
import { access } from "fs-extra";
import { BaseLogger } from "../common";
import { BaseLogger, extLogger } from "../common";
import { showAndLogExceptionWithTelemetry } from "../common/vscode/logging";
import { DisposableObject } from "../pure/disposable-object";
import {
showAndLogExceptionWithTelemetry,
showAndLogWarningMessage,
} from "../common/vscode/log";
import { showAndLogWarningMessage } from "../common/logging";
async function isFileAccessible(uri: Uri): Promise<boolean> {
try {
@@ -88,6 +86,7 @@ export class TestRunner extends DisposableObject {
// Explorer UI swallows any thrown exception without reporting it to the user.
// So we need to display the error message ourselves and then rethrow.
void showAndLogExceptionWithTelemetry(
extLogger,
redactableError(asError(e))`Cannot remove database ${
database.name
}: ${getErrorMessage(e)}`,
@@ -128,7 +127,10 @@ export class TestRunner extends DisposableObject {
// This method is invoked from Test Explorer UI, and testing indicates that Test
// Explorer UI swallows any thrown exception without reporting it to the user.
// So we need to display the error message ourselves and then rethrow.
void showAndLogWarningMessage(`Cannot reopen database ${uri}: ${e}`);
void showAndLogWarningMessage(
extLogger,
`Cannot reopen database ${uri}: ${e}`,
);
throw e;
}
}

View File

@@ -31,7 +31,7 @@ import { DecodedBqrsChunk, EntityValue } from "./pure/bqrs-cli-types";
import { BaseLogger, extLogger } from "./common";
import { generateSummarySymbolsFile } from "./log-insights/summary-parser";
import { getErrorMessage } from "./pure/helpers-pure";
import { showAndLogWarningMessage } from "./common/vscode/log";
import { showAndLogWarningMessage } from "./common/logging";
/**
* run-queries.ts
@@ -261,7 +261,7 @@ export class QueryEvaluationInfo extends QueryOutputDir {
): Promise<boolean> {
const resultSet = await this.chooseResultSet(cliServer);
if (!resultSet) {
void showAndLogWarningMessage("Query has no result set.");
void showAndLogWarningMessage(extLogger, "Query has no result set.");
return false;
}
let stopDecoding = false;
@@ -659,6 +659,7 @@ async function generateHumanReadableLogSummary(
return true;
} catch (e) {
void showAndLogWarningMessage(
extLogger,
`Failed to generate human-readable structured evaluator log summary. Reason: ${getErrorMessage(
e,
)}`,
@@ -682,6 +683,7 @@ export async function logEndSummary(
void logger.log(endSummaryContent);
} catch (e) {
void showAndLogWarningMessage(
extLogger,
`Could not read structured evaluator log end of summary file at ${endSummary}.`,
);
}

View File

@@ -1,7 +1,7 @@
import { join } from "path";
import { CancellationToken, Uri, workspace, window as Window } from "vscode";
import { CodeQLCliServer } from "./codeql-cli/cli";
import { OutputChannelLogger } from "./common";
import { BaseLogger } from "./common";
import { Credentials } from "./common/authentication";
import { QueryLanguage } from "./common/query-language";
import {
@@ -49,7 +49,7 @@ export class SkeletonQueryWizard {
private readonly cliServer: CodeQLCliServer,
private readonly progress: ProgressCallback,
private readonly credentials: Credentials | undefined,
private readonly extLogger: OutputChannelLogger,
private readonly logger: BaseLogger,
private readonly databaseManager: DatabaseManager,
private readonly token: CancellationToken,
private readonly databaseStoragePath: string | undefined,
@@ -88,7 +88,7 @@ export class SkeletonQueryWizard {
try {
await this.openExampleFile();
} catch (e: unknown) {
void this.extLogger.log(
void this.logger.log(
`Could not open example query file: ${getErrorMessage(e)}`,
);
}
@@ -174,7 +174,7 @@ export class SkeletonQueryWizard {
await qlPackGenerator.generate();
} catch (e: unknown) {
void this.extLogger.log(
void this.logger.log(
`Could not create skeleton QL pack: ${getErrorMessage(e)}`,
);
}
@@ -206,7 +206,7 @@ export class SkeletonQueryWizard {
this.fileName = await this.determineNextFileName(this.folderName);
await qlPackGenerator.createExampleQlFile(this.fileName);
} catch (e: unknown) {
void this.extLogger.log(
void this.logger.log(
`Could not create skeleton QL pack: ${getErrorMessage(e)}`,
);
}

View File

@@ -11,7 +11,8 @@ import {
} from "../pure/interface-types";
import { DataFlowPaths } from "./shared/data-flow-paths";
import { redactableError } from "../pure/errors";
import { showAndLogExceptionWithTelemetry } from "../common/vscode/log";
import { extLogger } from "../common";
import { showAndLogExceptionWithTelemetry } from "../common/vscode/logging";
export class DataFlowPathsView extends AbstractWebview<
ToDataFlowPathsMessage,
@@ -59,6 +60,7 @@ export class DataFlowPathsView extends AbstractWebview<
break;
case "unhandledError":
void showAndLogExceptionWithTelemetry(
extLogger,
redactableError(
msg.error,
)`Unhandled error in data flow paths view: ${msg.error.message}`,

View File

@@ -2,7 +2,8 @@ import { TextDocumentContentProvider, Uri } from "vscode";
import { URLSearchParams } from "url";
import { SHOW_QUERY_TEXT_MSG } from "../query-history/query-history-manager";
import { VariantAnalysisManager } from "./variant-analysis-manager";
import { showAndLogWarningMessage } from "../common/vscode/log";
import { showAndLogWarningMessage } from "../common/logging";
import { extLogger } from "../common";
export const createVariantAnalysisContentProvider = (
variantAnalysisManager: VariantAnalysisManager,
@@ -13,6 +14,7 @@ export const createVariantAnalysisContentProvider = (
const variantAnalysisIdString = params.get("variantAnalysisId");
if (!variantAnalysisIdString) {
void showAndLogWarningMessage(
extLogger,
"Unable to show query text. No variant analysis ID provided.",
);
return undefined;
@@ -24,6 +26,7 @@ export const createVariantAnalysisContentProvider = (
);
if (!variantAnalysis) {
void showAndLogWarningMessage(
extLogger,
"Unable to show query text. No variant analysis found.",
);
return undefined;

View File

@@ -71,12 +71,11 @@ import {
} from "./repo-states-store";
import { GITHUB_AUTH_PROVIDER_ID } from "../common/vscode/authentication";
import { FetchError } from "node-fetch";
import { extLogger } from "../common";
import { showAndLogExceptionWithTelemetry } from "../common/vscode/logging";
import {
showAndLogExceptionWithTelemetry,
showAndLogInformationMessage,
showAndLogWarningMessage,
} from "../common/vscode/log";
} from "../common/logging";
const maxRetryCount = 3;
@@ -256,6 +255,7 @@ export class VariantAnalysisManager
await this.onVariantAnalysisSubmitted(processedVariantAnalysis);
void showAndLogInformationMessage(
this.app.logger,
`Variant analysis ${processedVariantAnalysis.query.name} submitted for processing`,
);
@@ -328,6 +328,7 @@ export class VariantAnalysisManager
public async showView(variantAnalysisId: number): Promise<void> {
if (!this.variantAnalyses.get(variantAnalysisId)) {
void showAndLogExceptionWithTelemetry(
this.app.logger,
redactableError`No variant analysis found with id: ${variantAnalysisId}.`,
);
}
@@ -347,6 +348,7 @@ export class VariantAnalysisManager
const variantAnalysis = await this.getVariantAnalysis(variantAnalysisId);
if (!variantAnalysis) {
void showAndLogWarningMessage(
this.app.logger,
"Could not open variant analysis query text. Variant analysis not found.",
);
return;
@@ -367,6 +369,7 @@ export class VariantAnalysisManager
await Window.showTextDocument(doc, { preview: false });
} catch (error) {
void showAndLogWarningMessage(
this.app.logger,
"Could not open variant analysis query text. Failed to open text document.",
);
}
@@ -377,6 +380,7 @@ export class VariantAnalysisManager
if (!variantAnalysis) {
void showAndLogWarningMessage(
this.app.logger,
"Could not open variant analysis query file",
);
return;
@@ -389,6 +393,7 @@ export class VariantAnalysisManager
await Window.showTextDocument(textDocument, ViewColumn.One);
} catch (error) {
void showAndLogWarningMessage(
this.app.logger,
`Could not open file: ${variantAnalysis.query.filePath}`,
);
}
@@ -633,14 +638,14 @@ export class VariantAnalysisManager
e instanceof FetchError &&
(e.code === "ETIMEDOUT" || e.code === "ECONNRESET")
) {
void extLogger.log(
void this.app.logger.log(
`Timeout while trying to download variant analysis with id: ${
variantAnalysis.id
}. Error: ${getErrorMessage(e)}. Retrying...`,
);
continue;
}
void extLogger.log(
void this.app.logger.log(
`Failed to download variant analysis after ${retry} attempts.`,
);
throw e;
@@ -701,6 +706,7 @@ export class VariantAnalysisManager
}
void showAndLogInformationMessage(
this.app.logger,
"Cancelling variant analysis. This may take a while.",
);
await cancelVariantAnalysis(this.app.credentials, variantAnalysis);

View File

@@ -14,8 +14,7 @@ import { DisposableObject } from "../pure/disposable-object";
import { sleep } from "../pure/time";
import { getErrorMessage } from "../pure/helpers-pure";
import { App } from "../common/app";
import { extLogger } from "../common";
import { showAndLogWarningMessage } from "../common/vscode/log";
import { showAndLogWarningMessage } from "../common/logging";
export class VariantAnalysisMonitor extends DisposableObject {
// With a sleep of 5 seconds, the maximum number of attempts takes
@@ -47,7 +46,7 @@ export class VariantAnalysisMonitor extends DisposableObject {
variantAnalysis: VariantAnalysis,
): Promise<void> {
if (this.monitoringVariantAnalyses.has(variantAnalysis.id)) {
void extLogger.log(
void this.app.logger.log(
`Already monitoring variant analysis ${variantAnalysis.id}`,
);
return;
@@ -96,9 +95,9 @@ export class VariantAnalysisMonitor extends DisposableObject {
// If we have already shown this error to the user, don't show it again.
if (lastErrorShown === errorMessage) {
void extLogger.log(message);
void this.app.logger.log(message);
} else {
void showAndLogWarningMessage(message);
void showAndLogWarningMessage(this.app.logger, message);
lastErrorShown = errorMessage;
}
@@ -107,7 +106,7 @@ export class VariantAnalysisMonitor extends DisposableObject {
// keep polling for the variant analysis if it no longer exists.
// Therefore, this block is down here rather than at the top of the
// catch block.
void extLogger.log(
void this.app.logger.log(
`Variant analysis ${variantAnalysisLabel} no longer exists or is no longer accessible, stopping monitoring.`,
);
// Cancel monitoring on 404, as this probably means the user does not have access to it anymore

View File

@@ -3,7 +3,7 @@ import {
AbstractWebview,
WebviewPanelConfig,
} from "../common/vscode/abstract-webview";
import { extLogger } from "../common";
import { showAndLogExceptionWithTelemetry } from "../common/vscode/logging";
import {
FromVariantAnalysisMessage,
ToVariantAnalysisMessage,
@@ -27,10 +27,7 @@ import {
getVariantAnalysisDefaultResultsFilter,
getVariantAnalysisDefaultResultsSort,
} from "../config";
import {
showAndLogExceptionWithTelemetry,
showAndLogWarningMessage,
} from "../common/vscode/log";
import { showAndLogWarningMessage } from "../common/logging";
export class VariantAnalysisView
extends AbstractWebview<ToVariantAnalysisMessage, FromVariantAnalysisMessage>
@@ -166,6 +163,7 @@ export class VariantAnalysisView
break;
case "unhandledError":
void showAndLogExceptionWithTelemetry(
this.app.logger,
redactableError(
msg.error,
)`Unhandled error in variant analysis results view: ${msg.error.message}`,
@@ -179,14 +177,17 @@ export class VariantAnalysisView
protected async onWebViewLoaded() {
super.onWebViewLoaded();
void extLogger.log("Variant analysis view loaded");
void this.app.logger.log("Variant analysis view loaded");
const variantAnalysis = await this.manager.getVariantAnalysis(
this.variantAnalysisId,
);
if (!variantAnalysis) {
void showAndLogWarningMessage("Unable to load variant analysis");
void showAndLogWarningMessage(
this.app.logger,
"Unable to load variant analysis",
);
return;
}

View File

@@ -8,6 +8,7 @@ import { testCredentialsWithStub } from "../factories/authentication";
import { Credentials } from "../../src/common/authentication";
import { AppCommandManager } from "../../src/common/commands";
import { createMockCommandManager } from "./commandsMock";
import { NotificationLogger } from "../../src/common";
export function createMockApp({
extensionPath = "/mock/extension/path",
@@ -18,6 +19,7 @@ export function createMockApp({
credentials = testCredentialsWithStub(),
commands = createMockCommandManager(),
environment = createMockEnvironmentContext(),
logger = createMockLogger(),
}: {
extensionPath?: string;
workspaceStoragePath?: string;
@@ -27,10 +29,11 @@ export function createMockApp({
credentials?: Credentials;
commands?: AppCommandManager;
environment?: EnvironmentContext;
logger?: NotificationLogger;
}): App {
return {
mode: AppMode.Test,
logger: createMockLogger(),
logger,
subscriptions: [],
extensionPath,
workspaceStoragePath,

View File

@@ -1,8 +1,11 @@
import { Logger } from "../../src/common";
import { NotificationLogger } from "../../src/common";
export function createMockLogger(): Logger {
export function createMockLogger(): NotificationLogger {
return {
log: jest.fn(() => Promise.resolve()),
show: jest.fn(),
showErrorMessage: jest.fn(),
showWarningMessage: jest.fn(),
showInformationMessage: jest.fn(),
};
}

View File

@@ -23,8 +23,8 @@ import {
import { createMockVariantAnalysis } from "../../../factories/variant-analysis/shared/variant-analysis";
import { createMockApp } from "../../../__mocks__/appMock";
import { createMockCommandManager } from "../../../__mocks__/commandsMock";
import * as log from "../../../../src/common/vscode/log";
import { showAndLogWarningMessage } from "../../../../src/common/vscode/log";
import { NotificationLogger } from "../../../../src/common/logging";
import { createMockLogger } from "../../../__mocks__/loggerMock";
jest.setTimeout(60_000);
@@ -39,16 +39,21 @@ describe("Variant Analysis Monitor", () => {
const onVariantAnalysisChangeSpy = jest.fn();
const mockEecuteCommand = jest.fn();
let logger: NotificationLogger;
beforeEach(async () => {
variantAnalysis = createMockVariantAnalysis({});
shouldCancelMonitor = jest.fn();
logger = createMockLogger();
variantAnalysisMonitor = new VariantAnalysisMonitor(
createMockApp({
commands: createMockCommandManager({
executeCommand: mockEecuteCommand,
}),
logger,
}),
shouldCancelMonitor,
);
@@ -200,17 +205,9 @@ describe("Variant Analysis Monitor", () => {
});
describe("when some responses fail", () => {
let showAndLogWarningMessageSpy: jest.SpiedFunction<
typeof showAndLogWarningMessage
>;
let scannedRepos: ApiVariantAnalysisScannedRepository[];
beforeEach(async () => {
showAndLogWarningMessageSpy = jest
.spyOn(log, "showAndLogWarningMessage")
.mockResolvedValue(undefined);
scannedRepos = createMockScannedRepos([
"pending",
"in_progress",
@@ -266,20 +263,20 @@ describe("Variant Analysis Monitor", () => {
it("should only trigger the warning once per error", async () => {
await variantAnalysisMonitor.monitorVariantAnalysis(variantAnalysis);
expect(showAndLogWarningMessageSpy).toBeCalledTimes(4);
expect(showAndLogWarningMessageSpy).toHaveBeenNthCalledWith(
expect(logger.showWarningMessage).toBeCalledTimes(4);
expect(logger.showWarningMessage).toHaveBeenNthCalledWith(
1,
expect.stringMatching(/No internet connection/),
);
expect(showAndLogWarningMessageSpy).toHaveBeenNthCalledWith(
expect(logger.showWarningMessage).toHaveBeenNthCalledWith(
2,
expect.stringMatching(/My different error/),
);
expect(showAndLogWarningMessageSpy).toHaveBeenNthCalledWith(
expect(logger.showWarningMessage).toHaveBeenNthCalledWith(
3,
expect.stringMatching(/My different error/),
);
expect(showAndLogWarningMessageSpy).toHaveBeenNthCalledWith(
expect(logger.showWarningMessage).toHaveBeenNthCalledWith(
4,
expect.stringMatching(/Another different error/),
);
@@ -301,15 +298,7 @@ describe("Variant Analysis Monitor", () => {
});
describe("when a 404 is returned", () => {
let showAndLogWarningMessageSpy: jest.SpiedFunction<
typeof showAndLogWarningMessage
>;
beforeEach(async () => {
showAndLogWarningMessageSpy = jest
.spyOn(log, "showAndLogWarningMessage")
.mockResolvedValue(undefined);
const scannedRepos = createMockScannedRepos([
"pending",
"in_progress",
@@ -342,8 +331,8 @@ describe("Variant Analysis Monitor", () => {
await variantAnalysisMonitor.monitorVariantAnalysis(variantAnalysis);
expect(mockGetVariantAnalysis).toHaveBeenCalledTimes(2);
expect(showAndLogWarningMessageSpy).toHaveBeenCalledTimes(1);
expect(showAndLogWarningMessageSpy).toHaveBeenCalledWith(
expect(logger.showWarningMessage).toHaveBeenCalledTimes(1);
expect(logger.showWarningMessage).toHaveBeenCalledWith(
expect.stringMatching(/not found/i),
);
});

View File

@@ -4,17 +4,16 @@ import { join } from "path";
import { CodeQLCliServer } from "../../../../src/codeql-cli/cli";
import { getErrorMessage } from "../../../../src/pure/helpers-pure";
import * as log from "../../../../src/common/vscode/log";
import * as log from "../../../../src/common/logging/notifications";
import * as vscodeLog from "../../../../src/common/vscode/logging";
import {
handleDownloadPacks,
handleInstallPackDependencies,
} from "../../../../src/packaging";
import { mockedQuickPickItem } from "../../utils/mocking.helpers";
import { getActivatedExtension } from "../../global.helper";
import {
showAndLogExceptionWithTelemetry,
showAndLogInformationMessage,
} from "../../../../src/common/vscode/log";
import { showAndLogInformationMessage } from "../../../../src/common/logging";
import { showAndLogExceptionWithTelemetry } from "../../../../src/common/vscode/logging";
describe("Packaging commands", () => {
let cli: CodeQLCliServer;
@@ -36,7 +35,7 @@ describe("Packaging commands", () => {
.spyOn(window, "showInputBox")
.mockResolvedValue(undefined);
showAndLogExceptionWithTelemetrySpy = jest
.spyOn(log, "showAndLogExceptionWithTelemetry")
.spyOn(vscodeLog, "showAndLogExceptionWithTelemetry")
.mockResolvedValue(undefined);
showAndLogInformationMessageSpy = jest
.spyOn(log, "showAndLogInformationMessage")
@@ -54,6 +53,7 @@ describe("Packaging commands", () => {
await handleDownloadPacks(cli, progress);
expect(showAndLogExceptionWithTelemetrySpy).not.toHaveBeenCalled();
expect(showAndLogInformationMessageSpy).toHaveBeenCalledWith(
expect.anything(),
expect.stringContaining("Finished downloading packs."),
);
});
@@ -67,6 +67,7 @@ describe("Packaging commands", () => {
await handleDownloadPacks(cli, progress);
expect(showAndLogExceptionWithTelemetrySpy).not.toHaveBeenCalled();
expect(showAndLogInformationMessageSpy).toHaveBeenCalledWith(
expect.anything(),
expect.stringContaining("Finished downloading packs."),
);
});
@@ -81,7 +82,7 @@ describe("Packaging commands", () => {
expect(showAndLogExceptionWithTelemetrySpy).toHaveBeenCalled();
expect(
showAndLogExceptionWithTelemetrySpy.mock.calls[0][0].fullMessage,
showAndLogExceptionWithTelemetrySpy.mock.calls[0][1].fullMessage,
).toEqual("Unable to download all packs. See log for more details.");
});
@@ -98,6 +99,7 @@ describe("Packaging commands", () => {
await handleInstallPackDependencies(cli, progress);
expect(showAndLogInformationMessageSpy).toHaveBeenCalledWith(
expect.anything(),
expect.stringContaining("Finished installing pack dependencies."),
);
});

View File

@@ -1,7 +1,7 @@
import * as fetch from "node-fetch";
import { Range } from "semver";
import * as log from "../../../../src/common/vscode/log";
import * as log from "../../../../src/common/logging/notifications";
import { extLogger } from "../../../../src/common";
import * as fs from "fs-extra";
import * as path from "path";
@@ -18,7 +18,7 @@ import {
import {
showAndLogErrorMessage,
showAndLogWarningMessage,
} from "../../../../src/common/vscode/log";
} from "../../../../src/common/logging";
jest.mock("os", () => {
const original = jest.requireActual("os");

View File

@@ -7,11 +7,10 @@ import {
QlpacksInfo,
ResolveExtensionsResult,
} from "../../../../src/codeql-cli/cli";
import * as log from "../../../../src/common/vscode/log";
import { pickExtensionPackModelFile } from "../../../../src/data-extensions-editor/extension-pack-picker";
import { ExtensionPack } from "../../../../src/data-extensions-editor/shared/extension-pack";
import { showAndLogErrorMessage } from "../../../../src/common/vscode/log";
import { createMockLogger } from "../../../__mocks__/loggerMock";
describe("pickExtensionPackModelFile", () => {
let tmpDir: string;
@@ -33,9 +32,8 @@ describe("pickExtensionPackModelFile", () => {
const progress = jest.fn();
let showQuickPickSpy: jest.SpiedFunction<typeof window.showQuickPick>;
let showInputBoxSpy: jest.SpiedFunction<typeof window.showInputBox>;
let showAndLogErrorMessageSpy: jest.SpiedFunction<
typeof showAndLogErrorMessage
>;
const logger = createMockLogger();
beforeEach(async () => {
tmpDir = (
@@ -79,11 +77,6 @@ describe("pickExtensionPackModelFile", () => {
showInputBoxSpy = jest
.spyOn(window, "showInputBox")
.mockRejectedValue(new Error("Unexpected call to showInputBox"));
showAndLogErrorMessageSpy = jest
.spyOn(log, "showAndLogErrorMessage")
.mockImplementation((msg) => {
throw new Error(`Unexpected call to showAndLogErrorMessage: ${msg}`);
});
});
it("allows choosing an existing extension pack and model file", async () => {
@@ -104,6 +97,7 @@ describe("pickExtensionPackModelFile", () => {
await pickExtensionPackModelFile(
cliServer,
databaseItem,
logger,
progress,
token,
),
@@ -178,6 +172,7 @@ describe("pickExtensionPackModelFile", () => {
await pickExtensionPackModelFile(
cliServer,
databaseItem,
logger,
progress,
token,
),
@@ -212,6 +207,7 @@ describe("pickExtensionPackModelFile", () => {
await pickExtensionPackModelFile(
cliServer,
databaseItem,
logger,
progress,
token,
),
@@ -240,6 +236,7 @@ describe("pickExtensionPackModelFile", () => {
await pickExtensionPackModelFile(
cliServer,
databaseItem,
logger,
progress,
token,
),
@@ -314,6 +311,7 @@ describe("pickExtensionPackModelFile", () => {
...databaseItem,
language: "csharp",
},
logger,
progress,
token,
),
@@ -374,6 +372,7 @@ describe("pickExtensionPackModelFile", () => {
await pickExtensionPackModelFile(
cliServer,
databaseItem,
logger,
progress,
token,
),
@@ -397,6 +396,7 @@ describe("pickExtensionPackModelFile", () => {
await pickExtensionPackModelFile(
cliServer,
databaseItem,
logger,
progress,
token,
),
@@ -408,8 +408,6 @@ describe("pickExtensionPackModelFile", () => {
});
it("shows an error when an extension pack resolves to more than 1 location", async () => {
showAndLogErrorMessageSpy.mockResolvedValue(undefined);
const cliServer = mockCliServer(
{
"my-extension-pack": [
@@ -426,14 +424,14 @@ describe("pickExtensionPackModelFile", () => {
await pickExtensionPackModelFile(
cliServer,
databaseItem,
logger,
progress,
token,
),
).toEqual(undefined);
expect(showAndLogErrorMessageSpy).toHaveBeenCalledTimes(1);
expect(showAndLogErrorMessageSpy).toHaveBeenCalledWith(
expect(logger.showErrorMessage).toHaveBeenCalledTimes(1);
expect(logger.showErrorMessage).toHaveBeenCalledWith(
expect.stringMatching(/resolves to multiple paths/),
expect.anything(),
);
expect(showQuickPickSpy).toHaveBeenCalledTimes(1);
expect(showQuickPickSpy).toHaveBeenCalledWith(
@@ -465,6 +463,7 @@ describe("pickExtensionPackModelFile", () => {
await pickExtensionPackModelFile(
cliServer,
databaseItem,
logger,
progress,
token,
),
@@ -501,6 +500,7 @@ describe("pickExtensionPackModelFile", () => {
await pickExtensionPackModelFile(
cliServer,
databaseItem,
logger,
progress,
token,
),
@@ -534,12 +534,12 @@ describe("pickExtensionPackModelFile", () => {
);
showQuickPickSpy.mockResolvedValueOnce(undefined);
showAndLogErrorMessageSpy.mockResolvedValue(undefined);
expect(
await pickExtensionPackModelFile(
cliServer,
databaseItem,
logger,
progress,
token,
),
@@ -558,10 +558,9 @@ describe("pickExtensionPackModelFile", () => {
token,
);
expect(showInputBoxSpy).not.toHaveBeenCalled();
expect(showAndLogErrorMessageSpy).toHaveBeenCalledTimes(1);
expect(showAndLogErrorMessageSpy).toHaveBeenCalledWith(
expect(logger.showErrorMessage).toHaveBeenCalledTimes(1);
expect(logger.showErrorMessage).toHaveBeenCalledWith(
expect.stringMatching(/my-extension-pack/),
expect.anything(),
);
expect(cliServer.resolveQlpacks).toHaveBeenCalled();
expect(cliServer.resolveExtensions).not.toHaveBeenCalled();
@@ -582,12 +581,12 @@ describe("pickExtensionPackModelFile", () => {
await outputFile(join(tmpDir.path, "codeql-pack.yml"), dumpYaml("java"));
showQuickPickSpy.mockResolvedValueOnce(undefined);
showAndLogErrorMessageSpy.mockResolvedValue(undefined);
expect(
await pickExtensionPackModelFile(
cliServer,
databaseItem,
logger,
progress,
token,
),
@@ -606,10 +605,9 @@ describe("pickExtensionPackModelFile", () => {
token,
);
expect(showInputBoxSpy).not.toHaveBeenCalled();
expect(showAndLogErrorMessageSpy).toHaveBeenCalledTimes(1);
expect(showAndLogErrorMessageSpy).toHaveBeenCalledWith(
expect(logger.showErrorMessage).toHaveBeenCalledTimes(1);
expect(logger.showErrorMessage).toHaveBeenCalledWith(
expect.stringMatching(/my-extension-pack/),
expect.anything(),
);
expect(cliServer.resolveQlpacks).toHaveBeenCalled();
expect(cliServer.resolveExtensions).not.toHaveBeenCalled();
@@ -640,12 +638,12 @@ describe("pickExtensionPackModelFile", () => {
);
showQuickPickSpy.mockResolvedValueOnce(undefined);
showAndLogErrorMessageSpy.mockResolvedValue(undefined);
expect(
await pickExtensionPackModelFile(
cliServer,
databaseItem,
logger,
progress,
token,
),
@@ -664,10 +662,9 @@ describe("pickExtensionPackModelFile", () => {
token,
);
expect(showInputBoxSpy).not.toHaveBeenCalled();
expect(showAndLogErrorMessageSpy).toHaveBeenCalledTimes(1);
expect(showAndLogErrorMessageSpy).toHaveBeenCalledWith(
expect(logger.showErrorMessage).toHaveBeenCalledTimes(1);
expect(logger.showErrorMessage).toHaveBeenCalledWith(
expect.stringMatching(/my-extension-pack/),
expect.anything(),
);
expect(cliServer.resolveQlpacks).toHaveBeenCalled();
expect(cliServer.resolveExtensions).not.toHaveBeenCalled();
@@ -701,12 +698,12 @@ describe("pickExtensionPackModelFile", () => {
);
showQuickPickSpy.mockResolvedValueOnce(undefined);
showAndLogErrorMessageSpy.mockResolvedValue(undefined);
expect(
await pickExtensionPackModelFile(
cliServer,
databaseItem,
logger,
progress,
token,
),
@@ -725,10 +722,9 @@ describe("pickExtensionPackModelFile", () => {
token,
);
expect(showInputBoxSpy).not.toHaveBeenCalled();
expect(showAndLogErrorMessageSpy).toHaveBeenCalledTimes(1);
expect(showAndLogErrorMessageSpy).toHaveBeenCalledWith(
expect(logger.showErrorMessage).toHaveBeenCalledTimes(1);
expect(logger.showErrorMessage).toHaveBeenCalledWith(
expect.stringMatching(/my-extension-pack/),
expect.anything(),
);
expect(cliServer.resolveQlpacks).toHaveBeenCalled();
expect(cliServer.resolveExtensions).not.toHaveBeenCalled();
@@ -765,6 +761,7 @@ describe("pickExtensionPackModelFile", () => {
await pickExtensionPackModelFile(
cliServer,
databaseItem,
logger,
progress,
token,
),
@@ -788,6 +785,7 @@ describe("pickExtensionPackModelFile", () => {
await pickExtensionPackModelFile(
cliServer,
databaseItem,
logger,
progress,
token,
),
@@ -862,6 +860,7 @@ describe("pickExtensionPackModelFile", () => {
await pickExtensionPackModelFile(
cliServer,
databaseItem,
logger,
progress,
token,
),
@@ -946,6 +945,7 @@ describe("pickExtensionPackModelFile", () => {
await pickExtensionPackModelFile(
cliServer,
databaseItem,
logger,
progress,
token,
),
@@ -989,6 +989,7 @@ describe("pickExtensionPackModelFile", () => {
...databaseItem,
language: "csharp",
},
logger,
progress,
token,
),

View File

@@ -11,9 +11,9 @@ import { readdir, readFile } from "fs-extra";
import { load } from "js-yaml";
import { dirname, join } from "path";
import { fetchExternalApiQueries } from "../../../../src/data-extensions-editor/queries";
import * as log from "../../../../src/common/vscode/log";
import * as vscodeLog from "../../../../src/common/vscode/logging";
import { RedactableError } from "../../../../src/pure/errors";
import { showAndLogExceptionWithTelemetry } from "../../../../src/common/vscode/log";
import { showAndLogExceptionWithTelemetry } from "../../../../src/common/vscode/logging";
function createMockUri(path = "/a/b/c/foo"): Uri {
return {
@@ -140,7 +140,7 @@ describe("readQueryResults", () => {
beforeEach(() => {
showAndLogExceptionWithTelemetrySpy = jest.spyOn(
log,
vscodeLog,
"showAndLogExceptionWithTelemetry",
);
});
@@ -152,6 +152,7 @@ describe("readQueryResults", () => {
expect(await readQueryResults(options)).toBeUndefined();
expect(showAndLogExceptionWithTelemetrySpy).toHaveBeenCalledWith(
expect.anything(),
expect.any(RedactableError),
);
});
@@ -184,6 +185,7 @@ describe("readQueryResults", () => {
expect(await readQueryResults(options)).toBeUndefined();
expect(showAndLogExceptionWithTelemetrySpy).toHaveBeenCalledWith(
expect.anything(),
expect.any(RedactableError),
);
});

View File

@@ -3,7 +3,7 @@ import * as fs from "fs-extra";
import { getErrorMessage } from "../../../../../src/pure/helpers-pure";
import * as log from "../../../../../src/common/vscode/log";
import * as log from "../../../../../src/common/logging/notifications";
import * as workspaceFolders from "../../../../../src/common/vscode/workspace-folders";
import * as qlpack from "../../../../../src/databases/qlpack";
import {