github carthage-software/mago 1.40.0
Mago 1.40.0

latest release: 1.40.1
5 hours ago

Mago 1.40.0

A big release driven by community reports: three new formatter settings, a new suspicious-explode-arguments linter rule and a final-controller auto-fix, an inspect-baseline CLI command, a Composer-shipped editor schema, and a long list of analyzer, codex, prelude, and PHP-parity syntax fixes. Under the hood, the 2.0 groundwork landed on main: a new high-level IR, a unified mago-phpdoc-syntax, and new mago-allocator/mago-flags crates.

✨ Features

Analyzer

  • array_filter truthiness: a callback-less array_filter() narrows values to their truthy form. (#1990, bc9bede)

Formatter

  • Breaking binary expressions: preserve_breaking_binary_expression keeps author line breaks in such chains. (#1853, 5aacc7d)
  • Sort uses by length: optional sorting of use statements by length. (#1942, 0688859)
  • Tag + declare: optionally combine the opening tag and declare(strict_types=1) onto one line. (#1959, 2ff4cf5)

Linter

  • suspicious-explode-arguments: warns when explode's short literal looks swapped into the string position. (#1998, 577d40a)
  • final-controller fix: offers an auto-fix that inserts final before any modifier. (#2006, 82017a0)
  • sensitive-parameter: skips boolean-like parameters. (#1949, 2333626)

Type System

  • empty types: empty and empty-scalar are supported in type-syntax and codex. (#1968, e94cfdd)

CLI

  • inspect-baseline: new command to visualise the distribution of baselined issues. (#1900, efd07bd)

Composer

  • Editor schema: ships a version-matched schema.json under vendor/carthage-software/mago/. (#1899, 38b78d0)

Nix

  • Default package: packages.<system>.default now provides bin/mago. (#1970, 13d7071)

🐛 Bug Fixes

Analyzer

  • Named args + optional params: too-few-arguments fires when a named arg fills only an optional param. (#2004, c5ec4ef)
  • Conditional array shapes: double-quoted array-access keys reconcile like single-quoted ones. (#2005, 095badf)
  • Shadowed overrides: no false incompatible-return-type against an ancestor hidden by an intermediate override. (#1996, 431ff97)
  • $this calls: a property keeps its declared type instead of widening to mixed. (#1994, 5eef024)
  • Readonly narrowing: readonly property narrowings survive a call passing an object argument. (#1993, 5cbbe91)
  • foreach over unions: corrected always-entered inference, fixing a false impossible-condition. (#1986, 22951bd)
  • Compound conditions: avoid duplicate diagnostics in compound conditions. (#1961, 1ea5ba2)
  • @property traits: trait property conflicts are no longer reported against @property tags. (#1964, a5f3823)

Codex

  • Self-cased display: self/static/parent resolve to the original-cased class name in diagnostics. (#1995, b544222)
  • Closure instanceof: closures are treated as instances of Closure. (#1956, 6fe1bbd)
  • Callable variance: null is no longer ignored in contravariant callable parameter checks. (#1966, 3f94734)

Linter

  • String-concat chains: a whole chain collapses into one no-redundant-string-concat issue and fix. (#2003, f8a31f8)
  • no-dead-store: flags stores overwritten across a conditional branch. (#1999, a315465)
  • no-boolean-flag: only flags boolean parameters actually used as flags. (#1988, 50cdd11)
  • prefer-early-continue: the auto-fix preserves comments and indentation. (#1946, 495f639)

Syntax

  • Operator precedence: corrected clone/cast/unary precedence and bound print/yield above and/xor/or. (1ac37b0, 4d01d2d)
  • String interpolation: distinguishes ${label}/${ expr } and $a[offset] forms in the lexer. (b56a704, f3198c8)
  • Reference operands: relational stays above equality when a reference assignment is an operand. (ea6cbce)
  • Unicode escapes: \u{...} decodes to UTF-8 bytes to match Zend. (b19386c)

HIR

  • Integer literals: lowered with PHP long semantics, overflowing to float. (9014c33, 79a7600)
  • Anonymous classes: anonymous-class modifiers are now lowered. (797358f)

Docblock

  • static return: parses a static return type after the static method modifier. (#1963, d5fb015)

Prelude

  • phpversion(): $extension is optional. (#1950, 5aed5bf)
  • array_splice: preserves the element type in its return. (#1982, af4e647)
  • PCRE/mbstring stubs: corrected preg_match_all/preg_replace_callback_array and mb_ord stubs. (#1980, 958a4b7; #1981, dd0b80c)
  • Default values: added to ZipArchive::addEmptyDir, xml_parser_create, ini_get_all, and more. (#1967, 6c640d9; #1969, 054651d)
  • Precise types: base64_encode returns non-empty-string; tighter stdlib types. (#1974, c2c37f5; #1975, c7e595f)
  • Falsable returns: mb_chr/mb_ord and ReflectionClass::getReflectionConstant. (578e427, 327778a)

📖 Documentation

  • GitHub Actions: improved setup guide and refreshed action versions. (#1953, b852388)

🏗️ Internal

Architecture

  • High-level IR: new mago-hir crate lowering the CST to a high-level IR (2.0 groundwork). (ca15f9d, e32d0d8, afefad6)
  • PHPDoc unification: codex/analyzer/linter scan docblocks via mago-phpdoc-syntax, retiring two crates. (#1932, #1972, 70179ec)
  • New crates: mago-allocator (+ CopyInto) and mago-flags. (#1957, 0adfdc0, 9a4cd06)
  • Lexer heredoc: heredoc/nowdoc resolved in the lexer with indentation as trivia. (0e4c0e6)
  • astcst: renamed AST to CST across the workspace. (#1933, b7d64b6)

Dependencies

  • Slimmer deps: serde is now optional/off-by-default; dropped cruet, ustr, shell-words. (1751bae, 184c493, ec8e092)

CI / Tooling

  • Toolchain: routine pinned-nightly bumps. (#2002, #2000, #1997)
  • Miri & fuzzing: skip deep-nesting overflow tests under Miri; fix fuzz-target Arena import. (676e1a4, #1984, 92d29cd)

🙏 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:

Full Changelog: 1.30.0...1.40.0

Don't miss a new mago release

NewReleases is sending notifications on new releases.