From dc9573d9bd60ec966db626be91c13cc6a5c4bbef Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Mon, 11 Dec 2023 20:04:32 +0700 Subject: [PATCH] [Php55] Make StringClassNameToClassConstantRector configurable to keep first pre-backslash string configurable (#5354) --- .../FixtureKeepPreSlash/pre_slash.php.inc | 27 +++++++++++++++++ .../KeepPreSlashTest.php | 28 ++++++++++++++++++ .../config/configured_rule_keep_pre_slash.php | 18 ++++++++++++ .../StringClassNameToClassConstantRector.php | 29 +++++++++++++++++-- 4 files changed, 100 insertions(+), 2 deletions(-) create mode 100644 rules-tests/Php55/Rector/String_/StringClassNameToClassConstantRector/FixtureKeepPreSlash/pre_slash.php.inc create mode 100644 rules-tests/Php55/Rector/String_/StringClassNameToClassConstantRector/KeepPreSlashTest.php create mode 100644 rules-tests/Php55/Rector/String_/StringClassNameToClassConstantRector/config/configured_rule_keep_pre_slash.php diff --git a/rules-tests/Php55/Rector/String_/StringClassNameToClassConstantRector/FixtureKeepPreSlash/pre_slash.php.inc b/rules-tests/Php55/Rector/String_/StringClassNameToClassConstantRector/FixtureKeepPreSlash/pre_slash.php.inc new file mode 100644 index 00000000000..d05e6ee24eb --- /dev/null +++ b/rules-tests/Php55/Rector/String_/StringClassNameToClassConstantRector/FixtureKeepPreSlash/pre_slash.php.inc @@ -0,0 +1,27 @@ + +----- + diff --git a/rules-tests/Php55/Rector/String_/StringClassNameToClassConstantRector/KeepPreSlashTest.php b/rules-tests/Php55/Rector/String_/StringClassNameToClassConstantRector/KeepPreSlashTest.php new file mode 100644 index 00000000000..abe469117a1 --- /dev/null +++ b/rules-tests/Php55/Rector/String_/StringClassNameToClassConstantRector/KeepPreSlashTest.php @@ -0,0 +1,28 @@ +doTestFile($filePath); + } + + public static function provideData(): Iterator + { + return self::yieldFilesFromDirectory(__DIR__ . '/FixtureKeepPreSlash'); + } + + public function provideConfigFilePath(): string + { + return __DIR__ . '/config/configured_rule_keep_pre_slash.php'; + } +} diff --git a/rules-tests/Php55/Rector/String_/StringClassNameToClassConstantRector/config/configured_rule_keep_pre_slash.php b/rules-tests/Php55/Rector/String_/StringClassNameToClassConstantRector/config/configured_rule_keep_pre_slash.php new file mode 100644 index 00000000000..3c72ddf0de0 --- /dev/null +++ b/rules-tests/Php55/Rector/String_/StringClassNameToClassConstantRector/config/configured_rule_keep_pre_slash.php @@ -0,0 +1,18 @@ +ruleWithConfiguration(StringClassNameToClassConstantRector::class, [ + 'Nette\*', + 'Error', + 'Exception', + + // keep '\\' prefix string on string '\Foo\Bar' + StringClassNameToClassConstantRector::SHOULD_KEEP_PRE_SLASH => true + ]); +}; diff --git a/rules/Php55/Rector/String_/StringClassNameToClassConstantRector.php b/rules/Php55/Rector/String_/StringClassNameToClassConstantRector.php index 3aa772a2641..db43c8e8c7c 100644 --- a/rules/Php55/Rector/String_/StringClassNameToClassConstantRector.php +++ b/rules/Php55/Rector/String_/StringClassNameToClassConstantRector.php @@ -5,6 +5,7 @@ namespace Rector\Php55\Rector\String_; use PhpParser\Node; +use PhpParser\Node\Expr\BinaryOp\Concat; use PhpParser\Node\Expr\ClassConstFetch; use PhpParser\Node\Expr\FuncCall; use PhpParser\Node\Name\FullyQualified; @@ -37,6 +38,13 @@ final class StringClassNameToClassConstantRector extends AbstractRector implemen */ private array $classesToSkip = []; + private bool $shouldKeepPreslash = false; + + /** + * @var string + */ + public const SHOULD_KEEP_PRE_SLASH = 'should_keep_pre_slash'; + public function __construct( private readonly ReflectionProvider $reflectionProvider, ) { @@ -74,7 +82,11 @@ public function run() } CODE_SAMPLE , - ['ClassName', 'AnotherClassName'], + [ + 'ClassName', + 'AnotherClassName', + StringClassNameToClassConstantRector::SHOULD_KEEP_PRE_SLASH => false, + ], ), ]); } @@ -90,7 +102,7 @@ public function getNodeTypes(): array /** * @param String_|FuncCall|ClassConst $node */ - public function refactor(Node $node): ClassConstFetch|null|int + public function refactor(Node $node): Concat|ClassConstFetch|null|int { // allow class strings to be part of class const arrays, as probably on purpose if ($node instanceof ClassConst) { @@ -131,6 +143,14 @@ public function refactor(Node $node): ClassConstFetch|null|int } $fullyQualified = new FullyQualified($classLikeName); + if ($this->shouldKeepPreslash && $classLikeName !== $node->value) { + $preSlashCount = strlen($node->value) - strlen($classLikeName); + $preSlash = str_repeat('\\', $preSlashCount); + $string = new String_($preSlash); + + return new Concat($string, new ClassConstFetch($fullyQualified, 'class')); + } + return new ClassConstFetch($fullyQualified, 'class'); } @@ -139,6 +159,11 @@ public function refactor(Node $node): ClassConstFetch|null|int */ public function configure(array $configuration): void { + if (isset($configuration[self::SHOULD_KEEP_PRE_SLASH]) && is_bool($configuration[self::SHOULD_KEEP_PRE_SLASH])) { + $this->shouldKeepPreslash = $configuration[self::SHOULD_KEEP_PRE_SLASH]; + unset($configuration[self::SHOULD_KEEP_PRE_SLASH]); + } + Assert::allString($configuration); $this->classesToSkip = $configuration;