Merge pull request #2777 from github/robertbrignull/model-remove-disableAutoNameExtensionPack
Remove the disableAutoNameExtensionPack feature flag
This commit is contained in:
@@ -707,20 +707,12 @@ export function showQueriesPanel(): boolean {
|
||||
|
||||
const MODEL_SETTING = new Setting("model", ROOT_SETTING);
|
||||
const LLM_GENERATION = new Setting("llmGeneration", MODEL_SETTING);
|
||||
const DISABLE_AUTO_NAME_EXTENSION_PACK = new Setting(
|
||||
"disableAutoNameExtensionPack",
|
||||
MODEL_SETTING,
|
||||
);
|
||||
const EXTENSIONS_DIRECTORY = new Setting("extensionsDirectory", MODEL_SETTING);
|
||||
|
||||
export function showLlmGeneration(): boolean {
|
||||
return !!LLM_GENERATION.getValue<boolean>();
|
||||
}
|
||||
|
||||
export function disableAutoNameExtensionPack(): boolean {
|
||||
return !!DISABLE_AUTO_NAME_EXTENSION_PACK.getValue<boolean>();
|
||||
}
|
||||
|
||||
export function getExtensionsDirectory(languageId: string): string | undefined {
|
||||
return EXTENSIONS_DIRECTORY.getValue<string>({
|
||||
languageId,
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { join } from "path";
|
||||
import { outputFile, pathExists, readFile } from "fs-extra";
|
||||
import { dump as dumpYaml, load as loadYaml } from "js-yaml";
|
||||
import { CancellationToken, Uri, window } from "vscode";
|
||||
import { CodeQLCliServer, QlpacksInfo } from "../codeql-cli/cli";
|
||||
import { Uri } from "vscode";
|
||||
import { CodeQLCliServer } from "../codeql-cli/cli";
|
||||
import { getOnDiskWorkspaceFolders } from "../common/vscode/workspace-folders";
|
||||
import { ProgressCallback } from "../common/vscode/progress";
|
||||
import { DatabaseItem } from "../databases/local-databases";
|
||||
@@ -10,21 +10,13 @@ import { getQlPackPath, QLPACK_FILENAMES } from "../common/ql";
|
||||
import { getErrorMessage } from "../common/helpers-pure";
|
||||
import { ExtensionPack } from "./shared/extension-pack";
|
||||
import { NotificationLogger, showAndLogErrorMessage } from "../common/logging";
|
||||
import {
|
||||
disableAutoNameExtensionPack,
|
||||
getExtensionsDirectory,
|
||||
} from "../config";
|
||||
import { getExtensionsDirectory } from "../config";
|
||||
import {
|
||||
autoNameExtensionPack,
|
||||
ExtensionPackName,
|
||||
formatPackName,
|
||||
parsePackName,
|
||||
validatePackName,
|
||||
} from "./extension-pack-name";
|
||||
import {
|
||||
askForWorkspaceFolder,
|
||||
autoPickExtensionsDirectory,
|
||||
} from "./extensions-workspace-folder";
|
||||
import { autoPickExtensionsDirectory } from "./extensions-workspace-folder";
|
||||
|
||||
const maxStep = 3;
|
||||
|
||||
@@ -33,7 +25,6 @@ export async function pickExtensionPack(
|
||||
databaseItem: Pick<DatabaseItem, "name" | "language">,
|
||||
logger: NotificationLogger,
|
||||
progress: ProgressCallback,
|
||||
token: CancellationToken,
|
||||
): Promise<ExtensionPack | undefined> {
|
||||
progress({
|
||||
message: "Resolving extension packs...",
|
||||
@@ -52,182 +43,14 @@ export async function pickExtensionPack(
|
||||
true,
|
||||
);
|
||||
|
||||
if (!disableAutoNameExtensionPack()) {
|
||||
progress({
|
||||
message: "Creating extension pack...",
|
||||
step: 2,
|
||||
maxStep,
|
||||
});
|
||||
|
||||
return autoCreateExtensionPack(
|
||||
databaseItem.name,
|
||||
databaseItem.language,
|
||||
extensionPacksInfo,
|
||||
logger,
|
||||
);
|
||||
}
|
||||
|
||||
if (Object.keys(extensionPacksInfo).length === 0) {
|
||||
return pickNewExtensionPack(databaseItem, token);
|
||||
}
|
||||
|
||||
const extensionPacks = (
|
||||
await Promise.all(
|
||||
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(
|
||||
", ",
|
||||
)}`,
|
||||
},
|
||||
);
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const path = paths[0];
|
||||
|
||||
let extensionPack: ExtensionPack;
|
||||
try {
|
||||
extensionPack = await readExtensionPack(path, databaseItem.language);
|
||||
} catch (e: unknown) {
|
||||
void showAndLogErrorMessage(
|
||||
logger,
|
||||
`Could not read extension pack ${name}`,
|
||||
{
|
||||
fullMessage: `Could not read extension pack ${name} at ${path}: ${getErrorMessage(
|
||||
e,
|
||||
)}`,
|
||||
},
|
||||
);
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return extensionPack;
|
||||
}),
|
||||
)
|
||||
).filter((info): info is ExtensionPack => info !== undefined);
|
||||
|
||||
const extensionPacksForLanguage = extensionPacks.filter(
|
||||
(pack) =>
|
||||
pack.extensionTargets[`codeql/${databaseItem.language}-all`] !==
|
||||
undefined,
|
||||
);
|
||||
|
||||
const options: Array<{
|
||||
label: string;
|
||||
description: string | undefined;
|
||||
detail: string | undefined;
|
||||
extensionPack: ExtensionPack | null;
|
||||
}> = extensionPacksForLanguage.map((pack) => ({
|
||||
label: pack.name,
|
||||
description: pack.version,
|
||||
detail: pack.path,
|
||||
extensionPack: pack,
|
||||
}));
|
||||
options.push({
|
||||
label: "Create new extension pack",
|
||||
description: undefined,
|
||||
detail: undefined,
|
||||
extensionPack: null,
|
||||
});
|
||||
|
||||
progress({
|
||||
message: "Choosing extension pack...",
|
||||
step: 2,
|
||||
maxStep,
|
||||
});
|
||||
|
||||
const extensionPackOption = await window.showQuickPick(
|
||||
options,
|
||||
{
|
||||
title: "Select extension pack to use",
|
||||
},
|
||||
token,
|
||||
);
|
||||
if (!extensionPackOption) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (!extensionPackOption.extensionPack) {
|
||||
return pickNewExtensionPack(databaseItem, token);
|
||||
}
|
||||
|
||||
return extensionPackOption.extensionPack;
|
||||
}
|
||||
|
||||
async function pickNewExtensionPack(
|
||||
databaseItem: Pick<DatabaseItem, "name" | "language">,
|
||||
token: CancellationToken,
|
||||
): Promise<ExtensionPack | undefined> {
|
||||
const workspaceFolder = await askForWorkspaceFolder();
|
||||
if (!workspaceFolder) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const examplePackName = autoNameExtensionPack(
|
||||
databaseItem.name,
|
||||
databaseItem.language,
|
||||
);
|
||||
|
||||
const name = await window.showInputBox(
|
||||
{
|
||||
title: "Create new extension pack",
|
||||
prompt: "Enter name of extension pack",
|
||||
placeHolder: examplePackName
|
||||
? `e.g. ${formatPackName(examplePackName)}`
|
||||
: "",
|
||||
validateInput: async (value: string): Promise<string | undefined> => {
|
||||
const message = validatePackName(value);
|
||||
if (message) {
|
||||
return message;
|
||||
}
|
||||
|
||||
const packName = parsePackName(value);
|
||||
if (!packName) {
|
||||
return "Invalid pack name";
|
||||
}
|
||||
|
||||
const packPath = join(workspaceFolder.uri.fsPath, packName.name);
|
||||
if (await pathExists(packPath)) {
|
||||
return `A pack already exists at ${packPath}`;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
},
|
||||
},
|
||||
token,
|
||||
);
|
||||
if (!name) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const packName = parsePackName(name);
|
||||
if (!packName) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const packPath = join(workspaceFolder.uri.fsPath, packName.name);
|
||||
|
||||
if (await pathExists(packPath)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return writeExtensionPack(packPath, packName, databaseItem.language);
|
||||
}
|
||||
|
||||
async function autoCreateExtensionPack(
|
||||
name: string,
|
||||
language: string,
|
||||
extensionPacksInfo: QlpacksInfo,
|
||||
logger: NotificationLogger,
|
||||
): Promise<ExtensionPack | undefined> {
|
||||
// Get the `codeQL.model.extensionsDirectory` setting for the language
|
||||
const userExtensionsDirectory = getExtensionsDirectory(language);
|
||||
const userExtensionsDirectory = getExtensionsDirectory(databaseItem.language);
|
||||
|
||||
// If the setting is not set, automatically pick a suitable directory
|
||||
const extensionsDirectory = userExtensionsDirectory
|
||||
@@ -239,11 +62,14 @@ async function autoCreateExtensionPack(
|
||||
}
|
||||
|
||||
// Generate the name of the extension pack
|
||||
const packName = autoNameExtensionPack(name, language);
|
||||
const packName = autoNameExtensionPack(
|
||||
databaseItem.name,
|
||||
databaseItem.language,
|
||||
);
|
||||
if (!packName) {
|
||||
void showAndLogErrorMessage(
|
||||
logger,
|
||||
`Could not automatically name extension pack for database ${name}`,
|
||||
`Could not automatically name extension pack for database ${databaseItem.name}`,
|
||||
);
|
||||
|
||||
return undefined;
|
||||
@@ -259,7 +85,7 @@ async function autoCreateExtensionPack(
|
||||
try {
|
||||
extensionPack = await readExtensionPack(
|
||||
existingExtensionPackPaths[0],
|
||||
language,
|
||||
databaseItem.language,
|
||||
);
|
||||
} catch (e: unknown) {
|
||||
void showAndLogErrorMessage(
|
||||
@@ -309,7 +135,7 @@ async function autoCreateExtensionPack(
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return writeExtensionPack(packPath, packName, language);
|
||||
return writeExtensionPack(packPath, packName, databaseItem.language);
|
||||
}
|
||||
|
||||
async function writeExtensionPack(
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { FileType, Uri, window, workspace, WorkspaceFolder } from "vscode";
|
||||
import { FileType, Uri, workspace, WorkspaceFolder } from "vscode";
|
||||
import { getOnDiskWorkspaceFoldersObjects } from "../common/vscode/workspace-folders";
|
||||
import { extLogger } from "../common/logging/vscode";
|
||||
import { tmpdir } from "../common/files";
|
||||
@@ -200,25 +200,3 @@ export async function autoPickExtensionsDirectory(): Promise<Uri | undefined> {
|
||||
|
||||
return extensionsUri;
|
||||
}
|
||||
|
||||
export async function askForWorkspaceFolder(): Promise<
|
||||
WorkspaceFolder | undefined
|
||||
> {
|
||||
const workspaceFolders = getOnDiskWorkspaceFoldersObjects();
|
||||
const workspaceFolderOptions = workspaceFolders.map((folder) => ({
|
||||
label: folder.name,
|
||||
detail: folder.uri.fsPath,
|
||||
folder,
|
||||
}));
|
||||
|
||||
// We're not using window.showWorkspaceFolderPick because that also includes the database source folders while
|
||||
// we only want to include on-disk workspace folders.
|
||||
const workspaceFolder = await window.showQuickPick(workspaceFolderOptions, {
|
||||
title: "Select workspace folder to create extension pack in",
|
||||
});
|
||||
if (!workspaceFolder) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return workspaceFolder.folder;
|
||||
}
|
||||
|
||||
@@ -101,7 +101,7 @@ export class ModelEditorModule extends DisposableObject {
|
||||
}
|
||||
|
||||
return withProgress(
|
||||
async (progress, token) => {
|
||||
async (progress) => {
|
||||
if (!(await this.cliServer.cliConstraints.supportsQlpacksKind())) {
|
||||
void showAndLogErrorMessage(
|
||||
this.app.logger,
|
||||
@@ -125,7 +125,6 @@ export class ModelEditorModule extends DisposableObject {
|
||||
db,
|
||||
this.app.logger,
|
||||
progress,
|
||||
token,
|
||||
);
|
||||
if (!modelFile) {
|
||||
return;
|
||||
|
||||
@@ -483,7 +483,6 @@ export class ModelEditorView extends AbstractWebview<
|
||||
addedDatabase,
|
||||
this.app.logger,
|
||||
progress,
|
||||
token,
|
||||
);
|
||||
if (!modelFile) {
|
||||
return;
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
import {
|
||||
CancellationTokenSource,
|
||||
ConfigurationScope,
|
||||
QuickPickItem,
|
||||
Uri,
|
||||
window,
|
||||
workspace,
|
||||
WorkspaceConfiguration as VSCodeWorkspaceConfiguration,
|
||||
WorkspaceFolder,
|
||||
@@ -14,8 +11,6 @@ import { join } from "path";
|
||||
import { dir } from "tmp-promise";
|
||||
import { QlpacksInfo } from "../../../../src/codeql-cli/cli";
|
||||
|
||||
import * as config from "../../../../src/config";
|
||||
|
||||
import { pickExtensionPack } from "../../../../src/model-editor/extension-pack-picker";
|
||||
import { ExtensionPack } from "../../../../src/model-editor/shared/extension-pack";
|
||||
import { createMockLogger } from "../../../__mocks__/loggerMock";
|
||||
@@ -23,11 +18,8 @@ import { vscodeGetConfigurationMock } from "../../test-config";
|
||||
|
||||
describe("pickExtensionPack", () => {
|
||||
let tmpDir: string;
|
||||
let extensionPackPath: string;
|
||||
let anotherExtensionPackPath: string;
|
||||
const autoExtensionPackName = "github/vscode-codeql-java";
|
||||
let autoExtensionPackPath: string;
|
||||
let extensionPack: ExtensionPack;
|
||||
let anotherExtensionPack: ExtensionPack;
|
||||
let autoExtensionPack: ExtensionPack;
|
||||
|
||||
let qlPacks: QlpacksInfo;
|
||||
@@ -36,15 +28,7 @@ describe("pickExtensionPack", () => {
|
||||
language: "java",
|
||||
};
|
||||
|
||||
const cancellationTokenSource = new CancellationTokenSource();
|
||||
const token = cancellationTokenSource.token;
|
||||
|
||||
const progress = jest.fn();
|
||||
let showQuickPickSpy: jest.SpiedFunction<typeof window.showQuickPick>;
|
||||
let showInputBoxSpy: jest.SpiedFunction<typeof window.showInputBox>;
|
||||
let disableAutoNameExtensionPackSpy: jest.SpiedFunction<
|
||||
typeof config.disableAutoNameExtensionPack
|
||||
>;
|
||||
let workspaceFoldersSpy: jest.SpyInstance;
|
||||
let additionalPacks: string[];
|
||||
let workspaceFolder: WorkspaceFolder;
|
||||
@@ -59,41 +43,17 @@ describe("pickExtensionPack", () => {
|
||||
).path;
|
||||
|
||||
// Uri.file(...).fsPath normalizes the filenames so we can properly compare them on Windows
|
||||
extensionPackPath = Uri.file(join(tmpDir, "my-extension-pack")).fsPath;
|
||||
anotherExtensionPackPath = Uri.file(
|
||||
join(tmpDir, "another-extension-pack"),
|
||||
).fsPath;
|
||||
autoExtensionPackPath = Uri.file(join(tmpDir, "vscode-codeql-java")).fsPath;
|
||||
|
||||
qlPacks = {
|
||||
"my-extension-pack": [extensionPackPath],
|
||||
"another-extension-pack": [anotherExtensionPackPath],
|
||||
"github/vscode-codeql-java": [autoExtensionPackPath],
|
||||
};
|
||||
|
||||
extensionPack = await createMockExtensionPack(
|
||||
extensionPackPath,
|
||||
"my-extension-pack",
|
||||
);
|
||||
anotherExtensionPack = await createMockExtensionPack(
|
||||
anotherExtensionPackPath,
|
||||
"another-extension-pack",
|
||||
);
|
||||
autoExtensionPack = await createMockExtensionPack(
|
||||
autoExtensionPackPath,
|
||||
"github/vscode-codeql-java",
|
||||
autoExtensionPackName,
|
||||
);
|
||||
|
||||
showQuickPickSpy = jest
|
||||
.spyOn(window, "showQuickPick")
|
||||
.mockRejectedValue(new Error("Unexpected call to showQuickPick"));
|
||||
showInputBoxSpy = jest
|
||||
.spyOn(window, "showInputBox")
|
||||
.mockRejectedValue(new Error("Unexpected call to showInputBox"));
|
||||
disableAutoNameExtensionPackSpy = jest
|
||||
.spyOn(config, "disableAutoNameExtensionPack")
|
||||
.mockReturnValue(true);
|
||||
|
||||
workspaceFolder = {
|
||||
uri: Uri.file(tmpDir),
|
||||
name: "codeql-custom-queries-java",
|
||||
@@ -108,57 +68,7 @@ describe("pickExtensionPack", () => {
|
||||
.mockReturnValue([workspaceFolder]);
|
||||
});
|
||||
|
||||
it("allows choosing an existing extension pack", async () => {
|
||||
const cliServer = mockCliServer(qlPacks);
|
||||
|
||||
showQuickPickSpy.mockResolvedValueOnce({
|
||||
label: "my-extension-pack",
|
||||
extensionPack,
|
||||
} as QuickPickItem);
|
||||
|
||||
expect(
|
||||
await pickExtensionPack(cliServer, databaseItem, logger, progress, token),
|
||||
).toEqual(extensionPack);
|
||||
expect(showQuickPickSpy).toHaveBeenCalledTimes(1);
|
||||
expect(showQuickPickSpy).toHaveBeenCalledWith(
|
||||
[
|
||||
{
|
||||
label: "my-extension-pack",
|
||||
description: "0.0.0",
|
||||
detail: extensionPackPath,
|
||||
extensionPack,
|
||||
},
|
||||
{
|
||||
label: "another-extension-pack",
|
||||
description: "0.0.0",
|
||||
detail: anotherExtensionPackPath,
|
||||
extensionPack: anotherExtensionPack,
|
||||
},
|
||||
{
|
||||
label: "github/vscode-codeql-java",
|
||||
description: "0.0.0",
|
||||
detail: autoExtensionPackPath,
|
||||
extensionPack: autoExtensionPack,
|
||||
},
|
||||
{
|
||||
label: expect.stringMatching(/create/i),
|
||||
extensionPack: null,
|
||||
},
|
||||
],
|
||||
{
|
||||
title: expect.any(String),
|
||||
},
|
||||
token,
|
||||
);
|
||||
expect(cliServer.resolveQlpacks).toHaveBeenCalledTimes(1);
|
||||
expect(cliServer.resolveQlpacks).toHaveBeenCalledWith(
|
||||
additionalPacks,
|
||||
true,
|
||||
);
|
||||
});
|
||||
|
||||
it("automatically selects an extension pack", async () => {
|
||||
disableAutoNameExtensionPackSpy.mockReturnValue(false);
|
||||
it("selects an existing extension pack", async () => {
|
||||
vscodeGetConfigurationMock.mockImplementation(
|
||||
(
|
||||
section?: string,
|
||||
@@ -188,9 +98,8 @@ describe("pickExtensionPack", () => {
|
||||
const cliServer = mockCliServer(qlPacks);
|
||||
|
||||
expect(
|
||||
await pickExtensionPack(cliServer, databaseItem, logger, progress, token),
|
||||
await pickExtensionPack(cliServer, databaseItem, logger, progress),
|
||||
).toEqual(autoExtensionPack);
|
||||
expect(showQuickPickSpy).not.toHaveBeenCalled();
|
||||
expect(cliServer.resolveQlpacks).toHaveBeenCalledTimes(1);
|
||||
expect(cliServer.resolveQlpacks).toHaveBeenCalledWith(
|
||||
additionalPacks,
|
||||
@@ -198,8 +107,7 @@ describe("pickExtensionPack", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("automatically creates an extension pack and selects an extensions directory", async () => {
|
||||
disableAutoNameExtensionPackSpy.mockReturnValue(false);
|
||||
it("creates a new extension pack using default extensions directory", async () => {
|
||||
vscodeGetConfigurationMock.mockImplementation(
|
||||
(
|
||||
section?: string,
|
||||
@@ -265,11 +173,11 @@ describe("pickExtensionPack", () => {
|
||||
const cliServer = mockCliServer({});
|
||||
|
||||
expect(
|
||||
await pickExtensionPack(cliServer, databaseItem, logger, progress, token),
|
||||
await pickExtensionPack(cliServer, databaseItem, logger, progress),
|
||||
).toEqual({
|
||||
path: newPackDir,
|
||||
yamlPath: join(newPackDir, "codeql-pack.yml"),
|
||||
name: "github/vscode-codeql-java",
|
||||
name: autoExtensionPackName,
|
||||
version: "0.0.0",
|
||||
language: "java",
|
||||
extensionTargets: {
|
||||
@@ -277,14 +185,12 @@ describe("pickExtensionPack", () => {
|
||||
},
|
||||
dataExtensions: ["models/**/*.yml"],
|
||||
});
|
||||
expect(showQuickPickSpy).not.toHaveBeenCalled();
|
||||
expect(showInputBoxSpy).not.toHaveBeenCalled();
|
||||
expect(cliServer.resolveQlpacks).toHaveBeenCalled();
|
||||
|
||||
expect(
|
||||
loadYaml(await readFile(join(newPackDir, "codeql-pack.yml"), "utf8")),
|
||||
).toEqual({
|
||||
name: "github/vscode-codeql-java",
|
||||
name: autoExtensionPackName,
|
||||
version: "0.0.0",
|
||||
library: true,
|
||||
extensionTargets: {
|
||||
@@ -294,9 +200,7 @@ describe("pickExtensionPack", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("automatically creates an extension pack when extensions directory is set in config", async () => {
|
||||
disableAutoNameExtensionPackSpy.mockReturnValue(false);
|
||||
|
||||
it("creates a new extension pack when extensions directory is set in config", async () => {
|
||||
const tmpDir = await dir({
|
||||
unsafeCleanup: true,
|
||||
});
|
||||
@@ -337,11 +241,11 @@ describe("pickExtensionPack", () => {
|
||||
const cliServer = mockCliServer({});
|
||||
|
||||
expect(
|
||||
await pickExtensionPack(cliServer, databaseItem, logger, progress, token),
|
||||
await pickExtensionPack(cliServer, databaseItem, logger, progress),
|
||||
).toEqual({
|
||||
path: newPackDir,
|
||||
yamlPath: join(newPackDir, "codeql-pack.yml"),
|
||||
name: "github/vscode-codeql-java",
|
||||
name: autoExtensionPackName,
|
||||
version: "0.0.0",
|
||||
language: "java",
|
||||
extensionTargets: {
|
||||
@@ -349,14 +253,12 @@ describe("pickExtensionPack", () => {
|
||||
},
|
||||
dataExtensions: ["models/**/*.yml"],
|
||||
});
|
||||
expect(showQuickPickSpy).not.toHaveBeenCalled();
|
||||
expect(showInputBoxSpy).not.toHaveBeenCalled();
|
||||
expect(cliServer.resolveQlpacks).toHaveBeenCalled();
|
||||
|
||||
expect(
|
||||
loadYaml(await readFile(join(newPackDir, "codeql-pack.yml"), "utf8")),
|
||||
).toEqual({
|
||||
name: "github/vscode-codeql-java",
|
||||
name: autoExtensionPackName,
|
||||
version: "0.0.0",
|
||||
library: true,
|
||||
extensionTargets: {
|
||||
@@ -366,208 +268,21 @@ describe("pickExtensionPack", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("allows cancelling the prompt", async () => {
|
||||
const cliServer = mockCliServer(qlPacks);
|
||||
|
||||
showQuickPickSpy.mockResolvedValueOnce(undefined);
|
||||
|
||||
expect(
|
||||
await pickExtensionPack(cliServer, databaseItem, logger, progress, token),
|
||||
).toEqual(undefined);
|
||||
expect(cliServer.resolveQlpacks).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("allows user to create an extension pack when there are no extension packs", async () => {
|
||||
const cliServer = mockCliServer({});
|
||||
|
||||
const tmpDir = await dir({
|
||||
unsafeCleanup: true,
|
||||
});
|
||||
|
||||
const newPackDir = join(Uri.file(tmpDir.path).fsPath, "new-extension-pack");
|
||||
|
||||
showQuickPickSpy.mockResolvedValueOnce({
|
||||
label: "codeql-custom-queries-java",
|
||||
folder: {
|
||||
uri: Uri.file(tmpDir.path),
|
||||
name: "codeql-custom-queries-java",
|
||||
index: 0,
|
||||
},
|
||||
} as QuickPickItem);
|
||||
showInputBoxSpy.mockResolvedValueOnce("pack/new-extension-pack");
|
||||
showInputBoxSpy.mockResolvedValue("models/my-model.yml");
|
||||
|
||||
expect(
|
||||
await pickExtensionPack(cliServer, databaseItem, logger, progress, token),
|
||||
).toEqual({
|
||||
path: newPackDir,
|
||||
yamlPath: join(newPackDir, "codeql-pack.yml"),
|
||||
name: "pack/new-extension-pack",
|
||||
version: "0.0.0",
|
||||
language: "java",
|
||||
extensionTargets: {
|
||||
"codeql/java-all": "*",
|
||||
},
|
||||
dataExtensions: ["models/**/*.yml"],
|
||||
});
|
||||
expect(showQuickPickSpy).toHaveBeenCalledTimes(1);
|
||||
expect(showInputBoxSpy).toHaveBeenCalledTimes(1);
|
||||
expect(showInputBoxSpy).toHaveBeenCalledWith(
|
||||
{
|
||||
title: expect.stringMatching(/extension pack/i),
|
||||
prompt: expect.stringMatching(/extension pack/i),
|
||||
placeHolder: expect.stringMatching(/github\/vscode-codeql-java/),
|
||||
validateInput: expect.any(Function),
|
||||
},
|
||||
token,
|
||||
);
|
||||
expect(cliServer.resolveQlpacks).toHaveBeenCalled();
|
||||
|
||||
expect(
|
||||
loadYaml(await readFile(join(newPackDir, "codeql-pack.yml"), "utf8")),
|
||||
).toEqual({
|
||||
name: "pack/new-extension-pack",
|
||||
version: "0.0.0",
|
||||
library: true,
|
||||
extensionTargets: {
|
||||
"codeql/java-all": "*",
|
||||
},
|
||||
dataExtensions: ["models/**/*.yml"],
|
||||
});
|
||||
});
|
||||
|
||||
it("allows user to create an extension pack when there are no extension packs with a different language", async () => {
|
||||
const cliServer = mockCliServer({});
|
||||
|
||||
const tmpDir = await dir({
|
||||
unsafeCleanup: true,
|
||||
});
|
||||
|
||||
const newPackDir = join(Uri.file(tmpDir.path).fsPath, "new-extension-pack");
|
||||
|
||||
showQuickPickSpy.mockResolvedValueOnce({
|
||||
label: "codeql-custom-queries-java",
|
||||
folder: {
|
||||
uri: Uri.file(tmpDir.path),
|
||||
name: "codeql-custom-queries-java",
|
||||
index: 0,
|
||||
},
|
||||
} as QuickPickItem);
|
||||
showInputBoxSpy.mockResolvedValueOnce("pack/new-extension-pack");
|
||||
showInputBoxSpy.mockResolvedValue("models/my-model.yml");
|
||||
|
||||
expect(
|
||||
await pickExtensionPack(
|
||||
cliServer,
|
||||
{
|
||||
...databaseItem,
|
||||
language: "csharp",
|
||||
},
|
||||
logger,
|
||||
progress,
|
||||
token,
|
||||
),
|
||||
).toEqual({
|
||||
path: newPackDir,
|
||||
yamlPath: join(newPackDir, "codeql-pack.yml"),
|
||||
name: "pack/new-extension-pack",
|
||||
version: "0.0.0",
|
||||
language: "csharp",
|
||||
extensionTargets: {
|
||||
"codeql/csharp-all": "*",
|
||||
},
|
||||
dataExtensions: ["models/**/*.yml"],
|
||||
});
|
||||
expect(showQuickPickSpy).toHaveBeenCalledTimes(1);
|
||||
expect(showInputBoxSpy).toHaveBeenCalledTimes(1);
|
||||
expect(showInputBoxSpy).toHaveBeenCalledWith(
|
||||
{
|
||||
title: expect.stringMatching(/extension pack/i),
|
||||
prompt: expect.stringMatching(/extension pack/i),
|
||||
placeHolder: expect.stringMatching(/github\/vscode-codeql-csharp/),
|
||||
validateInput: expect.any(Function),
|
||||
},
|
||||
token,
|
||||
);
|
||||
expect(cliServer.resolveQlpacks).toHaveBeenCalled();
|
||||
|
||||
expect(
|
||||
loadYaml(await readFile(join(newPackDir, "codeql-pack.yml"), "utf8")),
|
||||
).toEqual({
|
||||
name: "pack/new-extension-pack",
|
||||
version: "0.0.0",
|
||||
library: true,
|
||||
extensionTargets: {
|
||||
"codeql/csharp-all": "*",
|
||||
},
|
||||
dataExtensions: ["models/**/*.yml"],
|
||||
});
|
||||
});
|
||||
|
||||
it("allows cancelling the workspace folder selection", async () => {
|
||||
const cliServer = mockCliServer({});
|
||||
|
||||
showQuickPickSpy.mockResolvedValueOnce(undefined);
|
||||
|
||||
expect(
|
||||
await pickExtensionPack(cliServer, databaseItem, logger, progress, token),
|
||||
).toEqual(undefined);
|
||||
expect(showQuickPickSpy).toHaveBeenCalledTimes(1);
|
||||
expect(showInputBoxSpy).toHaveBeenCalledTimes(0);
|
||||
expect(cliServer.resolveQlpacks).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("allows cancelling the extension pack name input", async () => {
|
||||
const cliServer = mockCliServer({});
|
||||
|
||||
showQuickPickSpy.mockResolvedValueOnce({
|
||||
label: "codeql-custom-queries-java",
|
||||
folder: {
|
||||
uri: Uri.file("/a/b/c"),
|
||||
name: "codeql-custom-queries-java",
|
||||
index: 0,
|
||||
},
|
||||
} as QuickPickItem);
|
||||
showInputBoxSpy.mockResolvedValueOnce(undefined);
|
||||
|
||||
expect(
|
||||
await pickExtensionPack(cliServer, databaseItem, logger, progress, token),
|
||||
).toEqual(undefined);
|
||||
expect(showQuickPickSpy).toHaveBeenCalledTimes(1);
|
||||
expect(showInputBoxSpy).toHaveBeenCalledTimes(1);
|
||||
expect(cliServer.resolveQlpacks).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("shows an error when an extension pack resolves to more than 1 location", async () => {
|
||||
const cliServer = mockCliServer({
|
||||
"my-extension-pack": [
|
||||
"github/vscode-codeql-java": [
|
||||
"/a/b/c/my-extension-pack",
|
||||
"/a/b/c/my-extension-pack2",
|
||||
],
|
||||
});
|
||||
|
||||
showQuickPickSpy.mockResolvedValueOnce(undefined);
|
||||
|
||||
expect(
|
||||
await pickExtensionPack(cliServer, databaseItem, logger, progress, token),
|
||||
await pickExtensionPack(cliServer, databaseItem, logger, progress),
|
||||
).toEqual(undefined);
|
||||
expect(logger.showErrorMessage).toHaveBeenCalledTimes(1);
|
||||
expect(logger.showErrorMessage).toHaveBeenCalledWith(
|
||||
expect.stringMatching(/resolves to multiple paths/),
|
||||
);
|
||||
expect(showQuickPickSpy).toHaveBeenCalledTimes(1);
|
||||
expect(showQuickPickSpy).toHaveBeenCalledWith(
|
||||
[
|
||||
{
|
||||
label: expect.stringMatching(/create/i),
|
||||
extensionPack: null,
|
||||
},
|
||||
],
|
||||
{
|
||||
title: "Select extension pack to use",
|
||||
},
|
||||
token,
|
||||
);
|
||||
expect(cliServer.resolveQlpacks).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
@@ -577,31 +292,15 @@ describe("pickExtensionPack", () => {
|
||||
});
|
||||
|
||||
const cliServer = mockCliServer({
|
||||
"my-extension-pack": [tmpDir.path],
|
||||
"github/vscode-codeql-java": [tmpDir.path],
|
||||
});
|
||||
|
||||
showQuickPickSpy.mockResolvedValueOnce(undefined);
|
||||
|
||||
expect(
|
||||
await pickExtensionPack(cliServer, databaseItem, logger, progress, token),
|
||||
await pickExtensionPack(cliServer, databaseItem, logger, progress),
|
||||
).toEqual(undefined);
|
||||
expect(showQuickPickSpy).toHaveBeenCalledTimes(1);
|
||||
expect(showQuickPickSpy).toHaveBeenCalledWith(
|
||||
[
|
||||
{
|
||||
label: expect.stringMatching(/create/i),
|
||||
extensionPack: null,
|
||||
},
|
||||
],
|
||||
{
|
||||
title: "Select extension pack to use",
|
||||
},
|
||||
token,
|
||||
);
|
||||
expect(showInputBoxSpy).not.toHaveBeenCalled();
|
||||
expect(logger.showErrorMessage).toHaveBeenCalledTimes(1);
|
||||
expect(logger.showErrorMessage).toHaveBeenCalledWith(
|
||||
expect.stringMatching(/my-extension-pack/),
|
||||
"Could not read extension pack github/vscode-codeql-java",
|
||||
);
|
||||
expect(cliServer.resolveQlpacks).toHaveBeenCalled();
|
||||
});
|
||||
@@ -612,33 +311,17 @@ describe("pickExtensionPack", () => {
|
||||
});
|
||||
|
||||
const cliServer = mockCliServer({
|
||||
"my-extension-pack": [tmpDir.path],
|
||||
"github/vscode-codeql-java": [tmpDir.path],
|
||||
});
|
||||
|
||||
await outputFile(join(tmpDir.path, "codeql-pack.yml"), dumpYaml("java"));
|
||||
|
||||
showQuickPickSpy.mockResolvedValueOnce(undefined);
|
||||
|
||||
expect(
|
||||
await pickExtensionPack(cliServer, databaseItem, logger, progress, token),
|
||||
await pickExtensionPack(cliServer, databaseItem, logger, progress),
|
||||
).toEqual(undefined);
|
||||
expect(showQuickPickSpy).toHaveBeenCalledTimes(1);
|
||||
expect(showQuickPickSpy).toHaveBeenCalledWith(
|
||||
[
|
||||
{
|
||||
label: expect.stringMatching(/create/i),
|
||||
extensionPack: null,
|
||||
},
|
||||
],
|
||||
{
|
||||
title: "Select extension pack to use",
|
||||
},
|
||||
token,
|
||||
);
|
||||
expect(showInputBoxSpy).not.toHaveBeenCalled();
|
||||
expect(logger.showErrorMessage).toHaveBeenCalledTimes(1);
|
||||
expect(logger.showErrorMessage).toHaveBeenCalledWith(
|
||||
expect.stringMatching(/my-extension-pack/),
|
||||
"Could not read extension pack github/vscode-codeql-java",
|
||||
);
|
||||
expect(cliServer.resolveQlpacks).toHaveBeenCalled();
|
||||
});
|
||||
@@ -649,13 +332,13 @@ describe("pickExtensionPack", () => {
|
||||
});
|
||||
|
||||
const cliServer = mockCliServer({
|
||||
"my-extension-pack": [tmpDir.path],
|
||||
"github/vscode-codeql-java": [tmpDir.path],
|
||||
});
|
||||
|
||||
await outputFile(
|
||||
join(tmpDir.path, "codeql-pack.yml"),
|
||||
dumpYaml({
|
||||
name: "my-extension-pack",
|
||||
name: autoExtensionPackName,
|
||||
version: "0.0.0",
|
||||
library: true,
|
||||
extensionTargets: {
|
||||
@@ -664,28 +347,12 @@ describe("pickExtensionPack", () => {
|
||||
}),
|
||||
);
|
||||
|
||||
showQuickPickSpy.mockResolvedValueOnce(undefined);
|
||||
|
||||
expect(
|
||||
await pickExtensionPack(cliServer, databaseItem, logger, progress, token),
|
||||
await pickExtensionPack(cliServer, databaseItem, logger, progress),
|
||||
).toEqual(undefined);
|
||||
expect(showQuickPickSpy).toHaveBeenCalledTimes(1);
|
||||
expect(showQuickPickSpy).toHaveBeenCalledWith(
|
||||
[
|
||||
{
|
||||
label: expect.stringMatching(/create/i),
|
||||
extensionPack: null,
|
||||
},
|
||||
],
|
||||
{
|
||||
title: "Select extension pack to use",
|
||||
},
|
||||
token,
|
||||
);
|
||||
expect(showInputBoxSpy).not.toHaveBeenCalled();
|
||||
expect(logger.showErrorMessage).toHaveBeenCalledTimes(1);
|
||||
expect(logger.showErrorMessage).toHaveBeenCalledWith(
|
||||
expect.stringMatching(/my-extension-pack/),
|
||||
"Could not read extension pack github/vscode-codeql-java",
|
||||
);
|
||||
expect(cliServer.resolveQlpacks).toHaveBeenCalled();
|
||||
});
|
||||
@@ -696,13 +363,13 @@ describe("pickExtensionPack", () => {
|
||||
});
|
||||
|
||||
const cliServer = mockCliServer({
|
||||
"my-extension-pack": [tmpDir.path],
|
||||
"github/vscode-codeql-java": [tmpDir.path],
|
||||
});
|
||||
|
||||
await outputFile(
|
||||
join(tmpDir.path, "codeql-pack.yml"),
|
||||
dumpYaml({
|
||||
name: "my-extension-pack",
|
||||
name: autoExtensionPackName,
|
||||
version: "0.0.0",
|
||||
library: true,
|
||||
extensionTargets: {
|
||||
@@ -714,94 +381,30 @@ describe("pickExtensionPack", () => {
|
||||
}),
|
||||
);
|
||||
|
||||
showQuickPickSpy.mockResolvedValueOnce(undefined);
|
||||
|
||||
expect(
|
||||
await pickExtensionPack(cliServer, databaseItem, logger, progress, token),
|
||||
await pickExtensionPack(cliServer, databaseItem, logger, progress),
|
||||
).toEqual(undefined);
|
||||
expect(showQuickPickSpy).toHaveBeenCalledTimes(1);
|
||||
expect(showQuickPickSpy).toHaveBeenCalledWith(
|
||||
[
|
||||
{
|
||||
label: expect.stringMatching(/create/i),
|
||||
extensionPack: null,
|
||||
},
|
||||
],
|
||||
{
|
||||
title: "Select extension pack to use",
|
||||
},
|
||||
token,
|
||||
);
|
||||
expect(showInputBoxSpy).not.toHaveBeenCalled();
|
||||
expect(logger.showErrorMessage).toHaveBeenCalledTimes(1);
|
||||
expect(logger.showErrorMessage).toHaveBeenCalledWith(
|
||||
expect.stringMatching(/my-extension-pack/),
|
||||
"Could not read extension pack github/vscode-codeql-java",
|
||||
);
|
||||
expect(cliServer.resolveQlpacks).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("validates the pack name input", async () => {
|
||||
const cliServer = mockCliServer({});
|
||||
|
||||
showQuickPickSpy.mockResolvedValueOnce({
|
||||
label: "a",
|
||||
folder: {
|
||||
uri: Uri.file("/a/b/c"),
|
||||
name: "a",
|
||||
index: 0,
|
||||
},
|
||||
} as QuickPickItem);
|
||||
showInputBoxSpy.mockResolvedValue(undefined);
|
||||
|
||||
expect(
|
||||
await pickExtensionPack(cliServer, databaseItem, logger, progress, token),
|
||||
).toEqual(undefined);
|
||||
|
||||
const validateFile = showInputBoxSpy.mock.calls[0][0]?.validateInput;
|
||||
expect(validateFile).toBeDefined();
|
||||
if (!validateFile) {
|
||||
return;
|
||||
}
|
||||
|
||||
expect(await validateFile("")).toEqual("Pack name must not be empty");
|
||||
expect(await validateFile("a".repeat(129))).toEqual(
|
||||
"Pack name must be no longer than 128 characters",
|
||||
);
|
||||
expect(await validateFile("github/vscode-codeql/extensions")).toEqual(
|
||||
"Invalid package name: a pack name must contain only lowercase ASCII letters, ASCII digits, and hyphens",
|
||||
);
|
||||
expect(await validateFile("VSCODE")).toEqual(
|
||||
"Invalid package name: a pack name must contain a slash to separate the scope from the pack name",
|
||||
);
|
||||
expect(await validateFile("github/")).toEqual(
|
||||
"Invalid package name: a pack name must contain only lowercase ASCII letters, ASCII digits, and hyphens",
|
||||
);
|
||||
expect(await validateFile("github/VSCODE")).toEqual(
|
||||
"Invalid package name: a pack name must contain only lowercase ASCII letters, ASCII digits, and hyphens",
|
||||
);
|
||||
expect(await validateFile("github/vscode-codeql-")).toEqual(
|
||||
"Invalid package name: a pack name must contain only lowercase ASCII letters, ASCII digits, and hyphens",
|
||||
);
|
||||
expect(
|
||||
await validateFile("github/vscode-codeql-extensions"),
|
||||
).toBeUndefined();
|
||||
expect(await validateFile("pack/vscode-codeql-extensions")).toBeUndefined();
|
||||
});
|
||||
|
||||
it("allows the dataExtensions to be a string", async () => {
|
||||
const tmpDir = await dir({
|
||||
unsafeCleanup: true,
|
||||
});
|
||||
|
||||
const cliServer = mockCliServer({
|
||||
"new-extension-pack": [tmpDir.path],
|
||||
"github/vscode-codeql-java": [tmpDir.path],
|
||||
});
|
||||
|
||||
const qlpackPath = join(tmpDir.path, "codeql-pack.yml");
|
||||
await outputFile(
|
||||
qlpackPath,
|
||||
dumpYaml({
|
||||
name: "new-extension-pack",
|
||||
name: autoExtensionPackName,
|
||||
version: "0.0.0",
|
||||
library: true,
|
||||
extensionTargets: {
|
||||
@@ -820,7 +423,7 @@ describe("pickExtensionPack", () => {
|
||||
const extensionPack = {
|
||||
path: tmpDir.path,
|
||||
yamlPath: qlpackPath,
|
||||
name: "new-extension-pack",
|
||||
name: autoExtensionPackName,
|
||||
version: "0.0.0",
|
||||
language: "java",
|
||||
extensionTargets: {
|
||||
@@ -828,75 +431,11 @@ describe("pickExtensionPack", () => {
|
||||
},
|
||||
dataExtensions: ["models/**/*.yml"],
|
||||
};
|
||||
showQuickPickSpy.mockResolvedValueOnce({
|
||||
label: "new-extension-pack",
|
||||
extensionPack,
|
||||
} as QuickPickItem);
|
||||
showQuickPickSpy.mockResolvedValueOnce(undefined);
|
||||
showInputBoxSpy.mockResolvedValue(undefined);
|
||||
|
||||
expect(
|
||||
await pickExtensionPack(cliServer, databaseItem, logger, progress, token),
|
||||
await pickExtensionPack(cliServer, databaseItem, logger, progress),
|
||||
).toEqual(extensionPack);
|
||||
});
|
||||
|
||||
it("only shows extension packs for the database language", async () => {
|
||||
const csharpPack = await createMockExtensionPack(
|
||||
join(tmpDir, "csharp-extensions"),
|
||||
"csharp-extension-pack",
|
||||
{
|
||||
version: "0.5.3",
|
||||
language: "csharp",
|
||||
extensionTargets: {
|
||||
"codeql/csharp-all": "*",
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
const cliServer = mockCliServer({
|
||||
...qlPacks,
|
||||
"csharp-extension-pack": [csharpPack.path],
|
||||
});
|
||||
|
||||
showQuickPickSpy.mockResolvedValueOnce(undefined);
|
||||
|
||||
expect(
|
||||
await pickExtensionPack(
|
||||
cliServer,
|
||||
{
|
||||
...databaseItem,
|
||||
language: "csharp",
|
||||
},
|
||||
logger,
|
||||
progress,
|
||||
token,
|
||||
),
|
||||
).toEqual(undefined);
|
||||
expect(showQuickPickSpy).toHaveBeenCalledTimes(1);
|
||||
expect(showQuickPickSpy).toHaveBeenCalledWith(
|
||||
[
|
||||
{
|
||||
label: "csharp-extension-pack",
|
||||
description: "0.5.3",
|
||||
detail: csharpPack.path,
|
||||
extensionPack: csharpPack,
|
||||
},
|
||||
{
|
||||
label: expect.stringMatching(/create/i),
|
||||
extensionPack: null,
|
||||
},
|
||||
],
|
||||
{
|
||||
title: expect.any(String),
|
||||
},
|
||||
token,
|
||||
);
|
||||
expect(cliServer.resolveQlpacks).toHaveBeenCalledTimes(1);
|
||||
expect(cliServer.resolveQlpacks).toHaveBeenCalledWith(
|
||||
additionalPacks,
|
||||
true,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
function mockCliServer(qlpacks: QlpacksInfo) {
|
||||
|
||||
Reference in New Issue
Block a user