Theia: How do I integrate "Theia+DSL" with Sprotty for visualization?

Created on 29 Apr 2018  路  23Comments  路  Source: eclipse-theia/theia

Hi there,

I am successful in integrating my DSL language server with Theia, but now I would like to use sprotty to visualize the content.

I have gone through one example online: https://github.com/theia-ide/theia-sprotty-example

It executes well, but not so clear how one can use sprotty with (XText LSP into Theia).

I would appreciate your inputs.
Thanks!

question

All 23 comments

The Yang extension is a complete example using this stack:
https://github.com/theia-ide/yang-lsp.

sure thing, I will analyze that. Thank you.

Please keep it open.

Hi All,
Good Evening / Morning!

I went through the above example and some conference videos of sprotty framework. I understood the basic architecture. But not getting how the Diagram server(DSL) is connecting to Diagram generator(sprotty client (Theia Widget)).

I would really appreciate if someone can give me a guideline/ share some pointers.
Yang example is a bit too abstract.

Thanks!

I hope you're using Xtext for your LSP :-)

We enhance the LSP with a few sprotty related methods (client, server), in order to connect the sprotty enhanced LS to the the sprotty enhanced client.

Hope this helps.

Hi there,
Yes, I am using Xtext for LSP.
Firstly thank you for sharing above pointer, I am currently going through it and Yangster example.

PS: I understand the examples, but what if I have to leverage these examples to build and understand sprotty + xtext(DSL) project of my own, which I am actually working upon.

The package manager commands/ installations are for running the samples, but where can I find some information which states how it's being developed (Integration). Do I just have to put my LSP in some place or I can create a whole thing.

I apologize if it's the repetitive question, but I am trying to understand how things are working.

Question 2: If I want to create a new diagram in sprotty, which visualizes as an actor, is that possible?

I am working on my thesis, which involves sprotty+theia+xtext as a base(root) and using these I have to create UML Goal / Scenario models. And in the end, put collaboration in place.

I will thoroughly go through the entire sample and will see if it helps.

Thanks!

Sorry that the entire story is still a bit rough around the edges. I'd suggest you start with a plain, non-sprotty Xtext LS and integrate it with Theia, then add sprotty support in a second step.

1) The LSP is usually started by Theia in the backend part of the extension, as soon as a file with the given extension is opened.

The DSL has to be registered as a language contribution to the frontend of the theia extension

For development, I usually start the backend in debug mode from Eclipse using this main class

2) I guess you mean: Can I create a view that looks like an actor in UML (usually a stickman)?
Answer: yes. You have to create your own implementation of IView, that returns the SVG representation of that figure in its render method. If you don't want to add it programmatically, but load it from an SVG file instead, have a look at
https://github.com/theia-ide/sprotty/blob/0ab0b2a8b1eefd7788a1c45e102c38896f702ce0/client/examples/svg/src/standalone.ts#L26

Hi there, thank you very much for putting your time and sharing details!

workdone: I have completed the (Xtext)DSL integration with Theia part, I am working on the second step, in which sprotty comes into frame.

PS: I was just executing the yangster example, however it throws URI issue during yarn installation.

Below:
src/frontend/language/yang-language-client-contribution.ts(57,29): error TS2345: Argument of type 'URI' is not assignable to parameter of type 'URI | PromiseLike | undefined'.
Type 'URI' is not assignable to type 'PromiseLike'.
Property 'then' is missing in type 'URI'.
src/frontend/yangdiagram/yang-diagram-manager.ts(30,60): error TS2345: Argument of type 'LanguageClientContribution' is not assignable to parameter of type 'LanguageClientContribution'.
Types of property 'waitForActivation' are incompatible.
Type '(app: FrontendApplication) => Promise' is not assignable to type '(app: FrontendApplication) => Promise'. Two different types with this name exist, but they are unrelated.
Types of parameters 'app' and 'app' are incompatible.
Type 'FrontendApplication' is not assignable to type 'FrontendApplication'. Two different types of this name exist, but they are unrelated.
Property 'commands' is protected but type 'FrontendApplication' is not a class derived from 'FrontendApplication'.

