1
0
mirror of https://github.com/danog/psalm.git synced 2024-11-30 04:39:00 +01:00

Improve type coverage in both good and bad ways

This commit is contained in:
Matthew Brown 2019-03-25 22:30:40 -04:00
parent aab2d48b13
commit 63a0e768b3
5 changed files with 120 additions and 23 deletions

View File

@ -19,6 +19,8 @@
<directory suffix=".php">src/Psalm/Issue/</directory>
<directory suffix=".php">src/Psalm/Internal/Stubs/</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/psalm.php</file>
<file>src/psalm-language-server.php</file>
@ -26,6 +28,7 @@
<file>src/psalm_plugin.php</file>
<file>src/Psalm/Internal/CallMap.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/Provider/ClassLikeStorageCacheProvider.php</file>
<file>src/Psalm/Internal/Provider/FileReferenceCacheProvider.php</file>

View File

@ -180,8 +180,6 @@ class AssertionFinder
if ($count_equality_position) {
if ($count_equality_position === self::ASSIGNMENT_TO_RIGHT) {
$counted_expr = $conditional->left;
} elseif ($count_equality_position === self::ASSIGNMENT_TO_LEFT) {
$counted_expr = $conditional->right;
} else {
throw new \UnexpectedValueException('$count_equality_position value');
}
@ -238,9 +236,7 @@ class AssertionFinder
$typed_value_position = self::hasTypedValueComparison($conditional);
if ($count_equality_position) {
if ($count_equality_position === self::ASSIGNMENT_TO_RIGHT) {
$count_expr = $conditional->left;
} elseif ($count_equality_position === self::ASSIGNMENT_TO_LEFT) {
if ($count_equality_position === self::ASSIGNMENT_TO_LEFT) {
$count_expr = $conditional->right;
} else {
throw new \UnexpectedValueException('$count_equality_position value');
@ -306,23 +302,6 @@ class AssertionFinder
if ($var_name) {
$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;
@ -718,7 +697,7 @@ class AssertionFinder
}
} else {
if (IssueBuffer::accepts(
new TypeDoesNotContainNull(
new TypeDoesNotContainType(
$var_type . ' does not contain empty array',
new CodeLocation($source, $conditional)
),

View File

@ -45,6 +45,12 @@ class AssignmentTest extends TestCase
echo $x;
}',
],
'ifAssignment' => [
'<?php
if ($foo = rand(0, 1)) {
echo $foo;
}',
],
];
}

View File

@ -335,6 +335,14 @@ class EmptyTest extends TestCase
if (empty($arr[$i]) && empty($arr[$j])) {}
}',
],
'checkArrayEmptyUnknownRoot' => [
'<?php
function foo(array $arr) : void {
if (empty($arr[rand(0, 1)])) {
if ($arr) {}
}
}',
],
];
}

View File

@ -560,6 +560,18 @@ class RedundantConditionTest extends TestCase
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',
],
'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',
],
];
}
}