Correctly handle ?-> in encapsed strings

Followup upstream change.
This commit is contained in:
Nikita Popov 2020-09-19 15:47:14 +02:00
parent c3e20d9970
commit 8505acd151
4 changed files with 52 additions and 14 deletions

View File

@ -22,15 +22,35 @@ final class NullsafeTokenEmulator extends TokenEmulator
// the tokens array on the way
$line = 1;
for ($i = 0, $c = count($tokens); $i < $c; ++$i) {
if (isset($tokens[$i + 1])) {
if ($tokens[$i] === '?' && $tokens[$i + 1][0] === \T_OBJECT_OPERATOR) {
array_splice($tokens, $i, 2, [
[\T_NULLSAFE_OBJECT_OPERATOR, '?->', $line]
]);
$c--;
continue;
}
if ($tokens[$i] === '?' && isset($tokens[$i + 1]) && $tokens[$i + 1][0] === \T_OBJECT_OPERATOR) {
array_splice($tokens, $i, 2, [
[\T_NULLSAFE_OBJECT_OPERATOR, '?->', $line]
]);
$c--;
continue;
}
// Handle ?-> inside encapsed string.
if ($tokens[$i][0] === \T_ENCAPSED_AND_WHITESPACE && isset($tokens[$i - 1])
&& $tokens[$i - 1][0] === \T_VARIABLE
&& preg_match('/^\?->([a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*)/', $tokens[$i][1], $matches)
) {
$replacement = [
[\T_NULLSAFE_OBJECT_OPERATOR, '?->', $line],
[\T_STRING, $matches[1], $line],
];
if (\strlen($matches[0]) !== \strlen($tokens[$i][1])) {
$replacement[] = [
\T_ENCAPSED_AND_WHITESPACE,
\substr($tokens[$i][1], \strlen($matches[0])),
$line
];
}
array_splice($tokens, $i, 1, $replacement);
$c += \count($replacement) - 1;
continue;
}
if (\is_array($tokens[$i])) {
$line += substr_count($tokens[$i][1], "\n");
}

View File

@ -320,6 +320,22 @@ class EmulativeTest extends LexerTest
['7.4', 'match', [[Tokens::T_STRING, 'match']]],
['7.4', 'fn', [[Tokens::T_FN, 'fn']]],
['7.3', 'fn', [[Tokens::T_STRING, 'fn']]],
// Tested here to skip testLeaveStuffAloneInStrings.
['8.0', '"$foo?->bar"', [
[ord('"'), '"'],
[Tokens::T_VARIABLE, '$foo'],
[Tokens::T_NULLSAFE_OBJECT_OPERATOR, '?->'],
[Tokens::T_STRING, 'bar'],
[ord('"'), '"'],
]],
['8.0', '"$foo?->bar baz"', [
[ord('"'), '"'],
[Tokens::T_VARIABLE, '$foo'],
[Tokens::T_NULLSAFE_OBJECT_OPERATOR, '?->'],
[Tokens::T_STRING, 'bar'],
[Tokens::T_ENCAPSED_AND_WHITESPACE, ' baz'],
[ord('"'), '"'],
]],
];
}
}

View File

@ -71,11 +71,13 @@ array(
4: Stmt_Expression(
expr: Scalar_Encapsed(
parts: array(
0: Expr_Variable(
name: a
)
1: Scalar_EncapsedStringPart(
value: ?->b
0: Expr_NullsafePropertyFetch(
var: Expr_Variable(
name: a
)
name: Identifier(
name: b
)
)
)
)

View File

@ -19,4 +19,4 @@ $a?->b($c)?->d;
$a?->b($c)();
new $a?->b();
"{$a?->b}";
"{$a}?->b";
"{$a?->b}";