I tried few things with Request_promise but it did not work.
I have attached word document with log details, kindly have a look.
LanguageContributionFail.docx

Thank you!

This is likely because you haven't checked out the Git submodules.
Use

git clone --recursive https://github.com/theia-ide/yangster.git

to clone the yangster repo.

Background: As this is the reference project of integrating Theia and sprotty, we often need to apply changes to a couple of repos for a single issue. We use Git submodules to check out all relevant repos into the yangser root directory and then build them all together.

Hi there,

Thank you again!

Learning: I got a very good understanding of the sprotty part. And I have tried adding my own symbols and played around with existing example in yangster project.

When it comes to "Server" part:

  1. There is one folder: xtext-diagram under sprotty, which has "TestLanguage.xtext" example.
    And then another one which is outside yangster folder i.e. yang-lsp, which has another "yang-xtext" example.
    Which one to refer?

  2. Yang-lsp: In this project, I see a difference from the Xtext LSP which I had created, a difference of io.typefox.yang.diagram this file. Are there any specific set of steps, need to follow while creating it. because If I do exactly like yang-lsp(diagram) file in my xtext-lsp. It does not pick my lsp.

  3. Class "YangModel.xtext" the classes which are used in it namely(YangNode, YangHeader, YangLabel etc) is it an example of Yang.xtext model? Because these classes are then referred in creating SModel under yang-sprotty. And if I have to create SModel of my Xtext (DSL model) should I be creating a file like (YangModel.xtext) first?

I am sharing the Xtext LSP generation link which I had followed.
https://typefox.io/tutorial-building-a-language-server-for-your-dsl.

Appreciate your time and attention!

It started picking my LSP :)

Good to hear you're making progress.

  1. The test language is, as the name suggests, a language we use in the tests. It should not matter to you. The grammar of the yang language is this one https://github.com/theia-ide/yang-lsp/blob/master/yang-lsp/io.typefox.yang/src/main/java/io/typefox/yang/Yang.xtext

  2. io.typefox.yang.diagram is the gradle project that contains the sprotty-speficic diagram extensions of the YANG LSP. This is where you should get your ideas from, how to do the server-side of the sprotty part for your language and how to use For simplicity, you could add the same stuff just in the .ide project.

  3. YandModel.xtend contains the YANG specific extensions for sprotty's diagram model, AKA SModel. If you want to transfer domain specific information on your diagram elements between client and server, you do it by extending the SModel, and implement it on client and server.

Hi there, thank you very much for sharing information.

I had tried making changes in below files, namely:
io.typefox.yang.diagram: YangDiagramGenerator.xtend , YangModel.xtend
yang-sprotty: di.config.ts, views.tsx, yang-model.ts

I tried to follow yang example for converting domain model to SModel. But it does not work somehow.
And is a bit hard to understand YangDiagramGenerator.xtend file.

May I please know, am I following the right set of files or am I missing any implementation here for connectivity.?

Thank you for putting your time!

The YangGenerator is very complex as it deals with a pretty complicated language. What you have to know is that it generates an SModel (Sprotty) from the AST model (Xtext).

In a client -server setting, things can go wrong in multiple places, so I'd start debugging and inspecting the logs.

On the client side, it's usually good to put a breakpoint in diagram-server.ts (Chrome debugger) handle(action: Action) and watch what kind of actions come through.
I'd expect something like described in https://github.com/theia-ide/sprotty/wiki/Client-Server-Protocol#c-client-and-server-layout
From that, you can find out whether it's a client or a server problem.

On the server, DefaultDiagramServer.accept() would be a good start for debugging.

Hi there, greetings :)

Yea given example (yangDiagramGenerator.xtend)'s visualization is working perfectly fine.
I found the issue is with my xtend grammar, I am trying to make it work.
Unless the grammar is correct, it won't show the visualization on the server.

Thank you very much for guiding me through the process.
Will get back with the results :)

Hi there, good morning/evening!

I am successfully able to generate the visualization of a module form my xtext grammar module. 馃憤

I have a question: is it possible if we can generate diagram view of individual resources.

