Aller au contenu principal

Language Server (LSP)

The OPC UA Modeler ships a fully standard Language Server Protocol server. VS Code users get it automatically via the VS Code Extension. For all other editors — Neovim, Zed, Emacs, or any LSP-compliant tool — this page covers manual setup.

Starting the server

# stdio mode — for editors that spawn the server as a child process
opcua-modeler lsp --stdio

# socket mode — for multi-client / WebSocket setups (e.g. browser-based editors)
opcua-modeler lsp --socket 7000

Neovim (nvim-lspconfig)

Add the following to your Neovim configuration (Lua):

local lspconfig = require("lspconfig")
local configs = require("lspconfig.configs")

-- Register the custom server if not already known
if not configs.opcua_modeler then
configs.opcua_modeler = {
default_config = {
cmd = { "opcua-modeler", "lsp", "--stdio" },
filetypes = {
"yaml", -- general YAML; restrict via root_dir if needed
},
root_dir = lspconfig.util.root_pattern("*.model.yaml", "*.nodeset.yaml", ".git"),
single_file_support = true,
settings = {},
},
}
end

lspconfig.opcua_modeler.setup({})

Tip: If you only want the OPC UA LSP to activate on .model.yaml / .nodeset.yaml files, add a custom filetypes detection or use vim.filetype.add to map those extensions to a dedicated filetype (e.g. opcua_yaml) before calling setup.


Zed

Add the following to your Zed settings.json (or ~/.config/zed/settings.json):

{
"lsp": {
"opcua-modeler": {
"binary": {
"path": "opcua-modeler",
"arguments": ["lsp", "--stdio"]
}
}
},
"languages": {
"YAML": {
"language_servers": ["opcua-modeler", "..."]
}
}
}

Emacs

With eglot (built-in from Emacs 29+)

(with-eval-after-load 'eglot
(add-to-list 'eglot-server-programs
'(yaml-mode . ("opcua-modeler" "lsp" "--stdio"))))

;; Auto-start eglot when opening model files
(add-hook 'yaml-mode-hook #'eglot-ensure)

With lsp-mode

(with-eval-after-load 'lsp-mode
(lsp-register-client
(make-lsp-client
:new-connection (lsp-stdio-connection
'("opcua-modeler" "lsp" "--stdio"))
:activation-fn (lsp-activate-on "yaml")
:server-id 'opcua-modeler)))

Socket / multi-client mode

For setups where multiple editors or a browser-based editor connect to a single shared server, use the --socket flag:

# Start a persistent LSP server on port 7000
opcua-modeler lsp --socket 7000

Clients connect via WebSocket or TCP to localhost:7000. The server maintains isolated per-connection state (document buffers, debounce timers, capability flags) while sharing the expensive OPC UA address space cache across all connections.


Diagnostics reference

The server emits diagnostics using structured codes in the form DSL-E-*, DSL-W-*, and DSL-I-*.

PrefixSeverityDescription
DSL-E-*ErrorMust be fixed — invalid or illegal model construct
DSL-W-*WarningPotentially incorrect — shown by default, suppressed with --quiet
DSL-I-*InfoStyle / conformance hints — hidden by default, shown with --style

Semantic checks performed

The following semantic diagnostics are produced by Layer 2:

CheckExample message
Invalid typeDefinition referenceUnknown type 'MySensor' — not found in address space
Invalid subtypeOf reference'MyBase' is not an ObjectType
Broken organizedBy / componentOf browse pathPath 'Root/Objects/Tank' does not exist in node tree
Invalid promotedToMandatory entry'Status' is not an optional member of 'SensorType'
Duplicate initializers: variable: entriesDuplicate initializer path 'Parameters/MaxValue'
Duplicate $anchor IDsAnchor 'pump1' is already defined on line 42
Self-referencing placementNode cannot reference itself or its own subtree as placement parent
YAML syntax errorYAML parse error at line 12: unexpected ':'

Suppressing specific codes

Use the --silence flag on the CLI, or configure suppressions in your project:

# Suppress a specific warning code
opcua-modeler generate --silence DSL-W-001

# Suppress all warnings matching a prefix
opcua-modeler generate --silence DSL-W

Address space cache

The server loads the OPC UA base address space (and all imported companion specs) once and caches it across all open connections. This means:

  • The first open of a model file may take a second while the address space loads
  • Subsequent completions and diagnostics are near-instant

The cache is invalidated when the list of namespaces: imports in your file changes.