Files
vscode-codeql/extensions/ql-vscode/src/model-editor/generate.ts
2023-11-01 14:55:49 +01:00

100 lines
2.8 KiB
TypeScript

import { CancellationToken } from "vscode";
import { DatabaseItem } from "../databases/local-databases";
import { basename } from "path";
import { QueryRunner } from "../query-server";
import { CodeQLCliServer } from "../codeql-cli/cli";
import { ProgressCallback } from "../common/vscode/progress";
import { getOnDiskWorkspaceFolders } from "../common/vscode/workspace-folders";
import { ModeledMethod } from "./modeled-method";
import { runQuery } from "../local-queries/run-query";
import { QueryConstraints, resolveQueries } from "../local-queries";
import { DecodedBqrs } from "../common/bqrs-cli-types";
type GenerateQueriesOptions = {
queryConstraints: QueryConstraints;
filterQueries?: (queryPath: string) => boolean;
parseResults: (
queryPath: string,
results: DecodedBqrs,
) => ModeledMethod[] | Promise<ModeledMethod[]>;
onResults: (results: ModeledMethod[]) => void | Promise<void>;
cliServer: CodeQLCliServer;
queryRunner: QueryRunner;
queryStorageDir: string;
databaseItem: DatabaseItem;
progress: ProgressCallback;
token: CancellationToken;
};
export async function runGenerateQueries(options: GenerateQueriesOptions) {
const { queryConstraints, filterQueries, parseResults, onResults } = options;
options.progress({
message: "Resolving queries",
step: 1,
maxStep: 5000,
});
const packsToSearch = [`codeql/${options.databaseItem.language}-queries`];
const queryPaths = await resolveQueries(
options.cliServer,
packsToSearch,
"generate model",
queryConstraints,
);
const filteredQueryPaths = filterQueries
? queryPaths.filter(filterQueries)
: queryPaths;
const maxStep = filteredQueryPaths.length * 1000;
for (let i = 0; i < filteredQueryPaths.length; i++) {
const queryPath = filteredQueryPaths[i];
const bqrs = await runSingleGenerateQuery(queryPath, i, maxStep, options);
if (bqrs) {
await onResults(await parseResults(queryPath, bqrs));
}
}
}
async function runSingleGenerateQuery(
queryPath: string,
queryStep: number,
maxStep: number,
{
cliServer,
queryRunner,
queryStorageDir,
databaseItem,
progress,
token,
}: GenerateQueriesOptions,
): Promise<DecodedBqrs | undefined> {
const queryBasename = basename(queryPath);
// Run the query
const completedQuery = await runQuery({
queryRunner,
databaseItem,
queryPath,
queryStorageDir,
additionalPacks: getOnDiskWorkspaceFolders(),
extensionPacks: undefined,
progress: ({ step, message }) =>
progress({
message: `Generating model from ${queryBasename}: ${message}`,
step: queryStep * 1000 + step,
maxStep,
}),
token,
});
if (!completedQuery) {
return undefined;
}
return cliServer.bqrsDecodeAll(completedQuery.outputDir.bqrsPath);
}