java-functional-lsp 0.9.15__tar.gz → 0.9.17__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.15 → java_functional_lsp-0.9.17}/PKG-INFO +1 -1
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/editors/intellij/README.md +1 -1
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/pyproject.toml +1 -1
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/src/java_functional_lsp/__init__.py +1 -1
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/src/java_functional_lsp/cli.py +40 -25
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/tests/test_cli.py +43 -1
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/tests/test_server.py +7 -2
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/.claude-plugin/plugin.json +0 -0
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/.githooks/pre-commit +0 -0
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/.githooks/pre-push +0 -0
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/.github/CODEOWNERS +0 -0
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/.github/ISSUE_TEMPLATE/bug-report.md +0 -0
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/.github/ISSUE_TEMPLATE/feature-request.md +0 -0
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/.github/SECURITY.md +0 -0
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/.github/dependabot.yml +0 -0
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/.github/release-drafter.yml +0 -0
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/.github/workflows/publish.yml +0 -0
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/.github/workflows/release-drafter.yml +0 -0
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/.github/workflows/stale.yml +0 -0
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/.github/workflows/test.yml +0 -0
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/.github/workflows/update-homebrew.yml +0 -0
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/.github/workflows/vscode-ext.yml +0 -0
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/.gitignore +0 -0
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/CONTRIBUTING.md +0 -0
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/LICENSE +0 -0
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/README.md +0 -0
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/SKILL.md +0 -0
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/commands/lint-java.md +0 -0
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/editors/intellij/lsp4ij-template.json +0 -0
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/editors/vscode/.vscodeignore +0 -0
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/editors/vscode/README.md +0 -0
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/editors/vscode/package-lock.json +0 -0
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/editors/vscode/package.json +0 -0
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/editors/vscode/src/extension.ts +0 -0
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/editors/vscode/tsconfig.json +0 -0
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/hooks/hooks.json +0 -0
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/hooks/java_linter_reminder.py +0 -0
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/scripts/ensure-lsp.sh +0 -0
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/scripts/generate-formula.py +0 -0
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/src/java_functional_lsp/__main__.py +0 -0
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/src/java_functional_lsp/analyzers/__init__.py +0 -0
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/src/java_functional_lsp/analyzers/base.py +0 -0
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/src/java_functional_lsp/analyzers/exception_checker.py +0 -0
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/src/java_functional_lsp/analyzers/functional_checker.py +0 -0
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/src/java_functional_lsp/analyzers/mutation_checker.py +0 -0
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/src/java_functional_lsp/analyzers/null_checker.py +0 -0
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/src/java_functional_lsp/analyzers/spring_checker.py +0 -0
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/src/java_functional_lsp/fixes.py +0 -0
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/src/java_functional_lsp/merkle.py +0 -0
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/src/java_functional_lsp/proxy.py +0 -0
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/src/java_functional_lsp/server.py +0 -0
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/tests/__init__.py +0 -0
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/tests/conftest.py +0 -0
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/tests/test_base.py +0 -0
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/tests/test_config.py +0 -0
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/tests/test_e2e.py +0 -0
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/tests/test_e2e_jdtls.py +0 -0
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/tests/test_exception_checker.py +0 -0
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/tests/test_fixes.py +0 -0
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/tests/test_functional_checker.py +0 -0
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/tests/test_merkle.py +0 -0
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/tests/test_merkle_proxy.py +0 -0
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/tests/test_mutation_checker.py +0 -0
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/tests/test_null_checker.py +0 -0
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/tests/test_proxy.py +0 -0
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/tests/test_spring_checker.py +0 -0
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/tests/test_suppress.py +0 -0
- {java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/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.17
|
|
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
|
|
@@ -84,7 +84,7 @@ The server automatically detects JetBrains IDEs and disables the jdtls proxy —
|
|
|
84
84
|
### No diagnostics appear
|
|
85
85
|
- Ensure the file mapping is set to Language: `Java`, Language ID: `java`
|
|
86
86
|
- Check that `.java-functional-lsp.json` doesn't have rules set to `"off"`
|
|
87
|
-
- Try restarting the language server: **
|
|
87
|
+
- Try restarting the language server: **Language Servers** (search it in intellij Actions [Double Shift on keyboard]) → click on java-functional-lsp → **Restart**
|
|
88
88
|
- If diagnostics worked before but stopped, the jdtls proxy may be interfering. Set `JAVA_FUNCTIONAL_LSP_JDTLS=off` in the server command environment to force-disable jdtls. The server auto-detects JetBrains IDEs and disables jdtls by default (since IntelliJ provides native Java support), but this can be overridden with `JAVA_FUNCTIONAL_LSP_JDTLS=on`.
|
|
89
89
|
|
|
90
90
|
### PATH not found
|
|
@@ -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.17"
|
|
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" }
|
|
@@ -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
|
|
@@ -66,14 +67,46 @@ def format_diagnostic(path: Path, d: Diagnostic) -> str:
|
|
|
66
67
|
return f"{path}:{d.line + 1}:{d.col}: [{sym}] {d.code}: {d.message}"
|
|
67
68
|
|
|
68
69
|
|
|
70
|
+
_USAGE = """\
|
|
71
|
+
Usage: java-functional-lsp check <file.java> [file2.java ...]
|
|
72
|
+
java-functional-lsp check --dir <directory>
|
|
73
|
+
java-functional-lsp (start LSP server on stdio)
|
|
74
|
+
java-functional-lsp --version"""
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def _collect_files(args: list[str]) -> list[Path]:
|
|
78
|
+
"""Resolve CLI args to a list of .java paths."""
|
|
79
|
+
files: list[Path] = []
|
|
80
|
+
if args and args[0] == "--dir":
|
|
81
|
+
if len(args) < 2:
|
|
82
|
+
print("Error: --dir requires a directory path", file=sys.stderr)
|
|
83
|
+
sys.exit(1)
|
|
84
|
+
directory = Path(args[1])
|
|
85
|
+
if not directory.is_dir():
|
|
86
|
+
print(f"Error: {directory} is not a directory", file=sys.stderr)
|
|
87
|
+
sys.exit(1)
|
|
88
|
+
return sorted(directory.rglob("*.java"))
|
|
89
|
+
for arg in args:
|
|
90
|
+
p = Path(arg)
|
|
91
|
+
if p.is_file():
|
|
92
|
+
files.append(p)
|
|
93
|
+
elif p.is_dir():
|
|
94
|
+
files.extend(sorted(p.rglob("*.java")))
|
|
95
|
+
else:
|
|
96
|
+
print(f"Warning: {arg} not found, skipping", file=sys.stderr)
|
|
97
|
+
return files
|
|
98
|
+
|
|
99
|
+
|
|
69
100
|
def main() -> None:
|
|
70
101
|
"""CLI entry point: java-functional-lsp check <files...>"""
|
|
71
102
|
args = sys.argv[1:]
|
|
72
103
|
|
|
73
104
|
if args and args[0] in ("-h", "--help"):
|
|
74
|
-
print(
|
|
75
|
-
|
|
76
|
-
|
|
105
|
+
print(_USAGE)
|
|
106
|
+
sys.exit(0)
|
|
107
|
+
|
|
108
|
+
if args and args[0] in ("-v", "--version"):
|
|
109
|
+
print(f"java-functional-lsp {__version__}")
|
|
77
110
|
sys.exit(0)
|
|
78
111
|
|
|
79
112
|
if not args or args[0] != "check":
|
|
@@ -85,34 +118,16 @@ def main() -> None:
|
|
|
85
118
|
|
|
86
119
|
args = args[1:] # skip "check"
|
|
87
120
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
if len(args) < 2:
|
|
92
|
-
print("Error: --dir requires a directory path", file=sys.stderr)
|
|
93
|
-
sys.exit(1)
|
|
94
|
-
directory = Path(args[1])
|
|
95
|
-
if not directory.is_dir():
|
|
96
|
-
print(f"Error: {directory} is not a directory", file=sys.stderr)
|
|
97
|
-
sys.exit(1)
|
|
98
|
-
files = sorted(directory.rglob("*.java"))
|
|
99
|
-
else:
|
|
100
|
-
for arg in args:
|
|
101
|
-
p = Path(arg)
|
|
102
|
-
if p.is_file():
|
|
103
|
-
files.append(p)
|
|
104
|
-
elif p.is_dir():
|
|
105
|
-
files.extend(sorted(p.rglob("*.java")))
|
|
106
|
-
else:
|
|
107
|
-
print(f"Warning: {arg} not found, skipping", file=sys.stderr)
|
|
121
|
+
if args and args[0] in ("-h", "--help"):
|
|
122
|
+
print(_USAGE)
|
|
123
|
+
sys.exit(0)
|
|
108
124
|
|
|
125
|
+
files = _collect_files(args)
|
|
109
126
|
if not files:
|
|
110
127
|
print("No .java files found", file=sys.stderr)
|
|
111
128
|
sys.exit(1)
|
|
112
129
|
|
|
113
|
-
# Load config from first file's directory
|
|
114
130
|
config = load_config(files[0])
|
|
115
|
-
|
|
116
131
|
total_diags = 0
|
|
117
132
|
excludes: list[str] = config.get("excludes", [])
|
|
118
133
|
for path in files:
|
|
@@ -4,8 +4,11 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
from pathlib import Path
|
|
6
6
|
from typing import Any
|
|
7
|
+
from unittest.mock import patch
|
|
7
8
|
|
|
8
|
-
|
|
9
|
+
import pytest
|
|
10
|
+
|
|
11
|
+
from java_functional_lsp.cli import check_file, format_diagnostic, load_config, main
|
|
9
12
|
|
|
10
13
|
|
|
11
14
|
class TestCheckFile:
|
|
@@ -53,3 +56,42 @@ class TestLoadConfig:
|
|
|
53
56
|
def test_missing_config(self, tmp_path: Path) -> None:
|
|
54
57
|
config = load_config(tmp_path / "Test.java")
|
|
55
58
|
assert config == {}
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class TestHelp:
|
|
62
|
+
def test_top_level_help(self, capsys: pytest.CaptureFixture[str]) -> None:
|
|
63
|
+
with patch("sys.argv", ["java-functional-lsp", "--help"]):
|
|
64
|
+
with pytest.raises(SystemExit) as exc:
|
|
65
|
+
main()
|
|
66
|
+
assert exc.value.code == 0
|
|
67
|
+
assert "check" in capsys.readouterr().out
|
|
68
|
+
|
|
69
|
+
def test_check_subcommand_help(self, capsys: pytest.CaptureFixture[str]) -> None:
|
|
70
|
+
with patch("sys.argv", ["java-functional-lsp", "check", "--help"]):
|
|
71
|
+
with pytest.raises(SystemExit) as exc:
|
|
72
|
+
main()
|
|
73
|
+
assert exc.value.code == 0
|
|
74
|
+
assert "check" in capsys.readouterr().out
|
|
75
|
+
|
|
76
|
+
def test_check_short_help(self, capsys: pytest.CaptureFixture[str]) -> None:
|
|
77
|
+
with patch("sys.argv", ["java-functional-lsp", "check", "-h"]):
|
|
78
|
+
with pytest.raises(SystemExit) as exc:
|
|
79
|
+
main()
|
|
80
|
+
assert exc.value.code == 0
|
|
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
|
|
@@ -109,12 +109,17 @@ async def lsp_client(tmp_path: Any) -> LanguageClient: # type: ignore[misc]
|
|
|
109
109
|
try:
|
|
110
110
|
yield client
|
|
111
111
|
finally:
|
|
112
|
+
# Teardown with timeouts: the server subprocess may be mid-jdtls-startup
|
|
113
|
+
# on a slow CI runner, causing shutdown_async or stop to hang indefinitely.
|
|
112
114
|
try:
|
|
113
|
-
await client.shutdown_async(None)
|
|
115
|
+
await asyncio.wait_for(client.shutdown_async(None), timeout=5.0)
|
|
114
116
|
client.exit(None)
|
|
115
117
|
except Exception:
|
|
116
118
|
pass
|
|
117
|
-
|
|
119
|
+
try:
|
|
120
|
+
await asyncio.wait_for(client.stop(), timeout=5.0)
|
|
121
|
+
except Exception:
|
|
122
|
+
pass
|
|
118
123
|
|
|
119
124
|
|
|
120
125
|
async def _open_and_wait_for_diagnostics(
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/.github/ISSUE_TEMPLATE/bug-report.md
RENAMED
|
File without changes
|
{java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/.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.15 → java_functional_lsp-0.9.17}/.github/workflows/release-drafter.yml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/.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
|
{java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/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.15 → java_functional_lsp-0.9.17}/src/java_functional_lsp/__main__.py
RENAMED
|
File without changes
|
|
File without changes
|
{java_functional_lsp-0.9.15 → java_functional_lsp-0.9.17}/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
|