Git Product home page Git Product logo

sprotty-vscode's Introduction

Gitpod Ready-to-Code

sprotty-vscode

This repository contains the glue code to integrate Sprotty diagrams - with or without a language server - in VSCode extensions.

Also contains an example extension for a domain-specific language for statemachines. The example is also available as States Example from the VS Code Marketplace.

Screenshot

Features

  • running Sprotty diagrams in VS Code webviews,
  • SVG export (ALT-E), animated center selection (ALT-C) and fit to screen (ALT-F) actions,
  • interaction with Sprotty-enhanced language servers to automatically synchronize diagrams with language artifacts.

Architecture

In VS Code, extensions can contribute new UI components using a webview. Webviews communicate with the extension using the vscode-messenger library. The WebviewPanelManager uses this to send and receive Sprotty Actions to and from a WebviewEndpoint. The latter runs a webpacked bundle.js that contains the Sprotty diagram code.

Architecture Diagram

If your extension provides a language, you can include a Sprotty-enhanced language server to get fully synchronized diagrams for your language artifacts. The SprottyLspVscodeExtension acts as a relay between the language server and a SprottyLanguageWebview, and intercepts actions/LSP messages that require to interact with the VS Code workbench.

Contents

The repo is structured as follows

  • examples: an example Sprotty visualization using a Langium-based Language Server.
  • packages/sprotty-vscode: library code for the VSCode extension.
  • packages/sprotty-vscode-protocol: common protocol classes for the communication between the extension and the webview.
  • packages/sprotty-vscode-webview: library code for the script that is run in the webview.

Development

Compile the library code and the examples:

yarn

If you also want to use the older Xtext-based example, you need to run this command before yarn:

./examples/states-xtext/language-server/gradlew -p examples/states-xtext/language-server/ build

sprotty-vscode's People

Contributors

christianmalek avatar dependabot[bot] avatar dhuebner avatar gfontorbe avatar jankoehnlein avatar nezteb avatar niklasrentzcau avatar robertwalteru3d avatar spoenemann avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

sprotty-vscode's Issues

Unable to load model in the non-language-server case

I'm trying to use the sprotty diagram in a VSCode extension that doesn't involve a language server. Basically I don't want to add a new DSL; instead the model is loaded from a JSON/YAML object (persisted as a file in the workspace).

I implemented my own SprottyVscodeExtension and SprottyStarter, and implemented the webview according to the class diagram example from sprotty. However there's only an empty diagram when I select "Open in Diagram". It turns out that the webview gets loaded correctly but the model is "EMPTY".

Looking into the implementation of SprottyStarter, I can see that the ModelSource is provided by VscodeDiagramServer:
container.bind(TYPES.ModelSource).toService(VscodeDiagramServer);

Doesn't this mean that the diagram is expected to be served from the language server? I don't see any code in sprotty-vscode that loads the model from a file in the workspace, and I have yet to find a working example that shows how this is achieved without a language server. I don't mind implementing a custom "loader", but I just don't see a way to invoke it.

[Question] Custom Notifications

Hi I'm a little bit confused about handling server to client communication.

What I'd like to achieve is to send a message which needs to be handled by the language client.

I imagined it is at easy as that but I'm not able to send anything custom to the client.

For example in the command service on the server side

public class CommandService implements IExecutableCommandService {
	
	
	@Override
	public List<String> initialize() {
		return Lists.newArrayList("mycommand.run");
	}

	@Override
	public Object execute(ExecuteCommandParams params, ILanguageServerAccess access, CancelIndicator cancelIndicator) {
		
		//Some server stuff going on here
               .....
		
                //What I'd like to do (the function is made up but show what I'd like to do)
		foo.sendNotificationToClient("/mycustomendpoint", "Message");
		
		return "works";
	}

}

Client side

extension.languageClient.onNotification("/custom/Message", ()=> {
        show a message or open a webview
})

Issues trying to build langium example

Hi,

never used Yarn before, so I'm a bit lost. The instructions in the root's ReadMe seem a bit outdated regarding how to build the library and example.

My goal is to run the Langium statemachine example from the "States Example (Langium)" configuration in VS Code. I'm on Windows 10, running VS Code1.70.1.

I installed Yarn (1.22.19) globally and ran yarn --cwd .. from the "states-langium" directory successfully.
When I run the "States Example (Langium)" configuration, the Language Server crashes several times with this output:

node:internal/modules/cjs/loader:990
  throw err;
  ^

Error: Cannot find module 'd:\Dev\sprotty\examples\states-langium\extension\pack\language-server'
    at Function._resolveFilename (node:internal/modules/cjs/loader:987:15)
    at node:internal/modules/cjs/loader:832:27
    at Function._load (node:electron/js2c/asar_bundle:5:13343)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
    at node:internal/main/run_main_module:17:47 {
  code: 'MODULE_NOT_FOUND',
  requireStack: []
}

So I'm guessing it was not build properly.
Trying to build it from the repo root with yarn and yarn --cwd .. results in errors when it is trying to build the states-language-server:

image

What am I doing wrong? Thanks!

How to run lsp in langium example?

Hi, I am currently trying to run the project in Langium example. I've followed the instruction in its nested repo (it is quite sketchy). When I opened the Extension Development Host, got this error below:
Untitled

The errors in details:
node:internal/modules/cjs/loader:990
throw err;
^

Error: Cannot find module 'dirname\sprotty-vscode\examples\states-langium\extension\pack\language-server'
at Function.Module._resolveFilename (node:internal/modules/cjs/loader:987:15)
at Module._load (node:internal/modules/cjs/loader:832:27)
at Function.c._load (node:electron/js2c/asar_bundle:5:13343)
at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
at node:internal/main/run_main_module:17:47 {
code: 'MODULE_NOT_FOUND',
requireStack: []
}
[Info - 9:47:41 PM] Connection to server got closed. Server will restart.
[Error - 9:47:41 PM] Server initialization failed.
Message: Pending response rejected since connection got disposed
Code: -32097
[Error - 9:47:41 PM] States client: couldn't create connection to server.
Message: Pending response rejected since connection got disposed
Code: -32097
node:internal/modules/cjs/loader:990
throw err;
^

Error: Cannot find module 'dirname\sprotty-vscode\examples\states-langium\extension\pack\language-server'
at Function.Module._resolveFilename (node:internal/modules/cjs/loader:987:15)
at Module._load (node:internal/modules/cjs/loader:832:27)
at Function.c._load (node:electron/js2c/asar_bundle:5:13343)
at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
at node:internal/main/run_main_module:17:47 {
code: 'MODULE_NOT_FOUND',
requireStack: []
}
[Info - 9:47:42 PM] Connection to server got closed. Server will restart.
[Error - 9:47:42 PM] Server initialization failed.
Message: Pending response rejected since connection got disposed
Code: -32097
[Error - 9:47:42 PM] States client: couldn't create connection to server.
Message: Pending response rejected since connection got disposed
Code: -32097
node:internal/modules/cjs/loader:990
throw err;
^

Error: Cannot find module 'dirname\sprotty-vscode\examples\states-langium\extension\pack\language-server'
at Function.Module._resolveFilename (node:internal/modules/cjs/loader:987:15)
at Module._load (node:internal/modules/cjs/loader:832:27)
at Function.c._load (node:electron/js2c/asar_bundle:5:13343)
at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
at node:internal/main/run_main_module:17:47 {
code: 'MODULE_NOT_FOUND',
requireStack: []
}
[Info - 9:47:43 PM] Connection to server got closed. Server will restart.
[Error - 9:47:43 PM] Server initialization failed.
Message: Pending response rejected since connection got disposed
Code: -32097
[Error - 9:47:43 PM] States client: couldn't create connection to server.
Message: Pending response rejected since connection got disposed
Code: -32097
[Error - 9:47:43 PM] Restarting server failed
Message: Pending response rejected since connection got disposed
Code: -32097
node:internal/modules/cjs/loader:990
throw err;
^

Error: Cannot find module 'dirname\sprotty-vscode\examples\states-langium\extension\pack\language-server'
at Function.Module._resolveFilename (node:internal/modules/cjs/loader:987:15)
at Module._load (node:internal/modules/cjs/loader:832:27)
at Function.c._load (node:electron/js2c/asar_bundle:5:13343)
at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
at node:internal/main/run_main_module:17:47 {
code: 'MODULE_NOT_FOUND',
requireStack: []
}
[Info - 9:47:43 PM] Connection to server got closed. Server will restart.
[Error - 9:47:43 PM] Server initialization failed.
Message: Pending response rejected since connection got disposed
Code: -32097
[Error - 9:47:43 PM] States client: couldn't create connection to server.
Message: Pending response rejected since connection got disposed
Code: -32097
[Error - 9:47:43 PM] Restarting server failed
Message: Pending response rejected since connection got disposed
Code: -32097
node:internal/modules/cjs/loader:990
throw err;
^

Error: Cannot find module 'dirname\sprotty-vscode\examples\states-langium\extension\pack\language-server'
at Function.Module._resolveFilename (node:internal/modules/cjs/loader:987:15)
at Module._load (node:internal/modules/cjs/loader:832:27)
at Function.c._load (node:electron/js2c/asar_bundle:5:13343)
at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
at node:internal/main/run_main_module:17:47 {
code: 'MODULE_NOT_FOUND',
requireStack: []
}
[Error - 9:47:45 PM] The States server crashed 5 times in the last 3 minutes. The server will not be restarted. See the output for more information.
[Error - 9:47:45 PM] Server initialization failed.
Message: Pending response rejected since connection got disposed
Code: -32097
[Error - 9:47:45 PM] States client: couldn't create connection to server.
Message: Pending response rejected since connection got disposed
Code: -32097
[Error - 9:47:45 PM] Restarting server failed
Message: Pending response rejected since connection got disposed
Code: -32097

Context Menu

Hi, I am currently looking into implementing vscode support for the GLSP over at https://github.com/eclipse-glsp/glsp-vscode-integration.

I was wondering wether there was any way to register any context menu items through this sprotty integration. Even though I added context menu contributions (editor/context), the sprotty view seems to swallow the right click action, meaning no context menu appears.

I would be very greatful for any directions on how to go about this.

sprotty (diagram &text) synchronized

why my colleague local sprotty project can achieve when diagram changed(right part),corresponding left part also synchronized change,i found new project(sprotty-vscode-master) can not synchronized since right part is readonly .he once used old sprotty-vscode project without langium module few years ago,only have xtext module,it is because xtext can achieve it?desperately for your answer,thanks ahead
image

How to restart an LSP server?

We have used this project to build a vscode extension for our language, see: https://github.com/opencaesar/oml-luxor

Sometimes, our XText-based LSP server gets confused; this can happen for example when someone is refactoring a lot of
files at once, resulting in lots of errors. While one can sometimes recover by closing all tabs and opening files one at a time,
this process can be tedious for novices. We would like to add a command to restart our LSP server, similar to what our NASA colleagues have done for the PVS VSCode extension, see: https://github.com/nasa/vscode-pvs/blob/master/vscode-pvs/docs/FAQ.md#q7-vscode-pvs-is-not-responding-and-reports-pvs-errors-what-can-i-do

There's been a related discussion in the Theia community about this:
https://spectrum.chat/theia/dev/whats-a-graceful-way-to-restart-a-language-server~063cd65d-9dfb-498f-ba9b-8ef8a19140db

One suggestion involves calling LanguageClient.stop() and LanguageClient.start().
With SprottyLspVscodeExtension, it is currently not possible:

export abstract class SprottyLspVscodeExtension extends SprottyVscodeExtension {
    readonly languageClient: LanguageClient;

    protected acceptFromLanguageServerEmitter = new Emitter<ActionMessage>();

    constructor(extensionPrefix: string, context: vscode.ExtensionContext)ย {
        super(extensionPrefix, context);
        this.languageClient = this.activateLanguageClient(context);
        this.languageClient.onReady().then(() => {
            this.languageClient.onNotification(acceptMessageType, message => this.acceptFromLanguageServerEmitter.fire(message));
            this.languageClient.onNotification(openInTextEditorMessageType, message => this.openInTextEditor(message));
        });
    }

Since languageClient is read-only, we cannot do something like this:

this.languageClient.stop();
this.languageClient =  this.activateLanguageClient(context);
        this.languageClient.onReady().then(() => {
            this.languageClient.onNotification(acceptMessageType, message => this.acceptFromLanguageServerEmitter.fire(message));
            this.languageClient.onNotification(openInTextEditorMessageType, message => this.openInTextEditor(message));
        });

Would it make sense to allow somehow doing something like shown above?

Is there perhaps a different way to achieve the desired effect?
For example, could we somehow force the extension to deactivate itself and re-activate itself?

How run project in local?

Is it possible to run the project locally? I would like to integrate a DSL with Sprotty, Theia and Xtext, but I can't find a stable project that at least runs locally...

Singleton webviews are not cleaned up correctly

Using a singleton webview can throw an error when the command "diagram.open" is executed. Following steps trow the error in the states example:

  1. Set singleton to true in StatesLspVscodeExtension.createWebView
  2. Start the extension and add two state maschine files in the example workspace. Named File1 and File2 in the following steps
  3. Open the diagram for File1
  4. Open File2. Singleton webview should switch the display to File2
  5. Close the singleton webview
  6. Open the diagram for File1
  7. See debug console for the produced error.
[[object Object]]Webview is disposed
Error: Webview is disposed
	at ExtHostWebviewPanel.assertNotDisposed (/usr/share/vscode/resources/app/out/vs/workbench/services/extensions/node/extensionHostProcess.js:54008)
	at ExtHostWebviewPanel.get visible [as visible] (/usr/share/vscode/resources/app/out/vs/workbench/services/extensions/node/extensionHostProcess.js:53985)
	at t.sendToWebview (/home/cf/Documents/bachelor/sprotty-examples/vsc-example/example/states/extension/pack/states-extension.js:1)
	at t.<anonymous> (/home/cf/Documents/bachelor/sprotty-examples/vsc-example/example/states/extension/pack/states-extension.js:1)
	at /home/cf/Documents/bachelor/sprotty-examples/vsc-example/example/states/extension/pack/states-extension.js:1
	at Object.next (/home/cf/Documents/bachelor/sprotty-examples/vsc-example/example/states/extension/pack/states-extension.js:1)
	at s (/home/cf/Documents/bachelor/sprotty-examples/vsc-example/example/states/extension/pack/states-extension.js:1)
	at processTicksAndRejections (internal/process/task_queues.js:93)

Duo to switching the files, the SprottyDiagramIdentifier changes in SprottyWebview.reloadContent.
SprottyVscodeExtension.didCloseWebview is then called with the updated identifier that was not used to store the singleton webview in SprottyVscodeExtension.webviewMap. Therefore, the disposed webview is not correctly removed from the webviewMap, where it was stored with the initial identifier.
Executing step 6 in the repro steps find the disposed webview in the webviewMap again and tries to reveal a disposed webview, causing the error.

exposing vscode-api

If one attempts to use this extension, but use a different communication channel than the language server implementation, one might want to use the vscode-api yourself in one's webview implementation. There's a good chance that I'm misunderstanding, but it seems like because the vscode-api is acquired in the sprotty-vscode-webview and not re-exported, it therefore cannot be used, since an attempt to acquire it "again" leads to an error (by design can only be acquired once).

[editing] revise lsp editing implementation

The current editing implementation based on LSP puts to much LSP magic on the client side. This leaks some abstractions, e.g. how to interpret traces. Into the bargain, it requires to relay language server requests between webview and extension, which was not necessary in Theia where there was no separate webview app.

  • Move as much as possible of the editing logic to the language server.
  • Use the new inline editing functionality of sprotty to edit rename labels
  • Maybe use new popup UI to edit cross-reference labels
  • Implement DeleteAction

Webview Active Check Prevents Command Execution

I am using a sprotty-vscode-based plugin in a Theia application, and I find that the .diagram.fit and .diagram.center commands are frequently (but not always) prevented from running because the findActiveWebview method inappropriately fails to identify the active webview if the command is triggered via the command palette. Theia has logic that restores focus to the webview, but the webview's state is checked before the refocus is registered. The following screenshot shows the output of a log during the findActiveWebview check, and one timed out by one second:

image

This screenshot shows that Theia correctly identifies the webview iframe as the active element, and that before the command is dispatched to Sprotty, a check for window.document.activeElement === this.activeElement (i.e. that focus has been restored to the iframe) passes.

image

I will cross-post an issue for Theia, since it may be an artifact of their command system.

Support webview views and webview editors

The current vscode integration uses the webview panel API to create unstructured diagram webviews. This should be extended to support the newer webview view and webview editor APIs.

Update dependencies `vscode-languageserver` and `vscode-languageclient` to `7.0.0` and reflect breaking changes

Hi ๐Ÿ‘‹ ,
first of all, thanks for your work.

When I tried out sprotty-vscode for an vscode-extension depending on vscode-languageserver and vscode-languageclient >= 7.0.0 I came across the breaking changes introduced in versions 7.0.0 of these packages.

I updated those dependencies and reflected the breaking changes to fix upcoming compile errors.

Is it of interest to merge the changes?
I will happily create a pull request. Otherwise feel free to close this issue.

[publish] find a way to publish the example

The current lerna-based build allows to compile and test the example with the source version of the framework packages, but it actually disables publishing the example to the VS Code marketplace.

It's likely we need a separate build to make that possible.

[code] extract common configs

We should extract common configuration like in tsconfig.json or webpack.config.js for each the framework packages and for the example packages and make sure we use the same everywhere.

compiled by a more recent version of JRE

Hey I recently came accross some issues relating the project.
cloning this repository on a fresh ubuntu 18.04.5 LTS machine with openjdk 8 installed I got the following error while building:

Class has been compiled by a more recent version of the Java Environment (class file version 55.0), this version of the Java Runtime only recognizes class file versions up to 52.0

I would be happy if anyone could give a hint how to fix that.

Also tried to just bump the jre to 11 but this results in another error:

com.google.inject.internal.util.$ComputationException: com.google.inject.internal.util.$ComputationException: java.lang.SecurityException: class "org.eclipse.core.runtime.OperationCanceledException"'s signer information does not match signer information of other classes in the same package
	at com.google.inject.internal.util.$MapMaker$StrategyImpl.compute(MapMaker.java:553)
	at com.google.inject.internal.util.$MapMaker$StrategyImpl.compute(MapMaker.java:419)
	at com.google.inject.internal.util.$CustomConcurrentHashMap$ComputingImpl.get(CustomConcurrentHashMap.java:2041)
	at com.google.inject.internal.FailableCache.get(FailableCache.java:50)
	at com.google.inject.internal.ConstructorInjectorStore.get(ConstructorInjectorStore.java:49)
	at com.google.inject.internal.ConstructorBindingImpl.initialize(ConstructorBindingImpl.java:125)
	at com.google.inject.internal.InjectorImpl.initializeJitBinding(InjectorImpl.java:521)
	at com.google.inject.internal.InjectorImpl.createJustInTimeBinding(InjectorImpl.java:847)
	at com.google.inject.internal.InjectorImpl.createJustInTimeBindingRecursive(InjectorImpl.java:772)
	at com.google.inject.internal.InjectorImpl.getJustInTimeBinding(InjectorImpl.java:256)
	at com.google.inject.internal.InjectorImpl.getBindingOrThrow(InjectorImpl.java:205)
	at com.google.inject.internal.InjectorImpl.getInternalFactory(InjectorImpl.java:853)
	at com.google.inject.internal.FactoryProxy.notify(FactoryProxy.java:46)
	at com.google.inject.internal.ProcessedBindingData.runCreationListeners(ProcessedBindingData.java:50)
	at com.google.inject.internal.InternalInjectorCreator.initializeStatically(InternalInjectorCreator.java:133)
	at com.google.inject.internal.InternalInjectorCreator.build(InternalInjectorCreator.java:106)
	at com.google.inject.Guice.createInjector(Guice.java:95)
	at com.google.inject.Guice.createInjector(Guice.java:72)
	at com.google.inject.Guice.createInjector(Guice.java:62)
	at ```

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.