Skip to content

Commit b763693

Browse files
committed
Convert remaining extension host code to handle multiple models
This converts all remaining extension host code to handle multiple models per method. The only place where we're using the legacy format is in the webview and in the boundary between the webview and the extension host.
1 parent 603c799 commit b763693

File tree

12 files changed

+179
-84
lines changed

12 files changed

+179
-84
lines changed

extensions/ql-vscode/src/model-editor/auto-model.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,13 @@ import { groupMethods, sortGroupNames, sortMethods } from "./shared/sorting";
1414
* the order in the UI.
1515
* @param mode Whether it is application or framework mode.
1616
* @param methods all methods.
17-
* @param modeledMethods the currently modeled methods.
17+
* @param modeledMethodsBySignature the currently modeled methods.
1818
* @returns list of modeled methods that are candidates for modeling.
1919
*/
2020
export function getCandidates(
2121
mode: Mode,
2222
methods: Method[],
23-
modeledMethods: Record<string, ModeledMethod>,
23+
modeledMethodsBySignature: Record<string, ModeledMethod[]>,
2424
): MethodSignature[] {
2525
// Sort the same way as the UI so we send the first ones listed in the UI first
2626
const grouped = groupMethods(methods, mode);
@@ -32,12 +32,11 @@ export function getCandidates(
3232
const candidates: MethodSignature[] = [];
3333

3434
for (const method of sortedMethods) {
35-
const modeledMethod: ModeledMethod = modeledMethods[method.signature] ?? {
36-
type: "none",
37-
};
35+
const modeledMethods: ModeledMethod[] =
36+
modeledMethodsBySignature[method.signature] ?? [];
3837

3938
// Anything that is modeled is not a candidate
40-
if (modeledMethod.type !== "none") {
39+
if (modeledMethods.some((m) => m.type !== "none")) {
4140
continue;
4241
}
4342

extensions/ql-vscode/src/model-editor/auto-modeler.ts

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ import { QueryRunner } from "../query-server";
1616
import { DatabaseItem } from "../databases/local-databases";
1717
import { Mode } from "./shared/mode";
1818
import { CancellationTokenSource } from "vscode";
19-
import { convertToLegacyModeledMethods } from "./modeled-methods-legacy";
2019

2120
// Limit the number of candidates we send to the model in each request
2221
// to avoid long requests.
@@ -43,7 +42,7 @@ export class AutoModeler {
4342
inProgressMethods: string[],
4443
) => Promise<void>,
4544
private readonly addModeledMethods: (
46-
modeledMethods: Record<string, ModeledMethod>,
45+
modeledMethods: Record<string, ModeledMethod[]>,
4746
) => Promise<void>,
4847
) {
4948
this.jobs = new Map<string, CancellationTokenSource>();
@@ -60,7 +59,7 @@ export class AutoModeler {
6059
public async startModeling(
6160
packageName: string,
6261
methods: Method[],
63-
modeledMethods: Record<string, ModeledMethod>,
62+
modeledMethods: Record<string, ModeledMethod[]>,
6463
mode: Mode,
6564
): Promise<void> {
6665
if (this.jobs.has(packageName)) {
@@ -107,7 +106,7 @@ export class AutoModeler {
107106
private async modelPackage(
108107
packageName: string,
109108
methods: Method[],
110-
modeledMethods: Record<string, ModeledMethod>,
109+
modeledMethods: Record<string, ModeledMethod[]>,
111110
mode: Mode,
112111
cancellationTokenSource: CancellationTokenSource,
113112
): Promise<void> {
@@ -193,31 +192,31 @@ export class AutoModeler {
193192
filename: "auto-model.yml",
194193
});
195194

196-
const rawLoadedMethods = loadDataExtensionYaml(models);
197-
if (!rawLoadedMethods) {
195+
const loadedMethods = loadDataExtensionYaml(models);
196+
if (!loadedMethods) {
198197
return;
199198
}
200199

201-
const loadedMethods = convertToLegacyModeledMethods(rawLoadedMethods);
202-
203200
// Any candidate that was part of the response is a negative result
204201
// meaning that the canidate is not a sink for the kinds that the LLM is checking for.
205202
// For now we model this as a sink neutral method, however this is subject
206203
// to discussion.
207204
for (const candidate of candidateMethods) {
208205
if (!(candidate.signature in loadedMethods)) {
209-
loadedMethods[candidate.signature] = {
210-
type: "neutral",
211-
kind: "sink",
212-
input: "",
213-
output: "",
214-
provenance: "ai-generated",
215-
signature: candidate.signature,
216-
packageName: candidate.packageName,
217-
typeName: candidate.typeName,
218-
methodName: candidate.methodName,
219-
methodParameters: candidate.methodParameters,
220-
};
206+
loadedMethods[candidate.signature] = [
207+
{
208+
type: "neutral",
209+
kind: "sink",
210+
input: "",
211+
output: "",
212+
provenance: "ai-generated",
213+
signature: candidate.signature,
214+
packageName: candidate.packageName,
215+
typeName: candidate.typeName,
216+
methodName: candidate.methodName,
217+
methodParameters: candidate.methodParameters,
218+
},
219+
];
221220
}
222221
}
223222

extensions/ql-vscode/src/model-editor/method-modeling/method-modeling-view-provider.ts

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ import { AbstractWebviewViewProvider } from "../../common/vscode/abstract-webvie
1313
import { assertNever } from "../../common/helpers-pure";
1414
import { ModelEditorViewTracker } from "../model-editor-view-tracker";
1515
import { showMultipleModels } from "../../config";
16+
import {
17+
convertFromLegacyModeledMethod,
18+
convertToLegacyModeledMethod,
19+
} from "../modeled-methods-legacy";
1620

1721
export class MethodModelingViewProvider extends AbstractWebviewViewProvider<
1822
ToMethodModelingMessage,
@@ -62,7 +66,9 @@ export class MethodModelingViewProvider extends AbstractWebviewViewProvider<
6266
await this.postMessage({
6367
t: "setSelectedMethod",
6468
method: selectedMethod.method,
65-
modeledMethod: selectedMethod.modeledMethod,
69+
modeledMethod: convertToLegacyModeledMethod(
70+
selectedMethod.modeledMethods,
71+
),
6672
isModified: selectedMethod.isModified,
6773
});
6874
}
@@ -94,9 +100,10 @@ export class MethodModelingViewProvider extends AbstractWebviewViewProvider<
94100
case "setModeledMethod": {
95101
const activeState = this.ensureActiveState();
96102

97-
this.modelingStore.updateModeledMethod(
103+
this.modelingStore.updateModeledMethods(
98104
activeState.databaseItem,
99-
msg.method,
105+
msg.method.signature,
106+
convertFromLegacyModeledMethod(msg.method),
100107
);
101108
break;
102109
}
@@ -141,11 +148,11 @@ export class MethodModelingViewProvider extends AbstractWebviewViewProvider<
141148
this.push(
142149
this.modelingStore.onModeledMethodsChanged(async (e) => {
143150
if (this.webviewView && e.isActiveDb) {
144-
const modeledMethod = e.modeledMethods[this.method?.signature ?? ""];
145-
if (modeledMethod) {
151+
const modeledMethods = e.modeledMethods[this.method?.signature ?? ""];
152+
if (modeledMethods) {
146153
await this.postMessage({
147154
t: "setModeledMethod",
148-
method: modeledMethod,
155+
method: convertToLegacyModeledMethod(modeledMethods),
149156
});
150157
}
151158
}
@@ -171,7 +178,7 @@ export class MethodModelingViewProvider extends AbstractWebviewViewProvider<
171178
await this.postMessage({
172179
t: "setSelectedMethod",
173180
method: e.method,
174-
modeledMethod: e.modeledMethod,
181+
modeledMethod: convertToLegacyModeledMethod(e.modeledMethods),
175182
isModified: e.isModified,
176183
});
177184
}

extensions/ql-vscode/src/model-editor/methods-usage/methods-usage-data-provider.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import { DatabaseItem } from "../../databases/local-databases";
1414
import { relative } from "path";
1515
import { CodeQLCliServer } from "../../codeql-cli/cli";
1616
import { INITIAL_HIDE_MODELED_METHODS_VALUE } from "../shared/hide-modeled-methods";
17-
import { getModelingStatus } from "../shared/modeling-status";
17+
import { getModelingStatusForModeledMethods } from "../shared/modeling-status";
1818
import { assertNever } from "../../common/helpers-pure";
1919
import { ModeledMethod } from "../modeled-method";
2020

@@ -26,7 +26,7 @@ export class MethodsUsageDataProvider
2626
private databaseItem: DatabaseItem | undefined = undefined;
2727
private sourceLocationPrefix: string | undefined = undefined;
2828
private hideModeledMethods: boolean = INITIAL_HIDE_MODELED_METHODS_VALUE;
29-
private modeledMethods: Record<string, ModeledMethod> = {};
29+
private modeledMethods: Record<string, ModeledMethod[]> = {};
3030
private modifiedMethodSignatures: Set<string> = new Set();
3131

3232
private readonly onDidChangeTreeDataEmitter = this.push(
@@ -52,7 +52,7 @@ export class MethodsUsageDataProvider
5252
methods: Method[],
5353
databaseItem: DatabaseItem,
5454
hideModeledMethods: boolean,
55-
modeledMethods: Record<string, ModeledMethod>,
55+
modeledMethods: Record<string, ModeledMethod[]>,
5656
modifiedMethodSignatures: Set<string>,
5757
): Promise<void> {
5858
if (
@@ -99,10 +99,13 @@ export class MethodsUsageDataProvider
9999
}
100100

101101
private getModelingStatusIcon(method: Method): ThemeIcon {
102-
const modeledMethod = this.modeledMethods[method.signature];
102+
const modeledMethods = this.modeledMethods[method.signature];
103103
const modifiedMethod = this.modifiedMethodSignatures.has(method.signature);
104104

105-
const status = getModelingStatus(modeledMethod, modifiedMethod);
105+
const status = getModelingStatusForModeledMethods(
106+
modeledMethods,
107+
modifiedMethod,
108+
);
106109
switch (status) {
107110
case "unmodeled":
108111
return new ThemeIcon("error", new ThemeColor("errorForeground"));

extensions/ql-vscode/src/model-editor/methods-usage/methods-usage-panel.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ export class MethodsUsagePanel extends DisposableObject {
3434
methods: Method[],
3535
databaseItem: DatabaseItem,
3636
hideModeledMethods: boolean,
37-
modeledMethods: Record<string, ModeledMethod>,
37+
modeledMethods: Record<string, ModeledMethod[]>,
3838
modifiedMethodSignatures: Set<string>,
3939
): Promise<void> {
4040
await this.dataProvider.setState(

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

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ import { telemetryListener } from "../common/vscode/telemetry";
4848
import { ModelingStore } from "./modeling-store";
4949
import { ModelEditorViewTracker } from "./model-editor-view-tracker";
5050
import {
51+
convertFromLegacyModeledMethod,
5152
convertFromLegacyModeledMethods,
5253
convertToLegacyModeledMethods,
5354
} from "./modeled-methods-legacy";
@@ -259,7 +260,7 @@ export class ModelEditorView extends AbstractWebview<
259260
await this.generateModeledMethodsFromLlm(
260261
msg.packageName,
261262
msg.methods,
262-
msg.modeledMethods,
263+
convertFromLegacyModeledMethods(msg.modeledMethods),
263264
);
264265
void telemetryListener?.sendUIInteraction(
265266
"model-editor-generate-methods-from-llm",
@@ -303,7 +304,10 @@ export class ModelEditorView extends AbstractWebview<
303304
);
304305
break;
305306
case "setModeledMethod": {
306-
this.setModeledMethod(msg.method);
307+
this.setModeledMethods(
308+
msg.method.signature,
309+
convertFromLegacyModeledMethod(msg.method),
310+
);
307311
break;
308312
}
309313
default:
@@ -363,10 +367,7 @@ export class ModelEditorView extends AbstractWebview<
363367
this.cliServer,
364368
this.app.logger,
365369
);
366-
this.modelingStore.setModeledMethods(
367-
this.databaseItem,
368-
convertToLegacyModeledMethods(modeledMethods),
369-
);
370+
this.modelingStore.setModeledMethods(this.databaseItem, modeledMethods);
370371
} catch (e: unknown) {
371372
void showAndLogErrorMessage(
372373
this.app.logger,
@@ -438,10 +439,16 @@ export class ModelEditorView extends AbstractWebview<
438439
queryStorageDir: this.queryStorageDir,
439440
databaseItem: addedDatabase ?? this.databaseItem,
440441
onResults: async (modeledMethods) => {
441-
const modeledMethodsByName: Record<string, ModeledMethod> = {};
442+
const modeledMethodsByName: Record<string, ModeledMethod[]> = {};
442443

443444
for (const modeledMethod of modeledMethods) {
444-
modeledMethodsByName[modeledMethod.signature] = modeledMethod;
445+
if (!(modeledMethod.signature in modeledMethodsByName)) {
446+
modeledMethodsByName[modeledMethod.signature] = [];
447+
}
448+
449+
modeledMethodsByName[modeledMethod.signature].push(
450+
modeledMethod,
451+
);
445452
}
446453

447454
this.addModeledMethods(modeledMethodsByName);
@@ -466,7 +473,7 @@ export class ModelEditorView extends AbstractWebview<
466473
private async generateModeledMethodsFromLlm(
467474
packageName: string,
468475
methods: Method[],
469-
modeledMethods: Record<string, ModeledMethod>,
476+
modeledMethods: Record<string, ModeledMethod[]>,
470477
): Promise<void> {
471478
await this.autoModeler.startModeling(
472479
packageName,
@@ -603,7 +610,7 @@ export class ModelEditorView extends AbstractWebview<
603610
if (event.dbUri === this.databaseItem.databaseUri.toString()) {
604611
await this.postMessage({
605612
t: "setModeledMethods",
606-
methods: event.modeledMethods,
613+
methods: convertToLegacyModeledMethods(event.modeledMethods),
607614
});
608615
}
609616
}),
@@ -621,7 +628,7 @@ export class ModelEditorView extends AbstractWebview<
621628
);
622629
}
623630

624-
private addModeledMethods(modeledMethods: Record<string, ModeledMethod>) {
631+
private addModeledMethods(modeledMethods: Record<string, ModeledMethod[]>) {
625632
this.modelingStore.addModeledMethods(this.databaseItem, modeledMethods);
626633

627634
this.modelingStore.addModifiedMethods(
@@ -630,13 +637,17 @@ export class ModelEditorView extends AbstractWebview<
630637
);
631638
}
632639

633-
private setModeledMethod(method: ModeledMethod) {
640+
private setModeledMethods(signature: string, methods: ModeledMethod[]) {
634641
const state = this.modelingStore.getStateForActiveDb();
635642
if (!state) {
636643
throw new Error("Attempting to set modeled method without active db");
637644
}
638645

639-
this.modelingStore.updateModeledMethod(state.databaseItem, method);
640-
this.modelingStore.addModifiedMethod(state.databaseItem, method.signature);
646+
this.modelingStore.updateModeledMethods(
647+
state.databaseItem,
648+
signature,
649+
methods,
650+
);
651+
this.modelingStore.addModifiedMethod(state.databaseItem, signature);
641652
}
642653
}

0 commit comments

Comments
 (0)