java-functional-lsp 0.9.6__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.6 → java_functional_lsp-0.9.7}/PKG-INFO +1 -1
  2. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/pyproject.toml +1 -1
  3. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/src/java_functional_lsp/__init__.py +1 -1
  4. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/src/java_functional_lsp/server.py +27 -6
  5. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/tests/test_server.py +28 -0
  6. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/.claude-plugin/plugin.json +0 -0
  7. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/.githooks/pre-commit +0 -0
  8. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/.githooks/pre-push +0 -0
  9. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/.github/CODEOWNERS +0 -0
  10. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/.github/ISSUE_TEMPLATE/bug-report.md +0 -0
  11. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/.github/ISSUE_TEMPLATE/feature-request.md +0 -0
  12. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  13. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/.github/SECURITY.md +0 -0
  14. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/.github/dependabot.yml +0 -0
  15. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/.github/release-drafter.yml +0 -0
  16. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/.github/workflows/publish.yml +0 -0
  17. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/.github/workflows/release-drafter.yml +0 -0
  18. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/.github/workflows/stale.yml +0 -0
  19. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/.github/workflows/test.yml +0 -0
  20. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/.github/workflows/update-homebrew.yml +0 -0
  21. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/.github/workflows/vscode-ext.yml +0 -0
  22. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/.gitignore +0 -0
  23. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/CONTRIBUTING.md +0 -0
  24. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/LICENSE +0 -0
  25. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/README.md +0 -0
  26. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/SKILL.md +0 -0
  27. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/commands/lint-java.md +0 -0
  28. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/editors/intellij/README.md +0 -0
  29. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/editors/intellij/lsp4ij-template.json +0 -0
  30. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/editors/vscode/.vscodeignore +0 -0
  31. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/editors/vscode/README.md +0 -0
  32. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/editors/vscode/package-lock.json +0 -0
  33. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/editors/vscode/package.json +0 -0
  34. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/editors/vscode/src/extension.ts +0 -0
  35. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/editors/vscode/tsconfig.json +0 -0
  36. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/hooks/hooks.json +0 -0
  37. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/hooks/java_linter_reminder.py +0 -0
  38. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/scripts/ensure-lsp.sh +0 -0
  39. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/scripts/generate-formula.py +0 -0
  40. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/src/java_functional_lsp/__main__.py +0 -0
  41. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/src/java_functional_lsp/analyzers/__init__.py +0 -0
  42. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/src/java_functional_lsp/analyzers/base.py +0 -0
  43. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/src/java_functional_lsp/analyzers/exception_checker.py +0 -0
  44. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/src/java_functional_lsp/analyzers/functional_checker.py +0 -0
  45. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/src/java_functional_lsp/analyzers/mutation_checker.py +0 -0
  46. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/src/java_functional_lsp/analyzers/null_checker.py +0 -0
  47. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/src/java_functional_lsp/analyzers/spring_checker.py +0 -0
  48. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/src/java_functional_lsp/cli.py +0 -0
  49. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/src/java_functional_lsp/fixes.py +0 -0
  50. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/src/java_functional_lsp/merkle.py +0 -0
  51. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/src/java_functional_lsp/proxy.py +0 -0
  52. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/tests/__init__.py +0 -0
  53. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/tests/conftest.py +0 -0
  54. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/tests/test_base.py +0 -0
  55. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/tests/test_cli.py +0 -0
  56. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/tests/test_config.py +0 -0
  57. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/tests/test_e2e.py +0 -0
  58. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/tests/test_e2e_jdtls.py +0 -0
  59. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/tests/test_exception_checker.py +0 -0
  60. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/tests/test_fixes.py +0 -0
  61. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/tests/test_functional_checker.py +0 -0
  62. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/tests/test_merkle.py +0 -0
  63. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/tests/test_merkle_proxy.py +0 -0
  64. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/tests/test_mutation_checker.py +0 -0
  65. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/tests/test_null_checker.py +0 -0
  66. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/tests/test_proxy.py +0 -0
  67. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/tests/test_spring_checker.py +0 -0
  68. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/tests/test_suppress.py +0 -0
  69. {java_functional_lsp-0.9.6 → java_functional_lsp-0.9.7}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: java-functional-lsp
