mirror of
https://github.com/rectorphp/rector.git
synced 2025-01-17 05:18:18 +01:00
[CI] simplify php linter (#5867)
* [CI] simplify php linter * [CI] merge code analysis to one * [docs] remove nodes overview, already in external repository * remove unused ci job * [CI] check annotation parser + sync * [DeadCode] Remove RemoveEmptyAbstractClassRector, not reliable with static-reflection, opionated * [CI] remove set validation, PHPStan handles this better with PHP * remove dead-code-strict [skip ci]
This commit is contained in:
parent
68bf6e8de8
commit
683f8319a8
17
.github/workflows/code_analysis.yaml
vendored
17
.github/workflows/code_analysis.yaml
vendored
@ -18,15 +18,22 @@ jobs:
|
||||
name: Validate Fixtures skip file prefix
|
||||
run: vendor/symplify/easy-testing/bin/easy-testing validate-fixture-skip-naming rules tests
|
||||
|
||||
-
|
||||
name: 'Validate Sets Loading'
|
||||
# this is very slow, so it has to be in own workflow
|
||||
run: bin/rector validate-sets --ansi
|
||||
|
||||
-
|
||||
name: 'Validate Max File Length'
|
||||
run: vendor/bin/easy-ci validate-file-length packages rules src tests
|
||||
|
||||
-
|
||||
name: 'PHPStan'
|
||||
run: vendor/bin/phpstan analyse --ansi --error-format symplify
|
||||
|
||||
-
|
||||
name: 'PHPStan for config'
|
||||
run: composer phpstan-config
|
||||
|
||||
-
|
||||
name: "Check doctrine/annotation"
|
||||
run: "bin/rector sync-annotation-parser --dry-run --ansi"
|
||||
|
||||
# see https://github.com/rectorphp/rector-generator
|
||||
-
|
||||
name: 'Rector Generate From Recipe'
|
||||
|
35
.github/workflows/code_analysis_php80.yaml
vendored
35
.github/workflows/code_analysis_php80.yaml
vendored
@ -1,35 +0,0 @@
|
||||
name: Code Analysis PHP 8.0
|
||||
|
||||
on:
|
||||
pull_request: null
|
||||
|
||||
jobs:
|
||||
code_analysis_php80:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
actions:
|
||||
-
|
||||
name: 'PHPStan'
|
||||
run: vendor/bin/phpstan analyse --ansi --error-format symplify
|
||||
|
||||
-
|
||||
name: 'PHPStan for config'
|
||||
run: composer phpstan-config
|
||||
|
||||
name: ${{ matrix.actions.name }}
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
# see https://github.com/shivammathur/setup-php
|
||||
-
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: 8.0
|
||||
coverage: none
|
||||
|
||||
- uses: "ramsey/composer-install@v1"
|
||||
|
||||
- run: ${{ matrix.actions.run }}
|
58
.github/workflows/daily_pull_requests.yaml
vendored
58
.github/workflows/daily_pull_requests.yaml
vendored
@ -1,58 +0,0 @@
|
||||
name: Daily Pull Requests
|
||||
|
||||
on:
|
||||
schedule:
|
||||
# https://crontab.guru/once-a-day
|
||||
- cron: "0 0 * * *"
|
||||
|
||||
jobs:
|
||||
daily_pull_requests:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
actions:
|
||||
-
|
||||
name: "Re-Generate Doctrine Annotation Parser"
|
||||
run: "bin/rector sync-annotation-parser --dry-run --ansi"
|
||||
branch: 'automated-regenerate-doctrine-parser'
|
||||
|
||||
-
|
||||
name: "Re-Propagate Monorepo Dependencies"
|
||||
run: "composer propagate --ansi"
|
||||
branch: 'automated-propagate-monorepo-dependencies'
|
||||
|
||||
name: ${{ matrix.actions.name }}
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
-
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
token: ${{ secrets.ACCESS_TOKEN }}
|
||||
|
||||
# see https://github.com/shivammathur/setup-php
|
||||
-
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: 7.4
|
||||
coverage: none
|
||||
|
||||
|
||||
-
|
||||
run: composer install --no-progress --ansi
|
||||
|
||||
-
|
||||
run: ${{ matrix.actions.run }}
|
||||
|
||||
# see https://github.com/peter-evans/create-pull-request
|
||||
-
|
||||
name: Create pull-request
|
||||
uses: peter-evans/create-pull-request@v3
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
commit-message: "[automated] ${{ matrix.actions.name }}"
|
||||
base: 'main'
|
||||
branch: ${{ matrix.actions.branch }}
|
||||
title: '[automated] ${{ matrix.actions.name }}'
|
||||
delete-branch: true
|
19
.github/workflows/php_linter.yaml
vendored
19
.github/workflows/php_linter.yaml
vendored
@ -5,30 +5,17 @@ on:
|
||||
|
||||
jobs:
|
||||
php_linter:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
actions:
|
||||
-
|
||||
php_version: 7.3
|
||||
run: vendor/bin/parallel-lint src bin/rector config tests packages rules --colors --exclude packages/rector-generator/templates --exclude rules/psr4/tests/Rector/Namespace_/MultipleClassFileToPsr4ClassesRector/Source --exclude rules/autodiscovery/tests/Rector/FileNode/MoveInterfacesToContractNamespaceDirectoryRector/Expected --exclude packages/node-type-resolver/tests/PerNodeTypeResolver/PropertyFetchTypeResolver/Source/ClassWithNativeProps.php --exclude packages/node-type-resolver/tests/PerNodeTypeResolver/PropertyFetchTypeResolver/Source/ClassWithNativePropsPhp80.php --exclude packages/node-type-resolver/tests/PerNodeTypeResolver/PropertyFetchTypeResolver/Source/ClassWithTypedPropertyTypes.php --exclude rules/nette-kdyby/tests/Rector/MethodCall/ReplaceEventManagerWithEventSubscriberRector/Source/ExpectedSomeClassCopyEvent.php --exclude rules/nette-kdyby/tests/Rector/MethodCall/ReplaceMagicPropertyEventWithEventClassRector/Source/ExpectedFileManagerUploadEvent.php --exclude rules/nette-kdyby/tests/Rector/MethodCall/ReplaceMagicPropertyEventWithEventClassRector/Source/ExpectedDuplicatedEventParamsUploadEvent.php --exclude rules/type-declaration/tests/Rector/ClassMethod/ParamTypeFromStrictTypedPropertyRector/Source/OutOfControlExternalClass.php
|
||||
|
||||
-
|
||||
php_version: 8.0
|
||||
run: vendor/bin/parallel-lint src bin/rector config tests packages rules --colors --exclude packages/rector-generator/templates
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
# see https://github.com/shivammathur/setup-php
|
||||
-
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ matrix.actions.php_version }}
|
||||
php-version: 7.3
|
||||
coverage: none
|
||||
|
||||
- uses: "ramsey/composer-install@v1"
|
||||
- run: composer create-project php-parallel-lint/php-parallel-lint php-parallel-lint
|
||||
|
||||
- run: ${{ matrix.actions.run }}
|
||||
- run: php-parallel-lint/parallel-lint src bin/rector config tests packages rules --colors --exclude rules/psr4/tests/Rector/Namespace_/MultipleClassFileToPsr4ClassesRector/Source --exclude rules/autodiscovery/tests/Rector/FileNode/MoveInterfacesToContractNamespaceDirectoryRector/Expected --exclude packages/node-type-resolver/tests/PerNodeTypeResolver/PropertyFetchTypeResolver/Source --exclude rules/nette-kdyby/tests/Rector/MethodCall/ReplaceEventManagerWithEventSubscriberRector/Source/ExpectedSomeClassCopyEvent.php --exclude rules/nette-kdyby/tests/Rector/MethodCall/ReplaceMagicPropertyEventWithEventClassRector/Source --exclude rules/type-declaration/tests/Rector/ClassMethod/ParamTypeFromStrictTypedPropertyRector/Source
|
||||
|
@ -65,7 +65,6 @@
|
||||
"nette/application": "^3.0.7",
|
||||
"nette/di": "^3.0",
|
||||
"nette/forms": "^3.0",
|
||||
"php-parallel-lint/php-parallel-lint": "^1.2",
|
||||
"phpstan/phpstan-nette": "^0.12.16",
|
||||
"phpunit/phpunit": "^9.5",
|
||||
"rector/rector-generator": "^0.1.1",
|
||||
@ -96,8 +95,7 @@
|
||||
"Rector\\RuleDocGenerator\\": "utils/rule-doc-generator/src",
|
||||
"Rector\\PHPStanExtensions\\": "utils/phpstan-extensions/src",
|
||||
"Rector\\PHPStanExtensions\\Tests\\": "utils/phpstan-extensions/tests",
|
||||
"Rector\\Utils\\DoctrineAnnotationParserSyncer\\": "utils/doctrine-annotation-parser-syncer/src",
|
||||
"Rector\\Utils\\ProjectValidator\\": "utils/project-validator/src"
|
||||
"Rector\\Utils\\DoctrineAnnotationParserSyncer\\": "utils/doctrine-annotation-parser-syncer/src"
|
||||
},
|
||||
"classmap": [
|
||||
"rules-tests/Autodiscovery/Rector/FileNode/MoveInterfacesToContractNamespaceDirectoryRector/Expected",
|
||||
@ -139,7 +137,7 @@
|
||||
"phpstan-config": "vendor/bin/phpstan analyse config --ansi --error-format symplify",
|
||||
"docs": [
|
||||
"vendor/bin/rule-doc-generator generate packages rules --output-file docs/rector_rules_overview.md --ansi --categorize",
|
||||
"vendor/bin/ecs check-markdown docs/rector_rules_overview.md docs/nodes_overview.md --ansi --fix"
|
||||
"vendor/bin/ecs check-markdown docs/rector_rules_overview.md --ansi --fix"
|
||||
],
|
||||
"rector": "bin/rector process --ansi"
|
||||
},
|
||||
|
@ -1,13 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Rector\DeadCode\Rector\Class_\RemoveEmptyAbstractClassRector;
|
||||
use Rector\DeadCode\Rector\ClassMethod\RemoveUnusedPublicMethodRector;
|
||||
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
|
||||
|
||||
return static function (ContainerConfigurator $containerConfigurator): void {
|
||||
$services = $containerConfigurator->services();
|
||||
$services->set(RemoveUnusedPublicMethodRector::class);
|
||||
$services->set(RemoveEmptyAbstractClassRector::class);
|
||||
};
|
@ -10,7 +10,6 @@ use Rector\DeadCode\Rector\Assign\RemoveUnusedVariableAssignRector;
|
||||
use Rector\DeadCode\Rector\BinaryOp\RemoveDuplicatedInstanceOfRector;
|
||||
use Rector\DeadCode\Rector\BooleanAnd\RemoveAndTrueRector;
|
||||
use Rector\DeadCode\Rector\Cast\RecastingRemovalRector;
|
||||
use Rector\DeadCode\Rector\Class_\RemoveEmptyAbstractClassRector;
|
||||
use Rector\DeadCode\Rector\Class_\RemoveUnusedDoctrineEntityMethodAndPropertyRector;
|
||||
use Rector\DeadCode\Rector\ClassConst\RemoveUnusedClassConstantRector;
|
||||
use Rector\DeadCode\Rector\ClassConst\RemoveUnusedPrivateConstantRector;
|
||||
@ -101,7 +100,6 @@ return static function (ContainerConfigurator $containerConfigurator): void {
|
||||
$services->set(RemoveDeadConditionAboveReturnRector::class);
|
||||
$services->set(RemoveUnusedConstructorParamRector::class);
|
||||
$services->set(RemoveDeadInstanceOfRector::class);
|
||||
$services->set(RemoveEmptyAbstractClassRector::class);
|
||||
$services->set(RemoveDeadLoopRector::class);
|
||||
|
||||
// docblock
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
||||
# 661 Rules Overview
|
||||
# 659 Rules Overview
|
||||
|
||||
<br>
|
||||
|
||||
@ -20,7 +20,7 @@
|
||||
|
||||
- [Composer](#composer) (5)
|
||||
|
||||
- [DeadCode](#deadcode) (49)
|
||||
- [DeadCode](#deadcode) (48)
|
||||
|
||||
- [DeadDocBlock](#deaddocblock) (5)
|
||||
|
||||
@ -112,7 +112,7 @@
|
||||
|
||||
- [Restoration](#restoration) (8)
|
||||
|
||||
- [Symfony](#symfony) (14)
|
||||
- [Symfony](#symfony) (13)
|
||||
|
||||
- [Symfony2](#symfony2) (3)
|
||||
|
||||
@ -3509,35 +3509,6 @@ Remove duplicated instanceof in one call
|
||||
|
||||
<br>
|
||||
|
||||
### RemoveEmptyAbstractClassRector
|
||||
|
||||
Empty abstract class that does nothing
|
||||
|
||||
- class: [`Rector\DeadCode\Rector\Class_\RemoveEmptyAbstractClassRector`](../rules/DeadCode/Rector/Class_/RemoveEmptyAbstractClassRector.php)
|
||||
|
||||
```diff
|
||||
-class SomeClass extends SomeAbstractClass
|
||||
+class SomeClass extends AnotherAbstractClass
|
||||
{
|
||||
}
|
||||
|
||||
-abstract class SomeAbstractClass extends AnotherAbstractClass
|
||||
+abstracst clas AnotherAbstractClass
|
||||
{
|
||||
-}
|
||||
-
|
||||
-abstract class AnotherAbstractClass
|
||||
-{
|
||||
public function getName()
|
||||
{
|
||||
- return 'name';
|
||||
+ return 'cowo';
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### RemoveEmptyClassMethodRector
|
||||
|
||||
Remove empty method calls not required by parents
|
||||
@ -13651,25 +13622,6 @@ Make Symfony commands lazy
|
||||
|
||||
<br>
|
||||
|
||||
### NormalizeAutowireMethodNamingRector
|
||||
|
||||
Use autowire + class name suffix for method with `@required` annotation
|
||||
|
||||
- class: [`Rector\Symfony\Rector\ClassMethod\NormalizeAutowireMethodNamingRector`](../rules/Symfony/Rector/ClassMethod/NormalizeAutowireMethodNamingRector.php)
|
||||
|
||||
```diff
|
||||
class SomeClass
|
||||
{
|
||||
/** @required */
|
||||
- public function foo()
|
||||
+ public function autowireSomeClass()
|
||||
{
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### RemoveServiceFromSensioRouteRector
|
||||
|
||||
Remove service from Sensio `@Route`
|
||||
|
@ -3,7 +3,15 @@
|
||||
namespace Rector\DoctrineAnnotationGenerated;
|
||||
|
||||
use Doctrine\Common\Annotations\Annotation\IgnoreAnnotation;
|
||||
|
||||
use Doctrine\Common\Annotations\Annotation\Target;
|
||||
use ReflectionClass;
|
||||
use ReflectionFunction;
|
||||
use ReflectionMethod;
|
||||
use ReflectionProperty;
|
||||
use function array_merge;
|
||||
use function class_exists;
|
||||
use function extension_loaded;
|
||||
use function ini_get;
|
||||
/**
|
||||
* A reader for docblock annotations.
|
||||
*/
|
||||
@ -14,10 +22,7 @@ class ConstantPreservingAnnotationReader implements \Doctrine\Common\Annotations
|
||||
*
|
||||
* @var array<string, class-string>
|
||||
*/
|
||||
private static $globalImports = [
|
||||
'ignoreannotation' => \Doctrine\Common\Annotations\Annotation\IgnoreAnnotation::class,
|
||||
];
|
||||
|
||||
private static $globalImports = ['ignoreannotation' => \Doctrine\Common\Annotations\Annotation\IgnoreAnnotation::class];
|
||||
/**
|
||||
* A list with annotations that are not causing exceptions when not resolved to an annotation class.
|
||||
*
|
||||
@ -26,7 +31,6 @@ class ConstantPreservingAnnotationReader implements \Doctrine\Common\Annotations
|
||||
* @var array<string, true>
|
||||
*/
|
||||
private static $globalIgnoredNames = \Doctrine\Common\Annotations\ImplicitlyIgnoredAnnotationNames::LIST;
|
||||
|
||||
/**
|
||||
* A list with annotations that are not causing exceptions when not resolved to an annotation class.
|
||||
*
|
||||
@ -35,50 +39,62 @@ class ConstantPreservingAnnotationReader implements \Doctrine\Common\Annotations
|
||||
* @var array<string, true>
|
||||
*/
|
||||
private static $globalIgnoredNamespaces = [];
|
||||
|
||||
/**
|
||||
* Add a new annotation to the globally ignored annotation names with regard to exception handling.
|
||||
*
|
||||
* @param string $name
|
||||
*/
|
||||
public static function addGlobalIgnoredName($name)
|
||||
{
|
||||
self::$globalIgnoredNames[$name] = true;
|
||||
}
|
||||
/**
|
||||
* Add a new annotation to the globally ignored annotation namespaces with regard to exception handling.
|
||||
*
|
||||
* @param string $namespace
|
||||
*/
|
||||
public static function addGlobalIgnoredNamespace($namespace)
|
||||
{
|
||||
self::$globalIgnoredNamespaces[$namespace] = true;
|
||||
}
|
||||
/**
|
||||
* Annotations parser.
|
||||
*
|
||||
* @var DocParser
|
||||
*/
|
||||
private $parser;
|
||||
|
||||
/**
|
||||
* Annotations parser used to collect parsing metadata.
|
||||
*
|
||||
* @var DocParser
|
||||
*/
|
||||
private $preParser;
|
||||
|
||||
/**
|
||||
* PHP parser used to collect imports.
|
||||
*
|
||||
* @var PhpParser
|
||||
*/
|
||||
private $phpParser;
|
||||
|
||||
/**
|
||||
* In-memory cache mechanism to store imported annotations per class.
|
||||
*
|
||||
* @var array<string, array<string, class-string>>
|
||||
* @psalm-var array<'class'|'function', array<string, array<string, class-string>>>
|
||||
*/
|
||||
private $imports = [];
|
||||
|
||||
/**
|
||||
* In-memory cache mechanism to store ignored annotations per class.
|
||||
*
|
||||
* @var array<string, array<string, true>>
|
||||
* @psalm-var array<'class'|'function', array<string, array<string, true>>>
|
||||
*/
|
||||
private $ignoredAnnotationNames = [];
|
||||
|
||||
/**
|
||||
* Initializes a new AnnotationReader.
|
||||
*
|
||||
* @throws AnnotationException
|
||||
*/
|
||||
public function __construct(\Rector\DoctrineAnnotationGenerated\ConstantPreservingDocParser $parser = null)
|
||||
{
|
||||
if (\extension_loaded('Zend Optimizer+') && (\ini_get('zend_optimizerplus.save_comments') === '0' || \ini_get(
|
||||
'opcache.save_comments'
|
||||
) === '0')) {
|
||||
if (\extension_loaded('Zend Optimizer+') && (\ini_get('zend_optimizerplus.save_comments') === '0' || \ini_get('opcache.save_comments') === '0')) {
|
||||
throw \Doctrine\Common\Annotations\AnnotationException::optimizerPlusSaveComments();
|
||||
}
|
||||
if (\extension_loaded('Zend OPcache') && \ini_get('opcache.save_comments') === 0) {
|
||||
@ -93,39 +109,17 @@ class ConstantPreservingAnnotationReader implements \Doctrine\Common\Annotations
|
||||
$this->preParser->setIgnoredAnnotationNames(self::$globalIgnoredNames);
|
||||
$this->phpParser = new \Doctrine\Common\Annotations\PhpParser();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new annotation to the globally ignored annotation names with regard to exception handling.
|
||||
*
|
||||
* @param string $name
|
||||
*/
|
||||
public static function addGlobalIgnoredName($name)
|
||||
{
|
||||
self::$globalIgnoredNames[$name] = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new annotation to the globally ignored annotation namespaces with regard to exception handling.
|
||||
*
|
||||
* @param string $namespace
|
||||
*/
|
||||
public static function addGlobalIgnoredNamespace($namespace)
|
||||
{
|
||||
self::$globalIgnoredNamespaces[$namespace] = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getClassAnnotations(\ReflectionClass $class)
|
||||
{
|
||||
$this->parser->setTarget(\Doctrine\Common\Annotations\Annotation\Target::TARGET_CLASS);
|
||||
$this->parser->setImports($this->getClassImports($class));
|
||||
$this->parser->setImports($this->getImports($class));
|
||||
$this->parser->setIgnoredAnnotationNames($this->getIgnoredAnnotationNames($class));
|
||||
$this->parser->setIgnoredAnnotationNamespaces(self::$globalIgnoredNamespaces);
|
||||
return $this->parser->parse($class->getDocComment(), 'class ' . $class->getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@ -139,7 +133,6 @@ class ConstantPreservingAnnotationReader implements \Doctrine\Common\Annotations
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@ -153,7 +146,6 @@ class ConstantPreservingAnnotationReader implements \Doctrine\Common\Annotations
|
||||
$this->parser->setIgnoredAnnotationNamespaces(self::$globalIgnoredNamespaces);
|
||||
return $this->parser->parse($property->getDocComment(), $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@ -167,7 +159,6 @@ class ConstantPreservingAnnotationReader implements \Doctrine\Common\Annotations
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@ -181,7 +172,6 @@ class ConstantPreservingAnnotationReader implements \Doctrine\Common\Annotations
|
||||
$this->parser->setIgnoredAnnotationNamespaces(self::$globalIgnoredNamespaces);
|
||||
return $this->parser->parse($method->getDocComment(), $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@ -195,37 +185,69 @@ class ConstantPreservingAnnotationReader implements \Doctrine\Common\Annotations
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ignored annotations for the given class.
|
||||
* Gets the annotations applied to a function.
|
||||
*
|
||||
* @phpstan-return list<object> An array of Annotations.
|
||||
*/
|
||||
public function getFunctionAnnotations(\ReflectionFunction $function): array
|
||||
{
|
||||
$context = 'function ' . $function->getName();
|
||||
$this->parser->setTarget(\Doctrine\Common\Annotations\Annotation\Target::TARGET_FUNCTION);
|
||||
$this->parser->setImports($this->getImports($function));
|
||||
$this->parser->setIgnoredAnnotationNames($this->getIgnoredAnnotationNames($function));
|
||||
$this->parser->setIgnoredAnnotationNamespaces(self::$globalIgnoredNamespaces);
|
||||
return $this->parser->parse($function->getDocComment(), $context);
|
||||
}
|
||||
/**
|
||||
* Gets a function annotation.
|
||||
*
|
||||
* @return object|null The Annotation or NULL, if the requested annotation does not exist.
|
||||
*/
|
||||
public function getFunctionAnnotation(\ReflectionFunction $function, string $annotationName)
|
||||
{
|
||||
$annotations = $this->getFunctionAnnotations($function);
|
||||
foreach ($annotations as $annotation) {
|
||||
if ($annotation instanceof $annotationName) {
|
||||
return $annotation;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* Returns the ignored annotations for the given class or function.
|
||||
*
|
||||
* @param ReflectionClass|ReflectionFunction $reflection
|
||||
*
|
||||
* @return array<string, true>
|
||||
*/
|
||||
private function getIgnoredAnnotationNames(\ReflectionClass $class)
|
||||
private function getIgnoredAnnotationNames($reflection): array
|
||||
{
|
||||
$name = $class->getName();
|
||||
if (isset($this->ignoredAnnotationNames[$name])) {
|
||||
return $this->ignoredAnnotationNames[$name];
|
||||
$type = $reflection instanceof \ReflectionClass ? 'class' : 'function';
|
||||
$name = $reflection->getName();
|
||||
if (isset($this->ignoredAnnotationNames[$type][$name])) {
|
||||
return $this->ignoredAnnotationNames[$type][$name];
|
||||
}
|
||||
$this->collectParsingMetadata($class);
|
||||
return $this->ignoredAnnotationNames[$name];
|
||||
$this->collectParsingMetadata($reflection);
|
||||
return $this->ignoredAnnotationNames[$type][$name];
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves imports.
|
||||
* Retrieves imports for a class or a function.
|
||||
*
|
||||
* @param ReflectionClass|ReflectionFunction $reflection
|
||||
*
|
||||
* @return array<string, class-string>
|
||||
*/
|
||||
private function getClassImports(\ReflectionClass $class)
|
||||
private function getImports($reflection): array
|
||||
{
|
||||
$name = $class->getName();
|
||||
if (isset($this->imports[$name])) {
|
||||
return $this->imports[$name];
|
||||
$type = $reflection instanceof \ReflectionClass ? 'class' : 'function';
|
||||
$name = $reflection->getName();
|
||||
if (isset($this->imports[$type][$name])) {
|
||||
return $this->imports[$type][$name];
|
||||
}
|
||||
$this->collectParsingMetadata($class);
|
||||
return $this->imports[$name];
|
||||
$this->collectParsingMetadata($reflection);
|
||||
return $this->imports[$type][$name];
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves imports for methods.
|
||||
*
|
||||
@ -234,17 +256,16 @@ class ConstantPreservingAnnotationReader implements \Doctrine\Common\Annotations
|
||||
private function getMethodImports(\ReflectionMethod $method)
|
||||
{
|
||||
$class = $method->getDeclaringClass();
|
||||
$classImports = $this->getClassImports($class);
|
||||
$classImports = $this->getImports($class);
|
||||
$traitImports = [];
|
||||
foreach ($class->getTraits() as $trait) {
|
||||
if (! $trait->hasMethod($method->getName()) || $trait->getFileName() !== $method->getFileName()) {
|
||||
if (!$trait->hasMethod($method->getName()) || $trait->getFileName() !== $method->getFileName()) {
|
||||
continue;
|
||||
}
|
||||
$traitImports = \array_merge($traitImports, $this->phpParser->parseClass($trait));
|
||||
$traitImports = \array_merge($traitImports, $this->phpParser->parseUseStatements($trait));
|
||||
}
|
||||
return \array_merge($classImports, $traitImports);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves imports for properties.
|
||||
*
|
||||
@ -253,36 +274,36 @@ class ConstantPreservingAnnotationReader implements \Doctrine\Common\Annotations
|
||||
private function getPropertyImports(\ReflectionProperty $property)
|
||||
{
|
||||
$class = $property->getDeclaringClass();
|
||||
$classImports = $this->getClassImports($class);
|
||||
$classImports = $this->getImports($class);
|
||||
$traitImports = [];
|
||||
foreach ($class->getTraits() as $trait) {
|
||||
if (! $trait->hasProperty($property->getName())) {
|
||||
if (!$trait->hasProperty($property->getName())) {
|
||||
continue;
|
||||
}
|
||||
$traitImports = \array_merge($traitImports, $this->phpParser->parseClass($trait));
|
||||
$traitImports = \array_merge($traitImports, $this->phpParser->parseUseStatements($trait));
|
||||
}
|
||||
return \array_merge($classImports, $traitImports);
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects parsing metadata for a given class.
|
||||
* Collects parsing metadata for a given class or function.
|
||||
*
|
||||
* @param ReflectionClass|ReflectionFunction $reflection
|
||||
*/
|
||||
private function collectParsingMetadata(\ReflectionClass $class)
|
||||
private function collectParsingMetadata($reflection): void
|
||||
{
|
||||
$type = $reflection instanceof \ReflectionClass ? 'class' : 'function';
|
||||
$name = $reflection->getName();
|
||||
$ignoredAnnotationNames = self::$globalIgnoredNames;
|
||||
$annotations = $this->preParser->parse($class->getDocComment(), 'class ' . $class->name);
|
||||
$annotations = $this->preParser->parse($reflection->getDocComment(), $type . ' ' . $name);
|
||||
foreach ($annotations as $annotation) {
|
||||
if (! $annotation instanceof \Doctrine\Common\Annotations\Annotation\IgnoreAnnotation) {
|
||||
if (!$annotation instanceof \Doctrine\Common\Annotations\Annotation\IgnoreAnnotation) {
|
||||
continue;
|
||||
}
|
||||
foreach ($annotation->names as $annot) {
|
||||
$ignoredAnnotationNames[$annot] = true;
|
||||
}
|
||||
}
|
||||
$name = $class->getName();
|
||||
$this->imports[$name] = \array_merge(self::$globalImports, $this->phpParser->parseClass($class), [
|
||||
'__NAMESPACE__' => $class->getNamespaceName(), 'self' => $name,
|
||||
]);
|
||||
$this->ignoredAnnotationNames[$name] = $ignoredAnnotationNames;
|
||||
$this->imports[$type][$name] = \array_merge(self::$globalImports, $this->phpParser->parseUseStatements($reflection), ['__NAMESPACE__' => $reflection->getNamespaceName(), 'self' => $name]);
|
||||
$this->ignoredAnnotationNames[$type][$name] = $ignoredAnnotationNames;
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -98,11 +98,6 @@ final class SetList implements SetListInterface
|
||||
*/
|
||||
public const DEAD_CODE = __DIR__ . '/../../../config/set/dead-code.php';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public const DEAD_CODE_STRICT = __DIR__ . '/../../../config/set/dead-code-strict.php';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
|
@ -1,42 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Tests\DeadCode\Rector\Class_\RemoveEmptyAbstractClassRector;
|
||||
|
||||
use Iterator;
|
||||
use Rector\DeadCode\Rector\Class_\RemoveEmptyAbstractClassRector;
|
||||
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
|
||||
use Symplify\SmartFileSystem\SmartFileInfo;
|
||||
|
||||
final class ExtraFilesTest extends AbstractRectorTestCase
|
||||
{
|
||||
/**
|
||||
* @dataProvider provideData()
|
||||
* @param SmartFileInfo[] $extraFileInfos
|
||||
*/
|
||||
public function test(SmartFileInfo $originalFileInfo, array $extraFileInfos = []): void
|
||||
{
|
||||
$this->doTestFileInfo($originalFileInfo, $extraFileInfos);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Iterator<array<int, SmartFileInfo[]>|SmartFileInfo[]>
|
||||
*/
|
||||
public function provideData(): Iterator
|
||||
{
|
||||
$extraFileInfos = [new SmartFileInfo(__DIR__ . '/Source/UseAbstract.php')];
|
||||
yield [new SmartFileInfo(__DIR__ . '/FixtureExtraFiles/SkipUsedAbstractClass.php.inc'), $extraFileInfos];
|
||||
|
||||
$extraFileInfos = [
|
||||
new SmartFileInfo(__DIR__ . '/Source/AbstractMain.php'),
|
||||
new SmartFileInfo(__DIR__ . '/Source/AbstractChild.php'),
|
||||
];
|
||||
yield [new SmartFileInfo(__DIR__ . '/FixtureExtraFiles/ExtendsAbstractChild.php.inc'), $extraFileInfos];
|
||||
}
|
||||
|
||||
protected function getRectorClass(): string
|
||||
{
|
||||
return RemoveEmptyAbstractClassRector::class;
|
||||
}
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\DeadCode\Rector\Class_\RemoveEmptyAbstractClassRector\Fixture;
|
||||
|
||||
abstract class AbstractClassMulti
|
||||
{
|
||||
}
|
||||
|
||||
abstract class AbstractClassUsedMulti extends AbstractClassMulti
|
||||
{
|
||||
}
|
||||
|
||||
final class AnyClass2
|
||||
{
|
||||
public function process($some)
|
||||
{
|
||||
if ($some instanceof AbstractClassUsedMulti) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\DeadCode\Rector\Class_\RemoveEmptyAbstractClassRector\Fixture;
|
||||
|
||||
abstract class AbstractClassUsedMulti
|
||||
{
|
||||
}
|
||||
|
||||
final class AnyClass2
|
||||
{
|
||||
public function process($some)
|
||||
{
|
||||
if ($some instanceof AbstractClassUsedMulti) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
@ -1,43 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\DeadCode\Rector\Class_\RemoveEmptyAbstractClassRector\Fixture;
|
||||
|
||||
abstract class AbstractClassMultiUpper
|
||||
{
|
||||
}
|
||||
|
||||
abstract class AbstractClassUsedMultiUpper extends AbstractClassMultiUpper
|
||||
{
|
||||
}
|
||||
|
||||
final class AnyClass3
|
||||
{
|
||||
public function process($some)
|
||||
{
|
||||
if ($some instanceof AbstractClassMultiUpper) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\DeadCode\Rector\Class_\RemoveEmptyAbstractClassRector\Fixture;
|
||||
|
||||
abstract class AbstractClassMultiUpper
|
||||
{
|
||||
}
|
||||
|
||||
final class AnyClass3
|
||||
{
|
||||
public function process($some)
|
||||
{
|
||||
if ($some instanceof AbstractClassMultiUpper) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
@ -1,39 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\DeadCode\Rector\Class_\RemoveEmptyAbstractClassRector\Fixture;
|
||||
|
||||
abstract class AnotherAbstractClass
|
||||
{
|
||||
public function getName()
|
||||
{
|
||||
return 'name';
|
||||
}
|
||||
}
|
||||
|
||||
abstract class SomeAbstractClass extends AnotherAbstractClass
|
||||
{
|
||||
}
|
||||
|
||||
class SomeClass extends SomeAbstractClass
|
||||
{
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\DeadCode\Rector\Class_\RemoveEmptyAbstractClassRector\Fixture;
|
||||
|
||||
abstract class AnotherAbstractClass
|
||||
{
|
||||
public function getName()
|
||||
{
|
||||
return 'name';
|
||||
}
|
||||
}
|
||||
|
||||
class SomeClass extends \Rector\Tests\DeadCode\Rector\Class_\RemoveEmptyAbstractClassRector\Fixture\AnotherAbstractClass
|
||||
{
|
||||
}
|
||||
|
||||
?>
|
@ -1,43 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\DeadCode\Rector\Class_\RemoveEmptyAbstractClassRector\Fixture;
|
||||
|
||||
abstract class AnotherAbstractClassMulti
|
||||
{
|
||||
public function getName()
|
||||
{
|
||||
return 'name';
|
||||
}
|
||||
}
|
||||
|
||||
abstract class SomeAbstractClassMulti1 extends AnotherAbstractClassMulti
|
||||
{
|
||||
}
|
||||
|
||||
abstract class SomeAbstractClassMulti2 extends SomeAbstractClassMulti1
|
||||
{
|
||||
}
|
||||
|
||||
class MultiExtends extends SomeAbstractClassMulti2
|
||||
{
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\DeadCode\Rector\Class_\RemoveEmptyAbstractClassRector\Fixture;
|
||||
|
||||
abstract class AnotherAbstractClassMulti
|
||||
{
|
||||
public function getName()
|
||||
{
|
||||
return 'name';
|
||||
}
|
||||
}
|
||||
|
||||
class MultiExtends extends \Rector\Tests\DeadCode\Rector\Class_\RemoveEmptyAbstractClassRector\Fixture\AnotherAbstractClassMulti
|
||||
{
|
||||
}
|
||||
|
||||
?>
|
@ -1,23 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\DeadCode\Rector\Class_\RemoveEmptyAbstractClassRector\Fixture;
|
||||
|
||||
abstract class SingleEmptyAbstract
|
||||
{
|
||||
}
|
||||
|
||||
class Single extends SingleEmptyAbstract
|
||||
{
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\DeadCode\Rector\Class_\RemoveEmptyAbstractClassRector\Fixture;
|
||||
|
||||
class Single
|
||||
{
|
||||
}
|
||||
|
||||
?>
|
@ -1,21 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\DeadCode\Rector\Class_\RemoveEmptyAbstractClassRector\Fixture;
|
||||
|
||||
abstract class AbstractClassUsed
|
||||
{
|
||||
}
|
||||
|
||||
class skipAbstractClassUsed extends AbstractClassUsed
|
||||
{
|
||||
}
|
||||
|
||||
final class AnyClass
|
||||
{
|
||||
public function process($some)
|
||||
{
|
||||
if ($some instanceof AbstractClassUsed) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\DeadCode\Rector\Class_\RemoveEmptyAbstractClassRector\Fixture;
|
||||
|
||||
abstract class SkipHasConstant
|
||||
{
|
||||
protected const A_CONSTANT = 'foo';
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\DeadCode\Rector\Class_\RemoveEmptyAbstractClassRector\Fixture;
|
||||
|
||||
abstract class SkipHasMethod
|
||||
{
|
||||
public abstract function run();
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\DeadCode\Rector\Class_\RemoveEmptyAbstractClassRector\Fixture;
|
||||
|
||||
abstract class SkipHasProperty
|
||||
{
|
||||
protected $foo;
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\DeadCode\Rector\Class_\RemoveEmptyAbstractClassRector\Fixture;
|
||||
|
||||
use Rector\Tests\DeadCode\Rector\Class_\RemoveEmptyAbstractClassRector\Source\ATrait;
|
||||
|
||||
abstract class SkipHasTrait
|
||||
{
|
||||
use ATrait;
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\DeadCode\Rector\Class_\RemoveEmptyAbstractClassRector\Fixture;
|
||||
|
||||
use Rector\Tests\DeadCode\Rector\Class_\RemoveEmptyAbstractClassRector\Source\AnInterface;
|
||||
|
||||
abstract class SkipImplementsInterface implements AnInterface
|
||||
{
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\DeadCode\Rector\Class_\RemoveEmptyAbstractClassRector\Fixture;
|
||||
|
||||
final class SkipNotAbstract
|
||||
{
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\DeadCode\Rector\Class_\RemoveEmptyAbstractClassRector\Fixture;
|
||||
|
||||
abstract class SkipSingleEmptyAbstractUsed
|
||||
{
|
||||
}
|
||||
|
||||
class Single2
|
||||
{
|
||||
function run($some)
|
||||
{
|
||||
if ($some instanceof SkipSingleEmptyAbstractUsed) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
@ -1,23 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\DeadCode\Rector\Class_\RemoveEmptyAbstractClassRector\FixtureExtraFiles;
|
||||
|
||||
use Rector\Tests\DeadCode\Rector\Class_\RemoveEmptyAbstractClassRector\Source\AbstractChild;
|
||||
|
||||
final class ExtendsAbstractChild extends AbstractChild
|
||||
{
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\DeadCode\Rector\Class_\RemoveEmptyAbstractClassRector\FixtureExtraFiles;
|
||||
|
||||
use Rector\Tests\DeadCode\Rector\Class_\RemoveEmptyAbstractClassRector\Source\AbstractChild;
|
||||
|
||||
final class ExtendsAbstractChild extends \Rector\Tests\DeadCode\Rector\Class_\RemoveEmptyAbstractClassRector\Source\AbstractMain
|
||||
{
|
||||
}
|
||||
|
||||
?>
|
@ -1,7 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\DeadCode\Rector\Class_\RemoveEmptyAbstractClassRector\FixtureExtraFiles;
|
||||
|
||||
abstract class SkipUsedAbstractClass
|
||||
{
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Tests\DeadCode\Rector\Class_\RemoveEmptyAbstractClassRector;
|
||||
|
||||
use Iterator;
|
||||
use Rector\DeadCode\Rector\Class_\RemoveEmptyAbstractClassRector;
|
||||
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
|
||||
use Symplify\SmartFileSystem\SmartFileInfo;
|
||||
|
||||
final class RemoveEmptyAbstractClassRectorTest 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');
|
||||
}
|
||||
|
||||
protected function getRectorClass(): string
|
||||
{
|
||||
return RemoveEmptyAbstractClassRector::class;
|
||||
}
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\DeadCode\Rector\Class_\RemoveEmptyAbstractClassRector\Source;
|
||||
|
||||
trait ATrait
|
||||
{}
|
@ -1,7 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\DeadCode\Rector\Class_\RemoveEmptyAbstractClassRector\Source;
|
||||
|
||||
abstract class AbstractChild extends AbstractMain
|
||||
{
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\DeadCode\Rector\Class_\RemoveEmptyAbstractClassRector\Source;
|
||||
|
||||
abstract class AbstractMain
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
}
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\DeadCode\Rector\Class_\RemoveEmptyAbstractClassRector\Source;
|
||||
|
||||
interface AnInterface
|
||||
{
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\DeadCode\Rector\Class_\RemoveEmptyAbstractClassRector\Source;
|
||||
|
||||
use Rector\Tests\DeadCode\Rector\Class_\RemoveEmptyAbstractClassRector\FixtureExtraFiles\SkipUsedAbstractClass;
|
||||
|
||||
final class UseAbstract
|
||||
{
|
||||
public function __construct(?SkipUsedAbstractClass $class = null)
|
||||
{
|
||||
}
|
||||
}
|
@ -1,126 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\DeadCode\Rector\Class_;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Name\FullyQualified;
|
||||
use PhpParser\Node\Stmt\Class_;
|
||||
use PhpParser\Node\Stmt\UseUse;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
|
||||
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
|
||||
|
||||
/**
|
||||
* @see \Rector\Tests\DeadCode\Rector\Class_\RemoveEmptyAbstractClassRector\RemoveEmptyAbstractClassRectorTest
|
||||
*/
|
||||
final class RemoveEmptyAbstractClassRector extends AbstractRector
|
||||
{
|
||||
/**
|
||||
* @return array<class-string<Node>>
|
||||
*/
|
||||
public function getNodeTypes(): array
|
||||
{
|
||||
return [Class_::class];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Class_ $node
|
||||
*/
|
||||
public function refactor(Node $node): ?Node
|
||||
{
|
||||
if ($this->shouldSkip($node)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->processRemove($node);
|
||||
}
|
||||
|
||||
public function getRuleDefinition(): RuleDefinition
|
||||
{
|
||||
return new RuleDefinition(
|
||||
'Empty abstract class that does nothing',
|
||||
[
|
||||
new CodeSample(
|
||||
<<<'CODE_SAMPLE'
|
||||
class SomeClass extends SomeAbstractClass
|
||||
{
|
||||
}
|
||||
|
||||
abstract class SomeAbstractClass extends AnotherAbstractClass
|
||||
{
|
||||
}
|
||||
|
||||
abstract class AnotherAbstractClass
|
||||
{
|
||||
public function getName()
|
||||
{
|
||||
return 'name';
|
||||
}
|
||||
}
|
||||
CODE_SAMPLE
|
||||
,
|
||||
<<<'CODE_SAMPLE'
|
||||
class SomeClass extends AnotherAbstractClass
|
||||
{
|
||||
}
|
||||
|
||||
abstracst clas AnotherAbstractClass
|
||||
{
|
||||
public function getName()
|
||||
{
|
||||
return 'cowo';
|
||||
}
|
||||
}
|
||||
CODE_SAMPLE
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
private function shouldSkip(Class_ $class): bool
|
||||
{
|
||||
if (! $class->isAbstract()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($class->implements !== []) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return $class->stmts !== [];
|
||||
}
|
||||
|
||||
private function processRemove(Class_ $class): ?Class_
|
||||
{
|
||||
$className = $this->getName($class->namespacedName);
|
||||
$names = $this->nodeRepository->findNames($className);
|
||||
|
||||
foreach ($names as $name) {
|
||||
$parent = $name->getAttribute(AttributeKey::PARENT_NODE);
|
||||
if ($parent instanceof Class_) {
|
||||
continue;
|
||||
}
|
||||
if ($parent instanceof UseUse) {
|
||||
continue;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
$children = $this->nodeRepository->findChildrenOfClass($className);
|
||||
|
||||
foreach ($children as $child) {
|
||||
if ($class->extends !== null) {
|
||||
$parentClass = $this->getName($class->extends);
|
||||
$child->extends = new FullyQualified($parentClass);
|
||||
} else {
|
||||
$child->extends = null;
|
||||
}
|
||||
}
|
||||
|
||||
$this->removeNode($class);
|
||||
|
||||
return $class;
|
||||
}
|
||||
}
|
@ -131,7 +131,7 @@ CODE_SAMPLE
|
||||
$arguments = [$identifierVariable, $resolvedVariable];
|
||||
$staticCall = $this->nodeFactory->createStaticCall(
|
||||
ResolvedConstantStaticCollector::class,
|
||||
'collects',
|
||||
'collect',
|
||||
$arguments
|
||||
);
|
||||
|
||||
|
@ -1,17 +0,0 @@
|
||||
<?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()
|
||||
->autoconfigure();
|
||||
|
||||
$services->load('Rector\Utils\ProjectValidator\\', __DIR__ . '/../src')
|
||||
->exclude([__DIR__ . '/../src/HttpKernel', __DIR__ . '/../src/ValueObject']);
|
||||
};
|
@ -1,114 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Utils\ProjectValidator\Command;
|
||||
|
||||
use Rector\Core\Application\ActiveRectorsProvider;
|
||||
use Rector\Core\HttpKernel\RectorKernel;
|
||||
use Rector\Set\RectorSetProvider;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
use Symfony\Component\HttpKernel\KernelInterface;
|
||||
use Symplify\PackageBuilder\Console\ShellCode;
|
||||
use Symplify\SetConfigResolver\ValueObject\Set;
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* We'll only check one file for now.
|
||||
* This makes sure that all sets are "runnable" but keeps the runtime at a managable level
|
||||
*/
|
||||
final class ValidateSetsCommand extends Command
|
||||
{
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
private const EXCLUDED_SETS = [
|
||||
// required Kernel class to be set in parameters
|
||||
'symfony-code-quality',
|
||||
];
|
||||
|
||||
/**
|
||||
* @var RectorSetProvider
|
||||
*/
|
||||
private $rectorSetProvider;
|
||||
|
||||
/**
|
||||
* @var SymfonyStyle
|
||||
*/
|
||||
private $symfonyStyle;
|
||||
|
||||
public function __construct(RectorSetProvider $rectorSetProvider, SymfonyStyle $symfonyStyle)
|
||||
{
|
||||
$this->rectorSetProvider = $rectorSetProvider;
|
||||
$this->symfonyStyle = $symfonyStyle;
|
||||
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
protected function configure(): void
|
||||
{
|
||||
$this->setDescription('[CI] Validate each sets has correct configuration by loading the configs');
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
$hasErrors = false;
|
||||
|
||||
$message = sprintf('Testing %d sets', count($this->rectorSetProvider->provide()));
|
||||
$this->symfonyStyle->title($message);
|
||||
|
||||
foreach ($this->rectorSetProvider->provide() as $set) {
|
||||
if (in_array($set->getName(), self::EXCLUDED_SETS, true)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$setFileInfo = $set->getSetFileInfo();
|
||||
|
||||
try {
|
||||
$rectorKernel = $this->bootRectorKernelWithSet($set);
|
||||
} catch (Throwable $throwable) {
|
||||
$message = sprintf(
|
||||
'Failed to load "%s" set from "%s" path',
|
||||
$set->getName(),
|
||||
$setFileInfo->getRelativeFilePathFromCwd()
|
||||
);
|
||||
$this->symfonyStyle->error($message);
|
||||
$this->symfonyStyle->writeln($throwable->getMessage());
|
||||
|
||||
$hasErrors = true;
|
||||
sleep(3);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$container = $rectorKernel->getContainer();
|
||||
$activeRectorsProvider = $container->get(ActiveRectorsProvider::class);
|
||||
|
||||
$activeRectors = $activeRectorsProvider->provide();
|
||||
|
||||
$setFileInfo = $set->getSetFileInfo();
|
||||
$message = sprintf(
|
||||
'Set "%s" loaded correctly from "%s" path with %d rules',
|
||||
$set->getName(),
|
||||
$setFileInfo->getRelativeFilePathFromCwd(),
|
||||
count($activeRectors)
|
||||
);
|
||||
|
||||
$this->symfonyStyle->success($message);
|
||||
}
|
||||
|
||||
return $hasErrors ? ShellCode::ERROR : ShellCode::SUCCESS;
|
||||
}
|
||||
|
||||
private function bootRectorKernelWithSet(Set $set): KernelInterface
|
||||
{
|
||||
$rectorKernel = new RectorKernel('prod' . sha1($set->getName()), true);
|
||||
$rectorKernel->setConfigs([$set->getSetPathname()]);
|
||||
$rectorKernel->boot();
|
||||
|
||||
return $rectorKernel;
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user