Move workspace folder functions to separate file

This commit is contained in:
Koen Vlaswinkel
2023-06-12 12:02:45 +02:00
parent bfead07592
commit 0cfbf0cb2a
24 changed files with 169 additions and 162 deletions

View File

@@ -0,0 +1,64 @@
import { dirname, join } from "path";
import { workspace, WorkspaceFolder } from "vscode";
/** Returns true if the specified workspace folder is on the file system. */
export function isWorkspaceFolderOnDisk(
workspaceFolder: WorkspaceFolder,
): boolean {
return workspaceFolder.uri.scheme === "file";
}
/** Gets all active workspace folders that are on the filesystem. */
export function getOnDiskWorkspaceFoldersObjects() {
const workspaceFolders = workspace.workspaceFolders ?? [];
return workspaceFolders.filter(isWorkspaceFolderOnDisk);
}
/** Gets all active workspace folders that are on the filesystem. */
export function getOnDiskWorkspaceFolders() {
return getOnDiskWorkspaceFoldersObjects().map((folder) => folder.uri.fsPath);
}
/** Check if folder is already present in workspace */
export function isFolderAlreadyInWorkspace(folderName: string) {
const workspaceFolders = workspace.workspaceFolders || [];
return !!workspaceFolders.find(
(workspaceFolder) => workspaceFolder.name === folderName,
);
}
/**
* Returns the path of the first folder in the workspace.
* This is used to decide where to create skeleton QL packs.
*
* If the first folder is a QL pack, then the parent folder is returned.
* This is because the vscode-codeql-starter repo contains a ql pack in
* the first folder.
*
* This is a temporary workaround until we can retire the
* vscode-codeql-starter repo.
*/
export function getFirstWorkspaceFolder() {
const workspaceFolders = getOnDiskWorkspaceFolders();
if (!workspaceFolders || workspaceFolders.length === 0) {
throw new Error("No workspace folders found");
}
const firstFolderFsPath = workspaceFolders[0];
// For the vscode-codeql-starter repo, the first folder will be a ql pack
// so we need to get the parent folder
if (
firstFolderFsPath.includes(
join("vscode-codeql-starter", "codeql-custom-queries"),
)
) {
// return the parent folder
return dirname(firstFolderFsPath);
} else {
// if the first folder is not a ql pack, then we are in a normal workspace
return firstFolderFsPath;
}
}

View File

@@ -4,11 +4,11 @@ import { dump as dumpYaml, load as loadYaml } from "js-yaml";
import { minimatch } from "minimatch";
import { CancellationToken, window } from "vscode";
import { CodeQLCliServer } from "../codeql-cli/cli";
import { showAndLogErrorMessage } from "../helpers";
import {
getOnDiskWorkspaceFolders,
getOnDiskWorkspaceFoldersObjects,
showAndLogErrorMessage,
} from "../helpers";
} from "../common/vscode/workspace-folders";
import { ProgressCallback } from "../common/vscode/progress";
import { DatabaseItem } from "../databases/local-databases";
import { getQlPackPath, QLPACK_FILENAMES } from "../pure/ql";

View File

@@ -2,10 +2,8 @@ import { CoreCompletedQuery, QueryRunner } from "../query-server";
import { dir } from "tmp-promise";
import { writeFile } from "fs-extra";
import { dump as dumpYaml } from "js-yaml";
import {
getOnDiskWorkspaceFolders,
showAndLogExceptionWithTelemetry,
} from "../helpers";
import { showAndLogExceptionWithTelemetry } from "../helpers";
import { getOnDiskWorkspaceFolders } from "../common/vscode/workspace-folders";
import { TeeLogger } from "../common";
import { isQueryLanguage } from "../common/query-language";
import { CancellationToken } from "vscode";

View File

