Skip to content

Commit 102976e

Browse files
committed
Use functions instead of class for generating flow model
We were using a single-use class for generating the flow model, while we are actually able to do it using two functions. This is more in line with our existing codebase.
1 parent 4e8df30 commit 102976e

File tree

2 files changed

+121
-131
lines changed

2 files changed

+121
-131
lines changed

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

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -276,13 +276,13 @@ export class DataExtensionsEditorView extends AbstractWebview<
276276
});
277277

278278
try {
279-
await generateFlowModel(
280-
this.cliServer,
281-
this.queryRunner,
282-
this.queryStorageDir,
283-
workspaceFolder.uri.fsPath,
284-
database,
285-
async (results) => {
279+
await generateFlowModel({
280+
cliServer: this.cliServer,
281+
queryRunner: this.queryRunner,
282+
queryStorageDir: this.queryStorageDir,
283+
qlDir: workspaceFolder.uri.fsPath,
284+
databaseItem: database,
285+
onResults: async (results) => {
286286
const modeledMethodsByName: Record<string, ModeledMethod> = {};
287287

288288
for (const result of results) {
@@ -295,9 +295,9 @@ export class DataExtensionsEditorView extends AbstractWebview<
295295
overrideNone: true,
296296
});
297297
},
298-
(update) => this.showProgress(update),
299-
tokenSource.token,
300-
);
298+
progress: (update) => this.showProgress(update),
299+
token: tokenSource.token,
300+
});
301301
} catch (e: unknown) {
302302
void showAndLogExceptionWithTelemetry(
303303
redactableError(

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

Lines changed: 111 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -12,140 +12,130 @@ import {
1212
ModeledMethodWithSignature,
1313
} from "./modeled-method";
1414

15-
class FlowModelGenerator {
16-
constructor(
17-
private readonly cli: CodeQLCliServer,
18-
private readonly queryRunner: QueryRunner,
19-
private readonly queryStorageDir: string,
20-
private readonly qlDir: string,
21-
private readonly databaseItem: DatabaseItem,
22-
private readonly progress: ProgressCallback,
23-
private readonly token: CancellationToken,
24-
) {}
25-
26-
private async getModeledMethodsFromFlow(
27-
type: Exclude<ModeledMethodType, "none">,
28-
queryName: string,
29-
queryStep: number,
30-
): Promise<ModeledMethodWithSignature[]> {
31-
const definition = extensiblePredicateDefinitions[type];
32-
33-
const query = join(
34-
this.qlDir,
35-
this.databaseItem.language,
36-
"ql/src/utils/modelgenerator",
37-
queryName,
38-
);
15+
type FlowModelOptions = {
16+
cliServer: CodeQLCliServer;
17+
queryRunner: QueryRunner;
18+
queryStorageDir: string;
19+
qlDir: string;
20+
databaseItem: DatabaseItem;
21+
progress: ProgressCallback;
22+
token: CancellationToken;
23+
onResults: (results: ModeledMethodWithSignature[]) => void | Promise<void>;
24+
};
25+
26+
async function getModeledMethodsFromFlow(
27+
type: Exclude<ModeledMethodType, "none">,
28+
queryName: string,
29+
queryStep: number,
30+
{
31+
cliServer,
32+
queryRunner,
33+
queryStorageDir,
34+
qlDir,
35+
databaseItem,
36+
progress,
37+
token,
38+
}: Omit<FlowModelOptions, "onResults">,
39+
): Promise<ModeledMethodWithSignature[]> {
40+
const definition = extensiblePredicateDefinitions[type];
3941

40-
const queryRun = this.queryRunner.createQueryRun(
41-
this.databaseItem.databaseUri.fsPath,
42-
{ queryPath: query, quickEvalPosition: undefined },
43-
false,
44-
getOnDiskWorkspaceFolders(),
45-
undefined,
46-
this.queryStorageDir,
47-
undefined,
48-
undefined,
49-
);
42+
const query = join(
43+
qlDir,
44+
databaseItem.language,
45+
"ql/src/utils/modelgenerator",
46+
queryName,
47+
);
5048

51-
const queryResult = await queryRun.evaluate(
52-
({ step, message }) =>
53-
this.progress({
54-
message: `Generating ${type} model: ${message}`,
55-
step: queryStep * 1000 + step,
56-
maxStep: 4000,
57-
}),
58-
this.token,
59-
new TeeLogger(this.queryRunner.logger, queryRun.outputDir.logPath),
60-
);
49+
const queryRun = queryRunner.createQueryRun(
50+
databaseItem.databaseUri.fsPath,
51+
{ queryPath: query, quickEvalPosition: undefined },
52+
false,
53+
getOnDiskWorkspaceFolders(),
54+
undefined,
55+
queryStorageDir,
56+
undefined,
57+
undefined,
58+
);
6159

62-
const bqrsPath = queryResult.outputDir.bqrsPath;
60+
const queryResult = await queryRun.evaluate(
61+
({ step, message }) =>
62+
progress({
63+
message: `Generating ${type} model: ${message}`,
64+
step: queryStep * 1000 + step,
65+
maxStep: 4000,
66+
}),
67+
token,
68+
new TeeLogger(queryRunner.logger, queryRun.outputDir.logPath),
69+
);
6370

64-
const bqrsInfo = await this.cli.bqrsInfo(bqrsPath);
65-
if (bqrsInfo["result-sets"].length !== 1) {
66-
throw new Error(
67-
`Expected exactly one result set, got ${bqrsInfo["result-sets"].length}`,
68-
);
69-
}
71+
const bqrsPath = queryResult.outputDir.bqrsPath;
7072

71-
const resultSet = bqrsInfo["result-sets"][0];
73+
const bqrsInfo = await cliServer.bqrsInfo(bqrsPath);
74+
if (bqrsInfo["result-sets"].length !== 1) {
75+
throw new Error(
76+
`Expected exactly one result set, got ${bqrsInfo["result-sets"].length}`,
77+
);
78+
}
7279

73-
const decodedResults = await this.cli.bqrsDecode(bqrsPath, resultSet.name);
80+
const resultSet = bqrsInfo["result-sets"][0];
7481

75-
const results = decodedResults.tuples;
82+
const decodedResults = await cliServer.bqrsDecode(bqrsPath, resultSet.name);
7683

77-
return (
78-
results
79-
// This is just a sanity check. The query should only return strings.
80-
.filter((result) => typeof result[0] === "string")
81-
.map((result) => {
82-
const row = result[0] as string;
84+
const results = decodedResults.tuples;
8385

84-
return definition.readModeledMethod(row.split(";"));
85-
})
86-
);
86+
return (
87+
results
88+
// This is just a sanity check. The query should only return strings.
89+
.filter((result) => typeof result[0] === "string")
90+
.map((result) => {
91+
const row = result[0] as string;
92+
93+
return definition.readModeledMethod(row.split(";"));
94+
})
95+
);
96+
}
97+
98+
export async function generateFlowModel({
99+
onResults,
100+
...options
101+
}: FlowModelOptions) {
102+
const summaryResults = await getModeledMethodsFromFlow(
103+
"summary",
104+
"CaptureSummaryModels.ql",
105+
0,
106+
options,
107+
);
108+
if (summaryResults) {
109+
await onResults(summaryResults);
87110
}
88111

89-
async run(
90-
onResults: (results: ModeledMethodWithSignature[]) => void | Promise<void>,
91-
) {
92-
const summaryResults = await this.getModeledMethodsFromFlow(
93-
"summary",
94-
"CaptureSummaryModels.ql",
95-
0,
96-
);
97-
if (summaryResults) {
98-
await onResults(summaryResults);
99-
}
100-
101-
const sinkResults = await this.getModeledMethodsFromFlow(
102-
"sink",
103-
"CaptureSinkModels.ql",
104-
1,
105-
);
106-
if (sinkResults) {
107-
await onResults(sinkResults);
108-
}
109-
110-
const sourceResults = await this.getModeledMethodsFromFlow(
111-
"source",
112-
"CaptureSourceModels.ql",
113-
2,
114-
);
115-
if (sourceResults) {
116-
await onResults(sourceResults);
117-
}
118-
119-
const neutralResults = await this.getModeledMethodsFromFlow(
120-
"neutral",
121-
"CaptureNeutralModels.ql",
122-
3,
123-
);
124-
if (neutralResults) {
125-
await onResults(neutralResults);
126-
}
112+
const sinkResults = await getModeledMethodsFromFlow(
113+
"sink",
114+
"CaptureSinkModels.ql",
115+
1,
116+
options,
117+
);
118+
if (sinkResults) {
119+
await onResults(sinkResults);
127120
}
128-
}
129121

130-
export async function generateFlowModel(
131-
cli: CodeQLCliServer,
132-
queryRunner: QueryRunner,
133-
queryStorageDir: string,
134-
qlDir: string,
135-
databaseItem: DatabaseItem,
136-
onResults: (results: ModeledMethodWithSignature[]) => void | Promise<void>,
137-
progress: ProgressCallback,
138-
token: CancellationToken,
139-
) {
140-
const generator = new FlowModelGenerator(
141-
cli,
142-
queryRunner,
143-
queryStorageDir,
144-
qlDir,
145-
databaseItem,
146-
progress,
147-
token,
122+
const sourceResults = await getModeledMethodsFromFlow(
123+
"source",
124+
"CaptureSourceModels.ql",
125+
2,
126+
options,
148127
);
128+
if (sourceResults) {
129+
await onResults(sourceResults);
130+
}
149131

150-
return generator.run(onResults);
132+
const neutralResults = await getModeledMethodsFromFlow(
133+
"neutral",
134+
"CaptureNeutralModels.ql",
135+
3,
136+
options,
137+
);
138+
if (neutralResults) {
139+
await onResults(neutralResults);
140+
}
151141
}

0 commit comments

Comments
 (0)