Skip to content

Commit

Permalink
Add webview serializer
Browse files Browse the repository at this point in the history
  • Loading branch information
msujew committed Jun 15, 2023
1 parent 78ab11a commit 24f2f43
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 16 deletions.
16 changes: 14 additions & 2 deletions packages/langium-railroad/src/grammar-railroad.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,25 @@ svg.railroad-diagram rect {
}
`.trim();

export function createGrammarDiagramHtml(grammar: GrammarAST.Grammar): string {
export interface GrammarDiagramOptions {
css?: string;
javascript?: string;
}

export function createGrammarDiagramHtml(grammar: GrammarAST.Grammar, options?: GrammarDiagramOptions): string {
let text = `<!DOCTYPE HTML>
<html>
<head>
<style>
${defaultCss}
</style>
</style>${options?.css ? `
<style>
${options.css}
</style>` : ''}
${options?.javascript ? `
<script>
${options.javascript}
</script>` : ''}
</head>
<body>
`;
Expand Down
4 changes: 2 additions & 2 deletions packages/langium-vscode/src/language-server/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { createLangiumGrammarServices, startLanguageServer } from 'langium';
import { NodeFileSystem } from 'langium/node';
import { createConnection, ProposedFeatures } from 'vscode-languageserver/node';
import { LangiumGrammarWorkspaceManager } from './grammar-workspace-manager';
import { registerRailroadHandler } from './railroad-handler';
import { registerRailroadConnectionHandler } from './railroad-handler';

const connection = createConnection(ProposedFeatures.all);

Expand All @@ -20,5 +20,5 @@ export const LangiumGrammarSharedModule: Module<LangiumSharedServices, PartialLa
};

const { shared, grammar } = createLangiumGrammarServices({ connection, ...NodeFileSystem }, LangiumGrammarSharedModule);
registerRailroadHandler(connection, grammar);
registerRailroadConnectionHandler(connection, grammar);
startLanguageServer(shared);
10 changes: 7 additions & 3 deletions packages/langium-vscode/src/language-server/railroad-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,25 +12,29 @@ import { URI } from 'vscode-uri';
import { DOCUMENTS_VALIDATED_NOTIFICATION, RAILROAD_DIAGRAM_REQUEST } from './messages';
import { createGrammarDiagramHtml } from 'langium-railroad';

export function registerRailroadHandler(connection: Connection, services: LangiumServices): void {
export function registerRailroadConnectionHandler(connection: Connection, services: LangiumServices): void {
const documentBuilder = services.shared.workspace.DocumentBuilder;
const documents = services.shared.workspace.LangiumDocuments;
documentBuilder.onBuildPhase(DocumentState.Validated, documents => {
const uris = documents.map(e => e.uri.toString());
connection.sendNotification(DOCUMENTS_VALIDATED_NOTIFICATION, uris);
});
// After receiving the `DOCUMENTS_VALIDATED_NOTIFICATION`
// the vscode extension will perform the following request
connection.onRequest(RAILROAD_DIAGRAM_REQUEST, (uri: string) => {
try {
const parsedUri = URI.parse(uri);
const document = documents.getOrCreateDocument(parsedUri);
if (document.diagnostics?.some(e => e.severity === DiagnosticSeverity.Error)) {
return undefined;
}
const generatedRailroadHtml = createGrammarDiagramHtml(document.parseResult.value as Grammar);
const generatedRailroadHtml = createGrammarDiagramHtml(document.parseResult.value as Grammar, {
javascript: `const vscode = acquireVsCodeApi(); vscode.setState(${JSON.stringify(uri)});`
});
return generatedRailroadHtml;
} catch {
// Document couldn't be found or uri was invalid, just return nothing
return undefined;
}
});
}
}
43 changes: 34 additions & 9 deletions packages/langium-vscode/src/railroad-webview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,40 @@ export function registerRailroadWebview(client: LanguageClient): void {
RailroadDiagramPanel.current.update();
}
});
vscode.window.registerWebviewPanelSerializer(
RailroadDiagramPanel.viewType,
new RailroadDiagramSerializer(client)
);
}

class RailroadDiagramSerializer implements vscode.WebviewPanelSerializer {

private readonly client: LanguageClient;

constructor(client: LanguageClient) {
this.client = client;
}

deserializeWebviewPanel(webviewPanel: vscode.WebviewPanel, state: unknown): Thenable<void> {
if (typeof state === 'string') {
const uri = vscode.Uri.parse(state);
RailroadDiagramPanel.revive(webviewPanel, this.client, uri);
}
return Promise.resolve();
}

}

export class RailroadDiagramPanel implements vscode.Disposable {

uri: string;
client: LanguageClient;
panel: vscode.WebviewPanel;

private panel: vscode.WebviewPanel;
private client: LanguageClient;
private disposables: vscode.Disposable[] = [];

static current?: RailroadDiagramPanel;

static viewType = 'railroadDiagram';
static readonly viewType = 'railroadDiagram';

static createOrShow(client: LanguageClient, fileUri: vscode.Uri): void {
if (this.current) {
Expand All @@ -38,13 +59,18 @@ export class RailroadDiagramPanel implements vscode.Disposable {
}
const panel = vscode.window.createWebviewPanel(
RailroadDiagramPanel.viewType,
'Railroad Diagram ' + getFileName(fileUri.path),
getPanelTitle(fileUri.path),
vscode.ViewColumn.Beside,
);
this.current = new RailroadDiagramPanel(client, panel, fileUri);
this.current.update();
}

static revive(panel: vscode.WebviewPanel, client: LanguageClient, fileUri: vscode.Uri): void {
this.current = new RailroadDiagramPanel(client, panel, fileUri);
this.current.update();
}

constructor(client: LanguageClient, panel: vscode.WebviewPanel, uri: vscode.Uri) {
this.uri = uri.toString();
this.client = client;
Expand All @@ -69,7 +95,7 @@ export class RailroadDiagramPanel implements vscode.Disposable {
this.uri = uri;
}
try {
this.panel.title = 'Railroad Diagram ' + getFileName(this.uri);
this.panel.title = getPanelTitle(this.uri);
const railroad: string | undefined = await this.client.sendRequest(RAILROAD_DIAGRAM_REQUEST, this.uri);
if (railroad) {
this.panel.webview.html = railroad;
Expand All @@ -79,9 +105,8 @@ export class RailroadDiagramPanel implements vscode.Disposable {
// It might already be disposed
}
}

}

function getFileName(uri: string): string {
return uri.substring(uri.lastIndexOf('/') + 1);
function getPanelTitle(uri: string) {
return `Railroad Diagram ${uri.substring(uri.lastIndexOf('/') + 1)}`;
}

0 comments on commit 24f2f43

Please sign in to comment.