Skip to content

Commit a0fb3b4

Browse files
committed
Merge remote-tracking branch 'origin/main' into koesie10/variant-analysis-results-manager
2 parents 902c489 + 86d10b4 commit a0fb3b4

File tree

11 files changed

+489
-209
lines changed

11 files changed

+489
-209
lines changed

extensions/ql-vscode/.storybook/preview.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,5 +33,6 @@ export const parameters = {
3333
};
3434

3535
(window as any).acquireVsCodeApi = () => ({
36-
postMessage: action('post-vscode-message')
36+
postMessage: action('post-vscode-message'),
37+
setState: action('set-vscode-state'),
3738
});

extensions/ql-vscode/package-lock.json

Lines changed: 7 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

extensions/ql-vscode/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
"onCommand:codeQL.quickQuery",
6464
"onCommand:codeQL.restartQueryServer",
6565
"onWebviewPanel:resultsView",
66+
"onWebviewPanel:codeQL.variantAnalysis",
6667
"onFileSystem:codeql-zip-archive"
6768
],
6869
"main": "./out/extension",
@@ -1207,7 +1208,7 @@
12071208
"dependencies": {
12081209
"@octokit/plugin-retry": "^3.0.9",
12091210
"@octokit/rest": "^19.0.4",
1210-
"@primer/octicons-react": "^16.3.0",
1211+
"@primer/octicons-react": "^17.6.0",
12111212
"@primer/react": "^35.0.0",
12121213
"@vscode/codicons": "^0.0.31",
12131214
"@vscode/webview-ui-toolkit": "^1.0.1",

extensions/ql-vscode/src/abstract-webview.ts

Lines changed: 38 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@ export abstract class AbstractWebview<ToMessage extends WebviewMessage, FromMess
3333
super();
3434
}
3535

36+
public async restoreView(panel: WebviewPanel): Promise<void> {
37+
this.panel = panel;
38+
this.setupPanel(panel);
39+
}
40+
3641
protected get isShowingPanel() {
3742
return !!this.panel;
3843
}
@@ -59,37 +64,43 @@ export abstract class AbstractWebview<ToMessage extends WebviewMessage, FromMess
5964
],
6065
}
6166
);
62-
this.push(
63-
this.panel.onDidDispose(
64-
() => {
65-
this.panel = undefined;
66-
this.panelLoaded = false;
67-
this.onPanelDispose();
68-
},
69-
null,
70-
ctx.subscriptions
71-
)
72-
);
73-
74-
this.panel.webview.html = getHtmlForWebview(
75-
ctx,
76-
this.panel.webview,
77-
config.view,
78-
{
79-
allowInlineStyles: true,
80-
}
81-
);
82-
this.push(
83-
this.panel.webview.onDidReceiveMessage(
84-
async (e) => this.onMessage(e),
85-
undefined,
86-
ctx.subscriptions
87-
)
88-
);
67+
this.setupPanel(this.panel);
8968
}
9069
return this.panel;
9170
}
9271

72+
protected setupPanel(panel: WebviewPanel): void {
73+
const config = this.getPanelConfig();
74+
75+
this.push(
76+
panel.onDidDispose(
77+
() => {
78+
this.panel = undefined;
79+
this.panelLoaded = false;
80+
this.onPanelDispose();
81+
},
82+
null,
83+
this.ctx.subscriptions
84+
)
85+
);
86+
87+
panel.webview.html = getHtmlForWebview(
88+
this.ctx,
89+
panel.webview,
90+
config.view,
91+
{
92+
allowInlineStyles: true,
93+
}
94+
);
95+
this.push(
96+
panel.webview.onDidReceiveMessage(
97+
async (e) => this.onMessage(e),
98+
undefined,
99+
this.ctx.subscriptions
100+
)
101+
);
102+
}
103+
93104
protected abstract getPanelConfig(): WebviewPanelConfig;
94105

95106
protected abstract onPanelDispose(): void;

extensions/ql-vscode/src/extension.ts

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@ import { LogScannerService } from './log-insights/log-scanner-service';
104104
import { createInitialQueryInfo } from './run-queries-shared';
105105
import { LegacyQueryRunner } from './legacy-query-server/legacyRunner';
106106
import { QueryRunner } from './queryRunner';
107+
import { VariantAnalysisView } from './remote-queries/variant-analysis-view';
108+
import { VariantAnalysisViewSerializer } from './remote-queries/variant-analysis-view-serializer';
107109
import { VariantAnalysis } from './remote-queries/shared/variant-analysis';
108110
import {
109111
VariantAnalysis as VariantAnalysisApiResponse,
@@ -176,6 +178,7 @@ export interface CodeQLExtensionInterface {
176178
readonly distributionManager: DistributionManager;
177179
readonly databaseManager: DatabaseManager;
178180
readonly databaseUI: DatabaseUI;
181+
readonly variantAnalysisManager: VariantAnalysisManager;
179182
readonly dispose: () => void;
180183
}
181184

@@ -386,14 +389,21 @@ export async function activate(ctx: ExtensionContext): Promise<CodeQLExtensionIn
386389
allowAutoUpdating: true
387390
})));
388391

