Skip to content

[Feature] support PHP 8.5 first-class callable as default value for parameters and properties#569

Merged
lisachenko merged 2 commits into
masterfrom
feature/support-php85-fcc-default-values
May 8, 2026
Merged

[Feature] support PHP 8.5 first-class callable as default value for parameters and properties#569
lisachenko merged 2 commits into
masterfrom
feature/support-php85-fcc-default-values

Conversation

@lisachenko
Copy link
Copy Markdown
Member

Summary

  • Proxy generation now preserves FCC default expressions (e.g. function foo($cb = strlen(...))) via raw AST nodes
  • ValueGenerator — added fromExprNode() factory for pre-built AST Expr nodes that can't be represented as PHP scalars
  • PropertyGenerator — added setDefaultExpressionNode() for Expr-based property defaults
  • ParameterGenerator::fromReflection() — uses getNode()->default directly when parser-reflection is available, avoiding parser-reflection bugs where getDefaultValue() crashes (uninitialized typed property) or returns null for Closure defaults
  • AbstractInterceptedPropertyGenerator::createBasePropertyGenerator() — same AST-first approach for intercepted properties

Why AST-first?

When parser-reflection is loaded, the raw AST default node is the authoritative source — it works uniformly for scalars, arrays, and FCC expressions. Calling getDefaultValue() can crash parser-reflection (ReflectionParameter::$defaultValue is uninitialized for FCC) or silently return null (ReflectionProperty::$defaultValue defaults to null). By reading getNode()->default directly, we bypass these issues entirely.

Test plan

  • Full test suite: 2467 tests, 0 failures, 0 errors
  • PHPStan level 10: 0 errors
  • Array property interception test passes (validates AST path works for non-Closure const-expr defaults)
  • PHP 8.4 safety: all new code paths gated by method_exists($param, 'getNode') (parser-reflection only)

🤖 Generated with Claude Code

…eters and properties

Proxy generation now preserves FCC default expressions (e.g. `function foo($cb = strlen(...))`)
via raw AST nodes instead of calling getDefaultValue(), which crashes or returns null in
parser-reflection for Closure defaults.

- ValueGenerator: add fromExprNode() factory for pre-built AST Expr nodes
- PropertyGenerator: add setDefaultExpressionNode() for Expr-based defaults
- ParameterGenerator: use getNode()->default when parser-reflection available
- AbstractInterceptedPropertyGenerator: use getNode()->default for property defaults

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@lisachenko
Copy link
Copy Markdown
Member Author

Depends on goaop/parser-reflection#193

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the proxy-generation pipeline to preserve PHP 8.5+ first-class callable (FCC) default expressions for parameters and (promoted/intercepted) properties by carrying raw PhpParser AST Expr nodes through generation, instead of relying on Reflection*::getDefaultValue().

Changes:

  • Add ValueGenerator::fromExprNode() to support defaults represented as pre-built AST expressions.
  • Extend PropertyGenerator with setDefaultExpressionNode() and emit expression defaults directly when present.
  • Update ParameterGenerator::fromReflection() and AbstractInterceptedPropertyGenerator::createBasePropertyGenerator() to prefer getNode()->default (parser-reflection) and throw a clear exception when a Closure default can’t be represented without AST access.
  • Document the feature in CHANGELOG.md.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/Proxy/Part/AbstractInterceptedPropertyGenerator.php Switch intercepted property default handling to prefer AST defaults when available.
src/Proxy/Generator/ValueGenerator.php Add an AST-node-backed construction path for defaults that can’t be represented as scalars.
src/Proxy/Generator/PropertyGenerator.php Allow property defaults to be set via a raw Expr node and emitted verbatim.
src/Proxy/Generator/ParameterGenerator.php Prefer parameter AST defaults when available; add explicit failure for Closure defaults without AST access.
CHANGELOG.md Add changelog entry documenting PHP 8.5+ FCC default value support.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/Proxy/Part/AbstractInterceptedPropertyGenerator.php Outdated
Comment thread src/Proxy/Generator/ParameterGenerator.php Outdated
Comment thread src/Proxy/Generator/ValueGenerator.php
Comment thread src/Proxy/Generator/PropertyGenerator.php
Comment thread src/Proxy/Generator/ParameterGenerator.php
- Remove unused Closure/LogicException imports from both source files
- Add ValueGeneratorTest::testFromExprNode for fromExprNode() factory
- Add PropertyGeneratorTest::testSetDefaultExpressionNode for Expr defaults
- Add ParameterGeneratorTest tests for AST-first default path and FCC defaults
- Add PHP 8.5-gated FCC stub file for parser-reflection FCC parameter test

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@lisachenko lisachenko changed the title feat: support PHP 8.5 first-class callable as default value for parameters and properties [Feature] support PHP 8.5 first-class callable as default value for parameters and properties May 8, 2026
@lisachenko lisachenko merged commit 8afdb58 into master May 8, 2026
5 checks passed
@lisachenko lisachenko deleted the feature/support-php85-fcc-default-values branch May 8, 2026 15:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Development

Successfully merging this pull request may close these issues.

2 participants