Skip to content

Commit 5c861bb

Browse files
committed
Rename D12 to "Mago diagnostic proxy" and update integration details
1 parent ba16be9 commit 5c861bb

2 files changed

Lines changed: 94 additions & 23 deletions

File tree

docs/todo.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ within the same impact tier.
2929
| P9 | [`resolved_class_cache` generic-arg specialisation](todo/performance.md#p9-resolved_class_cache-generic-arg-specialisation) | Medium | Medium |
3030
| P18 | [Subtype result caching](todo/performance.md#p18-subtype-result-caching) (per-request HashMap for hierarchy walks) | Medium | Low |
3131
| D4 | [Unused variable diagnostic](todo/diagnostics.md#d4-unused-variable-diagnostic) | Medium | Medium |
32-
| D12 | [Mago linter integration](todo/diagnostics.md#d12-mago-linter-integration-optional-diagnostics) | Medium | Medium |
32+
| D12 | [Mago diagnostic proxy](todo/diagnostics.md#d12-mago-diagnostic-proxy) | Medium | Medium |
3333
| F4 | [Return type and closure parameter type inlay hints](todo/lsp-features.md#f4-return-type-and-closure-parameter-type-inlay-hints) | Medium | Medium |
3434
| F9 | [Namespace renaming](todo/lsp-features.md#f9-namespace-renaming) | Medium | Medium |
3535
| A40 | [Convert to instance variable](todo/actions.md#a40-convert-to-instance-variable) | Medium | Medium |

docs/todo/diagnostics.md

Lines changed: 93 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -230,31 +230,102 @@ with `command`, `timeout`, and tool-specific options mirroring the
230230

231231
---
232232

233-
## D12. Mago linter integration (optional diagnostics)
233+
## D12. Mago diagnostic proxy
234234

235235
**Impact: Medium · Effort: Medium**
236236

237-
PHPantom already depends on several mago crates (`mago-syntax`,
238-
`mago-docblock`, `mago-names`, `mago-formatter`, `mago-span`). The
239-
`mago-linter` crate provides ~159 lint rules covering redundancy,
240-
best practices, clarity, consistency, correctness, and deprecation.
241-
Integrating it as an optional diagnostics provider would give users
242-
"PHPStan-lite" diagnostics without requiring PHPStan to be installed.
243-
244-
**Integration approach:** call `Linter::lint()` on the parsed AST
245-
(already available), convert `IssueCollection` to LSP `Diagnostic`s,
246-
convert `TextEdit` fixes to LSP `CodeAction`s. The linter is AST-only
247-
(no type inference), so it is fast.
248-
249-
Offer as opt-in via `.phpantom.toml` configuration. Default to
250-
disabled so it does not conflict with users who already run PHPStan
251-
or Psalm. Mark with `source: "mago"` to distinguish from PHPantom's
252-
own diagnostics.
253-
254-
**Notable rules:** `no-redundant-method-override`,
255-
`str-contains`/`str-starts-with` modernization,
256-
`prefer-arrow-function`, `constant-condition`, `no-self-assignment`,
257-
`explicit-nullable-param`, `valid-docblock`.
237+
Proxy Mago the same way PHPantom proxies PHPStan and PHPCS:
238+
auto-detect the binary, spawn it on file changes, parse JSON
239+
output, and surface diagnostics in the editor.
240+
241+
**Why proxy, not in-process:** PHPantom already vendors several
242+
mago crates for parsing, but the `mago-linter` crate contains
243+
~159 lint rules with their own configuration surface. Building it
244+
in-process would mean PHPantom owns every false positive those
245+
rules produce, must duplicate or re-expose mago's `mago.toml`
246+
config format, and must document and support someone else's rule
247+
options. An opt-in toggle that 99% of users never discover is
248+
wasted effort. The proxy approach lets users who already use Mago
249+
get diagnostics automatically: they already have a `mago.toml`
250+
with rules tuned for their codebase, baselines for known issues,
251+
and framework integrations configured. PHPantom just shows what
252+
Mago reports.
253+
254+
### Auto-detection
255+
256+
Enable automatically when the project has `mago.toml` at the
257+
workspace root and `vendor/bin/mago` (or `mago` on `$PATH`)
258+
exists. Same resolution chain as PHPStan/PHPCS: explicit
259+
`.phpantom.toml` command > Composer bin-dir > `$PATH`. Setting
260+
the command to `""` disables the proxy.
261+
262+
### Execution
263+
264+
Mago has two separate commands, both accepting `--stdin-input`
265+
and `--reporting-format json`:
266+
267+
- **`mago lint`** — AST-level rules: style, naming, code smells,
268+
best practices (e.g. `strict-types`, `file-name`,
269+
`prefer-arrow-function`). Comparable to PHPCS. Fast.
270+
- **`mago analyze`** — Static analysis with type inference: type
271+
mismatches, unreachable code, unused definitions. Comparable
272+
to PHPStan. Slower.
273+
274+
A project's `mago.toml` can configure either or both via
275+
`[linter]` and `[analyzer]` sections. PHPantom should run
276+
whichever the project has configured. When both are present,
277+
run `mago lint` on the fast path (same debounce as PHPCS) and
278+
`mago analyze` on the slow path (same debounce/worker pattern
279+
as PHPStan: single pending URI, configurable timeout,
280+
cancellation on new edits). Use `source: "mago-lint"` and
281+
`source: "mago-analyze"` to distinguish the two.
282+
283+
### JSON output mapping
284+
285+
Mago's JSON output provides everything needed:
286+
287+
- `level` (Error, Warning, Note, Help) maps to LSP severity.
288+
- `code` (rule name, e.g. `strict-types`, `no-empty`) becomes
289+
the diagnostic code.
290+
- `annotations[].span` provides file, offset, and line for the
291+
diagnostic range.
292+
- `edits` provides auto-fix `TextEdit`s with a `safety`
293+
classification (safe, potentially-unsafe, unsafe).
294+
295+
Mark diagnostics with `source: "mago-lint"` or
296+
`source: "mago-analyze"` depending on the originating command.
297+
298+
### Quick-fix code actions from edits
299+
300+
Mago's JSON includes fix edits with safety levels. Convert these
301+
to LSP `CodeAction`s:
302+
303+
- `safe` fixes: offer as preferred quick-fix.
304+
- `potentially-unsafe` / `unsafe` fixes: offer as non-preferred
305+
quick-fix with the safety level noted in the action title.
306+
307+
### Configuration
308+
309+
Add a `[mago]` section to `.phpantom.toml`:
310+
311+
- `command` — explicit path to the mago binary (default:
312+
auto-detect).
313+
- `timeout` — per-invocation timeout in seconds (default: 30).
314+
315+
No rule-level configuration in `.phpantom.toml`. The user
316+
configures rules in `mago.toml` where they belong.
317+
318+
### Files
319+
320+
- `src/mago.rs``resolve_mago`, `run_mago_lint`,
321+
`run_mago_analyze`, `parse_mago_json`, JSON structs.
322+
Shared binary resolution (one binary, two commands).
323+
- `src/server.rs` — two workers: `mago_lint_worker` (fast,
324+
PHPCS-like debounce) and `mago_analyze_worker` (slow,
325+
PHPStan-like debounce). Both follow the existing
326+
single-pending-URI pattern.
327+
- `src/config.rs``MagoConfig` struct.
328+
- `src/code_actions/mago/` — quick-fix code actions from edits.
258329

259330
## D13. Unify diagnostic subject resolution with completion/hover
260331

0 commit comments

Comments
 (0)