diff --git a/src/Target/Php70.php b/src/Target/Php70.php index 87316a9..c2401f9 100644 --- a/src/Target/Php70.php +++ b/src/Target/Php70.php @@ -12,7 +12,7 @@ use Phabel\Target\Php70\IssetExpressionFixer; use Phabel\Target\Php70\NestedExpressionFixer; use Phabel\Target\Php70\NullCoalesceReplacer; use Phabel\Target\Php70\ReservedNameReplacer; -use Phabel\Target\Php70\ScalarTypeHintsRemover; +use Phabel\Target\Php70\ScalarTypeHints; use Phabel\Target\Php70\SpaceshipOperatorReplacer; use Phabel\Target\Php70\StrictTypesDeclareStatementRemover; use Phabel\Target\Php70\ThrowableReplacer; @@ -42,7 +42,7 @@ class Php70 extends Plugin GroupUseReplacer::class, NullCoalesceReplacer::class, ReservedNameReplacer::class, - ScalarTypeHintsRemover::class, + ScalarTypeHints::class, SpaceshipOperatorReplacer::class, StrictTypesDeclareStatementRemover::class, ThrowableReplacer::class, diff --git a/src/Target/Php70/ScalarTypeHintsRemover.php b/src/Target/Php70/ScalarTypeHints.php similarity index 91% rename from src/Target/Php70/ScalarTypeHintsRemover.php rename to src/Target/Php70/ScalarTypeHints.php index d3e922b..304b004 100644 --- a/src/Target/Php70/ScalarTypeHintsRemover.php +++ b/src/Target/Php70/ScalarTypeHints.php @@ -9,7 +9,7 @@ use Phabel\Plugin\TypeHintStripper; * @author Daniil Gentili * @license MIT */ -class ScalarTypeHintsRemover extends Plugin +class ScalarTypeHints extends Plugin { /** * Alias. diff --git a/src/Target/Php71.php b/src/Target/Php71.php index dc2345d..ecfd4a8 100644 --- a/src/Target/Php71.php +++ b/src/Target/Php71.php @@ -6,6 +6,7 @@ use Phabel\Plugin; use Phabel\Target\Php71\ArrayList; use Phabel\Target\Php71\ClassConstantVisibilityModifiersRemover; use Phabel\Target\Php71\IssetExpressionFixer; +use Phabel\Target\Php71\IterableHint; use Phabel\Target\Php71\ListKey; use Phabel\Target\Php71\MultipleCatchReplacer; use Phabel\Target\Php71\NestedExpressionFixer; @@ -32,6 +33,7 @@ class Php71 extends Plugin ArrayList::class, ClassConstantVisibilityModifiersRemover::class, ListKey::class, + IterableHint::class, MultipleCatchReplacer::class, VoidReturnType::class, NullableType::class diff --git a/src/Target/Php71/IterableHint.php b/src/Target/Php71/IterableHint.php new file mode 100644 index 0000000..6e83695 --- /dev/null +++ b/src/Target/Php71/IterableHint.php @@ -0,0 +1,27 @@ + + * @license MIT + */ +class IterableHint extends Plugin +{ + /** + * Alias. + * + * @return array + */ + public static function runAfter(): array + { + return [ + TypeHintStripper::class => [ + 'types' => ['iterable'] + ] + ]; + } +} diff --git a/src/Target/Php73/ListReference.php b/src/Target/Php73/ListReference.php new file mode 100644 index 0000000..3d3cb0d --- /dev/null +++ b/src/Target/Php73/ListReference.php @@ -0,0 +1,95 @@ +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; + } +}