Move qlpacks helpers to separate file

This commit is contained in:
Koen Vlaswinkel
2023-06-12 10:59:42 +02:00
parent fe21a21ca2
commit 706c6b8a7a
6 changed files with 144 additions and 139 deletions

View File

@@ -0,0 +1,130 @@
import { window } from "vscode";
import { glob } from "glob";
import { basename } from "path";
import { load } from "js-yaml";
import { readFile } from "fs-extra";
import { getQlPackPath } from "../pure/ql";
import { CodeQLCliServer, QlpacksInfo } from "../codeql-cli/cli";
import { extLogger } from "../common";
import { getOnDiskWorkspaceFolders } from "../helpers";
export interface QlPacksForLanguage {
/** The name of the pack containing the dbscheme. */
dbschemePack: string;
/** `true` if `dbschemePack` is a library pack. */
dbschemePackIsLibraryPack: boolean;
/**
* The name of the corresponding standard query pack.
* Only defined if `dbschemePack` is a library pack.
*/
queryPack?: string;
}
interface QlPackWithPath {
packName: string;
packDir: string | undefined;
}
async function findDbschemePack(
packs: QlPackWithPath[],
dbschemePath: string,
): Promise<{ name: string; isLibraryPack: boolean }> {
for (const { packDir, packName } of packs) {
if (packDir !== undefined) {
const qlpackPath = await getQlPackPath(packDir);
if (qlpackPath !== undefined) {
const qlpack = load(await readFile(qlpackPath, "utf8")) as {
dbscheme?: string;
library?: boolean;
};
if (
qlpack.dbscheme !== undefined &&
basename(qlpack.dbscheme) === basename(dbschemePath)
) {
return {
name: packName,
isLibraryPack: qlpack.library === true,
};
}
}
}
}
throw new Error(`Could not find qlpack file for dbscheme ${dbschemePath}`);
}
function findStandardQueryPack(
qlpacks: QlpacksInfo,
dbschemePackName: string,
): string | undefined {
const matches = dbschemePackName.match(/^codeql\/(?<language>[a-z]+)-all$/);
if (matches) {
const queryPackName = `codeql/${matches.groups!.language}-queries`;
if (qlpacks[queryPackName] !== undefined) {
return queryPackName;
}
}
// Either the dbscheme pack didn't look like one where the queries might be in the query pack, or
// no query pack was found in the search path. Either is OK.
return undefined;
}
export async function getQlPackForDbscheme(
cliServer: Pick<CodeQLCliServer, "resolveQlpacks">,
dbschemePath: string,
): Promise<QlPacksForLanguage> {
const qlpacks = await cliServer.resolveQlpacks(getOnDiskWorkspaceFolders());
const packs: QlPackWithPath[] = Object.entries(qlpacks).map(
([packName, dirs]) => {
if (dirs.length < 1) {
void extLogger.log(
`In getQlPackFor ${dbschemePath}, qlpack ${packName} has no directories`,
);
return { packName, packDir: undefined };
}
if (dirs.length > 1) {
void extLogger.log(
`In getQlPackFor ${dbschemePath}, qlpack ${packName} has more than one directory; arbitrarily choosing the first`,
);
}
return {
packName,
packDir: dirs[0],
};
},
);
const dbschemePack = await findDbschemePack(packs, dbschemePath);
const queryPack = dbschemePack.isLibraryPack
? findStandardQueryPack(qlpacks, dbschemePack.name)
: undefined;
return {
dbschemePack: dbschemePack.name,
dbschemePackIsLibraryPack: dbschemePack.isLibraryPack,
queryPack,
};
}
export async function getPrimaryDbscheme(
datasetFolder: string,
): Promise<string> {
const dbschemes = await glob("*.dbscheme", {
cwd: datasetFolder,
});
if (dbschemes.length < 1) {
throw new Error(
`Can't find dbscheme for current database in ${datasetFolder}`,
);
}
dbschemes.sort();
const dbscheme = dbschemes[0];
if (dbschemes.length > 1) {
void window.showErrorMessage(
`Found multiple dbschemes in ${datasetFolder} during quick query; arbitrarily choosing the first, ${dbscheme}, to decide what library to use.`,
);
}
return dbscheme;
}

