From ef17dae32da3b57d417b93d298cae6074523df50 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Fri, 13 Feb 2026 19:31:57 +0700 Subject: [PATCH 1/3] [Php70] Keep right parentheses on TernaryToNullCoalescingRector --- .../Fixture/keep_right_parentheses.php.inc | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 rules-tests/Php70/Rector/Ternary/TernaryToNullCoalescingRector/Fixture/keep_right_parentheses.php.inc 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..8b0f9accfa6 --- /dev/null +++ b/rules-tests/Php70/Rector/Ternary/TernaryToNullCoalescingRector/Fixture/keep_right_parentheses.php.inc @@ -0,0 +1,27 @@ + +----- + From 668171d4ded6c4ba712e3908f7473e282588ddac Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Fri, 13 Feb 2026 12:33:52 +0000 Subject: [PATCH 2/3] [ci-review] Rector Rectify --- rules/Carbon/NodeFactory/CarbonCallFactory.php | 4 ++-- .../Rector/Catch_/CatchExceptionNameMatchingTypeRector.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) 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] ?? ''); From 9dc9fdf4a403d056edb069ec4065734aac30e72c Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Fri, 13 Feb 2026 19:45:30 +0700 Subject: [PATCH 3/3] Fix --- .../Fixture/keep_right_parentheses.php.inc | 4 +-- .../Ternary/TernaryToNullCoalescingRector.php | 36 +++++++++++++++++++ 2 files changed, 38 insertions(+), 2 deletions(-) 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 index 8b0f9accfa6..909fd0915f6 100644 --- 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 @@ -4,7 +4,7 @@ namespace Rector\Tests\Php70\Rector\Ternary\TernaryToNullCoalescingRector\Fixtur class KeepRightParentheses { - public function run() + public function run($port, $scheme) { $port = isset($port) ? $port : (($scheme == 'https') ? '443' : '80'); } @@ -18,7 +18,7 @@ namespace Rector\Tests\Php70\Rector\Ternary\TernaryToNullCoalescingRector\Fixtur class KeepRightParentheses { - public function run() + public function run($port, $scheme) { $port = $port ?? (($scheme == 'https') ? '443' : '80'); } 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)) {