java-functional-lsp 0.9.16__tar.gz → 0.9.18__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.16 → java_functional_lsp-0.9.18}/PKG-INFO +1 -1
  2. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/pyproject.toml +1 -1
  3. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/src/java_functional_lsp/__init__.py +1 -1
  4. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/src/java_functional_lsp/cli.py +7 -1
  5. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/src/java_functional_lsp/server.py +42 -2
  6. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/tests/test_cli.py +16 -0
  7. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/uv.lock +1 -1
  8. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/.claude-plugin/plugin.json +0 -0
  9. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/.githooks/pre-commit +0 -0
  10. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/.githooks/pre-push +0 -0
  11. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/.github/CODEOWNERS +0 -0
  12. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/.github/ISSUE_TEMPLATE/bug-report.md +0 -0
  13. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/.github/ISSUE_TEMPLATE/feature-request.md +0 -0
  14. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  15. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/.github/SECURITY.md +0 -0
  16. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/.github/dependabot.yml +0 -0
  17. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/.github/release-drafter.yml +0 -0
  18. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/.github/workflows/publish.yml +0 -0
  19. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/.github/workflows/release-drafter.yml +0 -0
  20. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/.github/workflows/stale.yml +0 -0
  21. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/.github/workflows/test.yml +0 -0
  22. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/.github/workflows/update-homebrew.yml +0 -0
  23. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/.github/workflows/vscode-ext.yml +0 -0
  24. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/.gitignore +0 -0
  25. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/CONTRIBUTING.md +0 -0
  26. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/LICENSE +0 -0
  27. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/README.md +0 -0
  28. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/SKILL.md +0 -0
  29. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/commands/lint-java.md +0 -0
  30. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/editors/intellij/README.md +0 -0
  31. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/editors/intellij/lsp4ij-template.json +0 -0
  32. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/editors/vscode/.vscodeignore +0 -0
  33. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/editors/vscode/README.md +0 -0
  34. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/editors/vscode/package-lock.json +0 -0
  35. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/editors/vscode/package.json +0 -0
  36. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/editors/vscode/src/extension.ts +0 -0
  37. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/editors/vscode/tsconfig.json +0 -0
  38. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/hooks/hooks.json +0 -0
  39. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/hooks/java_linter_reminder.py +0 -0
  40. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/scripts/ensure-lsp.sh +0 -0
  41. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/scripts/generate-formula.py +0 -0
  42. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/src/java_functional_lsp/__main__.py +0 -0
  43. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/src/java_functional_lsp/analyzers/__init__.py +0 -0
  44. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/src/java_functional_lsp/analyzers/base.py +0 -0
  45. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/src/java_functional_lsp/analyzers/exception_checker.py +0 -0
  46. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/src/java_functional_lsp/analyzers/functional_checker.py +0 -0
  47. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/src/java_functional_lsp/analyzers/mutation_checker.py +0 -0
  48. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/src/java_functional_lsp/analyzers/null_checker.py +0 -0
  49. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/src/java_functional_lsp/analyzers/spring_checker.py +0 -0
  50. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/src/java_functional_lsp/fixes.py +0 -0
  51. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/src/java_functional_lsp/merkle.py +0 -0
  52. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/src/java_functional_lsp/proxy.py +0 -0
  53. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/tests/__init__.py +0 -0
  54. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/tests/conftest.py +0 -0
  55. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/tests/test_base.py +0 -0
  56. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/tests/test_config.py +0 -0
  57. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/tests/test_e2e.py +0 -0
  58. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/tests/test_e2e_jdtls.py +0 -0
  59. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/tests/test_exception_checker.py +0 -0
  60. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/tests/test_fixes.py +0 -0
  61. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/tests/test_functional_checker.py +0 -0
  62. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/tests/test_merkle.py +0 -0
  63. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/tests/test_merkle_proxy.py +0 -0
  64. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/tests/test_mutation_checker.py +0 -0
  65. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/tests/test_null_checker.py +0 -0
  66. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/tests/test_proxy.py +0 -0
  67. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/tests/test_server.py +0 -0
  68. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/tests/test_spring_checker.py +0 -0
  69. {java_functional_lsp-0.9.16 → java_functional_lsp-0.9.18}/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.16
3
+ Version: 0.9.18
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.16"
7
+ version = "0.9.18"
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.16"
3
+ __version__ = "0.9.18"
@@ -7,6 +7,7 @@ import sys
7
7
  from pathlib import Path
8
8
  from typing import Any
9
9
 
10
+ from . import __version__
10
11
  from .analyzers.base import Analyzer, Diagnostic, Severity, get_parser, is_excluded
11
12
  from .analyzers.exception_checker import ExceptionChecker
12
13
  from .analyzers.functional_checker import FunctionalChecker
