Wire up variant analysis updates to Model Alerts view (#3485)

This commit is contained in:
Charis Kyriakou
2024-03-18 11:35:45 +00:00
committed by GitHub
parent 752ec04400
commit 79d4e8cb78
5 changed files with 149 additions and 24 deletions

View File

@@ -739,7 +739,9 @@ interface OpenModelPackMessage {
export type ToModelAlertsMessage =
| SetModelAlertsViewStateMessage
| SetVariantAnalysisMessage;
| SetVariantAnalysisMessage
| SetRepoResultsMessage
| SetRepoStatesMessage;
export type FromModelAlertsMessage =
| CommonFromViewMessages

View File

@@ -15,7 +15,11 @@ import type { ModelingEvents } from "../modeling-events";
import type { ModelingStore } from "../modeling-store";
import type { DatabaseItem } from "../../databases/local-databases";
import type { ExtensionPack } from "../shared/extension-pack";
import type { VariantAnalysis } from "../../variant-analysis/shared/variant-analysis";
import type {
VariantAnalysis,
VariantAnalysisScannedRepositoryResult,
VariantAnalysisScannedRepositoryState,
} from "../../variant-analysis/shared/variant-analysis";
export class ModelAlertsView extends AbstractWebview<
ToModelAlertsMessage,
@@ -35,17 +39,12 @@ export class ModelAlertsView extends AbstractWebview<
this.registerToModelingEvents();
}
public async showView(variantAnalysis: VariantAnalysis) {
public async showView() {
const panel = await this.getPanel();
panel.reveal(undefined, true);
await this.waitForPanelLoaded();
await this.setViewState();
await this.postMessage({
t: "setVariantAnalysis",
variantAnalysis,
});
}
protected async getPanelConfig(): Promise<WebviewPanelConfig> {
@@ -96,6 +95,45 @@ export class ModelAlertsView extends AbstractWebview<
});
}
public async updateVariantAnalysis(
variantAnalysis: VariantAnalysis,
): Promise<void> {
if (!this.isShowingPanel) {
return;
}
await this.postMessage({
t: "setVariantAnalysis",
variantAnalysis,
});
}
public async updateRepoState(
repoState: VariantAnalysisScannedRepositoryState,
): Promise<void> {
if (!this.isShowingPanel) {
return;
}
await this.postMessage({
t: "setRepoStates",
repoStates: [repoState],
});
}
public async updateRepoResults(
repositoryResult: VariantAnalysisScannedRepositoryResult,
): Promise<void> {
if (!this.isShowingPanel) {
return;
}
await this.postMessage({
t: "setRepoResults",
repoResults: [repositoryResult],
});
}
public async focusView(): Promise<void> {
this.panel?.reveal();
}

View File

