Mago 1.10.0
This release introduces wildcard pragma suppression (@mago-ignore all), auto-fix for unused pragmas, a new just-in-time binary download for Composer, and a large number of bug fixes across the analyzer, linter, formatter, and type system.
✨ Features
Collector (Pragma System)
@mago-ignore all/@mago-expect allwildcard pragmas: You can now useallas the issue code in suppress pragmas to suppress all issues within a category (e.g.,@mago-ignore lint:all) or across all categories (e.g.,@mago-ignore all). This is especially useful for legacy code where listing individual codes is impractical (#1034)- Auto-fix suggestions for unused pragmas: When running
mago lint --fixormago analyze --fix, unused@mago-ignoreand unfulfilled@mago-expectdirectives are now automatically stripped. The fixer handles three cases: removing a single code from a comma-separated list, removing a directive line from a multi-line comment, or deleting the entire comment when all pragmas are unused (#1187)
Linter
check-functionsoption forprefer-first-class-callable: The rule now supports acheck-functionsconfig option (default:false). When disabled, the rule only suggests first-class callable conversion for method and static method calls, avoiding false positives with internal PHP functions that throwArgumentCountErroron extra arguments (#1147, #1160)exclude-setters-and-constructorsoption forno-boolean-flag-parameter: The rule now supports excluding setter methods and constructors from boolean flag parameter detection, reducing noise for legitimate boolean setter patterns (#1155)
Composer
- Just-in-time binary download: The Composer plugin has been replaced with a lightweight wrapper script that detects the platform and downloads the correct Mago binary on first run. This eliminates the need to allow a Composer plugin and supports multi-platform environments (e.g., Docker on macOS with mounted volumes) (#1141, #1159)
CLI
- Fully resolved formatter settings in
configoutput: Themago config --show formattercommand now displays all resolved formatter settings flattened alongsideexcludes, matching the TOML configuration structure. The--schemaoutput has also been updated to reflect the flat structure. Previously, only{"excludes": []}was shown (#1180)
🐛 Bug Fixes
Analyzer
- False positive
redundant-conditionforis_float()onint|floatunion: Theint ⊂ floatcontainment rule is now guarded by assertion context, preventing incorrectredundant-conditionandredundant-type-comparisondiagnostics whenis_float()oris_double()is called onint|floatvariables (#1186) - Bogus diagnostic when writing an unknown array index: Fixed false
undefined-string-array-indexerrors when writing to (not reading from) unknown array keys withallow-possibly-undefined-array-keysset tofalse(#1168, #1171) - Class names reported as written instead of normalized: The
catch-type-not-throwablediagnostic now shows class names in their original casing instead of all-lowercase (#1185) - Multiple incremental analysis bugs in watch mode: Fixed several issues where editing one file would clear diagnostics in other files, and body-only changes would lose existing errors. The populator now correctly clears
invalid_dependenciesduring class-like metadata re-population, and the incremental analysis service properly tracks per-file issues (#1176, #1178) - False positive
missing-magic-methodwith trait@property/@method: Real inherited properties and methods from parent classes now correctly override trait pseudo@propertyand@methodannotations, preventing false positives when a trait declares magic accessors that shadow real parent members (#1184) - Mixin types inherited from parent classes: Mixin types declared via
@mixinon parent classes are now correctly inherited by child classes during method and property resolution (#1169)
Linter
prefer-arrow-functiondisabled inside constant expressions: Arrow function suggestions are no longer emitted inside constant expressions (e.g., class constant initializers) where closures are the only valid syntax (#1166)
Formatter
- Pint preset:
method-chain-semicolon-on-next-linedisabled by default: The Pint preset now correctly defaults this setting tofalse, matching Pint's actual behavior (#1164)
Syntax
yieldexpression detected insidereturnstatement: The parser now correctly identifiesyieldexpressions when used as a return value (e.g.,return yield $value), preventing incorrect diagnostics on generator functions (#1167)
Prelude (Type Stubs)
dir()second argument marked as optional: The second parameter ofdir()is now correctly annotated as optional, fixing falsetoo-few-argumentserrors when callingdir()with a single argument (#1163)
Reporter
- Writer buffer flushed in watch mode: The JSON reporter now flushes its writer buffer after each report, preventing incomplete JSON output when piped to external tools like VS Code extensions (#1170)
Atom (Case Folding)
- Case folding matches PHP's behavior for non-ASCII characters: Fixed a bug where non-ASCII characters were incorrectly lowercased using full Unicode rules instead of ASCII-only folding, matching PHP's actual
strtolower()behavior. This could cause mago to fail to detect errors resulting from case differences in non-ASCII class names (#1161)
Playground
file-namerule disabled by default: Thefile-namelint rule is now disabled in the Mago playground to reduce noise for single-file examples (#1162)
🙏 Thank You
Contributors
A huge thank you to everyone who contributed code to this release:
Issue Reporters
Thank you to everyone who reported issues and requested features that shaped this release:
- @ADmad — #1163
- @bendavies — #1184
- @chrisopperwall-qz — #1176, #1178
- @dragosprotung — #1166
- @gusberinger — #1164
- @karoun — #1187
- @mad-briller — #1155
- @mathroc — #1162
- @SFRisso — #1168
- @wryk — #1167
- @ZigZagSK — #1180
Full Changelog: 1.9.1...1.10.0