java-functional-lsp 0.9.4__tar.gz → 0.9.7__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/PKG-INFO +1 -1
  2. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/pyproject.toml +1 -1
  3. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/src/java_functional_lsp/__init__.py +1 -1
  4. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/src/java_functional_lsp/server.py +265 -14
  5. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/tests/test_server.py +604 -10
  6. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/uv.lock +1 -1
  7. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/.claude-plugin/plugin.json +0 -0
  8. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/.githooks/pre-commit +0 -0
  9. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/.githooks/pre-push +0 -0
  10. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/.github/CODEOWNERS +0 -0
  11. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/.github/ISSUE_TEMPLATE/bug-report.md +0 -0
  12. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/.github/ISSUE_TEMPLATE/feature-request.md +0 -0
  13. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  14. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/.github/SECURITY.md +0 -0
  15. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/.github/dependabot.yml +0 -0
  16. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/.github/release-drafter.yml +0 -0
  17. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/.github/workflows/publish.yml +0 -0
  18. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/.github/workflows/release-drafter.yml +0 -0
  19. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/.github/workflows/stale.yml +0 -0
  20. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/.github/workflows/test.yml +0 -0
  21. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/.github/workflows/update-homebrew.yml +0 -0
  22. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/.github/workflows/vscode-ext.yml +0 -0
  23. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/.gitignore +0 -0
  24. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/CONTRIBUTING.md +0 -0
  25. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/LICENSE +0 -0
  26. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/README.md +0 -0
  27. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/SKILL.md +0 -0
  28. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/commands/lint-java.md +0 -0
  29. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/editors/intellij/README.md +0 -0
  30. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/editors/intellij/lsp4ij-template.json +0 -0
  31. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/editors/vscode/.vscodeignore +0 -0
  32. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/editors/vscode/README.md +0 -0
  33. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/editors/vscode/package-lock.json +0 -0
  34. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/editors/vscode/package.json +0 -0
  35. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/editors/vscode/src/extension.ts +0 -0
  36. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/editors/vscode/tsconfig.json +0 -0
  37. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/hooks/hooks.json +0 -0
  38. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/hooks/java_linter_reminder.py +0 -0
  39. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/scripts/ensure-lsp.sh +0 -0
  40. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/scripts/generate-formula.py +0 -0
  41. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/src/java_functional_lsp/__main__.py +0 -0
  42. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/src/java_functional_lsp/analyzers/__init__.py +0 -0
  43. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/src/java_functional_lsp/analyzers/base.py +0 -0
  44. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/src/java_functional_lsp/analyzers/exception_checker.py +0 -0
  45. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/src/java_functional_lsp/analyzers/functional_checker.py +0 -0
  46. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/src/java_functional_lsp/analyzers/mutation_checker.py +0 -0
  47. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/src/java_functional_lsp/analyzers/null_checker.py +0 -0
  48. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/src/java_functional_lsp/analyzers/spring_checker.py +0 -0
  49. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/src/java_functional_lsp/cli.py +0 -0
  50. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/src/java_functional_lsp/fixes.py +0 -0
  51. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/src/java_functional_lsp/merkle.py +0 -0
  52. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/src/java_functional_lsp/proxy.py +0 -0
  53. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/tests/__init__.py +0 -0
  54. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/tests/conftest.py +0 -0
  55. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/tests/test_base.py +0 -0
  56. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/tests/test_cli.py +0 -0
  57. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/tests/test_config.py +0 -0
  58. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/tests/test_e2e.py +0 -0
  59. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/tests/test_e2e_jdtls.py +0 -0
  60. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/tests/test_exception_checker.py +0 -0
  61. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/tests/test_fixes.py +0 -0
  62. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/tests/test_functional_checker.py +0 -0
  63. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/tests/test_merkle.py +0 -0
  64. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/tests/test_merkle_proxy.py +0 -0
  65. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/tests/test_mutation_checker.py +0 -0
  66. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/tests/test_null_checker.py +0 -0
  67. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/tests/test_proxy.py +0 -0
  68. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/tests/test_spring_checker.py +0 -0
  69. {java_functional_lsp-0.9.4 → java_functional_lsp-0.9.7}/tests/test_suppress.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: java-functional-lsp
