diff --git a/.phpstorm.meta.php b/.phpstorm.meta.php index 7d4b46d7425..89bfac1a231 100644 --- a/.phpstorm.meta.php +++ b/.phpstorm.meta.php @@ -60,6 +60,7 @@ expectedArguments( \Rector\NodeTypeResolver\Node\AttributeKey::VIRTUAL_NODE, \Rector\NodeTypeResolver\Node\AttributeKey::PARAMETER_POSITION, \Rector\NodeTypeResolver\Node\AttributeKey::ARGUMENT_POSITION, + \Rector\NodeTypeResolver\Node\AttributeKey::RAW_VALUE, ); expectedArguments( @@ -79,4 +80,5 @@ expectedArguments( \Rector\NodeTypeResolver\Node\AttributeKey::VIRTUAL_NODE, \Rector\NodeTypeResolver\Node\AttributeKey::PARAMETER_POSITION, \Rector\NodeTypeResolver\Node\AttributeKey::ARGUMENT_POSITION, + \Rector\NodeTypeResolver\Node\AttributeKey::RAW_VALUE, ); diff --git a/composer.json b/composer.json index 69a620f6360..e1b33896685 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,7 @@ "composer/xdebug-handler": "^3.0", "doctrine/inflector": "^2.0", "nette/utils": "^3.2.7", - "nikic/php-parser": "^4.13.2", + "nikic/php-parser": "^4.14.0", "ondram/ci-detector": "^4.1", "phpstan/phpdoc-parser": "^1.5.1", "phpstan/phpstan": "^1.7.6", diff --git a/packages/NodeTypeResolver/Node/AttributeKey.php b/packages/NodeTypeResolver/Node/AttributeKey.php index 5fab3c94491..7c227dcdcc2 100644 --- a/packages/NodeTypeResolver/Node/AttributeKey.php +++ b/packages/NodeTypeResolver/Node/AttributeKey.php @@ -9,6 +9,12 @@ namespace Rector\NodeTypeResolver\Node; */ final class AttributeKey { + /** + * Internal php-parser key for String_, LNumber and DNumber nodes to hold original value (with "_" separators etc.) + * @var string + */ + public const RAW_VALUE = 'rawValue'; + /** * @var string */ @@ -103,14 +109,6 @@ final class AttributeKey */ public const DOC_INDENTATION = 'docIndentation'; - /** - * Internal php-parser name. - * Do not change this even if you want! - * - * @var string - */ - public const START_TOKEN_POSITION = 'startTokenPos'; - /** * @var string * Use often in php-parser diff --git a/rules-tests/DowngradePhp74/Rector/LNumber/DowngradeNumericLiteralSeparatorRector/Fixture/fixture.php.inc b/rules-tests/DowngradePhp74/Rector/LNumber/DowngradeNumericLiteralSeparatorRector/Fixture/downgrade_floats.php.inc similarity index 77% rename from rules-tests/DowngradePhp74/Rector/LNumber/DowngradeNumericLiteralSeparatorRector/Fixture/fixture.php.inc rename to rules-tests/DowngradePhp74/Rector/LNumber/DowngradeNumericLiteralSeparatorRector/Fixture/downgrade_floats.php.inc index 93c4790bd59..d1eb6db5fb0 100644 --- a/rules-tests/DowngradePhp74/Rector/LNumber/DowngradeNumericLiteralSeparatorRector/Fixture/fixture.php.inc +++ b/rules-tests/DowngradePhp74/Rector/LNumber/DowngradeNumericLiteralSeparatorRector/Fixture/downgrade_floats.php.inc @@ -2,13 +2,11 @@ namespace Rector\Tests\DowngradePhp74\Rector\LNumber\DowngradeNumericLiteralSeparatorRector\Fixture; -class Fixture +final class DowngradeFloats { public function run() { - $int = 1_000; $float = 1_000_500.001; - $negative_int = -1_000; $negative_float = -1_000_500.001; } } @@ -19,13 +17,11 @@ class Fixture namespace Rector\Tests\DowngradePhp74\Rector\LNumber\DowngradeNumericLiteralSeparatorRector\Fixture; -class Fixture +final class DowngradeFloats { public function run() { - $int = 1000; $float = 1000500.001; - $negative_int = -1000; $negative_float = -1000500.001; } } diff --git a/rules-tests/DowngradePhp74/Rector/LNumber/DowngradeNumericLiteralSeparatorRector/Fixture/downgrade_integers.php.inc b/rules-tests/DowngradePhp74/Rector/LNumber/DowngradeNumericLiteralSeparatorRector/Fixture/downgrade_integers.php.inc new file mode 100644 index 00000000000..05e6347d8f6 --- /dev/null +++ b/rules-tests/DowngradePhp74/Rector/LNumber/DowngradeNumericLiteralSeparatorRector/Fixture/downgrade_integers.php.inc @@ -0,0 +1,29 @@ + +----- + diff --git a/rules/DeadCode/NodeCollector/NodeByTypeAndPositionCollector.php b/rules/DeadCode/NodeCollector/NodeByTypeAndPositionCollector.php index b34cfa240a8..3e4faf8081f 100644 --- a/rules/DeadCode/NodeCollector/NodeByTypeAndPositionCollector.php +++ b/rules/DeadCode/NodeCollector/NodeByTypeAndPositionCollector.php @@ -60,7 +60,6 @@ final class NodeByTypeAndPositionCollector foreach ($assignedVariablesUse as $assignedVariableUse) { $startTokenPos = $assignedVariableUse->getStartTokenPos(); - // "-1" is empty value default if ($startTokenPos === -1) { continue; diff --git a/rules/DowngradePhp74/Rector/LNumber/DowngradeNumericLiteralSeparatorRector.php b/rules/DowngradePhp74/Rector/LNumber/DowngradeNumericLiteralSeparatorRector.php index bfd8ae97437..df03d956554 100644 --- a/rules/DowngradePhp74/Rector/LNumber/DowngradeNumericLiteralSeparatorRector.php +++ b/rules/DowngradePhp74/Rector/LNumber/DowngradeNumericLiteralSeparatorRector.php @@ -64,40 +64,27 @@ CODE_SAMPLE */ public function refactor(Node $node): ?Node { - if ($this->shouldSkip($node)) { + $rawValue = $node->getAttribute(AttributeKey::RAW_VALUE); + if ($this->shouldSkip($node, $rawValue)) { return null; } - $numberValueAsString = (string) $node->value; - if (\str_contains($numberValueAsString, '+')) { + if (\str_contains((string) $rawValue, '+')) { return null; } // trigger reprint $node->setAttribute(AttributeKey::ORIGINAL_NODE, null); - if ($node instanceof LNumber) { - return $node; - } - - /** - * This code follows a guess, to avoid modifying floats needlessly. - * If the node is a float, but it doesn't contain ".", - * then it's likely that the number was forced to be a float - * by adding ".0" at the end (eg: 0.0). - * Then, add it again. - */ - if (! \str_contains($numberValueAsString, '.')) { - $numberValueAsString .= '.0'; - } - - $node->value = (float) $numberValueAsString; - return $node; } - private function shouldSkip(LNumber | DNumber $node): bool + private function shouldSkip(LNumber | DNumber $node, mixed $rawValue): bool { + if (! is_string($rawValue)) { + return true; + } + // "_" notation can be applied to decimal numbers only if ($node instanceof LNumber) { $numberKind = $node->getAttribute(AttributeKey::KIND); @@ -106,14 +93,6 @@ CODE_SAMPLE } } - // 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 ! str_contains((string) $tokenValue, '_'); + return ! str_contains($rawValue, '_'); } } diff --git a/rules/Php74/Rector/LNumber/AddLiteralSeparatorToNumberRector.php b/rules/Php74/Rector/LNumber/AddLiteralSeparatorToNumberRector.php index 137c3cd5527..ed43177c430 100644 --- a/rules/Php74/Rector/LNumber/AddLiteralSeparatorToNumberRector.php +++ b/rules/Php74/Rector/LNumber/AddLiteralSeparatorToNumberRector.php @@ -107,18 +107,19 @@ CODE_SAMPLE */ public function refactor(Node $node): ?Node { - $numericValueAsString = (string) $node->value; - if ($this->shouldSkip($node, $numericValueAsString)) { + $rawValue = $node->getAttribute(AttributeKey::RAW_VALUE); + + if ($this->shouldSkip($node, $rawValue)) { return null; } - if (\str_contains($numericValueAsString, '.')) { - [$mainPart, $decimalPart] = explode('.', $numericValueAsString); + if (\str_contains((string) $rawValue, '.')) { + [$mainPart, $decimalPart] = explode('.', (string) $rawValue); $chunks = $this->strSplitNegative($mainPart, self::GROUP_SIZE); $literalSeparatedNumber = implode('_', $chunks) . '.' . $decimalPart; } else { - $chunks = $this->strSplitNegative($numericValueAsString, self::GROUP_SIZE); + $chunks = $this->strSplitNegative($rawValue, self::GROUP_SIZE); $literalSeparatedNumber = implode('_', $chunks); // PHP converts: (string) 1000.0 -> "1000"! @@ -137,28 +138,18 @@ CODE_SAMPLE return PhpVersionFeature::LITERAL_SEPARATOR; } - private function shouldSkip(LNumber | DNumber $node, string $numericValueAsString): bool + private function shouldSkip(LNumber | DNumber $node, mixed $rawValue): bool { - $startTokenPos = $node->getStartTokenPos(); - - $oldTokens = $this->file->getOldTokens(); - $tokenValue = $oldTokens[$startTokenPos][1] ?? null; - - if (! is_string($tokenValue)) { + if (! is_string($rawValue)) { return true; } // already contains separator - if (str_contains($tokenValue, '_')) { + if (str_contains($rawValue, '_')) { return true; } - if ($numericValueAsString < $this->limitValue) { - return true; - } - - // already separated - if (\str_contains($numericValueAsString, '_')) { + if ($node->value < $this->limitValue) { return true; } @@ -168,12 +159,12 @@ CODE_SAMPLE } // e+/e- - if (StringUtils::isMatch($numericValueAsString, '#e#i')) { + if (StringUtils::isMatch($rawValue, '#e#i')) { return true; } // too short - return Strings::length($numericValueAsString) <= self::GROUP_SIZE; + return Strings::length($rawValue) <= self::GROUP_SIZE; } /**