@@ -69,7 +70,8 @@ def format_diagnostic(path: Path, d: Diagnostic) -> str:
69
70
  _USAGE = """\
70
71
  Usage: java-functional-lsp check <file.java> [file2.java ...]
71
72
  java-functional-lsp check --dir <directory>
72
- java-functional-lsp (start LSP server on stdio)"""
73
+ java-functional-lsp (start LSP server on stdio)
74
+ java-functional-lsp --version"""
73
75
 
74
76
 
75
77
  def _collect_files(args: list[str]) -> list[Path]:
@@ -103,6 +105,10 @@ def main() -> None:
103
105
  print(_USAGE)
104
106
  sys.exit(0)
105
107
 
108
+ if args and args[0] in ("-v", "--version"):
109
+ print(f"java-functional-lsp {__version__}")
110
+ sys.exit(0)
111
+
106
112
  if not args or args[0] != "check":
107
113
  # No args or unknown command — start LSP server on stdio
108
114
  from .server import main as lsp_main
@@ -16,7 +16,11 @@ import time
16
16
  from collections import OrderedDict
17
17
  from collections.abc import Coroutine
18
18
  from pathlib import Path
19
- from typing import Any
19
+ from threading import Event
20
+ from typing import TYPE_CHECKING, Any
21
+
22
+ if TYPE_CHECKING:
23
+ from typing import BinaryIO
20
24
 
21
25
  from lsprotocol import types as lsp
22
26
  from lsprotocol.converters import get_converter
@@ -1204,10 +1208,46 @@ def on_code_action(params: lsp.CodeActionParams) -> list[lsp.CodeAction] | None:
1204
1208
  # --- Entry point ---
1205
1209
 
1206
1210
 
1211
+ class _EternalStdinBuffer:
1212
+ """Wraps sys.stdin.buffer so EOF never propagates to the pygls reader.
1213
+
1214
+ Claude Code (ENABLE_LSP_TOOL, versions ≤ 0.2.x) closes the LSP subprocess's
1215
+ stdin pipe immediately after process startup — before sending any LSP messages.
1216
+ pygls sees EOF on the first readline() and shuts down the server.
1217
+
1218
+ This wrapper intercepts that EOF: instead of returning b'' (which pygls's
1219
+ run_async() treats as a signal to break its read loop and shut down), it
1220
+ blocks the calling thread indefinitely via threading.Event.wait().
1221
+
1222
+ pygls uses a ThreadPoolExecutor for stdin reads (run_in_executor), so
1223
+ blocking one thread does not stall the asyncio event loop — all other
1224
+ coroutines (jdtls proxy, diagnostics publishing, etc.) remain responsive.
1225
+
1226
+ When Claude Code is fixed upstream, this class becomes a transparent pass-
1227
+ through: data before EOF is forwarded unchanged; only the EOF itself is swallowed.
1228
+ """
1229
+
1230
+ def __init__(self, buf: BinaryIO) -> None:
1231
+ self._buf = buf
1232
+ self._eof_gate = Event() # never set — waits block forever
1233
+
1234
+ def readline(self) -> bytes:
1235
+ line = self._buf.readline()
1236
+ if not line:
1237
+ self._eof_gate.wait() # block forever instead of returning b''
1238
+ return line
1239
+
1240
+ def read(self, n: int) -> bytes:
1241
+ data = self._buf.read(n)
1242
+ if not data:
1243
+ self._eof_gate.wait()
1244
+ return data
1245
+
1246
+
1207
1247
  def main() -> None:
1208
1248
  """Entry point for the LSP server."""
1209
1249
  logging.basicConfig(level=logging.INFO, format="%(name)s %(levelname)s: %(message)s")
1210
- server.start_io()
1250
+ server.start_io(stdin=_EternalStdinBuffer(sys.stdin.buffer)) # type: ignore[arg-type]
1211
1251
 
1212
1252
 
1213
1253
  if __name__ == "__main__":
@@ -79,3 +79,19 @@ class TestHelp:
79
79
  main()
80
80
  assert exc.value.code == 0
81
81
  assert "check" in capsys.readouterr().out
82
+
83
+
84
+ class TestVersion:
85
+ def test_version_flag(self, capsys: pytest.CaptureFixture[str]) -> None:
86
+ with patch("sys.argv", ["java-functional-lsp", "--version"]):
87
+ with pytest.raises(SystemExit) as exc:
88
+ main()
89
+ assert exc.value.code == 0
90
+ assert "java-functional-lsp" in capsys.readouterr().out
91
+
92
+ def test_version_short_flag(self, capsys: pytest.CaptureFixture[str]) -> None:
93
+ with patch("sys.argv", ["java-functional-lsp", "-v"]):
94
+ with pytest.raises(SystemExit) as exc:
95
+ main()
96
+ assert exc.value.code == 0
97
+ assert "java-functional-lsp" in capsys.readouterr().out
@@ -184,7 +184,7 @@ wheels = [
184
184
 
185
185
  [[package]]
186
186
  name = "java-functional-lsp"
187
- version = "0.9.14"
187
+ version = "0.9.18"
188
188
  source = { editable = "." }
189
189
  dependencies = [
190
190
  { name = "pygls" },