3
- Version: 0.9.4
3
+ Version: 0.9.7
4
4
  Summary: Java LSP server enforcing functional programming best practices — null safety, immutability, no exceptions
5
5
  Project-URL: Homepage, https://github.com/aviadshiber/java-functional-lsp
6
6
  Project-URL: Repository, https://github.com/aviadshiber/java-functional-lsp
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "java-functional-lsp"
7
- version = "0.9.4"
7
+ version = "0.9.7"
8
8
  description = "Java LSP server enforcing functional programming best practices — null safety, immutability, no exceptions"
9
9
  readme = "README.md"
10
10
  license = { text = "MIT" }
@@ -1,3 +1,3 @@
1
1
  """java-functional-lsp: A Java LSP server enforcing functional programming best practices."""
2
2
 
3
- __version__ = "0.9.4"
3
+ __version__ = "0.9.7"
@@ -446,6 +446,20 @@ _JDTLS_CAPABILITIES: list[tuple[str, str, type[Any], dict[str, Any]]] = [
446
446
  ("definition", lsp.TEXT_DOCUMENT_DEFINITION, lsp.DefinitionRegistrationOptions, {}),
447
447
  ("references", lsp.TEXT_DOCUMENT_REFERENCES, lsp.ReferenceRegistrationOptions, {}),
448
448
  ("document-symbol", lsp.TEXT_DOCUMENT_DOCUMENT_SYMBOL, lsp.DocumentSymbolRegistrationOptions, {}),
449
+ ("call-hierarchy", lsp.TEXT_DOCUMENT_PREPARE_CALL_HIERARCHY, lsp.CallHierarchyRegistrationOptions, {}),
450
+ (
451
+ "signature-help",
452
+ lsp.TEXT_DOCUMENT_SIGNATURE_HELP,
453
+ lsp.SignatureHelpRegistrationOptions,
454
+ {"trigger_characters": ["(", ","], "retrigger_characters": [")"]},
455
+ ),
456
+ ("implementation", lsp.TEXT_DOCUMENT_IMPLEMENTATION, lsp.ImplementationRegistrationOptions, {}),
457
+ ("type-definition", lsp.TEXT_DOCUMENT_TYPE_DEFINITION, lsp.TypeDefinitionRegistrationOptions, {}),
458
+ ("declaration", lsp.TEXT_DOCUMENT_DECLARATION, lsp.DeclarationRegistrationOptions, {}),
459
+ ("document-highlight", lsp.TEXT_DOCUMENT_DOCUMENT_HIGHLIGHT, lsp.DocumentHighlightRegistrationOptions, {}),
460
+ ("rename", lsp.TEXT_DOCUMENT_RENAME, lsp.RenameRegistrationOptions, {"prepare_provider": True}),
461
+ ("type-hierarchy", lsp.TEXT_DOCUMENT_PREPARE_TYPE_HIERARCHY, lsp.TypeHierarchyRegistrationOptions, {}),
462
+ ("workspace-symbol", lsp.WORKSPACE_SYMBOL, lsp.WorkspaceSymbolRegistrationOptions, {}),
449
463
  ]
450
464
 
451
465
  # Maps LSP method → handler function for dynamic registration.
@@ -457,14 +471,20 @@ _jdtls_capabilities_registered = False
457
471
 
458
472
  def _build_jdtls_registrations() -> list[lsp.Registration]:
459
473
  """Build LSP Registration objects for jdtls-dependent capabilities."""
