Skip to content

Commit d71f210

Browse files
authored
Merge pull request #2504 from github/koesie10/split-helpers
Split helpers.ts file
2 parents fe21a21 + bfead07 commit d71f210

File tree

20 files changed

+440
-431
lines changed

20 files changed

+440
-431
lines changed

extensions/ql-vscode/src/codeql-cli/cli.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,11 @@ import {
2222
getErrorMessage,
2323
getErrorStack,
2424
} from "../pure/helpers-pure";
25+
import { walkDirectory } from "../pure/files";
2526
import { QueryMetadata, SortDirection } from "../pure/interface-types";
2627
import { BaseLogger, Logger, ProgressReporter } from "../common";
2728
import { CompilationMessage } from "../pure/legacy-messages";
2829
import { sarifParser } from "../common/sarif-parser";
29-
import { walkDirectory } from "../helpers";
3030
import { App } from "../common/app";
3131
import { QueryLanguage } from "../common/query-language";
3232

extensions/ql-vscode/src/common/query-language.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,7 @@ export const dbSchemeToLanguage = {
3535
"ruby.dbscheme": "ruby",
3636
"swift.dbscheme": "swift",
3737
};
38+
39+
export function isQueryLanguage(language: string): language is QueryLanguage {
40+
return Object.values(QueryLanguage).includes(language as QueryLanguage);
41+
}

extensions/ql-vscode/src/data-extensions-editor/external-api-usage-query.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ import { writeFile } from "fs-extra";
44
import { dump as dumpYaml } from "js-yaml";
55
import {
66
getOnDiskWorkspaceFolders,
7-
isQueryLanguage,
87
showAndLogExceptionWithTelemetry,
98
} from "../helpers";
109
import { TeeLogger } from "../common";
10+
import { isQueryLanguage } from "../common/query-language";
1111
import { CancellationToken } from "vscode";
1212
import { CodeQLCliServer } from "../codeql-cli/cli";
1313
import { DatabaseItem } from "../databases/local-databases";

