Skip to content

Commit

Permalink
Report always false usages of is_a
Browse files Browse the repository at this point in the history
  • Loading branch information
b1rdex committed Jan 31, 2021
1 parent bef5a26 commit 4af149f
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 3 deletions.
3 changes: 0 additions & 3 deletions src/Rules/Comparison/ImpossibleCheckTypeFunctionCallRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,6 @@ public function processNode(Node $node, Scope $scope): array
}

$functionName = (string) $node->name;
if (strtolower($functionName) === 'is_a') {
return [];
}
$isAlways = $this->impossibleCheckTypeHelper->findSpecifiedType($scope, $node);
if ($isAlways === null) {
return [];
Expand Down
16 changes: 16 additions & 0 deletions src/Rules/Comparison/ImpossibleCheckTypeHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@
use PHPStan\Analyser\TypeSpecifier;
use PHPStan\Analyser\TypeSpecifierContext;
use PHPStan\Reflection\ReflectionProvider;
use PHPStan\TrinaryLogic;
use PHPStan\Type\Constant\ConstantArrayType;
use PHPStan\Type\Constant\ConstantBooleanType;
use PHPStan\Type\Constant\ConstantStringType;
use PHPStan\Type\MixedType;
use PHPStan\Type\NeverType;
use PHPStan\Type\ObjectType;
use PHPStan\Type\StringType;
use PHPStan\Type\TypeCombinator;
use PHPStan\Type\TypeUtils;
use PHPStan\Type\TypeWithClassName;
Expand Down Expand Up @@ -157,6 +159,20 @@ public function findSpecifiedType(
}
}
}
} elseif ($functionName === 'is_a') {
$allowString = TrinaryLogic::createNo();
if (count($node->args) > 2) {
$allowStringParameterType = $scope->getType($node->args[2]->value);
$allowString = $allowStringParameterType instanceof ConstantBooleanType
? TrinaryLogic::createFromBoolean($allowStringParameterType->getValue())
: TrinaryLogic::createMaybe();
}
$objectType = $scope->getType($node->args[0]->value);
if ($allowString->no() && (new StringType())->isSuperTypeOf($objectType)) {
return false;
}

return null;
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -385,4 +385,16 @@ public function testBug3994(): void
$this->analyse([__DIR__ . '/data/bug-3994.php'], []);
}

public function testBug4371(): void
{
$this->checkAlwaysTrueCheckTypeFunctionCall = true;
$this->treatPhpDocTypesAsCertain = true;
$this->analyse([__DIR__ . '/data/bug-4371.php'], [
[
"Call to function is_a() with 'Bug4371\\\\Bar' and 'Bug4371\\\\Foo' will always evaluate to false.",
12,
],
]);
}

}
14 changes: 14 additions & 0 deletions tests/PHPStan/Rules/Comparison/data/bug-4371.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

namespace Bug4371;

class Foo {
}

class Bar extends Foo {

}

$a = is_a(Bar::class, Foo::class); // should be reported

$a = is_a(Bar::class, Foo::class, true); // should be fine

0 comments on commit 4af149f

Please sign in to comment.