Skip to content

Commit e78f7e6

Browse files
authored
Moved logic to get standard pack for variant analysis (github#3384)
1 parent db73cfe commit e78f7e6

File tree

4 files changed

+119
-98
lines changed

4 files changed

+119
-98
lines changed
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import { join } from "path";
2+
import type { BaseLogger } from "../common/logging";
3+
import type { QueryLanguage } from "../common/query-language";
4+
import type { CodeQLCliServer } from "../codeql-cli/cli";
5+
import type { QlPackDetails } from "./ql-pack-details";
6+
import { getQlPackFilePath } from "../common/ql";
7+
8+
export async function resolveCodeScanningQueryPack(
9+
logger: BaseLogger,
10+
cliServer: CodeQLCliServer,
11+
language: QueryLanguage,
12+
): Promise<QlPackDetails> {
13+
// Get pack
14+
void logger.log(`Downloading pack for language: ${language}`);
15+
const packName = `codeql/${language}-queries`;
16+
const packDownloadResult = await cliServer.packDownload([packName]);
17+
const downloadedPack = packDownloadResult.packs[0];
18+
19+
const packDir = join(
20+
packDownloadResult.packDir,
21+
downloadedPack.name,
22+
downloadedPack.version,
23+
);
24+
25+
// Resolve queries
26+
void logger.log(`Resolving queries for pack: ${packName}`);
27+
const suitePath = join(
28+
packDir,
29+
"codeql-suites",
30+
`${language}-code-scanning.qls`,
31+
);
32+
const resolvedQueries = await cliServer.resolveQueries(suitePath);
33+
34+
const problemQueries = await filterToOnlyProblemQueries(
35+
logger,
36+
cliServer,
37+
resolvedQueries,
38+
);
39+
40+
if (problemQueries.length === 0) {
41+
throw Error(
42+
`No problem queries found in published query pack: ${packName}.`,
43+
);
44+
}
45+
46+
// Return pack details
47+
const qlPackFilePath = await getQlPackFilePath(packDir);
48+
49+
const qlPackDetails: QlPackDetails = {
50+
queryFiles: problemQueries,
51+
qlPackRootPath: packDir,
52+
qlPackFilePath,
53+
language,
54+
};
55+
56+
return qlPackDetails;
57+
}
58+
59+
async function filterToOnlyProblemQueries(
60+
logger: BaseLogger,
61+
cliServer: CodeQLCliServer,
62+
queries: string[],
63+
): Promise<string[]> {
64+
const problemQueries: string[] = [];
65+
for (const query of queries) {
66+
const queryMetadata = await cliServer.resolveMetadata(query);
67+
if (
68+
queryMetadata.kind === "problem" ||
69+
queryMetadata.kind === "path-problem"
70+
) {
71+
problemQueries.push(query);
72+
} else {
73+
void logger.log(`Skipping non-problem query ${query}`);
74+
}
75+
}
76+
return problemQueries;
77+
}

extensions/ql-vscode/src/variant-analysis/variant-analysis-manager.ts

Lines changed: 8 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ import { getQlPackFilePath } from "../common/ql";
9494
import { tryGetQueryMetadata } from "../codeql-cli/query-metadata";
9595
import { getOnDiskWorkspaceFolders } from "../common/vscode/workspace-folders";
9696
import { findVariantAnalysisQlPackRoot } from "./ql";
97+
import { resolveCodeScanningQueryPack } from "./code-scanning-pack";
9798

9899
const maxRetryCount = 3;
99100

@@ -219,7 +220,7 @@ export class VariantAnalysisManager
219220
public async runVariantAnalysisFromPublishedPack(): Promise<void> {
220221
return withProgress(async (progress, token) => {
221222
progress({
222-
maxStep: 8,
223+
maxStep: 7,
223224
step: 0,
224225
message: "Determining query language",
225226
});
@@ -230,53 +231,17 @@ export class VariantAnalysisManager
230231
}
231232

232233
progress({
233-
maxStep: 8,
234-
step: 1,
235-
message: "Downloading query pack",
236-
});
237-
238-
const packName = `codeql/${language}-queries`;
239-
const packDownloadResult = await this.cliServer.packDownload([packName]);
240-
const downloadedPack = packDownloadResult.packs[0];
241-
242-
const packDir = join(
243-
packDownloadResult.packDir,
244-
downloadedPack.name,
245-
downloadedPack.version,
246-
);
247-
248-
progress({
249-
maxStep: 8,
234+
maxStep: 7,
250235
step: 2,
251-
message: "Resolving queries in pack",
236+
message: "Downloading query pack and resolving queries",
252237
});
253238

254-
const suitePath = join(
255-
packDir,
256-
"codeql-suites",
257-
`${language}-code-scanning.qls`,
258-
);
259-
const resolvedQueries = await this.cliServer.resolveQueries(suitePath);
260-
261-
const problemQueries =
262-
await this.filterToOnlyProblemQueries(resolvedQueries);
263-
264-
if (problemQueries.length === 0) {
265-
void this.app.logger.showErrorMessage(
266-
`Unable to trigger variant analysis. No problem queries found in published query pack: ${packName}.`,
267-
);
268-
return;
269-
}
270-
271-
const qlPackFilePath = await getQlPackFilePath(packDir);
272-
273239
// Build up details to pass to the functions that run the variant analysis.
274-
const qlPackDetails: QlPackDetails = {
275-
queryFiles: problemQueries,
276-
qlPackRootPath: packDir,
277-
qlPackFilePath,
240+
const qlPackDetails = await resolveCodeScanningQueryPack(
241+
this.app.logger,
242+
this.cliServer,
278243
language,
279-
};
244+
);
280245

281246
await this.runVariantAnalysis(
282247
qlPackDetails,
@@ -291,24 +256,6 @@ export class VariantAnalysisManager
291256
});
292257
}
293258

294-
private async filterToOnlyProblemQueries(
295-
queries: string[],
296-
): Promise<string[]> {
297-
const problemQueries: string[] = [];
298-
for (const query of queries) {
299-
const queryMetadata = await this.cliServer.resolveMetadata(query);
300-
if (
301-
queryMetadata.kind === "problem" ||
302-
queryMetadata.kind === "path-problem"
303-
) {
304-
problemQueries.push(query);
305-
} else {
306-
void this.app.logger.log(`Skipping non-problem query ${query}`);
307-
}
308-
}
309-
return problemQueries;
310-
}
311-
312259
private async runVariantAnalysisCommand(queryFiles: Uri[]): Promise<void> {
313260
if (queryFiles.length === 0) {
314261
throw new Error("Please select a .ql file to run as a variant analysis");
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import type { CodeQLCliServer } from "../../../../src/codeql-cli/cli";
2+
import type { App } from "../../../../src/common/app";
3+
import { QueryLanguage } from "../../../../src/common/query-language";
4+
import { ExtensionApp } from "../../../../src/common/vscode/vscode-app";
5+
import { resolveCodeScanningQueryPack } from "../../../../src/variant-analysis/code-scanning-pack";
6+
import { getActivatedExtension } from "../../global.helper";
7+
8+
describe("Code Scanning pack", () => {
9+
let cli: CodeQLCliServer;
10+
let app: App;
11+
12+
beforeEach(async () => {
13+
const extension = await getActivatedExtension();
14+
cli = extension.cliServer;
15+
app = new ExtensionApp(extension.ctx);
16+
});
17+
18+
it("should download pack for correct language and identify problem queries", async () => {
19+
const pack = await resolveCodeScanningQueryPack(
20+
app.logger,
21+
cli,
22+
QueryLanguage.Javascript,
23+
);
24+
// Should include queries. Just check that at least one known query exists.
25+
// It doesn't particularly matter which query we check for.
26+
expect(
27+
pack.queryFiles.some((q) => q.includes("PostMessageStar.ql")),
28+
).toBeTruthy();
29+
// Should not include non-problem queries.
30+
expect(
31+
pack.queryFiles.some((q) => q.includes("LinesOfCode.ql")),
32+
).toBeFalsy();
33+
});
34+
});

extensions/ql-vscode/test/vscode-tests/cli-integration/variant-analysis/variant-analysis-manager.test.ts

Lines changed: 0 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -477,41 +477,4 @@ describe("Variant Analysis Manager", () => {
477477
}
478478
}
479479
});
480-
481-
describe("runVariantAnalysisFromPublishedPack", () => {
482-
// Temporarily disabling this until we add a way to receive multiple queries in the
483-
// runVariantAnalysis function.
484-
it("should download pack for correct language and identify problem queries", async () => {
485-
const showQuickPickSpy = jest
486-
.spyOn(window, "showQuickPick")
487-
.mockResolvedValue(
488-
mockedQuickPickItem({
489-
label: "JavaScript",
490-
description: "javascript",
491-
language: "javascript",
492-
}),
493-
);
494-
495-
const runVariantAnalysisMock = jest.fn();
496-
variantAnalysisManager.runVariantAnalysis = runVariantAnalysisMock;
497-
498-
await variantAnalysisManager.runVariantAnalysisFromPublishedPack();
499-
500-
expect(showQuickPickSpy).toHaveBeenCalledTimes(1);
501-
expect(runVariantAnalysisMock).toHaveBeenCalledTimes(1);
502-
503-
console.log(runVariantAnalysisMock.mock.calls[0][0]);
504-
const queries: string[] =
505-
runVariantAnalysisMock.mock.calls[0][0].queryFiles;
506-
// Should include queries. Just check that at least one known query exists.
507-
// It doesn't particularly matter which query we check for.
508-
expect(
509-
queries.find((q) => q.includes("PostMessageStar.ql")),
510-
).toBeDefined();
511-
// Should not include non-problem queries.
512-
expect(
513-
queries.find((q) => q.includes("LinesOfCode.ql")),
514-
).not.toBeDefined();
515-
});
516-
});
517480
});

0 commit comments

Comments
 (0)