@@ -27,6 +27,8 @@ export class ModelEvaluator extends DisposableObject {
// submitted, we use the variant analysis manager's cancellation support.
private cancellationSource: CancellationTokenSource;
private modelAlertsView: ModelAlertsView | undefined;
public constructor(
private readonly app: App,
private readonly cliServer: CodeQLCliServer,
@@ -36,7 +38,7 @@ export class ModelEvaluator extends DisposableObject {
private readonly dbItem: DatabaseItem,
private readonly language: QueryLanguage,
private readonly extensionPack: ExtensionPack,
private readonly updateView: (
private readonly updateModelEditorView: (
run: ModelEvaluationRunState,
) => Promise<void>,
) {
@@ -117,18 +119,17 @@ export class ModelEvaluator extends DisposableObject {
return;
} else {
this.modelingStore.updateIsModelAlertsViewOpen(this.dbItem, true);
const view = new ModelAlertsView(
this.modelAlertsView = new ModelAlertsView(
this.app,
this.modelingEvents,
this.modelingStore,
this.dbItem,
this.extensionPack,
);
await this.modelAlertsView.showView();
// There should be a variant analysis available at this point, as the
// view can only opened when the variant analysis is complete. So we
// send this to the view. This is temporary until we have logic to
// listen to variant analysis updates and update the view accordingly.
// view can only opened when the variant analysis is submitted.
const evaluationRun = this.modelingStore.getModelEvaluationRun(
this.dbItem,
);
@@ -143,7 +144,7 @@ export class ModelEvaluator extends DisposableObject {
throw new Error("No variant analysis available");
}
await view.showView(variantAnalysis);
await this.modelAlertsView.updateVariantAnalysis(variantAnalysis);
}
}
@@ -152,7 +153,7 @@ export class ModelEvaluator extends DisposableObject {
this.modelingEvents.onModelEvaluationRunChanged(async (event) => {
if (event.dbUri === this.dbItem.databaseUri.toString()) {
if (!event.evaluationRun) {
await this.updateView({
await this.updateModelEditorView({
isPreparing: false,
variantAnalysis: undefined,
});
@@ -164,7 +165,7 @@ export class ModelEvaluator extends DisposableObject {
isPreparing: event.evaluationRun.isPreparing,
variantAnalysis,
};
await this.updateView(run);
await this.updateModelEditorView(run);
}
}
}),
@@ -241,14 +242,34 @@ export class ModelEvaluator extends DisposableObject {
this.variantAnalysisManager.onVariantAnalysisStatusUpdated(
async (variantAnalysis) => {
// Make sure it's the variant analysis we're interested in
if (variantAnalysisId === variantAnalysis.id) {
await this.updateView({
if (variantAnalysis.id === variantAnalysisId) {
// Update model editor view
await this.updateModelEditorView({
isPreparing: false,
variantAnalysis,
});
// Update model alerts view
await this.modelAlertsView?.updateVariantAnalysis(variantAnalysis);
}
},
),
);
this.push(
this.variantAnalysisManager.onRepoStatesUpdated(async (e) => {
if (e.variantAnalysisId === variantAnalysisId) {
await this.modelAlertsView?.updateRepoState(e.repoState);
}
}),
);
this.push(
this.variantAnalysisManager.onRepoResultsLoaded(async (e) => {
if (e.variantAnalysisId === variantAnalysisId) {
await this.modelAlertsView?.updateRepoResults(e);
}
}),
);
}
}

View File

@@ -122,6 +122,21 @@ export class VariantAnalysisManager
public readonly onVariantAnalysisRemoved =
this._onVariantAnalysisRemoved.event;
private readonly _onRepoStateUpdated = this.push(
new EventEmitter<{
variantAnalysisId: number;
repoState: VariantAnalysisScannedRepositoryState;
}>(),
);
public readonly onRepoStatesUpdated = this._onRepoStateUpdated.event;
private readonly _onRepoResultsLoaded = this.push(
new EventEmitter<VariantAnalysisScannedRepositoryResult>(),
);
public readonly onRepoResultsLoaded = this._onRepoResultsLoaded.event;
private readonly variantAnalysisMonitor: VariantAnalysisMonitor;
private readonly variantAnalyses = new Map<number, VariantAnalysis>();
private readonly views = new Map<number, VariantAnalysisView>();
@@ -685,6 +700,8 @@ export class VariantAnalysisManager
await this.getView(
repositoryResult.variantAnalysisId,
)?.sendRepositoryResults([repositoryResult]);
this._onRepoResultsLoaded.fire(repositoryResult);
}
private async onRepoStateUpdated(
@@ -700,6 +717,8 @@ export class VariantAnalysisManager
}
repoStates[repoState.repositoryId] = repoState;
this._onRepoStateUpdated.fire({ variantAnalysisId, repoState });
}
private async onDidChangeSessions(

View File

@@ -2,7 +2,11 @@ import { useCallback, useEffect, useState } from "react";
import { ModelAlertsHeader } from "./ModelAlertsHeader";
import type { ModelAlertsViewState } from "../../model-editor/shared/view-state";
import type { ToModelAlertsMessage } from "../../common/interface-types";
import type { VariantAnalysis } from "../../variant-analysis/shared/variant-analysis";
import type {
VariantAnalysis,
VariantAnalysisScannedRepositoryResult,
VariantAnalysisScannedRepositoryState,
} from "../../variant-analysis/shared/variant-analysis";
import { vscode } from "../vscode-api";
type Props = {
@@ -24,6 +28,12 @@ export function ModelAlerts({ initialViewState }: Props): React.JSX.Element {
const [variantAnalysis, setVariantAnalysis] = useState<
VariantAnalysis | undefined
>(undefined);
const [repoStates, setRepoStates] = useState<
VariantAnalysisScannedRepositoryState[]
>([]);
const [repoResults, setRepoResults] = useState<
VariantAnalysisScannedRepositoryResult[]
>([]);
useEffect(() => {
const listener = (evt: MessageEvent) => {
@@ -36,6 +46,31 @@ export function ModelAlerts({ initialViewState }: Props): React.JSX.Element {
}
case "setVariantAnalysis": {
setVariantAnalysis(msg.variantAnalysis);
break;
}
case "setRepoStates": {
setRepoStates((oldRepoStates) => {
const newRepoIds = msg.repoStates.map((r) => r.repositoryId);
return [
...oldRepoStates.filter(
(v) => !newRepoIds.includes(v.repositoryId),
),
...msg.repoStates,
];
});
break;
}
case "setRepoResults": {
setRepoResults((oldRepoResults) => {
const newRepoIds = msg.repoResults.map((r) => r.repositoryId);
return [
...oldRepoResults.filter(
(v) => !newRepoIds.includes(v.repositoryId),
),
...msg.repoResults,
];
});
break;
}
}
} else {
@@ -56,10 +91,20 @@ export function ModelAlerts({ initialViewState }: Props): React.JSX.Element {
}
return (
<ModelAlertsHeader
viewState={viewState}
variantAnalysis={variantAnalysis}
openModelPackClick={onOpenModelPackClick}
></ModelAlertsHeader>
<>
<ModelAlertsHeader
viewState={viewState}
variantAnalysis={variantAnalysis}
openModelPackClick={onOpenModelPackClick}
></ModelAlertsHeader>
<div>
<h3>Repo states</h3>
<p>{JSON.stringify(repoStates, null, 2)}</p>
</div>
<div>
<h3>Repo results</h3>
<p>{JSON.stringify(repoResults, null, 2)}</p>
</div>
</>
);
}