SysML v2 语言服务器

一个为 SysML v2 建模语言提供语言服务器协议实现的开发工具,支持语法诊断、代码补全、导航引用、模型语义验证、复杂度分析与 Mermaid 预览,可集成到 VS Code、Web 与 Python 客户端。

  • by daltskin
  • TypeScript
  • 本地部署
  • 22 星标
  • 更新于
在 GitHub 查看 daltskin/sysml-v2-lsp

使用说明

SysML v2 Language Server

A Language Server Protocol (LSP) implementation for SysML v2.

Features

Feature Status Description
Diagnostics ✅ Syntax error reporting with red squiggles
Document Symbols ✅ Outline panel with SysML model structure
Hover ✅ Element kind, type, and documentation on hover
Go to Definition ✅ Ctrl+Click navigation to declarations
Find References ✅ Find all usages of a symbol
Code Completion ✅ Keywords, snippets, and symbol suggestions
Semantic Tokens ✅ Rich, context-aware syntax highlighting
Folding Ranges ✅ Collapsible { } blocks and comments
Rename ✅ Rename symbol and all references
Semantic Validation ✅ Unresolved types, invalid multiplicity, duplicates
Code Actions ✅ Quick-fixes: naming, doc stubs, empty enums, unused defs
Complexity Analysis ✅ Structural metrics, composite index, hotspot detection
Mermaid Preview ✅ 6 diagram types with auto-detect, focus, and diff modes
MCP Server ✅ AI-assisted modelling via sysml-mcp CLI

Quick Start

Unicode and unrestricted names

Use single quotes for names outside the ASCII basic-name syntax, for example attribute 'temperature Ω' : Real;. Names may contain Unicode characters, combining marks, spaces and escaped quotes or backslashes. Their spelling is preserved without Unicode normalization (SysML 7.2.2; KerML 8.2.2.3).

Navigation, hover, references, rename and completions handle the whole quoted name. Rename updates resolved workspace references, not comments, string literals, usage names or unrelated same-named declarations. Completion and rename insert the required quotes and escapes automatically; editor positions use UTF-16, including after characters outside the Basic Multilingual Plane.

Experimental text validation

sysml/validateText checks proposed document texts against the current workspace, including unsaved documents, without opening documents or publishing diagnostics. It is disabled by default. Enable sysml.experimental.validateText.enabled to use it. Requests contain documents, an array of { uri, text } entries. The response contains each requested URI and its diagnostics, in request order.

The default limits are 5 documents, 200 lines per document, 8,192 characters per document, and 16,384 characters across the request. Characters are UTF-16 code units, so an emoji outside the Basic Multilingual Plane counts as two. The corresponding settings are maxDocuments, maxLines, maxCharacters and maxTotalCharacters under sysml.experimental.validateText. Oversized requests fail with InvalidParams before parsing or changing cached documents. Disabled requests fail with MethodNotFound.

Only requested documents are checked. Include an affected existing document with its current text to check it too. Results use the server's existing diagnostic checks; they do not certify complete SysML conformance. Input limits reduce work but do not guarantee a fixed response time.

Install from Marketplace

Install via the VS Code extension from the VS Code Marketplace.

Dev Container (recommended)

Open in GitHub Codespaces or VS Code Dev Containers — everything is pre-installed, including Python 3.13, Jupyter, and Node.js 22.

Manual Setup

npm install && npm run build && npm test

Development

npm run watch        # recompiles on file changes
# Then press F5 in VS Code to launch the extension + server

Use the "Client + Server" compound debug configuration to debug both sides simultaneously. The TypeScript project and build scripts use clients/vscode/ as the canonical extension source directory.

Release packaging downloads the pinned VS Code packaging CLI on demand, keeping its dependency tree out of normal development and CI installs:

npm run package

Client Examples

The LSP server is language-agnostic. Three client implementations are included to demonstrate different integration patterns:

VS Code Extension (clients/vscode/)

The primary client — a full VS Code extension using vscode-languageclient, communicating over IPC. Provides diagnostics, completions, hover, go-to-definition, semantic tokens, and all other LSP features directly in the editor.

Web Client (clients/web/)

A browser-based SysML explorer with a Node.js HTTP bridge to the LSP server. Features a live editor with auto-analyse, diagnostics panel, symbol outline, and Mermaid diagram generation with zoom/pan.

make web             # build + start on http://localhost:3000

Python Client (clients/python/)

A zero-dependency Python script and Jupyter notebook that drives the LSP over stdio — the same JSON-RPC protocol VS Code uses, with no framework overhead.

python3 clients/python/sysml_lsp_client.py                    # analyse all examples
python3 clients/python/sysml_lsp_client.py examples/bike.sysml # analyse a specific file

The Jupyter notebook (sysml_lsp_demo.ipynb) provides an interactive walkthrough of every LSP feature.

Architecture

                         ┌───────────────────────────┐
                         │    Language Server        │
                         │    (Node.js process)      │
                         ├───────────────────────────┤
                         │ • ANTLR4 parser           │
                         │ • Diagnostics             │
                         │ • Symbols / hover         │
                         │ • Completions / rename    │
                         │ • Semantic tokens         │
                         │ • Go-to-def / references  │
                         └────────┬──────────────────┘
                                  │  LSP (JSON-RPC)
              ┌───────────────────┼────────────────────┐
              │                   │                    │
     ┌────────┴───────┐  ┌────────┴───────┐  ┌─────────┴──────┐
     │  VS Code (IPC) │  │  Web (HTTP)    │  │  Python (stdio)│
     │  Extension     │  │  Browser SPA   │  │  Script/Jupyter│
     └────────────────┘  └────────────────┘  └────────────────┘

