Start implementing list references
This commit is contained in:
parent
1265dd87ff
commit
2cb2f73898
|
@ -12,7 +12,7 @@ use Phabel\Target\Php70\IssetExpressionFixer;
|
||||||
use Phabel\Target\Php70\NestedExpressionFixer;
|
use Phabel\Target\Php70\NestedExpressionFixer;
|
||||||
use Phabel\Target\Php70\NullCoalesceReplacer;
|
use Phabel\Target\Php70\NullCoalesceReplacer;
|
||||||
use Phabel\Target\Php70\ReservedNameReplacer;
|
use Phabel\Target\Php70\ReservedNameReplacer;
|
||||||
use Phabel\Target\Php70\ScalarTypeHintsRemover;
|
use Phabel\Target\Php70\ScalarTypeHints;
|
||||||
use Phabel\Target\Php70\SpaceshipOperatorReplacer;
|
use Phabel\Target\Php70\SpaceshipOperatorReplacer;
|
||||||
use Phabel\Target\Php70\StrictTypesDeclareStatementRemover;
|
use Phabel\Target\Php70\StrictTypesDeclareStatementRemover;
|
||||||
use Phabel\Target\Php70\ThrowableReplacer;
|
use Phabel\Target\Php70\ThrowableReplacer;
|
||||||
|
@ -42,7 +42,7 @@ class Php70 extends Plugin
|
||||||
GroupUseReplacer::class,
|
GroupUseReplacer::class,
|
||||||
NullCoalesceReplacer::class,
|
NullCoalesceReplacer::class,
|
||||||
ReservedNameReplacer::class,
|
ReservedNameReplacer::class,
|
||||||
ScalarTypeHintsRemover::class,
|
ScalarTypeHints::class,
|
||||||
SpaceshipOperatorReplacer::class,
|
SpaceshipOperatorReplacer::class,
|
||||||
StrictTypesDeclareStatementRemover::class,
|
StrictTypesDeclareStatementRemover::class,
|
||||||
ThrowableReplacer::class,
|
ThrowableReplacer::class,
|
||||||
|
|
|
@ -9,7 +9,7 @@ use Phabel\Plugin\TypeHintStripper;
|
||||||
* @author Daniil Gentili <daniil@daniil.it>
|
* @author Daniil Gentili <daniil@daniil.it>
|
||||||
* @license MIT
|
* @license MIT
|
||||||
*/
|
*/
|
||||||
class ScalarTypeHintsRemover extends Plugin
|
class ScalarTypeHints extends Plugin
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Alias.
|
* Alias.
|
|
@ -6,6 +6,7 @@ use Phabel\Plugin;
|
||||||
use Phabel\Target\Php71\ArrayList;
|
use Phabel\Target\Php71\ArrayList;
|
||||||
use Phabel\Target\Php71\ClassConstantVisibilityModifiersRemover;
|
use Phabel\Target\Php71\ClassConstantVisibilityModifiersRemover;
|
||||||
use Phabel\Target\Php71\IssetExpressionFixer;
|
use Phabel\Target\Php71\IssetExpressionFixer;
|
||||||
|
use Phabel\Target\Php71\IterableHint;
|
||||||
use Phabel\Target\Php71\ListKey;
|
use Phabel\Target\Php71\ListKey;
|
||||||
use Phabel\Target\Php71\MultipleCatchReplacer;
|
use Phabel\Target\Php71\MultipleCatchReplacer;
|
||||||
use Phabel\Target\Php71\NestedExpressionFixer;
|
use Phabel\Target\Php71\NestedExpressionFixer;
|
||||||
|
@ -32,6 +33,7 @@ class Php71 extends Plugin
|
||||||
ArrayList::class,
|
ArrayList::class,
|
||||||
ClassConstantVisibilityModifiersRemover::class,
|
ClassConstantVisibilityModifiersRemover::class,
|
||||||
ListKey::class,
|
ListKey::class,
|
||||||
|
IterableHint::class,
|
||||||
MultipleCatchReplacer::class,
|
MultipleCatchReplacer::class,
|
||||||
VoidReturnType::class,
|
VoidReturnType::class,
|
||||||
NullableType::class
|
NullableType::class
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Phabel\Target\Php71;
|
||||||
|
|
||||||
|
use Phabel\Plugin;
|
||||||
|
use Phabel\Plugin\TypeHintStripper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Daniil Gentili <daniil@daniil.it>
|
||||||
|
* @license MIT
|
||||||
|
*/
|
||||||
|
class IterableHint extends Plugin
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Alias.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public static function runAfter(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
TypeHintStripper::class => [
|
||||||
|
'types' => ['iterable']
|
||||||
|
]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,95 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Phabel\Target\Php73;
|
||||||
|
|
||||||
|
use Phabel\Context;
|
||||||
|
use Phabel\Plugin;
|
||||||
|
use PhpParser\Node\Expr\Array_;
|
||||||
|
use PhpParser\Node\Expr\ArrayDimFetch;
|
||||||
|
use PhpParser\Node\Expr\Assign;
|
||||||
|
use PhpParser\Node\Expr\AssignRef;
|
||||||
|
use PhpParser\Node\Expr\List_;
|
||||||
|
use PhpParser\Node\Expr\Variable;
|
||||||
|
use PhpParser\Node\Stmt\Foreach_;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Polyfills list assignment by reference.
|
||||||
|
*/
|
||||||
|
class ListReference extends Plugin
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Parse list foreach with custom keys.
|
||||||
|
*
|
||||||
|
* @param Foreach_ $node Foreach
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function enterForeach(Foreach_ $node, Context $ctx): void
|
||||||
|
{
|
||||||
|
if (!($node->valueVar instanceof List_ || $node->valueVar instanceof Array_) || !$this->shouldSplit($node->valueVar)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$list = $node->valueVar;
|
||||||
|
$var = $node->valueVar = $ctx->getVariable();
|
||||||
|
$assignments = self::splitList($list, $var);
|
||||||
|
$node->stmts
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Parse list assignment with custom keys.
|
||||||
|
*
|
||||||
|
* @param Assign $node List assignment
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function enterAssign(Assign $node, Context $ctx): void
|
||||||
|
{
|
||||||
|
if (!($node->var instanceof List_ || $node->var instanceof Array_) || !$this->shouldSplit($node->var)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
[$node->var, $array] = $this->splitList($node->var, $ctx);
|
||||||
|
$node->expr = self::callPoly('destructure', $array, $node->expr);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Split referenced list into multiple assignments.
|
||||||
|
*
|
||||||
|
* @param Array_|List_ $list List
|
||||||
|
* @param Variable $var Variable
|
||||||
|
*
|
||||||
|
* @return (Assign|AssignRef)[]
|
||||||
|
*/
|
||||||
|
private static function splitList($list, Variable $var): array
|
||||||
|
{
|
||||||
|
$assignments = [];
|
||||||
|
$key = 0; // Technically a list assignment does not support mixed keys, but we need this for nested assignments
|
||||||
|
foreach ($list->items as $item) {
|
||||||
|
if (!$item) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$curKey = $item->key ?? $key++;
|
||||||
|
if ($item->value instanceof List_ || $item->value instanceof Array_) {
|
||||||
|
// Do nothing, will re-split later if needed
|
||||||
|
} else if ($item->byRef) {
|
||||||
|
$assignments []= new AssignRef($item->value, new ArrayDimFetch($var, $curKey));
|
||||||
|
} else {
|
||||||
|
$assignments []= new Assign($item->value, new ArrayDimFetch($var, $curKey));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $assignments;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Whether this is a referenced list.
|
||||||
|
*
|
||||||
|
* @param List_|Array_ $list List
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
private function shouldSplit($list): bool
|
||||||
|
{
|
||||||
|
foreach ($list->items ?? [] as $item) {
|
||||||
|
if ($item->byRef) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue