Skip to content

Commit 79d4e8c

Browse files
authored
Wire up variant analysis updates to Model Alerts view (#3485)
1 parent 752ec04 commit 79d4e8c

File tree

5 files changed

+149
-24
lines changed

5 files changed

+149
-24
lines changed

extensions/ql-vscode/src/common/interface-types.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -739,7 +739,9 @@ interface OpenModelPackMessage {
739739

740740
export type ToModelAlertsMessage =
741741
| SetModelAlertsViewStateMessage
742-
| SetVariantAnalysisMessage;
742+
| SetVariantAnalysisMessage
743+
| SetRepoResultsMessage
744+
| SetRepoStatesMessage;
743745

744746
export type FromModelAlertsMessage =
745747
| CommonFromViewMessages

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

Lines changed: 45 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,11 @@ import type { ModelingEvents } from "../modeling-events";
1515
import type { ModelingStore } from "../modeling-store";
1616
import type { DatabaseItem } from "../../databases/local-databases";
1717
import type { ExtensionPack } from "../shared/extension-pack";
18-
import type { VariantAnalysis } from "../../variant-analysis/shared/variant-analysis";
18+
import type {
19+
VariantAnalysis,
20+
VariantAnalysisScannedRepositoryResult,
21+
VariantAnalysisScannedRepositoryState,
22+
} from "../../variant-analysis/shared/variant-analysis";
1923

2024
export class ModelAlertsView extends AbstractWebview<
2125
ToModelAlertsMessage,
@@ -35,17 +39,12 @@ export class ModelAlertsView extends AbstractWebview<
3539
this.registerToModelingEvents();
3640
}
3741

38-
public async showView(variantAnalysis: VariantAnalysis) {
42+
public async showView() {
3943
const panel = await this.getPanel();
4044
panel.reveal(undefined, true);
4145

4246
await this.waitForPanelLoaded();
4347
await this.setViewState();
44-
45-
await this.postMessage({
46-
t: "setVariantAnalysis",
47-
variantAnalysis,
48-
});
4948
}
5049

5150
protected async getPanelConfig(): Promise<WebviewPanelConfig> {
@@ -96,6 +95,45 @@ export class ModelAlertsView extends AbstractWebview<
9695
});
9796
}
9897