Like if the user wants to see the visualization of each resource individually instead of all at once, in a similar pattern as we get outline generated of our model. And if the user wants to visualize any of the resources can just generate a diagram.

For Example, Screen Shot attached, the way outline gets generated.
Is there any possible mean if we can make it possible or is it already implemented / under implementation or cannot be done.

Thank you!

screen shot 2018-06-22 at 6 24 10 pm

I am not sure what you mean. In EMF (and Xtext) a _resource_ is equivalent to one file, and that's the scope that the diagram generator gets in. How much of that resource (and other cross-referenced ones) is visualized, is determined here and therefore up to you to implement. In yangster, we show the module (file) as well, and it's referenced modules only on demand. So yes, that's implemented, and available in the UI via contest menu entries in the editor on the files in the navigator.

If _resource_ for you means _model element_ (one node in the outline, maybe a map in your model) then this requires additional UI that you have to implement.

@JanKoehnlein - Is it possible to customize the Outline-view-widget in order to create a menu for it so that separate diagram can be generated for each model element? Currently, we can only expand it as a tree and the model elements are not editable through any menu.

@Rijul5 That's possible, but it requires a bit of work.

Add context menu for outline:

Have a look at how we registered and populate the context menu in the navigator, namely
https://github.com/theia-ide/theia/blob/248775060d2e4815306ac025b18f67364ff5d62a/packages/navigator/src/browser/navigator-container.ts#L48
https://github.com/theia-ide/theia/blob/248775060d2e4815306ac025b18f67364ff5d62a/packages/navigator/src/browser/navigator-container.ts#L30
https://github.com/theia-ide/theia/blob/248775060d2e4815306ac025b18f67364ff5d62a/packages/navigator/src/browser/navigator-contribution.ts#L98
and transfer that to the outline view, e.g. by rebinding
https://github.com/theia-ide/theia/blob/248775060d2e4815306ac025b18f67364ff5d62a/packages/outline-view/src/browser/outline-view-frontend-module.ts#L25

Adapt open diagram command

Then add an appropriate open command that also contains the information on the symbol. Currently, different diagrams need different URIs. This is why I'd recommend to encode the symbol's location as the fragment of the URI.

Adapt the server

  • IDiagramGenerator needs to know which element in the resource it should generate the diagram for. I'd propose to put that information in the IDiagramState.

That may not be the entire story, but it is how I would approach this task.

BTW, just as you mentioned editing (=changing) an element in the outline by means of the context menu, I'd rather avoid that.

@JanKoehnlein - Thank you for explaining this in detail. Firstly, I only want to bind the menu to outline-widget and do not want to make it editable(=changing). I think the approach suggested by you will help us a lot in achieving the scenario where we can open different diagrams for model elements. I am currently trying the same and will update you shortly.

Secondly, I would like to know that if I make the changes in Theia packages for outline-view in Theia project then how can I use the built packages/node modules in the Yangster project. Currently, I am using my own grammar and its Sprotty representation in the same Yangster project for experimental purposes. Please guide on this.

@Rijul5 This usually depends on what you want to change. In many scenarios, it's just OK to use dependency injection and rebind some service in the container module of _your_ extension without applying changes to the _original_ extension.

The binding you would want to change is the one of TreeProps in the outline view which is defined in the child container returned by createOutlineViewWidget()
That method is called in the outline widget factory.

So in the frontend module of your extension
1) get the rebind callback by specifying all four parameters in the new ContainerModule constructor
2) use it to rebind OutlineViewWidgetFactory to a factory that calls a new method createOutlineViewWidgetWithContextMenu
3) implement that method to similar to createOutlineViewWidget but rebind the TreeProps of the container to the implementation that defines a context menu path.

For more details on DI, please refer to the documentation of Theia and InversifyJS.

@JanKoehnlein - Thank you for the detailed information on this step. Now, I am able to change the binding in outline view and can see the menu for outline view as well. PFB the screenshot for your reference.

image

