在字符串拼接中,除了第一个元素之外,剩下的字符串如果出现空字符串,忽略这个字符串 #19

Merged
韩天峰 merged 3 commits from concat_empty_string into master 1 month ago
  1. 9
      phpunit/src/SsaAnalysisTest.php
  2. 3
      src/CompilerBase.php
  3. 7
      src/Parser/BinaryOpTrait.php
  4. 33
      tests/compiler/concat_empty.phpt

@ -1263,6 +1263,15 @@ class SsaAnalysisTest extends TestCase
}
}
public function testDetectTypeOfConcatExpressions(): void
{
$concat = new Expr\BinaryOp\Concat(new Scalar\LNumber(1), new Scalar\String_(''));
$concatAssign = new Expr\AssignOp\Concat(new Expr\Variable('value'), new Scalar\LNumber(2));
$this->assertSame(Type::STR, $this->invoke('detectTypeOfExpr', $concat));
$this->assertSame(Type::STR, $this->invoke('detectTypeOfExpr', $concatAssign));
}
public function testDetectSsaDefTypeNull(): void
{
$ssaVar = new SsaVar(1, 'x');

@ -2299,6 +2299,9 @@ class CompilerBase implements PropertyAccessContext
case 'Expr_Array':
case 'Expr_Cast_Array':
return Type::ARRAY;
case 'Expr_BinaryOp_Concat':
case 'Expr_AssignOp_Concat':
return Type::STR;
case 'Expr_BinaryOp_Plus':
case 'Expr_BinaryOp_Minus':
case 'Expr_BinaryOp_Mul':

@ -265,6 +265,13 @@ trait BinaryOpTrait
$argList = $prefixExpressions;
foreach ($items as $item) {
// Keep one operand so concat still performs PHP string coercion.
// Prefix expressions are operands too (for example, the left-hand
// value of `.=`), so an empty RHS literal can be omitted there.
if ($argList !== [] && $this->isScalarString($item) && $item->value === '') {
continue;
}
$type = $this->detectTypeOfExpr($item);
$parsed = $this->parseExprAsValue($item);
$argList[] = $this->prepareConcatOperand($parsed, $type);

@ -0,0 +1,33 @@
--TEST--
Concat empty strings
--FILE--
<?php
function main() {
var_dump('' . 1 . '' . 'a' . '');
var_dump('' . 1);
var_dump(1 . '');
var_dump(false . '');
var_dump('' . '' . '');
$value = 'value';
var_dump('' . $value . '');
var_dump('' . get_value() . '');
$number = 1;
$number .= '';
var_dump($number);
}
function get_value(): string {
return 'called';
}
?>
--EXPECT--
string(2) "1a"
string(1) "1"
string(1) "1"
string(0) ""
string(0) ""
string(5) "value"
string(6) "called"
string(1) "1"
Loading…
Cancel
Save