Skip to content

Commit dd6d756

Browse files
committed
Add command for running a query suite
This uses a new query-server command for running multiple queries, so that a single evaluator log will be produced for the entire run. To avoid too much code duplication, I have updated a lot of the code paths involved in running local queries to work with multiple query paths. This also required some refactoring to explicitly associate an output basename (used to produce the .bqrs, .csv, etc. paths) with each query, where before those output filenames were hard-coded.
1 parent 806fcf8 commit dd6d756

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+678
-210
lines changed

extensions/ql-vscode/package.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -571,6 +571,10 @@
571571
"command": "codeQL.runQueries",
572572
"title": "CodeQL: Run Queries in Selected Files"
573573
},
574+
{
575+
"command": "codeQL.runQuerySuite",
576+
"title": "CodeQL: Run Selected Query Suite"
577+
},
574578
{
575579
"command": "codeQL.quickEval",
576580
"title": "CodeQL: Quick Evaluation"
@@ -1361,6 +1365,11 @@
13611365
"group": "9_qlCommands",
13621366
"when": "resourceScheme != codeql-zip-archive"
13631367
},
1368+
{
1369+
"command": "codeQL.runQuerySuite",
1370+
"group": "9_qlCommands",
1371+
"when": "resourceScheme != codeql-zip-archive && resourceExtname == .qls && !explorerResourceIsFolder && !listMultiSelection && config.codeQL.canary"
1372+
},
13641373
{
13651374
"command": "codeQL.runVariantAnalysisContextExplorer",
13661375
"group": "9_qlCommands",
@@ -1458,6 +1467,10 @@
14581467
"command": "codeQL.runQueries",
14591468
"when": "false"
14601469
},
1470+
{
1471+
"command": "codeQL.runQuerySuite",
1472+
"when": "false"
1473+
},
14611474
{
14621475
"command": "codeQL.quickEval",
14631476
"when": "editorLangId == ql"

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export interface CliFeatures {
1313
featuresInVersionResult?: boolean;
1414
mrvaPackCreate?: boolean;
1515
generateSummarySymbolMap?: boolean;
16+
queryServerRunQueries?: boolean;
1617
}
1718

1819
export interface VersionAndFeatures {

extensions/ql-vscode/src/common/commands.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ export type LocalQueryCommands = {
138138
"codeQLQueries.createQuery": () => Promise<void>;
139139
"codeQL.runLocalQueryFromFileTab": (uri: Uri) => Promise<void>;
140140
"codeQL.runQueries": ExplorerSelectionCommandFunction<Uri>;
141+
"codeQL.runQuerySuite": ExplorerSelectionCommandFunction<Uri>;
141142
"codeQL.quickEval": (uri: Uri) => Promise<void>;
142143
"codeQL.quickEvalCount": (uri: Uri) => Promise<void>;
143144
"codeQL.quickEvalContextEditor": (uri: Uri) => Promise<void>;

extensions/ql-vscode/src/compare/compare-view.ts

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -70,22 +70,20 @@ export class CompareView extends AbstractWebview<
7070
selectedResultSetName?: string,
7171
) {
7272
const [fromSchemas, toSchemas] = await Promise.all([
73-
this.cliServer.bqrsInfo(
74-
from.completedQuery.query.resultsPaths.resultsPath,
75-
),
76-
this.cliServer.bqrsInfo(to.completedQuery.query.resultsPaths.resultsPath),
73+
this.cliServer.bqrsInfo(from.completedQuery.query.resultsPath),
74+
this.cliServer.bqrsInfo(to.completedQuery.query.resultsPath),
7775
]);
7876

7977
const [fromSchemaNames, toSchemaNames] = await Promise.all([
8078
getResultSetNames(
8179
fromSchemas,
8280
from.completedQuery.query.metadata,
83-
from.completedQuery.query.resultsPaths.interpretedResultsPath,
81+
from.completedQuery.query.interpretedResultsPath,
8482
),
8583
getResultSetNames(
8684
toSchemas,
8785
to.completedQuery.query.metadata,
88-
to.completedQuery.query.resultsPaths.interpretedResultsPath,
86+
to.completedQuery.query.interpretedResultsPath,
8987
),
9088
]);
9189

@@ -101,15 +99,14 @@ export class CompareView extends AbstractWebview<
10199
schemaNames: fromSchemaNames,
102100
metadata: from.completedQuery.query.metadata,
103101
interpretedResultsPath:
104-
from.completedQuery.query.resultsPaths.interpretedResultsPath,
102+
from.completedQuery.query.interpretedResultsPath,
105103
},
106104
to,
107105
toInfo: {
108106
schemas: toSchemas,
109107
schemaNames: toSchemaNames,
110108
metadata: to.completedQuery.query.metadata,
111-
interpretedResultsPath:
112-
to.completedQuery.query.resultsPaths.interpretedResultsPath,
109+
interpretedResultsPath: to.completedQuery.query.interpretedResultsPath,
113110
},
114111
commonResultSetNames,
115112
};
@@ -392,12 +389,12 @@ export class CompareView extends AbstractWebview<
392389
this.getResultSet(
393390
fromInfo.schemas,
394391
fromResultSetName,
395-
from.completedQuery.query.resultsPaths.resultsPath,
392+
from.completedQuery.query.resultsPath,
396393
),
397394
this.getResultSet(
398395
toInfo.schemas,
399396
toResultSetName,
400-
to.completedQuery.query.resultsPaths.resultsPath,
397+
to.completedQuery.query.resultsPath,
401398
),
402399
]);
403400

