Skip to content
Permalink
Browse files

Added optional chaining for $var->elem?[1]

  • Loading branch information
dg committed Dec 20, 2019
1 parent 135535f commit 04263b80eb85ee97795585c0fbf47ed699250421
@@ -298,14 +298,14 @@ public function optionalChainingPass(MacroTokens $tokens): MacroTokens

do {
if ($tokens->nextToken('?')) {
if ($tokens->isNext() && (!$tokens->isNext($tokens::T_CHAR) || $tokens->isNext('(', '[', '{', ':', '!', '@', '\\'))) { // is it ternary operator?
if ($tokens->isNext() && (!$tokens->isNext($tokens::T_CHAR) || $tokens->isNext('(', '{', ':', '!', '@', '\\'))) { // is it ternary operator?
$expr->append($addBraces . ' ?');
break;
}

$rescue = [$res->tokens, $expr->tokens, $tokens->position, $addBraces];

if (!$tokens->isNext('->')) {
if (!$tokens->isNext('->', '[')) {
$expr->prepend('(');
$expr->append(' ?? null)' . $addBraces);
break;
@@ -141,6 +141,7 @@ test(function () { // optionalChainingPass
Assert::same('$a', formatArgs('$a'));
Assert::same('($a ?? null)', formatArgs('$a?'));
Assert::same('(($a ?? null))', formatArgs('($a?)'));
Assert::same('(($_tmp = $foo ?? null) === null ? null : $_tmp[1])', formatArgs('$foo?[1]'));
Assert::same('$var->prop->elem[1]->call(2)->item', formatArgs('$var->prop->elem[1]->call(2)->item'));
Assert::same('(($_tmp = $var ?? null) === null ? null : (($_tmp = $_tmp->prop ?? null) === null ? null : (($_tmp = $_tmp->elem[1] ?? null) === null ? null : (($_tmp = $_tmp->call(2) ?? null) === null ? null : ($_tmp->item ?? null)))))', formatArgs('$var?->prop?->elem[1]?->call(2)?->item?'));
});
@@ -70,6 +70,7 @@ test(function () { // depth
test(function () { // optionalChainingPass
Assert::same('($this->filters->mod)(@, ($a ?? null))', formatModifiers('@', 'mod:$a?'));
Assert::same('($this->filters->mod)(@, (($a ?? null)))', formatModifiers('@', 'mod:($a?)'));
Assert::same('($this->filters->mod)(@, (($_tmp = $foo ?? null) === null ? null : $_tmp[1]))', formatModifiers('@', 'mod:$foo?[1]'));
Assert::same('($this->filters->mod)(@, (($_tmp = $var ?? null) === null ? null : (($_tmp = $_tmp->prop ?? null) === null ? null : (($_tmp = $_tmp->elem[1] ?? null) === null ? null : (($_tmp = $_tmp->call(2) ?? null) === null ? null : ($_tmp->item ?? null))))))', formatModifiers('@', 'mod:$var?->prop?->elem[1]?->call(2)?->item?'));
});

@@ -22,8 +22,15 @@ test(function () {
Assert::same('($a ?? null)', optionalChaining('$a?'));
Assert::same('(($a ?? null))', optionalChaining('($a?)'));
Assert::same('a?', optionalChaining('a?'));
Assert::same('(($_tmp = $foo ?? null) === null ? null : $_tmp[1])', optionalChaining('$foo?[1]'));
Assert::same('($foo[1] ?? null)', optionalChaining('$foo[1]?'));
Assert::same('(($_tmp = $foo ?? null) === null ? null : ($_tmp[1] ?? null))', optionalChaining('$foo?[1]?'));
Assert::same('(($_tmp = $foo ?? null) === null ? null : ($_tmp[1] ?? null)) + 10', optionalChaining('$foo?[1]? + 10'));
Assert::same('(($foo[1] ?? null))', optionalChaining('($foo[1]?)'));
Assert::same('((($_tmp = $foo ?? null) === null ? null : $_tmp[1]))', optionalChaining('($foo?[1])'));
Assert::same('[(($_tmp = $foo ?? null) === null ? null : ($_tmp[1] ?? null))]', optionalChaining('[$foo?[1]?]'));
Assert::same('(($_tmp = $foo ?? null) === null ? null : ($_tmp[ ($a ?? null) ] ?? null))', optionalChaining('$foo?[ $a? ]?'));
Assert::same('(($_tmp = $foo ?? null) === null ? null : ($_tmp[ (($_tmp = $a ?? null) === null ? null : ($_tmp[2] ?? null)) ] ?? null))', optionalChaining('$foo?[ $a?[2]? ]?'));

Assert::same('(($_tmp = $foo ?? null) === null ? null : $_tmp->prop)', optionalChaining('$foo?->prop'));
Assert::same('($foo->prop ?? null)', optionalChaining('$foo->prop?'));
@@ -50,17 +57,20 @@ test(function () {
Assert::same('$var->prop->elem[1]->call(2)->item', optionalChaining('$var->prop->elem[1]->call(2)->item'));
Assert::same('(($_tmp = $var ?? null) === null ? null : $_tmp->prop->elem[1]->call(2)->item)', optionalChaining('$var?->prop->elem[1]->call(2)->item'));
Assert::same('(($_tmp = $var->prop ?? null) === null ? null : $_tmp->elem[1]->call(2)->item)', optionalChaining('$var->prop?->elem[1]->call(2)->item'));
Assert::same('(($_tmp = $var->prop->elem ?? null) === null ? null : $_tmp[1]->call(2)->item)', optionalChaining('$var->prop->elem?[1]->call(2)->item'));
Assert::same('(($_tmp = $var->prop->elem[1] ?? null) === null ? null : $_tmp->call(2)->item)', optionalChaining('$var->prop->elem[1]?->call(2)->item'));
Assert::same('(($_tmp = $var->prop->elem[1]->call(2) ?? null) === null ? null : $_tmp->item)', optionalChaining('$var->prop->elem[1]->call(2)?->item'));
Assert::same('($var->prop->elem[1]->call(2)->item ?? null)', optionalChaining('$var->prop->elem[1]->call(2)->item?'));
Assert::same(
'(($_tmp = $var ?? null) === null ? null : (($_tmp = $_tmp->prop ?? null) === null ? null : (($_tmp = $_tmp->elem ?? null) === null ? null : (($_tmp = $_tmp[1] ?? null) === null ? null : (($_tmp = $_tmp->call(2) ?? null) === null ? null : ($_tmp->item ?? null))))))',
optionalChaining('$var?->prop?->elem?[1]?->call(2)?->item?')
);
});


test(function () { // not allowed
Assert::same('$foo ?(hello)', optionalChaining('$foo?(hello)'));
Assert::same('$foo->foo ?(hello)', optionalChaining('$foo->foo?(hello)'));

Assert::same('$foo ?[1]', optionalChaining('$foo?[1]')); // not allowed due to collision with short ternary
});


0 comments on commit 04263b8

Please sign in to comment.
You can’t perform that action at this time.