java-functional-lsp 0.1.0__tar.gz → 0.3.0__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 (56) hide show
  1. java_functional_lsp-0.3.0/.claude-plugin/plugin.json +5 -0
  2. {java_functional_lsp-0.1.0 → java_functional_lsp-0.3.0}/.github/workflows/release-drafter.yml +2 -4
  3. java_functional_lsp-0.3.0/.github/workflows/update-homebrew.yml +61 -0
  4. java_functional_lsp-0.3.0/.github/workflows/vscode-ext.yml +48 -0
  5. {java_functional_lsp-0.1.0 → java_functional_lsp-0.3.0}/.gitignore +4 -0
  6. {java_functional_lsp-0.1.0 → java_functional_lsp-0.3.0}/PKG-INFO +50 -8
  7. {java_functional_lsp-0.1.0 → java_functional_lsp-0.3.0}/README.md +49 -7
  8. java_functional_lsp-0.3.0/SKILL.md +77 -0
  9. java_functional_lsp-0.3.0/commands/lint-java.md +40 -0
  10. java_functional_lsp-0.3.0/editors/intellij/README.md +90 -0
  11. java_functional_lsp-0.3.0/editors/intellij/lsp4ij-template.json +10 -0
  12. java_functional_lsp-0.3.0/editors/vscode/.vscodeignore +6 -0
  13. java_functional_lsp-0.3.0/editors/vscode/README.md +60 -0
  14. java_functional_lsp-0.3.0/editors/vscode/package-lock.json +4080 -0
  15. java_functional_lsp-0.3.0/editors/vscode/package.json +66 -0
  16. java_functional_lsp-0.3.0/editors/vscode/src/extension.ts +64 -0
  17. java_functional_lsp-0.3.0/editors/vscode/tsconfig.json +17 -0
  18. java_functional_lsp-0.3.0/hooks/hooks.json +28 -0
  19. java_functional_lsp-0.3.0/hooks/java_linter_reminder.py +36 -0
  20. {java_functional_lsp-0.1.0 → java_functional_lsp-0.3.0}/pyproject.toml +6 -3
  21. java_functional_lsp-0.3.0/scripts/ensure-lsp.sh +18 -0
  22. java_functional_lsp-0.3.0/scripts/generate-formula.py +64 -0
  23. {java_functional_lsp-0.1.0 → java_functional_lsp-0.3.0}/src/java_functional_lsp/__init__.py +1 -1
  24. java_functional_lsp-0.3.0/src/java_functional_lsp/analyzers/__init__.py +1 -0
  25. {java_functional_lsp-0.1.0 → java_functional_lsp-0.3.0}/src/java_functional_lsp/analyzers/base.py +1 -1
  26. java_functional_lsp-0.3.0/src/java_functional_lsp/cli.py +121 -0
  27. java_functional_lsp-0.3.0/src/java_functional_lsp/proxy.py +235 -0
  28. java_functional_lsp-0.3.0/src/java_functional_lsp/server.py +324 -0
  29. java_functional_lsp-0.3.0/tests/test_cli.py +55 -0
  30. java_functional_lsp-0.3.0/tests/test_proxy.py +248 -0
  31. {java_functional_lsp-0.1.0 → java_functional_lsp-0.3.0}/uv.lock +26 -1
  32. java_functional_lsp-0.1.0/src/java_functional_lsp/analyzers/__init__.py +0 -1
  33. java_functional_lsp-0.1.0/src/java_functional_lsp/server.py +0 -145
  34. {java_functional_lsp-0.1.0 → java_functional_lsp-0.3.0}/.github/CODEOWNERS +0 -0
  35. {java_functional_lsp-0.1.0 → java_functional_lsp-0.3.0}/.github/ISSUE_TEMPLATE/bug-report.md +0 -0
  36. {java_functional_lsp-0.1.0 → java_functional_lsp-0.3.0}/.github/ISSUE_TEMPLATE/feature-request.md +0 -0
  37. {java_functional_lsp-0.1.0 → java_functional_lsp-0.3.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  38. {java_functional_lsp-0.1.0 → java_functional_lsp-0.3.0}/.github/SECURITY.md +0 -0
  39. {java_functional_lsp-0.1.0 → java_functional_lsp-0.3.0}/.github/dependabot.yml +0 -0
  40. {java_functional_lsp-0.1.0 → java_functional_lsp-0.3.0}/.github/release-drafter.yml +0 -0
  41. {java_functional_lsp-0.1.0 → java_functional_lsp-0.3.0}/.github/workflows/publish.yml +0 -0
  42. {java_functional_lsp-0.1.0 → java_functional_lsp-0.3.0}/.github/workflows/stale.yml +0 -0
  43. {java_functional_lsp-0.1.0 → java_functional_lsp-0.3.0}/.github/workflows/test.yml +0 -0
  44. {java_functional_lsp-0.1.0 → java_functional_lsp-0.3.0}/CONTRIBUTING.md +0 -0
  45. {java_functional_lsp-0.1.0 → java_functional_lsp-0.3.0}/LICENSE +0 -0
  46. {java_functional_lsp-0.1.0 → java_functional_lsp-0.3.0}/src/java_functional_lsp/analyzers/exception_checker.py +0 -0
  47. {java_functional_lsp-0.1.0 → java_functional_lsp-0.3.0}/src/java_functional_lsp/analyzers/mutation_checker.py +0 -0
  48. {java_functional_lsp-0.1.0 → java_functional_lsp-0.3.0}/src/java_functional_lsp/analyzers/null_checker.py +0 -0
  49. {java_functional_lsp-0.1.0 → java_functional_lsp-0.3.0}/src/java_functional_lsp/analyzers/spring_checker.py +0 -0
  50. {java_functional_lsp-0.1.0 → java_functional_lsp-0.3.0}/tests/__init__.py +0 -0
  51. {java_functional_lsp-0.1.0 → java_functional_lsp-0.3.0}/tests/conftest.py +0 -0
  52. {java_functional_lsp-0.1.0 → java_functional_lsp-0.3.0}/tests/test_config.py +0 -0
  53. {java_functional_lsp-0.1.0 → java_functional_lsp-0.3.0}/tests/test_exception_checker.py +0 -0
  54. {java_functional_lsp-0.1.0 → java_functional_lsp-0.3.0}/tests/test_mutation_checker.py +0 -0
  55. {java_functional_lsp-0.1.0 → java_functional_lsp-0.3.0}/tests/test_null_checker.py +0 -0
  56. {java_functional_lsp-0.1.0 → java_functional_lsp-0.3.0}/tests/test_spring_checker.py +0 -0
@@ -0,0 +1,5 @@
1
+ {
2
+ "name": "java-functional-lsp",
3
+ "description": "Java LSP with functional programming rules enforcement — null safety, immutability, no exceptions, Spring best practices. Wraps jdtls for full Java language support.",
4
+ "version": "0.3.0"
5
+ }
@@ -3,17 +3,15 @@ name: Release Drafter
3
3
  on:
4
4
  push:
5
5
  branches: [main]
6
- pull_request:
7
- types: [opened, reopened, synchronize]
8
6
 
9
7
  permissions:
10
- contents: read
8
+ contents: write
11
9
  pull-requests: write
12
10
 
13
11
  jobs:
14
12
  update-release-draft:
15
13
  runs-on: ubuntu-latest
16
14
  steps:
17
- - uses: release-drafter/release-drafter@v6
15
+ - uses: release-drafter/release-drafter@v7
18
16
  env:
19
17
  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -0,0 +1,61 @@
1
+ name: Update Homebrew Formula
2
+
3
+ on:
4
+ workflow_run:
5
+ workflows: ["Publish to PyPI"]
6
+ types: [completed]
7
+ workflow_dispatch:
8
+
9
+ jobs:
10
+ update-formula:
11
+ runs-on: ubuntu-latest
12
+ if: ${{ github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success' }}
13
+ steps:
14
+ - uses: actions/checkout@v6
15
+ - name: Get release version
16
+ id: version
17
+ env:
18
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
19
+ run: |
20
+ VERSION=$(gh api "repos/${{ github.repository }}/releases/latest" --jq .tag_name)
21
+ echo "version=${VERSION#v}" >> "$GITHUB_OUTPUT"
22
+ - name: Set up Python
23
+ uses: actions/setup-python@v6
24
+ with:
25
+ python-version: "3.12"
26
+ - name: Wait for PyPI availability
27
+ env:
28
+ PKG_VERSION: ${{ steps.version.outputs.version }}
29
+ run: |
30
+ for i in $(seq 1 30); do
31
+ if pip index versions java-functional-lsp 2>/dev/null | grep -q "$PKG_VERSION"; then
32
+ echo "java-functional-lsp==$PKG_VERSION available on PyPI"
33
+ break
34
+ fi
35
+ echo "Waiting for PyPI... attempt $i/30"
36
+ sleep 20
37
+ done
38
+ - name: Generate formula
39
+ env:
40
+ PKG_VERSION: ${{ steps.version.outputs.version }}
41
+ run: |
42
+ python3 scripts/generate-formula.py "$PKG_VERSION" > java-functional-lsp.rb
43
+ echo "Generated formula:"
44
+ cat java-functional-lsp.rb
45
+ - name: Checkout tap repo
46
+ uses: actions/checkout@v6
47
+ with:
48
+ repository: aviadshiber/homebrew-tap
49
+ token: ${{ secrets.TAP_GITHUB_TOKEN }}
50
+ path: homebrew-tap
51
+ - name: Update formula
52
+ env:
53
+ PKG_VERSION: ${{ steps.version.outputs.version }}
54
+ run: |
55
+ cp java-functional-lsp.rb homebrew-tap/Formula/java-functional-lsp.rb
56
+ cd homebrew-tap
57
+ git config user.name "github-actions[bot]"
58
+ git config user.email "github-actions[bot]@users.noreply.github.com"
59
+ git add Formula/java-functional-lsp.rb
60
+ git diff --cached --quiet || git commit -m "Update java-functional-lsp to $PKG_VERSION"
61
+ git push
@@ -0,0 +1,48 @@
1
+ name: VS Code Extension
2
+
3
+ on:
4
+ push:
5
+ paths:
6
+ - "editors/vscode/**"
7
+ branches: [main]
8
+ release:
9
+ types: [published]
10
+
11
+ permissions:
12
+ contents: write
13
+
14
+ jobs:
15
+ build:
16
+ runs-on: ubuntu-latest
17
+ defaults:
18
+ run:
19
+ working-directory: editors/vscode
20
+ steps:
21
+ - uses: actions/checkout@v6
22
+
23
+ - name: Set up Node.js
24
+ uses: actions/setup-node@v4
25
+ with:
26
+ node-version: "20"
27
+
28
+ - name: Install dependencies
29
+ run: npm install
30
+
31
+ - name: Compile
32
+ run: npm run compile
33
+
34
+ - name: Package VSIX
35
+ run: npx vsce package --no-dependencies
36
+
37
+ - name: Upload VSIX artifact
38
+ uses: actions/upload-artifact@v4
39
+ with:
40
+ name: java-functional-lsp-vsix
41
+ path: editors/vscode/*.vsix
42
+
43
+ - name: Attach VSIX to release
44
+ if: github.event_name == 'release'
45
+ env:
46
+ GH_TOKEN: ${{ github.token }}
47
+ RELEASE_TAG: ${{ github.event.release.tag_name }}
48
+ run: gh release upload "$RELEASE_TAG" *.vsix
@@ -14,5 +14,9 @@ htmlcov/
14
14
  .coverage
15
15
  *.egg
16
16
  *.zip
17
+ # VS Code extension
18
+ editors/vscode/node_modules/
19
+ editors/vscode/out/
20
+ *.vsix
17
21
  # Claude Code
18
22
  .claude/
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: java-functional-lsp
3
- Version: 0.1.0
3
+ Version: 0.3.0
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
@@ -29,8 +29,8 @@ Description-Content-Type: text/markdown
29
29
  # java-functional-lsp
30
30
 
31
31
  [![CI](https://github.com/aviadshiber/java-functional-lsp/actions/workflows/test.yml/badge.svg)](https://github.com/aviadshiber/java-functional-lsp/actions/workflows/test.yml)
32
- [![PyPI version](https://img.shields.io/pypi/v/java-functional-lsp)](https://pypi.org/project/java-functional-lsp/)
33
- [![Python](https://img.shields.io/pypi/pyversions/java-functional-lsp)](https://pypi.org/project/java-functional-lsp/)
32
+ [![PyPI version](https://img.shields.io/pypi/v/java-functional-lsp?v=1)](https://pypi.org/project/java-functional-lsp/)
33
+ [![Python](https://img.shields.io/pypi/pyversions/java-functional-lsp?v=1)](https://pypi.org/project/java-functional-lsp/)
34
34
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
35
35
 
36
36
  A Java Language Server that enforces functional programming best practices. Designed for teams using **Vavr**, **Lombok**, and **Spring** with a functional-first approach.
@@ -55,18 +55,50 @@ A Java Language Server that enforces functional programming best practices. Desi
55
55
  ## Install
56
56
 
57
57
  ```bash
58
+ # Homebrew
59
+ brew install aviadshiber/tap/java-functional-lsp
60
+
61
+ # pip
58
62
  pip install java-functional-lsp
63
+
64
+ # From source
65
+ pip install git+https://github.com/aviadshiber/java-functional-lsp.git
59
66
  ```
60
67
 
61
- Or from source:
68
+ ## IDE Setup
69
+
70
+ ### VS Code
71
+
72
+ Install the extension from a `.vsix` file ([download from releases](https://github.com/aviadshiber/java-functional-lsp/releases)) or build it:
62
73
 
63
74
  ```bash
64
- pip install git+https://github.com/aviadshiber/java-functional-lsp.git
75
+ cd editors/vscode
76
+ npm install && npm run compile
77
+ npx vsce package
78
+ code --install-extension java-functional-lsp-*.vsix
65
79
  ```
66
80
 
67
- ## Usage with Claude Code
81
+ The extension launches the LSP server automatically for `.java` files. Configure the binary path in settings if needed (`javaFunctionalLsp.serverPath`). See [editors/vscode/README.md](editors/vscode/README.md) for details.
82
+
83
+ ### IntelliJ IDEA
84
+
85
+ Use the [LSP4IJ](https://github.com/redhat-developer/lsp4ij) plugin (works on Community & Ultimate):
86
+
87
+ 1. Install **LSP4IJ** from the JetBrains Marketplace
88
+ 2. **Settings** → **Languages & Frameworks** → **Language Servers** → **`+`**
89
+ 3. Set **Command**: `java-functional-lsp`, then in **Mappings** → **File name patterns** add `*.java` with Language Id `java`
68
90
 
69
- Install the `deeperdive-java-linter` plugin from the DeeperDive marketplace, which registers this server as a Java LSP.
91
+ See [editors/intellij/README.md](editors/intellij/README.md) for detailed instructions.
92
+
93
+ ### Claude Code
94
+
95
+ Install as a plugin directly from GitHub:
96
+
97
+ ```bash
98
+ claude plugin add https://github.com/aviadshiber/java-functional-lsp.git
99
+ ```
100
+
101
+ This registers the LSP server, adds auto-install hooks, and provides the `/lint-java` command.
70
102
 
71
103
  Or manually add to your Claude Code config:
72
104
 
@@ -81,9 +113,19 @@ Or manually add to your Claude Code config:
81
113
  }
82
114
  ```
83
115
 
116
+ ### Other Editors
117
+
118
+ Any LSP client that supports stdio transport can use this server. Point it to the `java-functional-lsp` command for `java` files.
119
+
120
+ | Editor | Config |
121
+ |--------|--------|
122
+ | **Neovim** | `vim.lsp.start({ cmd = {"java-functional-lsp"}, filetypes = {"java"} })` |
123
+ | **Emacs (eglot)** | `(add-to-list 'eglot-server-programs '(java-mode "java-functional-lsp"))` |
124
+ | **Sublime Text** | LSP package → add server with `"command": ["java-functional-lsp"]` |
125
+
84
126
  ## Configuration
85
127
 
86
- Create `.deeperdive-linter.json` in your project root to customize rules:
128
+ Create `.java-functional-lsp.json` in your project root to customize rules:
87
129
 
88
130
  ```json
89
131
  {
@@ -1,8 +1,8 @@
1
1
  # java-functional-lsp
2
2
 
3
3
  [![CI](https://github.com/aviadshiber/java-functional-lsp/actions/workflows/test.yml/badge.svg)](https://github.com/aviadshiber/java-functional-lsp/actions/workflows/test.yml)
4
- [![PyPI version](https://img.shields.io/pypi/v/java-functional-lsp)](https://pypi.org/project/java-functional-lsp/)
5
- [![Python](https://img.shields.io/pypi/pyversions/java-functional-lsp)](https://pypi.org/project/java-functional-lsp/)
4
+ [![PyPI version](https://img.shields.io/pypi/v/java-functional-lsp?v=1)](https://pypi.org/project/java-functional-lsp/)
5
+ [![Python](https://img.shields.io/pypi/pyversions/java-functional-lsp?v=1)](https://pypi.org/project/java-functional-lsp/)
6
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
7
 
8
8
  A Java Language Server that enforces functional programming best practices. Designed for teams using **Vavr**, **Lombok**, and **Spring** with a functional-first approach.
@@ -27,18 +27,50 @@ A Java Language Server that enforces functional programming best practices. Desi
27
27
  ## Install
28
28
 
29
29
  ```bash
30
+ # Homebrew
31
+ brew install aviadshiber/tap/java-functional-lsp
32
+
33
+ # pip
30
34
  pip install java-functional-lsp
35
+
36
+ # From source
37
+ pip install git+https://github.com/aviadshiber/java-functional-lsp.git
31
38
  ```
32
39
 
33
- Or from source:
40
+ ## IDE Setup
41
+
42
+ ### VS Code
43
+
44
+ Install the extension from a `.vsix` file ([download from releases](https://github.com/aviadshiber/java-functional-lsp/releases)) or build it:
34
45
 
35
46
  ```bash
36
- pip install git+https://github.com/aviadshiber/java-functional-lsp.git
47
+ cd editors/vscode
48
+ npm install && npm run compile
49
+ npx vsce package
50
+ code --install-extension java-functional-lsp-*.vsix
37
51
  ```
38
52
 
39
- ## Usage with Claude Code
53
+ The extension launches the LSP server automatically for `.java` files. Configure the binary path in settings if needed (`javaFunctionalLsp.serverPath`). See [editors/vscode/README.md](editors/vscode/README.md) for details.
54
+
55
+ ### IntelliJ IDEA
56
+
57
+ Use the [LSP4IJ](https://github.com/redhat-developer/lsp4ij) plugin (works on Community & Ultimate):
58
+
59
+ 1. Install **LSP4IJ** from the JetBrains Marketplace
60
+ 2. **Settings** → **Languages & Frameworks** → **Language Servers** → **`+`**
61
+ 3. Set **Command**: `java-functional-lsp`, then in **Mappings** → **File name patterns** add `*.java` with Language Id `java`
40
62
 
41
- Install the `deeperdive-java-linter` plugin from the DeeperDive marketplace, which registers this server as a Java LSP.
63
+ See [editors/intellij/README.md](editors/intellij/README.md) for detailed instructions.
64
+
65
+ ### Claude Code
66
+
67
+ Install as a plugin directly from GitHub:
68
+
69
+ ```bash
70
+ claude plugin add https://github.com/aviadshiber/java-functional-lsp.git
71
+ ```
72
+
73
+ This registers the LSP server, adds auto-install hooks, and provides the `/lint-java` command.
42
74
 
43
75
  Or manually add to your Claude Code config:
44
76
 
@@ -53,9 +85,19 @@ Or manually add to your Claude Code config:
53
85
  }
54
86
  ```
55
87
 
88
+ ### Other Editors
89
+
90
+ Any LSP client that supports stdio transport can use this server. Point it to the `java-functional-lsp` command for `java` files.
91
+
92
+ | Editor | Config |
93
+ |--------|--------|
94
+ | **Neovim** | `vim.lsp.start({ cmd = {"java-functional-lsp"}, filetypes = {"java"} })` |
95
+ | **Emacs (eglot)** | `(add-to-list 'eglot-server-programs '(java-mode "java-functional-lsp"))` |
96
+ | **Sublime Text** | LSP package → add server with `"command": ["java-functional-lsp"]` |
97
+
56
98
  ## Configuration
57
99
 
58
- Create `.deeperdive-linter.json` in your project root to customize rules:
100
+ Create `.java-functional-lsp.json` in your project root to customize rules:
59
101
 
60
102
  ```json
61
103
  {
@@ -0,0 +1,77 @@
1
+ ---
2
+ name: java-functional-lsp
3
+ description: Java LSP with full language support (completions, hover, go-to-def, compile errors) plus 12 functional programming rules enforcement. Auto-invoke when setting up Java language support or discussing Java linting configuration.
4
+ allowed-tools: Bash
5
+ disable-model-invocation: true
6
+ ---
7
+
8
+ # Java Functional LSP
9
+
10
+ A Java LSP server that wraps jdtls and adds 12 functional programming rules. Gives you **full Java language support** (completions, hover, go-to-def, compile errors) **plus** custom diagnostics — all before compilation.
11
+
12
+ ## Prerequisites
13
+
14
+ ```bash
15
+ # Install the LSP server
16
+ brew install aviadshiber/tap/java-functional-lsp
17
+ # Or: pip install java-functional-lsp
18
+
19
+ # Install jdtls for full Java support (optional)
20
+ brew install jdtls
21
+ ```
22
+
23
+ Without jdtls, the server runs in standalone mode — custom rules still work, but no completions/hover/compile errors.
24
+
25
+ ## Rules (12 checks)
26
+
27
+ | Rule | Detects | Suggests |
28
+ |------|---------|----------|
29
+ | `null-literal-arg` | `null` passed as argument | `Option.none()` or default |
30
+ | `null-return` | `return null` | `Option.of()`, `Option.none()`, or `Either` |
31
+ | `null-assignment` | `Type x = null` | `Option<Type>` |
32
+ | `null-field-assignment` | Field initialized to `null` | `Option<T>` with `Option.none()` |
33
+ | `throw-statement` | `throw new XxxException(...)` | `Either.left()` or `Try.of()` |
34
+ | `catch-rethrow` | catch wraps + rethrows | `Try.of().toEither()` |
35
+ | `mutable-variable` | Variable reassignment | Final + functional transforms |
36
+ | `imperative-loop` | `for`/`while` loops | `.map()`/`.filter()`/`.flatMap()` |
37
+ | `mutable-dto` | `@Data` or `@Setter` | `@Value` (immutable) |
38
+ | `imperative-option-unwrap` | `if (opt.isDefined()) { opt.get() }` | `map()`/`flatMap()`/`fold()` |
39
+ | `field-injection` | `@Autowired` on field | Constructor injection |
40
+ | `component-annotation` | `@Component`/`@Service`/`@Repository` | `@Configuration` + `@Bean` |
41
+
42
+ ## Configuration
43
+
44
+ Create `.java-functional-lsp.json` in your project root:
45
+
46
+ ```json
47
+ {
48
+ "rules": {
49
+ "imperative-loop": "hint",
50
+ "mutable-variable": "info",
51
+ "throw-statement": "off"
52
+ }
53
+ }
54
+ ```
55
+
56
+ Severity levels: `error`, `warning` (default), `info`, `hint`, `off`.
57
+
58
+ ## On-Demand Linting
59
+
60
+ Use `/lint-java <path>` to force-run the linter on specific files or directories.
61
+
62
+ ## Releasing a New Version
63
+
64
+ To release a new version:
65
+
66
+ 1. Bump version in `src/java_functional_lsp/__init__.py` and `pyproject.toml`
67
+ 2. Update `.claude-plugin/plugin.json` version to match
68
+ 3. Commit and push to main
69
+ 4. Create a GitHub release with a tag matching `v*` (e.g., `v0.3.0`)
70
+ 5. CI automatically publishes to PyPI and builds the VS Code extension `.vsix`
71
+ 6. Run `python3 scripts/generate-formula.py <version>` and update the Homebrew tap
72
+
73
+ ## Troubleshooting
74
+
75
+ - **"java-functional-lsp not found"**: Run `brew install aviadshiber/tap/java-functional-lsp`
76
+ - **No completions/hover**: Install jdtls: `brew install jdtls`
77
+ - **Too many warnings**: Create `.java-functional-lsp.json` to tune severity or disable noisy rules
@@ -0,0 +1,40 @@
1
+ ---
2
+ name: lint-java
3
+ description: Run java-functional-lsp linter on Java files and report diagnostics
4
+ allowed-tools: Bash, Read, Glob
5
+ ---
6
+
7
+ # Java Functional Linter
8
+
9
+ Run the Java code quality linter on specified files or directories.
10
+
11
+ ## Arguments
12
+
13
+ $ARGUMENTS - Java files, directories, or glob patterns to lint. If empty, lint all .java files in the current directory.
14
+
15
+ ## Instructions
16
+
17
+ 1. Determine the target files:
18
+ - If $ARGUMENTS is provided, use it as the path(s)
19
+ - If empty, use the current working directory
20
+
21
+ 2. Run the linter:
22
+ ```bash
23
+ java-functional-lsp check $ARGUMENTS
24
+ ```
25
+ If no arguments: `java-functional-lsp check --dir .`
26
+
27
+ 3. Present the results clearly:
28
+ - Group diagnostics by file
29
+ - For each diagnostic, show the line number, rule, and suggestion
30
+ - If the file is short, show the offending line of code
31
+ - Summarize total issues at the end
32
+
33
+ 4. If the user asks to fix issues, suggest concrete code changes:
34
+ - `null-return` → wrap in `Option.of()` or return `Either.left(error)`
35
+ - `throw-statement` → convert to `Either.left()` or `Try.of()`
36
+ - `mutable-variable` → make final, use functional transforms
37
+ - `imperative-loop` → replace with `.map()`, `.filter()`, `.flatMap()`
38
+ - `mutable-dto` → change `@Data` to `@Value`
39
+ - `field-injection` → convert to constructor injection
40
+ - `component-annotation` → move to `@Configuration` class with `@Bean`
@@ -0,0 +1,90 @@
1
+ # Java Functional LSP — IntelliJ IDEA Setup
2
+
3
+ Use [LSP4IJ](https://github.com/redhat-developer/lsp4ij) (by Red Hat) to connect `java-functional-lsp` to IntelliJ IDEA. Works on both **Community** and **Ultimate** editions.
4
+
5
+ ## Prerequisites
6
+
7
+ 1. Install the LSP server:
8
+
9
+ ```bash
10
+ # Homebrew
11
+ brew install aviadshiber/tap/java-functional-lsp
12
+
13
+ # pip
14
+ pip install java-functional-lsp
15
+ ```
16
+
17
+ 2. Verify it's on your PATH:
18
+
19
+ ```bash
20
+ java-functional-lsp --help
21
+ ```
22
+
23
+ If not on PATH, note the full path (e.g., `which java-functional-lsp`).
24
+
25
+ ## Step 1: Install LSP4IJ Plugin
26
+
27
+ 1. Open IntelliJ IDEA
28
+ 2. Go to **Settings** → **Plugins** → **Marketplace**
29
+ 3. Search for **"LSP4IJ"**
30
+ 4. Click **Install** and restart the IDE
31
+
32
+ ## Step 2: Add Language Server
33
+
34
+ 1. Go to **Settings** → **Languages & Frameworks** → **Language Servers**
35
+ 2. Click the **`+`** button to add a new server
36
+ 3. Configure:
37
+
38
+ | Field | Value |
39
+ |-------|-------|
40
+ | **Name** | `Java Functional LSP` |
41
+ | **Command** | `java-functional-lsp` |
42
+
43
+ > **PATH issues?** If IntelliJ can't find the binary, use the full path:
44
+ > - Homebrew: `/opt/homebrew/bin/java-functional-lsp`
45
+ > - pip: `~/.local/bin/java-functional-lsp` (or check with `which java-functional-lsp`)
46
+ >
47
+ > On macOS, you can also use: `sh -c java-functional-lsp`
48
+
49
+ ## Step 3: Configure File Mappings
50
+
51
+ In the **Mappings** tab of the server configuration, add mappings so the LSP server activates for Java files. Set up **all three** sub-tabs:
52
+
53
+ **Language** tab:
54
+ 1. Click **`+`** → select **Java**
55
+
56
+ **File type** tab:
57
+ 1. Click **`+`** → select **Java**
58
+
59
+ **File name patterns** tab:
60
+ 1. Click **`+`** to add a pattern
61
+ 2. Set **File name patterns**: `*.java`
62
+ 3. Set **Language Id**: `java`
63
+
64
+ ## Step 4: Verify
65
+
66
+ 1. Open any `.java` file in your project
67
+ 2. Check the bottom status bar — you should see the LSP server connecting
68
+ 3. Write code that triggers a rule (e.g., `return null;`) — a warning should appear
69
+
70
+ ## Configuration
71
+
72
+ Project-level rules are configured via `.java-functional-lsp.json` in your project root. See the [main README](../../README.md) for details.
73
+
74
+ ## Coexistence with IntelliJ's Java Support
75
+
76
+ LSP4IJ is designed to **supplement** IntelliJ's native Java support, not replace it. Your custom functional programming diagnostics appear alongside IntelliJ's built-in inspections. No conflicts.
77
+
78
+ ## Troubleshooting
79
+
80
+ ### Server doesn't start
81
+ - Check **Settings** → **Languages & Frameworks** → **Language Servers** → select your server → **Traces** tab for error logs
82
+ - Verify the binary works: run `java-functional-lsp check --help` in a terminal
83
+
84
+ ### No diagnostics appear
85
+ - Ensure the file mapping is set to Language: `Java`, Language ID: `java`
86
+ - Check that `.java-functional-lsp.json` doesn't have rules set to `"off"`
87
+ - Try restarting the language server: **Tools** → **Language Servers** → **Restart**
88
+
89
+ ### PATH not found
90
+ - IntelliJ may not inherit your shell's PATH. Use the full absolute path to the binary in the server command.
@@ -0,0 +1,10 @@
1
+ {
2
+ "name": "Java Functional LSP",
3
+ "command": "java-functional-lsp",
4
+ "mappings": [
5
+ {
6
+ "language": "Java",
7
+ "languageId": "java"
8
+ }
9
+ ]
10
+ }
@@ -0,0 +1,6 @@
1
+ src/**
2
+ node_modules/**
3
+ tsconfig.json
4
+ .vscode/**
5
+ **/*.ts
6
+ **/*.map
@@ -0,0 +1,60 @@
1
+ # Java Functional LSP — VS Code Extension
2
+
3
+ Enforces functional programming best practices in Java files. Detects null usage, mutable state, exceptions, imperative loops, and Spring anti-patterns — and suggests functional alternatives using Vavr, Lombok, and idiomatic patterns.
4
+
5
+ ## Prerequisites
6
+
7
+ Install the LSP server:
8
+
9
+ ```bash
10
+ # Homebrew
11
+ brew install aviadshiber/tap/java-functional-lsp
12
+
13
+ # pip
14
+ pip install java-functional-lsp
15
+ ```
16
+
17
+ ## Install the Extension
18
+
19
+ ### From VSIX (recommended)
20
+
21
+ Download the latest `.vsix` from [GitHub Releases](https://github.com/aviadshiber/java-functional-lsp/releases), then:
22
+
23
+ ```bash
24
+ code --install-extension java-functional-lsp-*.vsix
25
+ ```
26
+
27
+ Or in VS Code: Extensions panel → `...` menu → "Install from VSIX..."
28
+
29
+ ### Build from Source
30
+
31
+ ```bash
32
+ cd editors/vscode
33
+ npm install
34
+ npm run compile
35
+ npx vsce package
36
+ code --install-extension java-functional-lsp-*.vsix
37
+ ```
38
+
39
+ ## Configuration
40
+
41
+ | Setting | Default | Description |
42
+ |---------|---------|-------------|
43
+ | `javaFunctionalLsp.serverPath` | `"java-functional-lsp"` | Path to the LSP binary. Override if not on PATH. |
44
+ | `javaFunctionalLsp.enabled` | `true` | Enable/disable the extension. |
45
+
46
+ Example `settings.json`:
47
+
48
+ ```json
49
+ {
50
+ "javaFunctionalLsp.serverPath": "/opt/homebrew/bin/java-functional-lsp"
51
+ }
52
+ ```
53
+
54
+ ## Coexistence with Other Extensions
55
+
56
+ This extension **coexists** with the Red Hat Java extension (`redhat.java`) and other Java extensions. Diagnostics from all servers are shown together — no configuration needed.
57
+
58
+ ## Rules
59
+
60
+ See the [main README](../../README.md) for the full list of 12 rules and configuration options via `.java-functional-lsp.json`.