Skip to content

fix: dynamically register jdtls capabilities to avoid blocking diagnostics#44

Merged
aviadshiber merged 2 commits intomainfrom
fix/dynamic-jdtls-capabilities
Apr 10, 2026
Merged

fix: dynamically register jdtls capabilities to avoid blocking diagnostics#44
aviadshiber merged 2 commits intomainfrom
fix/dynamic-jdtls-capabilities

Conversation

@aviadshiber
Copy link
Copy Markdown
Owner

Summary

Fixes diagnostic tooltips being suppressed when jdtls isn't ready yet.

The Problem

The server statically advertised hoverProvider: true, definitionProvider: true, etc in the InitializeResult — even before jdtls started. When IntelliJ sends a hover request and we return null (jdtls not ready), IntelliJ suppresses its built-in diagnostic tooltip entirely. Users saw no hint/warning messages on hover.

The Fix

  • Removed hover, definition, references, completion, and documentSymbol from static InitializeResult capabilities
  • Added dynamic capability registration via client/registerCapability — these are registered only AFTER jdtls initializes successfully
  • Moved handler registration from module-level @server.feature decorators to runtime server.feature() calls inside _register_jdtls_capabilities(), because pygls auto-advertises capabilities for decorated handlers

Result

  • Diagnostic tooltips (from our custom tree-sitter rules) show immediately on hover — no interference from jdtls
  • jdtls features (hover, go-to-def, references, completion, documentSymbol) activate only when jdtls is ready
  • No more request cancellation storms during jdtls startup

Code Changes

  • Extracted _JDTLS_CAPABILITIES table + _build_jdtls_registrations() helper to eliminate duplicate registration boilerplate
  • 334 tests, 83% coverage

🤖 Generated with Claude Code

aviadsTaboola and others added 2 commits April 10, 2026 09:22
…stics

Previously, hover/definition/references/completion/documentSymbol were
advertised in the static InitializeResult even before jdtls started.
This caused the IDE to defer hover to us, and when jdtls wasn't ready
(or returned null), diagnostic tooltips were suppressed.

Now these capabilities are only registered via client/registerCapability
AFTER jdtls initializes successfully. The handlers are also registered
at that point via server.feature() instead of module-level decorators,
since pygls auto-advertises capabilities for decorated handlers.

Result: diagnostic tooltips show immediately (our custom rules), and
jdtls features activate only when jdtls is actually ready.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ertions

- Add _jdtls_capabilities_registered flag to prevent FeatureAlreadyRegisteredError
  on double invocation (critical finding)
- Move server.feature() calls inside try/except to prevent capability mismatch
  when client_register_capability_async fails (high finding)
- Use _JDTLS_HANDLERS dict to collect handlers, iterated during registration
- Extract _JDTLS_REG_PREFIX constant for registration IDs
- Fix test_register_jdtls_capabilities_logs_on_failure: patch server.feature
  and reset _jdtls_capabilities_registered to avoid singleton mutation
- Add test_register_jdtls_capabilities_happy_path: verifies handlers are
  registered and success log is emitted
- Add test_register_jdtls_capabilities_idempotent: verifies second call is no-op
- Strengthen test_build_jdtls_registrations: assert java language value,
  triggerCharacters for completion, id uniqueness and prefix
- Add completion_provider/document_symbol_provider None assertions to
  integration test

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@aviadshiber aviadshiber merged commit a88a9f1 into main Apr 10, 2026
14 checks passed
@aviadshiber aviadshiber deleted the fix/dynamic-jdtls-capabilities branch April 10, 2026 07:13
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