From 6bada3c03798377fd4aef41a997008c4915faac2 Mon Sep 17 00:00:00 2001 From: Timm Friebe Date: Sun, 5 Jul 2026 19:38:26 +0200 Subject: [PATCH 1/2] Support primary constructors --- .../emit/ArgumentPromotionTest.class.php | 97 ++++++++++++++++++- 1 file changed, 94 insertions(+), 3 deletions(-) diff --git a/src/test/php/lang/ast/unittest/emit/ArgumentPromotionTest.class.php b/src/test/php/lang/ast/unittest/emit/ArgumentPromotionTest.class.php index 6ac984a2..c1e86be2 100755 --- a/src/test/php/lang/ast/unittest/emit/ArgumentPromotionTest.class.php +++ b/src/test/php/lang/ast/unittest/emit/ArgumentPromotionTest.class.php @@ -156,7 +156,7 @@ public function __construct(public final string $name) { } #[Test] public function promoted_property_hook() { - $c= $this->declare('class %T { + $t= $this->declare('class %T { public function __construct( public private(set) float $celsius= 100 { set { @@ -169,7 +169,98 @@ public function __construct( ) { } }'); - Assert::equals(0.0, $c->newInstance(0.0)->celsius); - Assert::throws(InvocationFailed::class, fn() => $c->newInstance(-300.0)); + Assert::equals(0.0, $t->newInstance(0.0)->celsius); + Assert::throws(InvocationFailed::class, fn() => $t->newInstance(-300.0)); + } + + #[Test] + public function primary_constructors() { + $t= $this->declare('class %T(public int $x, public int $y) { + public function coordinates() { + return [$this->x, $this->y]; + } + }'); + + Assert::equals([14, 12], $t->newInstance(14, 12)->coordinates()); + } + + #[Test] + public function primary_constructor_with_parent() { + $b= $this->declare('class %T { + public $invoked= 0; + public function __construct($invoked= 1) { $this->invoked+= $invoked; } + }'); + $i= $this->declare('class %T(public string $name) extends '.$b->literal().' { }')->newInstance('admin'); + + Assert::equals(0, $i->invoked); + Assert::equals('admin', $i->name); + } + + #[Test] + public function primary_constructor_invoking_parent() { + $b= $this->declare('class %T { + public $invoked= 0; + public function __construct($invoked= 1) { $this->invoked+= $invoked; } + }'); + $i= $this->declare('class %T(public string $name) extends '.$b->literal().'() { }')->newInstance('admin'); + + Assert::equals(1, $i->invoked); + Assert::equals('admin', $i->name); + } + + #[Test] + public function primary_constructor_passing_value_to_parent() { + $b= $this->declare('class %T { + public $invoked= 0; + public function __construct($invoked= 1) { $this->invoked+= $invoked; } + }'); + $i= $this->declare('class %T(public string $name) extends '.$b->literal().'(2) { }')->newInstance('admin'); + + Assert::equals(2, $i->invoked); + Assert::equals('admin', $i->name); + } + + #[Test] + public function primary_constructor_passing_param_to_parent() { + $b= $this->declare('class %T { + public $invoked= 0; + public function __construct($invoked= 1) { $this->invoked+= $invoked; } + }'); + $i= $this->declare('class %T(public string $name, $i= 2) extends '.$b->literal().'($i) { }')->newInstance('admin'); + + Assert::equals(2, $i->invoked); + Assert::equals('admin', $i->name); + } + + #[Test] + public function primary_constructor_with_hooks() { + $t= $this->declare('class %T( + public private(set) float $celsius { + set { + if ($value < -273.15) { + throw new \lang\IllegalArgumentException("below absolute zero"); + } + $this->celsius = $value; + } + } + ) { }'); + + Assert::equals(0.0, $t->newInstance(0.0)->celsius); + Assert::throws(InvocationFailed::class, fn() => $t->newInstance(-300.0)); + } + + #[Test] + public function primary_constructor_doc_comment() { + $t= $this->declare('/** Test */ class %T(public string $name) { }'); + + Assert::equals('Test', $t->comment()); + Assert::equals('Test', $t->constructor()->comment()); + } + + #[Test] + public function primary_constructor_param_annotations() { + $t= $this->declare('class %T(#[Inject] public string $name) { }'); + + Assert::true($t->constructor()->parameter('name')->annotations()->provides('Inject')); } } \ No newline at end of file From 17d10dfb6f70204ecc1d59a9ab3adfd10a6a08ca Mon Sep 17 00:00:00 2001 From: Timm Friebe Date: Sun, 5 Jul 2026 19:39:31 +0200 Subject: [PATCH 2/2] Bump dependency to AST library feature branch --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 94ca42cf..6c62385d 100755 --- a/composer.json +++ b/composer.json @@ -8,7 +8,7 @@ "require" : { "xp-framework/core": "^12.0 | ^11.6 | ^10.16", "xp-framework/reflection": "^3.2 | ^2.15", - "xp-framework/ast": "^13.0 | ^12.2", + "xp-framework/ast": "dev-feature/primary-constructors as 13.1.0", "php" : ">=7.4.0" }, "require-dev" : {