Mago 1.27.0
A feature release built around Mago\Available* attributes for version-gating PHP symbols, several formatter additions for attribute ordering and multi-trait use splits under PER-CS/PSR-12, a hierarchy-aware Class::method form for class-initializers, and a namespaced mode for no-fully-qualified-global-function that imports the parent namespace instead of the function. The rest is a batch of analyzer narrowings, a mago lint --only CLI fix, the long-standing PHP 8.4 inline new X()->method() formatter fix, and docs work (playground contrast, version-switch keeping you on the same page).
✨ Features
Codex
Mago\Available*attributes: version-gate symbols across codex, analyzer, prelude, and composer. (#1113, 7a59a92)
Analyzer
Class::methodinclass-initializers: scope an initializer to a class hierarchy viaFoo::configure. (#1684, 6fb88c6)
Linter
namespacedoption onno-fully-qualified-global-function: import the namespace, not the function. (#1804, af49248)no-negated-ternarycovers!==,!=,<>: rule now flags negated comparisons beyond!=. (#1825, 629cbe6)no-assign-in-conditionwhileopt-out: optionally ignorewhilestatements. (#1819, 47e3118)
Formatter
attributes-order+separate-attributesoptions: control attribute ordering and grouping. (#1820, 0e835ef0)- Multi-trait
usesplit: one trait perusestatement under PER-CS / PSR-12. (#1807, e06da32)
Reporting
- Structured baseline diff:
--verify-baseline --reporting-format jsonemits a structured diff. (#1812, e5d26d6)
Testing
- Standalone integration test runner: independent harness for cross-crate integration tests. (#1805, 56e6414)
🐛 Bug Fixes
Analyzer
array_filter/array_allcallback narrowing: lift callback assertions onto array values frommixed. (#1801, 60e34a9)- Property narrowings across opaque calls: preserved when the call cannot see the property. (#1811, c1bce5b)
- Relational comparisons on arrays: warns when one operand may be an array. (#1815, f843108)
array_allunwrap: replaced withlet-binding to avoid panicking on unexpected shapes. (ab1792c)
Codex
- Generic index parameters in
TIndexAccess: now expanded soT[K]resolves through bounds. (#1810, 03791963)
Linter
no-is-nullautofix: cleannull === $x/null !== $xoutput across negation, parens, and double-negation. (#1821, 45f7972)
Formatter
- PHP 8.4 inline
new X()->method(): emitted when both paren options are off. (#1808, a70b2ef) - Tab-width-aware line wrapping:
use-tabs = truenow counts tab columns againstprint-width. (#1806, a91604a)
CLI
--onlystops swallowing paths:mago lint -o code path.phpnow lintspath.phpinstead of treating it as another rule. (#1814, 81cae5c)
Orchestrator
ParallelPipelineDebug: includesphp_versionfor clearer diagnostics. (1bfce02)
Nix flake
- Correct Rust version: flake pins its own toolchain rather than inheriting global settings. (#1822, 61c3a82)
📖 Documentation
- Playground contrast: fixed text-selection visibility, link styling, and sidebar contrast. (#1795, a27851a)
- Version switch keeps the page: per-version paths recorded so the dropdown links to the same page across versions. (#1803, ef0b0e0)
- Docker recipe GitLab CI: documents the
entrypointoverride for GitLab pipelines. (#1824, 85164ee)
🙏 Thank You
Contributors
A huge thank you to everyone who contributed code to this release:
Issue Reporters
Thank you to everyone who reported issues that shaped this release:
- @mathroc: #1684, #1803, #1801
- @maximal: #1806, #1807
- @Zuruuh: #1820, #1821
- @bendavies: #1804
- @kczx3: #1795
- @LocalHeroPro: #1808
- @ddanielou: #1810
- @nimetu: #1811
- @UweOhse: #1815
- @tijsverkoyen: #1824
- @MidnightDesign: #1825
- @kzmshx: #1113
Full Changelog: 1.26.0...1.27.0