Skip to content

Commit f75437a

Browse files
committed
Expose running extension API for integration tests
1 parent e4df952 commit f75437a

6 files changed

Lines changed: 50 additions & 3 deletions

File tree

‎client/src/extension.ts‎

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,14 @@ import { registerAutocomplete } from "./services/autocomplete";
1212
import { refreshCodeLenses, registerCodeLens } from "./services/codelens";
1313
import { runLanguageServer, stopLanguageServer } from "./lsp/server";
1414
import { runClient, stopClient } from "./lsp/client";
15+
import type { LiquidJavaTestApi } from "./types/test-api";
1516

1617
/**
1718
* Activates the LiquidJava extension
1819
* @param context The extension context
1920
*/
20-
export async function activate(context: vscode.ExtensionContext) {
21+
export async function activate(context: vscode.ExtensionContext): Promise<LiquidJavaTestApi> {
22+
context.subscriptions.push(extension.diagnosticsEmitter);
2123
registerLogger(context);
2224
extension.logger!.client.info("Activating LiquidJava extension...");
2325

@@ -30,6 +32,22 @@ export async function activate(context: vscode.ExtensionContext) {
3032
registerHover();
3133
await applyItalicOverlay();
3234
await startExtension(context);
35+
36+
const ready = extension.client?.isRunning()
37+
? Promise.resolve()
38+
: Promise.reject(new Error("LiquidJava language client did not start"));
39+
// keep activation behavior while callers observe startup failures through ready
40+
void ready.catch(() => {});
41+
42+
return {
43+
ready,
44+
onDiagnostics: extension.diagnosticsEmitter.event,
45+
getState: () => ({
46+
status: extension.status,
47+
diagnostics: [...(extension.diagnostics ?? [])],
48+
}),
49+
onWebviewMessage: extension.webview!.onWebviewMessage,
50+
};
3351
}
3452

3553
/**

‎client/src/services/diagnostics.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ export function handleLJDiagnostics(diagnostics: LJDiagnostic[]) {
1919
extension.webview?.sendMessage({ type: "diagnostics", diagnostics });
2020
if (extension.context)
2121
extension.webview?.sendMessage({ type: "context", context: extension.context, errorAtCursor: extension.errorAtCursor });
22+
extension.diagnosticsEmitter.fire(diagnostics);
2223
}
2324

2425
/**

‎client/src/services/webview.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export function registerWebview(context: vscode.ExtensionContext) {
1313

1414
// webview provider
1515
context.subscriptions.push(
16+
extension.webview,
1617
vscode.window.registerWebviewViewProvider(LiquidJavaWebviewProvider.viewType, extension.webview)
1718
);
1819
// show view command

‎client/src/state.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ export class ExtensionState {
2525
// application state
2626
file?: string;
2727
diagnostics?: LJDiagnostic[];
28+
readonly diagnosticsEmitter = new vscode.EventEmitter<LJDiagnostic[]>();
2829
stateMachine?: LJStateMachine | null;
2930
context?: LJContext;
3031
currentSelection?: Range;

‎client/src/types/test-api.ts‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import type * as vscode from "vscode";
2+
import type { ExtensionStatus } from "../state";
3+
import type { LJDiagnostic } from "./diagnostics";
4+
5+
export interface WebviewMessage {
6+
direction: "toWebview" | "fromWebview";
7+
message: any;
8+
}
9+
10+
export interface LiquidJavaTestApi {
11+
readonly ready: Promise<void>;
12+
readonly onDiagnostics: vscode.Event<LJDiagnostic[]>;
13+
getState(): { status: ExtensionStatus | undefined; diagnostics: LJDiagnostic[] };
14+
readonly onWebviewMessage: vscode.Event<WebviewMessage>;
15+
}

‎client/src/webview/provider.ts‎

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
11
import * as vscode from 'vscode';
22
import { getHtml } from './html';
33
import { highlightRange, openFile } from '../services/editor';
4+
import type { WebviewMessage } from '../types/test-api';
45

56
/**
67
* Webview provider for the LiquidJava extension
78
* Provides an interactive user interface for the LiquidJava diagnostics
89
*/
9-
export class LiquidJavaWebviewProvider implements vscode.WebviewViewProvider {
10+
export class LiquidJavaWebviewProvider implements vscode.WebviewViewProvider, vscode.Disposable {
1011
public static readonly viewType = "liquidJavaView";
1112
private view?: vscode.WebviewView;
1213
private messageEmitter = new vscode.EventEmitter<any>();
1314
public readonly onDidReceiveMessage = this.messageEmitter.event;
15+
private webviewMessageEmitter = new vscode.EventEmitter<WebviewMessage>();
16+
public readonly onWebviewMessage = this.webviewMessageEmitter.event;
1417

1518
constructor(private readonly extensionUri: vscode.Uri) {}
1619

@@ -29,6 +32,7 @@ export class LiquidJavaWebviewProvider implements vscode.WebviewViewProvider {
2932
// listen for messages coming from webview
3033
webviewView.webview.onDidReceiveMessage(message => {
3134
// emit the message to any external listeners
35+
this.webviewMessageEmitter.fire({ direction: "fromWebview", message });
3236
this.messageEmitter.fire(message);
3337

3438
// handle message
@@ -46,7 +50,14 @@ export class LiquidJavaWebviewProvider implements vscode.WebviewViewProvider {
4650
* @param message
4751
*/
4852
public sendMessage(message: any) {
49-
this.view?.webview.postMessage(message);
53+
if (!this.view) return;
54+
this.webviewMessageEmitter.fire({ direction: "toWebview", message });
55+
this.view.webview.postMessage(message);
56+
}
57+
58+
public dispose() {
59+
this.messageEmitter.dispose();
60+
this.webviewMessageEmitter.dispose();
5061
}
5162

5263
/**

0 commit comments

Comments
 (0)