Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: no_useless_concat_operator - do not break variable #7827

Merged
35 changes: 35 additions & 0 deletions src/Fixer/Operator/NoUselessConcatOperatorFixer.php
Expand Up @@ -130,6 +130,10 @@ private function fixConcatOperation(Tokens $tokens, array $firstOperand, int $co
}

if (self::STR_DOUBLE_QUOTE_VAR === $firstOperand['type'] && self::STR_DOUBLE_QUOTE_VAR === $secondOperand['type']) {
if ($this->operandsCanNotBeMerged($tokens, $firstOperand, $secondOperand)) {
return;
}

$this->mergeConstantEscapedStringVarOperands($tokens, $firstOperand, $concatIndex, $secondOperand);

return;
Expand All @@ -146,6 +150,10 @@ private function fixConcatOperation(Tokens $tokens, array $firstOperand, int $co
[$operand1, $operand2] = $operandPair;

if (self::STR_DOUBLE_QUOTE_VAR === $operand1['type'] && self::STR_DOUBLE_QUOTE === $operand2['type']) {
if ($this->operandsCanNotBeMerged($tokens, $operand1, $operand2)) {
return;
}

$this->mergeConstantEscapedStringVarOperands($tokens, $firstOperand, $concatIndex, $secondOperand);

return;
Expand All @@ -169,6 +177,10 @@ private function fixConcatOperation(Tokens $tokens, array $firstOperand, int $co
$operantContent = $tokens[$operand2['start']]->getContent();

if ($this->isSimpleQuotedStringContent($operantContent)) {
if ($this->operandsCanNotBeMerged($tokens, $operand1, $operand2)) {
return;
}

$this->mergeConstantEscapedStringVarOperands($tokens, $firstOperand, $concatIndex, $secondOperand);
}

Expand Down Expand Up @@ -336,4 +348,27 @@ private function containsLinebreak(Tokens $tokens, int $startIndex, int $endInde

return false;
}

/**
* @param array{
julienfalque marked this conversation as resolved.
Show resolved Hide resolved
* start: int,
* end: int,
* type: self::STR_*,
* } $firstOperand
* @param array{
* start: int,
* end: int,
* type: self::STR_*,
* } $secondOperand
*/
private function operandsCanNotBeMerged(Tokens $tokens, array $firstOperand, array $secondOperand): bool
{
// If the first operand ends with a variable and the second operand does not start with a space,
// the variable in the first operand may be broken by the concatenation.

// example: "$param" . "hello" -> "$paramhello"

return $tokens[$firstOperand['end'] - 1]->isGivenKind(T_VARIABLE)
&& !str_starts_with($tokens[$secondOperand['start'] + 1]->getContent(), ' ');
julienfalque marked this conversation as resolved.
Show resolved Hide resolved
}
}
3 changes: 3 additions & 0 deletions tests/Fixer/Operator/NoUselessConcatOperatorFixerTest.php
Expand Up @@ -133,6 +133,9 @@ public static function provideFixCases(): iterable
$f201 = b"a".b"b";
$f203 = "a".B"b";
echo b"He drank some juice made of {$fruit}s.".b" Sliced the {$fruit}s.";
echo "abc $d" . "e $f";
julienfalque marked this conversation as resolved.
Show resolved Hide resolved
echo "abc $d" . "e";
echo "abc $d" . \'e\';
julienfalque marked this conversation as resolved.
Show resolved Hide resolved
',
];

Expand Down