3
- Version: 0.9.6
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.6"
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.6"
3
+ __version__ = "0.9.7"
@@ -660,7 +660,24 @@ async def _lazy_start_jdtls(file_uri: str) -> None:
660
660
  # they only activate after jdtls starts.
661
661
 
662
662
 
663
- 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:
664
681
  """Forward a request to jdtls, ensuring the file's module is loaded.
665
682
 
666
683
  Uses ``ModuleRegistry`` for adaptive waiting:
@@ -668,8 +685,11 @@ async def _ensure_module_and_forward(method: str, params: Any, file_uri: str) ->
668
685
  - **UNKNOWN**: add module, wait until ready (adaptive, not fixed sleep)
669
686
  - **ADDED**: module sent but not confirmed — wait until ready
670
687
 
671
- When a request succeeds, marks the module as READY so subsequent
672
- 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.
673
693
  """
674
694
  proxy = server._proxy
675
695
  if not proxy.is_available:
@@ -687,9 +707,10 @@ async def _ensure_module_and_forward(method: str, params: Any, file_uri: str) ->
687
707
  serialized = _serialize_params(params)
688
708
  result = await proxy.send_request(method, serialized)
689
709
 
710
+ can_mark_ready = method not in _LIGHTWEIGHT_METHODS
690
711
  if result is not None:
691
- # Success — mark module as ready so future requests are instant.
692
- if module_uri:
712
+ # Success — mark module as ready so future cross-file requests are instant.
713
+ if can_mark_ready and module_uri:
693
714
  proxy.modules.mark_ready(module_uri)
694
715
  return result
695
716
 
@@ -701,7 +722,7 @@ async def _ensure_module_and_forward(method: str, params: Any, file_uri: str) ->
701
722
  await proxy.modules.wait_until_ready(wait_uri, timeout=5.0)
702
723
  # Always retry once after waiting — even on timeout the module may be ready.
703
724
  result = await proxy.send_request(method, serialized)
704
- if result is not None and module_uri:
725
+ if result is not None and can_mark_ready and module_uri:
705
726
  proxy.modules.mark_ready(module_uri)
706
727
  return result
707
728
 
@@ -581,6 +581,34 @@ class TestServerInternals:
581
581
  finally:
582
582
  srv._proxy.modules.clear()
583
583
 
584
+ async def test_ensure_module_and_forward_lightweight_methods_skip_transition(self) -> None:
585
+ """Methods in _LIGHTWEIGHT_METHODS do not transition module to READY."""
586
+ from unittest.mock import AsyncMock, patch
587
+
588
+ from java_functional_lsp.proxy import ModuleState
589
+ from java_functional_lsp.server import _LIGHTWEIGHT_METHODS, _ensure_module_and_forward
590
+ from java_functional_lsp.server import server as srv
591
+
592
+ mock_add = AsyncMock(return_value="file:///mod")
593
+ raw_result = [{"range": {"start": {"line": 0, "character": 0}, "end": {"line": 0, "character": 3}}}]
594
+ mock_send = AsyncMock(return_value=raw_result)
595
+ try:
596
+ for lightweight_method in _LIGHTWEIGHT_METHODS:
597
+ srv._proxy.modules.clear()
598
+ with (
599
+ patch.object(srv._proxy, "add_module_if_new", mock_add),
600
+ patch.object(srv._proxy, "send_request", mock_send),
601
+ patch.object(srv._proxy, "_available", True),
602
+ patch("java_functional_lsp.server._resolve_module_uri", return_value="file:///mod"),
603
+ ):
604
+ await _ensure_module_and_forward(lightweight_method, {}, "file:///mod/F.java")
605
+ # Module should NOT be READY — lightweight op does not confirm full indexing.
606
+ assert srv._proxy.modules.get_state("file:///mod") != ModuleState.READY, (
607
+ f"{lightweight_method} should not mark module as READY"
608
+ )
609
+ finally:
610
+ srv._proxy.modules.clear()
611
+
584
612
  async def test_on_prepare_call_hierarchy_forwards_to_jdtls(self) -> None:
585
613
  """_on_prepare_call_hierarchy forwards request and structures result."""
586
614
  from unittest.mock import AsyncMock, patch