Skip to content

Commit 1764151

Browse files
committed
Change automodel queries to use shared methods.
1 parent 82c40c6 commit 1764151

1 file changed

Lines changed: 83 additions & 130 deletions

File tree

extensions/ql-vscode/src/data-extensions-editor/auto-model-codeml-queries.ts

Lines changed: 83 additions & 130 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,21 @@
11
import { CodeQLCliServer, SourceInfo } from "../codeql-cli/cli";
2-
import { QueryRunner } from "../query-server";
2+
import { CoreCompletedQuery, QueryRunner } from "../query-server";
33
import { DatabaseItem } from "../databases/local-databases";
44
import { ProgressCallback } from "../common/vscode/progress";
55
import * as Sarif from "sarif";
66
import { qlpackOfDatabase, resolveQueries } from "../local-queries";
7-
import { extLogger } from "../common/logging/vscode";
87
import { Mode } from "./shared/mode";
9-
import { QlPacksForLanguage } from "../databases/qlpack";
10-
import { createLockFileForStandardQuery } from "../local-queries/standard-queries";
11-
import { CancellationToken, CancellationTokenSource } from "vscode";
128
import { getOnDiskWorkspaceFolders } from "../common/vscode/workspace-folders";
13-
import { showAndLogExceptionWithTelemetry, TeeLogger } from "../common/logging";
14-
import { QueryResultType } from "../query-server/new-messages";
15-
import { telemetryListener } from "../common/vscode/telemetry";
16-
import { redactableError } from "../common/errors";
179
import { interpretResultsSarif } from "../query-results";
1810
import { join } from "path";
1911
import { assertNever } from "../common/helpers-pure";
2012
import { dir } from "tmp-promise";
2113
import { writeFile, outputFile } from "fs-extra";
2214
import { dump as dumpYaml } from "js-yaml";
2315
import { MethodSignature } from "./external-api-usage";
16+
import { runQuery } from "../local-queries/run-query";
17+
import { QueryMetadata } from "../common/interface-types";
18+
import { CancellationTokenSource } from "vscode";
2419

