diff --git a/.github/workflows/code_analysis.yaml b/.github/workflows/code_analysis.yaml index 195a1a60f42..3600e580d46 100644 --- a/.github/workflows/code_analysis.yaml +++ b/.github/workflows/code_analysis.yaml @@ -53,7 +53,7 @@ jobs: - name: 'Active Classes' run: | - vendor/bin/class-leak check bin config src rules utils --skip-suffix "Rector" --skip-type="Rector\\Utils\\Compiler\\Unprefixer" --skip-type="Rector\\NodeCollector\\BinaryOpConditionsCollector" --skip-type="Rector\\Set\\Contract\\SetListInterface" --skip-type="Rector\\DependencyInjection\\PHPStan\\RichParserFactory" --skip-type="Rector\\Utils\\PHPStan\\Tests\\Rule\\SingleServiceRegistrationRule\\Source\\DuplicateRegistrationFactory" --skip-type="Rector\\Utils\\PHPStan\\Tests\\Rule\\SingleServiceRegistrationRule\\Source\\SingleRegistrationFactory" --skip-type="Rector\\ChangesReporting\\Contract\\Output\\OutputFormatterInterface" --skip-type="Rector\\NodeTypeResolver\\Contract\\NodeTypeResolverInterface" --skip-type="Rector\\CodingStyle\\Contract\\ClassNameImport\\ClassNameImportSkipVoterInterface" --skip-type="Rector\\Php80\\Contract\\ConverterAttributeDecoratorInterface" --skip-type="Rector\\NodeNameResolver\\Contract\\NodeNameResolverInterface" --skip-type="Rector\\StaticTypeMapper\\Contract\\PhpDocParser\\PhpDocTypeMapperInterface" + vendor/bin/class-leak check bin config src rules utils --skip-suffix "Rector" --skip-type="Rector\\Utils\\Compiler\\Unprefixer" --skip-type="Rector\\NodeCollector\\BinaryOpConditionsCollector" --skip-type="Rector\\Set\\Contract\\SetListInterface" --skip-type="Rector\\DependencyInjection\\PHPStan\\RichParserFactory" --skip-type="Rector\\Utils\\PHPStan\\Tests\\Rule\\SingleServiceRegistrationRule\\Source\\DuplicateRegistrationFactory" --skip-type="Rector\\Utils\\PHPStan\\Tests\\Rule\\SingleServiceRegistrationRule\\Source\\SingleRegistrationFactory" --skip-type="Rector\\ChangesReporting\\Contract\\Output\\OutputFormatterInterface" --skip-type="Rector\\NodeTypeResolver\\Contract\\NodeTypeResolverInterface" --skip-type="Rector\\CodingStyle\\Contract\\ClassNameImport\\ClassNameImportSkipVoterInterface" --skip-type="Rector\\Php80\\Contract\\ConverterAttributeDecoratorInterface" --skip-type="Rector\\NodeNameResolver\\Contract\\NodeNameResolverInterface" --skip-type="Rector\\StaticTypeMapper\\Contract\\PhpDocParser\\PhpDocTypeMapperInterface" --skip-type="Rector\\PhpAttribute\\Contract\\AnnotationToAttributeMapperInterface" - name: 'Compatible PHPStan versions' diff --git a/src/DependencyInjection/LazyContainerFactory.php b/src/DependencyInjection/LazyContainerFactory.php index 3ca32b36378..949354dd878 100644 --- a/src/DependencyInjection/LazyContainerFactory.php +++ b/src/DependencyInjection/LazyContainerFactory.php @@ -54,13 +54,8 @@ use Rector\PhpAttribute\AnnotationToAttributeMapper; use Rector\PhpAttribute\AnnotationToAttributeMapper\ArrayAnnotationToAttributeMapper; use Rector\PhpAttribute\AnnotationToAttributeMapper\ArrayItemNodeAnnotationToAttributeMapper; -use Rector\PhpAttribute\AnnotationToAttributeMapper\ClassConstFetchAnnotationToAttributeMapper; -use Rector\PhpAttribute\AnnotationToAttributeMapper\ConstExprNodeAnnotationToAttributeMapper; use Rector\PhpAttribute\AnnotationToAttributeMapper\CurlyListNodeAnnotationToAttributeMapper; use Rector\PhpAttribute\AnnotationToAttributeMapper\DoctrineAnnotationAnnotationToAttributeMapper; -use Rector\PhpAttribute\AnnotationToAttributeMapper\StringAnnotationToAttributeMapper; -use Rector\PhpAttribute\AnnotationToAttributeMapper\StringNodeAnnotationToAttributeMapper; -use Rector\PhpAttribute\Contract\AnnotationToAttributeMapperInterface; use Rector\PhpDocParser\NodeTraverser\SimpleCallableNodeTraverser; use Rector\PhpParser\Comparing\NodeComparator; use Rector\PhpParser\Node\NodeFactory; @@ -140,20 +135,6 @@ final class LazyContainerFactory UnionTypeNodePhpDocNodeVisitor::class, ]; - /** - * @var array> - */ - private const array ANNOTATION_TO_ATTRIBUTE_MAPPER_CLASSES = [ - ArrayAnnotationToAttributeMapper::class, - ArrayItemNodeAnnotationToAttributeMapper::class, - ClassConstFetchAnnotationToAttributeMapper::class, - ConstExprNodeAnnotationToAttributeMapper::class, - CurlyListNodeAnnotationToAttributeMapper::class, - DoctrineAnnotationAnnotationToAttributeMapper::class, - StringAnnotationToAttributeMapper::class, - StringNodeAnnotationToAttributeMapper::class, - ]; - /** * @var array> */ @@ -413,11 +394,7 @@ static function (AbstractRector $rector) use ($rectorConfig): void { private function registerTaggedServices(RectorConfig $rectorConfig): void { // PHP 8.0 attributes - $this->registerTagged( - $rectorConfig, - self::ANNOTATION_TO_ATTRIBUTE_MAPPER_CLASSES, - AnnotationToAttributeMapperInterface::class - ); + $rectorConfig->autodiscover(__DIR__ . '/../PhpAttribute/AnnotationToAttributeMapper'); $this->registerTagged($rectorConfig, self::TYPE_MAPPER_CLASSES, TypeMapperInterface::class); $rectorConfig->autodiscover(__DIR__ . '/../StaticTypeMapper/PhpDocParser'); diff --git a/src/PhpAttribute/AnnotationToAttributeMapper/StringAnnotationToAttributeMapper.php b/src/PhpAttribute/AnnotationToAttributeMapper/StringAnnotationToAttributeMapper.php index 726a66eaf46..638c6a6da7a 100644 --- a/src/PhpAttribute/AnnotationToAttributeMapper/StringAnnotationToAttributeMapper.php +++ b/src/PhpAttribute/AnnotationToAttributeMapper/StringAnnotationToAttributeMapper.php @@ -15,7 +15,13 @@ final class StringAnnotationToAttributeMapper implements AnnotationToAttributeMa { public function isCandidate(mixed $value): bool { - return is_string($value); + if (! is_string($value)) { + return false; + } + + // an unquoted "Class::CONST" reference is handled by the class const fetch mapper; + // excluding it here keeps the two mappers mutually exclusive, so match order no longer matters + return ! str_contains($value, '::') || str_starts_with($value, '"'); } /**