Skip to content

Extend LSP capabilities: 17 protocol features via TreeSitter adapter#387

Merged
lagergren merged 19 commits intomasterfrom
lagergren/lsp-extend3
Feb 11, 2026
Merged

Extend LSP capabilities: 17 protocol features via TreeSitter adapter#387
lagergren merged 19 commits intomasterfrom
lagergren/lsp-extend3

Conversation

@lagergren
Copy link
Contributor

@lagergren lagergren commented Feb 8, 2026

Summary

This PR extends the XTC language server with comprehensive LSP protocol support, backed by an incremental tree-sitter parser with full XTC grammar coverage.

Key achievements

  • 17 LSP capabilities implemented via the TreeSitter adapter: hover, completion, go-to-definition, find-references, document symbols, document highlight, selection range, folding range, rename, code actions, formatting, range formatting, inlay hints (stub), signature help, document links, diagnostics, and text document sync
  • 100% XTC grammar coverage — all 692 .x files from lib_* parse successfully with the tree-sitter grammar
  • Out-of-process LSP server with automatic JRE 25 provisioning via Foojay (IntelliJ runs on JBR 21, but jtreesitter requires Java 25+ for FFM API)
  • Cross-platform native tree-sitter libraries for 5 targets (darwin-arm64, darwin-x64, linux-x64, linux-arm64, windows-x64) built via Zig cross-compilation
  • Comprehensive test suite — 2,500+ lines covering all implemented features, edge cases, and integration tests
  • Version catalog cleanup — moved hardcoded JUnit 4 dependency to libs.versions.toml, grouped all IntelliJ-specific versions together

LSP feature matrix

Feature TreeSitter Mock Notes
Hover Yes Yes Type signatures + markdown docs
Completion Yes Yes Keywords, types, symbols, imports
Go-to-Definition Yes Yes Same-file only
Find References Yes Yes Same-file text matching
Document Symbols Yes Yes Hierarchical outline
Document Highlight Yes Yes Occurrence highlighting
Selection Range Yes Stub AST parent-chain walking
Folding Range Yes Yes Declarations, blocks, comments
Rename Yes Yes Same-file, AST-based
Code Actions Yes Yes Organize imports
Formatting Yes Yes Trailing whitespace + final newline
Range Formatting Yes Yes Within selection
Signature Help Yes No Active parameter tracking
Inlay Hints Stub Stub Requires type inference
Document Links Yes Yes Import path links
Diagnostics Yes Yes Syntax errors from parse tree
Text Document Sync Yes Yes Full document sync

What's not yet implemented (next steps)

  1. Semantic tokens — type-aware syntax highlighting (highest impact, achievable with tree-sitter alone)
  2. Cross-file navigation — go-to-definition and find-references across files (requires compiler integration)
  3. Context-aware completion — members after . and : (requires type inference)
  4. Workspace symbol search — find symbols across all open files
  5. Type/call hierarchy — super/subtypes and caller/callee trees
  6. Smart inlay hints — inferred types and parameter names

Build & infrastructure changes

  • Tail LSP server logs to Gradle console during runIde
  • JRE resolution logging and sandbox INFO-level log config
  • Fixed LSP server notification spam
  • Removed hardcoded IDE paths in favor of proper Gradle/IntelliJ APIs
  • ConcurrentHashMap usage documented with threading-model comments
  • All IntelliJ dependency versions consolidated in version catalog

Test plan

  • lsp-server:test — all TreeSitterAdapter, MockAdapter, and integration tests pass
  • lsp-server:ktlintCheck — no style violations
  • intellij-plugin:compileKotlin — plugin builds cleanly with version catalog references
  • javatools:test — existing tests unaffected
  • Manual: runIde launches IntelliJ with working LSP features (hover, completion, go-to-definition, etc.)

Add 22 new tests (96 → 118 total) covering gaps in mock adapter unit
tests (findReferences, formatRange), server-layer LSP4J wiring for all
14 capabilities, and integration tests for signatureHelp, rangeFormatting,
and inlayHint.

Update KDoc across XtcCompilerAdapter, TreeSitterAdapter, and
MockXtcCompilerAdapter with per-method documentation explaining LSP
capability, adapter implementations, and compiler upgrade path.

Update MANUAL_TEST_PLAN.md feature matrix to reflect newly implemented
features (rename, codeAction, formatting, foldingRange, documentHighlight,
documentLink, signatureHelp, selectionRange) and add headless Neovim test
commands to EDITOR_SETUP.md.
Feature matrices in 5 documentation files were outdated, showing many
LSP capabilities as stubs/future that are now fully implemented in both
the Mock and TreeSitter adapters (rename, code actions, formatting,
folding ranges, document highlights, document links, signature help,
selection ranges).
@lagergren lagergren self-assigned this Feb 8, 2026
@lagergren lagergren marked this pull request as draft February 8, 2026 14:32
@lagergren
Copy link
Contributor Author

This is put up here as a browsable preview for interested bleeding edge testers, but it is not ready for review so please don't waste time on this until it is out of DRAFT mode.

…the kdocs in the language server common api implemantation code.
- Fix findServerJar() to use PluginManagerCore instead of hardcoded
  IntelliJIdea2025.1 paths that broke on other IDE versions