extensions/ql-vscode/src/databases/local-databases-ui.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,13 @@ import {
2929
withProgress,
3030
} from "../common/vscode/progress";
3131
import {
32-
isLikelyDatabaseRoot,
33-
isLikelyDbLanguageFolder,
3432
showAndLogErrorMessage,
3533
showAndLogExceptionWithTelemetry,
3634
} from "../helpers";
35+
import {
36+
isLikelyDatabaseRoot,
37+
isLikelyDbLanguageFolder,
38+
} from "./local-databases/db-contents-heuristics";
3739
import { extLogger } from "../common";
3840
import {
3941
importArchiveDatabase,

extensions/ql-vscode/src/databases/local-databases/database-item-impl.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {
1010
zipArchiveScheme,
1111
} from "../../common/vscode/archive-filesystem-provider";
1212
import { DatabaseItem, PersistedDatabaseItem } from "./database-item";
13-
import { isLikelyDatabaseRoot } from "../../helpers";
13+
import { isLikelyDatabaseRoot } from "./db-contents-heuristics";
1414
import { stat } from "fs-extra";
1515
import { pathsEqual } from "../../pure/files";
1616
import { DatabaseContents } from "./database-contents";

extensions/ql-vscode/src/databases/local-databases/database-manager.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ import { DatabaseItemImpl } from "./database-item-impl";
1616
import {
1717
getFirstWorkspaceFolder,
1818
isFolderAlreadyInWorkspace,
19-
isQueryLanguage,
2019
showAndLogExceptionWithTelemetry,
2120
showNeverAskAgainDialog,
2221
} from "../../helpers";
22+
import { isQueryLanguage } from "../../common/query-language";
2323
import { existsSync } from "fs";
2424
import { QlPackGenerator } from "../../qlpack-generator";
2525
import { asError, getErrorMessage } from "../../pure/helpers-pure";
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { pathExists } from "fs-extra";
2+
import { basename, join } from "path";
3+
import { glob } from "glob";
4+
5+
/**
6+
* The following functions al heuristically determine metadata about databases.
7+
*/
8+
9+
/**
10+
* Heuristically determines if the directory passed in corresponds
11+
* to a database root. A database root is a directory that contains
12+
* a codeql-database.yml or (historically) a .dbinfo file. It also
13+
* contains a folder starting with `db-`.
14+
*/
15+
export async function isLikelyDatabaseRoot(maybeRoot: string) {
16+
const [a, b, c] = await Promise.all([
17+
// databases can have either .dbinfo or codeql-database.yml.
18+
pathExists(join(maybeRoot, ".dbinfo")),
19+
pathExists(join(maybeRoot, "codeql-database.yml")),
20+
21+
// they *must* have a db-{language} folder
22+
glob("db-*/", { cwd: maybeRoot }),
23+
]);
24+
25+
return (a || b) && c.length > 0;
26+
}
27+
28+
/**
29+
* A language folder is any folder starting with `db-` that is itself not a database root.
30+
*/
31+
export async function isLikelyDbLanguageFolder(dbPath: string) {
32+
return (
33+
basename(dbPath).startsWith("db-") && !(await isLikelyDatabaseRoot(dbPath))
34+
);
35+
}
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
import { window } from "vscode";
2+
import { glob } from "glob";
3+
import { basename } from "path";
4+
import { load } from "js-yaml";
5+
import { readFile } from "fs-extra";
6+
import { getQlPackPath } from "../pure/ql";
7+
import { CodeQLCliServer, QlpacksInfo } from "../codeql-cli/cli";
8+
import { extLogger } from "../common";
9+
import { getOnDiskWorkspaceFolders } from "../helpers";
10+
11+
export interface QlPacksForLanguage {
12+
/** The name of the pack containing the dbscheme. */
13+
dbschemePack: string;
14+
/** `true` if `dbschemePack` is a library pack. */
15+
dbschemePackIsLibraryPack: boolean;
16+
/**
17+
* The name of the corresponding standard query pack.
18+
* Only defined if `dbschemePack` is a library pack.
19+
*/
20+
queryPack?: string;
21+
}
22+
23+
interface QlPackWithPath {
24+
packName: string;
25+
packDir: string | undefined;
26+
}
27+
28+
async function findDbschemePack(
29+
packs: QlPackWithPath[],
30+
dbschemePath: string,
31+
): Promise<{ name: string; isLibraryPack: boolean }> {
32+
for (const { packDir, packName } of packs) {
33+
if (packDir !== undefined) {
34+
const qlpackPath = await getQlPackPath(packDir);
35+
36+
if (qlpackPath !== undefined) {
37+
const qlpack = load(await readFile(qlpackPath, "utf8")) as {
38+
dbscheme?: string;
39+
library?: boolean;
40+
};
41+
if (
42+
qlpack.dbscheme !== undefined &&
43+
basename(qlpack.dbscheme) === basename(dbschemePath)
44+
) {
45+
return {
46+
name: packName,
47+
isLibraryPack: qlpack.library === true,
48+
};
49+
}
50+
}
51+
}
52+
}
53+
throw new Error(`Could not find qlpack file for dbscheme ${dbschemePath}`);
54+
}
55+
56+
function findStandardQueryPack(
57+
qlpacks: QlpacksInfo,
58+
dbschemePackName: string,
59+
): string | undefined {
60+
const matches = dbschemePackName.match(/^codeql\/(?<language>[a-z]+)-all$/);
61+
if (matches) {
62+
const queryPackName = `codeql/${matches.groups!.language}-queries`;
63+
if (qlpacks[queryPackName] !== undefined) {
64+
return queryPackName;
65+
}
66+
}
67+
68+
// Either the dbscheme pack didn't look like one where the queries might be in the query pack, or
69+
// no query pack was found in the search path. Either is OK.
70+
return undefined;
71+
}
72+
73+
export async function getQlPackForDbscheme(
74+
cliServer: Pick<CodeQLCliServer, "resolveQlpacks">,
75+
dbschemePath: string,
76+
): Promise<QlPacksForLanguage> {
77+
const qlpacks = await cliServer.resolveQlpacks(getOnDiskWorkspaceFolders());
78+
const packs: QlPackWithPath[] = Object.entries(qlpacks).map(
79+
([packName, dirs]) => {
80+
if (dirs.length < 1) {
81+
void extLogger.log(
82+
`In getQlPackFor ${dbschemePath}, qlpack ${packName} has no directories`,
83+
);
84+
return { packName, packDir: undefined };
85+
}
86+
if (dirs.length > 1) {
87+
void extLogger.log(
88+
`In getQlPackFor ${dbschemePath}, qlpack ${packName} has more than one directory; arbitrarily choosing the first`,
89+
);
90+
}
91+
return {
92+
packName,
93+
packDir: dirs[0],
94+
};
95+
},
96+
);
97+
const dbschemePack = await findDbschemePack(packs, dbschemePath);
98+
const queryPack = dbschemePack.isLibraryPack
99+
? findStandardQueryPack(qlpacks, dbschemePack.name)
100+
: undefined;
101+
return {
102+
dbschemePack: dbschemePack.name,
103+
dbschemePackIsLibraryPack: dbschemePack.isLibraryPack,
104+
queryPack,
105+
};
106+
}
107+
108+
export async function getPrimaryDbscheme(
109+
datasetFolder: string,
110+
): Promise<string> {
111+
const dbschemes = await glob("*.dbscheme", {
112+
cwd: datasetFolder,
113+
});
114+
115+
if (dbschemes.length < 1) {
116+
throw new Error(
117+
`Can't find dbscheme for current database in ${datasetFolder}`,
118+
);
119+
}
120+
121+
dbschemes.sort();
122+
const dbscheme = dbschemes[0];
123+
124+
if (dbschemes.length > 1) {
125+
void window.showErrorMessage(
126+
`Found multiple dbschemes in ${datasetFolder} during quick query; arbitrarily choosing the first, ${dbscheme}, to decide what library to use.`,
127+
);
128+
}
129+
return dbscheme;
130+
}

0 commit comments

Comments
 (0)