View File

@@ -1,23 +1,20 @@
import {
ensureDirSync,
readFile,
pathExists,
ensureDir,
writeFile,
opendir,
} from "fs-extra";
import { glob } from "glob";
import { load } from "js-yaml";
import { join, basename, dirname } from "path";
import { dirSync } from "tmp-promise";
import { Uri, window as Window, workspace, env, WorkspaceFolder } from "vscode";
import { CodeQLCliServer, QlpacksInfo } from "./codeql-cli/cli";
import { CodeQLCliServer } from "./codeql-cli/cli";
import { UserCancellationException } from "./common/vscode/progress";
import { extLogger, OutputChannelLogger } from "./common";
import { QueryMetadata } from "./pure/interface-types";
import { telemetryListener } from "./telemetry";
import { RedactableError } from "./pure/errors";
import { getQlPackPath } from "./pure/ql";
import { dbSchemeToLanguage, QueryLanguage } from "./common/query-language";
import { isCodespacesTemplate } from "./config";
import { AppCommandManager } from "./common/commands";
@@ -356,127 +353,6 @@ export async function prepareCodeTour(
}
}
export interface QlPacksForLanguage {
/** The name of the pack containing the dbscheme. */
dbschemePack: string;
/** `true` if `dbschemePack` is a library pack. */
dbschemePackIsLibraryPack: boolean;
/**
* The name of the corresponding standard query pack.
* Only defined if `dbschemePack` is a library pack.
*/
queryPack?: string;
}
interface QlPackWithPath {
packName: string;
packDir: string | undefined;
}
async function findDbschemePack(
packs: QlPackWithPath[],
dbschemePath: string,
): Promise<{ name: string; isLibraryPack: boolean }> {
for (const { packDir, packName } of packs) {
if (packDir !== undefined) {
const qlpackPath = await getQlPackPath(packDir);
if (qlpackPath !== undefined) {
const qlpack = load(await readFile(qlpackPath, "utf8")) as {
dbscheme?: string;
library?: boolean;
};
if (
qlpack.dbscheme !== undefined &&
basename(qlpack.dbscheme) === basename(dbschemePath)
) {
return {
name: packName,
isLibraryPack: qlpack.library === true,
};
}
}
}
}
throw new Error(`Could not find qlpack file for dbscheme ${dbschemePath}`);
}
function findStandardQueryPack(
qlpacks: QlpacksInfo,
dbschemePackName: string,
): string | undefined {
const matches = dbschemePackName.match(/^codeql\/(?<language>[a-z]+)-all$/);
if (matches) {
const queryPackName = `codeql/${matches.groups!.language}-queries`;
if (qlpacks[queryPackName] !== undefined) {
return queryPackName;
}
}
// Either the dbscheme pack didn't look like one where the queries might be in the query pack, or
// no query pack was found in the search path. Either is OK.
return undefined;
}
export async function getQlPackForDbscheme(
cliServer: Pick<CodeQLCliServer, "resolveQlpacks">,
dbschemePath: string,
): Promise<QlPacksForLanguage> {
const qlpacks = await cliServer.resolveQlpacks(getOnDiskWorkspaceFolders());
const packs: QlPackWithPath[] = Object.entries(qlpacks).map(
([packName, dirs]) => {
if (dirs.length < 1) {
void extLogger.log(
`In getQlPackFor ${dbschemePath}, qlpack ${packName} has no directories`,
);
return { packName, packDir: undefined };
}
if (dirs.length > 1) {
void extLogger.log(
`In getQlPackFor ${dbschemePath}, qlpack ${packName} has more than one directory; arbitrarily choosing the first`,
);
}
return {
packName,
packDir: dirs[0],
};
},
);
const dbschemePack = await findDbschemePack(packs, dbschemePath);
const queryPack = dbschemePack.isLibraryPack
? findStandardQueryPack(qlpacks, dbschemePack.name)
: undefined;
return {
dbschemePack: dbschemePack.name,
dbschemePackIsLibraryPack: dbschemePack.isLibraryPack,
queryPack,
};
}
export async function getPrimaryDbscheme(
datasetFolder: string,
): Promise<string> {
const dbschemes = await glob("*.dbscheme", {
cwd: datasetFolder,
});
if (dbschemes.length < 1) {
throw new Error(
`Can't find dbscheme for current database in ${datasetFolder}`,
);
}
dbschemes.sort();
const dbscheme = dbschemes[0];
if (dbschemes.length > 1) {
void Window.showErrorMessage(
`Found multiple dbschemes in ${datasetFolder} during quick query; arbitrarily choosing the first, ${dbscheme}, to decide what library to use.`,
);
}
return dbscheme;
}
/**
* The following functions al heuristically determine metadata about databases.
*/

