[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:
Tomas Votruba 2020-10-01 21:45:29 +02:00 committed by GitHub
parent ae816c2c3d
commit 8ae3868a57
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
51 changed files with 760 additions and 227 deletions

View File

@ -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": {

View File

@ -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)

View File

@ -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'],
]);

View File

@ -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);
}
}

View File

@ -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

View File

@ -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
*/

View File

@ -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()

View File

@ -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
{

View File

@ -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
{

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
{

View File

@ -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

View File

@ -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
{

View File

@ -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

View File

@ -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

View File

@ -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

View 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']);
};

View 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;
}
}

View File

@ -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;
}
}

View 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;
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}
}

View File

@ -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

View File

@ -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
{
}
?>

View File

@ -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)
{
}
}
?>

View File

@ -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
{
}
}
?>

View File

@ -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)
{
}
}
?>

View File

@ -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
{
}
}
?>

View File

@ -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;
}
}

View File

@ -0,0 +1,10 @@
<?php
declare(strict_types=1);
namespace Rector\Restoration\Tests\Rector\Use_\RestoreFullyQualifiedNameRector\Source;
final class ShortClassOnly
{
}

View File

@ -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

View File

@ -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
{

View File

@ -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

View File

@ -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
*

View File

@ -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]

View File

@ -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;
}
}

View File

@ -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'
);
}
}

View File

@ -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();
}
}

View File

@ -1,10 +0,0 @@
<?php
namespace Rector\PHPStanExtensions\Tests\Rule\CheckNotTestsNamespaceOutsideTestsDirectoryRule\Fixture\Tests;
class TestsNamespaceInsideTestsDirectoryClass
{
}

View File

@ -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'
);
}
}

View File

@ -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'
);
}
}

View File

@ -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'
);
}
}

View File

@ -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'
);
}
}

View File

@ -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()