From 7565bde3acc722c85ff0092e5254c1fd4832fb3b Mon Sep 17 00:00:00 2001 From: Nathan Dench Date: Wed, 19 Jun 2024 12:35:16 +1000 Subject: [PATCH 1/8] AddTypeToConst allow ignoring inheritance --- Dockerfile | 3 +- .../docs/rector_rules_overview.md | 12 +++++ .../apply_to_abstract_class.php.inc | 21 ++++++++ .../apply_to_public_const.php.inc | 23 ++++++++ .../IgnoreInheritanceRectorTest.php | 28 ++++++++++ .../config/ignore_inheritance.php | 15 ++++++ .../FuncCall/HebrevcToNl2brHebrevRector.php | 7 +-- .../ClassConst/AddTypeToConstRector.php | 52 +++++++++++++++++-- .../PhpParser/NameNodeMapper.php | 2 +- 9 files changed, 150 insertions(+), 13 deletions(-) create mode 100644 rules-tests/Php83/Rector/ClassConst/AddTypeToConstRector/FixtureIgnoreInheritance/apply_to_abstract_class.php.inc create mode 100644 rules-tests/Php83/Rector/ClassConst/AddTypeToConstRector/FixtureIgnoreInheritance/apply_to_public_const.php.inc create mode 100644 rules-tests/Php83/Rector/ClassConst/AddTypeToConstRector/IgnoreInheritanceRectorTest.php create mode 100644 rules-tests/Php83/Rector/ClassConst/AddTypeToConstRector/config/ignore_inheritance.php diff --git a/Dockerfile b/Dockerfile index b8511e95781..4626674410d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,8 +3,9 @@ FROM php:8-cli-alpine WORKDIR /etc/rector # required for composer patches -RUN apk add --no-cache patch +RUN apk add --no-cache patch git COPY --from=composer:2 /usr/bin/composer /usr/bin/composer RUN mkdir -p /etc/rector +RUN git config --global --add safe.directory /etc/rector diff --git a/build/target-repository/docs/rector_rules_overview.md b/build/target-repository/docs/rector_rules_overview.md index e460902499e..3186ed5af17 100644 --- a/build/target-repository/docs/rector_rules_overview.md +++ b/build/target-repository/docs/rector_rules_overview.md @@ -5510,6 +5510,8 @@ Add override attribute to overridden methods Add type to constants +:wrench: **configure it!** + - class: [`Rector\Php83\Rector\ClassConst\AddTypeToConstRector`](../rules/Php83/Rector/ClassConst/AddTypeToConstRector.php) ```diff @@ -5522,6 +5524,16 @@ Add type to constants
+```diff + class SomeClass extends SomeOtherClass + { +- public const TYPE = 'some_type'; ++ public const string TYPE = 'some_type'; + } +``` + +
+ ### CombineHostPortLdapUriRector Combine separated host and port on `ldap_connect()` args diff --git a/rules-tests/Php83/Rector/ClassConst/AddTypeToConstRector/FixtureIgnoreInheritance/apply_to_abstract_class.php.inc b/rules-tests/Php83/Rector/ClassConst/AddTypeToConstRector/FixtureIgnoreInheritance/apply_to_abstract_class.php.inc new file mode 100644 index 00000000000..1a1a246eb3c --- /dev/null +++ b/rules-tests/Php83/Rector/ClassConst/AddTypeToConstRector/FixtureIgnoreInheritance/apply_to_abstract_class.php.inc @@ -0,0 +1,21 @@ + +----- + diff --git a/rules-tests/Php83/Rector/ClassConst/AddTypeToConstRector/FixtureIgnoreInheritance/apply_to_public_const.php.inc b/rules-tests/Php83/Rector/ClassConst/AddTypeToConstRector/FixtureIgnoreInheritance/apply_to_public_const.php.inc new file mode 100644 index 00000000000..8ba8af9e07d --- /dev/null +++ b/rules-tests/Php83/Rector/ClassConst/AddTypeToConstRector/FixtureIgnoreInheritance/apply_to_public_const.php.inc @@ -0,0 +1,23 @@ + +----- + diff --git a/rules-tests/Php83/Rector/ClassConst/AddTypeToConstRector/IgnoreInheritanceRectorTest.php b/rules-tests/Php83/Rector/ClassConst/AddTypeToConstRector/IgnoreInheritanceRectorTest.php new file mode 100644 index 00000000000..1d115f02cdd --- /dev/null +++ b/rules-tests/Php83/Rector/ClassConst/AddTypeToConstRector/IgnoreInheritanceRectorTest.php @@ -0,0 +1,28 @@ +doTestFile($filePath); + } + + public static function provideData(): Iterator + { + return self::yieldFilesFromDirectory(__DIR__ . '/FixtureIgnoreInheritance'); + } + + public function provideConfigFilePath(): string + { + return __DIR__ . '/config/ignore_inheritance.php'; + } +} diff --git a/rules-tests/Php83/Rector/ClassConst/AddTypeToConstRector/config/ignore_inheritance.php b/rules-tests/Php83/Rector/ClassConst/AddTypeToConstRector/config/ignore_inheritance.php new file mode 100644 index 00000000000..f0651d73184 --- /dev/null +++ b/rules-tests/Php83/Rector/ClassConst/AddTypeToConstRector/config/ignore_inheritance.php @@ -0,0 +1,15 @@ +ruleWithConfiguration(AddTypeToConstRector::class, [ + AddTypeToConstRector::IGNORE_INHERITANCE => true, + ]); + + $rectorConfig->phpVersion(PhpVersion::PHP_83); +}; diff --git a/rules/Php74/Rector/FuncCall/HebrevcToNl2brHebrevRector.php b/rules/Php74/Rector/FuncCall/HebrevcToNl2brHebrevRector.php index 65ffdcb93b8..0f4cd2bbf02 100644 --- a/rules/Php74/Rector/FuncCall/HebrevcToNl2brHebrevRector.php +++ b/rules/Php74/Rector/FuncCall/HebrevcToNl2brHebrevRector.php @@ -65,11 +65,6 @@ public function refactor(Node $node): ?FuncCall } $node->name = new Name('hebrev'); - return new FuncCall( - new Name('nl2br'), - [ - new Arg($node) - ] - ); + return new FuncCall(new Name('nl2br'), [new Arg($node)]); } } diff --git a/rules/Php83/Rector/ClassConst/AddTypeToConstRector.php b/rules/Php83/Rector/ClassConst/AddTypeToConstRector.php index b2474721540..2baa42a21d2 100644 --- a/rules/Php83/Rector/ClassConst/AddTypeToConstRector.php +++ b/rules/Php83/Rector/ClassConst/AddTypeToConstRector.php @@ -20,19 +20,29 @@ use PhpParser\Node\Stmt\ClassConst; use PHPStan\Reflection\ClassReflection; use PHPStan\Reflection\ReflectionProvider; +use Rector\Contract\Rector\ConfigurableRectorInterface; use Rector\PHPStanStaticTypeMapper\Enum\TypeKind; use Rector\Rector\AbstractRector; use Rector\StaticTypeMapper\StaticTypeMapper; use Rector\ValueObject\PhpVersionFeature; use Rector\VersionBonding\Contract\MinPhpVersionInterface; -use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; +use Symplify\RuleDocGenerator\ValueObject\CodeSample\ConfiguredCodeSample; use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; +use Webmozart\Assert\Assert; /** * @see \Rector\Tests\Php83\Rector\ClassConst\AddTypeToConstRector\AddTypeToConstRectorTest */ -final class AddTypeToConstRector extends AbstractRector implements MinPhpVersionInterface +final class AddTypeToConstRector extends AbstractRector implements ConfigurableRectorInterface, MinPhpVersionInterface { + /** + * @api + * @var string + */ + final public const IGNORE_INHERITANCE = 'ignore_inheritance'; + + private bool $ignoreInheritance = false; + public function __construct( private readonly ReflectionProvider $reflectionProvider, private readonly StaticTypeMapper $staticTypeMapper @@ -42,7 +52,7 @@ public function __construct( public function getRuleDefinition(): RuleDefinition { return new RuleDefinition('Add type to constants', [ - new CodeSample( + new ConfiguredCodeSample( <<<'CODE_SAMPLE' final class SomeClass { @@ -57,6 +67,28 @@ final class SomeClass } CODE_SAMPLE , + [ + AddTypeToConstRector::IGNORE_INHERITANCE => false, + ] + ), + new ConfiguredCodeSample( + <<<'CODE_SAMPLE' +class SomeClass extends SomeOtherClass +{ + public const TYPE = 'some_type'; +} +CODE_SAMPLE + , + <<<'CODE_SAMPLE' +class SomeClass extends SomeOtherClass +{ + public const string TYPE = 'some_type'; +} +CODE_SAMPLE + , + [ + AddTypeToConstRector::IGNORE_INHERITANCE => true, + ] ), ]); } @@ -76,7 +108,7 @@ public function refactor(Node $node): ?Class_ return null; } - if ($node->isAbstract()) { + if (! $this->ignoreInheritance && $node->isAbstract()) { return null; } @@ -103,7 +135,7 @@ public function refactor(Node $node): ?Class_ continue; } - if ($this->canBeInherited($classConst, $node)) { + if (! $this->ignoreInheritance && $this->canBeInherited($classConst, $node)) { continue; } @@ -139,6 +171,16 @@ public function refactor(Node $node): ?Class_ return $node; } + /** + * @param mixed[] $configuration + */ + public function configure(array $configuration): void + { + $ignoreInheritance = $configuration[self::IGNORE_INHERITANCE] ?? (bool) current($configuration); + Assert::boolean($ignoreInheritance); + $this->ignoreInheritance = $ignoreInheritance; + } + public function provideMinPhpVersion(): int { return PhpVersionFeature::TYPED_CLASS_CONSTANTS; diff --git a/src/StaticTypeMapper/PhpParser/NameNodeMapper.php b/src/StaticTypeMapper/PhpParser/NameNodeMapper.php index 1953b9f4de9..e81c3e908cf 100644 --- a/src/StaticTypeMapper/PhpParser/NameNodeMapper.php +++ b/src/StaticTypeMapper/PhpParser/NameNodeMapper.php @@ -61,7 +61,7 @@ private function expandedNamespacedName(Node $node): ?FullyQualified return null; } - if (!$node->hasAttribute(AttributeKey::NAMESPACED_NAME)) { + if (! $node->hasAttribute(AttributeKey::NAMESPACED_NAME)) { return null; } From ee0ad911f2d2a75ff4210de4a7d7c88093f68c85 Mon Sep 17 00:00:00 2001 From: Nathan Dench Date: Thu, 20 Jun 2024 21:42:05 +1000 Subject: [PATCH 2/8] rename ignoreInheritance to allowHasChild --- .../config/ignore_inheritance.php | 2 +- .../Rector/ClassConst/AddTypeToConstRector.php | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/rules-tests/Php83/Rector/ClassConst/AddTypeToConstRector/config/ignore_inheritance.php b/rules-tests/Php83/Rector/ClassConst/AddTypeToConstRector/config/ignore_inheritance.php index f0651d73184..58d22e2c53d 100644 --- a/rules-tests/Php83/Rector/ClassConst/AddTypeToConstRector/config/ignore_inheritance.php +++ b/rules-tests/Php83/Rector/ClassConst/AddTypeToConstRector/config/ignore_inheritance.php @@ -8,7 +8,7 @@ return static function (RectorConfig $rectorConfig): void { $rectorConfig->ruleWithConfiguration(AddTypeToConstRector::class, [ - AddTypeToConstRector::IGNORE_INHERITANCE => true, + AddTypeToConstRector::ALLOW_HAS_CHILD => true, ]); $rectorConfig->phpVersion(PhpVersion::PHP_83); diff --git a/rules/Php83/Rector/ClassConst/AddTypeToConstRector.php b/rules/Php83/Rector/ClassConst/AddTypeToConstRector.php index 2baa42a21d2..6b815692151 100644 --- a/rules/Php83/Rector/ClassConst/AddTypeToConstRector.php +++ b/rules/Php83/Rector/ClassConst/AddTypeToConstRector.php @@ -39,9 +39,9 @@ final class AddTypeToConstRector extends AbstractRector implements ConfigurableR * @api * @var string */ - final public const IGNORE_INHERITANCE = 'ignore_inheritance'; + final public const ALLOW_HAS_CHILD = 'allow_has_child'; - private bool $ignoreInheritance = false; + private bool $allowHasChild = false; public function __construct( private readonly ReflectionProvider $reflectionProvider, @@ -68,7 +68,7 @@ final class SomeClass CODE_SAMPLE , [ - AddTypeToConstRector::IGNORE_INHERITANCE => false, + AddTypeToConstRector::ALLOW_HAS_CHILD => false, ] ), new ConfiguredCodeSample( @@ -87,7 +87,7 @@ class SomeClass extends SomeOtherClass CODE_SAMPLE , [ - AddTypeToConstRector::IGNORE_INHERITANCE => true, + AddTypeToConstRector::ALLOW_HAS_CHILD => true, ] ), ]); @@ -108,7 +108,7 @@ public function refactor(Node $node): ?Class_ return null; } - if (! $this->ignoreInheritance && $node->isAbstract()) { + if (! $this->allowHasChild && $node->isAbstract()) { return null; } @@ -135,7 +135,7 @@ public function refactor(Node $node): ?Class_ continue; } - if (! $this->ignoreInheritance && $this->canBeInherited($classConst, $node)) { + if (! $this->allowHasChild && $this->canBeInherited($classConst, $node)) { continue; } @@ -176,9 +176,9 @@ public function refactor(Node $node): ?Class_ */ public function configure(array $configuration): void { - $ignoreInheritance = $configuration[self::IGNORE_INHERITANCE] ?? (bool) current($configuration); + $ignoreInheritance = $configuration[self::ALLOW_HAS_CHILD] ?? (bool) current($configuration); Assert::boolean($ignoreInheritance); - $this->ignoreInheritance = $ignoreInheritance; + $this->allowHasChild = $ignoreInheritance; } public function provideMinPhpVersion(): int From 75dabd3ff0beb0a20c23c6b3640f6d7c48832a30 Mon Sep 17 00:00:00 2001 From: Nathan Dench Date: Thu, 20 Jun 2024 21:58:02 +1000 Subject: [PATCH 3/8] Add failing test for inheritance --- .../apply_to_abstract_class.php.inc | 21 ---------- ...ublic_const_when_no_child_classes.php.inc} | 6 +-- ...to_class_const_when_not_overridden.php.inc | 39 +++++++++++++++++++ .../ClassConst/AddTypeToConstRector.php | 2 +- 4 files changed, 42 insertions(+), 26 deletions(-) delete mode 100644 rules-tests/Php83/Rector/ClassConst/AddTypeToConstRector/FixtureIgnoreInheritance/apply_to_abstract_class.php.inc rename rules-tests/Php83/Rector/ClassConst/AddTypeToConstRector/FixtureIgnoreInheritance/{apply_to_public_const.php.inc => apply_to_public_const_when_no_child_classes.php.inc} (73%) create mode 100644 rules-tests/Php83/Rector/ClassConst/AddTypeToConstRector/FixtureIgnoreInheritance/apply_type_to_class_const_when_not_overridden.php.inc diff --git a/rules-tests/Php83/Rector/ClassConst/AddTypeToConstRector/FixtureIgnoreInheritance/apply_to_abstract_class.php.inc b/rules-tests/Php83/Rector/ClassConst/AddTypeToConstRector/FixtureIgnoreInheritance/apply_to_abstract_class.php.inc deleted file mode 100644 index 1a1a246eb3c..00000000000 --- a/rules-tests/Php83/Rector/ClassConst/AddTypeToConstRector/FixtureIgnoreInheritance/apply_to_abstract_class.php.inc +++ /dev/null @@ -1,21 +0,0 @@ - ------ - diff --git a/rules-tests/Php83/Rector/ClassConst/AddTypeToConstRector/FixtureIgnoreInheritance/apply_to_public_const.php.inc b/rules-tests/Php83/Rector/ClassConst/AddTypeToConstRector/FixtureIgnoreInheritance/apply_to_public_const_when_no_child_classes.php.inc similarity index 73% rename from rules-tests/Php83/Rector/ClassConst/AddTypeToConstRector/FixtureIgnoreInheritance/apply_to_public_const.php.inc rename to rules-tests/Php83/Rector/ClassConst/AddTypeToConstRector/FixtureIgnoreInheritance/apply_to_public_const_when_no_child_classes.php.inc index 8ba8af9e07d..49ed5c43cde 100644 --- a/rules-tests/Php83/Rector/ClassConst/AddTypeToConstRector/FixtureIgnoreInheritance/apply_to_public_const.php.inc +++ b/rules-tests/Php83/Rector/ClassConst/AddTypeToConstRector/FixtureIgnoreInheritance/apply_to_public_const_when_no_child_classes.php.inc @@ -2,11 +2,10 @@ namespace Rector\Tests\Php83\Rector\ClassConst\AddTypeToConstRector\Fixture; -class ApplyToPublicConst +class ApplyTypeWhenNoChildren { private const A = 1000; public const B = 'foo'; - public const C = 'bar'; } ?> ----- @@ -14,10 +13,9 @@ class ApplyToPublicConst namespace Rector\Tests\Php83\Rector\ClassConst\AddTypeToConstRector\Fixture; -class ApplyToPublicConst +class ApplyTypeWhenNoChildren { private const int A = 1000; public const string B = 'foo'; - public const string C = 'bar'; } ?> diff --git a/rules-tests/Php83/Rector/ClassConst/AddTypeToConstRector/FixtureIgnoreInheritance/apply_type_to_class_const_when_not_overridden.php.inc b/rules-tests/Php83/Rector/ClassConst/AddTypeToConstRector/FixtureIgnoreInheritance/apply_type_to_class_const_when_not_overridden.php.inc new file mode 100644 index 00000000000..1bcf6fd6905 --- /dev/null +++ b/rules-tests/Php83/Rector/ClassConst/AddTypeToConstRector/FixtureIgnoreInheritance/apply_type_to_class_const_when_not_overridden.php.inc @@ -0,0 +1,39 @@ + +----- + diff --git a/rules/Php83/Rector/ClassConst/AddTypeToConstRector.php b/rules/Php83/Rector/ClassConst/AddTypeToConstRector.php index 6b815692151..f00ed8bfbed 100644 --- a/rules/Php83/Rector/ClassConst/AddTypeToConstRector.php +++ b/rules/Php83/Rector/ClassConst/AddTypeToConstRector.php @@ -108,7 +108,7 @@ public function refactor(Node $node): ?Class_ return null; } - if (! $this->allowHasChild && $node->isAbstract()) { + if ($node->isAbstract()) { return null; } From 364ba53ecabdb1ba01af48ee09c4d89ad8680e92 Mon Sep 17 00:00:00 2001 From: Nathan Dench Date: Thu, 20 Jun 2024 22:22:46 +1000 Subject: [PATCH 4/8] Only type constants without child overrides --- .../ClassConst/AddTypeToConstRector.php | 53 ++++++++++++++++++- 1 file changed, 51 insertions(+), 2 deletions(-) diff --git a/rules/Php83/Rector/ClassConst/AddTypeToConstRector.php b/rules/Php83/Rector/ClassConst/AddTypeToConstRector.php index f00ed8bfbed..8aac4766736 100644 --- a/rules/Php83/Rector/ClassConst/AddTypeToConstRector.php +++ b/rules/Php83/Rector/ClassConst/AddTypeToConstRector.php @@ -21,6 +21,9 @@ use PHPStan\Reflection\ClassReflection; use PHPStan\Reflection\ReflectionProvider; use Rector\Contract\Rector\ConfigurableRectorInterface; +use Rector\FamilyTree\Reflection\FamilyRelationsAnalyzer; +use Rector\PhpParser\AstResolver; +use Rector\PhpParser\Comparing\NodeComparator; use Rector\PHPStanStaticTypeMapper\Enum\TypeKind; use Rector\Rector\AbstractRector; use Rector\StaticTypeMapper\StaticTypeMapper; @@ -45,7 +48,9 @@ final class AddTypeToConstRector extends AbstractRector implements ConfigurableR public function __construct( private readonly ReflectionProvider $reflectionProvider, - private readonly StaticTypeMapper $staticTypeMapper + private readonly StaticTypeMapper $staticTypeMapper, + private readonly FamilyRelationsAnalyzer $familyRelationsAnalyzer, + private readonly AstResolver $astResolver, ) { } @@ -118,6 +123,7 @@ public function refactor(Node $node): ?Class_ } $parentClassReflections = $this->getParentReflections($className); + $childClassReflections = $this->getChildClassReflections($className); $hasChanged = false; @@ -139,6 +145,10 @@ public function refactor(Node $node): ?Class_ continue; } + if ($this->allowHasChild && $this->isConstGuardedByChildren($constNode, $childClassReflections)) { + continue; + } + $valueTypes[] = $this->findValueType($constNode->value); } @@ -202,6 +212,29 @@ public function isConstGuardedByParents(Const_ $const, array $parentClassReflect return false; } + /** + * @param ClassReflection[] $childClassReflections + */ + public function isConstGuardedByChildren(Const_ $const, array $childClassReflections): bool + { + foreach ($childClassReflections as $childClassReflection) { + $classLike = $this->astResolver->resolveClassFromClassReflection($childClassReflection); + if (! $classLike instanceof Class_) { + continue; + } + + foreach ($classLike->getConstants() as $childClassConstants) { + foreach ($childClassConstants->consts as $childConst) { + if ($this->nodeComparator->areNodesEqual($childConst, $const)) { + return true; + } + } + } + } + + return false; + } + private function findValueType(Expr $expr): ?Identifier { if ($expr instanceof UnaryPlus || $expr instanceof UnaryMinus) { @@ -262,8 +295,24 @@ private function getParentReflections(string $className): array $currentClassReflection !== $classReflection); } + /** + * @return ClassReflection[] + */ + private function getChildClassReflections(string $className): array + { + if (! $this->reflectionProvider->hasClass($className)) { + return []; + } + + $currentClassReflection = $this->reflectionProvider->getClass($className); + + return $this->familyRelationsAnalyzer->getChildrenOfClassReflection($currentClassReflection); + } + private function canBeInherited(ClassConst $classConst, Class_ $class): bool { - return ! $class->isFinal() && ! $classConst->isPrivate() && ! $classConst->isFinal(); + if (! $this->allowHasChild) { + return ! $class->isFinal() && ! $classConst->isPrivate() && ! $classConst->isFinal(); + } } } From b6c49a56384045cfe65ae3d3d762f117517ff9a3 Mon Sep 17 00:00:00 2001 From: Nathan Dench Date: Thu, 20 Jun 2024 22:23:28 +1000 Subject: [PATCH 5/8] Undo Dockerfile changes --- Dockerfile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 4626674410d..b8511e95781 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,9 +3,8 @@ FROM php:8-cli-alpine WORKDIR /etc/rector # required for composer patches -RUN apk add --no-cache patch git +RUN apk add --no-cache patch COPY --from=composer:2 /usr/bin/composer /usr/bin/composer RUN mkdir -p /etc/rector -RUN git config --global --add safe.directory /etc/rector From 9742ede08806bcb750bfb9f076b22672d65f5a07 Mon Sep 17 00:00:00 2001 From: Nathan Dench Date: Thu, 20 Jun 2024 22:25:58 +1000 Subject: [PATCH 6/8] CI run --- rules/Php83/Rector/ClassConst/AddTypeToConstRector.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/rules/Php83/Rector/ClassConst/AddTypeToConstRector.php b/rules/Php83/Rector/ClassConst/AddTypeToConstRector.php index 8aac4766736..77613e347e1 100644 --- a/rules/Php83/Rector/ClassConst/AddTypeToConstRector.php +++ b/rules/Php83/Rector/ClassConst/AddTypeToConstRector.php @@ -23,7 +23,6 @@ use Rector\Contract\Rector\ConfigurableRectorInterface; use Rector\FamilyTree\Reflection\FamilyRelationsAnalyzer; use Rector\PhpParser\AstResolver; -use Rector\PhpParser\Comparing\NodeComparator; use Rector\PHPStanStaticTypeMapper\Enum\TypeKind; use Rector\Rector\AbstractRector; use Rector\StaticTypeMapper\StaticTypeMapper; @@ -311,8 +310,6 @@ private function getChildClassReflections(string $className): array private function canBeInherited(ClassConst $classConst, Class_ $class): bool { - if (! $this->allowHasChild) { - return ! $class->isFinal() && ! $classConst->isPrivate() && ! $classConst->isFinal(); - } + return ! $class->isFinal() && ! $classConst->isPrivate() && ! $classConst->isFinal(); } } From da761bde5aec33518fe360f66ad5538261b67ba4 Mon Sep 17 00:00:00 2001 From: Nathan Dench Date: Thu, 20 Jun 2024 22:30:01 +1000 Subject: [PATCH 7/8] Update documentation for allow_has_child --- .../docs/rector_rules_overview.md | 8 +++++++- .../Rector/ClassConst/AddTypeToConstRector.php | 16 ++++++++++++++-- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/build/target-repository/docs/rector_rules_overview.md b/build/target-repository/docs/rector_rules_overview.md index 3186ed5af17..683d94acf92 100644 --- a/build/target-repository/docs/rector_rules_overview.md +++ b/build/target-repository/docs/rector_rules_overview.md @@ -5525,10 +5525,16 @@ Add type to constants
```diff - class SomeClass extends SomeOtherClass + class ParentClass extends ChildClass { - public const TYPE = 'some_type'; + public const string TYPE = 'some_type'; + public const OTHER_TYPE = 'other_type'; + } + + class ChildClass + { + public const OTHER_TYPE = 'other_type'; } ``` diff --git a/rules/Php83/Rector/ClassConst/AddTypeToConstRector.php b/rules/Php83/Rector/ClassConst/AddTypeToConstRector.php index 77613e347e1..eecd34f183b 100644 --- a/rules/Php83/Rector/ClassConst/AddTypeToConstRector.php +++ b/rules/Php83/Rector/ClassConst/AddTypeToConstRector.php @@ -77,16 +77,28 @@ final class SomeClass ), new ConfiguredCodeSample( <<<'CODE_SAMPLE' -class SomeClass extends SomeOtherClass +class ParentClass extends ChildClass { public const TYPE = 'some_type'; + public const OTHER_TYPE = 'other_type'; +} + +class ChildClass +{ + public const OTHER_TYPE = 'other_type'; } CODE_SAMPLE , <<<'CODE_SAMPLE' -class SomeClass extends SomeOtherClass +class ParentClass extends ChildClass { public const string TYPE = 'some_type'; + public const OTHER_TYPE = 'other_type'; +} + +class ChildClass +{ + public const OTHER_TYPE = 'other_type'; } CODE_SAMPLE , From 092bf6c97fb7d9e022efee15a3241eb7dbb42cf9 Mon Sep 17 00:00:00 2001 From: Nathan Dench Date: Thu, 20 Jun 2024 22:33:18 +1000 Subject: [PATCH 8/8] Rename IgnoreInheritance tests to AllowHasChild --- ...nheritanceRectorTest.php => AllowHasChildRectorTest.php} | 6 +++--- .../apply_to_public_const_when_no_child_classes.php.inc | 0 .../apply_type_to_class_const_when_not_overridden.php.inc | 0 .../config/{ignore_inheritance.php => allow_has_child.php} | 0 rules/Php83/Rector/ClassConst/AddTypeToConstRector.php | 2 +- 5 files changed, 4 insertions(+), 4 deletions(-) rename rules-tests/Php83/Rector/ClassConst/AddTypeToConstRector/{IgnoreInheritanceRectorTest.php => AllowHasChildRectorTest.php} (78%) rename rules-tests/Php83/Rector/ClassConst/AddTypeToConstRector/{FixtureIgnoreInheritance => FixtureAllowHasChild}/apply_to_public_const_when_no_child_classes.php.inc (100%) rename rules-tests/Php83/Rector/ClassConst/AddTypeToConstRector/{FixtureIgnoreInheritance => FixtureAllowHasChild}/apply_type_to_class_const_when_not_overridden.php.inc (100%) rename rules-tests/Php83/Rector/ClassConst/AddTypeToConstRector/config/{ignore_inheritance.php => allow_has_child.php} (100%) diff --git a/rules-tests/Php83/Rector/ClassConst/AddTypeToConstRector/IgnoreInheritanceRectorTest.php b/rules-tests/Php83/Rector/ClassConst/AddTypeToConstRector/AllowHasChildRectorTest.php similarity index 78% rename from rules-tests/Php83/Rector/ClassConst/AddTypeToConstRector/IgnoreInheritanceRectorTest.php rename to rules-tests/Php83/Rector/ClassConst/AddTypeToConstRector/AllowHasChildRectorTest.php index 1d115f02cdd..7aa091aaa15 100644 --- a/rules-tests/Php83/Rector/ClassConst/AddTypeToConstRector/IgnoreInheritanceRectorTest.php +++ b/rules-tests/Php83/Rector/ClassConst/AddTypeToConstRector/AllowHasChildRectorTest.php @@ -8,7 +8,7 @@ use PHPUnit\Framework\Attributes\DataProvider; use Rector\Testing\PHPUnit\AbstractRectorTestCase; -final class IgnoreInheritanceRectorTest extends AbstractRectorTestCase +final class AllowHasChildRectorTest extends AbstractRectorTestCase { #[DataProvider('provideData')] public function test(string $filePath): void @@ -18,11 +18,11 @@ public function test(string $filePath): void public static function provideData(): Iterator { - return self::yieldFilesFromDirectory(__DIR__ . '/FixtureIgnoreInheritance'); + return self::yieldFilesFromDirectory(__DIR__ . '/FixtureAllowHasChild'); } public function provideConfigFilePath(): string { - return __DIR__ . '/config/ignore_inheritance.php'; + return __DIR__ . '/config/allow_has_child.php'; } } diff --git a/rules-tests/Php83/Rector/ClassConst/AddTypeToConstRector/FixtureIgnoreInheritance/apply_to_public_const_when_no_child_classes.php.inc b/rules-tests/Php83/Rector/ClassConst/AddTypeToConstRector/FixtureAllowHasChild/apply_to_public_const_when_no_child_classes.php.inc similarity index 100% rename from rules-tests/Php83/Rector/ClassConst/AddTypeToConstRector/FixtureIgnoreInheritance/apply_to_public_const_when_no_child_classes.php.inc rename to rules-tests/Php83/Rector/ClassConst/AddTypeToConstRector/FixtureAllowHasChild/apply_to_public_const_when_no_child_classes.php.inc diff --git a/rules-tests/Php83/Rector/ClassConst/AddTypeToConstRector/FixtureIgnoreInheritance/apply_type_to_class_const_when_not_overridden.php.inc b/rules-tests/Php83/Rector/ClassConst/AddTypeToConstRector/FixtureAllowHasChild/apply_type_to_class_const_when_not_overridden.php.inc similarity index 100% rename from rules-tests/Php83/Rector/ClassConst/AddTypeToConstRector/FixtureIgnoreInheritance/apply_type_to_class_const_when_not_overridden.php.inc rename to rules-tests/Php83/Rector/ClassConst/AddTypeToConstRector/FixtureAllowHasChild/apply_type_to_class_const_when_not_overridden.php.inc diff --git a/rules-tests/Php83/Rector/ClassConst/AddTypeToConstRector/config/ignore_inheritance.php b/rules-tests/Php83/Rector/ClassConst/AddTypeToConstRector/config/allow_has_child.php similarity index 100% rename from rules-tests/Php83/Rector/ClassConst/AddTypeToConstRector/config/ignore_inheritance.php rename to rules-tests/Php83/Rector/ClassConst/AddTypeToConstRector/config/allow_has_child.php diff --git a/rules/Php83/Rector/ClassConst/AddTypeToConstRector.php b/rules/Php83/Rector/ClassConst/AddTypeToConstRector.php index eecd34f183b..d893913a206 100644 --- a/rules/Php83/Rector/ClassConst/AddTypeToConstRector.php +++ b/rules/Php83/Rector/ClassConst/AddTypeToConstRector.php @@ -226,7 +226,7 @@ public function isConstGuardedByParents(Const_ $const, array $parentClassReflect /** * @param ClassReflection[] $childClassReflections */ - public function isConstGuardedByChildren(Const_ $const, array $childClassReflections): bool + private function isConstGuardedByChildren(Const_ $const, array $childClassReflections): bool { foreach ($childClassReflections as $childClassReflection) { $classLike = $this->astResolver->resolveClassFromClassReflection($childClassReflection);