Skip to content

Conversation

@alfredbez
Copy link
Contributor

I wasn't able to find a rule like this and we use this in our project, have a look at the problem here:

@TomasVotruba TomasVotruba requested a review from samsonasik May 19, 2022 06:51
$classReflection = $scope->getClassReflection();
if (! $classReflection instanceof ClassReflection) {
return false;
}
Copy link
Member

@samsonasik samsonasik May 19, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should only apply when it used inside final class, ref https://3v4l.org/jYOjL vs https://3v4l.org/LWrtJ which result is different.

You can verify inside class with final with:

Suggested change
}
}
if (! $classReflection->isClass()) {
return false;
}
if (! $classReflection->isFinal()) {
return false;
}

Copy link
Member

@samsonasik samsonasik May 19, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, you can get ClassReflection via ReflectionResolver->resolveClassReflection() ref

public function resolveClassReflection(?Node $node): ?ClassReflection

You can inject ReflectionResolver into constructor:

    public function __construct(
        private readonly \Rector\Core\Reflection\ReflectionResolver $reflectionResolver,
    ) {
    }

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see my comment #2332 (comment) for cover non-final class if it going to be included to avoid constant redefinition

[
new CodeSample(
<<<'CODE_SAMPLE'
class Foo {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
class Foo {
final class Foo {

CODE_SAMPLE
,
<<<'CODE_SAMPLE'
class Foo {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
class Foo {
final class Foo {

public function getRuleDefinition(): RuleDefinition
{
return new RuleDefinition(
'Replaces static::* access to private constants with self::*',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
'Replaces static::* access to private constants with self::*',
'Replaces static::* access to private constants with self::* on final class',

@samsonasik
Copy link
Member

samsonasik commented May 19, 2022

For non-final class that extendable, it seems you may looking for child of classes, eg:

$childrenClassReflections = $this->familyRelationsAnalyzer->getChildrenOfClassReflection($classReflection);

loop and verify:

foreach ($childrenClassReflections as $childrenClassReflection) {
    if ($childrenClassReflection->hasConstant($constantName)) {
        return false;
    }
}

ref https://github.com/phpstan/phpstan-src/blob/af49049b5467be26f20f0ae54ff292fc384b2175/src/Reflection/ClassReflection.php#L836

@samsonasik
Copy link
Member

please add test for skip extended class that has the same constant base on #2332 (comment)

@samsonasik
Copy link
Member

samsonasik commented May 19, 2022

After some thinking, it can be dangerous that may cause a BC break if the class is not final as extendable can be anywere.

This should be configurable if need to be applied, with:

  1. make it implements AllowEmptyConfigurableRectorInterface
  2. make it safe by default, eg: make onlyApplyToFinalClass = true config by default.
  3. If it allow non final, still check the existing child codebase for the rescue, while still can break if the position in vendor.

@samsonasik
Copy link
Member

I am closing it as it can cause BC break without various check like my comments before. Feel free to reopen PR when you have a chance to polish it. Thank you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants