Skip to content

LSP extensions

sysml-lsp speaks the Language Server Protocol, plus the three methods on this page. They are not in the protocol, so a client must ask for them by name; the server says it serves them by advertising, in the initialize result:

{ "capabilities": { "experimental": { "openSysmlRender": true } } }

A client that does not see that capability must not send these methods — that is how a new client and an older server stay compatible.

Everything here is read-only: it renders what a document says, and never writes it. The renderings are the ones %view and sysml -view produce, from the same renderer.

opensysml/render (request)

Renders one view of a document.

{
  "textDocument": { "uri": "file:///tmp/kit.sysml" },
  "view": "KitViews::widgetTree",
  "form": "mermaid"
}
Field Meaning
textDocument.uri The document to render. It must be one the session holds — an open document, or a workspace file the server read.
view The qualified name of a view the document declares, a pseudo-view (below), or omitted.
form mermaid, text or markdown. Omitted writes the machine form of the rendering's kind: markdown for a table, mermaid for every other kind.

Omitting view renders the view the document declares. A document declaring several is ambiguous, and the request fails naming them (declares 6 views (KitViews::widgetActions, …); name the one to render) rather than picking one; a document declaring none fails pointing at the pseudo-views.

A form a rendering is not written in — Mermaid for a table, Markdown for a diagram — is refused with the form the kind is written in instead, and a form that is no form at all is refused naming the three.

Pseudo-views. A document being written usually declares no view, so a rendering can be asked for as if one had been declared:

view Renders
#tree Everything the document declares, as a tree
#interconnection …as an interconnection diagram
#state …as a state diagram
#action …as an action flow
#table …as an element table
#state:Kit::WidgetStates One element the document declares, here as a state diagram

A pseudo-view adds nothing to the model and nothing to the symbol index: the exposed set is passed to the renderer directly, and the result reports it in stated, as no view declared; rendering Kit::WidgetStates directly.

The result, for {"view": "KitViews::widgetTree"} over a document declaring part def Widget { part cog : Cog; part gear : Cog; connect cog to gear; }:

{
  "view": "KitViews::widgetTree",
  "kind": "tree",
  "stated": "",
  "form": "mermaid",
  "artifact": "%% KitViews::widgetTree — tree rendering\nflowchart TD\n  n0[\"part def Kit::Widget\"]\n  n1[\"part cog (Cog)\"]\n  n0 --- n1\n  …",
  "nodes": [
    {
      "id": "n0",
      "kind": "part def",
      "name": "Kit::Widget",
      "detail": "",
      "origin": {
        "uri": "file:///tmp/kit.sysml",
        "range": { "start": { "line": 1, "character": 1 }, "end": { "line": 6, "character": 1 } },
        "selectionRange": { "start": { "line": 1, "character": 10 }, "end": { "line": 1, "character": 16 } }
      }
    },
    {
      "id": "n1",
      "kind": "part",
      "name": "cog",
      "detail": "Cog",
      "parent": "n0",
      "origin": { "uri": "file:///tmp/kit.sysml", "range": { "…": "…" } }
    }
  ],
  "edges": [{ "from": "n0", "to": "n1", "label": "", "kind": "connection" }],
  "notices": [],
  "version": 7
}
Field Meaning
view The view rendered, by qualified name; empty for a pseudo-view.
kind tree, interconnection, state, action or table.
stated How the kind was decided — the rendering the view names, the standard view definition it specializes, or that no view was declared. Empty when the view took the default.
artifact What to draw or show: a Mermaid diagram, the text form, or a Markdown table.
nodes, edges What the artifact is made of, so a client can map a click on it back to the source. A node's parent is the node containing it, when one does. An edge's kind is connection, transition, succession or flow.
rows, columns A table rendering's cells, in place of nodes and edges.
origin Where the element was declared, as a document URI, the range of the whole declaration and, when the declaration names one, the selectionRange of the identifier alone. A client highlights the element whose range holds the cursor and navigates to its selectionRange, as textDocument/definition does. Absent for an element with no locatable declaration: a standard library symbol the index served from its cache, or a step a lowering sequenced without a declaration of its own, carries none rather than a bogus range.
notices What the rendering could not represent, as the text form reports it.
version The version of the document the rendering was made from, so a client can tell a rendering of the text it is showing from a stale one.

A view stating a rendering this implementation does not produce — sequence, geometry, textual — fails with the reason, e.g. KitViews::widgetSequence: sequence rendering (view def SequenceView) is not supported.

opensysml/views (request)

Lists the views a document declares, which is what fills a diagram panel's view picker.

{ "textDocument": { "uri": "file:///tmp/kit.sysml" } }
{
  "views": [
    { "name": "KitViews::widgetParts", "kind": "interconnection", "supported": true },
    {
      "name": "KitViews::widgetSequence",
      "kind": "sequence",
      "supported": false,
      "reason": "KitViews::widgetSequence: sequence rendering (view def SequenceView) is not supported"
    }
  ]
}

Views come in qualified-name order. An unsupported one stays in the listing, with supported: false and the reason, so a client can say why it cannot be drawn instead of hiding it.

opensysml/renderChanged (notification, server → client)

{ "textDocument": { "uri": "file:///tmp/kit.sysml" }, "version": 8 }

Sent after the analysis that publishes the document's diagnostics, so a client sees the diagnostics of a version before the notification for it. It is debounced on the window the cross-document diagnostics sweep uses, so a burst of keystrokes costs one notification rather than one per keystroke.

It carries no artifact: the client answers with a fresh opensysml/render if it is showing the document, and does nothing if it is not — which keeps a large diagram off the wire for a panel nobody is looking at.

Trying it by hand

The protocol is JSON-RPC over stdio, so the methods can be driven without an editor — initialize, textDocument/didOpen, then:

→ opensysml/render  { "textDocument": { "uri": "file:///tmp/kit.sysml" }, "view": "#tree" }
← { "view": "", "kind": "tree",
    "stated": "no view declared; rendering /tmp/kit.sysml directly",
    "form": "mermaid",
    "artifact": "%%  — tree rendering (no view declared; …)\nflowchart TD\n  n0[\"part def Kit::Widget\"]\n…",
    "nodes": [ … ], "edges": [ … ], "notices": [], "version": 1 }

The VS Code extension's diagram panel is the reference client — see the editors guide.