2520
function modeTag(mode: Mode): string {
2621
switch (mode) {
@@ -59,22 +54,13 @@ export async function runAutoModelQueries({
5954
progress,
6055
cancellationTokenSource,
6156
}: AutoModelQueriesOptions): Promise<AutoModelQueriesResult | undefined> {
62-
const qlpack = await qlpackOfDatabase(cliServer, databaseItem);
63-
64-
// CodeQL needs to have access to the database to be able to retrieve the
65-
// snippets from it. The source location prefix is used to determine the
66-
// base path of the database.
67-
const sourceLocationPrefix = await databaseItem.getSourceLocationPrefix(
57+
// First, resolve the query that we want to run.
58+
const queryPath = await resolveAutomodelQueries(
6859
cliServer,
60+
databaseItem,
61+
"candidates",
62+
mode,
6963
);
70-
const sourceArchiveUri = databaseItem.sourceArchive;
71-
const sourceInfo =
72-
sourceArchiveUri === undefined
73-
? undefined
74-
: {
75-
sourceArchive: sourceArchiveUri.fsPath,
76-
sourceLocationPrefix,
77-
};
7864

7965
// Generate a pack containing the candidate filters
8066
const filterPackDir = await generateCandidateFilterPack(
@@ -87,30 +73,89 @@ export async function runAutoModelQueries({
8773
await cliServer.resolveQlpacks(additionalPacks, true),
8874
);
8975

90-
const candidates = await runAutoModelQuery({
91-
mode,
92-
queryTag: "candidates",
76+
// Run the actual query
77+
const completedQuery = await runQuery({
9378
cliServer,
9479
queryRunner,
9580
databaseItem,
96-
qlpack,
97-
sourceInfo,
81+
queryPath,
82+
queryStorageDir,
9883
additionalPacks,
9984
extensionPacks,
100-
queryStorageDir,
10185
progress,
10286
token: cancellationTokenSource.token,
10387
});
10488

105-
if (!candidates) {
89+
if (!completedQuery) {
10690
return undefined;
10791
}
10892

93+
// Get metadata for the query. This is required to interpret the results. We already know the kind is problem
94+
// (because of the constraint in resolveQueries), so we don't need any more checks on the metadata.
95+
const metadata = await cliServer.resolveMetadata(queryPath);
96+
97+
// CodeQL needs to have access to the database to be able to retrieve the
98+
// snippets from it. The source location prefix is used to determine the
99+
// base path of the database.
100+
const sourceLocationPrefix = await databaseItem.getSourceLocationPrefix(
101+
cliServer,
102+
);
103+
const sourceArchiveUri = databaseItem.sourceArchive;
104+
const sourceInfo =
105+
sourceArchiveUri === undefined
106+
? undefined
107+
: {
108+
sourceArchive: sourceArchiveUri.fsPath,
109+
sourceLocationPrefix,
110+
};
111+
112+
const candidates = await interpretAutomodelResults(
113+
cliServer,
114+
completedQuery,
115+
metadata,
116+
sourceInfo,
117+
);
118+
109119
return {
110120
candidates,
111121
};
112122
}
113123

124+
async function resolveAutomodelQueries(
125+
cliServer: CodeQLCliServer,
126+
databaseItem: DatabaseItem,
127+
queryTag: string,
128+
mode: Mode,
129+
): Promise<string> {
130+
const qlpack = await qlpackOfDatabase(cliServer, databaseItem);
131+
132+
// First, resolve the query that we want to run.
133+
// All queries are tagged like this:
134+
// internal extract automodel <mode> <queryTag>
135+
// Example: internal extract automodel framework-mode candidates
136+
const queries = await resolveQueries(
137+
cliServer,
138+
qlpack,
139+
`Extract automodel ${queryTag}`,
140+
{
141+
kind: "problem",
142+
"tags contain all": ["automodel", modeTag(mode), ...queryTag.split(" ")],
143+
},
144+
);
145+
if (queries.length > 1) {
146+
throw new Error(
147+
`Found multiple auto model queries for ${mode} ${queryTag}. Can't continue`,
148+
);
149+
}
150+
if (queries.length === 0) {
151+
throw new Error(
152+
`Did not found any auto model queries for ${mode} ${queryTag}. Can't continue`,
153+
);
154+
}
155+
156+
return queries[0];
157+
}
158+
114159
/**
115160
* generateCandidateFilterPack will create a temporary extension pack.
116161
* This pack will contain a filter that will restrict the automodel queries
@@ -167,107 +212,15 @@ export async function generateCandidateFilterPack(
167212
return packDir;
168213
}
169214

170-
type AutoModelQueryOptions = {
171-
queryTag: string;
172-
mode: Mode;
173-
cliServer: CodeQLCliServer;
174-
queryRunner: QueryRunner;
175-
databaseItem: DatabaseItem;
176-
qlpack: QlPacksForLanguage;
177-
sourceInfo: SourceInfo | undefined;
178-
additionalPacks: string[];
179-
extensionPacks: string[];
180-
queryStorageDir: string;
181-
182-
progress: ProgressCallback;
183-
token: CancellationToken;
184-
};
185-
186-
async function runAutoModelQuery({
187-
queryTag,
188-
mode,
189-
cliServer,
190-
queryRunner,
191-
databaseItem,
192-
qlpack,
193-
sourceInfo,
194-
additionalPacks,
195-
extensionPacks,
196-
queryStorageDir,
197-
progress,
198-
token,
199-
}: AutoModelQueryOptions): Promise<Sarif.Log | undefined> {
200-
// First, resolve the query that we want to run.
201-
// All queries are tagged like this:
202-
// internal extract automodel <mode> <queryTag>
203-
// Example: internal extract automodel framework-mode candidates
204-
const queries = await resolveQueries(
205-
cliServer,
206-
qlpack,
207-
`Extract automodel ${queryTag}`,
208-
{
209-
kind: "problem",
210-
"tags contain all": ["automodel", modeTag(mode), ...queryTag.split(" ")],
211-
},
212-
);
213-
if (queries.length > 1) {
214-
throw new Error(
215-
`Found multiple auto model queries for ${mode} ${queryTag}. Can't continue`,
216-
);
217-
}
218-
if (queries.length === 0) {
219-
throw new Error(
220-
`Did not found any auto model queries for ${mode} ${queryTag}. Can't continue`,
221-
);
222-
}
223-
224-
const queryPath = queries[0];
225-
const { cleanup: cleanupLockFile } = await createLockFileForStandardQuery(
226-
cliServer,
227-
queryPath,
228-
);
229-
230-
// Get metadata for the query. This is required to interpret the results. We already know the kind is problem
231-
// (because of the constraint in resolveQueries), so we don't need any more checks on the metadata.
232-
const metadata = await cliServer.resolveMetadata(queryPath);
233-
234-
const queryRun = queryRunner.createQueryRun(
235-
databaseItem.databaseUri.fsPath,
236-
{
237-
queryPath,
238-
quickEvalPosition: undefined,
239-
quickEvalCountOnly: false,
240-
},
241-
false,
242-
additionalPacks,
243-
extensionPacks,
244-
queryStorageDir,
245-
undefined,
246-
undefined,
247-
);
248-
249-
const completedQuery = await queryRun.evaluate(
250-
progress,
251-
token,
252-
new TeeLogger(queryRunner.logger, queryRun.outputDir.logPath),
253-
);
254-
255-
await cleanupLockFile?.();
256-
257-
if (completedQuery.resultType !== QueryResultType.SUCCESS) {
258-
void showAndLogExceptionWithTelemetry(
259-
extLogger,
260-
telemetryListener,
261-
redactableError`Auto-model query ${queryTag} failed: ${
262-
completedQuery.message ?? "No message"
263-
}`,
264-
);
265-
return;
266-
}
267-
215+
async function interpretAutomodelResults(
216+
cliServer: CodeQLCliServer,
217+
completedQuery: CoreCompletedQuery,
218+
metadata: QueryMetadata,
219+
sourceInfo: SourceInfo | undefined,
220+
): Promise<Sarif.Log> {
268221
const interpretedResultsPath = join(
269-
queryStorageDir,
270-
`interpreted-results-${queryTag.replaceAll(" ", "-")}-${queryRun.id}.sarif`,
222+
completedQuery.outputDir.querySaveDir,
223+
"results.sarif",
271224
);
272225

273226
// eslint-disable-next-line @typescript-eslint/no-unused-vars -- We only need the actual SARIF data, not the extra fields added by SarifInterpretationData

0 commit comments

Comments
 (0)