phpinspectionsea
phpinspectionsea copied to clipboard
[EA] Null pointer exception may occur here. False positive.
Subject | Details |
---|---|
Plugin | Php Inspections (EA Extended), 4.0.7.1 |
Language level | PHP 7.4 |
I think this is related to https://www.giters.com/kalessil/phpinspectionsea/issues/1560 or at least, pretty similar (by @voku)
Current behaviour
When using "Person.ageNullable" property, then there is a complain about a possible null although the method Person->getName()
has a non-nullable return type of /** @return Age */
.

The reason seems to be that it's getting the return type from the property /** @var Age|null */
and not from the method /** @return Age */
.

Expected behaviour
I would expect to don't have this warning of "Possible NULL" when the method has a specific non-nullable return type.

Environment details
This applies to all PHP versions. But especially from PHP >=7.4
The code used to reproduce the example
<?php declare(strict_types = 1);
class Age
{
private int $value;
public static function fromInt(int $age): self
{
if ($age < 0) {
throw new \RuntimeException('Impossible');
}
$self = new self();
$self->value = $age;
return $self;
}
public function value(): int
{
return $this->value;
}
}
class Person
{
/** @var Age|null */
private $ageNullable;
/** @var Age */
private $ageForced;
public static function withAge(int $age): self
{
$self = new self();
$self->age = Age::fromInt($age);
return $self;
}
/** @return Age */
public function getAge()
{
return $this->ageNullable;
}
}
class MainExample
{
public static function main(): void
{
$person = Person::withAge(28);
$age = $person->getAge();
self::printAge($age); # <---- THIS IS A FALSE POSITIVE
}
private static function printAge(Age $age): void
{
echo 'Age value: ' . $age->value();
}
}
I'm sorry for the code, it's not ideal I know... but this is the quickest way to share the problem. Using real return types at level function is (unfortunately) not an option in this context. That's why I think it's a pretty nice edge case...
Exactly the same issue with older Symfony code:
abstract class ContainerAwareCommand extends Command implements ContainerAwareInterface
{
/**
* @var ContainerInterface|null
*/
private $container;
/**
* @return ContainerInterface
*
* @throws \LogicException
*/
protected function getContainer()
then in any extending class:
$this->getContainer()->getParameter('kernel.environment')
ends with Null pointer exception may occur here
. The plugin should respect the annotations if you ask me as this is the ultimate source of truth provider by the developer.
The same thing occurs in Doctrine:
$criteria = Criteria::create()
->where(Criteria::expr()->eq('active', 1)) // <---- THIS IS A FALSE POSITIVE
;
Doctrine Code:
/**
* Returns the expression builder.
*
* @return \Doctrine\Common\Collections\ExpressionBuilder
*/
public static function expr()
{
if (self::$expressionBuilder === null) {
self::$expressionBuilder = new ExpressionBuilder();
}
return self::$expressionBuilder;
}