389-
return await installOrUpdateThenTryActivate({
392+
const variantAnalysisViewSerializer = new VariantAnalysisViewSerializer(ctx);
393+
Window.registerWebviewPanelSerializer(VariantAnalysisView.viewType, variantAnalysisViewSerializer);
394+
395+
const codeQlExtension = await installOrUpdateThenTryActivate({
390396
isUserInitiated: !!ctx.globalState.get(shouldUpdateOnNextActivationKey),
391397
shouldDisplayMessageWhenNoUpdates: false,
392398

393399
// only auto update on startup if the user has previously requested an update
394400
// otherwise, ask user to accept the update
395401
allowAutoUpdating: !!ctx.globalState.get(shouldUpdateOnNextActivationKey)
396402
});
403+
404+
variantAnalysisViewSerializer.onExtensionLoaded(codeQlExtension.variantAnalysisManager);
405+
406+
return codeQlExtension;
397407
}
398408

399409
async function activateWithInstalledDistribution(
@@ -939,7 +949,10 @@ async function activateWithInstalledDistribution(
939949

940950
ctx.subscriptions.push(
941951
commandRunner('codeQL.mockVariantAnalysisView', async () => {
942-
await variantAnalysisManager.showView(1);
952+
// Generate a random variant analysis ID for testing
953+
const variantAnalysisId: number = Math.floor(Math.random() * 1000000);
954+
955+
await variantAnalysisManager.showView(variantAnalysisId);
943956
})
944957
);
945958

@@ -1164,6 +1177,7 @@ async function activateWithInstalledDistribution(
11641177
distributionManager,
11651178
databaseManager: dbm,
11661179
databaseUI,
1180+
variantAnalysisManager,
11671181
dispose: () => {
11681182
ctx.subscriptions.forEach(d => d.dispose());
11691183
}

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,15 @@ export interface SetVariantAnalysisMessage {
440440
variantAnalysis: VariantAnalysis;
441441
}
442442

443+
export type StopVariantAnalysisMessage = {
444+
t: 'stopVariantAnalysis';
445+
variantAnalysisId: number;
446+
}
447+
448+
export type VariantAnalysisState = {
449+
variantAnalysisId: number;
450+
}
451+
443452
export interface SetRepoResultsMessage {
444453
t: 'setRepoResults';
445454
repoResults: VariantAnalysisScannedRepositoryResult[];
@@ -456,4 +465,5 @@ export type ToVariantAnalysisMessage =
456465
| SetRepoStatesMessage;
457466

458467
export type FromVariantAnalysisMessage =
459-
| ViewLoadedMsg;
468+
| ViewLoadedMsg
469+
| StopVariantAnalysisMessage;
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import { ExtensionContext, WebviewPanel, WebviewPanelSerializer } from 'vscode';
2+
import { VariantAnalysisView } from './variant-analysis-view';
3+
import { VariantAnalysisState } from '../pure/interface-types';
4+
import { VariantAnalysisViewManager } from './variant-analysis-view-manager';
5+
6+
export class VariantAnalysisViewSerializer implements WebviewPanelSerializer {
7+
private resolvePromises: ((value: VariantAnalysisViewManager<VariantAnalysisView>) => void)[] = [];
8+
9+
private manager?: VariantAnalysisViewManager<VariantAnalysisView>;
10+
11+
public constructor(
12+
private readonly ctx: ExtensionContext,
13+
) { }
14+
15+
onExtensionLoaded(manager: VariantAnalysisViewManager<VariantAnalysisView>): void {
16+
this.manager = manager;
17+
18+
this.resolvePromises.forEach((resolve) => resolve(manager));
19+
this.resolvePromises = [];
20+
}
21+
22+
async deserializeWebviewPanel(webviewPanel: WebviewPanel, state: unknown): Promise<void> {
23+
if (!state || typeof state !== 'object') {
24+
return;
25+
}
26+
27+
if (!('variantAnalysisId' in state)) {
28+
return;
29+
}
30+
31+
const variantAnalysisState: VariantAnalysisState = state as VariantAnalysisState;
32+
33+
const manager = await this.waitForExtensionFullyLoaded();
34+
35+
const view = new VariantAnalysisView(this.ctx, variantAnalysisState.variantAnalysisId, manager);
36+
await view.restoreView(webviewPanel);
37+
}
38+
39+
private waitForExtensionFullyLoaded(): Promise<VariantAnalysisViewManager<VariantAnalysisView>> {
40+
if (this.manager) {
41+
return Promise.resolve(this.manager);
42+
}
43+
44+
return new Promise<VariantAnalysisViewManager<VariantAnalysisView>>((resolve) => {
45+
this.resolvePromises.push(resolve);
46+
});
47+
}
48+
}

0 commit comments

Comments
 (0)