Skip to content

Commit 401cb65

Browse files
committed
Update docs
1 parent fe446e8 commit 401cb65

4 files changed

Lines changed: 146 additions & 22 deletions

File tree

docs/CLI.md

Lines changed: 104 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22

33
PHPantom is a language server, but it also ships CLI tools for batch
44
analysis and automated fixing. These run the same engine that powers the
5-
editor, so results are consistent.
5+
editor, so results are consistent between what you see in your editor
6+
and what CI reports.
67

78
## Modes
89

@@ -21,8 +22,49 @@ this automatically.
2122
## `analyze`
2223

2324
Scans PHP files and reports PHPantom diagnostics in a PHPStan-style
24-
table format. Use it to find spots where the LSP cannot resolve a
25-
symbol, so you can achieve full completion coverage.
25+
table format. The goal is full symbol resolution: every class, member,
26+
and function call in your codebase should be resolvable. When that
27+
holds, completion and hover work everywhere, and PHPStan gets the type
28+
information it needs at every level.
29+
30+
Use it to find and fix the spots where the editor can't resolve a
31+
symbol, so you can achieve and maintain full type coverage across
32+
the project.
33+
34+
### What it checks
35+
36+
It doesn't try to find every possible bug. Its main focus is symbol
37+
resolution: every class, member, and function call should point to
38+
something real. It also catches basic correctness issues like wrong
39+
argument counts and missing interface implementations. When a codebase
40+
passes cleanly, completions work everywhere for every developer on the
41+
team.
42+
43+
That makes it useful in a few situations:
44+
45+
- **Teams that just want completions to work in their editor.** If
46+
your goal is "every `->` and `::` resolves to something" rather
47+
than "catch every possible runtime error," PHPantom's analysis
48+
covers exactly that.
49+
- **As a companion to PHPStan at a moderate level.** A team running
50+
PHPStan at level 4 (catching dead code and type mismatches) can add
51+
PHPantom's analysis to enforce that every class, member, and function
52+
is resolvable across the full codebase. PHPStan catches logic errors,
53+
PHPantom catches structural gaps. Together they cover a useful quality
54+
surface without the effort of configuring PHPStan at max level.
55+
- **As a quick sanity check.** Point it at a Composer project and it
56+
reports what it finds. No baselines, no ignore files, no level to
57+
choose. The only configuration worth knowing about is
58+
`unresolved-member-access`: enable it in `.phpantom.toml` to also
59+
flag member access on variables whose type could not be resolved
60+
(off by default because it is noisy on untyped codebases).
61+
62+
> [!NOTE]
63+
> There are still occasional false positives, though they are getting
64+
> fewer with each release. If you hit one, please
65+
> [report it](https://github.com/AJenbo/phpantom_lsp/issues).
66+
67+
### Usage
2668

2769
```sh
2870
phpantom_lsp analyze # scan entire project
@@ -87,6 +129,10 @@ Each has a rule identifier shown below the message.
87129
Applies code fixes across the project. Specify which rules to run, or
88130
omit `--rule` to run all preferred native fixers.
89131

132+
This is useful for cleaning up an entire codebase in one pass. For
133+
example, a project with hundreds of unused `use` statements can be
134+
cleaned up in seconds rather than file by file.
135+
90136
```sh
91137
phpantom_lsp fix # apply all preferred fixers
92138
phpantom_lsp fix --rule unused_import # only remove unused imports
@@ -156,13 +202,6 @@ phpantom_lsp fix --dry-run --project-root /path/to/app
156202
[DRY RUN] 1 fix in 1 file (not applied)
157203
```
158204

159-
Use `--dry-run` in CI to enforce that imports stay clean:
160-
161-
```sh
162-
phpantom_lsp fix --dry-run --rule unused_import --project-root .
163-
# Exit code 2 means fixable issues exist. Fail the build.
164-
```
165-
166205
### Idempotency
167206

168207
Running `fix` twice produces the same result as running it once. If
@@ -186,35 +225,78 @@ on available settings.
186225

187226
---
188227

189-
## Common patterns
228+
## CI Integration
229+
230+
PHPantom works well as a lightweight CI gate. It's a single static
231+
binary with no runtime dependencies (no PHP, no Composer, no Node). Drop
232+
it into a pipeline and point it at your project root.
233+
234+
### Why use it in CI?
235+
236+
Editor diagnostics only help the developer who has the editor open.
237+
CI analysis protects the whole team: no PR can merge if it introduces
238+
an unresolvable symbol, regardless of which editor each developer uses.
239+
Over time this keeps the codebase fully navigable, so completions,
240+
hover, and go-to-definition work everywhere for everyone.
241+
242+
It also complements PHPStan rather than replacing it. PHPStan is better
243+
at catching logical errors, type mismatches, and dead code. PHPantom is
244+
better at catching structural gaps: unknown classes, unresolvable
245+
members, missing implementations. Running both gives you broad coverage
246+
without needing PHPStan at max level to get full symbol resolution.
247+
248+
### GitHub Actions example
190249

191-
### CI pipeline: diagnostics gate
250+
```yaml
251+
name: Type Coverage
252+
on: [push, pull_request]
192253

193-
Fail the build when PHPantom finds unresolvable symbols:
254+
jobs:
255+
phpantom:
256+
runs-on: ubuntu-latest
257+
steps:
258+
- uses: actions/checkout@v4
259+
260+
# Use --no-dev to catch production code that depends on dev-only
261+
# packages (e.g. calling PHPUnit classes from application code).
262+
- name: Install Composer dependencies
263+
run: composer install --no-interaction --prefer-dist --no-dev
264+
265+
- name: Install PHPantom
266+
run: |
267+
curl -sL https://github.com/AJenbo/phpantom_lsp/releases/download/0.6.0/phpantom_lsp-x86_64-unknown-linux-gnu.tar.gz | tar xz
268+
chmod +x phpantom_lsp
269+
270+
- name: Check type coverage
271+
run: ./phpantom_lsp analyze --severity warning --no-colour src/
272+
```
273+
274+
The `analyze` step fails the build if any class, member, or function
275+
cannot be resolved (including unused imports). The output is clean and
276+
readable in the CI log.
277+
278+
### Common patterns
279+
280+
**Diagnostics gate.** Fail the build when PHPantom finds unresolvable
281+
symbols:
194282

195283
```sh
196284
phpantom_lsp analyze --severity warning --project-root . --no-colour
197285
```
198286

199-
### CI pipeline: enforce clean imports
200-
201-
Fail the build when unused imports exist:
287+
**Enforce clean imports.** Fail the build when unused imports exist:
202288

203289
```sh
204290
phpantom_lsp fix --dry-run --rule unused_import --project-root . --no-colour
205291
```
206292

207-
### Pre-commit hook: auto-fix imports
208-
209-
Clean up imports before every commit:
293+
**Pre-commit hook.** Clean up imports before every commit:
210294

211295
```sh
212296
phpantom_lsp fix --rule unused_import --project-root .
213297
```
214298

215-
### Combine analyze and fix
216-
217-
Run fixes first, then check what remains:
299+
**Combine analyze and fix.** Run fixes first, then check what remains:
218300

219301
```sh
220302
phpantom_lsp fix --project-root .

docs/todo.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ within the same impact tier.
3535
| D11 | [Invalid class-like kind in context](todo/diagnostics.md#d11-invalid-class-like-kind-in-context) | Medium | Low |
3636
| F4 | [Return type and closure parameter type inlay hints](todo/lsp-features.md#f4-return-type-and-closure-parameter-type-inlay-hints) | Medium | Medium |
3737
| A36 | [Import all missing classes](todo/actions.md#a36-import-all-missing-classes) (bulk import) | Medium | Low |
38+
| F6 | [Machine-readable CLI output formats](todo/lsp-features.md#f6-machine-readable-cli-output-formats) (`--format github\|json`) | Medium | Low |
3839
| | **Release 0.8.0** | | |
3940

4041
> **Note:** F1 (Workspace symbol search), F2 (Document symbols), A8
@@ -133,6 +134,7 @@ unlikely to move the needle for most users.
133134
| FX4 | [`phpstan.missingType.iterableValue` — add `@return` with iterable type](todo/fix-cli.md#fx4-phpstanmissingtypeiterablevalue--add-return-with-iterable-type) | Medium | Medium |
134135
| FX5 | [`phpstan.property.unused` / `phpstan.method.unused` — remove unused member](todo/fix-cli.md#fx5-phpstanpropertyunused--phpstanmethodunused--remove-unused-member) | Low | Low |
135136
| FX6 | [`phpstan.generics.callSiteVarianceRedundant` — remove redundant variance](todo/fix-cli.md#fx6-phpstangenericscallsitevarianceredundant--remove-redundant-variance) | Low | Low |
137+
| FX7 | [`add_return_type` — generate `@return` docblocks from function bodies](todo/fix-cli.md#fx7-add_return_type--generate-return-docblocks-from-function-bodies) | Medium-High | Medium |
136138
| | **[LSP Features](todo/lsp-features.md)** | | |
137139
| F5 | [Call hierarchy](todo/lsp-features.md#f5-call-hierarchy) (incoming/outgoing calls) | Medium | Medium |
138140
| F2 | [Partial result streaming via `$/progress`](todo/lsp-features.md#f2-partial-result-streaming-via-progress) | Medium | Medium-High |

docs/todo/fix-cli.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,19 @@ with side effects in the RHS (method calls, function calls). When the
3737
RHS is pure (literal, property access, simple expression), remove the
3838
entire statement.
3939

40+
### FX7. `add_return_type` — Generate `@return` docblocks from function bodies
41+
42+
Wire up the existing "Generate PHPDoc" code action's return-type
43+
inference to the fix CLI. When a function or method has a native
44+
`array` return type (or no return type at all) and the body contains
45+
enough information to infer a specific element type, add a `@return`
46+
tag with the inferred type (e.g. `@return list<Butterfly>`).
47+
48+
This lets teams that want to reach PHPStan level 6 (require return
49+
type declarations) run a single command and get specific, useful
50+
return types across the entire codebase for free, instead of adding
51+
them by hand file by file.
52+
4053
---
4154

4255
## Planned PHPStan Rules

docs/todo/lsp-features.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,3 +239,30 @@ index (X4), the lookup becomes a simple index query.
239239

240240
Consider implementing after X4 (full background indexing) ships, or
241241
accept the same scan-based latency that Find References currently has.
242+
243+
## F6. Machine-readable CLI output formats
244+
245+
**Impact: Medium · Effort: Low**
246+
247+
Add a `--format` flag to `analyze` and `fix` that controls the output
248+
format. The default remains the current human-readable table.
249+
250+
### Formats
251+
252+
- **`github`** — Emit
253+
[workflow commands](https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/workflow-commands-for-github-actions#setting-a-warning-message)
254+
(`::warning file=...::message`) so diagnostics appear as inline
255+
annotations on pull request diffs. This is the highest-priority
256+
format because GitHub Actions is the most common CI environment for
257+
PHP projects.
258+
- **`json`** — One JSON object per diagnostic (or a top-level array).
259+
Enables integration with custom dashboards, editor plugins, and
260+
other tooling that wants to consume PHPantom output programmatically.
261+
262+
### Implementation
263+
264+
The output logic in `analyse.rs` and `fix.rs` currently writes
265+
directly to stderr/stdout with ANSI formatting. Extract the rendering
266+
behind a trait or enum so each format can be selected at the call
267+
site. The `--no-colour` flag becomes redundant for non-table formats
268+
but should continue to work for the default table output.

0 commit comments

Comments
 (0)