@@ -6,10 +6,8 @@ import { CodeQLCliServer } from "../codeql-cli/cli";
import { TeeLogger } from "../common";
import { extensiblePredicateDefinitions } from "./predicates";
import { ProgressCallback } from "../common/vscode/progress";
import {
getOnDiskWorkspaceFolders,
showAndLogExceptionWithTelemetry,
} from "../helpers";
import { showAndLogExceptionWithTelemetry } from "../helpers";
import { getOnDiskWorkspaceFolders } from "../common/vscode/workspace-folders";
import {
ModeledMethodType,
ModeledMethodWithSignature,

View File

@@ -14,11 +14,13 @@ import { join } from "path";
import { FullDatabaseOptions } from "./database-options";
import { DatabaseItemImpl } from "./database-item-impl";
import {
getFirstWorkspaceFolder,
isFolderAlreadyInWorkspace,
showAndLogExceptionWithTelemetry,
showNeverAskAgainDialog,
} from "../../helpers";
import {
getFirstWorkspaceFolder,
isFolderAlreadyInWorkspace,
} from "../../common/vscode/workspace-folders";
import { isQueryLanguage } from "../../common/query-language";
import { existsSync } from "fs";
import { QlPackGenerator } from "../../qlpack-generator";

View File

@@ -6,7 +6,7 @@ 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";
import { getOnDiskWorkspaceFolders } from "../common/vscode/workspace-folders";
export interface QlPacksForLanguage {
/** The name of the pack containing the dbscheme. */

View File

@@ -4,7 +4,8 @@ import {
DebugConfigurationProvider,
WorkspaceFolder,
} from "vscode";
import { getOnDiskWorkspaceFolders, showAndLogErrorMessage } from "../helpers";
import { showAndLogErrorMessage } from "../helpers";
import { getOnDiskWorkspaceFolders } from "../common/vscode/workspace-folders";
import { LocalQueries } from "../local-queries";
import { getQuickEvalContext, validateQueryPath } from "../run-queries-shared";
import * as CodeQLProtocol from "./debug-protocol";

View File

@@ -1,7 +1,7 @@
import { ensureDirSync, pathExists, ensureDir, writeFile } from "fs-extra";
import { join, dirname } from "path";
import { join } from "path";
import { dirSync } from "tmp-promise";
import { Uri, window as Window, workspace, env, WorkspaceFolder } from "vscode";
import { Uri, window as Window, workspace, env } from "vscode";
import { CodeQLCliServer } from "./codeql-cli/cli";
import { UserCancellationException } from "./common/vscode/progress";
import { extLogger, OutputChannelLogger } from "./common";
@@ -11,6 +11,7 @@ import { RedactableError } from "./pure/errors";
import { isQueryLanguage, QueryLanguage } from "./common/query-language";
import { isCodespacesTemplate } from "./config";
import { AppCommandManager } from "./common/commands";
import { getOnDiskWorkspaceFolders } from "./common/vscode/workspace-folders";
// Shared temporary folder for the extension.
export const tmpDir = dirSync({
@@ -232,13 +233,6 @@ export async function showInformationMessageWithAction(
return chosenItem === actionItem;
}
/** Returns true if the specified workspace folder is on the file system. */
export function isWorkspaceFolderOnDisk(
workspaceFolder: WorkspaceFolder,
): boolean {
return workspaceFolder.uri.scheme === "file";
}
/**
* Opens a modal dialog for the user to make a choice between yes/no/never be asked again.
*
@@ -279,26 +273,6 @@ export async function showNeverAskAgainDialog(
return chosenItem?.title;
}
/** Gets all active workspace folders that are on the filesystem. */
export function getOnDiskWorkspaceFoldersObjects() {
const workspaceFolders = workspace.workspaceFolders ?? [];
return workspaceFolders.filter(isWorkspaceFolderOnDisk);
}
/** Gets all active workspace folders that are on the filesystem. */
export function getOnDiskWorkspaceFolders() {
return getOnDiskWorkspaceFoldersObjects().map((folder) => folder.uri.fsPath);
}
/** Check if folder is already present in workspace */
export function isFolderAlreadyInWorkspace(folderName: string) {
const workspaceFolders = workspace.workspaceFolders || [];
return !!workspaceFolders.find(
(workspaceFolder) => workspaceFolder.name === folderName,
);
}
/** Check if the current workspace is the CodeTour and open the workspace folder.
* Without this, we can't run the code tour correctly.
**/
@@ -448,39 +422,3 @@ export async function createTimestampFile(storagePath: string) {
await ensureDir(storagePath);
await writeFile(timestampPath, Date.now().toString(), "utf8");
}
/**
* Returns the path of the first folder in the workspace.
* This is used to decide where to create skeleton QL packs.
*
* If the first folder is a QL pack, then the parent folder is returned.
* This is because the vscode-codeql-starter repo contains a ql pack in
* the first folder.
*
* This is a temporary workaround until we can retire the
* vscode-codeql-starter repo.
*/
export function getFirstWorkspaceFolder() {
const workspaceFolders = getOnDiskWorkspaceFolders();
if (!workspaceFolders || workspaceFolders.length === 0) {
throw new Error("No workspace folders found");
}
const firstFolderFsPath = workspaceFolders[0];
// For the vscode-codeql-starter repo, the first folder will be a ql pack
// so we need to get the parent folder
if (
firstFolderFsPath.includes(
join("vscode-codeql-starter", "codeql-custom-queries"),
)
) {
// return the parent folder
return dirname(firstFolderFsPath);
} else {
// if the first folder is not a ql pack, then we are in a normal workspace
return firstFolderFsPath;
}
}

View File

@@ -3,10 +3,8 @@ import { dump } from "js-yaml";
import { file } from "tmp-promise";
import { basename, dirname, resolve } from "path";
import {
getOnDiskWorkspaceFolders,
showAndLogExceptionWithTelemetry,
} from "../../helpers";
import { showAndLogExceptionWithTelemetry } from "../../helpers";
import { getOnDiskWorkspaceFolders } from "../../common/vscode/workspace-folders";
import {
getPrimaryDbscheme,
getQlPackForDbscheme,

View File

@@ -19,11 +19,11 @@ import { basename } from "path";
import {
createTimestampFile,
findLanguage,
getOnDiskWorkspaceFolders,
showAndLogErrorMessage,
showAndLogWarningMessage,
showBinaryChoiceDialog,
} from "../helpers";
import { getOnDiskWorkspaceFolders } from "../common/vscode/workspace-folders";
import { displayQuickQuery } from "./quick-query";
import { CoreCompletedQuery, QueryRunner } from "../query-server";
import { QueryHistoryManager } from "../query-history/query-history-manager";

View File

@@ -1,9 +1,9 @@
import { CodeQLCliServer } from "../codeql-cli/cli";
import {
getOnDiskWorkspaceFolders,
showAndLogExceptionWithTelemetry,
showAndLogInformationMessage,
} from "../helpers";
import { getOnDiskWorkspaceFolders } from "../common/vscode/workspace-folders";
import { QuickPickItem, window } from "vscode";
import {
ProgressCallback,

View File

@@ -5,7 +5,7 @@ import { Event, RelativePattern, Uri, WorkspaceFolder } from "vscode";
import { MultiFileSystemWatcher } from "../common/vscode/multi-file-system-watcher";
import { App } from "../common/app";
import { FileTreeDirectory, FileTreeLeaf } from "../common/file-tree-nodes";
import { getOnDiskWorkspaceFoldersObjects } from "../helpers";
import { getOnDiskWorkspaceFoldersObjects } from "../common/vscode/workspace-folders";
import { AppEventEmitter } from "../common/events";
import { QueryDiscoverer } from "./query-tree-data-provider";
import { extLogger } from "../common";

View File

@@ -1,9 +1,6 @@
import * as vscode from "vscode";
import {
getOnDiskWorkspaceFolders,
showAndLogExceptionWithTelemetry,
tmpDir,
} from "../../helpers";
import { showAndLogExceptionWithTelemetry, tmpDir } from "../../helpers";
import { getOnDiskWorkspaceFolders } from "../../common/vscode/workspace-folders";
import {
ProgressCallback,
UserCancellationException,

View File

@@ -16,7 +16,7 @@ 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 "../helpers";
import { getOnDiskWorkspaceFolders } from "../common/vscode/workspace-folders";
import { CodeQLCliServer } from "../codeql-cli/cli";
import { Logger } from "../common";
import { QueryOutputDir } from "../run-queries-shared";

View File

@@ -23,7 +23,7 @@ import { BaseLogger, LogOptions } from "../common";
import { TestRunner } from "./test-runner";
import { TestManagerBase } from "./test-manager-base";
import { App } from "../common/app";
import { isWorkspaceFolderOnDisk } from "../helpers";
import { isWorkspaceFolderOnDisk } from "../common/vscode/workspace-folders";
import {
FileTreeDirectory,
FileTreeLeaf,

View File

@@ -2,10 +2,10 @@ import { CancellationToken, Uri } from "vscode";
import { CodeQLCliServer, TestCompleted } from "../codeql-cli/cli";
import { DatabaseItem, DatabaseManager } from "../databases/local-databases";
import {
getOnDiskWorkspaceFolders,
showAndLogExceptionWithTelemetry,
showAndLogWarningMessage,
} from "../helpers";
import { getOnDiskWorkspaceFolders } from "../common/vscode/workspace-folders";
import { asError, getErrorMessage } from "../pure/helpers-pure";
import { redactableError } from "../pure/errors";
import { access } from "fs-extra";

View File

@@ -4,11 +4,11 @@ import { CodeQLCliServer } from "./codeql-cli/cli";
import { OutputChannelLogger } from "./common";
import { Credentials } from "./common/authentication";
import { QueryLanguage } from "./common/query-language";
import { askForLanguage } from "./helpers";
import {
askForLanguage,
getFirstWorkspaceFolder,
isFolderAlreadyInWorkspace,
} from "./helpers";
} from "./common/vscode/workspace-folders";
import { getErrorMessage } from "./pure/helpers-pure";
import { QlPackGenerator } from "./qlpack-generator";
import { DatabaseItem, DatabaseManager } from "./databases/local-databases";

View File

@@ -6,10 +6,10 @@ import { dir, tmpName } from "tmp-promise";
import {
askForLanguage,
findLanguage,
getOnDiskWorkspaceFolders,
tryGetQueryMetadata,
tmpDir,
} from "../helpers";
import { getOnDiskWorkspaceFolders } from "../common/vscode/workspace-folders";
import { Credentials } from "../common/authentication";
import * as cli from "../codeql-cli/cli";
import { extLogger } from "../common";

View File

@@ -20,7 +20,7 @@ import { join } from "path";
import { writeFile } from "fs-extra";
import { expect } from "@jest/globals";
import { AppCommandManager } from "../../../../src/common/commands";
import { getOnDiskWorkspaceFolders } from "../../../../src/helpers";
import { getOnDiskWorkspaceFolders } from "../../../../src/common/vscode/workspace-folders";
type Resolver<T> = (value: T) => void;

View File

@@ -7,7 +7,7 @@ import {
QueryInfoByLanguage,
} from "../../../src/codeql-cli/cli";
import { itWithCodeQL } from "../cli";
import { getOnDiskWorkspaceFolders } from "../../../src/helpers";
import { getOnDiskWorkspaceFolders } from "../../../src/common/vscode/workspace-folders";
import { KeyType, resolveQueries } from "../../../src/language-support";
import { faker } from "@faker-js/faker";
import { getActivatedExtension } from "../global.helper";

View File

@@ -8,7 +8,7 @@ import * as tmp from "tmp";
import { TextDocument, window, workspace, WorkspaceFolder } from "vscode";
import { extLogger } from "../../../src/common";
import { QlPackGenerator } from "../../../src/qlpack-generator";
import * as helpers from "../../../src/helpers";
import * as workspaceFolders from "../../../src/common/vscode/workspace-folders";
import { createFileSync, ensureDirSync, removeSync } from "fs-extra";
import { join } from "path";
import { CancellationTokenSource } from "vscode-jsonrpc";
@@ -139,7 +139,9 @@ describe("SkeletonQueryWizard", () => {
describe("if QL pack doesn't exist", () => {
beforeEach(() => {
jest.spyOn(helpers, "isFolderAlreadyInWorkspace").mockReturnValue(false);
jest
.spyOn(workspaceFolders, "isFolderAlreadyInWorkspace")
.mockReturnValue(false);
});
it("should try to create a new QL pack based on the language", async () => {
await wizard.execute();
@@ -166,7 +168,9 @@ describe("SkeletonQueryWizard", () => {
describe("if QL pack exists", () => {
beforeEach(async () => {
jest.spyOn(helpers, "isFolderAlreadyInWorkspace").mockReturnValue(true);
jest
.spyOn(workspaceFolders, "isFolderAlreadyInWorkspace")
.mockReturnValue(true);
// create a skeleton codeql-custom-queries-${language} folder
// with an example QL file inside

View File

@@ -0,0 +1,63 @@
import { workspace, WorkspaceFolder } from "vscode";
import { join } from "path";
import {
getFirstWorkspaceFolder,
isFolderAlreadyInWorkspace,
} from "../../../../../src/common/vscode/workspace-folders";
describe("isFolderAlreadyInWorkspace", () => {
beforeEach(() => {
const folders = [
{ name: "/first/path" },
{ name: "/second/path" },
] as WorkspaceFolder[];
jest.spyOn(workspace, "workspaceFolders", "get").mockReturnValue(folders);
});
it("should return true if the folder is already in the workspace", () => {
expect(isFolderAlreadyInWorkspace("/first/path")).toBe(true);
});
it("should return false if the folder is not in the workspace", () => {
expect(isFolderAlreadyInWorkspace("/third/path")).toBe(false);
});
});
describe("getFirstWorkspaceFolder", () => {
it("should return the first workspace folder", async () => {
jest.spyOn(workspace, "workspaceFolders", "get").mockReturnValue([
{
name: "codespaces-codeql",
uri: { fsPath: "codespaces-codeql", scheme: "file" },
},
] as WorkspaceFolder[]);
expect(getFirstWorkspaceFolder()).toEqual("codespaces-codeql");
});
describe("if user is in vscode-codeql-starter workspace", () => {
it("should set storage path to parent folder", async () => {
jest.spyOn(workspace, "workspaceFolders", "get").mockReturnValue([
{
name: "codeql-custom-queries-cpp",
uri: {
fsPath: join("vscode-codeql-starter", "codeql-custom-queries-cpp"),
scheme: "file",
},
},
{
name: "codeql-custom-queries-csharp",
uri: {
fsPath: join(
"vscode-codeql-starter",
"codeql-custom-queries-csharp",
),
scheme: "file",
},
},
] as WorkspaceFolder[]);
expect(getFirstWorkspaceFolder()).toEqual("vscode-codeql-starter");
});
});
});

View File

@@ -4,8 +4,6 @@ import { join } from "path";
import { writeFile, mkdir } from "fs-extra";
import {
getFirstWorkspaceFolder,
isFolderAlreadyInWorkspace,
prepareCodeTour,
showBinaryChoiceDialog,
showBinaryChoiceWithUrlDialog,
@@ -235,24 +233,6 @@ describe("helpers", () => {
});
});
describe("isFolderAlreadyInWorkspace", () => {
beforeEach(() => {
const folders = [
{ name: "/first/path" },
{ name: "/second/path" },
] as WorkspaceFolder[];
jest.spyOn(workspace, "workspaceFolders", "get").mockReturnValue(folders);
});
it("should return true if the folder is already in the workspace", () => {
expect(isFolderAlreadyInWorkspace("/first/path")).toBe(true);
});
it("should return false if the folder is not in the workspace", () => {
expect(isFolderAlreadyInWorkspace("/third/path")).toBe(false);
});
});
describe("prepareCodeTour", () => {
let dir: tmp.DirResult;
let showInformationMessageSpy: jest.SpiedFunction<
@@ -354,42 +334,3 @@ describe("prepareCodeTour", () => {
});
});
});
describe("getFirstWorkspaceFolder", () => {
it("should return the first workspace folder", async () => {
jest.spyOn(workspace, "workspaceFolders", "get").mockReturnValue([
{
name: "codespaces-codeql",
uri: { fsPath: "codespaces-codeql", scheme: "file" },
},
] as WorkspaceFolder[]);
expect(getFirstWorkspaceFolder()).toEqual("codespaces-codeql");
});
describe("if user is in vscode-codeql-starter workspace", () => {
it("should set storage path to parent folder", async () => {
jest.spyOn(workspace, "workspaceFolders", "get").mockReturnValue([
{
name: "codeql-custom-queries-cpp",
uri: {
fsPath: join("vscode-codeql-starter", "codeql-custom-queries-cpp"),
scheme: "file",
},
},
{
name: "codeql-custom-queries-csharp",
uri: {
fsPath: join(
"vscode-codeql-starter",
"codeql-custom-queries-csharp",
),
scheme: "file",
},
},
] as WorkspaceFolder[]);
expect(getFirstWorkspaceFolder()).toEqual("vscode-codeql-starter");
});
});
});

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 workspaceFolders from "../../../../../src/common/vscode/workspace-folders";
import * as qlpack from "../../../../../src/databases/qlpack";
import {
KeyType,
@@ -38,7 +39,9 @@ describe("queryResolver", () => {
.spyOn(qlpack, "getPrimaryDbscheme")
.mockResolvedValue("primaryDbscheme");
jest.spyOn(helpers, "getOnDiskWorkspaceFolders").mockReturnValue([]);
jest
.spyOn(workspaceFolders, "getOnDiskWorkspaceFolders")
.mockReturnValue([]);
jest.spyOn(helpers, "showAndLogErrorMessage").mockResolvedValue(undefined);
});