View File

@@ -4,12 +4,14 @@ import { file } from "tmp-promise";
import { basename, dirname, resolve } from "path";
import {
getPrimaryDbscheme,
getQlPackForDbscheme,
getOnDiskWorkspaceFolders,
QlPacksForLanguage,
showAndLogExceptionWithTelemetry,
} from "../../helpers";
import {
getPrimaryDbscheme,
getQlPackForDbscheme,
QlPacksForLanguage,
} from "../../databases/qlpack";
import {
KeyType,
kindOfKeyType,

View File

@@ -5,12 +5,8 @@ import { CancellationToken, window as Window, workspace, Uri } from "vscode";
import { LSPErrorCodes, ResponseError } from "vscode-languageclient";
import { CodeQLCliServer } from "../codeql-cli/cli";
import { DatabaseUI } from "../databases/local-databases-ui";
import {
getInitialQueryContents,
getPrimaryDbscheme,
getQlPackForDbscheme,
showBinaryChoiceDialog,
} from "../helpers";
import { getInitialQueryContents, showBinaryChoiceDialog } from "../helpers";
import { getPrimaryDbscheme, getQlPackForDbscheme } from "../databases/qlpack";
import {
ProgressCallback,
UserCancellationException,

View File

@@ -9,13 +9,13 @@ import {
import { itWithCodeQL } from "../cli";
import {
getOnDiskWorkspaceFolders,
getQlPackForDbscheme,
languageToDbScheme,
} from "../../../src/helpers";
import { KeyType, resolveQueries } from "../../../src/language-support";
import { faker } from "@faker-js/faker";
import { getActivatedExtension } from "../global.helper";
import { BaseLogger } from "../../../src/common";
import { getQlPackForDbscheme } from "../../../src/databases/qlpack";
/**
* Perform proper integration tests by running the CLI

View File

@@ -4,6 +4,7 @@ import * as fs from "fs-extra";
import { getErrorMessage } from "../../../../../src/pure/helpers-pure";
import * as helpers from "../../../../../src/helpers";
import * as qlpack from "../../../../../src/databases/qlpack";
import {
KeyType,
qlpackOfDatabase,
@@ -14,10 +15,10 @@ import { mockDatabaseItem, mockedObject } from "../../../utils/mocking.helpers";
describe("queryResolver", () => {
let getQlPackForDbschemeSpy: jest.SpiedFunction<
typeof helpers.getQlPackForDbscheme
typeof qlpack.getQlPackForDbscheme
>;
let getPrimaryDbschemeSpy: jest.SpiedFunction<
typeof helpers.getPrimaryDbscheme
typeof qlpack.getPrimaryDbscheme
>;
const resolveQueriesInSuite = jest.fn();
@@ -28,13 +29,13 @@ describe("queryResolver", () => {
beforeEach(() => {
getQlPackForDbschemeSpy = jest
.spyOn(helpers, "getQlPackForDbscheme")
.spyOn(qlpack, "getQlPackForDbscheme")
.mockResolvedValue({
dbschemePack: "dbschemePack",
dbschemePackIsLibraryPack: false,
});
getPrimaryDbschemeSpy = jest
.spyOn(helpers, "getPrimaryDbscheme")
.spyOn(qlpack, "getPrimaryDbscheme")
.mockResolvedValue("primaryDbscheme");
jest.spyOn(helpers, "getOnDiskWorkspaceFolders").mockReturnValue([]);