Skip to content

Commit ac0dfa5

Browse files
authored
Merge pull request #2742 from github/starcke/flow-queries-refactor
Starcke/flow queries refactor
2 parents 2ffb789 + 886f211 commit ac0dfa5

2 files changed

Lines changed: 80 additions & 118 deletions

File tree

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import {
2222
import { DatabaseItem, DatabaseManager } from "../databases/local-databases";
2323
import { CodeQLCliServer } from "../codeql-cli/cli";
2424
import { asError, assertNever, getErrorMessage } from "../common/helpers-pure";
25-
import { generateFlowModel } from "./flow-model-queries";
25+
import { runFlowModelQueries } from "./flow-model-queries";
2626
import { promptImportGithubDatabase } from "../databases/database-fetcher";
2727
import { App } from "../common/app";
2828
import { showResolvableLocation } from "../databases/local-databases/locations";
@@ -389,7 +389,7 @@ export class DataExtensionsEditorView extends AbstractWebview<
389389
});
390390

391391
try {
392-
await generateFlowModel({
392+
await runFlowModelQueries({
393393
cliServer: this.cliServer,
394394
queryRunner: this.queryRunner,
395395
queryStorageDir: this.queryStorageDir,

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

Lines changed: 78 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,16 @@ import { DatabaseItem } from "../databases/local-databases";
33
import { basename } from "path";
44
import { QueryRunner } from "../query-server";
55
import { CodeQLCliServer } from "../codeql-cli/cli";
6-
import { showAndLogExceptionWithTelemetry, TeeLogger } from "../common/logging";
6+
import { showAndLogExceptionWithTelemetry } from "../common/logging";
77
import { extLogger } from "../common/logging/vscode";
88
import { extensiblePredicateDefinitions } from "./predicates";
99
import { ProgressCallback } from "../common/vscode/progress";
1010
import { getOnDiskWorkspaceFolders } from "../common/vscode/workspace-folders";
1111
import { ModeledMethod, ModeledMethodType } from "./modeled-method";
1212
import { redactableError } from "../common/errors";
13-
import { QueryResultType } from "../query-server/new-messages";
14-
import { file } from "tmp-promise";
15-
import { writeFile } from "fs-extra";
16-
import { dump } from "js-yaml";
17-
import { qlpackOfDatabase } from "../local-queries";
13+
import { qlpackOfDatabase, resolveQueries } from "../local-queries";
1814
import { telemetryListener } from "../common/vscode/telemetry";
15+
import { runQuery } from "../local-queries/run-query";
1916

2017
type FlowModelOptions = {
2118
cliServer: CodeQLCliServer;
@@ -27,44 +24,73 @@ type FlowModelOptions = {
2724
onResults: (results: ModeledMethod[]) => void | Promise<void>;
2825
};
2926

30-
async function resolveQueries(
31-
cliServer: CodeQLCliServer,
32-
databaseItem: DatabaseItem,
33-
): Promise<string[]> {
34-
const qlpacks = await qlpackOfDatabase(cliServer, databaseItem);
27+
export async function runFlowModelQueries({
28+
onResults,
29+
...options
30+
}: FlowModelOptions) {
31+
const queries = await resolveFlowQueries(
32+
options.cliServer,
33+
options.databaseItem,
34+
);
3535

36-
const packsToSearch: string[] = [];
36+
const queriesByBasename: Record<string, string> = {};
37+
for (const query of queries) {
38+
queriesByBasename[basename(query)] = query;
39+
}
3740

38-
// The CLI can handle both library packs and query packs, so search both packs in order.
39-
packsToSearch.push(qlpacks.dbschemePack);
40-
if (qlpacks.queryPack !== undefined) {
41-
packsToSearch.push(qlpacks.queryPack);
41+
const summaryResults = await runSingleFlowQuery(
42+
"summary",
43+
queriesByBasename["CaptureSummaryModels.ql"],
44+
0,
45+
options,
46+
);
47+
if (summaryResults) {
48+
await onResults(summaryResults);
4249
}
4350

44-
const suiteFile = (
45-
await file({
46-
postfix: ".qls",
47-
})
48-
).path;
49-
const suiteYaml = [];
50-
for (const qlpack of packsToSearch) {
51-
suiteYaml.push({
52-
from: qlpack,
53-
queries: ".",
54-
include: {
55-
"tags contain": "modelgenerator",
56-
},
57-
});
51+
const sinkResults = await runSingleFlowQuery(
52+
"sink",
53+
queriesByBasename["CaptureSinkModels.ql"],
54+
1,
55+
options,
56+
);
57+
if (sinkResults) {
58+
await onResults(sinkResults);
5859
}
59-
await writeFile(suiteFile, dump(suiteYaml), "utf8");
6060

61-
return await cliServer.resolveQueriesInSuite(
62-
suiteFile,
63-
getOnDiskWorkspaceFolders(),
61+
const sourceResults = await runSingleFlowQuery(
62+
"source",
63+
queriesByBasename["CaptureSourceModels.ql"],
64+
2,
65+
options,
66+
);
67+
if (sourceResults) {
68+
await onResults(sourceResults);
69+
}
70+
71+
const neutralResults = await runSingleFlowQuery(
72+
"neutral",
73+
queriesByBasename["CaptureNeutralModels.ql"],
74+
3,
75+
options,
6476
);
77+
if (neutralResults) {
78+
await onResults(neutralResults);
79+
}
6580
}
6681

67-
async function getModeledMethodsFromFlow(
82+
async function resolveFlowQueries(
83+
cliServer: CodeQLCliServer,
84+
databaseItem: DatabaseItem,
85+
): Promise<string[]> {
86+
const qlpacks = await qlpackOfDatabase(cliServer, databaseItem);
87+
88+
return await resolveQueries(cliServer, qlpacks, "flow model generator", {
89+
"tags contain": ["modelgenerator"],
90+
});
91+
}
92+
93+
async function runSingleFlowQuery(
6894
type: Exclude<ModeledMethodType, "none">,
6995
queryPath: string | undefined,
7096
queryStep: number,
@@ -77,6 +103,7 @@ async function getModeledMethodsFromFlow(
77103
token,
78104
}: Omit<FlowModelOptions, "onResults">,
79105
): Promise<ModeledMethod[]> {
106+
// Check that the right query was found
80107
if (queryPath === undefined) {
81108
void showAndLogExceptionWithTelemetry(
82109
extLogger,
@@ -86,45 +113,32 @@ async function getModeledMethodsFromFlow(
86113
return [];
87114
}
88115

89-
const definition = extensiblePredicateDefinitions[type];
90-
91-
const queryRun = queryRunner.createQueryRun(
92-
databaseItem.databaseUri.fsPath,
93-
{
94-
queryPath,
95-
quickEvalPosition: undefined,
96-
quickEvalCountOnly: false,
97-
},
98-
false,
99-
getOnDiskWorkspaceFolders(),
100-
undefined,
116+
// Run the query
117+
const completedQuery = await runQuery({
118+
cliServer,
119+
queryRunner,
120+
databaseItem,
121+
queryPath,
101122
queryStorageDir,
102-
undefined,
103-
undefined,
104-
);
105-
106-
const queryResult = await queryRun.evaluate(
107-
({ step, message }) =>
123+
additionalPacks: getOnDiskWorkspaceFolders(),
124+
extensionPacks: undefined,
125+
progress: ({ step, message }) =>
108126
progress({
109127
message: `Generating ${type} model: ${message}`,
110128
step: queryStep * 1000 + step,
111129
maxStep: 4000,
112130
}),
113131
token,
114-
new TeeLogger(queryRunner.logger, queryRun.outputDir.logPath),
115-
);
116-
if (queryResult.resultType !== QueryResultType.SUCCESS) {
117-
void showAndLogExceptionWithTelemetry(
118-
extLogger,
119-
telemetryListener,
120-
redactableError`Failed to run ${basename(queryPath)} query: ${
121-
queryResult.message ?? "No message"
122-
}`,
123-
);
132+
});
133+
134+
if (!completedQuery) {
124135
return [];
125136
}
126137

127-
const bqrsPath = queryResult.outputDir.bqrsPath;
138+
// Interpret the results
139+
const definition = extensiblePredicateDefinitions[type];
140+
141+
const bqrsPath = completedQuery.outputDir.bqrsPath;
128142

129143
const bqrsInfo = await cliServer.bqrsInfo(bqrsPath);
130144
if (bqrsInfo["result-sets"].length !== 1) {
@@ -154,55 +168,3 @@ async function getModeledMethodsFromFlow(
154168
})
155169
);
156170
}
157-
158-
export async function generateFlowModel({
159-
onResults,
160-
...options
161-
}: FlowModelOptions) {
162-
const queries = await resolveQueries(options.cliServer, options.databaseItem);
163-
164-
const queriesByBasename: Record<string, string> = {};
165-
for (const query of queries) {
166-
queriesByBasename[basename(query)] = query;
167-
}
168-
169-
const summaryResults = await getModeledMethodsFromFlow(
170-
"summary",
171-
queriesByBasename["CaptureSummaryModels.ql"],
172-
0,
173-
options,
174-
);
175-
if (summaryResults) {
176-
await onResults(summaryResults);
177-
}
178-
179-
const sinkResults = await getModeledMethodsFromFlow(
180-
"sink",
181-
queriesByBasename["CaptureSinkModels.ql"],
182-
1,
183-
options,
184-
);
185-
if (sinkResults) {
186-
await onResults(sinkResults);
187-
}
188-
189-
const sourceResults = await getModeledMethodsFromFlow(
190-
"source",
191-
queriesByBasename["CaptureSourceModels.ql"],
192-
2,
193-
options,
194-
);
195-
if (sourceResults) {
196-
await onResults(sourceResults);
197-
}
198-
199-
const neutralResults = await getModeledMethodsFromFlow(
200-
"neutral",
201-
queriesByBasename["CaptureNeutralModels.ql"],
202-
3,
203-
options,
204-
);
205-
if (neutralResults) {
206-
await onResults(neutralResults);
207-
}
208-
}

0 commit comments

Comments
 (0)