Skip to content

Commit db3550a

Browse files
Merge pull request #3245 from github/robertbrignull/multi-query-published-pack
Add prototype implementation for codeQL.runVariantAnalysisPublishedPack
2 parents a6a7a5c + 91a96da commit db3550a

File tree

3 files changed

+90
-3
lines changed

3 files changed

+90
-3
lines changed

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,16 @@ type GenerateExtensiblePredicateMetadataResult = {
121121
}>;
122122
};
123123

124+
type PackDownloadResult = {
125+
// There are other properties in this object, but they are
126+
// not relevant for its use in the extension, so we omit them.
127+
packs: Array<{
128+
name: string;
129+
version: string;
130+
}>;
131+
packDir: string;
132+
};
133+
124134
/**
125135
* The expected output of `codeql resolve qlref`.
126136
*/
@@ -1383,7 +1393,7 @@ export class CodeQLCliServer implements Disposable {
13831393
* Downloads a specified pack.
13841394
* @param packs The `<package-scope/name[@version]>` of the packs to download.
13851395
*/
1386-
async packDownload(packs: string[]) {
1396+
async packDownload(packs: string[]): Promise<PackDownloadResult> {
13871397
return this.runJsonCodeQlCliCommandWithAuthentication(
13881398
["pack", "download"],
13891399
packs,

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ export async function askForLanguage(
6363
.sort((a, b) => a.label.localeCompare(b.label));
6464

6565
const selectedItem = await window.showQuickPick(items, {
66-
placeHolder: "Select target language for your query",
66+
placeHolder: "Select target query language",
6767
ignoreFocusOut: true,
6868
});
6969
if (!selectedItem) {

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

Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ import type { QueryTreeViewItem } from "../queries-panel/query-tree-view-item";
8787
import { RequestError } from "@octokit/request-error";
8888
import { handleRequestError } from "./custom-errors";
8989
import { createMultiSelectionCommand } from "../common/vscode/selection-commands";
90+
import { askForLanguage } from "../codeql-cli/query-language";
9091

9192
const maxRetryCount = 3;
9293

@@ -214,7 +215,83 @@ export class VariantAnalysisManager
214215
}
215216

216217
private async runVariantAnalysisFromPublishedPack(): Promise<void> {
217-
throw new Error("Command not yet implemented");
218+
return withProgress(async (progress, token) => {
219+
progress({
220+
maxStep: 8,
221+
step: 0,
222+
message: "Determining query language",
223+
});
224+
225+
const language = await askForLanguage(this.cliServer);
226+
227+
progress({
228+
maxStep: 8,
229+
step: 1,
230+
message: "Downloading query pack",
231+
});
232+
233+
const packName = `codeql/${language}-queries`;
234+
const packDownloadResult = await this.cliServer.packDownload([packName]);
235+
const downloadedPack = packDownloadResult.packs[0];
236+
237+
const packDir = join(
238+
packDownloadResult.packDir,
239+
downloadedPack.name,
240+
downloadedPack.version,
241+
);
242+
243+
progress({
244+
maxStep: 8,
245+
step: 2,
246+
message: "Resolving queries in pack",
247+
});
248+
249+
const suitePath = join(
250+
packDir,
251+
"codeql-suites",
252+
`${language}-code-scanning.qls`,
253+
);
254+
const resolvedQueries = await this.cliServer.resolveQueries(suitePath);
255+
256+
const problemQueries =
257+
await this.filterToOnlyProblemQueries(resolvedQueries);
258+
259+
if (problemQueries.length === 0) {
260+
void this.app.logger.showErrorMessage(
261+
`Unable to trigger variant analysis. No problem queries found in published query pack: ${packName}.`,
262+
);
263+
return;
264+
}
265+
266+
await this.runVariantAnalysis(
267+
problemQueries.map((q) => Uri.file(q)),
268+
(p) =>
269+
progress({
270+
...p,
271+
maxStep: p.maxStep + 3,
272+
step: p.step + 3,
273+
}),
274+
token,
275+
);
276+
});
277+
}
278+
279+
private async filterToOnlyProblemQueries(
280+
queries: string[],
281+
): Promise<string[]> {
282+
const problemQueries: string[] = [];
283+
for (const query of queries) {
284+
const queryMetadata = await this.cliServer.resolveMetadata(query);
285+
if (
286+
queryMetadata.kind === "problem" ||
287+
queryMetadata.kind === "path-problem"
288+
) {
289+
problemQueries.push(query);
290+
} else {
291+
void this.app.logger.log(`Skipping non-problem query ${query}`);
292+
}
293+
}
294+
return problemQueries;
218295
}
219296

220297
private async runVariantAnalysisCommand(uri: Uri): Promise<void> {

0 commit comments

Comments
 (0)