98+
public async updateVariantAnalysis(
99+
variantAnalysis: VariantAnalysis,
100+
): Promise<void> {
101+
if (!this.isShowingPanel) {
102+
return;
103+
}
104+
105+
await this.postMessage({
106+
t: "setVariantAnalysis",
107+
variantAnalysis,
108+
});
109+
}
110+
111+
public async updateRepoState(
112+
repoState: VariantAnalysisScannedRepositoryState,
113+
): Promise<void> {
114+
if (!this.isShowingPanel) {
115+
return;
116+
}
117+
118+
await this.postMessage({
119+
t: "setRepoStates",
120+
repoStates: [repoState],
121+
});
122+
}
123+
124+
public async updateRepoResults(
125+
repositoryResult: VariantAnalysisScannedRepositoryResult,
126+
): Promise<void> {
127+
if (!this.isShowingPanel) {
128+
return;
129+
}
130+
131+
await this.postMessage({
132+
t: "setRepoResults",
133+
repoResults: [repositoryResult],
134+
});
135+
}
136+
99137
public async focusView(): Promise<void> {
100138
this.panel?.reveal();
101139
}

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

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ export class ModelEvaluator extends DisposableObject {
2727
// submitted, we use the variant analysis manager's cancellation support.
2828
private cancellationSource: CancellationTokenSource;
2929

30+
private modelAlertsView: ModelAlertsView | undefined;
31+
3032
public constructor(
3133
private readonly app: App,
3234
private readonly cliServer: CodeQLCliServer,
@@ -36,7 +38,7 @@ export class ModelEvaluator extends DisposableObject {
3638
private readonly dbItem: DatabaseItem,
3739
private readonly language: QueryLanguage,
3840
private readonly extensionPack: ExtensionPack,
39-
private readonly updateView: (
41+
private readonly updateModelEditorView: (
4042
run: ModelEvaluationRunState,
4143
) => Promise<void>,
4244
) {
@@ -117,18 +119,17 @@ export class ModelEvaluator extends DisposableObject {
117119
return;
118120
} else {
119121
this.modelingStore.updateIsModelAlertsViewOpen(this.dbItem, true);
120-
const view = new ModelAlertsView(
122+
this.modelAlertsView = new ModelAlertsView(
121123
this.app,
122124
this.modelingEvents,
123125
this.modelingStore,
124126
this.dbItem,
125127
this.extensionPack,
126128
);
129+
await this.modelAlertsView.showView();
127130

128131
// There should be a variant analysis available at this point, as the
129-
// view can only opened when the variant analysis is complete. So we
130-
// send this to the view. This is temporary until we have logic to
131-
// listen to variant analysis updates and update the view accordingly.
132+
// view can only opened when the variant analysis is submitted.
132133
const evaluationRun = this.modelingStore.getModelEvaluationRun(
133134
this.dbItem,
134135
);
@@ -143,7 +144,7 @@ export class ModelEvaluator extends DisposableObject {
143144
throw new Error("No variant analysis available");
144145
}
145146

146-
await view.showView(variantAnalysis);
147+
await this.modelAlertsView.updateVariantAnalysis(variantAnalysis);
147148
}
148149
}
149150

@@ -152,7 +153,7 @@ export class ModelEvaluator extends DisposableObject {
152153
this.modelingEvents.onModelEvaluationRunChanged(async (event) => {
153154
if (event.dbUri === this.dbItem.databaseUri.toString()) {
154155
if (!event.evaluationRun) {
155-
await this.updateView({
156+
await this.updateModelEditorView({
156157
isPreparing: false,
157158
variantAnalysis: undefined,
158159
});
@@ -164,7 +165,7 @@ export class ModelEvaluator extends DisposableObject {
164165
isPreparing: event.evaluationRun.isPreparing,
165166
variantAnalysis,
166167
};
167-
await this.updateView(run);
168+
await this.updateModelEditorView(run);
168169
}
169170
}
170171
}),
@@ -241,14 +242,34 @@ export class ModelEvaluator extends DisposableObject {
241242
this.variantAnalysisManager.onVariantAnalysisStatusUpdated(
242243
async (variantAnalysis) => {
243244
// Make sure it's the variant analysis we're interested in
244-
if (variantAnalysisId === variantAnalysis.id) {
245-
await this.updateView({
245+
if (variantAnalysis.id === variantAnalysisId) {
246+
// Update model editor view
247+
await this.updateModelEditorView({
246248
isPreparing: false,
247249
variantAnalysis,
248250
});
251+
252+
// Update model alerts view
253+
await this.modelAlertsView?.updateVariantAnalysis(variantAnalysis);
249254
}
250255
},
251256
),
252257
);
258+
259+
this.push(
260+
this.variantAnalysisManager.onRepoStatesUpdated(async (e) => {
261+
if (e.variantAnalysisId === variantAnalysisId) {
262+
await this.modelAlertsView?.updateRepoState(e.repoState);
263+
}
264+
}),
265+
);
266+
267+
this.push(
268+
this.variantAnalysisManager.onRepoResultsLoaded(async (e) => {
269+
if (e.variantAnalysisId === variantAnalysisId) {
270+
await this.modelAlertsView?.updateRepoResults(e);
271+
}
272+
}),
273+
);
253274
}
254275
}

extensions/ql-vscode/src/variant-analysis/variant-analysis-manager.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,21 @@ export class VariantAnalysisManager
122122
public readonly onVariantAnalysisRemoved =
123123
this._onVariantAnalysisRemoved.event;
124124

125+
private readonly _onRepoStateUpdated = this.push(
126+
new EventEmitter<{
127+
variantAnalysisId: number;
128+
repoState: VariantAnalysisScannedRepositoryState;
129+
}>(),
130+
);
131+
132+
public readonly onRepoStatesUpdated = this._onRepoStateUpdated.event;
133+
134+
private readonly _onRepoResultsLoaded = this.push(
135+
new EventEmitter<VariantAnalysisScannedRepositoryResult>(),
136+
);
137+
138+
public readonly onRepoResultsLoaded = this._onRepoResultsLoaded.event;
139+
125140
private readonly variantAnalysisMonitor: VariantAnalysisMonitor;
126141
private readonly variantAnalyses = new Map<number, VariantAnalysis>();
127142
private readonly views = new Map<number, VariantAnalysisView>();
@@ -685,6 +700,8 @@ export class VariantAnalysisManager
685700
await this.getView(
686701
repositoryResult.variantAnalysisId,
687702
)?.sendRepositoryResults([repositoryResult]);
703+
704+
this._onRepoResultsLoaded.fire(repositoryResult);
688705
}
689706

690707
private async onRepoStateUpdated(
@@ -700,6 +717,8 @@ export class VariantAnalysisManager
700717
}
701718

702719
repoStates[repoState.repositoryId] = repoState;
720+
721+
this._onRepoStateUpdated.fire({ variantAnalysisId, repoState });
703722
}
704723

705724
private async onDidChangeSessions(

extensions/ql-vscode/src/view/model-alerts/ModelAlerts.tsx

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,11 @@ import { useCallback, useEffect, useState } from "react";
22
import { ModelAlertsHeader } from "./ModelAlertsHeader";
33
import type { ModelAlertsViewState } from "../../model-editor/shared/view-state";
44
import type { ToModelAlertsMessage } from "../../common/interface-types";
5-
import type { VariantAnalysis } from "../../variant-analysis/shared/variant-analysis";
5+
import type {
6+
VariantAnalysis,
7+
VariantAnalysisScannedRepositoryResult,
8+
VariantAnalysisScannedRepositoryState,
9+
} from "../../variant-analysis/shared/variant-analysis";
610
import { vscode } from "../vscode-api";
711

812
type Props = {
@@ -24,6 +28,12 @@ export function ModelAlerts({ initialViewState }: Props): React.JSX.Element {
2428
const [variantAnalysis, setVariantAnalysis] = useState<
2529
VariantAnalysis | undefined
2630
>(undefined);
31+
const [repoStates, setRepoStates] = useState<
32+
VariantAnalysisScannedRepositoryState[]
33+
>([]);
34+
const [repoResults, setRepoResults] = useState<
35+
VariantAnalysisScannedRepositoryResult[]
36+
>([]);
2737

2838
useEffect(() => {
2939
const listener = (evt: MessageEvent) => {
@@ -36,6 +46,31 @@ export function ModelAlerts({ initialViewState }: Props): React.JSX.Element {
3646
}
3747
case "setVariantAnalysis": {
3848
setVariantAnalysis(msg.variantAnalysis);
49+
break;
50+
}
51+
case "setRepoStates": {
52+
setRepoStates((oldRepoStates) => {
53+
const newRepoIds = msg.repoStates.map((r) => r.repositoryId);
54+
return [
55+
...oldRepoStates.filter(
56+
(v) => !newRepoIds.includes(v.repositoryId),
57+
),
58+
...msg.repoStates,
59+
];
60+
});
61+
break;
62+
}
63+
case "setRepoResults": {
64+
setRepoResults((oldRepoResults) => {
65+
const newRepoIds = msg.repoResults.map((r) => r.repositoryId);
66+
return [
67+
...oldRepoResults.filter(
68+
(v) => !newRepoIds.includes(v.repositoryId),
69+
),
70+
...msg.repoResults,
71+
];
72+
});
73+
break;
3974
}
4075
}
4176
} else {
@@ -56,10 +91,20 @@ export function ModelAlerts({ initialViewState }: Props): React.JSX.Element {
5691
}
5792

5893
return (
59-
<ModelAlertsHeader
60-
viewState={viewState}
61-
variantAnalysis={variantAnalysis}
62-
openModelPackClick={onOpenModelPackClick}
63-
></ModelAlertsHeader>
94+
<>
95+
<ModelAlertsHeader
96+
viewState={viewState}
97+
variantAnalysis={variantAnalysis}
98+
openModelPackClick={onOpenModelPackClick}
99+
></ModelAlertsHeader>
100+
<div>
101+
<h3>Repo states</h3>
102+
<p>{JSON.stringify(repoStates, null, 2)}</p>
103+
</div>
104+
<div>
105+
<h3>Repo results</h3>
106+
<p>{JSON.stringify(repoResults, null, 2)}</p>
107+
</div>
108+
</>
64109
);
65110
}

0 commit comments

Comments
 (0)