Eclipse GLSP VSCode Integration
This package contains the glue code for integrating GLSP
diagrams in VS Code. This library enables the implementation of GLSP Diagram editors
for VS Code base on the Custom Editor API.
Where to find the sources?
In addition to this repository, the related source code can be found here:
Getting started
This section will show you how to get your first GLPS extension up and running using
the GLSP VSCode Integration.
Example Extension
You can find a complete example extension that uses this package
here.
It makes heavy use of default implementations like the default GLSP server, the
default GLSP client and the default GLSP Sprotty client.
Example Code
There are a few steps that are absolutely necessary for the GLSP VSCode Integration
to work. They are outlined in this section.
Extension
First you need to set up your extension starter code. This is done by setting the
"main"
field of your package.json
to the entry point of your extension and exporting
an activate()
function from that file. For more information on how to set up your
VSCode extension please visit https://code.visualstudio.com/api.
Code Example
import * as vscode from 'vscode';
export async function activate(context: vscode.ExtensionContext): Promise<void> {
}
Server
Next we will start a GLSP server from within the activate function. If you have
already have the server running through some other process you can skip this step.
If you are using the default GLSP server implementation provided at https://github.com/eclipse-glsp/glsp-server,
you can use the GlspServerLauncher
quickstart component
to start the server with very little code:
Code Example
import { GlspServerLauncher } from '@eclipse-glsp/vscode-integration/lib/quickstart-components';
export async function activate(context: vscode.ExtensionContext): Promise<void> {
const serverProcess = new GlspServerLauncher({
jarPath: '/your/path/to/server.jar',
serverPort: 5007
});
context.subscriptions.push(serverProcess);
await serverProcess.start();
}
Server Interface and GLSP VSCode Connector
A connector class is needed to provide an interface for the GLSP VSCode integration
to communicate with the server. If you are using the default GLSP server which communicates
over JSON-RPC, you can make use of the SocketGlspVscodeServer
quickstart component
to implement the needed interface with very little boilerplate code.
If we have a server component providing the needed interface we can create an instance
of the GlspVscodeConnector
and pass the server component. The GlspVscodeConnector
lies at the core of this package and provides all the needed functionality.
Code Example
import { GlspVscodeConnector } from '@eclipse-glsp/vscode-integration';
import { SocketGlspVscodeServer } from '@eclipse-glsp/vscode-integration/lib/quickstart-components';
export async function activate(context: vscode.ExtensionContext): Promise<void> {
const workflowServer = new SocketGlspVscodeServer({
clientId: 'some.client.id',
clientName: 'SomeClientName',
serverPort: 5007
});
const glspVscodeConnector = new GlspVscodeConnector({ server: workflowServer });
context.subscriptions.push(workflowServer, glspVscodeConnector);
}
Custom Editor Provider
In order to have a custom editor in VSCode a component implementing the vscode.CustomEditorProvider
needs to be registered from within the extension (more information on custom editors
here).
The GLSP VSCode integration package gives you free reign over how you implement
your CustomEditorProvider
, however a few function calls at certain places are
needed for the integration to work properly:
- The
onDidChangeCustomDocument
of your CustomEditorProvider
should always fire
at least when GlspVscodeConnector.onDidChangeCustomDocument
fires.
GlspVscodeConnector.saveDocument(document)
should be called when CustomEditorProvider.saveCustomDocument
is called.
GlspVscodeConnector.saveDocument(document, destination)
should be called when
CustomEditorProvider.saveCustomDocumentAs
is called.
GlspVscodeConnector.revertDocument()
should be called when CustomEditorProvider.revertCustomDocument
is called.
You can use the GlspEditorProvider
quickstart component
to set up such an editor provider without much boilerplate code.
If you chose to create a CustomEditorProvider
yourself, the resolveCustomEditor
function of the CustomEditorProvider
act as an excellent place to register your
GLSP clients. You can do this with the GlspVscodeConnector.registerClient(client)
function. You are free to choose on how your clients implement the needed interface,
however if you need inspiration on how to do it with the default GLSP components,
you can take a look at the example
here.
Code Example
import MyCustomEditorProvider from './my-custom-editor-provider.ts';
export async function activate(context: vscode.ExtensionContext): Promise<void> {
const customEditorProvider = vscode.window.registerCustomEditorProvider(
'your.custom.editor',
new MyCustomEditorProvider(glspVscodeConnector),
{
webviewOptions: { retainContextWhenHidden: true },
supportsMultipleEditorsPerDocument: false
}
);
context.subscriptions.push(customEditorProvider);
}
export default class WorkflowEditorProvider implements vscode.CustomEditorProvider {
onDidChangeCustomDocument: vscode.Event<vscode.CustomDocumentContentChangeEvent<vscode.CustomDocument>>;
constructor(private readonly glspVscodeConnector: GlspVscodeConnector) {
this.onDidChangeCustomDocument = glspVscodeConnector.onDidChangeCustomDocument;
}
saveCustomDocument(document: vscode.CustomDocument, cancellation: vscode.CancellationToken): Thenable<void> {
return this.glspVscodeConnector.saveDocument(document);
}
saveCustomDocumentAs(document: vscode.CustomDocument, destination: vscode.Uri, cancellation: vscode.CancellationToken): Thenable<void> {
return this.glspVscodeConnector.saveDocument(document, destination);
}
revertCustomDocument(document: vscode.CustomDocument, cancellation: vscode.CancellationToken): Thenable<void> {
return this.glspVscodeConnector.revertDocument(document, 'your.diagram.type');
}
resolveCustomEditor(
document: vscode.CustomDocument,
webviewPanel: vscode.WebviewPanel,
token: vscode.CancellationToken
): void | Thenable<void> {
const onSendToClientEmitter = new vscode.EventEmitter<unknown>();
const onClientMessage = new vscode.EventEmitter<unknown>();
this.glspVscodeConnector.registerClient({
clientId: 'your.glsp.client.id.here',
document: document,
webviewPanel: webviewPanel,
onClientMessage: onClientSendEmitter.event,
onSendToClientEmitter: onSendToClientEmitter
});
webviewPanel.webview.html = `(Your webview HTML here)`;
}
}
Final touches
All that's left to do is a final call to start the server and the extension
should be up and running.
Code Example
export async function activate(context: vscode.ExtensionContext): Promise<void> {
workflowServer.start();
}
API
This package exports a number of members, the most important one being the GlspVscodeConnector
-Class.
GlspVscodeConnector
This is the core of the VSCode integration and provides various functionality. It
primarily intercepts certain GLSP Actions sent from the clients or server to trigger
VSCode specific contributions. This currently includes:
- File dirty state
- File "Save" and "Save as..."
- File reverting
- Diagnostics or "markers" and "validations"
- External target navigation
- Exporting as SVG (with dialog window)
- Providing element selection context to extensions
Options
The GlspVscodeConnector
takes one constructor argument - an object containing its configuration.
export interface GlspVscodeConnectorOptions {
server: GlspVscodeServer;
logging?: boolean;
onBeforeReceiveMessageFromClient?: (message: unknown, callback: InterceptorCallback) => void;
onBeforeReceiveMessageFromServer?(message: unknown, callback: InterceptorCallback): void;
onBeforePropagateMessageToServer?(originalMessage: unknown, processedMessage: unknown, messageChanged: boolean): unknown | undefined;
onBeforePropagateMessageToClient?(originalMessage: unknown, processedMessage: unknown, messageChanged: boolean): unknown | undefined;
}
Methods and Fields
interface GlspVscodeConnector<D extends vscode.CustomDocument = vscode.CustomDocument> extends vscode.Disposable {
onSelectionUpdate: vscode.Event<string[]>;
onDidChangeCustomDocument: vscode.Event<vscode.CustomDocumentEditEvent<D>>;
registerClient(client: GlspVscodeClient<D>): void;
sendActionToActiveClient(action: Action): void;
saveDocument(document: D, destination?: vscode.Uri): Promise<void>;
revertDocument(document: D, diagramType: string): Promise<void>;
}
GlspVscodeServer
export interface GlspVscodeServer {
readonly onSendToServerEmitter: vscode.EventEmitter<unknown>;
readonly onServerMessage: vscode.Event<unknown>;
}
GlspVscodeClient
export interface GlspVscodeClient<D extends vscode.CustomDocument = vscode.CustomDocument> {
readonly clientId: string;
readonly webviewPanel: vscode.WebviewPanel;
readonly document: D;
readonly onSendToClientEmitter: vscode.EventEmitter<unknown>;
readonly onClientMessage: vscode.Event<unknown>;
}
Quickstart Components
This package also exposes components which can be taken advantage of if you are using the default GLSP components.
They can be imported using
import * as QuickstartComponents from '@eclipse-glsp/vscode-integration/lib/quickstart-components';
GlspServerLauncher
A small class used to start a default implementation GLSP server.
interface GlspServerLauncher extends vscode.Disposable {
constructor(options: JavaSocketServerLauncherOptions);
start(): Promise<void>;
stop(): void;
}
interface JavaSocketServerLauncherOptions {
readonly jarPath: string;
readonly serverPort: number;
readonly logging?: boolean;
readonly additionalArgs?: string[];
}
SocketGlspVscodeServer
A can component that provides the right interface for the GLSP VSCode integration
to be used as server and which can connect to a default implementation GLSP server.
interface SocketGlspVscodeServerOptions {
readonly serverPort: number;
readonly clientId: string;
readonly clientName: string;
}
interface SocketGlspVscodeServer extends GlspVscodeServer, vscode.Disposable {
constructor(private readonly options: SocketGlspVscodeServerOptions);
start(): Promise<void>;
stop(): Promise<void>;
}
GlspEditorProvider
An extensible base class to create a CustomEditorProvider that takes care of diagram
initialization and custom document events.
Webview setup needs to be implemented.
export abstract class GlspEditorProvider implements vscode.CustomEditorProvider {
abstract diagramType: string;
constructor(protected readonly glspVscodeConnector: GlspVscodeConnector);
abstract setUpWebview(
document: vscode.CustomDocument,
webviewPanel: vscode.WebviewPanel,
token: vscode.CancellationToken,
clientId: string
): void;
}
More information
For more information, please visit the Eclipse GLSP Umbrella repository
and the Eclipse GLSP Website. If you have questions,
contact us on our spectrum chat and have a look at our
communication and support options.