extensions/ql-vscode/src/compare/interpreted-results.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,9 @@ export async function compareInterpretedResults(
3636

3737
const [fromResultSet, toResultSet, sourceLocationPrefix] = await Promise.all([
3838
getInterpretedResults(
39-
fromQuery.completedQuery.query.resultsPaths.interpretedResultsPath,
40-
),
41-
getInterpretedResults(
42-
toQuery.completedQuery.query.resultsPaths.interpretedResultsPath,
39+
fromQuery.completedQuery.query.interpretedResultsPath,
4340
),
41+
getInterpretedResults(toQuery.completedQuery.query.interpretedResultsPath),
4442
database.getSourceLocationPrefix(cliServer),
4543
]);
4644

extensions/ql-vscode/src/debugger/debug-protocol.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ export interface EvaluationCompletedEvent extends Event {
3939
resultType: QueryResultType;
4040
message: string | undefined;
4141
evaluationTime: number;
42+
outputBaseName: string;
4243
};
4344
}
4445

extensions/ql-vscode/src/debugger/debug-session.ts

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import type { BaseLogger, LogOptions } from "../common/logging";
1616
import { queryServerLogger } from "../common/logging/vscode";
1717
import { QueryResultType } from "../query-server/messages";
1818
import type {
19-
CoreQueryResults,
19+
CoreQueryResult,
2020
CoreQueryRun,
2121
QueryRunner,
2222
} from "../query-server";
@@ -25,6 +25,7 @@ import type * as CodeQLProtocol from "./debug-protocol";
2525
import type { QuickEvalContext } from "../run-queries-shared";
2626
import { getErrorMessage } from "../common/helpers-pure";
2727
import { DisposableObject } from "../common/disposable-object";
28+
import { basename } from "path";
2829

2930
// More complete implementations of `Event` for certain events, because the classes from
3031
// `@vscode/debugadapter` make it more difficult to provide some of the message values.
@@ -107,9 +108,9 @@ class EvaluationCompletedEvent
107108
public readonly event = "codeql-evaluation-completed";
108109
public readonly body: CodeQLProtocol.EvaluationCompletedEvent["body"];
109110

110-
constructor(results: CoreQueryResults) {
111+
constructor(result: CoreQueryResult) {
111112
super("codeql-evaluation-completed");
112-
this.body = results;
113+
this.body = result;
113114
}
114115
}
115116

