java-functional-lsp 0.9.11__tar.gz → 0.9.12__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.11 → java_functional_lsp-0.9.12}/PKG-INFO +32 -2
  2. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/README.md +31 -1
  3. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/pyproject.toml +1 -1
  4. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/src/java_functional_lsp/__init__.py +1 -1
  5. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/src/java_functional_lsp/server.py +19 -0
  6. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/tests/test_server.py +44 -0
  7. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/.claude-plugin/plugin.json +0 -0
  8. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/.githooks/pre-commit +0 -0
  9. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/.githooks/pre-push +0 -0
  10. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/.github/CODEOWNERS +0 -0
  11. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/.github/ISSUE_TEMPLATE/bug-report.md +0 -0
  12. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/.github/ISSUE_TEMPLATE/feature-request.md +0 -0
  13. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  14. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/.github/SECURITY.md +0 -0
  15. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/.github/dependabot.yml +0 -0
  16. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/.github/release-drafter.yml +0 -0
  17. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/.github/workflows/publish.yml +0 -0
  18. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/.github/workflows/release-drafter.yml +0 -0
  19. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/.github/workflows/stale.yml +0 -0
  20. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/.github/workflows/test.yml +0 -0
  21. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/.github/workflows/update-homebrew.yml +0 -0
  22. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/.github/workflows/vscode-ext.yml +0 -0
  23. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/.gitignore +0 -0
  24. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/CONTRIBUTING.md +0 -0
  25. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/LICENSE +0 -0
  26. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/SKILL.md +0 -0
  27. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/commands/lint-java.md +0 -0
  28. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/editors/intellij/README.md +0 -0
  29. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/editors/intellij/lsp4ij-template.json +0 -0
  30. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/editors/vscode/.vscodeignore +0 -0
  31. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/editors/vscode/README.md +0 -0
  32. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/editors/vscode/package-lock.json +0 -0
  33. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/editors/vscode/package.json +0 -0
  34. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/editors/vscode/src/extension.ts +0 -0
  35. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/editors/vscode/tsconfig.json +0 -0
  36. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/hooks/hooks.json +0 -0
  37. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/hooks/java_linter_reminder.py +0 -0
  38. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/scripts/ensure-lsp.sh +0 -0
  39. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/scripts/generate-formula.py +0 -0
  40. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/src/java_functional_lsp/__main__.py +0 -0
  41. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/src/java_functional_lsp/analyzers/__init__.py +0 -0
  42. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/src/java_functional_lsp/analyzers/base.py +0 -0
  43. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/src/java_functional_lsp/analyzers/exception_checker.py +0 -0
  44. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/src/java_functional_lsp/analyzers/functional_checker.py +0 -0
  45. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/src/java_functional_lsp/analyzers/mutation_checker.py +0 -0
  46. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/src/java_functional_lsp/analyzers/null_checker.py +0 -0
  47. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/src/java_functional_lsp/analyzers/spring_checker.py +0 -0
  48. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/src/java_functional_lsp/cli.py +0 -0
  49. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/src/java_functional_lsp/fixes.py +0 -0
  50. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/src/java_functional_lsp/merkle.py +0 -0
  51. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/src/java_functional_lsp/proxy.py +0 -0
  52. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/tests/__init__.py +0 -0
  53. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/tests/conftest.py +0 -0
  54. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/tests/test_base.py +0 -0
  55. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/tests/test_cli.py +0 -0
  56. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/tests/test_config.py +0 -0
  57. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/tests/test_e2e.py +0 -0
  58. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/tests/test_e2e_jdtls.py +0 -0
  59. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/tests/test_exception_checker.py +0 -0
  60. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/tests/test_fixes.py +0 -0
  61. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/tests/test_functional_checker.py +0 -0
  62. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/tests/test_merkle.py +0 -0
  63. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/tests/test_merkle_proxy.py +0 -0
  64. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/tests/test_mutation_checker.py +0 -0
  65. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/tests/test_null_checker.py +0 -0
  66. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/tests/test_proxy.py +0 -0
  67. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/tests/test_spring_checker.py +0 -0
  68. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/tests/test_suppress.py +0 -0
  69. {java_functional_lsp-0.9.11 → java_functional_lsp-0.9.12}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: java-functional-lsp
3
- Version: 0.9.11
3
+ Version: 0.9.12
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
@@ -270,7 +270,37 @@ The server auto-discovers `lombok.jar` from these locations (first match wins):
270
270
  3. **Maven cache** — auto-discovered from `~/.m2/repository/org/projectlombok/lombok/`
271
271
  4. **Dedicated directory** — `~/.jdtls-libs/lombok.jar`
272
272
 
273
- If Lombok is used in your project but the jar isn't found, the server logs a warning. The jdtls cache is automatically cleared on version upgrade, so adding Lombok support takes effect immediately after `brew upgrade`.
273
+ If Lombok is used in your project but the jar isn't found, the server logs a warning.
274
+
275
+ ### jdtls settings
276
+
277
+ The server sends Maven/Gradle settings to jdtls at startup via `initializationOptions.settings`. Defaults are optimized for Maven monorepos (Maven enabled, Gradle disabled, build artifact exclusions). Override via `.java-functional-lsp.json`:
278
+
279
+ ```json
280
+ {
281
+ "jdtls": {
282
+ "settings": {
283
+ "java": {
284
+ "import": {
285
+ "maven": { "enabled": true },
286
+ "gradle": { "enabled": true },
287
+ "exclusions": ["**/node_modules/**", "**/target/**"]
288
+ },
289
+ "configuration": { "updateBuildConfiguration": "automatic" },
290
+ "maven": { "downloadSources": true }
291
+ }
292
+ }
293
+ }
294
+ }
295
+ ```
296
+
297
+ Custom settings fully replace the defaults (no merge). See the [jdtls Preferences reference](https://github.com/eclipse-jdtls/eclipse.jdt.ls/blob/main/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/preferences/Preferences.java) for all available keys.
298
+
299
+ ### jdtls cache
300
+
301
+ The jdtls Eclipse workspace index is cached in `~/.cache/jdtls-data/`. Warm starts (~10-20s) reuse this cache; cold starts (60-120s) rebuild from scratch. The cache is automatically invalidated when jdtls or Java is upgraded, but **not** when java-functional-lsp is upgraded — our Python code changes don't affect the Eclipse index.
302
+
303
+ To force a clean rebuild: `rm -rf ~/.cache/jdtls-data/`
274
304
 
275
305
  ### Suppressing jdtls diagnostics
276
306
 
@@ -242,7 +242,37 @@ The server auto-discovers `lombok.jar` from these locations (first match wins):
242
242
  3. **Maven cache** — auto-discovered from `~/.m2/repository/org/projectlombok/lombok/`
243
243
  4. **Dedicated directory** — `~/.jdtls-libs/lombok.jar`
244
244
 
245
- If Lombok is used in your project but the jar isn't found, the server logs a warning. The jdtls cache is automatically cleared on version upgrade, so adding Lombok support takes effect immediately after `brew upgrade`.
245
+ If Lombok is used in your project but the jar isn't found, the server logs a warning.
246
+
247
+ ### jdtls settings
248
+
249
+ The server sends Maven/Gradle settings to jdtls at startup via `initializationOptions.settings`. Defaults are optimized for Maven monorepos (Maven enabled, Gradle disabled, build artifact exclusions). Override via `.java-functional-lsp.json`:
250
+
251
+ ```json
252
+ {
253
+ "jdtls": {
254
+ "settings": {
255
+ "java": {
256
+ "import": {
257
+ "maven": { "enabled": true },
258
+ "gradle": { "enabled": true },
259
+ "exclusions": ["**/node_modules/**", "**/target/**"]
260
+ },
261
+ "configuration": { "updateBuildConfiguration": "automatic" },
262
+ "maven": { "downloadSources": true }
263
+ }
264
+ }
265
+ }
266
+ }
267
+ ```
268
+
269
+ Custom settings fully replace the defaults (no merge). See the [jdtls Preferences reference](https://github.com/eclipse-jdtls/eclipse.jdt.ls/blob/main/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/preferences/Preferences.java) for all available keys.
270
+
271
+ ### jdtls cache
272
+
273
+ The jdtls Eclipse workspace index is cached in `~/.cache/jdtls-data/`. Warm starts (~10-20s) reuse this cache; cold starts (60-120s) rebuild from scratch. The cache is automatically invalidated when jdtls or Java is upgraded, but **not** when java-functional-lsp is upgraded — our Python code changes don't affect the Eclipse index.
274
+
275
+ To force a clean rebuild: `rm -rf ~/.cache/jdtls-data/`
246
276
 
247
277
  ### Suppressing jdtls diagnostics
248
278
 
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "java-functional-lsp"
7
- version = "0.9.11"
7
+ version = "0.9.12"
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.11"
3
+ __version__ = "0.9.12"
@@ -12,6 +12,7 @@ import logging
12
12
  import os
13
13
  import re
14
14
  import sys
15
+ import time
15
16
  from collections.abc import Coroutine
16
17
  from pathlib import Path
17
18
  from typing import Any
@@ -635,6 +636,24 @@ async def on_did_close(params: lsp.DidCloseTextDocumentParams) -> None:
635
636
  _forward_or_queue("textDocument/didClose", _serialize_params(params))
636
637
 
637
638
 
639
+ _DIDCHANGE_CONFIG_COOLDOWN = 30.0 # seconds — rate-limit didChangeConfiguration forwarding
640
+ _last_config_forward: float = 0.0
641
+
642
+
643
+ @server.feature(lsp.WORKSPACE_DID_CHANGE_CONFIGURATION)
644
+ def on_did_change_configuration(params: lsp.DidChangeConfigurationParams) -> None:
645
+ """Forward IDE configuration changes to jdtls (rate-limited)."""
646
+ global _last_config_forward
647
+ if not server._proxy.is_available:
648
+ return
649
+ now = time.monotonic()
650
+ if now - _last_config_forward < _DIDCHANGE_CONFIG_COOLDOWN:
651
+ logger.debug("jdtls: throttling didChangeConfiguration (%.0fs cooldown)", _DIDCHANGE_CONFIG_COOLDOWN)
652
+ return
653
+ _last_config_forward = now
654
+ _fire_and_forget(server._proxy.send_notification("workspace/didChangeConfiguration", _serialize_params(params)))
655
+
656
+
638
657
  async def _lazy_start_jdtls(file_uri: str) -> None:
639
658
  """Background task: start jdtls scoped to the module containing *file_uri*.
640
659
 
@@ -1547,6 +1547,50 @@ class TestFindLombokJar:
1547
1547
  assert any("does not exist" in r.getMessage() for r in caplog.records)
1548
1548
 
1549
1549
 
1550
+ class TestDidChangeConfiguration:
1551
+ """Tests for workspace/didChangeConfiguration forwarding."""
1552
+
1553
+ def test_forwards_to_jdtls_when_available(self) -> None:
1554
+ from unittest.mock import AsyncMock, patch
1555
+
1556
+ import java_functional_lsp.server as srv_mod
1557
+ from java_functional_lsp.server import on_did_change_configuration, server
1558
+
1559
+ srv_mod._last_config_forward = 0.0 # reset cooldown
1560
+ server._proxy._available = True
1561
+ server._proxy.send_notification = AsyncMock() # type: ignore[assignment]
1562
+ params = lsp.DidChangeConfigurationParams(settings={"java": {"autobuild": {"enabled": True}}})
1563
+ with patch("java_functional_lsp.server._fire_and_forget") as mock_faf:
1564
+ on_did_change_configuration(params)
1565
+ mock_faf.assert_called_once()
1566
+
1567
+ def test_throttled_within_cooldown(self) -> None:
1568
+ from unittest.mock import patch
1569
+
1570
+ import java_functional_lsp.server as srv_mod
1571
+ from java_functional_lsp.server import on_did_change_configuration, server
1572
+
1573
+ server._proxy._available = True
1574
+ import time
1575
+
1576
+ srv_mod._last_config_forward = time.monotonic() # just sent
1577
+ params = lsp.DidChangeConfigurationParams(settings={})
1578
+ with patch("java_functional_lsp.server._fire_and_forget") as mock_faf:
1579
+ on_did_change_configuration(params)
1580
+ mock_faf.assert_not_called()
1581
+
1582
+ def test_skipped_when_proxy_unavailable(self) -> None:
1583
+ from unittest.mock import patch
1584
+
1585
+ from java_functional_lsp.server import on_did_change_configuration, server
1586
+
1587
+ server._proxy._available = False
1588
+ params = lsp.DidChangeConfigurationParams(settings={})
1589
+ with patch("java_functional_lsp.server._fire_and_forget") as mock_faf:
1590
+ on_did_change_configuration(params)
1591
+ mock_faf.assert_not_called()
1592
+
1593
+
1550
1594
  class TestCacheClear:
1551
1595
  """Tests for _clear_cache_on_version_change() and _compute_cache_marker()."""
1552
1596