diff --git a/rules-tests/Php70/Rector/Ternary/TernaryToNullCoalescingRector/Fixture/keep_right_parentheses.php.inc b/rules-tests/Php70/Rector/Ternary/TernaryToNullCoalescingRector/Fixture/keep_right_parentheses.php.inc new file mode 100644 index 00000000000..909fd0915f6 --- /dev/null +++ b/rules-tests/Php70/Rector/Ternary/TernaryToNullCoalescingRector/Fixture/keep_right_parentheses.php.inc @@ -0,0 +1,27 @@ + +----- + diff --git a/rules/Carbon/NodeFactory/CarbonCallFactory.php b/rules/Carbon/NodeFactory/CarbonCallFactory.php index f5c9c92f26c..3d0180a2ee2 100644 --- a/rules/Carbon/NodeFactory/CarbonCallFactory.php +++ b/rules/Carbon/NodeFactory/CarbonCallFactory.php @@ -37,8 +37,8 @@ public function createFromDateTimeString( $methodCall = $this->createModifyMethodCall( $carbonCall, new Int_((int) $match['count']), - (string) $match['unit'], - (string) $match['operator'] + $match['unit'], + $match['operator'] ); if ($methodCall instanceof MethodCall) { $carbonCall = $methodCall; diff --git a/rules/CodingStyle/Rector/Catch_/CatchExceptionNameMatchingTypeRector.php b/rules/CodingStyle/Rector/Catch_/CatchExceptionNameMatchingTypeRector.php index aefa965e17b..7864ddde1ca 100644 --- a/rules/CodingStyle/Rector/Catch_/CatchExceptionNameMatchingTypeRector.php +++ b/rules/CodingStyle/Rector/Catch_/CatchExceptionNameMatchingTypeRector.php @@ -170,7 +170,7 @@ private function resolveNewVariableName(string $typeShortName): string lcfirst($typeShortName), self::STARTS_WITH_ABBREVIATION_REGEX, static function (array $matches): string { - $output = isset($matches[1]) ? strtolower($matches[1]) : ''; + $output = isset($matches[1]) ? strtolower((string) $matches[1]) : ''; $output .= $matches[2] ?? ''; return $output . ($matches[3] ?? ''); diff --git a/rules/Php70/Rector/Ternary/TernaryToNullCoalescingRector.php b/rules/Php70/Rector/Ternary/TernaryToNullCoalescingRector.php index 2590a75baf2..5ff9d513d0a 100644 --- a/rules/Php70/Rector/Ternary/TernaryToNullCoalescingRector.php +++ b/rules/Php70/Rector/Ternary/TernaryToNullCoalescingRector.php @@ -11,8 +11,10 @@ use PhpParser\Node\Expr\BinaryOp\NotIdentical; use PhpParser\Node\Expr\Isset_; use PhpParser\Node\Expr\Ternary; +use Rector\NodeTypeResolver\Node\AttributeKey; use Rector\PhpParser\Node\Value\ValueResolver; use Rector\Rector\AbstractRector; +use Rector\ValueObject\Application\File; use Rector\ValueObject\PhpVersionFeature; use Rector\VersionBonding\Contract\MinPhpVersionInterface; use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; @@ -112,9 +114,43 @@ private function processTernaryWithIsset(Ternary $ternary, Isset_ $isset): ?Coal return null; } + if ($ternary->else instanceof Ternary && $this->isTernaryParenthesized($this->file, $ternary->cond, $ternary)) { + $ternary->else->setAttribute(AttributeKey::WRAPPED_IN_PARENTHESES, true); + } + return new Coalesce($ternary->if, $ternary->else); } + private function isTernaryParenthesized(File $file, Expr $expr, Ternary $ternary): bool + { + $oldTokens = $file->getOldTokens(); + $endTokenPost = $ternary->getEndTokenPos(); + + if (isset($oldTokens[$endTokenPost]) && (string) $oldTokens[$endTokenPost] === ')') { + $startTokenPos = $ternary->else->getStartTokenPos(); + $previousEndTokenPost = $expr->getEndTokenPos(); + + while ($startTokenPos > $previousEndTokenPost) { + --$startTokenPos; + + if (! isset($oldTokens[$startTokenPos])) { + return false; + } + + // handle space before open parentheses + if (trim((string) $oldTokens[$startTokenPos]) === '') { + continue; + } + + return (string) $oldTokens[$startTokenPos] === '('; + } + + return false; + } + + return false; + } + private function isNullMatch(Expr $possibleNullExpr, Expr $firstNode, Expr $secondNode): bool { if (! $this->valueResolver->isNull($possibleNullExpr)) {