mirror of
https://github.com/danog/psalm.git
synced 2024-12-02 09:37:59 +01:00
Improve type coverage in both good and bad ways
This commit is contained in:
parent
aab2d48b13
commit
63a0e768b3
@ -19,6 +19,8 @@
|
|||||||
<directory suffix=".php">src/Psalm/Issue/</directory>
|
<directory suffix=".php">src/Psalm/Issue/</directory>
|
||||||
<directory suffix=".php">src/Psalm/Internal/Stubs/</directory>
|
<directory suffix=".php">src/Psalm/Internal/Stubs/</directory>
|
||||||
<directory suffix=".php">src/Psalm/Internal/LanguageServer/</directory>
|
<directory suffix=".php">src/Psalm/Internal/LanguageServer/</directory>
|
||||||
|
<directory suffix=".php">src/Psalm/Internal/ExecutionEnvironment/</directory>
|
||||||
|
<directory suffix=".php">src/Psalm/SourceControl/</directory>
|
||||||
<file>src/command_functions.php</file>
|
<file>src/command_functions.php</file>
|
||||||
<file>src/psalm.php</file>
|
<file>src/psalm.php</file>
|
||||||
<file>src/psalm-language-server.php</file>
|
<file>src/psalm-language-server.php</file>
|
||||||
@ -26,6 +28,7 @@
|
|||||||
<file>src/psalm_plugin.php</file>
|
<file>src/psalm_plugin.php</file>
|
||||||
<file>src/Psalm/Internal/CallMap.php</file>
|
<file>src/Psalm/Internal/CallMap.php</file>
|
||||||
<file>src/Psalm/Internal/Fork/Pool.php</file>
|
<file>src/Psalm/Internal/Fork/Pool.php</file>
|
||||||
|
<file>src/Psalm/Internal/Fork/Restarter.php</file>
|
||||||
<file>src/Psalm/Internal/PropertyMap.php</file>
|
<file>src/Psalm/Internal/PropertyMap.php</file>
|
||||||
<file>src/Psalm/Internal/Provider/ClassLikeStorageCacheProvider.php</file>
|
<file>src/Psalm/Internal/Provider/ClassLikeStorageCacheProvider.php</file>
|
||||||
<file>src/Psalm/Internal/Provider/FileReferenceCacheProvider.php</file>
|
<file>src/Psalm/Internal/Provider/FileReferenceCacheProvider.php</file>
|
||||||
|
@ -180,8 +180,6 @@ class AssertionFinder
|
|||||||
if ($count_equality_position) {
|
if ($count_equality_position) {
|
||||||
if ($count_equality_position === self::ASSIGNMENT_TO_RIGHT) {
|
if ($count_equality_position === self::ASSIGNMENT_TO_RIGHT) {
|
||||||
$counted_expr = $conditional->left;
|
$counted_expr = $conditional->left;
|
||||||
} elseif ($count_equality_position === self::ASSIGNMENT_TO_LEFT) {
|
|
||||||
$counted_expr = $conditional->right;
|
|
||||||
} else {
|
} else {
|
||||||
throw new \UnexpectedValueException('$count_equality_position value');
|
throw new \UnexpectedValueException('$count_equality_position value');
|
||||||
}
|
}
|
||||||
@ -238,9 +236,7 @@ class AssertionFinder
|
|||||||
$typed_value_position = self::hasTypedValueComparison($conditional);
|
$typed_value_position = self::hasTypedValueComparison($conditional);
|
||||||
|
|
||||||
if ($count_equality_position) {
|
if ($count_equality_position) {
|
||||||
if ($count_equality_position === self::ASSIGNMENT_TO_RIGHT) {
|
if ($count_equality_position === self::ASSIGNMENT_TO_LEFT) {
|
||||||
$count_expr = $conditional->left;
|
|
||||||
} elseif ($count_equality_position === self::ASSIGNMENT_TO_LEFT) {
|
|
||||||
$count_expr = $conditional->right;
|
$count_expr = $conditional->right;
|
||||||
} else {
|
} else {
|
||||||
throw new \UnexpectedValueException('$count_equality_position value');
|
throw new \UnexpectedValueException('$count_equality_position value');
|
||||||
@ -306,23 +302,6 @@ class AssertionFinder
|
|||||||
|
|
||||||
if ($var_name) {
|
if ($var_name) {
|
||||||
$if_types[$var_name] = [['empty']];
|
$if_types[$var_name] = [['empty']];
|
||||||
} else {
|
|
||||||
// look for any variables we *can* use for an isset assertion
|
|
||||||
$array_root = $conditional->expr;
|
|
||||||
|
|
||||||
while ($array_root instanceof PhpParser\Node\Expr\ArrayDimFetch && !$var_name) {
|
|
||||||
$array_root = $array_root->var;
|
|
||||||
|
|
||||||
$var_name = ExpressionAnalyzer::getArrayVarId(
|
|
||||||
$array_root,
|
|
||||||
$this_class_name,
|
|
||||||
$source
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($var_name) {
|
|
||||||
$if_types[$var_name] = [['=empty']];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$conditional->assertions = $if_types;
|
$conditional->assertions = $if_types;
|
||||||
@ -718,7 +697,7 @@ class AssertionFinder
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (IssueBuffer::accepts(
|
if (IssueBuffer::accepts(
|
||||||
new TypeDoesNotContainNull(
|
new TypeDoesNotContainType(
|
||||||
$var_type . ' does not contain empty array',
|
$var_type . ' does not contain empty array',
|
||||||
new CodeLocation($source, $conditional)
|
new CodeLocation($source, $conditional)
|
||||||
),
|
),
|
||||||
|
@ -45,6 +45,12 @@ class AssignmentTest extends TestCase
|
|||||||
echo $x;
|
echo $x;
|
||||||
}',
|
}',
|
||||||
],
|
],
|
||||||
|
'ifAssignment' => [
|
||||||
|
'<?php
|
||||||
|
if ($foo = rand(0, 1)) {
|
||||||
|
echo $foo;
|
||||||
|
}',
|
||||||
|
],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -335,6 +335,14 @@ class EmptyTest extends TestCase
|
|||||||
if (empty($arr[$i]) && empty($arr[$j])) {}
|
if (empty($arr[$i]) && empty($arr[$j])) {}
|
||||||
}',
|
}',
|
||||||
],
|
],
|
||||||
|
'checkArrayEmptyUnknownRoot' => [
|
||||||
|
'<?php
|
||||||
|
function foo(array $arr) : void {
|
||||||
|
if (empty($arr[rand(0, 1)])) {
|
||||||
|
if ($arr) {}
|
||||||
|
}
|
||||||
|
}',
|
||||||
|
],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -560,6 +560,18 @@ class RedundantConditionTest extends TestCase
|
|||||||
assert(is_int($a[0]));
|
assert(is_int($a[0]));
|
||||||
}',
|
}',
|
||||||
],
|
],
|
||||||
|
'allowChecksOnFalsyIf' => [
|
||||||
|
'<?php
|
||||||
|
function foo(?string $s) : string {
|
||||||
|
if ($s == null) {
|
||||||
|
if ($s === null) {}
|
||||||
|
|
||||||
|
return "hello";
|
||||||
|
} else {
|
||||||
|
return $s;
|
||||||
|
}
|
||||||
|
}'
|
||||||
|
],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -865,6 +877,95 @@ class RedundantConditionTest extends TestCase
|
|||||||
}',
|
}',
|
||||||
'error_message' => 'RedundantCondition',
|
'error_message' => 'RedundantCondition',
|
||||||
],
|
],
|
||||||
|
'redundantInstanceof' => [
|
||||||
|
'<?php
|
||||||
|
/** @param Exception $a */
|
||||||
|
function foo($a) : void {
|
||||||
|
if ($a instanceof \Exception) {}
|
||||||
|
}',
|
||||||
|
'error_message' => 'RedundantConditionGivenDocblockType',
|
||||||
|
],
|
||||||
|
'preventDocblockTypesBeingIdenticalToTrue' => [
|
||||||
|
'<?php
|
||||||
|
class A {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param A $a
|
||||||
|
*/
|
||||||
|
function foo($a, $b) : void {
|
||||||
|
if ($a === true) {}
|
||||||
|
}',
|
||||||
|
'error_message' => 'DocblockTypeContradiction',
|
||||||
|
],
|
||||||
|
'preventDocblockTypesBeingIdenticalToTrueReversed' => [
|
||||||
|
'<?php
|
||||||
|
class A {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param A $a
|
||||||
|
*/
|
||||||
|
function foo($a, $b) : void {
|
||||||
|
if (true === $a) {}
|
||||||
|
}',
|
||||||
|
'error_message' => 'DocblockTypeContradiction',
|
||||||
|
],
|
||||||
|
'preventDocblockTypesBeingIdenticalToFalse' => [
|
||||||
|
'<?php
|
||||||
|
class A {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param A $a
|
||||||
|
*/
|
||||||
|
function foo($a, $b) : void {
|
||||||
|
if ($a === false) {}
|
||||||
|
}',
|
||||||
|
'error_message' => 'DocblockTypeContradiction',
|
||||||
|
],
|
||||||
|
'preventDocblockTypesBeingIdenticalToFalseReversed' => [
|
||||||
|
'<?php
|
||||||
|
class A {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param A $a
|
||||||
|
*/
|
||||||
|
function foo($a, $b) : void {
|
||||||
|
if (false === $a) {}
|
||||||
|
}',
|
||||||
|
'error_message' => 'DocblockTypeContradiction',
|
||||||
|
],
|
||||||
|
'preventDocblockTypesBeingSameAsEmptyArrayReversed' => [
|
||||||
|
'<?php
|
||||||
|
class A {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param A $a
|
||||||
|
*/
|
||||||
|
function foo($a, $b) : void {
|
||||||
|
if ([] == $a) {}
|
||||||
|
}',
|
||||||
|
'error_message' => 'DocblockTypeContradiction',
|
||||||
|
],
|
||||||
|
'preventDocblockTypesBeingIdenticalToEmptyArrayReversed' => [
|
||||||
|
'<?php
|
||||||
|
class A {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param A $a
|
||||||
|
*/
|
||||||
|
function foo($a, $b) : void {
|
||||||
|
if ([] === $a) {}
|
||||||
|
}',
|
||||||
|
'error_message' => 'DocblockTypeContradiction',
|
||||||
|
],
|
||||||
|
'preventTypesBeingIdenticalToEmptyArrayReversed' => [
|
||||||
|
'<?php
|
||||||
|
class A {}
|
||||||
|
|
||||||
|
function foo(A $a, $b) : void {
|
||||||
|
if ([] === $a) {}
|
||||||
|
}',
|
||||||
|
'error_message' => 'TypeDoesNotContainType',
|
||||||
|
],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user