Using the command "Generate Diagram", I am able to open the diagram for the entire Xtext model(for the given URI). I am using something similar to OpenInDiagramHandler to generate the diagram for the URI. However, I want to access the model element information so that I can encode this as the URI as suggested by you. Therefore, can you please elaborate how can I get the symbol information and encode it as the URI. Also, which files/methods need to be changed for making IDiagramGenerator compatible to the version where we are generating a diagram for each model element?

Finally, for developing is there a better way to see the changes on the client side. For the server, we can connect the running LSP through a socket and it is easy. However, for the client, I am not sure if there is any way similar to this because running yarn or yarn watch commands are expensive. Please guide on this.

Hi there,

Query: can we create two SGraph's in one digramGenerator file.

Example: If we want two child elements of the same type (Let's say Actor) under one diagram module.
Is it possible?

Actor One -> 2 Goals = A and B
Actor Two -> 3 Goals = C , D and E

we want to create a dependency relation of one actor's goal on another actor in the same diagram module.
LIKE: Goal A depends upon Goal D

Kindly suggest on this.

Hi there,

I am successful in integrating my DSL language server with Theia, but now I would like to use sprotty to visualize the content.

I have gone through one example online: https://github.com/theia-ide/theia-sprotty-example

It executes well, but not so clear how one can use sprotty with (XText LSP into Theia).

I would appreciate your inputs.
Thanks!

Hello, I am working on integrating my sprotty with theia and DSL language server. But I meet some problems. My sprotty does not show successfully.
[Error - 涓嬪崍2:46:55] Error during request: : java.lang.IllegalArgumentException: null is not an XtextResource
at org.eclipse.sprotty.xtext.tracing.PositionConverter.toPosition(PositionConverter.java:63)
at org.eclipse.sprotty.xtext.tracing.PositionConverter.toRange(PositionConverter.java:71)
at org.eclipse.sprotty.xtext.tracing.PositionConverter.toRange(PositionConverter.java:67)
at org.eclipse.sprotty.xtext.tracing.XtextTraceProvider.doTrace(XtextTraceProvider.java:85)
at org.eclipse.sprotty.xtext.tracing.XtextTraceProvider.trace(XtextTraceProvider.java:77)
at io.typefox.examples.theia.states.ide.diagram.StatesDiagramGenerator.lambda$toSNode$4(StatesDiagramGenerator.java:72)
at org.eclipse.sprotty.SNode.(SNode.java:47)
at io.typefox.examples.theia.states.ide.diagram.StatesDiagramGenerator.toSNode(StatesDiagramGenerator.java:84)
at io.typefox.examples.theia.states.ide.diagram.StatesDiagramGenerator.lambda$null$0(StatesDiagramGenerator.java:55)
at org.eclipse.xtext.xbase.lib.internal.FunctionDelegate.apply(FunctionDelegate.java:43)
at com.google.common.collect.Lists$TransformingRandomAccessList$1.transform(Lists.java:612)
at com.google.common.collect.TransformedIterator.next(TransformedIterator.java:47)
at org.eclipse.sprotty.SModelIndex.addToIndex(SModelIndex.java:72)
at org.eclipse.sprotty.SModelIndex.(SModelIndex.java:52)
at org.eclipse.sprotty.LayoutUtil.copyLayoutData(LayoutUtil.java:54)
at org.eclipse.sprotty.DefaultDiagramServer.updateModel(DefaultDiagramServer.java:189)
at org.eclipse.sprotty.xtext.ls.DiagramUpdater.lambda$null$3(DiagramUpdater.java:129)
at java.util.ArrayList.forEach(ArrayList.java:1257)
at org.eclipse.sprotty.xtext.ls.DiagramUpdater.lambda$doUpdateDiagrams$4(DiagramUpdater.java:132)
at org.eclipse.xtext.ide.server.LanguageServerImpl$1.lambda$null$0(LanguageServerImpl.java:1117)
at org.eclipse.xtext.ide.server.WorkspaceManager.doRead(WorkspaceManager.java:479)
at org.eclipse.xtext.ide.server.LanguageServerImpl$1.lambda$doRead$1(LanguageServerImpl.java:1116)
at org.eclipse.xtext

Was this page helpful?
0 / 5 - 0 ratings