diff --git a/rules/DowngradePhp74/Rector/LNumber/DowngradeNumericLiteralSeparatorRector.php b/rules/DowngradePhp74/Rector/LNumber/DowngradeNumericLiteralSeparatorRector.php index b5d006cac32..bfd8ae97437 100644 --- a/rules/DowngradePhp74/Rector/LNumber/DowngradeNumericLiteralSeparatorRector.php +++ b/rules/DowngradePhp74/Rector/LNumber/DowngradeNumericLiteralSeparatorRector.php @@ -64,17 +64,21 @@ public function getNodeTypes(): array */ public function refactor(Node $node): ?Node { - if (! $this->shouldRefactor($node)) { + if ($this->shouldSkip($node)) { return null; } - $numberNode = clone $node; - $numberNodeValue = (string) $numberNode->value; - if (\str_contains($numberNodeValue, '+')) { + $numberValueAsString = (string) $node->value; + if (\str_contains($numberValueAsString, '+')) { return null; } - $node->value = (string) $node->value; + // trigger reprint + $node->setAttribute(AttributeKey::ORIGINAL_NODE, null); + + if ($node instanceof LNumber) { + return $node; + } /** * This code follows a guess, to avoid modifying floats needlessly. @@ -83,24 +87,33 @@ public function refactor(Node $node): ?Node * by adding ".0" at the end (eg: 0.0). * Then, add it again. */ - if ($node instanceof DNumber && ! \str_contains($node->value, '.')) { - $node->value .= '.0'; + if (! \str_contains($numberValueAsString, '.')) { + $numberValueAsString .= '.0'; } - if (! str_contains($node->value, '_')) { - return null; - } + $node->value = (float) $numberValueAsString; return $node; } - public function shouldRefactor(LNumber | DNumber $node): bool + private function shouldSkip(LNumber | DNumber $node): bool { // "_" notation can be applied to decimal numbers only if ($node instanceof LNumber) { - return $node->getAttribute(AttributeKey::KIND) === LNumber::KIND_DEC; + $numberKind = $node->getAttribute(AttributeKey::KIND); + if ($numberKind !== LNumber::KIND_DEC) { + return true; + } + } + + // we have to hack around tokens to get original value, see https://github.com/nikic/PHP-Parser/pull/832 + $oldTokens = $this->file->getOldTokens(); + $tokenValue = $oldTokens[$node->getStartTokenPos()][1] ?? null; + + if ($tokenValue === null) { + return true; } - return true; + return ! str_contains((string) $tokenValue, '_'); } } diff --git a/src/Rector/AbstractRector.php b/src/Rector/AbstractRector.php index 93f6af6db0a..76eb50dad02 100644 --- a/src/Rector/AbstractRector.php +++ b/src/Rector/AbstractRector.php @@ -21,6 +21,7 @@ use Rector\ChangesReporting\ValueObject\RectorWithLineChange; use Rector\Core\Application\ChangedNodeScopeRefresher; use Rector\Core\Configuration\CurrentNodeProvider; +use Rector\Core\Console\Output\RectorOutputStyle; use Rector\Core\Contract\Rector\PhpRectorInterface; use Rector\Core\Exception\ShouldNotHappenException; use Rector\Core\Exclusion\ExclusionManager; @@ -123,6 +124,8 @@ abstract class AbstractRector extends NodeVisitorAbstract implements PhpRectorIn private UnreachableStmtAnalyzer $unreachableStmtAnalyzer; + private RectorOutputStyle $rectorOutputStyle; + #[Required] public function autowire( NodesToRemoveCollector $nodesToRemoveCollector, @@ -145,7 +148,8 @@ public function autowire( RectifiedAnalyzer $rectifiedAnalyzer, CreatedByRuleDecorator $createdByRuleDecorator, ChangedNodeScopeRefresher $changedNodeScopeRefresher, - UnreachableStmtAnalyzer $unreachableStmtAnalyzer + UnreachableStmtAnalyzer $unreachableStmtAnalyzer, + RectorOutputStyle $rectorOutputStyle, ): void { $this->nodesToRemoveCollector = $nodesToRemoveCollector; $this->nodesToAddCollector = $nodesToAddCollector; @@ -168,6 +172,7 @@ public function autowire( $this->createdByRuleDecorator = $createdByRuleDecorator; $this->changedNodeScopeRefresher = $changedNodeScopeRefresher; $this->unreachableStmtAnalyzer = $unreachableStmtAnalyzer; + $this->rectorOutputStyle = $rectorOutputStyle; } /** @@ -216,6 +221,8 @@ final public function enterNode(Node $node) $originalAttributes = $node->getAttributes(); + $this->printDebugCurrentFileAndRule(); + $node = $this->refactor($node); // nothing to change → continue @@ -435,4 +442,15 @@ private function connectParentNodes(Node $node): void $nodeTraverser->addVisitor(new ParentConnectingVisitor()); $nodeTraverser->traverse([$node]); } + + private function printDebugCurrentFileAndRule(): void + { + if (! $this->rectorOutputStyle->isDebug()) { + return; + } + + $this->rectorOutputStyle->writeln('[file] ' . $this->file->getRelativeFilePath()); + $this->rectorOutputStyle->writeln('[rule] ' . static::class); + $this->rectorOutputStyle->newLine(1); + } }