Skip to content

use conditional parameter for is_a() via stub #1306

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

Closed
wants to merge 12 commits into from

Conversation

staabm
Copy link
Contributor

@staabm staabm commented May 12, 2022

stubs/core.stub Outdated
@@ -1,5 +1,12 @@
<?php

/**
Copy link
Contributor Author

Choose a reason for hiding this comment

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

stub taken 1:1 from psalm

Copy link
Contributor Author

@staabm staabm May 12, 2022

Choose a reason for hiding this comment

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

update: psalm was missing the type for $allow_string, which will be added with vimeo/psalm#7951

@ondrejmirtes
Copy link
Member

Please read the title of the linked issue: is_a: "if third argument is false then do not allow string in first argument"

Which means that there should be a new test in CallToFunctionParametersRuleTest (or ImpossibleCheckTypeFunctionCallRuleTest, that depends) that reports a new error here https://phpstan.org/r/44b40ab5-7c7f-4ced-8048-e084d3d63f1d on line 10.

@staabm
Copy link
Contributor Author

staabm commented May 12, 2022

yeah, it seems the initially reported bug in 4371 is different from the one I had in phpstan/phpstan#4371 (comment)

but I am fine, with also covering the original issue here then

@@ -32,7 +32,7 @@ public function doFoo(

}
$className = 'Foo';
if (is_a($className, \Throwable::class, true)) { // should be fine
if (is_a($className, \Throwable::class, true)) { // always false
Copy link
Contributor Author

Choose a reason for hiding this comment

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

is no longer considered "fine" because Foo is not a subclass of Throwable

Copy link
Member

Choose a reason for hiding this comment

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

But also please test Foo::class (which is different thanks to namespace resolution), the class isn't final so a subclass might implement Throwable.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

hm I guess you mean I should test class-string<Foo> as a parameter not Foo::class.. at least thats what I did for now.. see added tests at the end of this file

@staabm staabm marked this pull request as draft May 13, 2022 07:34
Copy link
Contributor Author

@staabm staabm left a comment

Choose a reason for hiding this comment

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

this gets a few rough edges, therefore I pushed the current development state and hope for feedback.

@@ -32,7 +32,7 @@ public function doFoo(

}
$className = 'Foo';
if (is_a($className, \Throwable::class, true)) { // should be fine
if (is_a($className, \Throwable::class, true)) { // always false
Copy link
Contributor Author

Choose a reason for hiding this comment

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

hm I guess you mean I should test class-string<Foo> as a parameter not Foo::class.. at least thats what I did for now.. see added tests at the end of this file

$exceptionClass = get_class($exception);
assertType('false', is_a($exceptionClass, $classString));
assertType('bool', is_a($exceptionClass, $classString, true));
assertType('false', is_a($exceptionClass, $classString, false));
Copy link
Contributor Author

@staabm staabm May 13, 2022

Choose a reason for hiding this comment

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

with 3e955af I dropped the conditional return type stub again, as I am no longer sure its worth to report about string vs. class-string type errors for $class.. might be tedious.

since we already have extensions for is_a in place the stub itself was nevertheless only partly usefull, I think.

@@ -35,9 +34,6 @@ public function processNode(Node $node, Scope $scope): array
}

$functionName = (string) $node->name;
if (strtolower($functionName) === 'is_a') {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

because I dropped this early-return, I had to compensate a few false positives in the IsAFunctionTypeSpecifyingExtension - added a few early returns.

@@ -42,6 +46,16 @@ public function specifyTypes(FunctionReflection $functionReflection, FuncCall $n
$allowStringType = isset($node->getArgs()[2]) ? $scope->getType($node->getArgs()[2]->value) : new ConstantBooleanType(false);
$allowString = !$allowStringType->equals(new ConstantBooleanType(false));

// early exit in some cases, so we don't create false positives via IsAFunctionTypeSpecifyingHelper
if ($classType instanceof ClassStringType && !$classType instanceof GenericClassStringType) {
Copy link
Contributor Author

@staabm staabm May 13, 2022

Choose a reason for hiding this comment

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

especially this condition is pretty ugly .. would love feedback on how to improve it.

at first I only had the $classType instanceof ClassStringType part, but later on needed to add !$classType instanceof GenericClassStringType to prevent regressions of existing tests

@ondrejmirtes
Copy link
Member

This is already quite messy again :/ I think the stub solved a problem so I really don't want to have it reverted here 3e955af.

But this is truly a minor problem. I'd rather be if you worked on the NamedArgumentsHelper improvements :) Thanks.

@staabm
Copy link
Contributor Author

staabm commented May 13, 2022

I started workin on this topic, because we had a production issue, which would be great if beeing covered by phpstan the next time.

it looked easy at first, but it seems I have no luck in picking topics to work on, since most of the time it turns into walking thru rabbit holes, like we can see here :-/.

will do NamedArguments stuff, when free time allows again.

@ondrejmirtes
Copy link
Member

You can just send the conditional stub in a separate PR alongside with the tests as you initially did, without marking phpstan/phpstan#4371 as closing :)

@ondrejmirtes
Copy link
Member

Basically this commit 6bbb2a6 :)

@ondrejmirtes
Copy link
Member

I have no luck in picking topics to work on

That's normal, I just spent several hours today trying to clean up something about named arguments and I'm not happy with the result either. The combination of php-8-stubs, phpstorm-stubs and php-8-stubs is a mess in some situations. And PHP itself is a mess too :)

@staabm staabm deleted the is-a-cond branch May 13, 2022 13:38
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.

is_a: if third argument is false then do not allow string in first argument
3 participants