- Replace hardcoded ~/.gradle paths with gradle.gradleUserHomeDir
- Fix incorrect IDE cache path (was com.jetbrains.intellij.idea, actually idea/ideaIC)
- Use providers.systemProperty() for maven local repo (config cache safe)
- Add warnings when using local IDE mode (brittle version mismatches)
- Add cache purge instructions in build script comments
- Fix ktlint violations in build.gradle.kts
- Show "Server Started" notification only once per IDE session using
  AtomicBoolean guard (LSP4IJ may spawn multiple concurrent instances)
- Remove --enable-native-access flag (FFM API finalized in Java 22,
  unnecessary on our target Java 25, may trigger experimental alerts)
- Document LSP4IJ multi-spawn race condition with issue references:
  lsp4e#512 (same bug, fixed in PR #520), lsp4ij#888 (related)
- JreProvisioner now logs the full resolution chain: all registered
  JDKs with versions, which are suitable, and what was selected
- New configureSandboxLogging task pre-seeds log-categories.xml to
  enable INFO-level logging for org.xtclang in the sandbox IDE
FFM API is finalized since Java 22. Since the project targets Java 25,
this flag is no longer needed anywhere. Removed from editor setup docs
and Gradle JVM args.
The LSP server runs out-of-process and its logs were only visible in
IntelliJ's LSP4IJ panel. Now the runIde task starts a daemon thread
that tails ~/.xtc/logs/lsp-server.log and streams lines to the Gradle
console with a [lsp-server] prefix. The thread is interrupted in
doLast to prevent it lingering in the Gradle daemon.

Also enhances runIde startup logging with version matrix, IDE cache
layer details, sandbox status, and reset commands. Updates the README
with sandbox architecture documentation and corrects the outdated
LSP architecture diagram.
Enable the test task for the IntelliJ plugin module with JUnit Jupiter
and AssertJ. Extract JAR resolution into a testable companion function
and widen JreProvisioner filesystem methods to internal for testing.

LspServerJarResolutionTest verifies bin/xtc-lsp-server.jar lookup
across correct and incorrect plugin directory layouts (5 tests).
JreProvisionerTest covers findCachedJava() layouts, directory
flattening, and failure marker lifecycle (11 tests).
- Fix getSignatureHelp returning null: the grammar parses `name(args)`
  as generic_type (not call_expression) since it can't distinguish calls
  from type expressions without semantic analysis. Handle both node types.
- Fix argument node lookup: use correct grammar name "arguments" instead
  of "argument_list".
- Strengthen signature help tests to assert non-null results with exact
  label/parameter checks instead of silently passing on null.
- Fix British English spellings: linearise->linearize, recognises->recognizes.
- Fix unpaired symbol warnings: wrap `$"` and `$|` in backticks in KDoc.
- Fix pre-existing ktlint indentation issues.
Expand test coverage from 42 to 68 active tests across all LSP features:

- SignatureHelp: +11 tests (no-arg, 3-arg active param tracking, overloads,
  nested inner/outer calls, cross-method, 5-param, open-paren, unknown method)
- CallPatternParsing: +3 tests (new expression, declaration site, bare ref)
- CompletionsAtCallSite: +2 tests (sibling methods, multi-class symbols)
- SelectionRangesAtCallSite: +3 tests (call arg, nested arg, multi-position)
- Completions: +1 test (method names from compiled source)
- Definition: +2 tests (method from call site, class from type usage)
- DocumentHighlights: +1 test (method across declaration + calls)
- FoldingRanges: +1 test (deeply nested declarations)
- FindReferences: +1 test (method refs across declaration + calls)

Add SLF4J logger with logged() helper for verbose test output showing
full adapter return values (signatures, locations, highlights, ranges).
@lagergren lagergren changed the title [WIP / STILL DRAFT] Continue implementing the LSP capabilities and restructure documentation to be accurate and up to date. Continue implementing the LSP capabilities and restructure documentation to be accurate and up to date. Feb 10, 2026
@lagergren lagergren marked this pull request as ready for review February 10, 2026 15:07
@lagergren lagergren requested a review from ggleyzer February 10, 2026 15:07
@lagergren lagergren changed the title Continue implementing the LSP capabilities and restructure documentation to be accurate and up to date. Extend LSP capabilities: 17 protocol features via TreeSitter adapter Feb 10, 2026
The lang build (LSP server, IntelliJ plugin, tree-sitter) works but
is not yet ready to be enabled by default on this branch.
Deferring the @NotNull and import changes to the next iteration.
@lagergren
Copy link
Contributor Author

This is put up here as a browsable preview for interested bleeding edge testers, but it is not ready for review so please don't waste time on this until it is out of DRAFT mode.

This is now complete and no longer draft. I will merge after a final round of sanity checking.

…on catalog

- Add centralized ktlint configuration in lang root build: pin engine version
  from version catalog, auto-format before check so developers never see
  formatting-only failures
- Add lang- prefix to all lang-only version catalog entries for clear scoping
  (lang-kotlin, lang-ktlint, lang-lsp4j, lang-intellij-*, lang-zig, etc.)
- Restructure libs.versions.toml: alphabetical sorting within sections,
  clear section headers, tree-sitter deps in own section
- Add debug-adapter subproject with DAP server scaffold (XtcDebugServer,
  XtcDebugServerLauncher, logback config)
- Fix redundant libs.versions.lang.zig.get() call in tree-sitter build
@lagergren lagergren force-pushed the lagergren/lsp-extend3 branch from 07d5038 to 1b8e040 Compare February 11, 2026 11:12
@lagergren lagergren merged commit 040fd44 into master Feb 11, 2026
4 checks passed
@lagergren lagergren deleted the lagergren/lsp-extend3 branch February 11, 2026 12:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants