java-functional-lsp 0.9.10__tar.gz → 0.9.11__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.
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/PKG-INFO +1 -1
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/pyproject.toml +1 -1
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/src/java_functional_lsp/__init__.py +1 -1
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/src/java_functional_lsp/proxy.py +92 -27
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/tests/test_proxy.py +52 -0
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/tests/test_server.py +34 -13
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/.claude-plugin/plugin.json +0 -0
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/.githooks/pre-commit +0 -0
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/.githooks/pre-push +0 -0
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/.github/CODEOWNERS +0 -0
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/.github/ISSUE_TEMPLATE/bug-report.md +0 -0
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/.github/ISSUE_TEMPLATE/feature-request.md +0 -0
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/.github/SECURITY.md +0 -0
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/.github/dependabot.yml +0 -0
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/.github/release-drafter.yml +0 -0
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/.github/workflows/publish.yml +0 -0
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/.github/workflows/release-drafter.yml +0 -0
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/.github/workflows/stale.yml +0 -0
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/.github/workflows/test.yml +0 -0
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/.github/workflows/update-homebrew.yml +0 -0
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/.github/workflows/vscode-ext.yml +0 -0
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/.gitignore +0 -0
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/CONTRIBUTING.md +0 -0
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/LICENSE +0 -0
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/README.md +0 -0
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/SKILL.md +0 -0
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/commands/lint-java.md +0 -0
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/editors/intellij/README.md +0 -0
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/editors/intellij/lsp4ij-template.json +0 -0
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/editors/vscode/.vscodeignore +0 -0
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/editors/vscode/README.md +0 -0
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/editors/vscode/package-lock.json +0 -0
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/editors/vscode/package.json +0 -0
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/editors/vscode/src/extension.ts +0 -0
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/editors/vscode/tsconfig.json +0 -0
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/hooks/hooks.json +0 -0
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/hooks/java_linter_reminder.py +0 -0
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/scripts/ensure-lsp.sh +0 -0
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/scripts/generate-formula.py +0 -0
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/src/java_functional_lsp/__main__.py +0 -0
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/src/java_functional_lsp/analyzers/__init__.py +0 -0
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/src/java_functional_lsp/analyzers/base.py +0 -0
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/src/java_functional_lsp/analyzers/exception_checker.py +0 -0
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/src/java_functional_lsp/analyzers/functional_checker.py +0 -0
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/src/java_functional_lsp/analyzers/mutation_checker.py +0 -0
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/src/java_functional_lsp/analyzers/null_checker.py +0 -0
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/src/java_functional_lsp/analyzers/spring_checker.py +0 -0
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/src/java_functional_lsp/cli.py +0 -0
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/src/java_functional_lsp/fixes.py +0 -0
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/src/java_functional_lsp/merkle.py +0 -0
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/src/java_functional_lsp/server.py +0 -0
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/tests/__init__.py +0 -0
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/tests/conftest.py +0 -0
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/tests/test_base.py +0 -0
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/tests/test_cli.py +0 -0
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/tests/test_config.py +0 -0
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/tests/test_e2e.py +0 -0
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/tests/test_e2e_jdtls.py +0 -0
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/tests/test_exception_checker.py +0 -0
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/tests/test_fixes.py +0 -0
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/tests/test_functional_checker.py +0 -0
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/tests/test_merkle.py +0 -0
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/tests/test_merkle_proxy.py +0 -0
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/tests/test_mutation_checker.py +0 -0
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/tests/test_null_checker.py +0 -0
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/tests/test_spring_checker.py +0 -0
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/tests/test_suppress.py +0 -0
- {java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/uv.lock +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: java-functional-lsp
|
|
3
|
-
Version: 0.9.
|
|
3
|
+
Version: 0.9.11
|
|
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.
|
|
7
|
+
version = "0.9.11"
|
|
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" }
|
|
@@ -30,6 +30,27 @@ DEFAULT_JVM_MAX_HEAP = "4g"
|
|
|
30
30
|
_STDERR_LINE_MAX = 1000
|
|
31
31
|
_MAX_EXPANDED_GROUPS: int = 5 # hard cap on concurrent Maven group workspace folders (prevents jdtls OOM)
|
|
32
32
|
|
|
33
|
+
# Default jdtls initialization settings. Sent via initializationOptions.settings
|
|
34
|
+
# so they apply BEFORE the Maven import scan (didChangeConfiguration is too late).
|
|
35
|
+
# Users can override via .java-functional-lsp.json: {"jdtls": {"settings": {...}}}
|
|
36
|
+
_DEFAULT_JDTLS_SETTINGS: dict[str, Any] = {
|
|
37
|
+
"java": {
|
|
38
|
+
"import": {
|
|
39
|
+
"maven": {"enabled": True},
|
|
40
|
+
"gradle": {"enabled": False},
|
|
41
|
+
"exclusions": [
|
|
42
|
+
"**/node_modules/**",
|
|
43
|
+
"**/.metadata/**",
|
|
44
|
+
"**/archetype-resources/**",
|
|
45
|
+
"**/META-INF/maven/**",
|
|
46
|
+
"**/target/**",
|
|
47
|
+
],
|
|
48
|
+
},
|
|
49
|
+
"configuration": {"updateBuildConfiguration": "automatic"},
|
|
50
|
+
"maven": {"downloadSources": False},
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
33
54
|
#: Minimum Java major version required by jdtls 1.57+. Anything below this
|
|
34
55
|
#: is rejected by the jdtls Python launcher with ``"jdtls requires at least
|
|
35
56
|
#: Java 21"`` before the server even starts.
|
|
@@ -558,25 +579,43 @@ def _wipe_data_dir(data_dir: Path) -> None:
|
|
|
558
579
|
logger.info("jdtls: wiped data-dir %s after init timeout", _redact_path(str(data_dir)))
|
|
559
580
|
|
|
560
581
|
|
|
561
|
-
def
|
|
562
|
-
"""
|
|
582
|
+
def _compute_cache_marker() -> str:
|
|
583
|
+
"""Compute a stable cache marker from jdtls version path + Java version.
|
|
563
584
|
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
585
|
+
Our Python package version changes (pip upgrades) do NOT affect the jdtls
|
|
586
|
+
Eclipse workspace index — only jdtls binary upgrades or Java version
|
|
587
|
+
changes do. Resolves through symlinks so Homebrew Cellar version changes
|
|
588
|
+
(e.g. ``/opt/homebrew/Cellar/jdtls/1.58.0/...``) are detected even when
|
|
589
|
+
the wrapper script at ``/opt/homebrew/bin/jdtls`` doesn't change.
|
|
567
590
|
"""
|
|
568
|
-
|
|
591
|
+
parts: list[str] = []
|
|
592
|
+
jdtls_path = shutil.which("jdtls")
|
|
593
|
+
if jdtls_path:
|
|
594
|
+
resolved = str(Path(jdtls_path).resolve())
|
|
595
|
+
parts.append(hashlib.sha256(resolved.encode()).hexdigest()[:12])
|
|
596
|
+
parts.append(str(_MIN_JDTLS_JAVA_MAJOR))
|
|
597
|
+
return "|".join(parts)
|
|
598
|
+
|
|
599
|
+
|
|
600
|
+
def _clear_cache_on_version_change(cache_root: Path) -> None:
|
|
601
|
+
"""Clear jdtls data cache when the jdtls installation changes.
|
|
569
602
|
|
|
603
|
+
Stores a ``.version`` marker in the cache root. The marker is derived
|
|
604
|
+
from the resolved jdtls binary path + Java version requirement — NOT
|
|
605
|
+
from our Python ``__version__``. This preserves warm caches across
|
|
606
|
+
java-functional-lsp upgrades (which don't affect the Eclipse index).
|
|
607
|
+
"""
|
|
608
|
+
current_marker = _compute_cache_marker()
|
|
570
609
|
marker = cache_root / ".version"
|
|
571
610
|
try:
|
|
572
|
-
if marker.exists() and marker.read_text().strip() ==
|
|
611
|
+
if marker.exists() and marker.read_text().strip() == current_marker:
|
|
573
612
|
return
|
|
574
|
-
#
|
|
613
|
+
# jdtls or Java version changed, or first run — clear stale caches.
|
|
575
614
|
if cache_root.exists():
|
|
576
615
|
shutil.rmtree(cache_root)
|
|
577
|
-
logger.info("jdtls: cleared stale cache (
|
|
616
|
+
logger.info("jdtls: cleared stale cache (marker changed to %s)", current_marker)
|
|
578
617
|
cache_root.mkdir(parents=True, exist_ok=True)
|
|
579
|
-
marker.write_text(
|
|
618
|
+
marker.write_text(current_marker)
|
|
580
619
|
except OSError as e:
|
|
581
620
|
logger.warning("jdtls: failed to manage cache version marker: %s", e)
|
|
582
621
|
|
|
@@ -622,6 +661,48 @@ def _find_lombok_jar(config: Mapping[str, Any] | None = None) -> str | None:
|
|
|
622
661
|
return None
|
|
623
662
|
|
|
624
663
|
|
|
664
|
+
def _build_effective_params(
|
|
665
|
+
init_params: dict[str, Any],
|
|
666
|
+
module_root_uri: str | None,
|
|
667
|
+
original_root: str,
|
|
668
|
+
config: Mapping[str, Any] | None,
|
|
669
|
+
) -> dict[str, Any]:
|
|
670
|
+
"""Build the ``initialize`` request params for jdtls.
|
|
671
|
+
|
|
672
|
+
Deep-copies *init_params*, scopes to *module_root_uri* if provided,
|
|
673
|
+
injects workspaceFolders capability, and injects Maven/Gradle settings
|
|
674
|
+
from *config* (or defaults) into ``initializationOptions.settings``.
|
|
675
|
+
"""
|
|
676
|
+
from pygls.uris import to_fs_path
|
|
677
|
+
|
|
678
|
+
effective_params = copy.deepcopy(init_params)
|
|
679
|
+
if module_root_uri:
|
|
680
|
+
effective_params["rootUri"] = module_root_uri
|
|
681
|
+
effective_params["rootPath"] = to_fs_path(module_root_uri)
|
|
682
|
+
logger.info(
|
|
683
|
+
"jdtls: scoping to module %s (full root: %s)",
|
|
684
|
+
_redact_path(module_root_uri),
|
|
685
|
+
_redact_path(original_root),
|
|
686
|
+
)
|
|
687
|
+
|
|
688
|
+
# Inject workspaceFolders capability for later expansion.
|
|
689
|
+
caps = effective_params.setdefault("capabilities", {})
|
|
690
|
+
ws = caps.setdefault("workspace", {})
|
|
691
|
+
ws["workspaceFolders"] = True
|
|
692
|
+
|
|
693
|
+
# Inject jdtls Maven/Gradle settings into initializationOptions.
|
|
694
|
+
# Must be in initializationOptions (not didChangeConfiguration) so they
|
|
695
|
+
# apply before the Maven import scan starts.
|
|
696
|
+
jdtls_settings = copy.deepcopy(_DEFAULT_JDTLS_SETTINGS)
|
|
697
|
+
if config and "jdtls" in config and "settings" in config["jdtls"]:
|
|
698
|
+
jdtls_settings = copy.deepcopy(config["jdtls"]["settings"])
|
|
699
|
+
init_opts = effective_params.setdefault("initializationOptions", {})
|
|
700
|
+
init_opts["settings"] = jdtls_settings
|
|
701
|
+
logger.debug("jdtls: initializationOptions.settings = %s", jdtls_settings)
|
|
702
|
+
|
|
703
|
+
return effective_params
|
|
704
|
+
|
|
705
|
+
|
|
625
706
|
class JdtlsProxy:
|
|
626
707
|
"""Manages a jdtls subprocess and provides async request/notification forwarding."""
|
|
627
708
|
|
|
@@ -724,23 +805,7 @@ class JdtlsProxy:
|
|
|
724
805
|
data_dir = cache_root / data_hash
|
|
725
806
|
data_dir.mkdir(parents=True, exist_ok=True)
|
|
726
807
|
|
|
727
|
-
|
|
728
|
-
effective_params = copy.deepcopy(init_params)
|
|
729
|
-
if module_root_uri:
|
|
730
|
-
effective_params["rootUri"] = module_root_uri
|
|
731
|
-
from pygls.uris import to_fs_path
|
|
732
|
-
|
|
733
|
-
effective_params["rootPath"] = to_fs_path(module_root_uri)
|
|
734
|
-
logger.info(
|
|
735
|
-
"jdtls: scoping to module %s (full root: %s)",
|
|
736
|
-
_redact_path(module_root_uri),
|
|
737
|
-
_redact_path(original_root),
|
|
738
|
-
)
|
|
739
|
-
|
|
740
|
-
# Inject workspaceFolders capability for later expansion.
|
|
741
|
-
caps = effective_params.setdefault("capabilities", {})
|
|
742
|
-
ws = caps.setdefault("workspace", {})
|
|
743
|
-
ws["workspaceFolders"] = True
|
|
808
|
+
effective_params = _build_effective_params(init_params, module_root_uri, original_root, config)
|
|
744
809
|
|
|
745
810
|
jdtls_cmd: list[str] = [
|
|
746
811
|
jdtls_path,
|
|
@@ -1417,6 +1417,58 @@ class TestLazyStart:
|
|
|
1417
1417
|
# ---------------------------------------------------------------------------
|
|
1418
1418
|
|
|
1419
1419
|
|
|
1420
|
+
class TestBuildEffectiveParams:
|
|
1421
|
+
"""Tests for _build_effective_params."""
|
|
1422
|
+
|
|
1423
|
+
def test_defaults_injected_when_no_config(self) -> None:
|
|
1424
|
+
from java_functional_lsp.proxy import _build_effective_params
|
|
1425
|
+
|
|
1426
|
+
result = _build_effective_params({"rootUri": "file:///ws"}, None, "file:///ws", None)
|
|
1427
|
+
settings = result["initializationOptions"]["settings"]
|
|
1428
|
+
assert settings["java"]["import"]["maven"]["enabled"] is True
|
|
1429
|
+
assert settings["java"]["import"]["gradle"]["enabled"] is False
|
|
1430
|
+
assert "**/target/**" in settings["java"]["import"]["exclusions"]
|
|
1431
|
+
|
|
1432
|
+
def test_config_override_replaces_defaults(self) -> None:
|
|
1433
|
+
from java_functional_lsp.proxy import _build_effective_params
|
|
1434
|
+
|
|
1435
|
+
custom = {"java": {"custom": "value"}}
|
|
1436
|
+
config = {"jdtls": {"settings": custom}}
|
|
1437
|
+
result = _build_effective_params({"rootUri": "file:///ws"}, None, "file:///ws", config)
|
|
1438
|
+
settings = result["initializationOptions"]["settings"]
|
|
1439
|
+
assert settings == {"java": {"custom": "value"}}
|
|
1440
|
+
assert "import" not in settings.get("java", {})
|
|
1441
|
+
|
|
1442
|
+
def test_does_not_mutate_original_init_params(self) -> None:
|
|
1443
|
+
from java_functional_lsp.proxy import _build_effective_params
|
|
1444
|
+
|
|
1445
|
+
original = {"rootUri": "file:///ws", "capabilities": {}}
|
|
1446
|
+
_build_effective_params(original, "file:///mod", "file:///ws", None)
|
|
1447
|
+
assert "initializationOptions" not in original
|
|
1448
|
+
assert original["rootUri"] == "file:///ws"
|
|
1449
|
+
|
|
1450
|
+
def test_module_root_uri_scopes_root(self) -> None:
|
|
1451
|
+
from java_functional_lsp.proxy import _build_effective_params
|
|
1452
|
+
|
|
1453
|
+
result = _build_effective_params({"rootUri": "file:///ws"}, "file:///mod", "file:///ws", None)
|
|
1454
|
+
assert result["rootUri"] == "file:///mod"
|
|
1455
|
+
|
|
1456
|
+
def test_workspace_folders_capability_always_set(self) -> None:
|
|
1457
|
+
from java_functional_lsp.proxy import _build_effective_params
|
|
1458
|
+
|
|
1459
|
+
result = _build_effective_params({"rootUri": "file:///ws"}, None, "file:///ws", None)
|
|
1460
|
+
assert result["capabilities"]["workspace"]["workspaceFolders"] is True
|
|
1461
|
+
|
|
1462
|
+
def test_deepcopy_prevents_default_mutation(self) -> None:
|
|
1463
|
+
from java_functional_lsp.proxy import _DEFAULT_JDTLS_SETTINGS, _build_effective_params
|
|
1464
|
+
|
|
1465
|
+
result = _build_effective_params({"rootUri": "file:///ws"}, None, "file:///ws", None)
|
|
1466
|
+
# Mutate the returned settings
|
|
1467
|
+
result["initializationOptions"]["settings"]["java"]["import"]["exclusions"].append("MUTATED")
|
|
1468
|
+
# Module-level defaults must be unchanged
|
|
1469
|
+
assert "MUTATED" not in _DEFAULT_JDTLS_SETTINGS["java"]["import"]["exclusions"]
|
|
1470
|
+
|
|
1471
|
+
|
|
1420
1472
|
class TestWipeDataDir:
|
|
1421
1473
|
def test_wipe_removes_directory(self, tmp_path: Path) -> None:
|
|
1422
1474
|
"""Directory is removed and info is logged."""
|
|
@@ -1548,48 +1548,69 @@ class TestFindLombokJar:
|
|
|
1548
1548
|
|
|
1549
1549
|
|
|
1550
1550
|
class TestCacheClear:
|
|
1551
|
-
"""Tests for _clear_cache_on_version_change()."""
|
|
1551
|
+
"""Tests for _clear_cache_on_version_change() and _compute_cache_marker()."""
|
|
1552
1552
|
|
|
1553
1553
|
def test_clears_on_version_mismatch(self, tmp_path: Any) -> None:
|
|
1554
|
-
from java_functional_lsp.proxy import _clear_cache_on_version_change
|
|
1554
|
+
from java_functional_lsp.proxy import _clear_cache_on_version_change, _compute_cache_marker
|
|
1555
1555
|
|
|
1556
1556
|
cache = tmp_path / "jdtls-data"
|
|
1557
1557
|
cache.mkdir()
|
|
1558
1558
|
stale_dir = cache / "abc123"
|
|
1559
1559
|
stale_dir.mkdir()
|
|
1560
|
-
(cache / ".version").write_text("
|
|
1560
|
+
(cache / ".version").write_text("old-stale-marker")
|
|
1561
1561
|
|
|
1562
1562
|
_clear_cache_on_version_change(cache)
|
|
1563
1563
|
|
|
1564
1564
|
assert not stale_dir.exists(), "Stale data-dir should be cleared"
|
|
1565
1565
|
assert cache.exists(), "Cache root should be recreated"
|
|
1566
|
-
|
|
1566
|
+
assert (cache / ".version").read_text() == _compute_cache_marker()
|
|
1567
1567
|
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
def test_keeps_cache_on_same_version(self, tmp_path: Any) -> None:
|
|
1571
|
-
from java_functional_lsp import __version__
|
|
1572
|
-
from java_functional_lsp.proxy import _clear_cache_on_version_change
|
|
1568
|
+
def test_keeps_cache_on_same_marker(self, tmp_path: Any) -> None:
|
|
1569
|
+
from java_functional_lsp.proxy import _clear_cache_on_version_change, _compute_cache_marker
|
|
1573
1570
|
|
|
1574
1571
|
cache = tmp_path / "jdtls-data"
|
|
1575
1572
|
cache.mkdir()
|
|
1576
1573
|
existing_dir = cache / "abc123"
|
|
1577
1574
|
existing_dir.mkdir()
|
|
1578
|
-
(cache / ".version").write_text(
|
|
1575
|
+
(cache / ".version").write_text(_compute_cache_marker())
|
|
1579
1576
|
|
|
1580
1577
|
_clear_cache_on_version_change(cache)
|
|
1581
1578
|
|
|
1582
1579
|
assert existing_dir.exists(), "Existing data-dir should be preserved"
|
|
1583
1580
|
|
|
1584
1581
|
def test_creates_marker_on_first_run(self, tmp_path: Any) -> None:
|
|
1585
|
-
from java_functional_lsp.proxy import _clear_cache_on_version_change
|
|
1582
|
+
from java_functional_lsp.proxy import _clear_cache_on_version_change, _compute_cache_marker
|
|
1586
1583
|
|
|
1587
1584
|
cache = tmp_path / "jdtls-data"
|
|
1588
1585
|
_clear_cache_on_version_change(cache)
|
|
1589
1586
|
|
|
1590
|
-
|
|
1587
|
+
assert (cache / ".version").read_text() == _compute_cache_marker()
|
|
1588
|
+
|
|
1589
|
+
def test_python_version_bump_preserves_cache(self) -> None:
|
|
1590
|
+
"""Our __version__ is NOT in the cache marker — pip upgrades don't wipe."""
|
|
1591
|
+
from unittest.mock import patch
|
|
1592
|
+
|
|
1593
|
+
from java_functional_lsp.proxy import _compute_cache_marker
|
|
1594
|
+
|
|
1595
|
+
marker_before = _compute_cache_marker()
|
|
1596
|
+
with patch("java_functional_lsp.__version__", "99.99.99"):
|
|
1597
|
+
marker_after = _compute_cache_marker()
|
|
1598
|
+
assert marker_before == marker_after, "Changing __version__ must not change the cache marker"
|
|
1599
|
+
|
|
1600
|
+
def test_different_jdtls_paths_produce_different_markers(self) -> None:
|
|
1601
|
+
"""Different resolved jdtls paths produce different cache markers."""
|
|
1602
|
+
from pathlib import Path
|
|
1603
|
+
from unittest.mock import patch
|
|
1604
|
+
|
|
1605
|
+
from java_functional_lsp.proxy import _compute_cache_marker
|
|
1591
1606
|
|
|
1592
|
-
|
|
1607
|
+
with patch("java_functional_lsp.proxy.shutil.which", return_value="/opt/jdtls/1.57/bin/jdtls"):
|
|
1608
|
+
with patch("java_functional_lsp.proxy.Path.resolve", return_value=Path("/opt/jdtls/1.57/bin/jdtls")):
|
|
1609
|
+
marker_a = _compute_cache_marker()
|
|
1610
|
+
with patch("java_functional_lsp.proxy.shutil.which", return_value="/opt/jdtls/1.58/bin/jdtls"):
|
|
1611
|
+
with patch("java_functional_lsp.proxy.Path.resolve", return_value=Path("/opt/jdtls/1.58/bin/jdtls")):
|
|
1612
|
+
marker_b = _compute_cache_marker()
|
|
1613
|
+
assert marker_a != marker_b
|
|
1593
1614
|
|
|
1594
1615
|
|
|
1595
1616
|
# Subprocess-based tests — zero mocks, real LSP transport
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/.github/ISSUE_TEMPLATE/bug-report.md
RENAMED
|
File without changes
|
{java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/.github/ISSUE_TEMPLATE/feature-request.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/.github/workflows/release-drafter.yml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/.github/workflows/update-homebrew.yml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/editors/intellij/lsp4ij-template.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/src/java_functional_lsp/__main__.py
RENAMED
|
File without changes
|
|
File without changes
|
{java_functional_lsp-0.9.10 → java_functional_lsp-0.9.11}/src/java_functional_lsp/analyzers/base.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|