A Language Server Protocol implementation for the Umple modeling language. Provides IDE features for .ump files across multiple editors.
π Contributors / future maintainers β start at
wiki/README.md. The wiki has the full handoff documentation: architecture, dev setup, all four publishing pipelines (npm / VS Code / Zed / Neovim), CI automation, the AI-collab review protocol, and known gotchas.
- Diagnostics - Real-time error and warning detection via the Umple compiler
- Go-to-definition - Jump to classes, interfaces, traits, enums, attributes, methods, state machines, states, associations, mixsets, and requirements. Container-scoped resolution prevents false cross-class jumps. Includes reused standalone statemachine fallback.
- Find references - Semantic reference search with state-path disambiguation, inheritance chain walking, and shared-state equivalence for reused standalone statemachines
- Rename - Safe rename across all references (same pipeline as find-references)
- Hover - Contextual information for symbols with markdown formatting
- Code completion - Context-aware keyword and symbol suggestions
- Document symbols - Hierarchical outline of classes, state machines, states, attributes, methods
- Formatting - AST-driven indent correction, arrow spacing, blank-line normalization, compact state expansion
- Syntax highlighting - Tree-sitter grammar for accurate highlighting
- Cross-file support - Transitive
usestatement resolution and cross-file diagnostics - Import error reporting - Errors in imported files shown on the
usestatement line - Diagram navigation - Custom LSP requests (
umple/resolveStateLocation,umple/resolveTransitionLocation) for click-to-select in UML diagrams
The table below shows the LSP's support for Umple language features, based on the Umple Grammar. Priority: ** = high, * = lower.
| Feature | Priority | Status | Notes |
|---|---|---|---|
| Directive (top level) | |||
| generate | * | β | Language names, path, --override, -s suboption |
| suboption | * | Syntax works; specific suboption names not enumerated | |
| filter | * | β | Named/unnamed, numeric names, glob patterns, hops; class completions in include; go-to-def for plain names |
| useStatement | ** | β | File completions and go-to-def; lib: paths parse cleanly (runtime resolution deferred); comma-separated use A.ump, B.ump; |
| requireStatement | ** | β | require [mixset], require subfeature [...] with boolean operators |
| isFeature | * | β | Feature declarations in mixsets and top-level |
| requirement | ** | β | Parsed, indexed, go-to-def |
| reqImplementation | ** | β | Identifiers reference requirements; go-to-def |
| Entity | |||
| mixsetDefinition | ** | β | Top-level and inside class/SM bodies |
| classDefinition | ** | β | Including nested classes |
| Class content | |||
| displayColor | ** | β | In class body and state body |
| abstract | ** | β | abstract; standalone |
| immutable | ** | β | immutable; standalone |
| keyDefinition | ** | β | key { attr1, attr2 } with attribute references |
| softwarePattern (isA, singleton, codeInjection) | ** | β | |
| depend | ** | β | |
| symmetricReflexiveAssociation | ** | β | |
| attribute | ** | β | All modifiers (incl. immutable), typed/untyped, defaults |
| inlineAssociation | ** | β | All arrow types; type refs include traits and interfaces |
| concreteMethodDeclaration | ** | β | Visibility, static, return type, params |
| constantDeclaration | ** | β | |
| enumerationDefinition | ** | β | Inside class or top-level |
| templateAttributeDefinition | * | β | name <<! ... !>> |
| emitMethod | * | β | emit name(params)(templates); |
| invariant | * | β | Both [expr] and named [name: expr]; name field is structurally distinct |
| State machine | |||
| inlineStateMachine | ** | β | With queued/pooled |
| state | ** | β | Nested states, concurrent regions (||) |
| transitions (event/guard/action) | ** | β | All forms: event, guard, pre-arrow action, post-arrow action; guard-before-event ordering; timed events after(N)/afterEvery(N) |
| guard semantics | ** | β | Structured constraint expressions; go-to-def and completion on attributes/constants inside guards (own + inherited); event params and method calls deferred |
| entry / exit / do | ** | β | Optional guard and language-tagged code blocks |
| referencedStateMachine | ** | β | sm as baseSM { ... } reuse; shared-state equivalence for refs/rename; diagram click navigation with alias-local-first / base-fallback |
| changeType markers (+/-/*) | ** | β | |
| standaloneTransition | ** | β | In SM body and state body |
| final states | ** | β | Final auto-terminal; final stateName {} explicit final |
| trace statements | * | β | Common forms: trace, tracecase, activate/deactivate; postfix clauses; full MOTL coverage not yet verified |
| concreteMethodDeclaration (in state body) | * | β | Methods inside state bodies |
| mixsetDefinition (in SM/state) | ** | β | In SM body, state body, and top-level |
| activeDefinition | * | β | active [codeLangs] [name] moreCode+; comma-separated lang tags are spec-valid but crash current compiler (E9100 bug) |
| Top-level entities | |||
| traitDefinition | * | β | Parameters (isA constraints, default types, &-multi-constraint), abstract methods, nested traits, application-side bindings |
| interfaceDefinition | ** | β | |
| associationDefinition | ** | β | |
| associationClassDefinition | ** | β | |
| stateMachineDefinition | ** | β | |
| topLevelCodeInjection | * | β | before/after/around { Class } op { code } |
| codeInjection (wildcard) | * | β | before/after with wildcard event patterns: e*, ev*eee, etc. |
| templateDefinition (top-level) | * | β | Excluded for project scope: official grammar defines it, but non-empty top-level templates crash the current compiler and no manual examples exist |
Summary: β
45 supported, β 0 not supported,
| Editor | Repo | Auto-installs server? |
|---|---|---|
| VS Code | umple.vscode (Marketplace) | Bundled in .vsix at packaging time (not auto-pulled at runtime) |
| Zed | umple.zed (Zed Extensions) | Yes β downloaded from npm at extension load |
| Neovim | umple.nvim | Yes β npm install umple-lsp-server during plugin build |
| IntelliJ / JetBrains | Setup guide (LSP4IJ + npm) | No (npm install -g) |
| BBEdit | Setup guide (plist + npm) | No (npm install -g) |
| Sublime Text | Setup guide (config only) | No (manual build) |
The LSP server is also available as an npm package: umple-lsp-server
- Node.js 20+ (tested on 20 and 23)
- Java 11+ (for the Umple compiler β only needed if you want diagnostics)
npm install
npm run compile
npm run download-jarThen install the plugin for your editor (see table above).
umple-lsp/
βββ packages/
β βββ server/ # Standalone LSP server (npm: umple-lsp-server)
β β βββ src/
β β β βββ server.ts # LSP wiring, handlers, diagnostics orchestration
β β β βββ symbolIndex.ts # Symbol indexing, storage, queries
β β β βββ resolver.ts # Go-to-def / hover / rename symbol resolution
β β β βββ completionAnalysis.ts # Completion context detection (scope, keywords)
β β β βββ completionBuilder.ts # Completion item assembly
β β β βββ tokenAnalysis.ts # Token/context detection at cursor position
β β β βββ referenceSearch.ts # Find-references semantic matching
β β β βββ hoverBuilder.ts # Hover markdown content builders
β β β βββ documentSymbolBuilder.ts # Document outline (symbol hierarchy)
β β β βββ formatter.ts # Document formatting (indent, spacing, expansion)
β β β βββ formatRules.ts # Formatting node classification
β β β βββ formatSafetyNet.ts # Pre/post symbol-set check; aborts unsafe formats
β β β βββ diagramNavigation.ts # Diagram click-to-select resolution
β β β βββ diagramRequests.ts # Custom LSP request handlers for diagrams
β β β βββ importGraph.ts # Forward/reverse import edge management
β β β βββ traitSmEventResolver.ts # Trait-side SM operation event lookup
β β β βββ renameValidation.ts # RENAMEABLE_KINDS + kind-aware new-name regex
β β β βββ tokenTypes.ts # Shared token/symbol type definitions
β β β βββ symbolTypes.ts # Shared symbol entry types
β β β βββ treeUtils.ts # Shared tree-walking utilities
β β β βββ keywords.ts # Built-in type names
β β βββ bin/umple-lsp-server # 2-line shell shebang requiring out/server.js
β β βββ test/ # Semantic regression tests
β β βββ semantic.test.ts # Test runner (682 assertions)
β β βββ helpers.ts # Test harness helpers
β β βββ fixtures/semantic/ # .ump fixture files
β βββ tree-sitter-umple/ # Tree-sitter grammar & queries
βββ editors/ # Setup guides for Sublime, manual Neovim config
βββ test/ # Sample .ump files
Editor Plugin (separate repos)
β
βββ (stdio) βββΊ server.ts βββΊ umplesync.jar (diagnostics)
β
βββ resolver.ts βββΊ symbolIndex.ts (go-to-def, hover, rename)
βββ completionAnalysis.ts + completionBuilder.ts (completion)
βββ referenceSearch.ts (find-references)
βββ hoverBuilder.ts (hover content)
βββ documentSymbolBuilder.ts (outline)
βββ formatter.ts (formatting)
βββ diagramNavigation.ts + diagramRequests.ts (diagram clicks)
βββ tokenAnalysis.ts + treeUtils.ts (shared analysis)
- Server (
packages/server/) β Editor-agnostic LSP server (npm-publishable asumple-lsp-server). Split into focused modules:server.tshandles LSP wiring and diagnostics orchestration; semantic logic lives in dedicated modules. - Tree-sitter grammar (
packages/tree-sitter-umple/) β Parser and syntax highlighting queries
The server uses lazy indexing: files are only parsed when opened, and only files reachable via use statements are indexed. This keeps startup fast regardless of workspace size.
The tree-sitter grammar in packages/tree-sitter-umple/ is used by both the LSP server (for symbol indexing) and editors like Neovim (for syntax highlighting).
After editing grammar.js:
npm run build-grammar # Regenerate parser + WASM + compile serverThe LSP server accepts these initialization options:
| Option | Type | Default | Description |
|---|---|---|---|
umpleSyncJarPath |
string | auto-discovered at <server>/../umplesync.jar since v0.2.6 |
Path to umplesync.jar. Diagnostics are silently disabled if the jar can't be found. |
umpleSyncTimeoutMs |
number | 30000 | Timeout for umplesync per-request process (ms) |
Environment variables: UMPLESYNC_JAR_PATH, UMPLESYNC_TIMEOUT_MS, UMPLE_TREE_SITTER_WASM_PATH
In-depth docs:
wiki/03-development.mdcovers first-time setup, dev symlink mode, programmatic test probes, and editor-specific reload tips. The summary below is just the most-used commands.
npm run compile # Build server (also copies WASM)
npm run build-grammar # Full rebuild after grammar.js changes
npm run watch # Watch mode
npm test # Run semantic regression tests (682 assertions)The project includes a semantic regression test harness that exercises go-to-definition, find-references, completion, hover, document symbols, and formatting. Tests use real .ump fixture files with /*@marker*/ annotations for position-independent assertions.
npm test # Compile + run all 682 assertionsRun the server directly for JSON-RPC testing:
node packages/server/out/server.js --stdioSee wiki/ for the full project handoff:
| Topic | Page |
|---|---|
| What this project is + architecture | 01-overview, 02-architecture |
| Setup, build, test | 03-development |
| Editing the grammar | 04-grammar |
| Releasing β npm | 05-publishing-npm |
| Releasing β VS Code | 06-publishing-vscode |
| Releasing β Zed | 07-publishing-zed |
| Releasing β Neovim | 08-publishing-nvim |
| BBEdit / IntelliJ / Sublime | 09-other-editors |
| CI automation | 10-ci-automation |
| Review process (collab w/ Codex) | 11-collab-protocol |
| Common pitfalls | 12-gotchas |
| Roadmap + known gaps | 13-roadmap |