java-functional-lsp 0.9.3__tar.gz → 0.9.4__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.3 → java_functional_lsp-0.9.4}/PKG-INFO +1 -1
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/pyproject.toml +1 -1
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/src/java_functional_lsp/__init__.py +1 -1
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/src/java_functional_lsp/proxy.py +22 -14
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/tests/test_proxy.py +39 -17
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/.claude-plugin/plugin.json +0 -0
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/.githooks/pre-commit +0 -0
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/.githooks/pre-push +0 -0
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/.github/CODEOWNERS +0 -0
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/.github/ISSUE_TEMPLATE/bug-report.md +0 -0
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/.github/ISSUE_TEMPLATE/feature-request.md +0 -0
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/.github/SECURITY.md +0 -0
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/.github/dependabot.yml +0 -0
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/.github/release-drafter.yml +0 -0
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/.github/workflows/publish.yml +0 -0
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/.github/workflows/release-drafter.yml +0 -0
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/.github/workflows/stale.yml +0 -0
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/.github/workflows/test.yml +0 -0
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/.github/workflows/update-homebrew.yml +0 -0
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/.github/workflows/vscode-ext.yml +0 -0
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/.gitignore +0 -0
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/CONTRIBUTING.md +0 -0
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/LICENSE +0 -0
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/README.md +0 -0
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/SKILL.md +0 -0
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/commands/lint-java.md +0 -0
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/editors/intellij/README.md +0 -0
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/editors/intellij/lsp4ij-template.json +0 -0
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/editors/vscode/.vscodeignore +0 -0
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/editors/vscode/README.md +0 -0
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/editors/vscode/package-lock.json +0 -0
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/editors/vscode/package.json +0 -0
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/editors/vscode/src/extension.ts +0 -0
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/editors/vscode/tsconfig.json +0 -0
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/hooks/hooks.json +0 -0
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/hooks/java_linter_reminder.py +0 -0
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/scripts/ensure-lsp.sh +0 -0
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/scripts/generate-formula.py +0 -0
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/src/java_functional_lsp/__main__.py +0 -0
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/src/java_functional_lsp/analyzers/__init__.py +0 -0
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/src/java_functional_lsp/analyzers/base.py +0 -0
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/src/java_functional_lsp/analyzers/exception_checker.py +0 -0
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/src/java_functional_lsp/analyzers/functional_checker.py +0 -0
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/src/java_functional_lsp/analyzers/mutation_checker.py +0 -0
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/src/java_functional_lsp/analyzers/null_checker.py +0 -0
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/src/java_functional_lsp/analyzers/spring_checker.py +0 -0
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/src/java_functional_lsp/cli.py +0 -0
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/src/java_functional_lsp/fixes.py +0 -0
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/src/java_functional_lsp/merkle.py +0 -0
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/src/java_functional_lsp/server.py +0 -0
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/tests/__init__.py +0 -0
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/tests/conftest.py +0 -0
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/tests/test_base.py +0 -0
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/tests/test_cli.py +0 -0
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/tests/test_config.py +0 -0
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/tests/test_e2e.py +0 -0
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/tests/test_e2e_jdtls.py +0 -0
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/tests/test_exception_checker.py +0 -0
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/tests/test_fixes.py +0 -0
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/tests/test_functional_checker.py +0 -0
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/tests/test_merkle.py +0 -0
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/tests/test_merkle_proxy.py +0 -0
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/tests/test_mutation_checker.py +0 -0
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/tests/test_null_checker.py +0 -0
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/tests/test_server.py +0 -0
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/tests/test_spring_checker.py +0 -0
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/tests/test_suppress.py +0 -0
- {java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/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.4
|
|
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.4"
|
|
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" }
|
|
@@ -448,12 +448,12 @@ def _version_key(name: str) -> tuple[int, ...]:
|
|
|
448
448
|
def _find_maven_group_root(initial_module: Path, workspace_root: Path) -> Path:
|
|
449
449
|
"""Return the tightest Maven multi-module parent of *initial_module*.
|
|
450
450
|
|
|
451
|
-
Walks up from ``initial_module.parent`` (
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
``workspace_root``
|
|
456
|
-
|
|
451
|
+
Walks up from ``initial_module.parent`` toward (but NOT including)
|
|
452
|
+
``workspace_root``, returning the first ancestor whose ``pom.xml``
|
|
453
|
+
contains a ``<modules>`` section. Falls back to ``initial_module``
|
|
454
|
+
itself when no intermediate group pom exists (e.g. modules that sit
|
|
455
|
+
directly under ``workspace_root``), keeping the scope as tight as
|
|
456
|
+
possible and avoiding accidental full-monorepo indexing.
|
|
457
457
|
|
|
458
458
|
This keeps the jdtls index bounded to a module *group* (typically
|
|
459
459
|
5-20 modules) rather than the full IDE workspace (potentially 200+ modules)
|
|
@@ -463,11 +463,17 @@ def _find_maven_group_root(initial_module: Path, workspace_root: Path) -> Path:
|
|
|
463
463
|
before walking to avoid symlink-based boundary escapes.
|
|
464
464
|
"""
|
|
465
465
|
workspace_root = workspace_root.resolve()
|
|
466
|
-
|
|
467
|
-
|
|
466
|
+
resolved_module = initial_module.resolve()
|
|
467
|
+
current = resolved_module.parent
|
|
468
|
+
# Case 1: module is outside the workspace entirely — scope to workspace_root
|
|
469
|
+
# (also fires when initial_module == workspace_root, since parent is then
|
|
470
|
+
# outside workspace_root).
|
|
468
471
|
if not current.is_relative_to(workspace_root):
|
|
469
472
|
return workspace_root
|
|
470
|
-
|
|
473
|
+
# Walk up to (but NOT including) workspace_root. Inspecting workspace_root's
|
|
474
|
+
# own pom.xml would include the entire monorepo (e.g. 200+ modules) → OOM.
|
|
475
|
+
# `current.parent == current` detects the filesystem root (POSIX `/` or Windows drive).
|
|
476
|
+
while current not in (workspace_root, current.parent):
|
|
471
477
|
pom = current / "pom.xml"
|
|
472
478
|
if pom.is_file():
|
|
473
479
|
try:
|
|
@@ -475,10 +481,10 @@ def _find_maven_group_root(initial_module: Path, workspace_root: Path) -> Path:
|
|
|
475
481
|
return current
|
|
476
482
|
except OSError:
|
|
477
483
|
pass
|
|
478
|
-
if current in (workspace_root, current.parent):
|
|
479
|
-
break
|
|
480
484
|
current = current.parent
|
|
481
|
-
|
|
485
|
+
# Case 2: no intermediate group pom found — use the initial module as its own scope
|
|
486
|
+
# (tightest possible; avoids full-monorepo indexing for flat modules under workspace_root).
|
|
487
|
+
return resolved_module
|
|
482
488
|
|
|
483
489
|
|
|
484
490
|
@lru_cache(maxsize=256)
|
|
@@ -924,8 +930,10 @@ class JdtlsProxy:
|
|
|
924
930
|
Maven parent. This covers sibling modules (the common case for
|
|
925
931
|
cross-module navigation) without ballooning the index.
|
|
926
932
|
|
|
927
|
-
Falls back to the
|
|
928
|
-
multi-module parent is found.
|
|
933
|
+
Falls back to the initial module itself when no intermediate
|
|
934
|
+
multi-module parent is found (e.g. flat modules sitting directly
|
|
935
|
+
under the workspace root), keeping the jdtls scope as tight as
|
|
936
|
+
possible.
|
|
929
937
|
|
|
930
938
|
Removes all individually-added module folders to avoid double-indexing
|
|
931
939
|
with the newly added group root.
|
|
@@ -1131,17 +1131,24 @@ class TestLazyStart:
|
|
|
1131
1131
|
assert event["added"][0]["uri"] == group.as_uri()
|
|
1132
1132
|
assert event["added"][0]["uri"] != workspace_uri
|
|
1133
1133
|
|
|
1134
|
-
async def
|
|
1135
|
-
"""
|
|
1134
|
+
async def test_expand_noop_for_flat_module_directly_under_workspace(self, tmp_path: Path) -> None:
|
|
1135
|
+
"""No notification sent for flat modules sitting directly under workspace_root.
|
|
1136
|
+
|
|
1137
|
+
When there is no intermediate group pom between the module and workspace_root,
|
|
1138
|
+
_find_maven_group_root returns the module itself (not workspace_root). Since the
|
|
1139
|
+
module was already added, expand_full_workspace() is a no-op — which is correct:
|
|
1140
|
+
the scope is already as tight as possible and workspace_root's pom.xml
|
|
1141
|
+
(potentially 200+ modules → OOM) is never inspected.
|
|
1142
|
+
"""
|
|
1136
1143
|
from unittest.mock import AsyncMock
|
|
1137
1144
|
|
|
1138
1145
|
from java_functional_lsp.proxy import JdtlsProxy
|
|
1139
1146
|
|
|
1140
|
-
# Flat layout: workspace/module — no intermediate pom.xml
|
|
1147
|
+
# Flat layout: workspace/module — no intermediate pom.xml between module and workspace
|
|
1141
1148
|
workspace = tmp_path / "workspace"
|
|
1142
1149
|
module = workspace / "module"
|
|
1143
1150
|
module.mkdir(parents=True)
|
|
1144
|
-
# workspace/pom.xml has <modules>, but
|
|
1151
|
+
# workspace/pom.xml has <modules>, but the walk stops BEFORE reaching it
|
|
1145
1152
|
(workspace / "pom.xml").write_text("<project><modules><module>module</module></modules></project>")
|
|
1146
1153
|
|
|
1147
1154
|
module_uri = module.as_uri()
|
|
@@ -1155,9 +1162,9 @@ class TestLazyStart:
|
|
|
1155
1162
|
proxy.send_notification = AsyncMock() # type: ignore[assignment]
|
|
1156
1163
|
await proxy.expand_full_workspace()
|
|
1157
1164
|
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
assert
|
|
1165
|
+
# No notification — module was already added and is already the tightest scope
|
|
1166
|
+
proxy.send_notification.assert_not_called() # type: ignore[attr-defined]
|
|
1167
|
+
assert proxy._workspace_expanded is True
|
|
1161
1168
|
|
|
1162
1169
|
async def test_expand_full_workspace_sends_notification(self) -> None:
|
|
1163
1170
|
from unittest.mock import AsyncMock
|
|
@@ -1172,28 +1179,43 @@ class TestLazyStart:
|
|
|
1172
1179
|
proxy.send_notification.assert_called_once() # type: ignore[attr-defined]
|
|
1173
1180
|
assert proxy._workspace_expanded is True
|
|
1174
1181
|
|
|
1175
|
-
async def test_expand_full_workspace_removes_initial_module(self) -> None:
|
|
1176
|
-
"""All modules in _states
|
|
1182
|
+
async def test_expand_full_workspace_removes_initial_module(self, tmp_path: Path) -> None:
|
|
1183
|
+
"""All modules in _states are removed when expanding to an intermediate group root."""
|
|
1177
1184
|
from unittest.mock import AsyncMock
|
|
1178
1185
|
|
|
1179
1186
|
from java_functional_lsp.proxy import JdtlsProxy
|
|
1180
1187
|
|
|
1188
|
+
# Layout: monorepo/group/module-a, monorepo/group/module-b
|
|
1189
|
+
# group/pom.xml has <modules> → group becomes the expansion target
|
|
1190
|
+
monorepo = tmp_path / "monorepo"
|
|
1191
|
+
group = monorepo / "group"
|
|
1192
|
+
module_a = group / "module-a"
|
|
1193
|
+
module_b = group / "module-b"
|
|
1194
|
+
for d in (module_a, module_b):
|
|
1195
|
+
d.mkdir(parents=True)
|
|
1196
|
+
(group / "pom.xml").write_text("<project><modules><module>module-a</module></modules></project>")
|
|
1197
|
+
|
|
1198
|
+
module_a_uri = module_a.as_uri()
|
|
1199
|
+
module_b_uri = module_b.as_uri()
|
|
1200
|
+
monorepo_uri = monorepo.as_uri()
|
|
1201
|
+
group_uri = group.as_uri()
|
|
1202
|
+
|
|
1181
1203
|
proxy = JdtlsProxy()
|
|
1182
1204
|
proxy._available = True
|
|
1183
|
-
proxy._original_root_uri =
|
|
1184
|
-
proxy._initial_module_uri =
|
|
1185
|
-
# Simulate
|
|
1186
|
-
proxy.modules.mark_added(
|
|
1187
|
-
proxy.modules.mark_added(
|
|
1205
|
+
proxy._original_root_uri = monorepo_uri
|
|
1206
|
+
proxy._initial_module_uri = module_a_uri
|
|
1207
|
+
# Simulate module-a added during start() and module-b via add_module_if_new
|
|
1208
|
+
proxy.modules.mark_added(module_a_uri)
|
|
1209
|
+
proxy.modules.mark_added(module_b_uri)
|
|
1188
1210
|
proxy.send_notification = AsyncMock() # type: ignore[assignment]
|
|
1189
1211
|
await proxy.expand_full_workspace()
|
|
1190
1212
|
proxy.send_notification.assert_called_once() # type: ignore[attr-defined]
|
|
1191
1213
|
call_args = proxy.send_notification.call_args[0] # type: ignore[attr-defined]
|
|
1192
1214
|
event = call_args[1]["event"]
|
|
1193
1215
|
removed_uris = {e["uri"] for e in event["removed"]}
|
|
1194
|
-
assert
|
|
1195
|
-
assert
|
|
1196
|
-
assert event["added"][0]["uri"] ==
|
|
1216
|
+
assert module_a_uri in removed_uris
|
|
1217
|
+
assert module_b_uri in removed_uris
|
|
1218
|
+
assert event["added"][0]["uri"] == group_uri
|
|
1197
1219
|
|
|
1198
1220
|
async def test_expand_full_workspace_noop_when_not_available(self) -> None:
|
|
1199
1221
|
from unittest.mock import AsyncMock
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/.github/ISSUE_TEMPLATE/bug-report.md
RENAMED
|
File without changes
|
{java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/.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.3 → java_functional_lsp-0.9.4}/.github/workflows/release-drafter.yml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/.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.3 → java_functional_lsp-0.9.4}/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
|
|
File without changes
|
|
File without changes
|
{java_functional_lsp-0.9.3 → java_functional_lsp-0.9.4}/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
|
|
File without changes
|