mirror of
https://github.com/danog/psalm.git
synced 2024-11-26 12:24:49 +01:00
Fix int-mask-of expansion
This commit is contained in:
parent
b58782ae29
commit
e3a352d287
@ -290,8 +290,12 @@ class NonDivArithmeticOpAnalyzer
|
|||||||
): ?Type\Union {
|
): ?Type\Union {
|
||||||
if ($left_type_part instanceof TLiteralInt
|
if ($left_type_part instanceof TLiteralInt
|
||||||
&& $right_type_part instanceof TLiteralInt
|
&& $right_type_part instanceof TLiteralInt
|
||||||
&& ($left instanceof PhpParser\Node\Scalar || $left instanceof PhpParser\Node\Expr\ConstFetch)
|
&& ($left instanceof PhpParser\Node\Scalar
|
||||||
&& ($right instanceof PhpParser\Node\Scalar || $right instanceof PhpParser\Node\Expr\ConstFetch)
|
|| $left instanceof PhpParser\Node\Expr\ConstFetch
|
||||||
|
|| $left instanceof PhpParser\Node\Expr\ClassConstFetch)
|
||||||
|
&& ($right instanceof PhpParser\Node\Scalar
|
||||||
|
|| $right instanceof PhpParser\Node\Expr\ConstFetch
|
||||||
|
|| $right instanceof PhpParser\Node\Expr\ClassConstFetch)
|
||||||
) {
|
) {
|
||||||
// time for some arithmetic!
|
// time for some arithmetic!
|
||||||
|
|
||||||
|
@ -272,6 +272,12 @@ class ScalarTypeComparator
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (get_class($container_type_part) === TInt::class
|
||||||
|
&& $input_type_part instanceof TInt
|
||||||
|
) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if ((get_class($input_type_part) === TInt::class && $container_type_part instanceof TLiteralInt)
|
if ((get_class($input_type_part) === TInt::class && $container_type_part instanceof TLiteralInt)
|
||||||
|| (get_class($input_type_part) === TPositiveInt::class
|
|| (get_class($input_type_part) === TPositiveInt::class
|
||||||
&& $container_type_part instanceof TLiteralInt
|
&& $container_type_part instanceof TLiteralInt
|
||||||
|
@ -379,7 +379,46 @@ class TypeExpander
|
|||||||
$final
|
$final
|
||||||
);
|
);
|
||||||
|
|
||||||
if (\is_array($new_value_type) || !$new_value_type instanceof Type\Atomic\TLiteralInt) {
|
if (\is_array($new_value_type)) {
|
||||||
|
$new_value_type = reset($new_value_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$new_value_type instanceof Type\Atomic\TLiteralInt) {
|
||||||
|
return new Type\Atomic\TInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
$potential_ints[] = $new_value_type->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return \Psalm\Internal\Type\TypeParser::getComputedIntsFromMask($potential_ints);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($return_type instanceof Type\Atomic\TIntMaskOf) {
|
||||||
|
if (!$evaluate_class_constants) {
|
||||||
|
return new Type\Atomic\TInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
$value_type = $return_type->value;
|
||||||
|
|
||||||
|
$new_value_types = self::expandAtomic(
|
||||||
|
$codebase,
|
||||||
|
$value_type,
|
||||||
|
$self_class,
|
||||||
|
$static_class_type,
|
||||||
|
$parent_class,
|
||||||
|
$evaluate_class_constants,
|
||||||
|
$evaluate_conditional_types,
|
||||||
|
$final
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!is_array($new_value_types)) {
|
||||||
|
return new Type\Atomic\TInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
$potential_ints = [];
|
||||||
|
|
||||||
|
foreach ($new_value_types as $new_value_type) {
|
||||||
|
if (!$new_value_type instanceof Type\Atomic\TLiteralInt) {
|
||||||
return new Type\Atomic\TInt();
|
return new Type\Atomic\TInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1143,6 +1143,40 @@ class AnnotationTest extends TestCase
|
|||||||
/** @var DateTime $obj */
|
/** @var DateTime $obj */
|
||||||
echo $obj->format("Y");'
|
echo $obj->format("Y");'
|
||||||
],
|
],
|
||||||
|
'intMaskWithClassConstants' => [
|
||||||
|
'<?php
|
||||||
|
class FileFlag {
|
||||||
|
public const OPEN = 1;
|
||||||
|
public const MODIFIED = 2;
|
||||||
|
public const NEW = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int-mask<FileFlag::OPEN, FileFlag::MODIFIED, FileFlag::NEW> $flags
|
||||||
|
*/
|
||||||
|
function takesFlags(int $flags) : void {
|
||||||
|
echo $flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
takesFlags(FileFlag::MODIFIED | FileFlag::NEW);'
|
||||||
|
],
|
||||||
|
'intMaskOfWithClassWildcard' => [
|
||||||
|
'<?php
|
||||||
|
class FileFlag {
|
||||||
|
public const OPEN = 1;
|
||||||
|
public const MODIFIED = 2;
|
||||||
|
public const NEW = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int-mask-of<FileFlag::*> $flags
|
||||||
|
*/
|
||||||
|
function takesFlags(int $flags) : void {
|
||||||
|
echo $flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
takesFlags(FileFlag::MODIFIED | FileFlag::NEW);'
|
||||||
|
],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,8 +49,8 @@ class Php56Test extends TestCase
|
|||||||
$c4 = (new C)->four;',
|
$c4 = (new C)->four;',
|
||||||
'assertions' => [
|
'assertions' => [
|
||||||
'$c1' => 'int',
|
'$c1' => 'int',
|
||||||
'$c2' => 'positive-int',
|
'$c2===' => 'int(2)',
|
||||||
'$c3' => 'positive-int',
|
'$c3===' => 'int(3)',
|
||||||
'$c1_3rd' => 'float|int',
|
'$c1_3rd' => 'float|int',
|
||||||
'$c_sentence' => 'string',
|
'$c_sentence' => 'string',
|
||||||
'$cf' => 'int',
|
'$cf' => 'int',
|
||||||
|
Loading…
Reference in New Issue
Block a user