460
- return [
461
- lsp.Registration(
462
- id=f"{_JDTLS_REG_PREFIX}{suffix}",
463
- method=method,
464
- register_options=_converter.unstructure(opts_cls(document_selector=_JAVA_SELECTOR, **extra)),
474
+ result = []
475
+ for suffix, method, opts_cls, extra in _JDTLS_CAPABILITIES:
476
+ field_names = {f.name for f in getattr(opts_cls, "__attrs_attrs__", [])}
477
+ kwargs: dict[str, Any] = {**extra}
478
+ if "document_selector" in field_names:
479
+ kwargs["document_selector"] = _JAVA_SELECTOR
480
+ result.append(
481
+ lsp.Registration(
482
+ id=f"{_JDTLS_REG_PREFIX}{suffix}",
483
+ method=method,
484
+ register_options=_converter.unstructure(opts_cls(**kwargs)),
485
+ )
465
486
  )
466
- for suffix, method, opts_cls, extra in _JDTLS_CAPABILITIES
467
- ]
487
+ return result
468
488
 
469
489
 
470
490
  async def _register_jdtls_capabilities() -> None:
@@ -499,7 +519,11 @@ async def _register_jdtls_capabilities() -> None:
499
519
  return
500
520
 
501
521
  _jdtls_capabilities_registered = True
502
- logger.info("Dynamically registered jdtls capabilities (hover, definition, references, completion, symbol)")
522
+ logger.info(
523
+ "jdtls capabilities registered: completion, hover, definition, references, symbol, "
524
+ "call-hierarchy, signature-help, implementation, type-definition, declaration, "
525
+ "document-highlight, rename, type-hierarchy, workspace-symbol"
526
+ )
503
527
  except Exception:
504
528
  logger.warning("Failed to dynamically register jdtls capabilities", exc_info=True)
505
529
 
@@ -636,7 +660,24 @@ async def _lazy_start_jdtls(file_uri: str) -> None:
636
660
  # they only activate after jdtls starts.
637
661
 
638
662
 
639
- async def _ensure_module_and_forward(method: str, params: Any, file_uri: str) -> Any | None:
663
+ # Methods that operate on a single file and succeed before cross-file indexing
664
+ # is complete. A successful response from these does NOT mean the module is fully
665
+ # indexed, so we must NOT use them to transition the module to READY — doing so
666
+ # would cause cross-file requests (references, callHierarchy) to skip the wait
667
+ # and return empty results from an under-indexed jdtls instance.
668
+ _LIGHTWEIGHT_METHODS: frozenset[str] = frozenset(
669
+ {
670
+ "textDocument/documentHighlight",
671
+ "textDocument/documentSymbol",
672
+ }
673
+ )
674
+
675
+
676
+ async def _ensure_module_and_forward(
677
+ method: str,
678
+ params: Any,
679
+ file_uri: str,
680
+ ) -> Any | None:
640
681
  """Forward a request to jdtls, ensuring the file's module is loaded.
641
682
 
642
683
  Uses ``ModuleRegistry`` for adaptive waiting:
@@ -644,8 +685,11 @@ async def _ensure_module_and_forward(method: str, params: Any, file_uri: str) ->
644
685
  - **UNKNOWN**: add module, wait until ready (adaptive, not fixed sleep)
645
686
  - **ADDED**: module sent but not confirmed — wait until ready
646
687
 
647
- When a request succeeds, marks the module as READY so subsequent
648
- requests skip the wait entirely.
688
+ When a request that requires full project indexing succeeds, marks the
689
+ module as READY so subsequent requests skip the wait entirely.
690
+ Methods in ``_LIGHTWEIGHT_METHODS`` operate on a single file and succeed
691
+ before cross-file indexing completes — their success is never used to
692
+ signal readiness.
649
693
  """
650
694
  proxy = server._proxy
651
695
  if not proxy.is_available:
@@ -663,9 +707,10 @@ async def _ensure_module_and_forward(method: str, params: Any, file_uri: str) ->
663
707
  serialized = _serialize_params(params)
664
708
  result = await proxy.send_request(method, serialized)
665
709
 
710
+ can_mark_ready = method not in _LIGHTWEIGHT_METHODS
666
711
  if result is not None:
667
- # Success — mark module as ready so future requests are instant.
668
- if module_uri:
712
+ # Success — mark module as ready so future cross-file requests are instant.
713
+ if can_mark_ready and module_uri:
669
714
  proxy.modules.mark_ready(module_uri)
670
715
  return result
671
716
 
@@ -677,7 +722,7 @@ async def _ensure_module_and_forward(method: str, params: Any, file_uri: str) ->
677
722
  await proxy.modules.wait_until_ready(wait_uri, timeout=5.0)
678
723
  # Always retry once after waiting — even on timeout the module may be ready.
679
724
  result = await proxy.send_request(method, serialized)
680
- if result is not None and module_uri:
725
+ if result is not None and can_mark_ready and module_uri:
681
726
  proxy.modules.mark_ready(module_uri)
682
727
  return result
683
728
 
@@ -739,6 +784,198 @@ async def _on_document_symbol(params: lsp.DocumentSymbolParams) -> list[lsp.Docu
739
784
  return None
740
785
 
741
786
 
787
+ async def _on_prepare_call_hierarchy(params: lsp.CallHierarchyPrepareParams) -> list[lsp.CallHierarchyItem] | None:
788
+ """Forward prepareCallHierarchy request to jdtls."""
789
+ result = await _ensure_module_and_forward("textDocument/prepareCallHierarchy", params, params.text_document.uri)
790
+ if result is None:
791
+ return None
792
+ try:
793
+ return [_converter.structure(item, lsp.CallHierarchyItem) for item in result]
794
+ except Exception:
795
+ return None
796
+
797
+
798
+ async def _on_incoming_calls(
799
+ params: lsp.CallHierarchyIncomingCallsParams,
800
+ ) -> list[lsp.CallHierarchyIncomingCall] | None:
801
+ """Forward callHierarchy/incomingCalls request to jdtls."""
802
+ result = await _ensure_module_and_forward("callHierarchy/incomingCalls", params, params.item.uri)
803
+ if result is None:
804
+ return None
805
+ try:
806
+ return [_converter.structure(c, lsp.CallHierarchyIncomingCall) for c in result]
807
+ except Exception:
808
+ return None
809
+
810
+
811
+ async def _on_outgoing_calls(
812
+ params: lsp.CallHierarchyOutgoingCallsParams,
813
+ ) -> list[lsp.CallHierarchyOutgoingCall] | None:
814
+ """Forward callHierarchy/outgoingCalls request to jdtls."""
815
+ result = await _ensure_module_and_forward("callHierarchy/outgoingCalls", params, params.item.uri)
816
+ if result is None:
817
+ return None
818
+ try:
819
+ return [_converter.structure(c, lsp.CallHierarchyOutgoingCall) for c in result]
820
+ except Exception:
821
+ return None
822
+
823
+
824
+ async def _on_signature_help(params: lsp.SignatureHelpParams) -> lsp.SignatureHelp | None:
825
+ """Forward signatureHelp request to jdtls."""
826
+ result = await _ensure_module_and_forward("textDocument/signatureHelp", params, params.text_document.uri)
827
+ if result is None:
828
+ return None
829
+ try:
830
+ return _converter.structure(result, lsp.SignatureHelp)
831
+ except Exception:
832
+ logger.debug("Failed to structure signatureHelp result", exc_info=True)
833
+ return None
834
+
835
+
836
+ async def _on_implementation(params: lsp.ImplementationParams) -> list[lsp.Location] | None:
837
+ """Forward go-to-implementation request to jdtls."""
838
+ result = await _ensure_module_and_forward("textDocument/implementation", params, params.text_document.uri)
839
+ if result is None:
840
+ return None
841
+ try:
842
+ if isinstance(result, list):
843
+ return [_converter.structure(loc, lsp.Location) for loc in result]
844
+ return [_converter.structure(result, lsp.Location)]
845
+ except Exception:
846
+ logger.debug("Failed to structure implementation result", exc_info=True)
847
+ return None
848
+
849
+
850
+ async def _on_type_definition(params: lsp.TypeDefinitionParams) -> list[lsp.Location] | None:
851
+ """Forward go-to-type-definition request to jdtls."""
852
+ result = await _ensure_module_and_forward("textDocument/typeDefinition", params, params.text_document.uri)
853
+ if result is None:
854
+ return None
855
+ try:
856
+ if isinstance(result, list):
857
+ return [_converter.structure(loc, lsp.Location) for loc in result]
858
+ return [_converter.structure(result, lsp.Location)]
859
+ except Exception:
860
+ logger.debug("Failed to structure typeDefinition result", exc_info=True)
861
+ return None
862
+
863
+
864
+ async def _on_declaration(params: lsp.DeclarationParams) -> list[lsp.Location] | None:
865
+ """Forward go-to-declaration request to jdtls."""
866
+ result = await _ensure_module_and_forward("textDocument/declaration", params, params.text_document.uri)
867
+ if result is None:
868
+ return None
869
+ try:
870
+ if isinstance(result, list):
871
+ return [_converter.structure(loc, lsp.Location) for loc in result]
872
+ return [_converter.structure(result, lsp.Location)]
873
+ except Exception:
874
+ logger.debug("Failed to structure declaration result", exc_info=True)
875
+ return None
876
+
877
+
878
+ async def _on_document_highlight(params: lsp.DocumentHighlightParams) -> list[lsp.DocumentHighlight] | None:
879
+ """Forward documentHighlight request to jdtls."""
880
+ result = await _ensure_module_and_forward("textDocument/documentHighlight", params, params.text_document.uri)
881
+ if result is None:
882
+ return None
883
+ try:
884
+ return [_converter.structure(h, lsp.DocumentHighlight) for h in result]
885
+ except Exception:
886
+ logger.debug("Failed to structure documentHighlight result", exc_info=True)
887
+ return None
888
+
889
+
890
+ async def _on_rename(params: lsp.RenameParams) -> lsp.WorkspaceEdit | None:
891
+ """Forward rename request to jdtls."""
892
+ result = await _ensure_module_and_forward("textDocument/rename", params, params.text_document.uri)
893
+ if result is None:
894
+ return None
895
+ try:
896
+ return _converter.structure(result, lsp.WorkspaceEdit)
897
+ except Exception:
898
+ logger.debug("Failed to structure rename result", exc_info=True)
899
+ return None
900
+
901
+
902
+ async def _on_prepare_rename(
903
+ params: lsp.PrepareRenameParams,
904
+ ) -> lsp.Range | lsp.PrepareRenamePlaceholder | lsp.PrepareRenameDefaultBehavior | None:
905
+ """Forward prepareRename request to jdtls.
906
+
907
+ jdtls may return Range, PrepareRenamePlaceholder ({range, placeholder}),
908
+ or PrepareRenameDefaultBehavior ({defaultBehavior}) — try each in order.
909
+ """
910
+ result = await _ensure_module_and_forward("textDocument/prepareRename", params, params.text_document.uri)
911
+ if result is None:
912
+ return None
913
+ for target_type in (lsp.PrepareRenamePlaceholder, lsp.PrepareRenameDefaultBehavior, lsp.Range):
914
+ try:
915
+ return _converter.structure(result, target_type) # type: ignore[return-value]
916
+ except Exception:
917
+ pass
918
+ logger.debug("Failed to structure prepareRename result as any known type", exc_info=False)
919
+ return None
920
+
921
+
922
+ async def _on_prepare_type_hierarchy(
923
+ params: lsp.TypeHierarchyPrepareParams,
924
+ ) -> list[lsp.TypeHierarchyItem] | None:
925
+ """Forward prepareTypeHierarchy request to jdtls."""
926
+ result = await _ensure_module_and_forward("textDocument/prepareTypeHierarchy", params, params.text_document.uri)
927
+ if result is None:
928
+ return None
929
+ try:
930
+ return [_converter.structure(item, lsp.TypeHierarchyItem) for item in result]
931
+ except Exception:
932
+ logger.debug("Failed to structure prepareTypeHierarchy result", exc_info=True)
933
+ return None
934
+
935
+
936
+ async def _on_type_hierarchy_supertypes(
937
+ params: lsp.TypeHierarchySupertypesParams,
938
+ ) -> list[lsp.TypeHierarchyItem] | None:
939
+ """Forward typeHierarchy/supertypes request to jdtls."""
940
+ result = await _ensure_module_and_forward("typeHierarchy/supertypes", params, params.item.uri)
941
+ if result is None:
942
+ return None
943
+ try:
944
+ return [_converter.structure(item, lsp.TypeHierarchyItem) for item in result]
945
+ except Exception:
946
+ logger.debug("Failed to structure typeHierarchy/supertypes result", exc_info=True)
947
+ return None
948
+
949
+
950
+ async def _on_type_hierarchy_subtypes(
951
+ params: lsp.TypeHierarchySubtypesParams,
952
+ ) -> list[lsp.TypeHierarchyItem] | None:
953
+ """Forward typeHierarchy/subtypes request to jdtls."""
954
+ result = await _ensure_module_and_forward("typeHierarchy/subtypes", params, params.item.uri)
955
+ if result is None:
956
+ return None
957
+ try:
958
+ return [_converter.structure(item, lsp.TypeHierarchyItem) for item in result]
959
+ except Exception:
960
+ logger.debug("Failed to structure typeHierarchy/subtypes result", exc_info=True)
961
+ return None
962
+
963
+
964
+ async def _on_workspace_symbol(params: lsp.WorkspaceSymbolParams) -> list[lsp.WorkspaceSymbol] | None:
965
+ """Forward workspace/symbol request to jdtls (no text_document — use proxy directly)."""
966
+ proxy = server._proxy
967
+ if not proxy.is_available:
968
+ return None
969
+ result = await proxy.send_request("workspace/symbol", _serialize_params(params))
970
+ if result is None:
971
+ return None
972
+ try:
973
+ return [_converter.structure(s, lsp.WorkspaceSymbol) for s in result]
974
+ except Exception:
975
+ logger.debug("Failed to structure workspace/symbol result", exc_info=True)
976
+ return None
977
+
978
+
742
979
  # Populate handler map for dynamic registration.
743
980
  _JDTLS_HANDLERS.update(
744
981
  {
@@ -747,6 +984,20 @@ _JDTLS_HANDLERS.update(
747
984
  lsp.TEXT_DOCUMENT_DEFINITION: _on_definition,
748
985
  lsp.TEXT_DOCUMENT_REFERENCES: _on_references,
749
986
  lsp.TEXT_DOCUMENT_DOCUMENT_SYMBOL: _on_document_symbol,
987
+ lsp.TEXT_DOCUMENT_PREPARE_CALL_HIERARCHY: _on_prepare_call_hierarchy,
988
+ lsp.CALL_HIERARCHY_INCOMING_CALLS: _on_incoming_calls,
989
+ lsp.CALL_HIERARCHY_OUTGOING_CALLS: _on_outgoing_calls,
990
+ lsp.TEXT_DOCUMENT_SIGNATURE_HELP: _on_signature_help,
991
+ lsp.TEXT_DOCUMENT_IMPLEMENTATION: _on_implementation,
992
+ lsp.TEXT_DOCUMENT_TYPE_DEFINITION: _on_type_definition,
993
+ lsp.TEXT_DOCUMENT_DECLARATION: _on_declaration,
994
+ lsp.TEXT_DOCUMENT_DOCUMENT_HIGHLIGHT: _on_document_highlight,
995
+ lsp.TEXT_DOCUMENT_RENAME: _on_rename,
996
+ lsp.TEXT_DOCUMENT_PREPARE_RENAME: _on_prepare_rename,
997
+ lsp.TEXT_DOCUMENT_PREPARE_TYPE_HIERARCHY: _on_prepare_type_hierarchy,
998
+ lsp.TYPE_HIERARCHY_SUPERTYPES: _on_type_hierarchy_supertypes,
999
+ lsp.TYPE_HIERARCHY_SUBTYPES: _on_type_hierarchy_subtypes,
1000
+ lsp.WORKSPACE_SYMBOL: _on_workspace_symbol,
750
1001
  }
751
1002
  )
752
1003