Project Structure

sysml-v2-lsp/
├── clients/
│   ├── vscode/             # VS Code extension (TypeScript)
│   ├── web/                # Browser SPA + Node.js HTTP bridge
│   └── python/             # Zero-dep Python client + Jupyter notebook
├── server/src/             # Language Server
│   ├── server.ts           # LSP connection, capability registration
│   ├── documentManager.ts  # Parse cache, document lifecycle
│   ├── parser/             # Parse pipeline
│   ├── symbols/            # Symbol table, scopes, element types
│   ├── providers/          # LSP feature implementations
│   ├── analysis/           # Complexity analyzer
│   └── mcp/                # Mermaid diagram generator
├── grammar/                # ANTLR4 grammar files (.g4)
├── sysml.library/          # SysML v2 standard library
├── benchmarks/             # Performance benchmark suite
│   ├── src/                # Runner, suites, reporters, utilities
│   ├── baselines/          # Saved baseline for regression detection
│   ├── results/            # JSON + Markdown output per run
│   └── fixtures/           # Synthetic .sysml files for benchmarking
├── examples/               # Example .sysml models
├── test/                   # Unit tests (vitest)
└── package.json            # Extension manifest + monorepo scripts

Available Commands

make help             # Show all targets
make install          # Install all dependencies
make build            # Generate parser + compile + bundle
make watch            # Watch mode
make test             # Run unit tests
make lint             # ESLint
make package          # Build .vsix
make package-server   # Build server tarball for npm
make web              # Launch web client (http://localhost:3000)
make update-grammar   # Pull latest grammar, rebuild parser + DFA snapshot
make update-library   # Pull latest SysML v2 standard library
make dfa              # Regenerate DFA snapshot (after any grammar change)
make ci               # Full CI pipeline (lint + build + test)
make bench            # Run all benchmark suites (SUITE="parse" to select)
make bench-baseline   # Save a baseline from the stable suites
make bench-compare    # Compare two runs (BASE=<file|dir> HEAD=<file|dir>)
make bench-history    # Stable historical benchmark trends

Benchmarks

A built-in benchmark suite measures parser, symbol table, LSP provider, memory, throughput, folder-load, and sysml/validateText performance. Results are written as both JSON and Markdown to benchmarks/results/.

Running Benchmarks

npm run bench                                        # run all suites
npm run bench -- --suite parse --suite symbolTable   # specific suites
npm run bench -- --runs 10 --warmup 3                # custom iterations
npm run bench -- --output ./my-results               # custom output directory
npm run bench:compare -- --base <a> --head <b>       # compare two runs (used by CI)
npm run bench:history                                # stable historical trends

Suites

Suite What it measures
parse Raw ANTLR parse time with syntax validation; warm runs include stale-snapshot recovery
symbolTable Document parse plus symbol build, and cached lookup latency
providers Batched provider latency over pre-parsed data with verified non-empty results
memory Forced-GC retained-heap estimates; use for coarse trends, not precise allocation counts
throughput Syntax-valid lexer/parser throughput, including document-level stale-snapshot recovery
folderLoad Workspace-style file discovery, parse, and symbol build
validateText Main-thread time of a sysml/validateText request by workspace, text and request size, and the rebuild it leaves for the next request

Regression Detection

Save a baseline, then compare future runs against it:

make bench-baseline                                            # save a baseline
npm run bench -- --suite symbolTable --suite folderLoad --compare   # compare, exit 1 on regression

Run the same suites for the baseline and comparison: suites share a process, so earlier suites slow later ones. The comparison uses the same stable metrics, verdicts, and thresholds as the pull request check: it warns above 15% and fails above 35%. Override the failure threshold with --threshold <n>. Baselines must come from the same Node version and platform.

Viewing Results

Each run produces a JSON file and a Markdown report in benchmarks/results/. To convert an existing JSON result to Markdown:

npx tsx benchmarks/src/reporters/markdownReporter.ts benchmarks/results/<file>.json

Generate a historical report from saved JSON results with:

npm run bench:history

The history report tracks the stable metrics used by the pull request check, combining runs of the same commit and environment. Prefer medians and repeated runs for trend decisions; with the default five measured runs, p95 is indicative rather than statistically robust.

Pull Request Performance Check

The CI performance job benchmarks the PR base and head on the same runner using the PR's benchmark harness, then compares the stable metrics:

npm run bench:compare -- --base <base.json|dir> --head <head.json|dir> --warn 15 --fail 35

Results appear in the job summary as a table, slowdowns above 15% raise warning annotations, regressions above 35% fail the job, and the raw JSON/Markdown reports are uploaded as the benchmark-reports artifact.

If the base cannot be benchmarked (for example, when a PR changes server APIs the harness calls), the comparison is skipped with a warning and the job passes; check the job summary before relying on a green result.

Grammar Updates

The grammar files in grammar/ are sourced from daltskin/sysml-v2-grammar. To pull the latest version, rebuild the parser, and regenerate the DFA snapshot:

make update-grammar

This fetches the .g4 files, runs npm run build, and regenerates the DFA snapshot that eliminates the ANTLR4 cold-start penalty. If you edit grammar files manually, run make dfa afterwards.

Technology Stack

Component Technology
Language TypeScript (strict mode)
Runtime Node.js ≥ 18
Parser antlr4ng
Generator antlr-ng
LSP vscode-languageserver
Bundler esbuild
Tests vitest

Related Projects

License

MIT