Remove QueryRunner abstraction

Since we're only supporting the new query server, we can remove the
`QueryRunner` abstraction and just use the `NewQueryRunner` as a
concrete `QueryRunner` without an abstract base class. This simplifies
the code of the query server and removes some unnecessary indirection.
This commit is contained in:
Koen Vlaswinkel
2023-12-21 16:03:28 +01:00
parent 43ea7eb41d
commit 785a5fa48a
7 changed files with 138 additions and 205 deletions

View File

@@ -129,7 +129,7 @@ import { ModelEditorModule } from "./model-editor/model-editor-module";
import { TestManager } from "./query-testing/test-manager";
import { TestRunner } from "./query-testing/test-runner";
import { TestManagerBase } from "./query-testing/test-manager-base";
import { NewQueryRunner, QueryRunner, QueryServerClient } from "./query-server";
import { QueryRunner, QueryServerClient } from "./query-server";
import { QueriesModule } from "./queries-panel/queries-module";
import { OpenReferencedFileCodeLensProvider } from "./local-queries/open-referenced-file-code-lens-provider";
import { LanguageContextStore } from "./language-context-store";
@@ -1256,7 +1256,7 @@ async function createQueryServer(
);
ctx.subscriptions.push(qs);
await qs.startQueryServer();
return new NewQueryRunner(qs);
return new QueryRunner(qs);
}
function getContextStoragePath(ctx: ExtensionContext) {

View File

@@ -1,4 +1,3 @@
export * from "./new-query-runner";
export * from "./query-runner";
export * from "./query-server-client";
export * from "./run-queries";

View File

@@ -1,168 +0,0 @@
import { CancellationToken } from "vscode";
import {
ProgressCallback,
UserCancellationException,
} from "../common/vscode/progress";
import { DatabaseItem } from "../databases/local-databases";
import {
clearCache,
ClearCacheParams,
clearPackCache,
deregisterDatabases,
registerDatabases,
trimCache,
TrimCacheParams,
upgradeDatabase,
} from "./new-messages";
import { CoreQueryResults, CoreQueryTarget, QueryRunner } from "./query-runner";
import { QueryServerClient } from "./query-server-client";
import { compileAndRunQueryAgainstDatabaseCore } from "./run-queries";
import * as vscode from "vscode";
import { getOnDiskWorkspaceFolders } from "../common/vscode/workspace-folders";
import { CodeQLCliServer } from "../codeql-cli/cli";
import { Logger } from "../common/logging";
import { QueryOutputDir } from "../run-queries-shared";
export class NewQueryRunner extends QueryRunner {
constructor(public readonly qs: QueryServerClient) {
super();
}
get cliServer(): CodeQLCliServer {
return this.qs.cliServer;
}
get customLogDirectory(): string | undefined {
return this.qs.config.customLogDirectory;
}
get logger(): Logger {
return this.qs.logger;
}
async restartQueryServer(
progress: ProgressCallback,
token: CancellationToken,
): Promise<void> {
await this.qs.restartQueryServer(progress, token);
}
onStart(
callBack: (
progress: ProgressCallback,
token: CancellationToken,
) => Promise<void>,
) {
this.qs.onDidStartQueryServer(callBack);
}
async clearCacheInDatabase(
dbItem: DatabaseItem,
token: CancellationToken,
): Promise<void> {
if (dbItem.contents === undefined) {
throw new Error("Can't clear the cache in an invalid database.");
}
const db = dbItem.databaseUri.fsPath;
const params: ClearCacheParams = {
dryRun: false,
db,
};
await this.qs.sendRequest(clearCache, params, token);
}
async trimCacheInDatabase(
dbItem: DatabaseItem,
token: CancellationToken,
): Promise<void> {
if (dbItem.contents === undefined) {
throw new Error("Can't trim the cache in an invalid database.");
}
const db = dbItem.databaseUri.fsPath;
const params: TrimCacheParams = {
db,
};
await this.qs.sendRequest(trimCache, params, token);
}
public async compileAndRunQueryAgainstDatabaseCore(
dbPath: string,
query: CoreQueryTarget,
additionalPacks: string[],
extensionPacks: string[] | undefined,
additionalRunQueryArgs: Record<string, any>,
generateEvalLog: boolean,
outputDir: QueryOutputDir,
progress: ProgressCallback,
token: CancellationToken,
templates: Record<string, string> | undefined,
logger: Logger,
): Promise<CoreQueryResults> {
return await compileAndRunQueryAgainstDatabaseCore(
this.qs,
dbPath,
query,
generateEvalLog,
additionalPacks,
extensionPacks,
additionalRunQueryArgs,
outputDir,
progress,
token,
templates,
logger,
);
}
async deregisterDatabase(dbItem: DatabaseItem): Promise<void> {
if (dbItem.contents) {
const databases: string[] = [dbItem.databaseUri.fsPath];
await this.qs.sendRequest(deregisterDatabases, { databases });
}
}
async registerDatabase(dbItem: DatabaseItem): Promise<void> {
if (dbItem.contents) {
const databases: string[] = [dbItem.databaseUri.fsPath];
await this.qs.sendRequest(registerDatabases, { databases });
}
}
async clearPackCache(): Promise<void> {
await this.qs.sendRequest(clearPackCache, {});
}
async upgradeDatabaseExplicit(
dbItem: DatabaseItem,
progress: ProgressCallback,
token: CancellationToken,
): Promise<void> {
const yesItem = { title: "Yes", isCloseAffordance: false };
const noItem = { title: "No", isCloseAffordance: true };
const dialogOptions: vscode.MessageItem[] = [yesItem, noItem];
const message = `Should the database ${dbItem.databaseUri.fsPath} be destructively upgraded?\n\nThis should not be necessary to run queries
as we will non-destructively update it anyway.`;
const chosenItem = await vscode.window.showInformationMessage(
message,
{ modal: true },
...dialogOptions,
);
if (chosenItem !== yesItem) {
throw new UserCancellationException(
"User cancelled the database upgrade.",
);
}
await this.qs.sendRequest(
upgradeDatabase,
{
db: dbItem.databaseUri.fsPath,
additionalPacks: getOnDiskWorkspaceFolders(),
},
token,
progress,
);
}
}

View File

@@ -1,12 +1,29 @@
import { CancellationToken } from "vscode";
import vscode, { CancellationToken } from "vscode";
import { CodeQLCliServer } from "../codeql-cli/cli";
import { ProgressCallback } from "../common/vscode/progress";
import {
ProgressCallback,
UserCancellationException,
} from "../common/vscode/progress";
import { DatabaseItem } from "../databases/local-databases";
import { QueryOutputDir } from "../run-queries-shared";
import { Position, QueryResultType } from "./new-messages";
import {
clearCache,
ClearCacheParams,
clearPackCache,
deregisterDatabases,
Position,
QueryResultType,
registerDatabases,
trimCache,
TrimCacheParams,
upgradeDatabase,
} from "./new-messages";
import { BaseLogger, Logger } from "../common/logging";
import { basename, join } from "path";
import { nanoid } from "nanoid";
import { QueryServerClient } from "./query-server-client";
import { getOnDiskWorkspaceFolders } from "../common/vscode/workspace-folders";
import { compileAndRunQueryAgainstDatabaseCore } from "./run-queries";
export interface CoreQueryTarget {
/** The full path to the query. */
@@ -45,37 +62,69 @@ export interface CoreQueryRun {
export type CoreCompletedQuery = CoreQueryResults &
Omit<CoreQueryRun, "evaluate">;
export abstract class QueryRunner {
abstract restartQueryServer(
export class QueryRunner {
constructor(public readonly qs: QueryServerClient) {}
get cliServer(): CodeQLCliServer {
return this.qs.cliServer;
}
get customLogDirectory(): string | undefined {
return this.qs.config.customLogDirectory;
}
get logger(): Logger {
return this.qs.logger;
}
async restartQueryServer(
progress: ProgressCallback,
token: CancellationToken,
): Promise<void>;
): Promise<void> {
await this.qs.restartQueryServer(progress, token);
}
abstract cliServer: CodeQLCliServer;
abstract customLogDirectory: string | undefined;
abstract logger: Logger;
abstract onStart(
arg0: (
onStart(
callBack: (
progress: ProgressCallback,
token: CancellationToken,
) => Promise<void>,
): void;
) {
this.qs.onDidStartQueryServer(callBack);
}
abstract clearCacheInDatabase(
async clearCacheInDatabase(
dbItem: DatabaseItem,
token: CancellationToken,
): Promise<void>;
): Promise<void> {
if (dbItem.contents === undefined) {
throw new Error("Can't clear the cache in an invalid database.");
}
abstract trimCacheInDatabase(
const db = dbItem.databaseUri.fsPath;
const params: ClearCacheParams = {
dryRun: false,
db,
};
await this.qs.sendRequest(clearCache, params, token);
}
async trimCacheInDatabase(
dbItem: DatabaseItem,
token: CancellationToken,
): Promise<void>;
): Promise<void> {
if (dbItem.contents === undefined) {
throw new Error("Can't trim the cache in an invalid database.");
}
/**
* Overridden in subclasses to evaluate the query via the query server and return the results.
*/
public abstract compileAndRunQueryAgainstDatabaseCore(
const db = dbItem.databaseUri.fsPath;
const params: TrimCacheParams = {
db,
};
await this.qs.sendRequest(trimCache, params, token);
}
public async compileAndRunQueryAgainstDatabaseCore(
dbPath: string,
query: CoreQueryTarget,
additionalPacks: string[],
@@ -87,19 +136,72 @@ export abstract class QueryRunner {
token: CancellationToken,
templates: Record<string, string> | undefined,
logger: BaseLogger,
): Promise<CoreQueryResults>;
): Promise<CoreQueryResults> {
return await compileAndRunQueryAgainstDatabaseCore(
this.qs,
dbPath,
query,
generateEvalLog,
additionalPacks,
extensionPacks,
additionalRunQueryArgs,
outputDir,
progress,
token,
templates,
logger,
);
}
abstract deregisterDatabase(dbItem: DatabaseItem): Promise<void>;
async deregisterDatabase(dbItem: DatabaseItem): Promise<void> {
if (dbItem.contents) {
const databases: string[] = [dbItem.databaseUri.fsPath];
await this.qs.sendRequest(deregisterDatabases, { databases });
}
}
async registerDatabase(dbItem: DatabaseItem): Promise<void> {
if (dbItem.contents) {
const databases: string[] = [dbItem.databaseUri.fsPath];
await this.qs.sendRequest(registerDatabases, { databases });
}
}
abstract registerDatabase(dbItem: DatabaseItem): Promise<void>;
async clearPackCache(): Promise<void> {
await this.qs.sendRequest(clearPackCache, {});
}
abstract upgradeDatabaseExplicit(
async upgradeDatabaseExplicit(
dbItem: DatabaseItem,
progress: ProgressCallback,
token: CancellationToken,
): Promise<void>;
): Promise<void> {
const yesItem = { title: "Yes", isCloseAffordance: false };
const noItem = { title: "No", isCloseAffordance: true };
const dialogOptions: vscode.MessageItem[] = [yesItem, noItem];
abstract clearPackCache(): Promise<void>;
const message = `Should the database ${dbItem.databaseUri.fsPath} be destructively upgraded?\n\nThis should not be necessary to run queries
as we will non-destructively update it anyway.`;
const chosenItem = await vscode.window.showInformationMessage(
message,
{ modal: true },
...dialogOptions,
);
if (chosenItem !== yesItem) {
throw new UserCancellationException(
"User cancelled the database upgrade.",
);
}
await this.qs.sendRequest(
upgradeDatabase,
{
db: dbItem.databaseUri.fsPath,
additionalPacks: getOnDiskWorkspaceFolders(),
},
token,
progress,
);
}
/**
* Create a `CoreQueryRun` object. This creates an object whose `evaluate()` function can be

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, showAndLogErrorMessage } from "../common/logging";
import { BaseLogger, Logger, showAndLogErrorMessage } from "../common/logging";
import { extLogger, ProgressReporter } from "../common/logging/vscode";
import { progress, ProgressMessage, WithProgressId } from "./new-messages";
import {
@@ -57,7 +57,7 @@ export class QueryServerClient extends DisposableObject {
this.queryServerStartListeners.push(e);
};
public activeQueryLogger: Logger;
public activeQueryLogger: BaseLogger;
constructor(
app: App,

View File

@@ -4,7 +4,7 @@ import * as messages from "./new-messages";
import { QueryOutputDir } from "../run-queries-shared";
import * as qsClient from "./query-server-client";
import { CoreQueryResults, CoreQueryTarget } from "./query-runner";
import { Logger } from "../common/logging";
import { BaseLogger } from "../common/logging";
/**
* run-queries.ts
@@ -32,7 +32,7 @@ export async function compileAndRunQueryAgainstDatabaseCore(
progress: ProgressCallback,
token: CancellationToken,
templates: Record<string, string> | undefined,
logger: Logger,
logger: BaseLogger,
): Promise<CoreQueryResults> {
const target =
query.quickEvalPosition !== undefined

View File

@@ -12,7 +12,7 @@ import {
mockedObject,
} from "../utils/mocking.helpers";
import { BqrsKind } from "../../../src/common/bqrs-cli-types";
import { NewQueryRunner, QueryServerClient } from "../../../src/query-server";
import { QueryRunner, QueryServerClient } from "../../../src/query-server";
import { QueryEvaluationInfo } from "../../../src/run-queries-shared";
import {
deregisterDatabases,
@@ -169,7 +169,7 @@ describe("run-queries", () => {
describe("register", () => {
it("should register", async () => {
const qs = createMockQueryServerClient();
const runner = new NewQueryRunner(qs);
const runner = new QueryRunner(qs);
const databaseUri = Uri.file("database-uri");
const datasetUri = Uri.file("dataset-uri");
@@ -190,7 +190,7 @@ describe("run-queries", () => {
it("should deregister", async () => {
const qs = createMockQueryServerClient();
const runner = new NewQueryRunner(qs);
const runner = new QueryRunner(qs);
const databaseUri = Uri.file("database-uri");
const datasetUri = Uri.file("dataset-uri");