mirror of
https://github.com/danog/psalm.git
synced 2024-11-30 04:39:00 +01:00
Allow gettype vars to be compared to strings
This commit is contained in:
parent
9e2dacc9e4
commit
c7723df8ff
@ -29,10 +29,7 @@ abstract class ClassLikeAnalyzer extends SourceAnalyzer implements StatementsSou
|
||||
const VISIBILITY_PROTECTED = 2;
|
||||
const VISIBILITY_PRIVATE = 3;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
public static $SPECIAL_TYPES = [
|
||||
public const SPECIAL_TYPES = [
|
||||
'int' => 'int',
|
||||
'string' => 'string',
|
||||
'float' => 'float',
|
||||
@ -47,10 +44,7 @@ abstract class ClassLikeAnalyzer extends SourceAnalyzer implements StatementsSou
|
||||
'mixed' => 'mixed',
|
||||
];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
public static $GETTYPE_TYPES = [
|
||||
public const GETTYPE_TYPES = [
|
||||
'boolean' => true,
|
||||
'integer' => true,
|
||||
'double' => true,
|
||||
|
@ -632,7 +632,7 @@ class AssertionFinder
|
||||
/** @var PhpParser\Node\Scalar\String_ $string_expr */
|
||||
$var_type = $string_expr->value;
|
||||
|
||||
if (!isset(ClassLikeAnalyzer::$GETTYPE_TYPES[$var_type])
|
||||
if (!isset(ClassLikeAnalyzer::GETTYPE_TYPES[$var_type])
|
||||
&& $source instanceof StatementsSource
|
||||
) {
|
||||
if (IssueBuffer::accepts(
|
||||
@ -1159,7 +1159,7 @@ class AssertionFinder
|
||||
throw new \UnexpectedValueException('Shouldn’t get here');
|
||||
}
|
||||
|
||||
if (!isset(ClassLikeAnalyzer::$GETTYPE_TYPES[$var_type])) {
|
||||
if (!isset(ClassLikeAnalyzer::GETTYPE_TYPES[$var_type])) {
|
||||
if (IssueBuffer::accepts(
|
||||
new UnevaluatedCode(
|
||||
'gettype cannot return this value',
|
||||
|
@ -18,6 +18,7 @@ use Psalm\Type\Atomic\TGenericIterable;
|
||||
use Psalm\Type\Atomic\TGenericObject;
|
||||
use Psalm\Type\Atomic\TGenericParam;
|
||||
use Psalm\Type\Atomic\GetClassT;
|
||||
use Psalm\Type\Atomic\GetTypeT;
|
||||
use Psalm\Type\Atomic\THtmlEscapedString;
|
||||
use Psalm\Type\Atomic\TInt;
|
||||
use Psalm\Type\Atomic\TIterable;
|
||||
@ -543,6 +544,22 @@ class TypeAnalyzer
|
||||
);
|
||||
}
|
||||
|
||||
if ($input_type_part instanceof GetTypeT) {
|
||||
$input_type_part = new TString();
|
||||
|
||||
if ($container_type_part instanceof TLiteralString) {
|
||||
return isset(ClassLikeAnalyzer::GETTYPE_TYPES[$container_type_part->value]);
|
||||
}
|
||||
}
|
||||
|
||||
if ($container_type_part instanceof GetTypeT) {
|
||||
$container_type_part = new TString();
|
||||
|
||||
if ($input_type_part instanceof TLiteralString) {
|
||||
return isset(ClassLikeAnalyzer::GETTYPE_TYPES[$input_type_part->value]);
|
||||
}
|
||||
}
|
||||
|
||||
if ($input_type_part->shallowEquals($container_type_part)) {
|
||||
return self::isMatchingTypeContainedBy(
|
||||
$codebase,
|
||||
@ -869,16 +886,11 @@ class TypeAnalyzer
|
||||
if (($input_type_part instanceof TClassString
|
||||
|| $input_type_part instanceof TLiteralClassString)
|
||||
&& (get_class($container_type_part) === TString::class
|
||||
|| get_class($container_type_part) === TSingleLetter::class
|
||||
|| get_class($container_type_part) === GetClassT::class)
|
||||
|| get_class($container_type_part) === TSingleLetter::class)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($container_type_part instanceof TClassString && $input_type_part instanceof GetClassT) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($container_type_part instanceof TString
|
||||
&& ($input_type_part instanceof TNumericString
|
||||
|| $input_type_part instanceof THtmlEscapedString)
|
||||
|
@ -393,7 +393,7 @@ class ClassLikes
|
||||
*/
|
||||
public function classExists($fq_class_name)
|
||||
{
|
||||
if (isset(ClassLikeAnalyzer::$SPECIAL_TYPES[$fq_class_name])) {
|
||||
if (isset(ClassLikeAnalyzer::SPECIAL_TYPES[$fq_class_name])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -453,8 +453,8 @@ class ClassLikes
|
||||
return true;
|
||||
}
|
||||
|
||||
if (isset(ClassLikeAnalyzer::$SPECIAL_TYPES[$interface_id])
|
||||
|| isset(ClassLikeAnalyzer::$SPECIAL_TYPES[$fq_class_name])
|
||||
if (isset(ClassLikeAnalyzer::SPECIAL_TYPES[$interface_id])
|
||||
|| isset(ClassLikeAnalyzer::SPECIAL_TYPES[$fq_class_name])
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
@ -475,7 +475,7 @@ class ClassLikes
|
||||
*/
|
||||
public function interfaceExists($fq_interface_name)
|
||||
{
|
||||
if (isset(ClassLikeAnalyzer::$SPECIAL_TYPES[strtolower($fq_interface_name)])) {
|
||||
if (isset(ClassLikeAnalyzer::SPECIAL_TYPES[strtolower($fq_interface_name)])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1268,7 +1268,7 @@ class FunctionCallTest extends TestCase
|
||||
foo($a);
|
||||
}',
|
||||
],
|
||||
'SKIPPED-getTypeHasValues' => [
|
||||
'getTypeHasValues' => [
|
||||
'<?php
|
||||
/**
|
||||
* @param mixed $maybe
|
||||
@ -1649,6 +1649,17 @@ class FunctionCallTest extends TestCase
|
||||
}',
|
||||
'error_message' => 'DocblockTypeContradiction',
|
||||
],
|
||||
'getTypeInvalidValue' => [
|
||||
'<?php
|
||||
/**
|
||||
* @param mixed $maybe
|
||||
*/
|
||||
function matchesTypes($maybe) : void {
|
||||
$t = gettype($maybe);
|
||||
if ($t === "bool") {}
|
||||
}',
|
||||
'error_message' => 'TypeDoesNotContainType',
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user