Skip to content

Commit cae7239

Browse files
authored
Merge pull request #2416 from github/koesie10/resolve-data-extensions-editor-queries
Resolve queries instead of hardcoding the path
2 parents 12615f1 + c1edd08 commit cae7239

File tree

2 files changed

+66
-38
lines changed

2 files changed

+66
-38
lines changed

extensions/ql-vscode/src/data-extensions-editor/data-extensions-editor-view.ts

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import {
55
ViewColumn,
66
window,
77
workspace,
8-
WorkspaceFolder,
98
} from "vscode";
109
import {
1110
AbstractWebview,
@@ -47,19 +46,6 @@ import {
4746
import { showLlmGeneration } from "../config";
4847
import { getAutoModelUsages } from "./auto-model-usages-query";
4948

50-
function getQlSubmoduleFolder(): WorkspaceFolder | undefined {
51-
const workspaceFolder = workspace.workspaceFolders?.find(
52-
(folder) => folder.name === "ql",
53-
);
54-
if (!workspaceFolder) {
55-
void extLogger.log("No workspace folder 'ql' found");
56-
57-
return;
58-
}
59-
60-
return workspaceFolder;
61-
}
62-
6349
export class DataExtensionsEditorView extends AbstractWebview<
6450
ToDataExtensionsEditorMessage,
6551
FromDataExtensionsEditorMessage
@@ -324,11 +310,6 @@ export class DataExtensionsEditorView extends AbstractWebview<
324310
// but we need to set it back to the originally selected database.
325311
await this.databaseManager.setCurrentDatabaseItem(selectedDatabase);
326312

327-
const workspaceFolder = getQlSubmoduleFolder();
328-
if (!workspaceFolder) {
329-
return;
330-
}
331-
332313
await this.showProgress({
333314
step: 0,
334315
maxStep: 4000,
@@ -340,7 +321,6 @@ export class DataExtensionsEditorView extends AbstractWebview<
340321
cliServer: this.cliServer,
341322
queryRunner: this.queryRunner,
342323
queryStorageDir: this.queryStorageDir,
343-
qlDir: workspaceFolder.uri.fsPath,
344324
databaseItem: database,
345325
onResults: async (results) => {
346326
const modeledMethodsByName: Record<string, ModeledMethod> = {};

extensions/ql-vscode/src/data-extensions-editor/generate-flow-model.ts

Lines changed: 66 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { CancellationToken } from "vscode";
22
import { DatabaseItem } from "../databases/local-databases";
3-
import { join } from "path";
3+
import { basename } from "path";
44
import { QueryRunner } from "../query-server";
55
import { CodeQLCliServer } from "../codeql-cli/cli";
66
import { TeeLogger } from "../common";
@@ -16,45 +16,84 @@ import {
1616
} from "./modeled-method";
1717
import { redactableError } from "../pure/errors";
1818
import { QueryResultType } from "../pure/new-messages";
19+
import { file } from "tmp-promise";
20+
import { writeFile } from "fs-extra";
21+
import { dump } from "js-yaml";
22+
import { qlpackOfDatabase } from "../language-support";
1923

2024
type FlowModelOptions = {
2125
cliServer: CodeQLCliServer;
2226
queryRunner: QueryRunner;
2327
queryStorageDir: string;
24-
qlDir: string;
2528
databaseItem: DatabaseItem;
2629
progress: ProgressCallback;
2730
token: CancellationToken;
2831
onResults: (results: ModeledMethodWithSignature[]) => void | Promise<void>;
2932
};
3033

34+
async function resolveQueries(
35+
cliServer: CodeQLCliServer,
36+
databaseItem: DatabaseItem,
37+
): Promise<string[]> {
38+
const qlpacks = await qlpackOfDatabase(cliServer, databaseItem);
39+
40+
const packsToSearch: string[] = [];
41+
42+
// The CLI can handle both library packs and query packs, so search both packs in order.
43+
packsToSearch.push(qlpacks.dbschemePack);
44+
if (qlpacks.queryPack !== undefined) {
45+
packsToSearch.push(qlpacks.queryPack);
46+
}
47+
48+
const suiteFile = (
49+
await file({
50+
postfix: ".qls",
51+
})
52+
).path;
53+
const suiteYaml = [];
54+
for (const qlpack of packsToSearch) {
55+
suiteYaml.push({
56+
from: qlpack,
57+
queries: ".",
58+
include: {
59+
"tags contain": "modelgenerator",
60+
},
61+
});
62+
}
63+
await writeFile(suiteFile, dump(suiteYaml), "utf8");
64+
65+
return await cliServer.resolveQueriesInSuite(
66+
suiteFile,
67+
getOnDiskWorkspaceFolders(),
68+
);
69+
}
70+
3171
async function getModeledMethodsFromFlow(
3272
type: Exclude<ModeledMethodType, "none">,
33-
queryName: string,
73+
queryPath: string | undefined,
3474
queryStep: number,
3575
{
3676
cliServer,
3777
queryRunner,
3878
queryStorageDir,
39-
qlDir,
4079
databaseItem,
4180
progress,
4281
token,
4382
}: Omit<FlowModelOptions, "onResults">,
4483
): Promise<ModeledMethodWithSignature[]> {
45-
const definition = extensiblePredicateDefinitions[type];
84+
if (queryPath === undefined) {
85+
void showAndLogExceptionWithTelemetry(
86+
redactableError`Failed to find ${type} query`,
87+
);
88+
return [];
89+
}
4690

47-
const query = join(
48-
qlDir,
49-
databaseItem.language,
50-
"ql/src/utils/modelgenerator",
51-
queryName,
52-
);
91+
const definition = extensiblePredicateDefinitions[type];
5392

5493
const queryRun = queryRunner.createQueryRun(
5594
databaseItem.databaseUri.fsPath,
5695
{
57-
queryPath: query,
96+
queryPath,
5897
quickEvalPosition: undefined,
5998
quickEvalCountOnly: false,
6099
},
@@ -78,7 +117,7 @@ async function getModeledMethodsFromFlow(
78117
);
79118
if (queryResult.resultType !== QueryResultType.SUCCESS) {
80119
void showAndLogExceptionWithTelemetry(
81-
redactableError`Failed to run ${queryName} query: ${
120+
redactableError`Failed to run ${basename(queryPath)} query: ${
82121
queryResult.message ?? "No message"
83122
}`,
84123
);
@@ -90,7 +129,9 @@ async function getModeledMethodsFromFlow(
90129
const bqrsInfo = await cliServer.bqrsInfo(bqrsPath);
91130
if (bqrsInfo["result-sets"].length !== 1) {
92131
void showAndLogExceptionWithTelemetry(
93-
redactableError`Expected exactly one result set, got ${bqrsInfo["result-sets"].length} for ${queryName}`,
132+
redactableError`Expected exactly one result set, got ${
133+
bqrsInfo["result-sets"].length
134+
} for ${basename(queryPath)}`,
94135
);
95136
}
96137

@@ -116,9 +157,16 @@ export async function generateFlowModel({
116157
onResults,
117158
...options
118159
}: FlowModelOptions) {
160+
const queries = await resolveQueries(options.cliServer, options.databaseItem);
161+
162+
const queriesByBasename: Record<string, string> = {};
163+
for (const query of queries) {
164+
queriesByBasename[basename(query)] = query;
165+
}
166+
119167
const summaryResults = await getModeledMethodsFromFlow(
120168
"summary",
121-
"CaptureSummaryModels.ql",
169+
queriesByBasename["CaptureSummaryModels.ql"],
122170
0,
123171
options,
124172
);
@@ -128,7 +176,7 @@ export async function generateFlowModel({
128176

129177
const sinkResults = await getModeledMethodsFromFlow(
130178
"sink",
131-
"CaptureSinkModels.ql",
179+
queriesByBasename["CaptureSinkModels.ql"],
132180
1,
133181
options,
134182
);
@@ -138,7 +186,7 @@ export async function generateFlowModel({
138186

139187
const sourceResults = await getModeledMethodsFromFlow(
140188
"source",
141-
"CaptureSourceModels.ql",
189+
queriesByBasename["CaptureSourceModels.ql"],
142190
2,
143191
options,
144192
);
@@ -148,7 +196,7 @@ export async function generateFlowModel({
148196

149197
const neutralResults = await getModeledMethodsFromFlow(
150198
"neutral",
151-
"CaptureNeutralModels.ql",
199+
queriesByBasename["CaptureNeutralModels.ql"],
152200
3,
153201
options,
154202
);

0 commit comments

Comments
 (0)