Skip to content

Commit 2e30826

Browse files
authored
[code-quality] Add DirnameDirConcatStringToDirectStringPathRector (#7552)
* cs * [code-quality] Add DirnameDirConcatStringToDirectStringPathRector
1 parent b2667d6 commit 2e30826

9 files changed

Lines changed: 213 additions & 4 deletions

File tree

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Rector\Tests\CodeQuality\Rector\Concat\DirnameDirConcatStringToDirectStringPathRector;
6+
7+
use Iterator;
8+
use PHPUnit\Framework\Attributes\DataProvider;
9+
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
10+
11+
final class DirnameDirConcatStringToDirectStringPathRectorTest extends AbstractRectorTestCase
12+
{
13+
#[DataProvider('provideData')]
14+
public function test(string $filePath): void
15+
{
16+
$this->doTestFile($filePath);
17+
}
18+
19+
public static function provideData(): Iterator
20+
{
21+
return self::yieldFilesFromDirectory(__DIR__ . '/Fixture');
22+
}
23+
24+
public function provideConfigFilePath(): string
25+
{
26+
return __DIR__ . '/config/configured_rule.php';
27+
}
28+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
namespace Rector\Tests\CodeQuality\Rector\Concat\DirnameDirConcatStringToDirectStringPathRector\Fixture;
4+
5+
final class Fixture
6+
{
7+
public function run()
8+
{
9+
$path = dirname(__DIR__) . '/file.txt';
10+
}
11+
}
12+
13+
?>
14+
-----
15+
<?php
16+
17+
namespace Rector\Tests\CodeQuality\Rector\Concat\DirnameDirConcatStringToDirectStringPathRector\Fixture;
18+
19+
final class Fixture
20+
{
21+
public function run()
22+
{
23+
$path = __DIR__ . '/../file.txt';
24+
}
25+
}
26+
27+
?>
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
3+
namespace Rector\Tests\CodeQuality\Rector\Concat\DirnameDirConcatStringToDirectStringPathRector\Fixture;
4+
5+
final class SkipMultiDirnames
6+
{
7+
public function run()
8+
{
9+
$path = dirname(__DIR__, 3) . '/file.txt';
10+
}
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
3+
namespace Rector\Tests\CodeQuality\Rector\Concat\DirnameDirConcatStringToDirectStringPathRector\Fixture;
4+
5+
final class SkipTooShortPaths
6+
{
7+
public function run()
8+
{
9+
$path = dirname(__DIR__) . 'file.txt';
10+
}
11+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
namespace Rector\Tests\CodeQuality\Rector\Concat\DirnameDirConcatStringToDirectStringPathRector\Fixture;
4+
5+
final class WindowsPaths
6+
{
7+
public function run()
8+
{
9+
$path = dirname(__DIR__) . '\some\file.txt';
10+
}
11+
}
12+
13+
?>
14+
-----
15+
<?php
16+
17+
namespace Rector\Tests\CodeQuality\Rector\Concat\DirnameDirConcatStringToDirectStringPathRector\Fixture;
18+
19+
final class WindowsPaths
20+
{
21+
public function run()
22+
{
23+
$path = __DIR__ . '\..\some\file.txt';
24+
}
25+
}
26+
27+
?>
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use Rector\CodeQuality\Rector\Concat\DirnameDirConcatStringToDirectStringPathRector;
6+
use Rector\Config\RectorConfig;
7+
8+
return static function (RectorConfig $rectorConfig): void {
9+
$rectorConfig->rules([DirnameDirConcatStringToDirectStringPathRector::class]);
10+
};
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Rector\CodeQuality\Rector\Concat;
6+
7+
use PhpParser\Node;
8+
use PhpParser\Node\Expr\BinaryOp\Concat;
9+
use PhpParser\Node\Expr\FuncCall;
10+
use PhpParser\Node\Scalar\MagicConst\Dir;
11+
use PhpParser\Node\Scalar\String_;
12+
use Rector\Rector\AbstractRector;
13+
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
14+
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
15+
16+
/**
17+
* @see \Rector\Tests\CodeQuality\Rector\Concat\DirnameDirConcatStringToDirectStringPathRector\DirnameDirConcatStringToDirectStringPathRectorTest
18+
*/
19+
final class DirnameDirConcatStringToDirectStringPathRector extends AbstractRector
20+
{
21+
public function getRuleDefinition(): RuleDefinition
22+
{
23+
return new RuleDefinition('Change dirname() and string concat, to __DIR__ and direct string path', [
24+
new CodeSample(
25+
<<<'CODE_SAMPLE'
26+
class SomeClass
27+
{
28+
public function run()
29+
{
30+
$path = dirname(__DIR__) . '/vendor/autoload.php';
31+
}
32+
}
33+
CODE_SAMPLE
34+
,
35+
<<<'CODE_SAMPLE'
36+
class SomeClass
37+
{
38+
public function run()
39+
{
40+
$path = __DIR__ . '/../vendor/autoload.php';
41+
}
42+
}
43+
CODE_SAMPLE
44+
),
45+
]);
46+
47+
}
48+
49+
public function getNodeTypes(): array
50+
{
51+
return [Concat::class];
52+
}
53+
54+
/**
55+
* @param Concat $node
56+
*/
57+
public function refactor(Node $node): ?Concat
58+
{
59+
if (! $node->left instanceof FuncCall || ! $this->isName($node->left, 'dirname')) {
60+
return null;
61+
}
62+
63+
if (! $node->right instanceof String_) {
64+
return null;
65+
}
66+
67+
$dirnameFuncCall = $node->left;
68+
if ($dirnameFuncCall->isFirstClassCallable()) {
69+
return null;
70+
}
71+
72+
// avoid multiple dir nesting for now
73+
if (count($dirnameFuncCall->getArgs()) !== 1) {
74+
return null;
75+
}
76+
77+
$firstArg = $dirnameFuncCall->getArgs()[0];
78+
if (! $firstArg->value instanceof Dir) {
79+
return null;
80+
}
81+
82+
$string = $node->right;
83+
if (str_contains($string->value, '/')) {
84+
// linux paths
85+
$string->value = '/../' . ltrim($string->value, '/');
86+
$node->left = new Dir();
87+
return $node;
88+
}
89+
90+
if (str_contains($string->value, '\\')) {
91+
// windows paths
92+
$string->value = '\\..\\' . ltrim($string->value, '\\');
93+
$node->left = new Dir();
94+
return $node;
95+
}
96+
97+
return null;
98+
}
99+
}

scripts/list-unused-rules.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@
4545

4646
$unusedRectorRules = array_diff($rectorClasses, $usedRectorRules);
4747

48-
4948
$symfonyStyle->newLine();
5049
$symfonyStyle->listing($unusedRectorRules);
5150

src/NodeTypeResolver/NodeTypeCorrector.php

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,6 @@ private function removeAccessoryArrayListType(Type $type): Type
5050
$cleanTypes[] = $intersectionType;
5151
}
5252

53-
// dump($cleanTypes);
54-
// die;
55-
5653
if (count($cleanTypes) === 1) {
5754
return $cleanTypes[0];
5855
}

0 commit comments

Comments
 (0)