@@ -143,6 +144,7 @@ const QUERY_THREAD_NAME = "Evaluation thread";
143144
class RunningQuery extends DisposableObject {
144145
private readonly tokenSource = this.push(new CancellationTokenSource());
145146
public readonly queryRun: CoreQueryRun;
147+
private readonly queryPath: string;
146148

147149
public constructor(
148150
queryRunner: QueryRunner,
@@ -154,12 +156,15 @@ class RunningQuery extends DisposableObject {
154156
) {
155157
super();
156158

159+
this.queryPath = config.query;
157160
// Create the query run, which will give us some information about the query even before the
158161
// evaluation has completed.
159162
this.queryRun = queryRunner.createQueryRun(
160163
config.database,
161164
{
162-
queryPath: config.query,
165+
queryInputsOutputs: [
166+
{ queryPath: this.queryPath, outputBaseName: "results" },
167+
],
163168
quickEvalPosition: quickEvalContext?.quickEvalPosition,
164169
quickEvalCountOnly: quickEvalContext?.quickEvalCount,
165170
},
@@ -168,7 +173,7 @@ class RunningQuery extends DisposableObject {
168173
config.extensionPacks,
169174
config.additionalRunQueryArgs,
170175
queryStorageDir,
171-
undefined,
176+
basename(config.query),
172177
undefined,
173178
);
174179
}
@@ -208,7 +213,7 @@ class RunningQuery extends DisposableObject {
208213
progressStart.body.cancellable = true;
209214
this.sendEvent(progressStart);
210215
try {
211-
return await this.queryRun.evaluate(
216+
const completedQuery = await this.queryRun.evaluate(
212217
(p) => {
213218
const progressUpdate = new ProgressUpdateEvent(
214219
this.queryRun.id,
@@ -220,6 +225,14 @@ class RunningQuery extends DisposableObject {
220225
this.tokenSource.token,
221226
this.logger,
222227
);
228+
return (
229+
completedQuery.results.get(this.queryPath) ?? {
230+
resultType: QueryResultType.OTHER_ERROR,
231+
message: "Missing query results",
232+
evaluationTime: 0,
233+
outputBaseName: "unknown",
234+
}
235+
);
223236
} finally {
224237
this.sendEvent(new ProgressEndEvent(this.queryRun.id));
225238
}
@@ -229,6 +242,7 @@ class RunningQuery extends DisposableObject {
229242
resultType: QueryResultType.OTHER_ERROR,
230243
message,
231244
evaluationTime: 0,
245+
outputBaseName: "unknown",
232246
};
233247
}
234248
}

extensions/ql-vscode/src/debugger/debugger-ui.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { debug, Uri, CancellationTokenSource } from "vscode";
88
import type { DebuggerCommands } from "../common/commands";
99
import type { DatabaseManager } from "../databases/local-databases";
1010
import { DisposableObject } from "../common/disposable-object";
11-
import type { CoreQueryResults } from "../query-server";
11+
import type { CoreQueryResult } from "../query-server";
1212
import {
1313
getQuickEvalContext,
1414
saveBeforeStart,
@@ -134,8 +134,15 @@ class QLDebugAdapterTracker
134134
body: EvaluationCompletedEvent["body"],
135135
): Promise<void> {
136136
if (this.localQueryRun !== undefined) {
137-
const results: CoreQueryResults = body;
138-
await this.localQueryRun.complete(results, (_) => {});
137+
const results: CoreQueryResult = body;
138+
await this.localQueryRun.complete(
139+
{
140+
results: new Map<string, CoreQueryResult>([
141+
[this.configuration.query, results],
142+
]),
143+
},
144+
(_) => {},
145+
);
139146
this.localQueryRun = undefined;
140147
}
141148
}

extensions/ql-vscode/src/language-support/ast-viewer/ast-builder.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import type {
77
import type { DatabaseItem } from "../../databases/local-databases";
88
import type { ChildAstItem, AstItem } from "./ast-viewer";
99
import type { Uri } from "vscode";
10-
import type { QueryOutputDir } from "../../local-queries/query-output-dir";
1110
import { fileRangeFromURI } from "../contextual/file-range-from-uri";
1211
import { mapUrlValue } from "../../common/bqrs-raw-results-mapper";
1312

@@ -17,15 +16,12 @@ import { mapUrlValue } from "../../common/bqrs-raw-results-mapper";
1716
*/
1817
export class AstBuilder {
1918
private roots: AstItem[] | undefined;
20-
private bqrsPath: string;
2119
constructor(
22-
outputDir: QueryOutputDir,
20+
private readonly bqrsPath: string,
2321
private cli: CodeQLCliServer,
2422
public db: DatabaseItem,
2523
public fileName: Uri,
26-
) {
27-
this.bqrsPath = outputDir.bqrsPath;
28-
}
24+
) {}
2925

3026
async getRoots(): Promise<AstItem[]> {
3127
if (!this.roots) {

extensions/ql-vscode/src/language-support/contextual/location-finder.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ import {
2121
} from "./query-resolver";
2222
import type { CancellationToken, LocationLink } from "vscode";
2323
import { Uri } from "vscode";
24-
import type { QueryOutputDir } from "../../local-queries/query-output-dir";
2524
import type { QueryRunner } from "../../query-server";
2625
import { QueryResultType } from "../../query-server/messages";
2726
import { fileRangeFromURI } from "./file-range-from-uri";
@@ -84,23 +83,28 @@ export async function getLocationsForUriString(
8483
token,
8584
templates,
8685
);
87-
if (results.resultType === QueryResultType.SUCCESS) {
86+
const queryResult = results.results.get(query);
87+
if (queryResult?.resultType === QueryResultType.SUCCESS) {
8888
links.push(
89-
...(await getLinksFromResults(results.outputDir, cli, db, filter)),
89+
...(await getLinksFromResults(
90+
results.outputDir.getBqrsPath(queryResult.outputBaseName),
91+
cli,
92+
db,
93+
filter,
94+
)),
9095
);
9196
}
9297
}
9398
return links;
9499
}
95100

96101
async function getLinksFromResults(
97-
outputDir: QueryOutputDir,
102+
bqrsPath: string,
98103
cli: CodeQLCliServer,
99104
db: DatabaseItem,
100105
filter: (srcFile: string, destFile: string) => boolean,
101106
): Promise<FullLocationLink[]> {
102107
const localLinks: FullLocationLink[] = [];
103-
const bqrsPath = outputDir.bqrsPath;
104108
const info = await cli.bqrsInfo(bqrsPath);
105109
const selectInfo = info["result-sets"].find(
106110
(schema) => schema.name === SELECT_QUERY_NAME,

extensions/ql-vscode/src/language-support/contextual/query-resolver.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import type { CancellationToken } from "vscode";
1414
import type { ProgressCallback } from "../../common/vscode/progress";
1515
import type { CoreCompletedQuery, QueryRunner } from "../../query-server";
1616
import { createLockFileForStandardQuery } from "../../local-queries/standard-queries";
17+
import { basename } from "path";
1718

1819
/**
1920
* This wil try to determine the qlpacks for a given database. If it can't find a matching
@@ -80,13 +81,16 @@ export async function runContextualQuery(
8081
const { cleanup } = await createLockFileForStandardQuery(cli, query);
8182
const queryRun = qs.createQueryRun(
8283
db.databaseUri.fsPath,
83-
{ queryPath: query, quickEvalPosition: undefined },
84+
{
85+
queryInputsOutputs: [{ queryPath: query, outputBaseName: "results" }],
86+
quickEvalPosition: undefined,
87+
},
8488
false,
8589
getOnDiskWorkspaceFolders(),
8690
undefined,
8791
{},
8892
queryStorageDir,
89-
undefined,
93+
basename(query),
9094
templates,
9195
);
9296
void extLogger.log(

extensions/ql-vscode/src/language-support/contextual/template-provider.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,8 +209,14 @@ export class TemplatePrintAstProvider {
209209
? await this.cache.get(fileUri.toString(), progress, token)
210210
: await this.getAst(fileUri.toString(), progress, token);
211211

212+
const queryResults = Array.from(completedQuery.results.values());
213+
if (queryResults.length !== 1) {
214+
throw new Error(
215+
`Expected exactly one query result, but found ${queryResults.length}.`,
216+
);
217+
}
212218
return new AstBuilder(
213-
completedQuery.outputDir,
219+
completedQuery.outputDir.getBqrsPath(queryResults[0].outputBaseName),
214220
this.cli,
215221
this.dbm.findDatabaseItem(Uri.file(completedQuery.dbPath))!,
216222
fileUri,

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy