From 706c6b8a7aa8030f42586797fac598ad65bc86a2 Mon Sep 17 00:00:00 2001 From: Koen Vlaswinkel Date: Mon, 12 Jun 2023 10:59:42 +0200 Subject: [PATCH 1/6] Move qlpacks helpers to separate file --- extensions/ql-vscode/src/databases/qlpack.ts | 130 ++++++++++++++++++ extensions/ql-vscode/src/helpers.ts | 126 +---------------- .../contextual/query-resolver.ts | 8 +- .../src/local-queries/quick-query.ts | 8 +- .../cli-integration/run-cli.test.ts | 2 +- .../contextual/query-resolver.test.ts | 9 +- 6 files changed, 144 insertions(+), 139 deletions(-) create mode 100644 extensions/ql-vscode/src/databases/qlpack.ts diff --git a/extensions/ql-vscode/src/databases/qlpack.ts b/extensions/ql-vscode/src/databases/qlpack.ts new file mode 100644 index 00000000000..357ef49c4f4 --- /dev/null +++ b/extensions/ql-vscode/src/databases/qlpack.ts @@ -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\/(?[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, + dbschemePath: string, +): Promise { + 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 { + 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; +} diff --git a/extensions/ql-vscode/src/helpers.ts b/extensions/ql-vscode/src/helpers.ts index 780512f0fac..17a58c3dad1 100644 --- a/extensions/ql-vscode/src/helpers.ts +++ b/extensions/ql-vscode/src/helpers.ts @@ -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\/(?[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, - dbschemePath: string, -): Promise { - 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 { - 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. */ diff --git a/extensions/ql-vscode/src/language-support/contextual/query-resolver.ts b/extensions/ql-vscode/src/language-support/contextual/query-resolver.ts index 7cb3f398bc2..d5c79fde7dc 100644 --- a/extensions/ql-vscode/src/language-support/contextual/query-resolver.ts +++ b/extensions/ql-vscode/src/language-support/contextual/query-resolver.ts @@ -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, diff --git a/extensions/ql-vscode/src/local-queries/quick-query.ts b/extensions/ql-vscode/src/local-queries/quick-query.ts index cdf39233006..e62fed2b3ad 100644 --- a/extensions/ql-vscode/src/local-queries/quick-query.ts +++ b/extensions/ql-vscode/src/local-queries/quick-query.ts @@ -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, diff --git a/extensions/ql-vscode/test/vscode-tests/cli-integration/run-cli.test.ts b/extensions/ql-vscode/test/vscode-tests/cli-integration/run-cli.test.ts index 71908530cf3..e52026dc537 100644 --- a/extensions/ql-vscode/test/vscode-tests/cli-integration/run-cli.test.ts +++ b/extensions/ql-vscode/test/vscode-tests/cli-integration/run-cli.test.ts @@ -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 diff --git a/extensions/ql-vscode/test/vscode-tests/no-workspace/language-support/contextual/query-resolver.test.ts b/extensions/ql-vscode/test/vscode-tests/no-workspace/language-support/contextual/query-resolver.test.ts index 54448246e82..52e19460d44 100644 --- a/extensions/ql-vscode/test/vscode-tests/no-workspace/language-support/contextual/query-resolver.test.ts +++ b/extensions/ql-vscode/test/vscode-tests/no-workspace/language-support/contextual/query-resolver.test.ts @@ -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([]); From b0c18b33000332452d36d5ed3764909dae991fd3 Mon Sep 17 00:00:00 2001 From: Koen Vlaswinkel Date: Mon, 12 Jun 2023 11:01:42 +0200 Subject: [PATCH 2/6] Move unused languageToDbScheme --- extensions/ql-vscode/src/helpers.ts | 18 ------------------ .../cli-integration/run-cli.test.ts | 14 ++++++++++---- 2 files changed, 10 insertions(+), 22 deletions(-) diff --git a/extensions/ql-vscode/src/helpers.ts b/extensions/ql-vscode/src/helpers.ts index 17a58c3dad1..c214e345e4e 100644 --- a/extensions/ql-vscode/src/helpers.ts +++ b/extensions/ql-vscode/src/helpers.ts @@ -357,24 +357,6 @@ export async function prepareCodeTour( * The following functions al heuristically determine metadata about databases. */ -/** - * Note that this heuristic is only being used for backwards compatibility with - * CLI versions before the langauge name was introduced to dbInfo. Features - * that do not require backwards compatibility should call - * `cli.CodeQLCliServer.resolveDatabase` and use the first entry in the - * `languages` property. - * - * @see cli.CodeQLCliServer.resolveDatabase - */ - -export const languageToDbScheme = Object.entries(dbSchemeToLanguage).reduce( - (acc, [k, v]) => { - acc[v] = k; - return acc; - }, - {} as { [k: string]: string }, -); - /** * Returns the initial contents for an empty query, based on the language of the selected * databse. diff --git a/extensions/ql-vscode/test/vscode-tests/cli-integration/run-cli.test.ts b/extensions/ql-vscode/test/vscode-tests/cli-integration/run-cli.test.ts index e52026dc537..cf368245aae 100644 --- a/extensions/ql-vscode/test/vscode-tests/cli-integration/run-cli.test.ts +++ b/extensions/ql-vscode/test/vscode-tests/cli-integration/run-cli.test.ts @@ -7,15 +7,13 @@ import { QueryInfoByLanguage, } from "../../../src/codeql-cli/cli"; import { itWithCodeQL } from "../cli"; -import { - getOnDiskWorkspaceFolders, - languageToDbScheme, -} from "../../../src/helpers"; +import { getOnDiskWorkspaceFolders } 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"; +import { dbSchemeToLanguage } from "../../../src/common/query-language"; /** * Perform proper integration tests by running the CLI @@ -26,6 +24,14 @@ describe("Use cli", () => { let logSpy: jest.SpiedFunction; + const languageToDbScheme = Object.entries(dbSchemeToLanguage).reduce( + (acc, [k, v]) => { + acc[v] = k; + return acc; + }, + {} as { [k: string]: string }, + ); + beforeEach(async () => { const extension = await getActivatedExtension(); cli = extension.cliServer; From 754fa675f97ca424e138cccf21761460b1455409 Mon Sep 17 00:00:00 2001 From: Koen Vlaswinkel Date: Mon, 12 Jun 2023 11:07:25 +0200 Subject: [PATCH 3/6] Move db contents heuristics to separate file --- .../src/databases/local-databases-ui.ts | 6 +- .../local-databases/database-item-impl.ts | 2 +- .../local-databases/db-contents-heuristics.ts | 35 +++++++++ extensions/ql-vscode/src/helpers.ts | 33 -------- .../db-contents-heuristics.test.ts | 76 +++++++++++++++++++ .../vscode-tests/no-workspace/helpers.test.ts | 61 --------------- 6 files changed, 116 insertions(+), 97 deletions(-) create mode 100644 extensions/ql-vscode/src/databases/local-databases/db-contents-heuristics.ts create mode 100644 extensions/ql-vscode/test/unit-tests/databases/local-databases/db-contents-heuristics.test.ts diff --git a/extensions/ql-vscode/src/databases/local-databases-ui.ts b/extensions/ql-vscode/src/databases/local-databases-ui.ts index 5fbc23c564a..1177a46899f 100644 --- a/extensions/ql-vscode/src/databases/local-databases-ui.ts +++ b/extensions/ql-vscode/src/databases/local-databases-ui.ts @@ -29,11 +29,13 @@ import { withProgress, } from "../common/vscode/progress"; import { - isLikelyDatabaseRoot, - isLikelyDbLanguageFolder, showAndLogErrorMessage, showAndLogExceptionWithTelemetry, } from "../helpers"; +import { + isLikelyDatabaseRoot, + isLikelyDbLanguageFolder, +} from "./local-databases/db-contents-heuristics"; import { extLogger } from "../common"; import { importArchiveDatabase, diff --git a/extensions/ql-vscode/src/databases/local-databases/database-item-impl.ts b/extensions/ql-vscode/src/databases/local-databases/database-item-impl.ts index 4b206d4991a..1c4adfc7e04 100644 --- a/extensions/ql-vscode/src/databases/local-databases/database-item-impl.ts +++ b/extensions/ql-vscode/src/databases/local-databases/database-item-impl.ts @@ -10,7 +10,7 @@ import { zipArchiveScheme, } from "../../common/vscode/archive-filesystem-provider"; import { DatabaseItem, PersistedDatabaseItem } from "./database-item"; -import { isLikelyDatabaseRoot } from "../../helpers"; +import { isLikelyDatabaseRoot } from "./db-contents-heuristics"; import { stat } from "fs-extra"; import { pathsEqual } from "../../pure/files"; import { DatabaseContents } from "./database-contents"; diff --git a/extensions/ql-vscode/src/databases/local-databases/db-contents-heuristics.ts b/extensions/ql-vscode/src/databases/local-databases/db-contents-heuristics.ts new file mode 100644 index 00000000000..d76ac4e6571 --- /dev/null +++ b/extensions/ql-vscode/src/databases/local-databases/db-contents-heuristics.ts @@ -0,0 +1,35 @@ +import { pathExists } from "fs-extra"; +import { basename, join } from "path"; +import { glob } from "glob"; + +/** + * The following functions al heuristically determine metadata about databases. + */ + +/** + * Heuristically determines if the directory passed in corresponds + * to a database root. A database root is a directory that contains + * a codeql-database.yml or (historically) a .dbinfo file. It also + * contains a folder starting with `db-`. + */ +export async function isLikelyDatabaseRoot(maybeRoot: string) { + const [a, b, c] = await Promise.all([ + // databases can have either .dbinfo or codeql-database.yml. + pathExists(join(maybeRoot, ".dbinfo")), + pathExists(join(maybeRoot, "codeql-database.yml")), + + // they *must* have a db-{language} folder + glob("db-*/", { cwd: maybeRoot }), + ]); + + return (a || b) && c.length > 0; +} + +/** + * A language folder is any folder starting with `db-` that is itself not a database root. + */ +export async function isLikelyDbLanguageFolder(dbPath: string) { + return ( + basename(dbPath).startsWith("db-") && !(await isLikelyDatabaseRoot(dbPath)) + ); +} diff --git a/extensions/ql-vscode/src/helpers.ts b/extensions/ql-vscode/src/helpers.ts index c214e345e4e..6814b94f654 100644 --- a/extensions/ql-vscode/src/helpers.ts +++ b/extensions/ql-vscode/src/helpers.ts @@ -5,7 +5,6 @@ import { writeFile, opendir, } from "fs-extra"; -import { glob } from "glob"; import { join, basename, dirname } from "path"; import { dirSync } from "tmp-promise"; import { Uri, window as Window, workspace, env, WorkspaceFolder } from "vscode"; @@ -353,10 +352,6 @@ export async function prepareCodeTour( } } -/** - * The following functions al heuristically determine metadata about databases. - */ - /** * Returns the initial contents for an empty query, based on the language of the selected * databse. @@ -378,34 +373,6 @@ export function getInitialQueryContents(language: string, dbscheme: string) { return language ? `import ${language}\n\nselect ""` : 'select ""'; } -/** - * Heuristically determines if the directory passed in corresponds - * to a database root. A database root is a directory that contains - * a codeql-database.yml or (historically) a .dbinfo file. It also - * contains a folder starting with `db-`. - */ -export async function isLikelyDatabaseRoot(maybeRoot: string) { - const [a, b, c] = await Promise.all([ - // databases can have either .dbinfo or codeql-database.yml. - pathExists(join(maybeRoot, ".dbinfo")), - pathExists(join(maybeRoot, "codeql-database.yml")), - - // they *must* have a db-{language} folder - glob("db-*/", { cwd: maybeRoot }), - ]); - - return (a || b) && c.length > 0; -} - -/** - * A language folder is any folder starting with `db-` that is itself not a database root. - */ -export async function isLikelyDbLanguageFolder(dbPath: string) { - return ( - basename(dbPath).startsWith("db-") && !(await isLikelyDatabaseRoot(dbPath)) - ); -} - export function isQueryLanguage(language: string): language is QueryLanguage { return Object.values(QueryLanguage).includes(language as QueryLanguage); } diff --git a/extensions/ql-vscode/test/unit-tests/databases/local-databases/db-contents-heuristics.test.ts b/extensions/ql-vscode/test/unit-tests/databases/local-databases/db-contents-heuristics.test.ts new file mode 100644 index 00000000000..11ab977ded0 --- /dev/null +++ b/extensions/ql-vscode/test/unit-tests/databases/local-databases/db-contents-heuristics.test.ts @@ -0,0 +1,76 @@ +import * as tmp from "tmp"; +import { join } from "path"; +import { mkdirSync, writeFileSync } from "fs-extra"; +import { + isLikelyDatabaseRoot, + isLikelyDbLanguageFolder, +} from "../../../../src/databases/local-databases/db-contents-heuristics"; + +describe("isLikelyDatabaseRoot", () => { + let dir: tmp.DirResult; + beforeEach(() => { + dir = tmp.dirSync(); + }); + + afterEach(() => { + dir.removeCallback(); + }); + + it("should likely be a database root: codeql-database.yml", async () => { + const dbFolder = join(dir.name, "db"); + mkdirSync(dbFolder); + mkdirSync(join(dbFolder, "db-python")); + writeFileSync(join(dbFolder, "codeql-database.yml"), "", "utf8"); + + expect(await isLikelyDatabaseRoot(dbFolder)).toBe(true); + }); + + it("should likely be a database root: .dbinfo", async () => { + const dbFolder = join(dir.name, "db"); + mkdirSync(dbFolder); + mkdirSync(join(dbFolder, "db-python")); + writeFileSync(join(dbFolder, ".dbinfo"), "", "utf8"); + + expect(await isLikelyDatabaseRoot(dbFolder)).toBe(true); + }); + + it("should likely NOT be a database root: empty dir", async () => { + const dbFolder = join(dir.name, "db"); + mkdirSync(dbFolder); + mkdirSync(join(dbFolder, "db-python")); + + expect(await isLikelyDatabaseRoot(dbFolder)).toBe(false); + }); + + it("should likely NOT be a database root: no db language folder", async () => { + const dbFolder = join(dir.name, "db"); + mkdirSync(dbFolder); + writeFileSync(join(dbFolder, ".dbinfo"), "", "utf8"); + + expect(await isLikelyDatabaseRoot(dbFolder)).toBe(false); + }); +}); + +describe("isLikelyDbLanguageFolder", () => { + let dir: tmp.DirResult; + beforeEach(() => { + dir = tmp.dirSync(); + }); + + afterEach(() => { + dir.removeCallback(); + }); + + it("should find likely db language folder", async () => { + const dbFolder = join(dir.name, "db-python"); + mkdirSync(dbFolder); + mkdirSync(join(dbFolder, "db-python")); + writeFileSync(join(dbFolder, "codeql-database.yml"), "", "utf8"); + + // not a db folder since there is a db-python folder inside this one + expect(await isLikelyDbLanguageFolder(dbFolder)).toBe(false); + + const nestedDbPythonFolder = join(dbFolder, "db-python"); + expect(await isLikelyDbLanguageFolder(nestedDbPythonFolder)).toBe(true); + }); +}); diff --git a/extensions/ql-vscode/test/vscode-tests/no-workspace/helpers.test.ts b/extensions/ql-vscode/test/vscode-tests/no-workspace/helpers.test.ts index d6afc9cf672..e370cd44180 100644 --- a/extensions/ql-vscode/test/vscode-tests/no-workspace/helpers.test.ts +++ b/extensions/ql-vscode/test/vscode-tests/no-workspace/helpers.test.ts @@ -4,7 +4,6 @@ import * as tmp from "tmp"; import { join } from "path"; import { writeFileSync, - mkdirSync, ensureDirSync, symlinkSync, writeFile, @@ -16,8 +15,6 @@ import { getFirstWorkspaceFolder, getInitialQueryContents, isFolderAlreadyInWorkspace, - isLikelyDatabaseRoot, - isLikelyDbLanguageFolder, prepareCodeTour, showBinaryChoiceDialog, showBinaryChoiceWithUrlDialog, @@ -66,64 +63,6 @@ describe("helpers", () => { }); }); - describe("likely database tests", () => { - let dir: tmp.DirResult; - beforeEach(() => { - dir = tmp.dirSync(); - }); - - afterEach(() => { - dir.removeCallback(); - }); - - it("should likely be a database root: codeql-database.yml", async () => { - const dbFolder = join(dir.name, "db"); - mkdirSync(dbFolder); - mkdirSync(join(dbFolder, "db-python")); - writeFileSync(join(dbFolder, "codeql-database.yml"), "", "utf8"); - - expect(await isLikelyDatabaseRoot(dbFolder)).toBe(true); - }); - - it("should likely be a database root: .dbinfo", async () => { - const dbFolder = join(dir.name, "db"); - mkdirSync(dbFolder); - mkdirSync(join(dbFolder, "db-python")); - writeFileSync(join(dbFolder, ".dbinfo"), "", "utf8"); - - expect(await isLikelyDatabaseRoot(dbFolder)).toBe(true); - }); - - it("should likely NOT be a database root: empty dir", async () => { - const dbFolder = join(dir.name, "db"); - mkdirSync(dbFolder); - mkdirSync(join(dbFolder, "db-python")); - - expect(await isLikelyDatabaseRoot(dbFolder)).toBe(false); - }); - - it("should likely NOT be a database root: no db language folder", async () => { - const dbFolder = join(dir.name, "db"); - mkdirSync(dbFolder); - writeFileSync(join(dbFolder, ".dbinfo"), "", "utf8"); - - expect(await isLikelyDatabaseRoot(dbFolder)).toBe(false); - }); - - it("should find likely db language folder", async () => { - const dbFolder = join(dir.name, "db-python"); - mkdirSync(dbFolder); - mkdirSync(join(dbFolder, "db-python")); - writeFileSync(join(dbFolder, "codeql-database.yml"), "", "utf8"); - - // not a db folder since there is a db-python folder inside this one - expect(await isLikelyDbLanguageFolder(dbFolder)).toBe(false); - - const nestedDbPythonFolder = join(dbFolder, "db-python"); - expect(await isLikelyDbLanguageFolder(nestedDbPythonFolder)).toBe(true); - }); - }); - it("should report stream progress", () => { const progressSpy = jest.fn(); const mockReadable = { From a4e4c67bf2bdf574ab21d83dc92e8d52de0ae8ed Mon Sep 17 00:00:00 2001 From: Koen Vlaswinkel Date: Mon, 12 Jun 2023 11:10:23 +0200 Subject: [PATCH 4/6] Move getInitialQueryContents to separate file --- extensions/ql-vscode/src/helpers.ts | 25 +---------- .../src/local-queries/query-contents.ts | 23 +++++++++++ .../src/local-queries/quick-query.ts | 3 +- .../local-queries/query-contents.test.ts | 41 +++++++++++++++++++ .../vscode-tests/no-workspace/helpers.test.ts | 38 ----------------- 5 files changed, 68 insertions(+), 62 deletions(-) create mode 100644 extensions/ql-vscode/src/local-queries/query-contents.ts create mode 100644 extensions/ql-vscode/test/unit-tests/local-queries/query-contents.test.ts diff --git a/extensions/ql-vscode/src/helpers.ts b/extensions/ql-vscode/src/helpers.ts index 6814b94f654..feafa0211e8 100644 --- a/extensions/ql-vscode/src/helpers.ts +++ b/extensions/ql-vscode/src/helpers.ts @@ -5,7 +5,7 @@ import { writeFile, opendir, } from "fs-extra"; -import { join, basename, dirname } from "path"; +import { join, dirname } from "path"; import { dirSync } from "tmp-promise"; import { Uri, window as Window, workspace, env, WorkspaceFolder } from "vscode"; import { CodeQLCliServer } from "./codeql-cli/cli"; @@ -14,7 +14,7 @@ import { extLogger, OutputChannelLogger } from "./common"; import { QueryMetadata } from "./pure/interface-types"; import { telemetryListener } from "./telemetry"; import { RedactableError } from "./pure/errors"; -import { dbSchemeToLanguage, QueryLanguage } from "./common/query-language"; +import { QueryLanguage } from "./common/query-language"; import { isCodespacesTemplate } from "./config"; import { AppCommandManager } from "./common/commands"; @@ -352,27 +352,6 @@ export async function prepareCodeTour( } } -/** - * Returns the initial contents for an empty query, based on the language of the selected - * databse. - * - * First try to use the given language name. If that doesn't exist, try to infer it based on - * dbscheme. Otherwise return no import statement. - * - * @param language the database language or empty string if unknown - * @param dbscheme path to the dbscheme file - * - * @returns an import and empty select statement appropriate for the selected language - */ -export function getInitialQueryContents(language: string, dbscheme: string) { - if (!language) { - const dbschemeBase = basename(dbscheme) as keyof typeof dbSchemeToLanguage; - language = dbSchemeToLanguage[dbschemeBase]; - } - - return language ? `import ${language}\n\nselect ""` : 'select ""'; -} - export function isQueryLanguage(language: string): language is QueryLanguage { return Object.values(QueryLanguage).includes(language as QueryLanguage); } diff --git a/extensions/ql-vscode/src/local-queries/query-contents.ts b/extensions/ql-vscode/src/local-queries/query-contents.ts new file mode 100644 index 00000000000..762965f70eb --- /dev/null +++ b/extensions/ql-vscode/src/local-queries/query-contents.ts @@ -0,0 +1,23 @@ +import { basename } from "path"; +import { dbSchemeToLanguage } from "../common/query-language"; + +/** + * Returns the initial contents for an empty query, based on the language of the selected + * databse. + * + * First try to use the given language name. If that doesn't exist, try to infer it based on + * dbscheme. Otherwise return no import statement. + * + * @param language the database language or empty string if unknown + * @param dbscheme path to the dbscheme file + * + * @returns an import and empty select statement appropriate for the selected language + */ +export function getInitialQueryContents(language: string, dbscheme: string) { + if (!language) { + const dbschemeBase = basename(dbscheme) as keyof typeof dbSchemeToLanguage; + language = dbSchemeToLanguage[dbschemeBase]; + } + + return language ? `import ${language}\n\nselect ""` : 'select ""'; +} diff --git a/extensions/ql-vscode/src/local-queries/quick-query.ts b/extensions/ql-vscode/src/local-queries/quick-query.ts index e62fed2b3ad..bf52685408a 100644 --- a/extensions/ql-vscode/src/local-queries/quick-query.ts +++ b/extensions/ql-vscode/src/local-queries/quick-query.ts @@ -5,7 +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, showBinaryChoiceDialog } from "../helpers"; +import { showBinaryChoiceDialog } from "../helpers"; +import { getInitialQueryContents } from "./query-contents"; import { getPrimaryDbscheme, getQlPackForDbscheme } from "../databases/qlpack"; import { ProgressCallback, diff --git a/extensions/ql-vscode/test/unit-tests/local-queries/query-contents.test.ts b/extensions/ql-vscode/test/unit-tests/local-queries/query-contents.test.ts new file mode 100644 index 00000000000..e11596ee9ba --- /dev/null +++ b/extensions/ql-vscode/test/unit-tests/local-queries/query-contents.test.ts @@ -0,0 +1,41 @@ +import * as tmp from "tmp"; +import { dump } from "js-yaml"; +import { writeFileSync } from "fs-extra"; +import { join } from "path"; +import { QueryLanguage } from "../../../src/common/query-language"; +import { getInitialQueryContents } from "../../../src/local-queries/query-contents"; + +describe("getInitialQueryContents", () => { + let dir: tmp.DirResult; + let language: QueryLanguage; + + beforeEach(() => { + dir = tmp.dirSync(); + language = QueryLanguage.Cpp; + + const contents = dump({ + primaryLanguage: language, + }); + writeFileSync(join(dir.name, "codeql-database.yml"), contents, "utf8"); + }); + + afterEach(() => { + dir.removeCallback(); + }); + + it("should get initial query contents when language is known", () => { + expect(getInitialQueryContents(language, "hucairz")).toBe( + 'import cpp\n\nselect ""', + ); + }); + + it("should get initial query contents when dbscheme is known", () => { + expect(getInitialQueryContents("", "semmlecode.cpp.dbscheme")).toBe( + 'import cpp\n\nselect ""', + ); + }); + + it("should get initial query contents when nothing is known", () => { + expect(getInitialQueryContents("", "hucairz")).toBe('select ""'); + }); +}); diff --git a/extensions/ql-vscode/test/vscode-tests/no-workspace/helpers.test.ts b/extensions/ql-vscode/test/vscode-tests/no-workspace/helpers.test.ts index e370cd44180..71a4f3daf41 100644 --- a/extensions/ql-vscode/test/vscode-tests/no-workspace/helpers.test.ts +++ b/extensions/ql-vscode/test/vscode-tests/no-workspace/helpers.test.ts @@ -1,5 +1,4 @@ import { Uri, window, workspace, WorkspaceFolder } from "vscode"; -import { dump } from "js-yaml"; import * as tmp from "tmp"; import { join } from "path"; import { @@ -13,7 +12,6 @@ import { DirResult } from "tmp"; import { getFirstWorkspaceFolder, - getInitialQueryContents, isFolderAlreadyInWorkspace, prepareCodeTour, showBinaryChoiceDialog, @@ -23,46 +21,10 @@ import { walkDirectory, } from "../../../src/helpers"; import { reportStreamProgress } from "../../../src/common/vscode/progress"; -import { QueryLanguage } from "../../../src/common/query-language"; import { Setting } from "../../../src/config"; import { createMockCommandManager } from "../../__mocks__/commandsMock"; describe("helpers", () => { - describe("codeql-database.yml tests", () => { - let dir: tmp.DirResult; - let language: QueryLanguage; - - beforeEach(() => { - dir = tmp.dirSync(); - language = QueryLanguage.Cpp; - - const contents = dump({ - primaryLanguage: language, - }); - writeFileSync(join(dir.name, "codeql-database.yml"), contents, "utf8"); - }); - - afterEach(() => { - dir.removeCallback(); - }); - - it("should get initial query contents when language is known", () => { - expect(getInitialQueryContents(language, "hucairz")).toBe( - 'import cpp\n\nselect ""', - ); - }); - - it("should get initial query contents when dbscheme is known", () => { - expect(getInitialQueryContents("", "semmlecode.cpp.dbscheme")).toBe( - 'import cpp\n\nselect ""', - ); - }); - - it("should get initial query contents when nothing is known", () => { - expect(getInitialQueryContents("", "hucairz")).toBe('select ""'); - }); - }); - it("should report stream progress", () => { const progressSpy = jest.fn(); const mockReadable = { From 8c98401efed1ce83db5ae2db9eae25231d04b26f Mon Sep 17 00:00:00 2001 From: Koen Vlaswinkel Date: Mon, 12 Jun 2023 11:11:47 +0200 Subject: [PATCH 5/6] Move isQueryLanguage to query language file --- extensions/ql-vscode/src/common/query-language.ts | 4 ++++ .../src/data-extensions-editor/external-api-usage-query.ts | 2 +- .../src/databases/local-databases/database-manager.ts | 2 +- extensions/ql-vscode/src/helpers.ts | 6 +----- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/extensions/ql-vscode/src/common/query-language.ts b/extensions/ql-vscode/src/common/query-language.ts index acbe090183a..3f3a81024a3 100644 --- a/extensions/ql-vscode/src/common/query-language.ts +++ b/extensions/ql-vscode/src/common/query-language.ts @@ -35,3 +35,7 @@ export const dbSchemeToLanguage = { "ruby.dbscheme": "ruby", "swift.dbscheme": "swift", }; + +export function isQueryLanguage(language: string): language is QueryLanguage { + return Object.values(QueryLanguage).includes(language as QueryLanguage); +} diff --git a/extensions/ql-vscode/src/data-extensions-editor/external-api-usage-query.ts b/extensions/ql-vscode/src/data-extensions-editor/external-api-usage-query.ts index 0070c96ef3c..69d51394773 100644 --- a/extensions/ql-vscode/src/data-extensions-editor/external-api-usage-query.ts +++ b/extensions/ql-vscode/src/data-extensions-editor/external-api-usage-query.ts @@ -4,10 +4,10 @@ import { writeFile } from "fs-extra"; import { dump as dumpYaml } from "js-yaml"; import { getOnDiskWorkspaceFolders, - isQueryLanguage, showAndLogExceptionWithTelemetry, } from "../helpers"; import { TeeLogger } from "../common"; +import { isQueryLanguage } from "../common/query-language"; import { CancellationToken } from "vscode"; import { CodeQLCliServer } from "../codeql-cli/cli"; import { DatabaseItem } from "../databases/local-databases"; diff --git a/extensions/ql-vscode/src/databases/local-databases/database-manager.ts b/extensions/ql-vscode/src/databases/local-databases/database-manager.ts index 587c4b7bb7e..68e2b53191b 100644 --- a/extensions/ql-vscode/src/databases/local-databases/database-manager.ts +++ b/extensions/ql-vscode/src/databases/local-databases/database-manager.ts @@ -16,10 +16,10 @@ import { DatabaseItemImpl } from "./database-item-impl"; import { getFirstWorkspaceFolder, isFolderAlreadyInWorkspace, - isQueryLanguage, showAndLogExceptionWithTelemetry, showNeverAskAgainDialog, } from "../../helpers"; +import { isQueryLanguage } from "../../common/query-language"; import { existsSync } from "fs"; import { QlPackGenerator } from "../../qlpack-generator"; import { asError, getErrorMessage } from "../../pure/helpers-pure"; diff --git a/extensions/ql-vscode/src/helpers.ts b/extensions/ql-vscode/src/helpers.ts index feafa0211e8..bb944ebb5f6 100644 --- a/extensions/ql-vscode/src/helpers.ts +++ b/extensions/ql-vscode/src/helpers.ts @@ -14,7 +14,7 @@ import { extLogger, OutputChannelLogger } from "./common"; import { QueryMetadata } from "./pure/interface-types"; import { telemetryListener } from "./telemetry"; import { RedactableError } from "./pure/errors"; -import { QueryLanguage } from "./common/query-language"; +import { isQueryLanguage, QueryLanguage } from "./common/query-language"; import { isCodespacesTemplate } from "./config"; import { AppCommandManager } from "./common/commands"; @@ -352,10 +352,6 @@ export async function prepareCodeTour( } } -export function isQueryLanguage(language: string): language is QueryLanguage { - return Object.values(QueryLanguage).includes(language as QueryLanguage); -} - /** * Finds the language that a query targets. * If it can't be autodetected, prompt the user to specify the language manually. From bfead0759220f1accb1db501ee493fef10ad698b Mon Sep 17 00:00:00 2001 From: Koen Vlaswinkel Date: Mon, 12 Jun 2023 11:13:57 +0200 Subject: [PATCH 6/6] Move walkDirectory to pure files file --- extensions/ql-vscode/src/codeql-cli/cli.ts | 2 +- extensions/ql-vscode/src/helpers.ts | 31 +------- extensions/ql-vscode/src/pure/files.ts | 25 ++++++- .../test/unit-tests/pure/files.test.ts | 68 +++++++++++++++++ .../vscode-tests/no-workspace/helpers.test.ts | 74 +------------------ .../variant-analysis-history.test.ts | 3 +- 6 files changed, 97 insertions(+), 106 deletions(-) diff --git a/extensions/ql-vscode/src/codeql-cli/cli.ts b/extensions/ql-vscode/src/codeql-cli/cli.ts index 16882bb9faf..b4cd4c67d6d 100644 --- a/extensions/ql-vscode/src/codeql-cli/cli.ts +++ b/extensions/ql-vscode/src/codeql-cli/cli.ts @@ -22,11 +22,11 @@ import { getErrorMessage, getErrorStack, } from "../pure/helpers-pure"; +import { walkDirectory } from "../pure/files"; import { QueryMetadata, SortDirection } from "../pure/interface-types"; import { BaseLogger, Logger, ProgressReporter } from "../common"; import { CompilationMessage } from "../pure/legacy-messages"; import { sarifParser } from "../common/sarif-parser"; -import { walkDirectory } from "../helpers"; import { App } from "../common/app"; import { QueryLanguage } from "../common/query-language"; diff --git a/extensions/ql-vscode/src/helpers.ts b/extensions/ql-vscode/src/helpers.ts index bb944ebb5f6..1891376d75e 100644 --- a/extensions/ql-vscode/src/helpers.ts +++ b/extensions/ql-vscode/src/helpers.ts @@ -1,10 +1,4 @@ -import { - ensureDirSync, - pathExists, - ensureDir, - writeFile, - opendir, -} from "fs-extra"; +import { ensureDirSync, pathExists, ensureDir, writeFile } from "fs-extra"; import { join, dirname } from "path"; import { dirSync } from "tmp-promise"; import { Uri, window as Window, workspace, env, WorkspaceFolder } from "vscode"; @@ -455,29 +449,6 @@ export async function createTimestampFile(storagePath: string) { await writeFile(timestampPath, Date.now().toString(), "utf8"); } -/** - * Recursively walk a directory and return the full path to all files found. - * Symbolic links are ignored. - * - * @param dir the directory to walk - * - * @return An iterator of the full path to all files recursively found in the directory. - */ -export async function* walkDirectory( - dir: string, -): AsyncIterableIterator { - const seenFiles = new Set(); - for await (const d of await opendir(dir)) { - const entry = join(dir, d.name); - seenFiles.add(entry); - if (d.isDirectory()) { - yield* walkDirectory(entry); - } else if (d.isFile()) { - yield entry; - } - } -} - /** * Returns the path of the first folder in the workspace. * This is used to decide where to create skeleton QL packs. diff --git a/extensions/ql-vscode/src/pure/files.ts b/extensions/ql-vscode/src/pure/files.ts index f987bed0a34..5b3d38d0d69 100644 --- a/extensions/ql-vscode/src/pure/files.ts +++ b/extensions/ql-vscode/src/pure/files.ts @@ -1,4 +1,4 @@ -import { pathExists, stat, readdir } from "fs-extra"; +import { pathExists, stat, readdir, opendir } from "fs-extra"; import { join, resolve } from "path"; /** @@ -88,3 +88,26 @@ export async function readDirFullPaths(path: string): Promise { const baseNames = await readdir(path); return baseNames.map((baseName) => join(path, baseName)); } + +/** + * Recursively walk a directory and return the full path to all files found. + * Symbolic links are ignored. + * + * @param dir the directory to walk + * + * @return An iterator of the full path to all files recursively found in the directory. + */ +export async function* walkDirectory( + dir: string, +): AsyncIterableIterator { + const seenFiles = new Set(); + for await (const d of await opendir(dir)) { + const entry = join(dir, d.name); + seenFiles.add(entry); + if (d.isDirectory()) { + yield* walkDirectory(entry); + } else if (d.isFile()) { + yield entry; + } + } +} diff --git a/extensions/ql-vscode/test/unit-tests/pure/files.test.ts b/extensions/ql-vscode/test/unit-tests/pure/files.test.ts index 35adba6605d..0b51ab88cd0 100644 --- a/extensions/ql-vscode/test/unit-tests/pure/files.test.ts +++ b/extensions/ql-vscode/test/unit-tests/pure/files.test.ts @@ -6,7 +6,11 @@ import { getDirectoryNamesInsidePath, pathsEqual, readDirFullPaths, + walkDirectory, } from "../../../src/pure/files"; +import { DirResult } from "tmp"; +import * as tmp from "tmp"; +import { ensureDirSync, symlinkSync, writeFileSync } from "fs-extra"; describe("files", () => { const dataDir = join(__dirname, "../../data"); @@ -299,3 +303,67 @@ describe("containsPath", () => { }, ); }); + +describe("walkDirectory", () => { + let tmpDir: DirResult; + let dir: string; + let dir2: string; + + beforeEach(() => { + tmpDir = tmp.dirSync({ unsafeCleanup: true }); + dir = join(tmpDir.name, "dir"); + ensureDirSync(dir); + dir2 = join(tmpDir.name, "dir2"); + }); + + afterEach(() => { + tmpDir.removeCallback(); + }); + + it("should walk a directory", async () => { + const file1 = join(dir, "file1"); + const file2 = join(dir, "file2"); + const file3 = join(dir, "file3"); + const dir3 = join(dir, "dir3"); + const file4 = join(dir, "file4"); + const file5 = join(dir, "file5"); + const file6 = join(dir, "file6"); + + // These symlinks link back to paths that are already existing, so ignore. + const symLinkFile7 = join(dir, "symlink0"); + const symlinkDir = join(dir2, "symlink1"); + + // some symlinks that point outside of the base dir. + const file8 = join(tmpDir.name, "file8"); + const file9 = join(dir2, "file8"); + const symlinkDir2 = join(dir2, "symlink2"); + const symlinkFile2 = join(dir2, "symlinkFile3"); + + ensureDirSync(dir2); + ensureDirSync(dir3); + + writeFileSync(file1, "file1"); + writeFileSync(file2, "file2"); + writeFileSync(file3, "file3"); + writeFileSync(file4, "file4"); + writeFileSync(file5, "file5"); + writeFileSync(file6, "file6"); + writeFileSync(file8, "file8"); + writeFileSync(file9, "file9"); + + // We don't really need to be testing all of these variants of symlinks, + // but it doesn't hurt, and will help us if we ever do decide to support them. + symlinkSync(file6, symLinkFile7, "file"); + symlinkSync(dir3, symlinkDir, "dir"); + symlinkSync(file8, symlinkFile2, "file"); + symlinkSync(dir2, symlinkDir2, "dir"); + + const files = []; + for await (const file of walkDirectory(dir)) { + files.push(file); + } + + // Only real files should be returned. + expect(files.sort()).toEqual([file1, file2, file3, file4, file5, file6]); + }); +}); diff --git a/extensions/ql-vscode/test/vscode-tests/no-workspace/helpers.test.ts b/extensions/ql-vscode/test/vscode-tests/no-workspace/helpers.test.ts index 71a4f3daf41..c656c16025f 100644 --- a/extensions/ql-vscode/test/vscode-tests/no-workspace/helpers.test.ts +++ b/extensions/ql-vscode/test/vscode-tests/no-workspace/helpers.test.ts @@ -1,14 +1,7 @@ import { Uri, window, workspace, WorkspaceFolder } from "vscode"; import * as tmp from "tmp"; import { join } from "path"; -import { - writeFileSync, - ensureDirSync, - symlinkSync, - writeFile, - mkdir, -} from "fs-extra"; -import { DirResult } from "tmp"; +import { writeFile, mkdir } from "fs-extra"; import { getFirstWorkspaceFolder, @@ -18,7 +11,6 @@ import { showBinaryChoiceWithUrlDialog, showInformationMessageWithAction, showNeverAskAgainDialog, - walkDirectory, } from "../../../src/helpers"; import { reportStreamProgress } from "../../../src/common/vscode/progress"; import { Setting } from "../../../src/config"; @@ -243,70 +235,6 @@ describe("helpers", () => { }); }); -describe("walkDirectory", () => { - let tmpDir: DirResult; - let dir: string; - let dir2: string; - - beforeEach(() => { - tmpDir = tmp.dirSync({ unsafeCleanup: true }); - dir = join(tmpDir.name, "dir"); - ensureDirSync(dir); - dir2 = join(tmpDir.name, "dir2"); - }); - - afterEach(() => { - tmpDir.removeCallback(); - }); - - it("should walk a directory", async () => { - const file1 = join(dir, "file1"); - const file2 = join(dir, "file2"); - const file3 = join(dir, "file3"); - const dir3 = join(dir, "dir3"); - const file4 = join(dir, "file4"); - const file5 = join(dir, "file5"); - const file6 = join(dir, "file6"); - - // These symlinks link back to paths that are already existing, so ignore. - const symLinkFile7 = join(dir, "symlink0"); - const symlinkDir = join(dir2, "symlink1"); - - // some symlinks that point outside of the base dir. - const file8 = join(tmpDir.name, "file8"); - const file9 = join(dir2, "file8"); - const symlinkDir2 = join(dir2, "symlink2"); - const symlinkFile2 = join(dir2, "symlinkFile3"); - - ensureDirSync(dir2); - ensureDirSync(dir3); - - writeFileSync(file1, "file1"); - writeFileSync(file2, "file2"); - writeFileSync(file3, "file3"); - writeFileSync(file4, "file4"); - writeFileSync(file5, "file5"); - writeFileSync(file6, "file6"); - writeFileSync(file8, "file8"); - writeFileSync(file9, "file9"); - - // We don't really need to be testing all of these variants of symlinks, - // but it doesn't hurt, and will help us if we ever do decide to support them. - symlinkSync(file6, symLinkFile7, "file"); - symlinkSync(dir3, symlinkDir, "dir"); - symlinkSync(file8, symlinkFile2, "file"); - symlinkSync(dir2, symlinkDir2, "dir"); - - const files = []; - for await (const file of walkDirectory(dir)) { - files.push(file); - } - - // Only real files should be returned. - expect(files.sort()).toEqual([file1, file2, file3, file4, file5, file6]); - }); -}); - describe("isFolderAlreadyInWorkspace", () => { beforeEach(() => { const folders = [ diff --git a/extensions/ql-vscode/test/vscode-tests/no-workspace/query-history/variant-analysis-history.test.ts b/extensions/ql-vscode/test/vscode-tests/no-workspace/query-history/variant-analysis-history.test.ts index 77d08b25bae..036f1e3a919 100644 --- a/extensions/ql-vscode/test/vscode-tests/no-workspace/query-history/variant-analysis-history.test.ts +++ b/extensions/ql-vscode/test/vscode-tests/no-workspace/query-history/variant-analysis-history.test.ts @@ -10,7 +10,8 @@ import { join } from "path"; import { ExtensionContext, Uri } from "vscode"; import { DatabaseManager } from "../../../../src/databases/local-databases"; -import { tmpDir, walkDirectory } from "../../../../src/helpers"; +import { tmpDir } from "../../../../src/helpers"; +import { walkDirectory } from "../../../../src/pure/files"; import { DisposableBucket } from "../../disposable-bucket"; import { testDisposeHandler } from "../../test-dispose-handler"; import { HistoryItemLabelProvider } from "../../../../src/query-history/history-item-label-provider";