-
Notifications
You must be signed in to change notification settings - Fork 431
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
Support object for ReflectionClass #566
Conversation
public function doThing($rightClassOrObject, $wrongClassOrObject): void | ||
{ | ||
try { | ||
new \ReflectionClass($rightClassOrObject); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code needs more advanced logic if you have an expression that can contain something else besides an object.
(new ObjectWithoutClassType())->isSuperTypeOf($valueType)->yes()
will be true only for object
or Foo
or Foo|Bar
. And that test is missing here.
Foo|string
and similar types will fall through this condition.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Before the check
(new ObjectWithoutClassType())->isSuperTypeOf($valueType)->yes()
I have the code
foreach (TypeUtils::getConstantStrings($valueType) as $constantString) {
if (!$this->reflectionProvider->hasClass($constantString->getValue())) {
return $methodReflection->getThrowType();
}
$valueType = TypeCombinator::remove($valueType, $constantString);
}
I thought that after the foreach, the $valueType
would have been now \DateTime|\DateTimeImmutable
since I used TypeCombinator::remove
with the constant class-string<\DateTime>
.
This is exactly why I had two case:
\DateTime|\DateTimeImmutable|class-string<\DateTime>
should have been transformed to\DateTime|\DateTimeImmutable
after the foreach and then the condition returns true.\DateTime|\DateTimeImmutable|string
would have stayed untouched and then an exception is still possible.
What is wrong ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is wrong ?
Case new \ReflectionClass(new Foo());
is not tested. These new added tests would pass without changing src/
I believe.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I meant, why the current tests are failing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ReflectionClass(object) is tested and works.
ReflectionClass(\DateTime|\DateTimeImmutable|class-string<\DateTime>) should not throw an exception, but PHPStan is still believing an exception can be thrown.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ondrejmirtes I think it's because
try {
new \ReflectionClass(\\DateTime::class);
} catch (\Exception $e) {
}
works but
/** @var class-string<\DateTime> $foo */
$foo;
try {
new \ReflectionClass($foo);
} catch (\Exception $e) {
}
doesn't.
The first one is a
class PHPStan\Type\Constant\ConstantStringType#18453 (2) {
private string $value =>
string(8) "DateTime"
private bool $isClassString =>
bool(true)
}
The second one is a
class PHPStan\Type\Generic\GenericClassStringType#18511 (1) {
private PHPStan\Type\Type $type =>
class PHPStan\Type\ObjectType#18481 (6) {
private string $className =>
string(8) "DateTime"
private ?PHPStan\Type\Type $subtractedType =>
NULL
private ?PHPStan\Reflection\ClassReflection $classReflection =>
NULL
private ?PHPStan\Type\ObjectType $cachedParent =>
NULL
private ?array $cachedInterfaces =>
NULL
private array $currentAncestors =>
array(0) {
}
}
}
and TypeUtils::getConstantStrings($valueType)
is only returning the first one.
All the ThrowTypeExtension I provided have the same issue.
Any idea how to fix this ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any idea how to fix this ?
With different logic. Maybe use TypeUtils::flattenTypes()
and iterate over them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ondrejmirtes It's fixed now :)
I even cought a useless @throws
in the psalm codebase.
Thank you! |
Close phpstan/phpstan#5195