Skip to content

Release 4.0.0

Latest

Choose a tag to compare

@lisachenko lisachenko released this 25 Aug 05:49
· 23 commits to master since this release
d97fa7f

Parser Reflection 4.0.0

This is a major release that brings the library to full PHP 8.4 reflection parity: property hooks, the lazy-object API, native enum reflection, global constant reflection, and dozens of smaller gaps in the reflection API are now implemented on top of the AST — without loading the reflected code into memory.

💥 Breaking changes

  • PHP 8.4 or newer is now required (previously >=8.2). The CI matrix runs PHP 8.4 and 8.5, with 8.6 as experimental.
  • NodeExpressionResolver no longer implicitly autoloads classes while evaluating constant expressions. Reflection stays purely static; only APIs that genuinely need a live object (e.g. invoke()) trigger class loading.
  • Sources are now parsed with the newest PHP grammar supported by nikic/php-parser instead of the grammar of the host PHP version, so files using newer syntax can be reflected from an older runtime.

🚀 New reflection classes

  • ReflectionEnum, ReflectionEnumUnitCase and ReflectionEnumBackedCase — full static reflection for native enums, wired into ReflectionFile / ReflectionFileNamespace (new getEnums() method) — #189, #190, #192
  • ReflectionConstant — reflection for const-declared global constants — #213
  • NodeAwareInterface — every parsed reflection object now exposes its underlying AST node via getNode()#200

✨ PHP 8.4 API coverage

  • Property hooks: getHook(), getHooks(), hasHook(), hasHooks(), getSettableType(), isVirtual(), isDynamic(), plus correct getModifiers() for virtual and abstract properties — #161, #170, #171, #172, #213
  • Lazy objects: newLazyGhost(), newLazyProxy(), resetAsLazyGhost(), resetAsLazyProxy(), isLazy(), isUninitializedLazyObject(), initializeLazyObject(), markLazyObjectAsInitialized(), skipLazyInitialization(), getLazyInitializer() and raw property access (getRawValue() / setRawValue() / setRawValueWithoutLazyInitialization()) — #213
  • Abstract properties in interfaces and the final modifier on promoted constructor properties — #173, #213

✨ Other improvements

  • Filled PHP 8.1–8.4 function-like reflection gaps: getTentativeReturnType(), hasTentativeReturnType(), isAnonymous(), getClosureUsedVariables(), getClosureCalledClass(), and #[\Deprecated] attribute support — #213
  • getAttributes() now supports ReflectionAttribute::IS_INSTANCEOF filtering — #213
  • Complete trait support, including insteadof and as alias adaptations — #177
  • First-class callable syntax (strlen(...)) supported in constant expressions — #193
  • Enum::CASE->value expressions supported in constant expressions (e.g. parameter defaults) — #176
  • Closures (static fn() => ...) supported in constant-expression contexts — #213
  • Enum case constant introspection via the class-constant API — #213

🐛 Bug fixes

  • Fixed infinite recursion in NodeExpressionResolver::resolveExprClassConstFetch()#178
  • isSubclassOf() now compares fully-qualified class names via the resolved AST name — #180
  • __toString() for inherited methods now renders the inherits OriginalClass section like native reflection — #181
  • Fixed null handling in ReflectionParameter::getDeclaringClass() context resolution — #178

🔧 Internal & CI

  • Static analysis raised to PHPStan level 10 (phpstan/phpstan ^2.0), rector/rector bumped to ^2.0#156
  • PHP 8.6 added to the CI matrix as experimental — #201
  • GitHub Actions hardened with explicit workflow permissions and kept current via Dependabot — #191, #196, #197, #198, #199

Full Changelog: 3.1.0...4.0.0