Skip to content

Commit

Permalink
[Php55] Make StringClassNameToClassConstantRector configurable to kee…
Browse files Browse the repository at this point in the history
…p first pre-backslash string configurable (#5354)
  • Loading branch information
samsonasik committed Dec 11, 2023
1 parent 68c42e7 commit dc9573d
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 2 deletions.
@@ -0,0 +1,27 @@
<?php

namespace Rector\Tests\Php55\Rector\String_\StringClassNameToClassConstantRector\FixtureKeepPreSlash;

final class PreSlash
{
public function preSlash()
{
return '\Rector\Tests\Php55\Rector\String_\StringClassNameToClassConstantRector\Source\AnotherClass';
}
}

?>
-----
<?php

namespace Rector\Tests\Php55\Rector\String_\StringClassNameToClassConstantRector\FixtureKeepPreSlash;

final class PreSlash
{
public function preSlash()
{
return '\\' . \Rector\Tests\Php55\Rector\String_\StringClassNameToClassConstantRector\Source\AnotherClass::class;
}
}

?>
@@ -0,0 +1,28 @@
<?php

declare(strict_types=1);

namespace Rector\Tests\Php55\Rector\String_\StringClassNameToClassConstantRector;

use Iterator;
use PHPUnit\Framework\Attributes\DataProvider;
use Rector\Testing\PHPUnit\AbstractRectorTestCase;

final class KeepPreSlashTest extends AbstractRectorTestCase
{
#[DataProvider('provideData')]
public function test(string $filePath): void
{
$this->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';
}
}
@@ -0,0 +1,18 @@
<?php

declare(strict_types=1);

use Rector\Config\RectorConfig;
use Rector\Php55\Rector\String_\StringClassNameToClassConstantRector;

return static function (RectorConfig $rectorConfig): void {
$rectorConfig
->ruleWithConfiguration(StringClassNameToClassConstantRector::class, [
'Nette\*',
'Error',
'Exception',

// keep '\\' prefix string on string '\Foo\Bar'
StringClassNameToClassConstantRector::SHOULD_KEEP_PRE_SLASH => true
]);
};
Expand Up @@ -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;
Expand Down Expand Up @@ -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,
) {
Expand Down Expand Up @@ -74,7 +82,11 @@ public function run()
}
CODE_SAMPLE
,
['ClassName', 'AnotherClassName'],
[
'ClassName',
'AnotherClassName',
StringClassNameToClassConstantRector::SHOULD_KEEP_PRE_SLASH => false,
],
),
]);
}
Expand All @@ -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) {
Expand Down Expand Up @@ -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');
}

Expand All @@ -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;
Expand Down

0 comments on commit dc9573d

Please sign in to comment.