Merge FollowRequireByDirRector to almost identical AbsolutizeRequireAndIncludePathRector (#2048)

This commit is contained in:
Tomas Votruba 2022-04-10 22:04:59 +02:00 committed by GitHub
parent 0227d24e36
commit 60f1dadd6f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 95 additions and 175 deletions

View File

@ -20,7 +20,6 @@ use Rector\CodingStyle\Rector\FuncCall\ConsistentImplodeRector;
use Rector\CodingStyle\Rector\FuncCall\ConsistentPregDelimiterRector;
use Rector\CodingStyle\Rector\FuncCall\VersionCompareFuncCallToConstantRector;
use Rector\CodingStyle\Rector\If_\NullableCompareToNullRector;
use Rector\CodingStyle\Rector\Include_\FollowRequireByDirRector;
use Rector\CodingStyle\Rector\Plus\UseIncrementAssignRector;
use Rector\CodingStyle\Rector\PostInc\PostIncDecToPreIncDecRector;
use Rector\CodingStyle\Rector\Property\AddFalseDefaultToBoolPropertyRector;
@ -44,7 +43,6 @@ return static function (ContainerConfigurator $containerConfigurator): void {
$services->set(SplitGroupedConstantsAndPropertiesRector::class);
$services->set(StringClassNameToClassConstantRector::class);
$services->set(ConsistentPregDelimiterRector::class);
$services->set(FollowRequireByDirRector::class);
$services->set(CatchExceptionNameMatchingTypeRector::class);
$services->set(UseIncrementAssignRector::class);
$services->set(SplitDoubleAssignRector::class);

View File

@ -1,6 +1,6 @@
<?php
namespace Rector\Tests\CodingStyle\Rector\Include_\FollowRequireByDirRector\Fixture;
namespace Rector\Tests\CodeQuality\Rector\Include_\AbsolutizeRequireAndIncludePathRector\Fixture;
class ExtraDot
{
@ -15,7 +15,7 @@ class ExtraDot
-----
<?php
namespace Rector\Tests\CodingStyle\Rector\Include_\FollowRequireByDirRector\Fixture;
namespace Rector\Tests\CodeQuality\Rector\Include_\AbsolutizeRequireAndIncludePathRector\Fixture;
class ExtraDot
{

View File

@ -1,8 +1,8 @@
<?php
namespace Rector\Tests\CodingStyle\Rector\Include_\FollowRequireByDirRector\Fixture;
namespace Rector\Tests\CodeQuality\Rector\Include_\AbsolutizeRequireAndIncludePathRector\Fixture;
class Fixture
final class FullList
{
public function run()
{
@ -12,7 +12,7 @@ class Fixture
require_once 'autoload.php';
include 'autoload.php';
include_once 'autoload.php';
require 'path/' . $variable;
require $variable;
require __DIR__ . $variable;
require __DIR__ . 'string';
@ -23,9 +23,9 @@ class Fixture
-----
<?php
namespace Rector\Tests\CodingStyle\Rector\Include_\FollowRequireByDirRector\Fixture;
namespace Rector\Tests\CodeQuality\Rector\Include_\AbsolutizeRequireAndIncludePathRector\Fixture;
class Fixture
final class FullList
{
public function run()
{
@ -35,7 +35,7 @@ class Fixture
require_once __DIR__ . '/autoload.php';
include __DIR__ . '/autoload.php';
include_once __DIR__ . '/autoload.php';
require __DIR__ . '/path/' . $variable;
require $variable;
require __DIR__ . $variable;
require __DIR__ . 'string';

View File

@ -0,0 +1,27 @@
<?php
namespace Rector\Tests\CodeQuality\Rector\Include_\AbsolutizeRequireAndIncludePathRector\Fixture;
final class InterVariable
{
public function run(string $variable)
{
require 'path/' . $variable;
}
}
?>
-----
<?php
namespace Rector\Tests\CodeQuality\Rector\Include_\AbsolutizeRequireAndIncludePathRector\Fixture;
final class InterVariable
{
public function run(string $variable)
{
require __DIR__ . '/path/' . $variable;
}
}
?>

View File

@ -1,13 +1,12 @@
<?php
namespace Rector\Tests\CodingStyle\Rector\Include_\FollowRequireByDirRector\Fixture;
namespace Rector\Tests\CodeQuality\Rector\Include_\AbsolutizeRequireAndIncludePathRector\Fixture;
class Phar
{
public function run()
{
require 'vendor/autoload.php';
require '/vendor/autoload.php';
require 'phar://vendor/autoload.php';
}
}
@ -16,13 +15,12 @@ class Phar
-----
<?php
namespace Rector\Tests\CodingStyle\Rector\Include_\FollowRequireByDirRector\Fixture;
namespace Rector\Tests\CodeQuality\Rector\Include_\AbsolutizeRequireAndIncludePathRector\Fixture;
class Phar
{
public function run()
{
require __DIR__ . '/vendor/autoload.php';
require __DIR__ . '/vendor/autoload.php';
require 'phar://vendor/autoload.php';
}

View File

@ -0,0 +1,11 @@
<?php
namespace Rector\Tests\CodeQuality\Rector\Include_\AbsolutizeRequireAndIncludePathRector\Fixture;
final class SkipAbsolutePaths
{
public function run()
{
require '/vendor/autoload.php';
}
}

View File

@ -1,33 +0,0 @@
<?php
declare(strict_types=1);
namespace Rector\Tests\CodingStyle\Rector\Include_\FollowRequireByDirRector;
use Iterator;
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
use Symplify\SmartFileSystem\SmartFileInfo;
final class FollowRequireByDirRectorTest extends AbstractRectorTestCase
{
/**
* @dataProvider provideData()
*/
public function test(SmartFileInfo $fileInfo): void
{
$this->doTestFileInfo($fileInfo);
}
/**
* @return Iterator<SmartFileInfo>
*/
public function provideData(): Iterator
{
return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture');
}
public function provideConfigFilePath(): string
{
return __DIR__ . '/config/configured_rule.php';
}
}

View File

@ -1,11 +0,0 @@
<?php
declare(strict_types=1);
use Rector\CodingStyle\Rector\Include_\FollowRequireByDirRector;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return static function (ContainerConfigurator $containerConfigurator): void {
$services = $containerConfigurator->services();
$services->set(FollowRequireByDirRector::class);
};

View File

@ -68,10 +68,22 @@ CODE_SAMPLE
*/
public function refactor(Node $node): ?Node
{
if ($node->expr instanceof Concat && $node->expr->left instanceof String_ && $this->isRefactorableStringPath(
$node->expr->left
)) {
$node->expr->left = $this->prefixWithDirConstant($node->expr->left);
return $node;
}
if (! $node->expr instanceof String_) {
return null;
}
if (! $this->isRefactorableStringPath($node->expr)) {
return null;
}
/** @var string $includeValue */
$includeValue = $this->valueResolver->getValue($node->expr);
@ -96,8 +108,42 @@ CODE_SAMPLE
$node->expr->value = '/' . $includeValue;
}
$node->expr = new Concat(new Dir(), $node->expr);
$node->expr = $this->prefixWithDirConstant($node->expr);
return $node;
}
private function isRefactorableStringPath(String_ $string): bool
{
return ! \str_starts_with($string->value, 'phar://');
}
private function prefixWithDirConstant(String_ $string): Concat
{
$this->removeExtraDotSlash($string);
$this->prependSlashIfMissing($string);
return new Concat(new Dir(), $string);
}
/**
* Remove "./" which would break the path
*/
private function removeExtraDotSlash(String_ $string): void
{
if (! \str_starts_with($string->value, './')) {
return;
}
$string->value = Strings::replace($string->value, '#^\.\/#', '/');
}
private function prependSlashIfMissing(String_ $string): void
{
if (\str_starts_with($string->value, '/')) {
return;
}
$string->value = '/' . $string->value;
}
}

View File

@ -1,116 +0,0 @@
<?php
declare(strict_types=1);
namespace Rector\CodingStyle\Rector\Include_;
use Nette\Utils\Strings;
use PhpParser\Node;
use PhpParser\Node\Expr\BinaryOp\Concat;
use PhpParser\Node\Expr\Include_;
use PhpParser\Node\Scalar\MagicConst\Dir;
use PhpParser\Node\Scalar\String_;
use Rector\Core\Rector\AbstractRector;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
/**
* @see \Rector\Tests\CodingStyle\Rector\Include_\FollowRequireByDirRector\FollowRequireByDirRectorTest
*/
final class FollowRequireByDirRector extends AbstractRector
{
public function getRuleDefinition(): RuleDefinition
{
return new RuleDefinition(
'include/require should be followed by absolute path',
[
new CodeSample(
<<<'CODE_SAMPLE'
class SomeClass
{
public function run()
{
require 'autoload.php';
}
}
CODE_SAMPLE
,
<<<'CODE_SAMPLE'
class SomeClass
{
public function run()
{
require __DIR__ . '/autoload.php';
}
}
CODE_SAMPLE
),
]
);
}
/**
* @return array<class-string<Node>>
*/
public function getNodeTypes(): array
{
return [Include_::class];
}
/**
* @param Include_ $node
*/
public function refactor(Node $node): ?Node
{
if ($node->expr instanceof Concat && $node->expr->left instanceof String_ && $this->isRefactorableStringPath(
$node->expr->left
)) {
$node->expr->left = $this->prefixWithDir($node->expr->left);
return $node;
}
if ($node->expr instanceof String_ && $this->isRefactorableStringPath($node->expr)) {
$node->expr = $this->prefixWithDir($node->expr);
return $node;
}
// nothing we can do
return null;
}
private function isRefactorableStringPath(String_ $string): bool
{
return ! \str_starts_with($string->value, 'phar://');
}
private function prefixWithDir(String_ $string): Concat
{
$this->removeExtraDotSlash($string);
$this->prependSlashIfMissing($string);
return new Concat(new Dir(), $string);
}
/**
* Remove "./" which would break the path
*/
private function removeExtraDotSlash(String_ $string): void
{
if (! \str_starts_with($string->value, './')) {
return;
}
$string->value = Strings::replace($string->value, '#^\.\/#', '/');
}
private function prependSlashIfMissing(String_ $string): void
{
if (\str_starts_with($string->value, '/')) {
return;
}
$string->value = '/' . $string->value;
}
}