Skip to content

Commit 625b3a5

Browse files
authored
Merge branch 'main' into aeisenberg/multi-token
2 parents 0fa3cf5 + 558b932 commit 625b3a5

File tree

11 files changed

+264
-115
lines changed

11 files changed

+264
-115
lines changed

extensions/ql-vscode/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
## [UNRELEASED]
44

55
- Fix a bug where the query to Find Definitions in database source files would not be cancelled appropriately. [#2885](https://github.com/github/vscode-codeql/pull/2885)
6+
- Fix a bug where the query server was restarted twice after configuration changes. [#2884](https://github.com/github/vscode-codeql/pull/2884).
67

78
## 1.9.1 - 29 September 2023
89

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -598,8 +598,7 @@ export type FromModelEditorMessage =
598598
| SetModeledMethodMessage;
599599

600600
export type FromMethodModelingMessage =
601-
| TelemetryMessage
602-
| UnhandledErrorMessage
601+
| CommonFromViewMessages
603602
| SetModeledMethodMessage;
604603

605604
interface SetMethodMessage {
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import * as vscode from "vscode";
2+
import { Uri, WebviewViewProvider } from "vscode";
3+
import { WebviewKind, WebviewMessage, getHtmlForWebview } from "./webview-html";
4+
import { Disposable } from "../disposable-object";
5+
import { App } from "../app";
6+
7+
export abstract class AbstractWebviewViewProvider<
8+
ToMessage extends WebviewMessage,
9+
FromMessage extends WebviewMessage,
10+
> implements WebviewViewProvider
11+
{
12+
protected webviewView: vscode.WebviewView | undefined = undefined;
13+
private disposables: Disposable[] = [];
14+
15+
constructor(
16+
private readonly app: App,
17+
private readonly webviewKind: WebviewKind,
18+
) {}
19+
20+
/**
21+
* This is called when a view first becomes visible. This may happen when the view is
22+
* first loaded or when the user hides and then shows a view again.
23+
*/
24+
public resolveWebviewView(
25+
webviewView: vscode.WebviewView,
26+
_context: vscode.WebviewViewResolveContext,
27+
_token: vscode.CancellationToken,
28+
) {
29+
webviewView.webview.options = {
30+
enableScripts: true,
31+
localResourceRoots: [Uri.file(this.app.extensionPath)],
32+
};
33+
34+
const html = getHtmlForWebview(
35+
this.app,
36+
webviewView.webview,
37+
this.webviewKind,
38+
{
39+
allowInlineStyles: true,
40+
allowWasmEval: false,
41+
},
42+
);
43+
44+
webviewView.webview.html = html;
45+
46+
this.webviewView = webviewView;
47+
48+
webviewView.webview.onDidReceiveMessage(async (msg) => this.onMessage(msg));
49+
webviewView.onDidDispose(() => this.dispose());
50+
}
51+
52+
protected get isShowingView() {
53+
return this.webviewView?.visible ?? false;
54+
}
55+
56+
protected async postMessage(msg: ToMessage): Promise<void> {
57+
await this.webviewView?.webview.postMessage(msg);
58+
}
59+
60+
protected dispose() {
61+
while (this.disposables.length > 0) {
62+
const disposable = this.disposables.pop()!;
63+
disposable.dispose();
64+
}
65+
66+
this.webviewView = undefined;
67+
}
68+
69+
protected push<T extends Disposable>(obj: T): T {
70+
if (obj !== undefined) {
71+
this.disposables.push(obj);
72+
}
73+
return obj;
74+
}
75+
76+
protected abstract onMessage(msg: FromMessage): Promise<void>;
77+
78+
/**
79+
* This is called when a view first becomes visible. This may happen when the view is
80+
* first loaded or when the user hides and then shows a view again.
81+
*/
82+
protected onWebViewLoaded(): void {
83+
// Do nothing by default.
84+
}
85+
}

extensions/ql-vscode/src/extension.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -790,7 +790,7 @@ async function activateWithInstalledDistribution(
790790
);
791791
ctx.subscriptions.push(databaseUI);
792792

793-
QueriesModule.initialize(app, cliServer);
793+
QueriesModule.initialize(app, languageContext, cliServer);
794794

795795
void extLogger.log("Initializing evaluator log viewer.");
796796
const evalLogViewer = new EvalLogViewer();

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ export class MethodModelingPanel extends DisposableObject {
1212
super();
1313

1414
this.provider = new MethodModelingViewProvider(app, modelingStore);
15-
this.push(this.provider);
1615
this.push(
1716
window.registerWebviewViewProvider(
1817
MethodModelingViewProvider.viewType,
Lines changed: 71 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -1,82 +1,51 @@
1-
import * as vscode from "vscode";
2-
import { Uri, WebviewViewProvider } from "vscode";
3-
import { getHtmlForWebview } from "../../common/vscode/webview-html";
4-
import { FromMethodModelingMessage } from "../../common/interface-types";
1+
import {
2+
FromMethodModelingMessage,
3+
ToMethodModelingMessage,
4+
} from "../../common/interface-types";
55
import { telemetryListener } from "../../common/vscode/telemetry";
66
import { showAndLogExceptionWithTelemetry } from "../../common/logging/notifications";
77
import { extLogger } from "../../common/logging/vscode/loggers";
88
import { App } from "../../common/app";
99
import { redactableError } from "../../common/errors";
1010
import { Method } from "../method";
11-
import { DisposableObject } from "../../common/disposable-object";
1211
import { ModelingStore } from "../modeling-store";
12+
import { AbstractWebviewViewProvider } from "../../common/vscode/abstract-webview-view-provider";
1313

14-
export class MethodModelingViewProvider
15-
extends DisposableObject
16-
implements WebviewViewProvider
17-
{
14+
export class MethodModelingViewProvider extends AbstractWebviewViewProvider<
15+
ToMethodModelingMessage,
16+
FromMethodModelingMessage
17+
> {
1818
public static readonly viewType = "codeQLMethodModeling";
1919

20-
private webviewView: vscode.WebviewView | undefined = undefined;
21-
2220
private method: Method | undefined = undefined;
2321

2422
constructor(
25-
private readonly app: App,
23+
app: App,
2624
private readonly modelingStore: ModelingStore,
2725
) {
28-
super();
26+
super(app, "method-modeling");
2927
}
3028

31-
/**
32-
* This is called when a view first becomes visible. This may happen when the view is
33-
* first loaded or when the user hides and then shows a view again.
34-
*/
35-
public resolveWebviewView(
36-
webviewView: vscode.WebviewView,
37-
_context: vscode.WebviewViewResolveContext,
38-
_token: vscode.CancellationToken,
39-
) {
40-
webviewView.webview.options = {
41-
enableScripts: true,
42-
localResourceRoots: [Uri.file(this.app.extensionPath)],
43-
};
44-
45-
const html = getHtmlForWebview(
46-
this.app,
47-
webviewView.webview,
48-
"method-modeling",
49-
{
50-
allowInlineStyles: true,
51-
allowWasmEval: false,
52-
},
53-
);
54-
55-
webviewView.webview.html = html;
56-
57-
webviewView.webview.onDidReceiveMessage(async (msg) => this.onMessage(msg));
58-
59-
this.webviewView = webviewView;
60-
61-
this.setInitialState(webviewView);
29+
protected override onWebViewLoaded(): void {
30+
this.setInitialState();
6231
this.registerToModelingStoreEvents();
6332
}
6433

6534
public async setMethod(method: Method): Promise<void> {
6635
this.method = method;
6736

68-
if (this.webviewView) {
69-
await this.webviewView.webview.postMessage({
37+
if (this.isShowingView) {
38+
await this.postMessage({
7039
t: "setMethod",
7140
method,
7241
});
7342
}
7443
}
7544

76-
private setInitialState(webviewView: vscode.WebviewView): void {
45+
private setInitialState(): void {
7746
const selectedMethod = this.modelingStore.getSelectedMethodDetails();
7847
if (selectedMethod) {
79-
void webviewView.webview.postMessage({
48+
void this.postMessage({
8049
t: "setSelectedMethod",
8150
method: selectedMethod.method,
8251
modeledMethod: selectedMethod.modeledMethod,
@@ -85,24 +54,18 @@ export class MethodModelingViewProvider
8554
}
8655
}
8756

88-
private async onMessage(msg: FromMethodModelingMessage): Promise<void> {
57+
protected override async onMessage(
58+
msg: FromMethodModelingMessage,
59+
): Promise<void> {
8960
switch (msg.t) {
90-
case "setModeledMethod": {
91-
const activeState = this.modelingStore.getStateForActiveDb();
92-
if (!activeState) {
93-
throw new Error("No active state found in modeling store");
94-
}
95-
this.modelingStore.updateModeledMethod(
96-
activeState.databaseItem,
97-
msg.method,
98-
);
61+
case "viewLoaded":
62+
this.onWebViewLoaded();
9963
break;
100-
}
10164

102-
case "telemetry": {
65+
case "telemetry":
10366
telemetryListener?.sendUIInteraction(msg.action);
10467
break;
105-
}
68+
10669
case "unhandledError":
10770
void showAndLogExceptionWithTelemetry(
10871
extLogger,
@@ -112,42 +75,60 @@ export class MethodModelingViewProvider
11275
)`Unhandled error in method modeling view: ${msg.error.message}`,
11376
);
11477
break;
78+
79+
case "setModeledMethod": {
80+
const activeState = this.modelingStore.getStateForActiveDb();
81+
if (!activeState) {
82+
throw new Error("No active state found in modeling store");
83+
}
84+
this.modelingStore.updateModeledMethod(
85+
activeState.databaseItem,
86+
msg.method,
87+
);
88+
break;
89+
}
11590
}
11691
}
11792

11893
private registerToModelingStoreEvents(): void {
119-
this.modelingStore.onModeledMethodsChanged(async (e) => {
120-
if (this.webviewView && e.isActiveDb) {
121-
const modeledMethod = e.modeledMethods[this.method?.signature ?? ""];
122-
if (modeledMethod) {
94+
this.push(
95+
this.modelingStore.onModeledMethodsChanged(async (e) => {
96+
if (this.webviewView && e.isActiveDb) {
97+
const modeledMethod = e.modeledMethods[this.method?.signature ?? ""];
98+
if (modeledMethod) {
99+
await this.webviewView.webview.postMessage({
100+
t: "setModeledMethod",
101+
method: modeledMethod,
102+
});
103+
}
104+
}
105+
}),
106+
);
107+
108+
this.push(
109+
this.modelingStore.onModifiedMethodsChanged(async (e) => {
110+
if (this.webviewView && e.isActiveDb && this.method) {
111+
const isModified = e.modifiedMethods.has(this.method.signature);
123112
await this.webviewView.webview.postMessage({
124-
t: "setModeledMethod",
125-
method: modeledMethod,
113+
t: "setMethodModified",
114+
isModified,
126115
});
127116
}
128-
}
129-
});
130-
131-
this.modelingStore.onModifiedMethodsChanged(async (e) => {
132-
if (this.webviewView && e.isActiveDb && this.method) {
133-
const isModified = e.modifiedMethods.has(this.method.signature);
134-
await this.webviewView.webview.postMessage({
135-
t: "setMethodModified",
136-
isModified,
137-
});
138-
}
139-
});
117+
}),
118+
);
140119

141-
this.modelingStore.onSelectedMethodChanged(async (e) => {
142-
if (this.webviewView) {
143-
this.method = e.method;
144-
await this.webviewView.webview.postMessage({
145-
t: "setSelectedMethod",
146-
method: e.method,
147-
modeledMethod: e.modeledMethod,
148-
isModified: e.isModified,
149-
});
150-
}
151-
});
120+
this.push(
121+
this.modelingStore.onSelectedMethodChanged(async (e) => {
122+
if (this.webviewView) {
123+
this.method = e.method;
124+
await this.webviewView.webview.postMessage({
125+
t: "setSelectedMethod",
126+
method: e.method,
127+
modeledMethod: e.modeledMethod,
128+
isModified: e.isModified,
129+
});
130+
}
131+
}),
132+
);
152133
}
153134
}

extensions/ql-vscode/src/queries-panel/queries-module.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { DisposableObject } from "../common/disposable-object";
66
import { QueriesPanel } from "./queries-panel";
77
import { QueryDiscovery } from "./query-discovery";
88
import { QueryPackDiscovery } from "./query-pack-discovery";
9+
import { LanguageContextStore } from "../language-context-store";
910

1011
export class QueriesModule extends DisposableObject {
1112
private queriesPanel: QueriesPanel | undefined;
@@ -16,16 +17,21 @@ export class QueriesModule extends DisposableObject {
1617

1718
public static initialize(
1819
app: App,
20+
languageContext: LanguageContextStore,
1921
cliServer: CodeQLCliServer,
2022
): QueriesModule {
2123
const queriesModule = new QueriesModule(app);
2224
app.subscriptions.push(queriesModule);
2325

24-
queriesModule.initialize(app, cliServer);
26+
queriesModule.initialize(app, languageContext, cliServer);
2527
return queriesModule;
2628
}
2729

28-
private initialize(app: App, cliServer: CodeQLCliServer): void {
30+
private initialize(
31+
app: App,
32+
langauageContext: LanguageContextStore,
33+
cliServer: CodeQLCliServer,
34+
): void {
2935
// Currently, we only want to expose the new panel when we are in canary mode
3036
// and the user has enabled the "Show queries panel" flag.
3137
if (!isCanary() || !showQueriesPanel()) {
@@ -38,8 +44,9 @@ export class QueriesModule extends DisposableObject {
3844
void queryPackDiscovery.initialRefresh();
3945

4046
const queryDiscovery = new QueryDiscovery(
41-
app.environment,
47+
app,
4248
queryPackDiscovery,
49+
langauageContext,
4350
);
4451
this.push(queryDiscovery);
4552
void queryDiscovery.initialRefresh();

0 commit comments

Comments
 (0)