mirror of
https://github.com/rectorphp/rector.git
synced 2025-01-17 05:18:18 +01:00
[Restoration] Add RestoreFullyQualifiedNameRector (#4336)
* [Restoration] Add RestoreFullyQualifiedNameRector * update docs * use service aware test case for PHPStan rules * improve FullyQualifiedNameMatcher * cs fixes * add return doc resolution * composer: bump to symfony 4.4/5.1
This commit is contained in:
parent
ae816c2c3d
commit
8ae3868a57
@ -26,17 +26,18 @@
|
||||
"phpstan/phpstan-phpunit": "^0.12.10",
|
||||
"psr/simple-cache": "^1.0",
|
||||
"sebastian/diff": "^3.0|^4.0",
|
||||
"symfony/cache": "^4.4.8|^5.0.6",
|
||||
"symfony/console": "^4.4.8|^5.0.6",
|
||||
"symfony/dependency-injection": "^4.4.8|^5.0.6",
|
||||
"symfony/finder": "^4.4.8|^5.0.6",
|
||||
"symfony/process": "^4.4.8|^5.0.6",
|
||||
"symplify/autowire-array-parameter": "^8.3.17",
|
||||
"symplify/console-color-diff": "^8.3.17",
|
||||
"symplify/easy-testing": "^8.3.17",
|
||||
"symplify/package-builder": "^8.3.17",
|
||||
"symplify/set-config-resolver": "^8.3.17",
|
||||
"symplify/smart-file-system": "^8.3.17",
|
||||
"symfony/cache": "^4.4.8|^5.1",
|
||||
"symfony/console": "^4.4.8|^5.1",
|
||||
"symfony/dependency-injection": "^4.4.8|^5.1",
|
||||
"symfony/finder": "^4.4.8|^5.1",
|
||||
"symfony/process": "^4.4.8|^5.1",
|
||||
"symplify/autowire-array-parameter": "^8.3.24",
|
||||
"symplify/console-color-diff": "^8.3.24",
|
||||
"symplify/easy-testing": "^8.3.24",
|
||||
"symplify/composer-json-manipulator": "^8.3.24",
|
||||
"symplify/package-builder": "^8.3.24",
|
||||
"symplify/set-config-resolver": "^8.3.24",
|
||||
"symplify/smart-file-system": "^8.3.24",
|
||||
"webmozart/assert": "^1.8"
|
||||
},
|
||||
"require-dev": {
|
||||
@ -49,11 +50,11 @@
|
||||
"php-parallel-lint/php-parallel-lint": "^1.2",
|
||||
"phpunit/phpunit": "^8.5|^9.2",
|
||||
"psr/event-dispatcher": "^1.0",
|
||||
"symplify/changelog-linker": "^8.3.17",
|
||||
"symplify/easy-coding-standard": "^8.3.17",
|
||||
"symplify/easy-testing": "^8.3.17",
|
||||
"symplify/monorepo-builder": "^8.3.17",
|
||||
"symplify/phpstan-extensions": "^8.3.17",
|
||||
"symplify/changelog-linker": "^8.3.24",
|
||||
"symplify/easy-coding-standard": "^8.3.24",
|
||||
"symplify/easy-testing": "^8.3.24",
|
||||
"symplify/monorepo-builder": "^8.3.24",
|
||||
"symplify/phpstan-extensions": "^8.3.24",
|
||||
"tracy/tracy": "^2.7",
|
||||
"thecodingmachine/phpstan-strict-rules": "^0.12"
|
||||
},
|
||||
@ -154,7 +155,8 @@
|
||||
"Rector\\SymfonyPhpConfig\\": "rules/symfony-php-config/src"
|
||||
},
|
||||
"files": [
|
||||
"rules/symfony-php-config/functions/functions.php"
|
||||
"rules/symfony-php-config/functions/functions.php",
|
||||
"rules/restoration/tests/Rector/Use_/RestoreFullyQualifiedNameRector/Source/ShortClassOnly.php"
|
||||
]
|
||||
},
|
||||
"autoload-dev": {
|
||||
|
@ -1,4 +1,4 @@
|
||||
# All 582 Rectors Overview
|
||||
# All 583 Rectors Overview
|
||||
|
||||
- [Projects](#projects)
|
||||
---
|
||||
@ -62,7 +62,7 @@
|
||||
- [RectorGenerator](#rectorgenerator) (1)
|
||||
- [RemovingStatic](#removingstatic) (6)
|
||||
- [Renaming](#renaming) (9)
|
||||
- [Restoration](#restoration) (7)
|
||||
- [Restoration](#restoration) (8)
|
||||
- [SOLID](#solid) (12)
|
||||
- [Sensio](#sensio) (3)
|
||||
- [StrictCodeQuality](#strictcodequality) (1)
|
||||
@ -8718,8 +8718,6 @@ Change Form that extends Control to Controller and decoupled FormType
|
||||
|
||||
**New file**
|
||||
```php
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
@ -13977,6 +13975,24 @@ Remove interface, that are added just for its sake, but nowhere useful
|
||||
|
||||
<br><br>
|
||||
|
||||
### `RestoreFullyQualifiedNameRector`
|
||||
|
||||
- class: [`Rector\Restoration\Rector\Use_\RestoreFullyQualifiedNameRector`](/rules/restoration/src/Rector/Use_/RestoreFullyQualifiedNameRector.php)
|
||||
- [test fixtures](/rules/restoration/tests/Rector/Use_/RestoreFullyQualifiedNameRector/Fixture)
|
||||
|
||||
Restore accidentally shortened class names to its fully qualified form.
|
||||
|
||||
```diff
|
||||
-use ShortClassOnly;
|
||||
+use App\Whatever\ShortClassOnly;
|
||||
|
||||
class AnotherClass
|
||||
{
|
||||
}
|
||||
```
|
||||
|
||||
<br><br>
|
||||
|
||||
### `UpdateFileNameByClassNameFileSystemRector`
|
||||
|
||||
- class: [`Rector\Restoration\Rector\FileSystem\UpdateFileNameByClassNameFileSystemRector`](/rules/restoration/src/Rector/FileSystem/UpdateFileNameByClassNameFileSystemRector.php)
|
||||
|
6
ecs.php
6
ecs.php
@ -8,11 +8,13 @@ use PhpCsFixer\Fixer\Operator\UnaryOperatorSpacesFixer;
|
||||
use PhpCsFixer\Fixer\Phpdoc\GeneralPhpdocAnnotationRemoveFixer;
|
||||
use PhpCsFixer\Fixer\Phpdoc\NoSuperfluousPhpdocTagsFixer;
|
||||
use PhpCsFixer\Fixer\Phpdoc\PhpdocTypesFixer;
|
||||
use PhpCsFixer\Fixer\PhpTag\BlankLineAfterOpeningTagFixer;
|
||||
use PhpCsFixer\Fixer\PhpUnit\PhpUnitStrictFixer;
|
||||
use PhpCsFixer\Fixer\ReturnNotation\ReturnAssignmentFixer;
|
||||
use PhpCsFixer\Fixer\Strict\StrictComparisonFixer;
|
||||
use SlevomatCodingStandard\Sniffs\Variables\UnusedVariableSniff;
|
||||
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
|
||||
use Symplify\CodingStandard\Fixer\ArrayNotation\ArrayListItemNewlineFixer;
|
||||
use Symplify\CodingStandard\Fixer\ArrayNotation\ArrayOpenerAndCloserNewlineFixer;
|
||||
use Symplify\CodingStandard\Fixer\ArrayNotation\StandaloneLineInMultilineArrayFixer;
|
||||
use Symplify\CodingStandard\Fixer\LineLength\LineLengthFixer;
|
||||
@ -93,6 +95,10 @@ return static function (ContainerConfigurator $containerConfigurator): void {
|
||||
UnaryOperatorSpacesFixer::class => null,
|
||||
// breaks on-purpose annotated variables
|
||||
ReturnAssignmentFixer::class => null,
|
||||
// buggy with specific markdown snippet file in docs/rules_overview.md
|
||||
ArrayListItemNewlineFixer::class => null,
|
||||
BlankLineAfterOpeningTagFixer::class => null,
|
||||
|
||||
StrictComparisonFixer::class => [__DIR__ . '/rules/polyfill/src/ConditionEvaluator.php'],
|
||||
]);
|
||||
|
||||
|
@ -8,6 +8,14 @@ final class ClassExistenceStaticHelper
|
||||
{
|
||||
public static function doesClassLikeExist(string $classLike): bool
|
||||
{
|
||||
return class_exists($classLike) || interface_exists($classLike) || trait_exists($classLike);
|
||||
if (class_exists($classLike)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (interface_exists($classLike)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return trait_exists($classLike);
|
||||
}
|
||||
}
|
||||
|
67
phpstan.neon
67
phpstan.neon
@ -9,21 +9,20 @@ includes:
|
||||
|
||||
services:
|
||||
# require constant in argument position
|
||||
|
||||
#-
|
||||
# class: Symplify\CodingStandard\Rules\RequireMethodCallArgumentConstantRule
|
||||
# tags: [phpstan.rules.rule]
|
||||
# arguments:
|
||||
# constantArgByMethodByType:
|
||||
# Symfony\Component\Console\Command\Command:
|
||||
# addArgument: [0]
|
||||
# addOption: [0]
|
||||
# Symfony\Component\Console\Input\InputInterface:
|
||||
# getOption: [0]
|
||||
# getArgument: [0]
|
||||
# PhpParser\Node:
|
||||
# getAttribute: [0]
|
||||
# setAttribute: [0]
|
||||
-
|
||||
class: Symplify\CodingStandard\Rules\RequireMethodCallArgumentConstantRule
|
||||
tags: [phpstan.rules.rule]
|
||||
arguments:
|
||||
constantArgByMethodByType:
|
||||
Symfony\Component\Console\Command\Command:
|
||||
addArgument: [0]
|
||||
addOption: [0]
|
||||
Symfony\Component\Console\Input\InputInterface:
|
||||
getOption: [0]
|
||||
getArgument: [0]
|
||||
PhpParser\Node:
|
||||
getAttribute: [0]
|
||||
setAttribute: [0]
|
||||
|
||||
-
|
||||
class: Symplify\CodingStandard\Rules\SeeAnnotationToTestRule
|
||||
@ -521,16 +520,12 @@ parameters:
|
||||
|
||||
- '#Parameter \#1 \$rectors of method Rector\\DocumentationGenerator\\Printer\\RectorsDocumentationPrinter\:\:print\(\) expects array<Rector\\Core\\Contract\\Rector\\RectorInterface\>, array<object\> given#'
|
||||
|
||||
- '#Use "Symplify\\SmartFileSystem\\SmartFileSystem\:\:dumpFile\(\)" static call over "file_put_contents\(\)" func call#'
|
||||
- '#Class name start with Abstract must have abstract keyword#'
|
||||
- '#Class with base "CheckNotTestsNamespaceOutsideTestsDirectoryRule" name is already used in "Rector\\PHPStanExtensions\\Rule\\CheckNotTestsNamespaceOutsideTestsDirectoryRule", "Symplify\\CodingStandard\\Rules\\CheckNotTestsNamespaceOutsideTestsDirectoryRule"\. Use unique name to make classes easy to recognize#'
|
||||
- '#Class "Rector\\PHPStanExtensions\\Tests\\Rule\\CheckGetNodeTypesReturnPhpParserNodeRule\\CheckGetNodeTypesReturnPhpParserNodeRuleTest" inherits from forbidden parent class "PHPStan\\Testing\\RuleTestCase"\. Use "Symplify\\PHPStanExtensions\\Testing\\AbstractServiceAwareRuleTestCase" instead#'
|
||||
- '#Class "Rector\\PHPStanExtensions\\Tests\\Rule\\CheckNotTestsNamespaceOutsideTestsDirectoryRule\\CheckNotTestsNamespaceOutsideTestsDirectoryRuleTest" inherits from forbidden parent class "PHPStan\\Testing\\RuleTestCase"\. Use "Symplify\\PHPStanExtensions\\Testing\\AbstractServiceAwareRuleTestCase" instead#'
|
||||
- '#Class "Rector\\PHPStanExtensions\\Tests\\Rule\\ConfigurableRectorRule\\ConfigurableRectorRuleTest" inherits from forbidden parent class "PHPStan\\Testing\\RuleTestCase"\. Use "Symplify\\PHPStanExtensions\\Testing\\AbstractServiceAwareRuleTestCase" instead#'
|
||||
- '#Class "Rector\\PHPStanExtensions\\Tests\\Rule\\KeepRectorNamespaceForRectorRule\\KeepRectorNamespaceForRectorRuleTest" inherits from forbidden parent class "PHPStan\\Testing\\RuleTestCase"\. Use "Symplify\\PHPStanExtensions\\Testing\\AbstractServiceAwareRuleTestCase" instead#'
|
||||
- '#Class "Rector\\PHPStanExtensions\\Tests\\Rule\\RectorRuleAndValueObjectHaveSameStartsRule\\RectorRuleAndValueObjectHaveSameStartsRuleTest" inherits from forbidden parent class "PHPStan\\Testing\\RuleTestCase"\. Use "Symplify\\PHPStanExtensions\\Testing\\AbstractServiceAwareRuleTestCase" instead#'
|
||||
- '#Class "Rector\\PHPStanExtensions\\Tests\\Rule\\RequireRectorCategoryByGetNodeTypesRule\\RequireRectorCategoryByGetNodeTypesRuleTest" inherits from forbidden parent class "PHPStan\\Testing\\RuleTestCase"\. Use "Symplify\\PHPStanExtensions\\Testing\\AbstractServiceAwareRuleTestCase" instead#'
|
||||
- '#Class "Rector\\PHPStanExtensions\\Tests\\Rule\\ValueObjectHasNoValueObjectSuffixRule\\ValueObjectHasNoValueObjectSuffixRuleTest" inherits from forbidden parent class "PHPStan\\Testing\\RuleTestCase"\. Use "Symplify\\PHPStanExtensions\\Testing\\AbstractServiceAwareRuleTestCase" instead#'
|
||||
-
|
||||
message: '#Use "Nette\\Utils\\Strings\:\:contains\(\)" static call over "strstr\(\)" func call#'
|
||||
paths:
|
||||
- utils/phpstan-extensions/src/Rule/CheckNotTestsNamespaceOutsideTestsDirectoryRule.php # 76
|
||||
- utils/phpstan-extensions/src/Rule/CheckNotTestsNamespaceOutsideTestsDirectoryRule.php # 81
|
||||
|
||||
-
|
||||
message: '#Do not call parent method if no override process#'
|
||||
paths:
|
||||
@ -713,9 +708,27 @@ parameters:
|
||||
- src/Configuration/Configuration.php # 204
|
||||
- src/Configuration/Configuration.php # 227
|
||||
- src/Configuration/CurrentNodeProvider.php # 16
|
||||
- src/HttpKernel/RectorKernel.php # 70
|
||||
- src/Rector/AbstractRector/CallableNodeTraverserTrait.php # 24
|
||||
- src/Rector/AbstractRector/CallableNodeTraverserTrait.php # 24
|
||||
- src/Rector/AbstractRector/ConstFetchAnalyzerTrait.php # 24
|
||||
- src/Rector/AbstractRector/ConstFetchAnalyzerTrait.php # 24
|
||||
- src/Testing/NodeVisitor/AttributeCollectingNodeVisitor.php # 24
|
||||
- src/Testing/NodeVisitor/AttributeCollectingNodeVisitor.php # 24
|
||||
- src/Testing/NodeVisitor/AttributeCollectingNodeVisitor.php # 24
|
||||
|
||||
- '#Use "Symplify\\SmartFileSystem\\SmartFileSystem\:\:dumpFile\(\)" static call over "file_put_contents\(\)" func call#'
|
||||
- '#Class name start with Abstract must have abstract keyword#'
|
||||
- '#Parameter \#1 \$name of method Rector\\Restoration\\Rector\\Use_\\RestoreFullyQualifiedNameRector\:\:resolveFullyQualifiedName\(\) expects PhpParser\\Node\\Name, PhpParser\\Node\\Identifier\|PhpParser\\Node\\Name given#'
|
||||
|
||||
- '#Class with base "CheckNotTestsNamespaceOutsideTestsDirectoryRule" name is already used in "Rector\\PHPStanExtensions\\Rule\\CheckNotTestsNamespaceOutsideTestsDirectoryRule", "Symplify\\CodingStandard\\Rules\\CheckNotTestsNamespaceOutsideTestsDirectoryRule"\. Use unique name to make classes easy to recognize#'
|
||||
|
||||
-
|
||||
message: '#Do not use setter on a service#'
|
||||
paths:
|
||||
- src/HttpKernel/RectorKernel.php
|
||||
|
||||
# buggy, is fixed on symplify dev-master
|
||||
-
|
||||
message: '#Method call argument on position 0 must use constant over value#'
|
||||
paths:
|
||||
- src/Rector/AbstractRector.php # 419
|
||||
- src/Rector/AbstractRector.php # 419
|
||||
|
@ -13,7 +13,7 @@ use Symplify\SmartFileSystem\SmartFileInfo;
|
||||
final class MoveInterfacesToContractNamespaceDirectoryRectorTest extends AbstractFileSystemRectorTestCase
|
||||
{
|
||||
/**
|
||||
* @requires PHP >= 7.4
|
||||
* @requires PHP 7.4
|
||||
* @dataProvider provideData()
|
||||
* @param InputFilePathWithExpectedFile[] $InputFilePathWithExpectedFiles
|
||||
*/
|
||||
|
@ -12,7 +12,7 @@ use Symplify\SmartFileSystem\SmartFileInfo;
|
||||
final class SkipParentConstructOverrideInPHP72Test extends AbstractRectorTestCase
|
||||
{
|
||||
/**
|
||||
* @requires PHP >= 7.2
|
||||
* @requires PHP 7.2
|
||||
* @see https://phpunit.readthedocs.io/en/8.3/incomplete-and-skipped-tests.html#incomplete-and-skipped-tests-requires-tables-api
|
||||
*
|
||||
* @dataProvider provideData()
|
||||
|
@ -11,7 +11,7 @@ use Rector\DeadCode\Rector\FunctionLike\RemoveDeadReturnRector;
|
||||
use Symplify\SmartFileSystem\SmartFileInfo;
|
||||
|
||||
/**
|
||||
* @requires PHP >= 7.4
|
||||
* @requires PHP 7.4
|
||||
*/
|
||||
final class Php74Test extends AbstractRectorTestCase
|
||||
{
|
||||
|
@ -14,7 +14,7 @@ final class TypedPropertiesRemoveNullPropertyInitializationRectorTest extends Ab
|
||||
{
|
||||
/**
|
||||
* @dataProvider provideData()
|
||||
* @requires PHP >= 7.4
|
||||
* @requires PHP 7.4
|
||||
*/
|
||||
public function test(SmartFileInfo $fileInfo): void
|
||||
{
|
||||
|
@ -13,7 +13,7 @@ use Symplify\SmartFileSystem\SmartFileInfo;
|
||||
final class DowngradeParamObjectTypeDeclarationRectorTest extends AbstractRectorTestCase
|
||||
{
|
||||
/**
|
||||
* @requires PHP >= 7.2
|
||||
* @requires PHP 7.2
|
||||
* @dataProvider provideData()
|
||||
*/
|
||||
public function test(SmartFileInfo $fileInfo): void
|
||||
|
@ -13,7 +13,7 @@ use Symplify\SmartFileSystem\SmartFileInfo;
|
||||
final class DowngradeReturnObjectTypeDeclarationRectorTest extends AbstractRectorTestCase
|
||||
{
|
||||
/**
|
||||
* @requires PHP >= 7.2
|
||||
* @requires PHP 7.2
|
||||
* @dataProvider provideData()
|
||||
*/
|
||||
public function test(SmartFileInfo $fileInfo): void
|
||||
|
@ -13,7 +13,7 @@ use Symplify\SmartFileSystem\SmartFileInfo;
|
||||
final class ArrowFunctionToAnonymousFunctionRectorTest extends AbstractRectorTestCase
|
||||
{
|
||||
/**
|
||||
* @requires PHP >= 7.4
|
||||
* @requires PHP 7.4
|
||||
* @dataProvider provideData()
|
||||
*/
|
||||
public function test(SmartFileInfo $fileInfo): void
|
||||
|
@ -13,7 +13,7 @@ use Symplify\SmartFileSystem\SmartFileInfo;
|
||||
final class DowngradeNullCoalescingOperatorRectorTest extends AbstractRectorTestCase
|
||||
{
|
||||
/**
|
||||
* @requires PHP >= 7.4
|
||||
* @requires PHP 7.4
|
||||
* @dataProvider provideData()
|
||||
*/
|
||||
public function test(SmartFileInfo $fileInfo): void
|
||||
|
@ -13,7 +13,7 @@ use Symplify\SmartFileSystem\SmartFileInfo;
|
||||
final class DowngradeTypedPropertyRectorTest extends AbstractRectorTestCase
|
||||
{
|
||||
/**
|
||||
* @requires PHP >= 7.4
|
||||
* @requires PHP 7.4
|
||||
* @dataProvider provideData()
|
||||
*/
|
||||
public function test(SmartFileInfo $fileInfo): void
|
||||
|
@ -13,7 +13,7 @@ use Symplify\SmartFileSystem\SmartFileInfo;
|
||||
final class DowngradeTypedPropertyRectorTest extends AbstractRectorTestCase
|
||||
{
|
||||
/**
|
||||
* @requires PHP >= 7.4
|
||||
* @requires PHP 7.4
|
||||
* @dataProvider provideData()
|
||||
*/
|
||||
public function test(SmartFileInfo $fileInfo): void
|
||||
|
@ -12,7 +12,7 @@ use Symplify\SmartFileSystem\SmartFileInfo;
|
||||
final class TypedPropertyTest extends AbstractRectorTestCase
|
||||
{
|
||||
/**
|
||||
* @requires PHP >= 7.4
|
||||
* @requires PHP 7.4
|
||||
* @dataProvider provideData()
|
||||
*/
|
||||
public function test(SmartFileInfo $fileInfo): void
|
||||
|
@ -12,7 +12,7 @@ use Symplify\SmartFileSystem\SmartFileInfo;
|
||||
final class Php74Test extends AbstractRectorTestCase
|
||||
{
|
||||
/**
|
||||
* @requires PHP >= 7.4
|
||||
* @requires PHP 7.4
|
||||
* @dataProvider provideData()
|
||||
*/
|
||||
public function test(SmartFileInfo $fileInfo): void
|
||||
|
@ -11,7 +11,7 @@ use Rector\Naming\Rector\Property\MakeBoolPropertyRespectIsHasWasMethodNamingRec
|
||||
use Symplify\SmartFileSystem\SmartFileInfo;
|
||||
|
||||
/**
|
||||
* @requires PHP >= 7.4
|
||||
* @requires PHP 7.4
|
||||
*/
|
||||
final class Php74Test extends AbstractRectorTestCase
|
||||
{
|
||||
|
@ -12,7 +12,7 @@ use Symplify\SmartFileSystem\SmartFileInfo;
|
||||
final class Php74Test extends AbstractRectorTestCase
|
||||
{
|
||||
/**
|
||||
* @requires PHP >= 7.4
|
||||
* @requires PHP 7.4
|
||||
* @dataProvider provideData()
|
||||
*/
|
||||
public function test(SmartFileInfo $fileInfo): void
|
||||
|
@ -13,7 +13,7 @@ final class Php74Test extends AbstractRectorTestCase
|
||||
{
|
||||
/**
|
||||
* @dataProvider provideData()
|
||||
* @requires PHP >= 7.4
|
||||
* @requires PHP 7.4
|
||||
*/
|
||||
public function test(SmartFileInfo $fileInfo): void
|
||||
{
|
||||
|
@ -12,7 +12,7 @@ use Symplify\SmartFileSystem\SmartFileInfo;
|
||||
final class IsCountableRectorTest extends AbstractRectorTestCase
|
||||
{
|
||||
/**
|
||||
* @requires PHP >= 7.3
|
||||
* @requires PHP 7.3
|
||||
* @dataProvider provideData()
|
||||
*/
|
||||
public function test(SmartFileInfo $fileInfo): void
|
||||
|
@ -12,7 +12,7 @@ use Symplify\SmartFileSystem\SmartFileInfo;
|
||||
final class RestoreDefaultNullToNullableTypePropertyRectorTest extends AbstractRectorTestCase
|
||||
{
|
||||
/**
|
||||
* @requires PHP >= 7.4
|
||||
* @requires PHP 7.4
|
||||
* @dataProvider provideData()
|
||||
*/
|
||||
public function test(SmartFileInfo $fileInfo): void
|
||||
|
@ -12,7 +12,7 @@ use Symplify\SmartFileSystem\SmartFileInfo;
|
||||
final class ClassPropertyAssignToConstructorPromotionRectorTest extends AbstractRectorTestCase
|
||||
{
|
||||
/**
|
||||
* @requires PHP >= 7.4
|
||||
* @requires PHP 7.4
|
||||
* @dataProvider provideData()
|
||||
*/
|
||||
public function test(SmartFileInfo $fileInfo): void
|
||||
|
16
rules/restoration/config/config.php
Normal file
16
rules/restoration/config/config.php
Normal file
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
|
||||
|
||||
return static function (ContainerConfigurator $containerConfigurator): void {
|
||||
$services = $containerConfigurator->services();
|
||||
|
||||
$services->defaults()
|
||||
->public()
|
||||
->autowire();
|
||||
|
||||
$services->load('Rector\Restoration\\', __DIR__ . '/../src')
|
||||
->exclude([__DIR__ . '/../src/Rector', __DIR__ . '/../src/ValueObject']);
|
||||
};
|
84
rules/restoration/src/ClassMap/ExistingClassesProvider.php
Normal file
84
rules/restoration/src/ClassMap/ExistingClassesProvider.php
Normal file
@ -0,0 +1,84 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Restoration\ClassMap;
|
||||
|
||||
use Nette\Loaders\RobotLoader;
|
||||
use Symplify\ComposerJsonManipulator\ComposerJsonFactory;
|
||||
|
||||
final class ExistingClassesProvider
|
||||
{
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
private $existingClasses = [];
|
||||
|
||||
/**
|
||||
* @var ComposerJsonFactory
|
||||
*/
|
||||
private $composerJsonFactory;
|
||||
|
||||
public function __construct(ComposerJsonFactory $composerJsonFactory)
|
||||
{
|
||||
$this->composerJsonFactory = $composerJsonFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function provide(): array
|
||||
{
|
||||
if ($this->existingClasses === []) {
|
||||
$psr4Paths = $this->getPsr4PathFromComposerJson();
|
||||
|
||||
$existingClasses = $this->findClassesInDirectories($psr4Paths);
|
||||
|
||||
/** @var string[] $existingClasses */
|
||||
$existingClasses = array_merge($existingClasses, get_declared_classes());
|
||||
|
||||
$this->existingClasses = $existingClasses;
|
||||
}
|
||||
|
||||
return $this->existingClasses;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
private function getPsr4PathFromComposerJson(): array
|
||||
{
|
||||
$composerJsonFilePath = getcwd() . '/composer.json';
|
||||
$composerJson = $this->composerJsonFactory->createFromFilePath($composerJsonFilePath);
|
||||
|
||||
$psr4Paths = $composerJson->getAutoload()['psr-4'] ?? [];
|
||||
$classmapPaths = $composerJson->getAutoload()['classmap'] ?? [];
|
||||
|
||||
return array_merge($psr4Paths, $classmapPaths);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $directories
|
||||
* @return string[]
|
||||
*/
|
||||
private function findClassesInDirectories(array $directories): array
|
||||
{
|
||||
$robotLoader = new RobotLoader();
|
||||
$robotLoader->setTempDirectory(sys_get_temp_dir() . '/rector_restore');
|
||||
|
||||
foreach ($directories as $path) {
|
||||
$robotLoader->addDirectory(getcwd() . '/' . $path);
|
||||
}
|
||||
|
||||
$classNames = [];
|
||||
foreach (array_keys($robotLoader->getIndexedClasses()) as $className) {
|
||||
if (! is_string($className)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$classNames[] = $className;
|
||||
}
|
||||
|
||||
return $classNames;
|
||||
}
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Restoration\NameMatcher;
|
||||
|
||||
use PhpParser\Node\Identifier;
|
||||
use PhpParser\Node\Name;
|
||||
use PhpParser\Node\Name\FullyQualified;
|
||||
use PhpParser\Node\NullableType;
|
||||
use PhpParser\Node\UnionType;
|
||||
use Rector\NodeNameResolver\NodeNameResolver;
|
||||
use Rector\NodeTypeResolver\ClassExistenceStaticHelper;
|
||||
|
||||
final class FullyQualifiedNameMatcher
|
||||
{
|
||||
/**
|
||||
* @var NodeNameResolver
|
||||
*/
|
||||
private $nodeNameResolver;
|
||||
|
||||
/**
|
||||
* @var NameMatcher
|
||||
*/
|
||||
private $nameMatcher;
|
||||
|
||||
public function __construct(NodeNameResolver $nodeNameResolver, NameMatcher $nameMatcher)
|
||||
{
|
||||
$this->nodeNameResolver = $nodeNameResolver;
|
||||
$this->nameMatcher = $nameMatcher;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|Name|Identifier|FullyQualified|UnionType|NullableType|null $name
|
||||
* @return NullableType|FullyQualified|null
|
||||
*/
|
||||
public function matchFullyQualifiedName($name)
|
||||
{
|
||||
if ($name instanceof NullableType) {
|
||||
$fullyQulifiedNullableType = $this->matchFullyQualifiedName($name->type);
|
||||
if (! $fullyQulifiedNullableType instanceof Name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new NullableType($fullyQulifiedNullableType);
|
||||
}
|
||||
|
||||
if ($name instanceof Name) {
|
||||
if (count($name->parts) !== 1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$resolvedName = $this->nodeNameResolver->getName($name);
|
||||
if ($resolvedName === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (ClassExistenceStaticHelper::doesClassLikeExist($resolvedName)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$fullyQualified = $this->nameMatcher->makeNameFullyQualified($resolvedName);
|
||||
if ($fullyQualified === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new FullyQualified($fullyQualified);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
35
rules/restoration/src/NameMatcher/NameMatcher.php
Normal file
35
rules/restoration/src/NameMatcher/NameMatcher.php
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Restoration\NameMatcher;
|
||||
|
||||
use Nette\Utils\Strings;
|
||||
use Rector\Restoration\ClassMap\ExistingClassesProvider;
|
||||
|
||||
final class NameMatcher
|
||||
{
|
||||
/**
|
||||
* @var ExistingClassesProvider
|
||||
*/
|
||||
private $existingClassesProvider;
|
||||
|
||||
public function __construct(ExistingClassesProvider $existingClassesProvider)
|
||||
{
|
||||
$this->existingClassesProvider = $existingClassesProvider;
|
||||
}
|
||||
|
||||
public function makeNameFullyQualified(string $shortName): ?string
|
||||
{
|
||||
foreach ($this->existingClassesProvider->provide() as $declaredClass) {
|
||||
$declaredShortClass = (string) Strings::after($declaredClass, '\\', -1);
|
||||
if ($declaredShortClass !== $shortName) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return $declaredClass;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Restoration\NameMatcher;
|
||||
|
||||
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
|
||||
use Rector\AttributeAwarePhpDoc\Ast\Type\AttributeAwareFullyQualifiedIdentifierTypeNode;
|
||||
|
||||
final class PhpDocTypeNodeNameMatcher
|
||||
{
|
||||
/**
|
||||
* @var NameMatcher
|
||||
*/
|
||||
private $nameMatcher;
|
||||
|
||||
public function __construct(NameMatcher $nameMatcher)
|
||||
{
|
||||
$this->nameMatcher = $nameMatcher;
|
||||
}
|
||||
|
||||
public function matchIdentifier(string $name): ?TypeNode
|
||||
{
|
||||
$name = ltrim($name, '\\');
|
||||
|
||||
$fullyQualified = $this->nameMatcher->makeNameFullyQualified($name);
|
||||
if ($fullyQualified === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new AttributeAwareFullyQualifiedIdentifierTypeNode($fullyQualified);
|
||||
}
|
||||
}
|
@ -0,0 +1,180 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Restoration\Rector\Use_;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Name;
|
||||
use PhpParser\Node\Name\FullyQualified;
|
||||
use PhpParser\Node\Param;
|
||||
use PhpParser\Node\Stmt\ClassMethod;
|
||||
use PhpParser\Node\Stmt\Use_;
|
||||
use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
|
||||
use PHPStan\Type\MixedType;
|
||||
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
use Rector\Core\RectorDefinition\CodeSample;
|
||||
use Rector\Core\RectorDefinition\RectorDefinition;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
use Rector\Restoration\NameMatcher\FullyQualifiedNameMatcher;
|
||||
use Rector\Restoration\NameMatcher\PhpDocTypeNodeNameMatcher;
|
||||
|
||||
/**
|
||||
* @see \Rector\Restoration\Tests\Rector\Use_\RestoreFullyQualifiedNameRector\RestoreFullyQualifiedNameRectorTest
|
||||
*/
|
||||
final class RestoreFullyQualifiedNameRector extends AbstractRector
|
||||
{
|
||||
/**
|
||||
* @var FullyQualifiedNameMatcher
|
||||
*/
|
||||
private $fullyQualifiedNameMatcher;
|
||||
|
||||
/**
|
||||
* @var PhpDocTypeNodeNameMatcher
|
||||
*/
|
||||
private $phpDocTypeNodeNameMatcher;
|
||||
|
||||
public function __construct(
|
||||
FullyQualifiedNameMatcher $fullyQualifiedNameMatcher,
|
||||
PhpDocTypeNodeNameMatcher $phpDocTypeNodeNameMatcher
|
||||
) {
|
||||
$this->fullyQualifiedNameMatcher = $fullyQualifiedNameMatcher;
|
||||
$this->phpDocTypeNodeNameMatcher = $phpDocTypeNodeNameMatcher;
|
||||
}
|
||||
|
||||
public function getDefinition(): RectorDefinition
|
||||
{
|
||||
return new RectorDefinition(
|
||||
'Restore accidentally shortened class names to its fully qualified form.',
|
||||
[
|
||||
new CodeSample(
|
||||
<<<'CODE_SAMPLE'
|
||||
use ShortClassOnly;
|
||||
|
||||
class AnotherClass
|
||||
{
|
||||
}
|
||||
CODE_SAMPLE
|
||||
|
||||
,
|
||||
<<<'CODE_SAMPLE'
|
||||
use App\Whatever\ShortClassOnly;
|
||||
|
||||
class AnotherClass
|
||||
{
|
||||
}
|
||||
CODE_SAMPLE
|
||||
|
||||
),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function getNodeTypes(): array
|
||||
{
|
||||
return [Use_::class, Param::class, ClassMethod::class];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Use_|Param|ClassMethod $node
|
||||
*/
|
||||
public function refactor(Node $node): ?Node
|
||||
{
|
||||
if ($node instanceof Use_) {
|
||||
return $this->refactoryUse($node);
|
||||
}
|
||||
|
||||
if ($node instanceof Param) {
|
||||
return $this->refactorParam($node);
|
||||
}
|
||||
|
||||
if ($node instanceof ClassMethod) {
|
||||
return $this->refactorClassMethod($node);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private function refactoryUse(Use_ $use): Use_
|
||||
{
|
||||
foreach ($use->uses as $useUse) {
|
||||
$name = $useUse->name;
|
||||
|
||||
$fullyQualifiedName = $this->fullyQualifiedNameMatcher->matchFullyQualifiedName($name);
|
||||
if (! $fullyQualifiedName instanceof FullyQualified) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$useUse->name = $fullyQualifiedName;
|
||||
}
|
||||
|
||||
return $use;
|
||||
}
|
||||
|
||||
private function refactorParam(Param $param): ?Param
|
||||
{
|
||||
$name = $param->type;
|
||||
if (! $name instanceof Name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$fullyQualified = $this->fullyQualifiedNameMatcher->matchFullyQualifiedName($name);
|
||||
if ($fullyQualified === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$param->type = $fullyQualified;
|
||||
return $param;
|
||||
}
|
||||
|
||||
private function refactorClassMethod(ClassMethod $classMethod): ?ClassMethod
|
||||
{
|
||||
$this->refactorReturnTagValueNode($classMethod);
|
||||
|
||||
$returnType = $classMethod->returnType;
|
||||
if ($returnType === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$fullyQualified = $this->fullyQualifiedNameMatcher->matchFullyQualifiedName($returnType);
|
||||
if ($fullyQualified === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$classMethod->returnType = $fullyQualified;
|
||||
|
||||
return $classMethod;
|
||||
}
|
||||
|
||||
private function refactorReturnTagValueNode(Node $node): void
|
||||
{
|
||||
/** @var PhpDocInfo|null $phpDocInfo */
|
||||
$phpDocInfo = $node->getAttribute(AttributeKey::PHP_DOC_INFO);
|
||||
if (! $phpDocInfo instanceof PhpDocInfo) {
|
||||
return;
|
||||
}
|
||||
|
||||
$attributeAwareReturnTagValueNode = $phpDocInfo->getReturnTagValue();
|
||||
if ($attributeAwareReturnTagValueNode === null) {
|
||||
return;
|
||||
}
|
||||
if (! $phpDocInfo->getReturnType() instanceof MixedType) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($attributeAwareReturnTagValueNode->type instanceof IdentifierTypeNode) {
|
||||
$fullyQualifiedTypeNode = $this->phpDocTypeNodeNameMatcher->matchIdentifier(
|
||||
$attributeAwareReturnTagValueNode->type->name
|
||||
);
|
||||
if ($fullyQualifiedTypeNode === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$attributeAwareReturnTagValueNode->type = $fullyQualifiedTypeNode;
|
||||
}
|
||||
}
|
||||
}
|
@ -12,7 +12,7 @@ use Symplify\SmartFileSystem\SmartFileInfo;
|
||||
final class MakeTypedPropertyNullableIfCheckedRectorTest extends AbstractRectorTestCase
|
||||
{
|
||||
/**
|
||||
* @requires PHP >= 7.4
|
||||
* @requires PHP 7.4
|
||||
* @dataProvider provideData()
|
||||
*/
|
||||
public function test(SmartFileInfo $fileInfo): void
|
||||
|
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace Rector\Restoration\Tests\Rector\Use_\RestoreFullyQualifiedNameRector\Fixture;
|
||||
|
||||
use ShortClassOnly;
|
||||
|
||||
class AnotherClass
|
||||
{
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Restoration\Tests\Rector\Use_\RestoreFullyQualifiedNameRector\Fixture;
|
||||
|
||||
use Rector\Restoration\Tests\Rector\Use_\RestoreFullyQualifiedNameRector\Source\ShortClassOnly;
|
||||
|
||||
class AnotherClass
|
||||
{
|
||||
}
|
||||
|
||||
?>
|
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace Rector\Restoration\Tests\Rector\Use_\RestoreFullyQualifiedNameRector\Fixture;
|
||||
|
||||
class ParamType
|
||||
{
|
||||
public function run(\ShortClassOnly $shortClassOnly)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Restoration\Tests\Rector\Use_\RestoreFullyQualifiedNameRector\Fixture;
|
||||
|
||||
class ParamType
|
||||
{
|
||||
public function run(\Rector\Restoration\Tests\Rector\Use_\RestoreFullyQualifiedNameRector\Source\ShortClassOnly $shortClassOnly)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace Rector\Restoration\Tests\Rector\Use_\RestoreFullyQualifiedNameRector\Fixture;
|
||||
|
||||
class ReturnNullableType
|
||||
{
|
||||
public function get($shortClassOnly): ?\ShortClassOnly
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Restoration\Tests\Rector\Use_\RestoreFullyQualifiedNameRector\Fixture;
|
||||
|
||||
class ReturnNullableType
|
||||
{
|
||||
public function get($shortClassOnly): ?\Rector\Restoration\Tests\Rector\Use_\RestoreFullyQualifiedNameRector\Source\ShortClassOnly
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace Rector\Restoration\Tests\Rector\Use_\RestoreFullyQualifiedNameRector\Fixture;
|
||||
|
||||
class ReturnTagType
|
||||
{
|
||||
/**
|
||||
* @return \ShortClassOnly
|
||||
*/
|
||||
public function get($shortClassOnly)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Restoration\Tests\Rector\Use_\RestoreFullyQualifiedNameRector\Fixture;
|
||||
|
||||
class ReturnTagType
|
||||
{
|
||||
/**
|
||||
* @return \Rector\Restoration\Tests\Rector\Use_\RestoreFullyQualifiedNameRector\Source\ShortClassOnly
|
||||
*/
|
||||
public function get($shortClassOnly)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace Rector\Restoration\Tests\Rector\Use_\RestoreFullyQualifiedNameRector\Fixture;
|
||||
|
||||
class ReturnType
|
||||
{
|
||||
public function get($shortClassOnly): \ShortClassOnly
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Restoration\Tests\Rector\Use_\RestoreFullyQualifiedNameRector\Fixture;
|
||||
|
||||
class ReturnType
|
||||
{
|
||||
public function get($shortClassOnly): \Rector\Restoration\Tests\Rector\Use_\RestoreFullyQualifiedNameRector\Source\ShortClassOnly
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Restoration\Tests\Rector\Use_\RestoreFullyQualifiedNameRector;
|
||||
|
||||
use Iterator;
|
||||
use Rector\Core\Testing\PHPUnit\AbstractRectorTestCase;
|
||||
use Rector\Restoration\Rector\Use_\RestoreFullyQualifiedNameRector;
|
||||
use Symplify\SmartFileSystem\SmartFileInfo;
|
||||
|
||||
final class RestoreFullyQualifiedNameRectorTest extends AbstractRectorTestCase
|
||||
{
|
||||
/**
|
||||
* @dataProvider provideData()
|
||||
*/
|
||||
public function test(SmartFileInfo $fileInfo): void
|
||||
{
|
||||
$this->doTestFileInfo($fileInfo);
|
||||
}
|
||||
|
||||
public function provideData(): Iterator
|
||||
{
|
||||
return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture');
|
||||
}
|
||||
|
||||
protected function getRectorClass(): string
|
||||
{
|
||||
return RestoreFullyQualifiedNameRector::class;
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Restoration\Tests\Rector\Use_\RestoreFullyQualifiedNameRector\Source;
|
||||
|
||||
final class ShortClassOnly
|
||||
{
|
||||
|
||||
}
|
@ -13,7 +13,7 @@ use Symplify\SmartFileSystem\SmartFileInfo;
|
||||
final class PropertyTypeParamTypeDeclarationRectorTest extends AbstractRectorTestCase
|
||||
{
|
||||
/**
|
||||
* @requires PHP >= 7.4
|
||||
* @requires PHP 7.4
|
||||
* @dataProvider provideData()
|
||||
*/
|
||||
public function test(SmartFileInfo $fileInfo): void
|
||||
|
@ -11,7 +11,7 @@ use Rector\TypeDeclaration\Rector\Property\PropertyTypeDeclarationRector;
|
||||
use Symplify\SmartFileSystem\SmartFileInfo;
|
||||
|
||||
/**
|
||||
* @requires PHP >= 7.4
|
||||
* @requires PHP 7.4
|
||||
*/
|
||||
final class Php74Test extends AbstractRectorTestCase
|
||||
{
|
||||
|
@ -20,6 +20,7 @@ use Symfony\Component\HttpKernel\Bundle\BundleInterface;
|
||||
use Symfony\Component\HttpKernel\Config\FileLocator;
|
||||
use Symfony\Component\HttpKernel\Kernel;
|
||||
use Symplify\AutowireArrayParameter\DependencyInjection\CompilerPass\AutowireArrayParameterCompilerPass;
|
||||
use Symplify\ComposerJsonManipulator\ComposerJsonManipulatorBundle;
|
||||
use Symplify\ConsoleColorDiff\ConsoleColorDiffBundle;
|
||||
use Symplify\PackageBuilder\Contract\HttpKernel\ExtraConfigAwareKernelInterface;
|
||||
use Symplify\PackageBuilder\DependencyInjection\CompilerPass\AutowireInterfacesCompilerPass;
|
||||
@ -77,7 +78,7 @@ final class RectorKernel extends Kernel implements ExtraConfigAwareKernelInterfa
|
||||
*/
|
||||
public function registerBundles(): array
|
||||
{
|
||||
return [new ConsoleColorDiffBundle(), new PhpConfigPrinterBundle()];
|
||||
return [new ConsoleColorDiffBundle(), new PhpConfigPrinterBundle(), new ComposerJsonManipulatorBundle()];
|
||||
}
|
||||
|
||||
protected function build(ContainerBuilder $containerBuilder): void
|
||||
|
@ -9,6 +9,8 @@ use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\Array_;
|
||||
use PhpParser\Node\Expr\Closure;
|
||||
use PhpParser\Node\Expr\Yield_;
|
||||
use PhpParser\Node\Name;
|
||||
use PhpParser\Node\Name\FullyQualified;
|
||||
use PhpParser\Node\Scalar\DNumber;
|
||||
use PhpParser\Node\Scalar\EncapsedStringPart;
|
||||
use PhpParser\Node\Scalar\String_;
|
||||
@ -19,6 +21,7 @@ use PhpParser\Node\Stmt\Declare_;
|
||||
use PhpParser\Node\Stmt\Expression;
|
||||
use PhpParser\Node\Stmt\Nop;
|
||||
use PhpParser\Node\Stmt\TraitUse;
|
||||
use PhpParser\Node\Stmt\Use_;
|
||||
use PhpParser\PrettyPrinter\Standard;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
use Rector\NodeTypeResolver\PhpDoc\NodeAnalyzer\DocBlockManipulator;
|
||||
@ -401,6 +404,22 @@ final class BetterStandardPrinter extends Standard
|
||||
return Strings::replace($declareString, '#\s+#');
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove extra \\ from FQN use imports, for easier use in the code
|
||||
*/
|
||||
protected function pStmt_Use(Use_ $use): string
|
||||
{
|
||||
if ($use->type === Use_::TYPE_NORMAL) {
|
||||
foreach ($use->uses as $useUse) {
|
||||
if ($useUse->name instanceof FullyQualified) {
|
||||
$useUse->name = new Name($useUse->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return parent::pStmt_Use($use);
|
||||
}
|
||||
|
||||
/**
|
||||
* Solves https://github.com/rectorphp/rector/issues/1964
|
||||
*
|
||||
|
@ -11,10 +11,6 @@ services:
|
||||
class: Rector\PHPStanExtensions\Rule\KeepRectorNamespaceForRectorRule
|
||||
tags: [phpstan.rules.rule]
|
||||
|
||||
-
|
||||
class: Rector\PHPStanExtensions\Rule\CheckNotTestsNamespaceOutsideTestsDirectoryRule
|
||||
tags: [phpstan.rules.rule]
|
||||
|
||||
-
|
||||
class: Rector\PHPStanExtensions\Rule\ConfigurableRectorRule
|
||||
tags: [phpstan.rules.rule]
|
||||
|
@ -1,83 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\PHPStanExtensions\Rule;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Name;
|
||||
use PhpParser\Node\Stmt\Namespace_;
|
||||
use PHPStan\Analyser\Scope;
|
||||
use PHPStan\Rules\Rule;
|
||||
|
||||
/**
|
||||
* @see \Rector\PHPStanExtensions\Tests\Rule\CheckNotTestsNamespaceOutsideTestsDirectoryRule\CheckNotTestsNamespaceOutsideTestsDirectoryRuleTest
|
||||
*/
|
||||
final class CheckNotTestsNamespaceOutsideTestsDirectoryRule implements Rule
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private const ERROR_NAMESPACE_OUTSIDE_TEST_DIR = '"Tests" namespace (%s) used outside of "tests" directory (%s)';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private const ERROR_TEST_FILE_OUTSIDE_NAMESPACE = 'Test file (%s) is outside of "Tests" namespace (%s)';
|
||||
|
||||
public function getNodeType(): string
|
||||
{
|
||||
return Namespace_::class;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Namespace_ $node
|
||||
* @return string[]
|
||||
*/
|
||||
public function processNode(Node $node, Scope $scope): array
|
||||
{
|
||||
if ($node->name === null) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (! $this->hasTestsNamespace($node->name)) {
|
||||
if ($this->hasTestSuffix($scope)) {
|
||||
$errorMessage = sprintf(
|
||||
self::ERROR_TEST_FILE_OUTSIDE_NAMESPACE,
|
||||
$scope->getFileDescription(),
|
||||
$node->name->toString()
|
||||
);
|
||||
return [$errorMessage];
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
if ($this->inTestsDirectory($scope)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$errorMessage = sprintf(
|
||||
self::ERROR_NAMESPACE_OUTSIDE_TEST_DIR,
|
||||
$node->name->toString(),
|
||||
$scope->getFileDescription()
|
||||
);
|
||||
|
||||
return [$errorMessage];
|
||||
}
|
||||
|
||||
private function hasTestsNamespace(Name $name): bool
|
||||
{
|
||||
return in_array('Tests', $name->parts, true);
|
||||
}
|
||||
|
||||
private function hasTestSuffix(Scope $scope): bool
|
||||
{
|
||||
return strstr($scope->getFileDescription(), 'Test.php') !== false;
|
||||
}
|
||||
|
||||
private function inTestsDirectory(Scope $scope): bool
|
||||
{
|
||||
return strstr($scope->getFileDescription(), '/tests/') !== false;
|
||||
}
|
||||
}
|
@ -7,12 +7,12 @@ namespace Rector\PHPStanExtensions\Tests\Rule\CheckGetNodeTypesReturnPhpParserNo
|
||||
use Iterator;
|
||||
use PhpParser\Node;
|
||||
use PHPStan\Rules\Rule;
|
||||
use PHPStan\Testing\RuleTestCase;
|
||||
use Rector\PHPStanExtensions\Rule\CheckGetNodeTypesReturnPhpParserNodeRule;
|
||||
use Rector\PHPStanExtensions\Tests\Rule\CheckGetNodeTypesReturnPhpParserNodeRule\Fixture\IncorrectReturnRector;
|
||||
use Rector\PHPStanExtensions\Tests\Rule\CheckGetNodeTypesReturnPhpParserNodeRule\Source\ClassNotOfPhpParserNode;
|
||||
use Symplify\PHPStanExtensions\Testing\AbstractServiceAwareRuleTestCase;
|
||||
|
||||
final class CheckGetNodeTypesReturnPhpParserNodeRuleTest extends RuleTestCase
|
||||
final class CheckGetNodeTypesReturnPhpParserNodeRuleTest extends AbstractServiceAwareRuleTestCase
|
||||
{
|
||||
/**
|
||||
* @dataProvider provideData()
|
||||
@ -39,6 +39,9 @@ final class CheckGetNodeTypesReturnPhpParserNodeRuleTest extends RuleTestCase
|
||||
|
||||
protected function getRule(): Rule
|
||||
{
|
||||
return new CheckGetNodeTypesReturnPhpParserNodeRule();
|
||||
return $this->getRuleFromConfig(
|
||||
CheckGetNodeTypesReturnPhpParserNodeRule::class,
|
||||
__DIR__ . '/../../../config/phpstan-extensions.neon'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,31 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\PHPStanExtensions\Tests\Rule\CheckNotTestsNamespaceOutsideTestsDirectoryRule;
|
||||
|
||||
use Iterator;
|
||||
use PHPStan\Rules\Rule;
|
||||
use PHPStan\Testing\RuleTestCase;
|
||||
use Rector\PHPStanExtensions\Rule\CheckNotTestsNamespaceOutsideTestsDirectoryRule;
|
||||
|
||||
final class CheckNotTestsNamespaceOutsideTestsDirectoryRuleTest extends RuleTestCase
|
||||
{
|
||||
/**
|
||||
* @dataProvider provideData()
|
||||
*/
|
||||
public function testRule(string $filePath, array $expectedErrorsWithLines): void
|
||||
{
|
||||
$this->analyse([$filePath], $expectedErrorsWithLines);
|
||||
}
|
||||
|
||||
public function provideData(): Iterator
|
||||
{
|
||||
yield [__DIR__ . '/Fixture/tests/TestsNamespaceInsideTestsDirectoryClass.php', []];
|
||||
}
|
||||
|
||||
protected function getRule(): Rule
|
||||
{
|
||||
return new CheckNotTestsNamespaceOutsideTestsDirectoryRule();
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Rector\PHPStanExtensions\Tests\Rule\CheckNotTestsNamespaceOutsideTestsDirectoryRule\Fixture\Tests;
|
||||
|
||||
|
||||
class TestsNamespaceInsideTestsDirectoryClass
|
||||
{
|
||||
|
||||
}
|
@ -6,10 +6,10 @@ namespace Rector\PHPStanExtensions\Tests\Rule\ConfigurableRectorRule;
|
||||
|
||||
use Iterator;
|
||||
use PHPStan\Rules\Rule;
|
||||
use PHPStan\Testing\RuleTestCase;
|
||||
use Rector\PHPStanExtensions\Rule\ConfigurableRectorRule;
|
||||
use Symplify\PHPStanExtensions\Testing\AbstractServiceAwareRuleTestCase;
|
||||
|
||||
final class ConfigurableRectorRuleTest extends RuleTestCase
|
||||
final class ConfigurableRectorRuleTest extends AbstractServiceAwareRuleTestCase
|
||||
{
|
||||
/**
|
||||
* @dataProvider provideData()
|
||||
@ -34,16 +34,16 @@ final class ConfigurableRectorRuleTest extends RuleTestCase
|
||||
];
|
||||
|
||||
yield [__DIR__ . '/Fixture/NotImplementsAndHasNoConfiguredCodeSampleRector.php', []];
|
||||
|
||||
yield [__DIR__ . '/Fixture/ImplementsThroughAbstractClassRector.php', []];
|
||||
|
||||
yield [__DIR__ . '/Fixture/SkipClassNamesWithoutRectorSuffix.php', []];
|
||||
|
||||
yield [__DIR__ . '/Fixture/SkipAbstractRector.php', []];
|
||||
}
|
||||
|
||||
protected function getRule(): Rule
|
||||
{
|
||||
return new ConfigurableRectorRule();
|
||||
return $this->getRuleFromConfig(
|
||||
ConfigurableRectorRule::class,
|
||||
__DIR__ . '/../../../config/phpstan-extensions.neon'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -6,10 +6,10 @@ namespace Rector\PHPStanExtensions\Tests\Rule\KeepRectorNamespaceForRectorRule;
|
||||
|
||||
use Iterator;
|
||||
use PHPStan\Rules\Rule;
|
||||
use PHPStan\Testing\RuleTestCase;
|
||||
use Rector\PHPStanExtensions\Rule\KeepRectorNamespaceForRectorRule;
|
||||
use Symplify\PHPStanExtensions\Testing\AbstractServiceAwareRuleTestCase;
|
||||
|
||||
final class KeepRectorNamespaceForRectorRuleTest extends RuleTestCase
|
||||
final class KeepRectorNamespaceForRectorRuleTest extends AbstractServiceAwareRuleTestCase
|
||||
{
|
||||
/**
|
||||
* @dataProvider provideData()
|
||||
@ -29,6 +29,9 @@ final class KeepRectorNamespaceForRectorRuleTest extends RuleTestCase
|
||||
|
||||
protected function getRule(): Rule
|
||||
{
|
||||
return new KeepRectorNamespaceForRectorRule();
|
||||
return $this->getRuleFromConfig(
|
||||
KeepRectorNamespaceForRectorRule::class,
|
||||
__DIR__ . '/../../../config/phpstan-extensions.neon'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -6,10 +6,10 @@ namespace Rector\PHPStanExtensions\Tests\Rule\RectorRuleAndValueObjectHaveSameSt
|
||||
|
||||
use Iterator;
|
||||
use PHPStan\Rules\Rule;
|
||||
use PHPStan\Testing\RuleTestCase;
|
||||
use Rector\PHPStanExtensions\Rule\RectorRuleAndValueObjectHaveSameStartsRule;
|
||||
use Symplify\PHPStanExtensions\Testing\AbstractServiceAwareRuleTestCase;
|
||||
|
||||
final class RectorRuleAndValueObjectHaveSameStartsRuleTest extends RuleTestCase
|
||||
final class RectorRuleAndValueObjectHaveSameStartsRuleTest extends AbstractServiceAwareRuleTestCase
|
||||
{
|
||||
/**
|
||||
* @dataProvider provideData()
|
||||
@ -22,12 +22,10 @@ final class RectorRuleAndValueObjectHaveSameStartsRuleTest extends RuleTestCase
|
||||
public function provideData(): Iterator
|
||||
{
|
||||
yield [__DIR__ . '/Fixture/HaveSameStarts.php', []];
|
||||
|
||||
yield [__DIR__ . '/Fixture/SkipNoCall.php', []];
|
||||
|
||||
yield [__DIR__ . '/Fixture/SkipNoCallConfigure.php', []];
|
||||
|
||||
yield [__DIR__ . '/Fixture/SkipNoInlineValueObjects.php', []];
|
||||
yield [__DIR__ . '/Fixture/SkipConfigureValueObjectImplementsInterface.php', []];
|
||||
|
||||
$errorMessage = sprintf(
|
||||
RectorRuleAndValueObjectHaveSameStartsRule::ERROR,
|
||||
@ -35,12 +33,13 @@ final class RectorRuleAndValueObjectHaveSameStartsRuleTest extends RuleTestCase
|
||||
'ChangeMethodVisibility'
|
||||
);
|
||||
yield [__DIR__ . '/Fixture/HaveDifferentStarts.php', [[$errorMessage, 15]]];
|
||||
|
||||
yield [__DIR__ . '/Fixture/SkipConfigureValueObjectImplementsInterface.php', []];
|
||||
}
|
||||
|
||||
protected function getRule(): Rule
|
||||
{
|
||||
return new RectorRuleAndValueObjectHaveSameStartsRule();
|
||||
return $this->getRuleFromConfig(
|
||||
RectorRuleAndValueObjectHaveSameStartsRule::class,
|
||||
__DIR__ . '/../../../config/phpstan-extensions.neon'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -6,11 +6,11 @@ namespace Rector\PHPStanExtensions\Tests\Rule\RequireRectorCategoryByGetNodeType
|
||||
|
||||
use Iterator;
|
||||
use PHPStan\Rules\Rule;
|
||||
use PHPStan\Testing\RuleTestCase;
|
||||
use Rector\PHPStanExtensions\Rule\RequireRectorCategoryByGetNodeTypesRule;
|
||||
use Rector\PHPStanExtensions\Tests\Rule\RequireRectorCategoryByGetNodeTypesRule\Fixture\ClassMethod\ChangeSomethingRector;
|
||||
use Symplify\PHPStanExtensions\Testing\AbstractServiceAwareRuleTestCase;
|
||||
|
||||
final class RequireRectorCategoryByGetNodeTypesRuleTest extends RuleTestCase
|
||||
final class RequireRectorCategoryByGetNodeTypesRuleTest extends AbstractServiceAwareRuleTestCase
|
||||
{
|
||||
/**
|
||||
* @dataProvider provideData()
|
||||
@ -28,17 +28,18 @@ final class RequireRectorCategoryByGetNodeTypesRuleTest extends RuleTestCase
|
||||
'ClassMethod',
|
||||
'String_'
|
||||
);
|
||||
|
||||
yield [__DIR__ . '/Fixture/ClassMethod/ChangeSomethingRector.php', [[$errorMessage, 14]]];
|
||||
|
||||
yield [__DIR__ . '/Fixture/FunctionLike/SkipSubtypeRector.php', []];
|
||||
|
||||
yield [__DIR__ . '/Fixture/ClassMethod/SkipInterface.php', []];
|
||||
|
||||
yield [__DIR__ . '/Fixture/AbstractSkip.php', []];
|
||||
}
|
||||
|
||||
protected function getRule(): Rule
|
||||
{
|
||||
return new RequireRectorCategoryByGetNodeTypesRule();
|
||||
return $this->getRuleFromConfig(
|
||||
RequireRectorCategoryByGetNodeTypesRule::class,
|
||||
__DIR__ . '/../../../config/phpstan-extensions.neon'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -6,10 +6,10 @@ namespace Rector\PHPStanExtensions\Tests\Rule\ValueObjectHasNoValueObjectSuffixR
|
||||
|
||||
use Iterator;
|
||||
use PHPStan\Rules\Rule;
|
||||
use PHPStan\Testing\RuleTestCase;
|
||||
use Rector\PHPStanExtensions\Rule\ValueObjectHasNoValueObjectSuffixRule;
|
||||
use Symplify\PHPStanExtensions\Testing\AbstractServiceAwareRuleTestCase;
|
||||
|
||||
final class ValueObjectHasNoValueObjectSuffixRuleTest extends RuleTestCase
|
||||
final class ValueObjectHasNoValueObjectSuffixRuleTest extends AbstractServiceAwareRuleTestCase
|
||||
{
|
||||
/**
|
||||
* @dataProvider provideData()
|
||||
|
Loading…
x
Reference in New Issue
Block a user