Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Skip code changes on unresolvable/unknown classes #4619

Merged
merged 7 commits into from
Aug 7, 2023

Conversation

staabm
Copy link
Contributor

@staabm staabm commented Jul 29, 2023

adding test cases which show the bug described in rectorphp/rector#8093


class SkipUnknownParent extends UnknownParentClass
{
public function go($item)
Copy link
Contributor Author

@staabm staabm Jul 29, 2023

Choose a reason for hiding this comment

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

if we don't know the parent class (because e.g. its not autoloadable), we should be pessimistic and do no changes

@samsonasik
Copy link
Member

throw Exception to be validated in the rules can be the way to go:

try {
   parentGuard->...
} catch (ClassParentNotAtoloadedException) {

}

@staabm
Copy link
Contributor Author

staabm commented Jul 29, 2023

thanks for the suggestion. I have a different idea.. let me show it to you :)

@staabm staabm changed the title Added failling tests regarding unknown parents Skip code changes on unresolvable classes Aug 7, 2023
@staabm staabm changed the title Skip code changes on unresolvable classes Skip code changes on unresolvable/unknown classes Aug 7, 2023
@staabm staabm marked this pull request as ready for review August 7, 2023 10:05
@staabm staabm requested a review from TomasVotruba as a code owner August 7, 2023 10:05
@staabm
Copy link
Contributor Author

staabm commented Aug 7, 2023

I expect some delay until Roave/BetterReflection#1359 will be implemented in PHPStan. therefore I implemented the suggested workaround for now

@staabm
Copy link
Contributor Author

staabm commented Aug 7, 2023

@samsonasik should be good to go

) {
}

public function hasParentClassMethod(ClassMethod $classMethod): bool
public function hasParentClassMethod(ClassMethod $classMethod): ?bool
Copy link
Contributor Author

@staabm staabm Aug 7, 2023

Choose a reason for hiding this comment

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

this method now returns true/false when we can make a final decision or null when classes involved are not known and we can't judge

return $parentClassMethod instanceof MethodReflection;
} catch (UnresolvableClassException) {
// we don't know all involved parents.
return null;
Copy link
Member

Choose a reason for hiding this comment

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

just return true here, so it "marked" as has parent so bool can be returned.

Copy link
Contributor Author

@staabm staabm Aug 7, 2023

Choose a reason for hiding this comment

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

I don't think its a good idea to handle "we don't know" the same as "sure, the method exists".

for our callers, as they exist right now, this is acceptable, but it might suprisingly break in the future as soon as someone compares the result of this method against true .

callers might handle the situation differently, depending on the method exists or not.

Copy link
Member

Choose a reason for hiding this comment

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

I prefer to create separate service for param guard handling, eg: ClassMethodParamTypeOverrideGuard.

Something like ClassMethodReturnTypeOverrideGuard::shouldSkipClassMethod() do

public function shouldSkipClassMethod(ClassMethod $classMethod, Scope $scope): bool

Copy link
Member

Choose a reason for hiding this comment

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

@staabm just checked the getParentClassMethod() usages in rules, there are various usage directly, which cause exception, I think try catch should be in consumer instead of in hasParentClassMethod() as that cause double call.

I will create new PR for that.

Copy link
Member

Choose a reason for hiding this comment

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

hm.., the service is named ParentClassMethodTypeOverrideGuard, which has vs get should only validate instead of getting in real use case, so I prefer return bool true for hasParentClassMethod(), and return null for getParentClassMethod() when no parent at all.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

handling UnresolvableClassException at the caller site could indeed improve the current situation 👍

Copy link
Member

Choose a reason for hiding this comment

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

I create PR

return bool only should be the way to go as it only validate, not a "real" verification, we then return ?MethodReflection for getParentClassMethod()

Copy link
Member

@samsonasik samsonasik left a comment

Choose a reason for hiding this comment

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

@TomasVotruba let's merge it so we can improve in separate PR, thank you @staabm

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