Skip to content

Commit 8feae1c

Browse files
committed
Implement support for partial unpacking
1 parent 443aefe commit 8feae1c

File tree

2 files changed

+27
-5
lines changed

2 files changed

+27
-5
lines changed

src/main/php/lang/ast/emit/RewriteCloneWith.class.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ protected function emitClone($result, $clone) {
1212
// Wrap clone with, e.g. clone($x, ['id' => 6100]), inside an IIFE which
1313
/// iterates over the property-value pairs, assigning them to the clone.
1414
if ($with) {
15-
$result->out->write('(function($c, array $a) { foreach ($a as $p=>$v) { $c->$p= $v; } return $c;})(clone ');
15+
$result->out->write('(function($object, array $withProperties) {');
16+
$result->out->write('foreach ($withProperties as $p=>$v) { $object->$p=$v; } return $object;})(clone ');
1617
$this->emitOne($result, $expr);
1718
$result->out->write(',');
1819
$this->emitOne($result, $with);
@@ -22,7 +23,7 @@ protected function emitClone($result, $clone) {
2223
$this->emitOne($result, $expr);
2324
} else if ($expr instanceof UnpackExpression) {
2425
$result->out->write('(function($u) { $c= clone $u["object"] ?? $u[0];');
25-
$result->out->write('foreach ($u["withProperties"] ?? $u[1] ?? [] as $p=>$v) { $c->$p= $v; } return $c;})(');
26+
$result->out->write('foreach ($u["withProperties"] ?? $u[1] ?? [] as $p=>$v) { $c->$p=$v; } return $c;})(');
2627
$this->emitOne($result, $expr->expression);
2728
$result->out->write(')');
2829
} else {

src/test/php/lang/ast/unittest/emit/CloningTest.class.php

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,12 +90,33 @@ public function run($in) { return '.$expression.'; }
9090
public function clone_unpack() {
9191
$clone= $this->run('class %T {
9292
public function run($in) {
93-
$args= ["object" => $in];
94-
return clone(...$args);
93+
return clone(...["object" => $in]);
9594
}
9695
}', $this->fixture);
9796

98-
Assert::true($clone instanceof $this->fixture && $this->fixture !== $clone);
97+
Assert::equals('<id: 2, name: Test>', $clone->toString());
98+
}
99+
100+
#[Test]
101+
public function clone_unpack_with_properties() {
102+
$clone= $this->run('class %T {
103+
public function run($in) {
104+
return clone(...["object" => $in, "withProperties" => ["name" => "Changed"]]);
105+
}
106+
}', $this->fixture);
107+
108+
Assert::equals('<id: 2, name: Changed>', $clone->toString());
109+
}
110+
111+
#[Test]
112+
public function clone_unpack_only_properties() {
113+
$clone= $this->run('class %T {
114+
public function run($in) {
115+
return clone($in, ...["withProperties" => ["name" => "Changed"]]);
116+
}
117+
}', $this->fixture);
118+
119+
Assert::equals('<id: 2, name: Changed>', $clone->toString());
99120
}
100121

101122
#[Test]

0 commit comments

Comments
 (0)