mirror of
https://github.com/danog/psalm.git
synced 2024-11-30 04:39:00 +01:00
Update baseline
This commit is contained in:
commit
11e2163ce3
@ -429,6 +429,7 @@
|
||||
<xs:element name="ReferenceReusedFromConfusingScope" type="IssueHandlerType" minOccurs="0" />
|
||||
<xs:element name="ReservedWord" type="IssueHandlerType" minOccurs="0" />
|
||||
<xs:element name="RiskyCast" type="IssueHandlerType" minOccurs="0" />
|
||||
<xs:element name="RiskyTruthyFalsyComparison" type="IssueHandlerType" minOccurs="0" />
|
||||
<xs:element name="StringIncrement" type="IssueHandlerType" minOccurs="0" />
|
||||
<xs:element name="TaintedCallable" type="IssueHandlerType" minOccurs="0" />
|
||||
<xs:element name="TaintedCookie" type="IssueHandlerType" minOccurs="0" />
|
||||
|
@ -246,6 +246,7 @@ Level 5 and above allows a more non-verifiable code, and higher levels are even
|
||||
- [RedundantConditionGivenDocblockType](issues/RedundantConditionGivenDocblockType.md)
|
||||
- [RedundantFunctionCallGivenDocblockType](issues/RedundantFunctionCallGivenDocblockType.md)
|
||||
- [ReferenceConstraintViolation](issues/ReferenceConstraintViolation.md)
|
||||
- [RiskyTruthyFalsyComparison](issues/RiskyTruthyFalsyComparison.md)
|
||||
- [UndefinedTrace](issues/UndefinedTrace.md)
|
||||
- [UnresolvableInclude](issues/UnresolvableInclude.md)
|
||||
- [UnsafeInstantiation](issues/UnsafeInstantiation.md)
|
||||
|
@ -230,6 +230,7 @@
|
||||
- [ReferenceReusedFromConfusingScope](issues/ReferenceReusedFromConfusingScope.md)
|
||||
- [ReservedWord](issues/ReservedWord.md)
|
||||
- [RiskyCast](issues/RiskyCast.md)
|
||||
- [RiskyTruthyFalsyComparison](issues/RiskyTruthyFalsyComparison.md)
|
||||
- [StringIncrement](issues/StringIncrement.md)
|
||||
- [TaintedCallable](issues/TaintedCallable.md)
|
||||
- [TaintedCookie](issues/TaintedCookie.md)
|
||||
|
29
docs/running_psalm/issues/RiskyTruthyFalsyComparison.md
Normal file
29
docs/running_psalm/issues/RiskyTruthyFalsyComparison.md
Normal file
@ -0,0 +1,29 @@
|
||||
# RiskyTruthyFalsyComparison
|
||||
|
||||
Emitted when comparing a value with multiple types that can both contain truthy and falsy values.
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @param array|null $arg
|
||||
* @return void
|
||||
*/
|
||||
function foo($arg) {
|
||||
if ($arg) {
|
||||
// this is risky, bc the empty array and null case are handled together
|
||||
}
|
||||
|
||||
if (!$arg) {
|
||||
// this is risky, bc the empty array and null case are handled together
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Why this is bad
|
||||
|
||||
The truthy/falsy type of one variable is often forgotten and not handled explicitly causing hard to track down errors.
|
||||
|
||||
## How to fix
|
||||
|
||||
Explicitly validate the variable with strict comparison.
|
1662
psalm-baseline.xml
1662
psalm-baseline.xml
File diff suppressed because it is too large
Load Diff
@ -17,8 +17,10 @@ use Psalm\Internal\Scope\IfScope;
|
||||
use Psalm\Issue\DocblockTypeContradiction;
|
||||
use Psalm\Issue\RedundantCondition;
|
||||
use Psalm\Issue\RedundantConditionGivenDocblockType;
|
||||
use Psalm\Issue\RiskyTruthyFalsyComparison;
|
||||
use Psalm\Issue\TypeDoesNotContainType;
|
||||
use Psalm\IssueBuffer;
|
||||
use Psalm\Type\Atomic\TBool;
|
||||
use Psalm\Type\Reconciler;
|
||||
|
||||
use function array_diff_key;
|
||||
@ -368,6 +370,34 @@ final class IfConditionalAnalyzer
|
||||
$statements_analyzer->getSuppressedIssues(),
|
||||
);
|
||||
}
|
||||
} elseif (!($stmt instanceof PhpParser\Node\Expr\BinaryOp\NotIdentical)
|
||||
&& !($stmt instanceof PhpParser\Node\Expr\BinaryOp\Identical)
|
||||
&& !($stmt instanceof PhpParser\Node\Expr\BooleanNot)) {
|
||||
if (count($type->getAtomicTypes()) > 1) {
|
||||
$both_types = $type->getBuilder();
|
||||
foreach ($both_types->getAtomicTypes() as $key => $atomic_type) {
|
||||
if ($atomic_type->isTruthy()
|
||||
|| $atomic_type->isFalsy()
|
||||
|| $atomic_type instanceof TBool) {
|
||||
$both_types->removeType($key);
|
||||
}
|
||||
}
|
||||
|
||||
if (count($both_types->getAtomicTypes()) > 0) {
|
||||
$both_types = $both_types->freeze();
|
||||
IssueBuffer::maybeAdd(
|
||||
new RiskyTruthyFalsyComparison(
|
||||
'Operand of type ' . $type->getId() . ' contains ' .
|
||||
'type' . (count($both_types->getAtomicTypes()) > 1 ? 's' : '') . ' ' .
|
||||
$both_types->getId() . ', which can be falsy and truthy. ' .
|
||||
'This can cause possibly unexpected behavior. Use strict comparison instead.',
|
||||
new CodeLocation($statements_analyzer, $stmt),
|
||||
$type->getId(),
|
||||
),
|
||||
$statements_analyzer->getSuppressedIssues(),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,15 +5,20 @@ declare(strict_types=1);
|
||||
namespace Psalm\Internal\Analyzer\Statements\Expression;
|
||||
|
||||
use PhpParser;
|
||||
use Psalm\CodeLocation;
|
||||
use Psalm\Context;
|
||||
use Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer;
|
||||
use Psalm\Internal\Analyzer\StatementsAnalyzer;
|
||||
use Psalm\Issue\RiskyTruthyFalsyComparison;
|
||||
use Psalm\IssueBuffer;
|
||||
use Psalm\Type;
|
||||
use Psalm\Type\Atomic\TBool;
|
||||
use Psalm\Type\Atomic\TFalse;
|
||||
use Psalm\Type\Atomic\TTrue;
|
||||
use Psalm\Type\Union;
|
||||
|
||||
use function count;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
@ -42,6 +47,32 @@ final class BooleanNotAnalyzer
|
||||
} elseif ($expr_type->isAlwaysFalsy()) {
|
||||
$stmt_type = new TTrue($expr_type->from_docblock);
|
||||
} else {
|
||||
if (count($expr_type->getAtomicTypes()) > 1) {
|
||||
$both_types = $expr_type->getBuilder();
|
||||
foreach ($both_types->getAtomicTypes() as $key => $atomic_type) {
|
||||
if ($atomic_type->isTruthy()
|
||||
|| $atomic_type->isFalsy()
|
||||
|| $atomic_type instanceof TBool) {
|
||||
$both_types->removeType($key);
|
||||
}
|
||||
}
|
||||
|
||||
if (count($both_types->getAtomicTypes()) > 0) {
|
||||
$both_types = $both_types->freeze();
|
||||
IssueBuffer::maybeAdd(
|
||||
new RiskyTruthyFalsyComparison(
|
||||
'Operand of type ' . $expr_type->getId() . ' contains ' .
|
||||
'type' . (count($both_types->getAtomicTypes()) > 1 ? 's' : '') . ' ' .
|
||||
$both_types->getId() . ', which can be falsy and truthy. ' .
|
||||
'This can cause possibly unexpected behavior. Use strict comparison instead.',
|
||||
new CodeLocation($statements_analyzer, $stmt),
|
||||
$expr_type->getId(),
|
||||
),
|
||||
$statements_analyzer->getSuppressedIssues(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$stmt_type = new TBool();
|
||||
}
|
||||
|
||||
|
@ -10,8 +10,15 @@ use Psalm\Context;
|
||||
use Psalm\Internal\Analyzer\StatementsAnalyzer;
|
||||
use Psalm\Issue\ForbiddenCode;
|
||||
use Psalm\Issue\InvalidArgument;
|
||||
use Psalm\Issue\RiskyTruthyFalsyComparison;
|
||||
use Psalm\IssueBuffer;
|
||||
use Psalm\Type;
|
||||
use Psalm\Type\Atomic\TBool;
|
||||
use Psalm\Type\Atomic\TFalse;
|
||||
use Psalm\Type\Atomic\TTrue;
|
||||
use Psalm\Type\Union;
|
||||
|
||||
use function count;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
@ -37,10 +44,12 @@ final class EmptyAnalyzer
|
||||
);
|
||||
}
|
||||
|
||||
if (($stmt_expr_type = $statements_analyzer->node_data->getType($stmt->expr))
|
||||
&& $stmt_expr_type->hasBool()
|
||||
&& $stmt_expr_type->isSingle()
|
||||
&& !$stmt_expr_type->from_docblock
|
||||
$expr_type = $statements_analyzer->node_data->getType($stmt->expr);
|
||||
|
||||
if ($expr_type) {
|
||||
if ($expr_type->hasBool()
|
||||
&& $expr_type->isSingle()
|
||||
&& !$expr_type->from_docblock
|
||||
) {
|
||||
IssueBuffer::maybeAdd(
|
||||
new InvalidArgument(
|
||||
@ -52,6 +61,47 @@ final class EmptyAnalyzer
|
||||
);
|
||||
}
|
||||
|
||||
$statements_analyzer->node_data->setType($stmt, Type::getBool());
|
||||
if ($expr_type->isAlwaysTruthy() && $expr_type->possibly_undefined === false) {
|
||||
$stmt_type = new TFalse($expr_type->from_docblock);
|
||||
} elseif ($expr_type->isAlwaysFalsy()) {
|
||||
$stmt_type = new TTrue($expr_type->from_docblock);
|
||||
} else {
|
||||
if (count($expr_type->getAtomicTypes()) > 1) {
|
||||
$both_types = $expr_type->getBuilder();
|
||||
foreach ($both_types->getAtomicTypes() as $key => $atomic_type) {
|
||||
if ($atomic_type->isTruthy()
|
||||
|| $atomic_type->isFalsy()
|
||||
|| $atomic_type instanceof TBool) {
|
||||
$both_types->removeType($key);
|
||||
}
|
||||
}
|
||||
|
||||
if (count($both_types->getAtomicTypes()) > 0) {
|
||||
$both_types = $both_types->freeze();
|
||||
IssueBuffer::maybeAdd(
|
||||
new RiskyTruthyFalsyComparison(
|
||||
'Operand of type ' . $expr_type->getId() . ' contains ' .
|
||||
'type' . (count($both_types->getAtomicTypes()) > 1 ? 's' : '') . ' ' .
|
||||
$both_types->getId() . ', which can be falsy and truthy. ' .
|
||||
'This can cause possibly unexpected behavior. Use strict comparison instead.',
|
||||
new CodeLocation($statements_analyzer, $stmt),
|
||||
$expr_type->getId(),
|
||||
),
|
||||
$statements_analyzer->getSuppressedIssues(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$stmt_type = new TBool();
|
||||
}
|
||||
|
||||
$stmt_type = new Union([$stmt_type], [
|
||||
'parent_nodes' => $expr_type->parent_nodes,
|
||||
]);
|
||||
} else {
|
||||
$stmt_type = Type::getBool();
|
||||
}
|
||||
|
||||
$statements_analyzer->node_data->setType($stmt, $stmt_type);
|
||||
}
|
||||
}
|
||||
|
@ -314,14 +314,18 @@ final class ArrayFetchAnalyzer
|
||||
&& !$context->inside_unset
|
||||
&& ($stmt_var_type && !$stmt_var_type->hasMixed())
|
||||
) {
|
||||
IssueBuffer::maybeAdd(
|
||||
if (IssueBuffer::accepts(
|
||||
new PossiblyUndefinedArrayOffset(
|
||||
'Possibly undefined array key ' . $keyed_array_var_id
|
||||
. ' on ' . $stmt_var_type->getId(),
|
||||
new CodeLocation($statements_analyzer->getSource(), $stmt),
|
||||
),
|
||||
$statements_analyzer->getSuppressedIssues(),
|
||||
);
|
||||
)) {
|
||||
$stmt_type = $stmt_type->getBuilder()->addType(new TNull())->freeze();
|
||||
}
|
||||
} elseif ($stmt_type->possibly_undefined) {
|
||||
$stmt_type = $stmt_type->getBuilder()->addType(new TNull())->freeze();
|
||||
}
|
||||
|
||||
$stmt_type = $stmt_type->setPossiblyUndefined(false);
|
||||
|
17
src/Psalm/Issue/RiskyTruthyFalsyComparison.php
Normal file
17
src/Psalm/Issue/RiskyTruthyFalsyComparison.php
Normal file
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace Psalm\Issue;
|
||||
|
||||
use Psalm\CodeLocation;
|
||||
|
||||
final class RiskyTruthyFalsyComparison extends CodeIssue
|
||||
{
|
||||
public const ERROR_LEVEL = 2;
|
||||
public const SHORTCODE = 356;
|
||||
|
||||
public function __construct(string $message, CodeLocation $code_location, ?string $dupe_key)
|
||||
{
|
||||
parent::__construct($message, $code_location);
|
||||
$this->dupe_key = $dupe_key;
|
||||
}
|
||||
}
|
@ -55,8 +55,8 @@ final class PluginFileExtensionsSocket implements FileExtensionsInterface
|
||||
1_622_727_271,
|
||||
);
|
||||
}
|
||||
if (!empty($this->config->getFiletypeScanners()[$fileExtension])
|
||||
|| !empty($this->additionalFileTypeScanners[$fileExtension])
|
||||
if (isset($this->config->getFiletypeScanners()[$fileExtension])
|
||||
|| isset($this->additionalFileTypeScanners[$fileExtension])
|
||||
) {
|
||||
throw new LogicException(
|
||||
sprintf('Cannot redeclare scanner for file-type %s', $fileExtension),
|
||||
@ -91,8 +91,8 @@ final class PluginFileExtensionsSocket implements FileExtensionsInterface
|
||||
1_622_727_281,
|
||||
);
|
||||
}
|
||||
if (!empty($this->config->getFiletypeAnalyzers()[$fileExtension])
|
||||
|| !empty($this->additionalFileTypeAnalyzers[$fileExtension])
|
||||
if (isset($this->config->getFiletypeAnalyzers()[$fileExtension])
|
||||
|| isset($this->additionalFileTypeAnalyzers[$fileExtension])
|
||||
) {
|
||||
throw new LogicException(
|
||||
sprintf('Cannot redeclare analyzer for file-type %s', $fileExtension),
|
||||
|
@ -656,6 +656,19 @@ class ArrayAccessTest extends TestCase
|
||||
'$x3===' => "array{b: 'value'}",
|
||||
],
|
||||
],
|
||||
'possiblyUndefinedArrayOffsetKeyedArray' => [
|
||||
'code' => '<?php
|
||||
$d = [];
|
||||
if (!rand(0,1)) {
|
||||
$d[0] = "a";
|
||||
}
|
||||
|
||||
$x = $d[0];',
|
||||
'assertions' => [
|
||||
'$x===' => '\'a\'',
|
||||
],
|
||||
'ignored_issues' => ['PossiblyUndefinedArrayOffset'],
|
||||
],
|
||||
'domNodeListAccessible' => [
|
||||
'code' => '<?php
|
||||
$doc = new DOMDocument();
|
||||
@ -680,7 +693,7 @@ class ArrayAccessTest extends TestCase
|
||||
'assertions' => [],
|
||||
'ignored_issues' => ['MixedArgument', 'MixedArrayOffset', 'MissingParamType'],
|
||||
],
|
||||
'suppressPossiblyUndefinedStringArrayOffet' => [
|
||||
'suppressPossiblyUndefinedStringArrayOffset' => [
|
||||
'code' => '<?php
|
||||
/** @var array{a?:string} */
|
||||
$entry = ["a"];
|
||||
@ -1338,7 +1351,7 @@ class ArrayAccessTest extends TestCase
|
||||
echo $a[new Foo];',
|
||||
'error_message' => 'InvalidArrayOffset',
|
||||
],
|
||||
'possiblyUndefinedIntArrayOffet' => [
|
||||
'possiblyUndefinedIntArrayOffset' => [
|
||||
'code' => '<?php
|
||||
/** @var array{0?:string} */
|
||||
$entry = ["a"];
|
||||
@ -1346,7 +1359,7 @@ class ArrayAccessTest extends TestCase
|
||||
[$elt] = $entry;',
|
||||
'error_message' => 'PossiblyUndefinedArrayOffset',
|
||||
],
|
||||
'possiblyUndefinedStringArrayOffet' => [
|
||||
'possiblyUndefinedStringArrayOffset' => [
|
||||
'code' => '<?php
|
||||
/** @var array{a?:string} */
|
||||
$entry = ["a"];
|
||||
@ -1531,6 +1544,19 @@ class ArrayAccessTest extends TestCase
|
||||
avg(["a" => 0.5, "b" => 1.5, "c" => new Exception()]);',
|
||||
'error_message' => 'InvalidArgument',
|
||||
],
|
||||
'possiblyUndefinedArrayOffsetKeyedArray' => [
|
||||
'code' => '<?php
|
||||
$d = [];
|
||||
if (!rand(0,1)) {
|
||||
$d[0] = "a";
|
||||
}
|
||||
|
||||
$x = $d[0];
|
||||
|
||||
// should not report TypeDoesNotContainNull
|
||||
if ($x === null) {}',
|
||||
'error_message' => 'PossiblyUndefinedArrayOffset',
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@ -1939,7 +1939,7 @@ class FunctionCallTest extends TestCase
|
||||
'strposAllowDictionary' => [
|
||||
'code' => '<?php
|
||||
function sayHello(string $format): void {
|
||||
if (strpos("abcdefghijklmno", $format)) {}
|
||||
if (strpos("abcdefghijklmno", $format) !== false) {}
|
||||
}',
|
||||
],
|
||||
'curlInitIsResourceAllowedIn7x' => [
|
||||
@ -2140,7 +2140,7 @@ class FunctionCallTest extends TestCase
|
||||
'strposFirstParamAllowClassString' => [
|
||||
'code' => '<?php
|
||||
function sayHello(string $needle): void {
|
||||
if (strpos(DateTime::class, $needle)) {}
|
||||
if (strpos(DateTime::class, $needle) !== false) {}
|
||||
}',
|
||||
],
|
||||
'mb_strtolowerProducesStringWithSecondArgument' => [
|
||||
|
@ -302,7 +302,7 @@ class ImmutableAnnotationTest extends TestCase
|
||||
|
||||
$dto = new DTO("BOOM!");
|
||||
|
||||
if ($dto->getError()) {
|
||||
if ($dto->getError() !== null) {
|
||||
takesString($dto->getError());
|
||||
}',
|
||||
],
|
||||
|
@ -140,6 +140,7 @@ class JsonOutputTest extends TestCase
|
||||
],
|
||||
'singleIssueForTypeDifference' => [
|
||||
'code' => '<?php
|
||||
/** @psalm-suppress RiskyTruthyFalsyComparison */
|
||||
function fooFoo(?string $a, ?string $b): void {
|
||||
if ($a || $b) {
|
||||
if ($a || $b) {}
|
||||
@ -147,7 +148,7 @@ class JsonOutputTest extends TestCase
|
||||
}',
|
||||
'error_count' => 1,
|
||||
'message' => 'Operand of type non-falsy-string is always truthy',
|
||||
'line' => 4,
|
||||
'line' => 5,
|
||||
'error' => '$b',
|
||||
],
|
||||
];
|
||||
|
@ -247,7 +247,7 @@ class DoTest extends TestCase
|
||||
$c = null;
|
||||
|
||||
do {
|
||||
if (!$c) {
|
||||
if ($c === null || $c === "" || $c === "0") {
|
||||
foo($c);
|
||||
} else {
|
||||
bar($c);
|
||||
|
@ -157,7 +157,7 @@ class WhileTest extends TestCase
|
||||
}
|
||||
|
||||
while ($a = foo()) {
|
||||
if ($a->bar) {}
|
||||
if ($a->bar !== null) {}
|
||||
}',
|
||||
],
|
||||
'whileTrueWithBreak' => [
|
||||
@ -273,7 +273,7 @@ class WhileTest extends TestCase
|
||||
$c = null;
|
||||
|
||||
while (rand(0, 1)) {
|
||||
if (!$c) {
|
||||
if ($c === null || $c === "" || $c === "0") {
|
||||
foo($c);
|
||||
} else {
|
||||
bar($c);
|
||||
|
@ -151,7 +151,7 @@ class MethodCallTest extends TestCase
|
||||
|
||||
$obj = new SomeClass();
|
||||
|
||||
if ($obj->getInt()) {
|
||||
if ($obj->getInt() !== null) {
|
||||
printInt($obj->getInt());
|
||||
}',
|
||||
);
|
||||
@ -187,7 +187,7 @@ class MethodCallTest extends TestCase
|
||||
|
||||
$obj = new SomeClass();
|
||||
|
||||
if ($obj->getInt()) {
|
||||
if ($obj->getInt() !== null) {
|
||||
printInt($obj->getInt());
|
||||
}',
|
||||
);
|
||||
@ -938,7 +938,7 @@ class MethodCallTest extends TestCase
|
||||
|
||||
$a = new A();
|
||||
|
||||
if ($a->getA()) {
|
||||
if ($a->getA() !== null) {
|
||||
echo strlen($a->getA());
|
||||
}',
|
||||
],
|
||||
@ -1009,7 +1009,7 @@ class MethodCallTest extends TestCase
|
||||
|
||||
$obj = new SomeClass();
|
||||
|
||||
if ($obj->getInt()) {
|
||||
if ($obj->getInt() !== null) {
|
||||
printInt($obj->getInt());
|
||||
}',
|
||||
],
|
||||
@ -1033,7 +1033,7 @@ class MethodCallTest extends TestCase
|
||||
|
||||
$obj = new SomeClass();
|
||||
|
||||
if ($obj->getInt()) {
|
||||
if ($obj->getInt() !== null) {
|
||||
printInt($obj->getInt());
|
||||
}',
|
||||
],
|
||||
@ -1633,7 +1633,7 @@ class MethodCallTest extends TestCase
|
||||
}
|
||||
|
||||
function foo(A $a) : void {
|
||||
if ($a->getA()) {
|
||||
if ($a->getA() !== null) {
|
||||
echo strlen($a->getA());
|
||||
}
|
||||
}
|
||||
@ -1699,7 +1699,7 @@ class MethodCallTest extends TestCase
|
||||
|
||||
$obj = new SomeClass();
|
||||
|
||||
if ($obj->getInt()) {
|
||||
if ($obj->getInt() !== null) {
|
||||
printInt($obj->getInt());
|
||||
}',
|
||||
'error_message' => 'PossiblyNullArgument',
|
||||
|
@ -313,7 +313,7 @@ class MethodSignatureTest extends TestCase
|
||||
|
||||
class B extends A {
|
||||
public function foo(?string $s): string {
|
||||
return $s ?: "hello";
|
||||
return $s !== null ? $s : "hello";
|
||||
}
|
||||
}
|
||||
|
||||
@ -329,7 +329,7 @@ class MethodSignatureTest extends TestCase
|
||||
|
||||
class B extends A {
|
||||
public function foo(string $s = null): string {
|
||||
return $s ?: "hello";
|
||||
return $s !== null ? $s : "hello";
|
||||
}
|
||||
}
|
||||
|
||||
@ -1058,7 +1058,7 @@ class MethodSignatureTest extends TestCase
|
||||
'code' => '<?php
|
||||
class A {
|
||||
public function foo(?string $s): string {
|
||||
return $s ?: "hello";
|
||||
return $s !== null ? $s : "hello";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -185,7 +185,7 @@ class PropertyTypeTest extends TestCase
|
||||
}
|
||||
|
||||
function testX(X $x): void {
|
||||
if ($x->getX()) {
|
||||
if (is_int($x->getX())) {
|
||||
XCollector::modify();
|
||||
if ($x->getX() === null) {}
|
||||
}
|
||||
@ -223,7 +223,7 @@ class PropertyTypeTest extends TestCase
|
||||
}
|
||||
|
||||
function testX(X $x): void {
|
||||
if ($x->getX()) {
|
||||
if ($x->getX() !== null) {
|
||||
XCollector::modify();
|
||||
if ($x->getX() === null) {}
|
||||
}
|
||||
@ -257,7 +257,7 @@ class PropertyTypeTest extends TestCase
|
||||
}
|
||||
|
||||
function testX(X $x): void {
|
||||
if ($x->x) {
|
||||
if ($x->x !== null) {
|
||||
XCollector::modify();
|
||||
if ($x->x === null) {}
|
||||
}
|
||||
@ -688,6 +688,8 @@ class PropertyTypeTest extends TestCase
|
||||
}
|
||||
|
||||
echo substr($a->aa, 1);',
|
||||
'assertions' => [],
|
||||
'ignored_issues' => ['RiskyTruthyFalsyComparison'],
|
||||
],
|
||||
'nullableStaticPropertyWithIfCheck' => [
|
||||
'code' => '<?php
|
||||
|
@ -102,6 +102,8 @@ class ReturnTypeTest extends TestCase
|
||||
return $str;
|
||||
}
|
||||
}',
|
||||
'assertions' => [],
|
||||
'ignored_issues' => ['RiskyTruthyFalsyComparison'],
|
||||
],
|
||||
'returnTypeNotEmptyCheckInElseIf' => [
|
||||
'code' => '<?php
|
||||
@ -120,6 +122,8 @@ class ReturnTypeTest extends TestCase
|
||||
return $str;
|
||||
}
|
||||
}',
|
||||
'assertions' => [],
|
||||
'ignored_issues' => ['RiskyTruthyFalsyComparison'],
|
||||
],
|
||||
'returnTypeNotEmptyCheckInElse' => [
|
||||
'code' => '<?php
|
||||
@ -138,6 +142,8 @@ class ReturnTypeTest extends TestCase
|
||||
return $str;
|
||||
}
|
||||
}',
|
||||
'assertions' => [],
|
||||
'ignored_issues' => ['RiskyTruthyFalsyComparison'],
|
||||
],
|
||||
'returnTypeAfterIf' => [
|
||||
'code' => '<?php
|
||||
|
@ -549,7 +549,7 @@ class SwitchTypeTest extends TestCase
|
||||
return "float";
|
||||
}
|
||||
|
||||
if ($fq_const_name && isset($predefined_constants[$fq_const_name])) {
|
||||
if ($fq_const_name !== null && isset($predefined_constants[$fq_const_name])) {
|
||||
return "mixed";
|
||||
}
|
||||
|
||||
|
@ -2880,6 +2880,8 @@ class ClassTemplateTest extends TestCase
|
||||
): void {
|
||||
}
|
||||
}',
|
||||
'assertions' => [],
|
||||
'ignored_issues' => ['RiskyTruthyFalsyComparison'],
|
||||
],
|
||||
'noCrashTemplateInsideGenerator' => [
|
||||
'code' => '<?php
|
||||
|
@ -299,6 +299,8 @@ class AssignmentInConditionalTest extends TestCase
|
||||
|
||||
return $pos;
|
||||
}',
|
||||
'assertions' => [],
|
||||
'ignored_issues' => ['RiskyTruthyFalsyComparison'],
|
||||
],
|
||||
'assignmentInIf' => [
|
||||
'code' => '<?php
|
||||
@ -417,7 +419,7 @@ class AssignmentInConditionalTest extends TestCase
|
||||
}
|
||||
|
||||
if (rand(0, 10) > 5) {
|
||||
} elseif (($a = rand(0, 1) ? new A : null) && $a->foo) {}',
|
||||
} elseif (($a = rand(0, 1) ? new A : null) && is_string($a->foo)) {}',
|
||||
],
|
||||
'noParadoxAfterConditionalAssignment' => [
|
||||
'code' => '<?php
|
||||
@ -486,7 +488,7 @@ class AssignmentInConditionalTest extends TestCase
|
||||
return "b";
|
||||
}',
|
||||
'error_message' => 'InvalidReturnStatement',
|
||||
'ignored_issues' => [],
|
||||
'ignored_issues' => ['RiskyTruthyFalsyComparison'],
|
||||
'php_version' => '8.0',
|
||||
],
|
||||
'assignmentInBranchOfAndReferencedAfterIf' => [
|
||||
|
@ -40,6 +40,32 @@ class ConditionalTest extends TestCase
|
||||
if ($b === $a) { }
|
||||
}',
|
||||
],
|
||||
'nonStrictConditionTruthyFalsyNoOverlap' => [
|
||||
'code' => '<?php
|
||||
/**
|
||||
* @param non-empty-array|null $arg
|
||||
* @return void
|
||||
*/
|
||||
function foo($arg) {
|
||||
if ($arg) {
|
||||
}
|
||||
|
||||
if (!$arg) {
|
||||
}
|
||||
|
||||
if (bar($arg)) {
|
||||
}
|
||||
|
||||
if (!bar($arg)) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $arg
|
||||
* @return non-empty-array|null
|
||||
*/
|
||||
function bar($arg) {}',
|
||||
],
|
||||
'typeResolutionFromDocblock' => [
|
||||
'code' => '<?php
|
||||
class A { }
|
||||
@ -570,6 +596,8 @@ class ConditionalTest extends TestCase
|
||||
}
|
||||
return false;
|
||||
}',
|
||||
'assertions' => [],
|
||||
'ignored_issues' => ['RiskyTruthyFalsyComparison'],
|
||||
],
|
||||
'numericStringAssertion' => [
|
||||
'code' => '<?php
|
||||
@ -1142,11 +1170,19 @@ class ConditionalTest extends TestCase
|
||||
],
|
||||
'notEmptyCheckOnMixedInTernary' => [
|
||||
'code' => '<?php
|
||||
$a = !empty($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] !== "off" ? true : false;',
|
||||
/** @psalm-suppress InvalidReturnType */
|
||||
function foo(): array {}
|
||||
|
||||
$b = foo();
|
||||
$a = !empty($b["hello"]) && $b["hello"] !== "off" ? true : false;',
|
||||
],
|
||||
'notEmptyCheckOnMixedInIf' => [
|
||||
'code' => '<?php
|
||||
if (!empty($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] !== "off") {
|
||||
/** @psalm-suppress InvalidReturnType */
|
||||
function foo(): array {}
|
||||
|
||||
$b = foo();
|
||||
if (!empty($b["hello"]) && $b["hello"] !== "off") {
|
||||
$a = true;
|
||||
} else {
|
||||
$a = false;
|
||||
@ -1918,6 +1954,8 @@ class ConditionalTest extends TestCase
|
||||
if ($a && strlen($a) > 5) {}
|
||||
}
|
||||
}',
|
||||
'assertions' => [],
|
||||
'ignored_issues' => ['RiskyTruthyFalsyComparison'],
|
||||
],
|
||||
'arrayUnionTypeSwitching' => [
|
||||
'code' => '<?php
|
||||
@ -1933,6 +1971,8 @@ class ConditionalTest extends TestCase
|
||||
|
||||
}
|
||||
}',
|
||||
'assertions' => [],
|
||||
'ignored_issues' => ['RiskyTruthyFalsyComparison'],
|
||||
],
|
||||
'propertySetOnElementInConditional' => [
|
||||
'code' => '<?php
|
||||
@ -2140,6 +2180,8 @@ class ConditionalTest extends TestCase
|
||||
echo $valuePath;
|
||||
}
|
||||
}',
|
||||
'assertions' => [],
|
||||
'ignored_issues' => ['RiskyTruthyFalsyComparison'],
|
||||
],
|
||||
'issetAssertionOnStaticProperty' => [
|
||||
'code' => '<?php
|
||||
@ -2483,6 +2525,8 @@ class ConditionalTest extends TestCase
|
||||
|
||||
return [$type];
|
||||
}',
|
||||
'assertions' => [],
|
||||
'ignored_issues' => ['RiskyTruthyFalsyComparison'],
|
||||
],
|
||||
'nonEmptyStringAfterLiteralCheck' => [
|
||||
'code' => '<?php
|
||||
@ -3492,6 +3536,66 @@ class ConditionalTest extends TestCase
|
||||
',
|
||||
'error_message' => 'TypeDoesNotContainType',
|
||||
],
|
||||
'nonStrictConditionTruthyFalsy' => [
|
||||
'code' => '<?php
|
||||
/**
|
||||
* @param array|null $arg
|
||||
* @return void
|
||||
*/
|
||||
function foo($arg) {
|
||||
if ($arg) {
|
||||
}
|
||||
}',
|
||||
'error_message' => 'RiskyTruthyFalsyComparison',
|
||||
],
|
||||
'nonStrictConditionTruthyFalsyNegated' => [
|
||||
'code' => '<?php
|
||||
/**
|
||||
* @param array|null $arg
|
||||
* @return void
|
||||
*/
|
||||
function foo($arg) {
|
||||
if (!$arg) {
|
||||
}
|
||||
}',
|
||||
'error_message' => 'RiskyTruthyFalsyComparison',
|
||||
],
|
||||
'nonStrictConditionTruthyFalsyFuncCall' => [
|
||||
'code' => '<?php
|
||||
/**
|
||||
* @param array|null $arg
|
||||
* @return void
|
||||
*/
|
||||
function foo($arg) {
|
||||
if (bar($arg)) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $arg
|
||||
* @return array|null
|
||||
*/
|
||||
function bar($arg) {}',
|
||||
'error_message' => 'RiskyTruthyFalsyComparison',
|
||||
],
|
||||
'nonStrictConditionTruthyFalsyFuncCallNegated' => [
|
||||
'code' => '<?php
|
||||
/**
|
||||
* @param array|null $arg
|
||||
* @return void
|
||||
*/
|
||||
function foo($arg) {
|
||||
if (!bar($arg)) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $arg
|
||||
* @return array|null
|
||||
*/
|
||||
function bar($arg) {}',
|
||||
'error_message' => 'RiskyTruthyFalsyComparison',
|
||||
],
|
||||
'redundantConditionForNonEmptyString' => [
|
||||
'code' => '<?php
|
||||
|
||||
|
@ -116,6 +116,8 @@ class EmptyTest extends TestCase
|
||||
|
||||
return "an exception";
|
||||
}',
|
||||
'assertions' => [],
|
||||
'ignored_issues' => ['RiskyTruthyFalsyComparison'],
|
||||
],
|
||||
'emptyExceptionReconciliationAfterIf' => [
|
||||
'code' => '<?php
|
||||
@ -177,6 +179,8 @@ class EmptyTest extends TestCase
|
||||
foreach ($arr as $item) {
|
||||
if (empty($item["hide"]) || $item["hide"] === 3) {}
|
||||
}',
|
||||
'assertions' => [],
|
||||
'ignored_issues' => ['RiskyTruthyFalsyComparison'],
|
||||
],
|
||||
'alwaysBoolResult' => [
|
||||
'code' => '<?php
|
||||
@ -221,7 +225,7 @@ class EmptyTest extends TestCase
|
||||
if (empty($scopes)){}
|
||||
}',
|
||||
'assertions' => [],
|
||||
'ignored_issues' => ['MixedAssignment', 'MissingParamType', 'MixedArgument'],
|
||||
'ignored_issues' => ['MixedAssignment', 'MissingParamType', 'MixedArgument', 'RiskyTruthyFalsyComparison'],
|
||||
],
|
||||
'multipleEmptiesInCondition' => [
|
||||
'code' => '<?php
|
||||
@ -391,6 +395,8 @@ class EmptyTest extends TestCase
|
||||
|
||||
echo $arr["a"];
|
||||
}',
|
||||
'assertions' => [],
|
||||
'ignored_issues' => ['RiskyTruthyFalsyComparison'],
|
||||
],
|
||||
'reconcileEmptyTwiceWithoutReturn' => [
|
||||
'code' => '<?php
|
||||
@ -614,6 +620,14 @@ class EmptyTest extends TestCase
|
||||
'$GLOBALS[\'sql_query\']===' => 'string',
|
||||
],
|
||||
],
|
||||
'emptyLiteralTrueFalse' => [
|
||||
'code' => '<?php
|
||||
$b = "asdf";
|
||||
$x = !empty($b);',
|
||||
'assertions' => [
|
||||
'$x===' => 'true',
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
@ -722,6 +736,30 @@ class EmptyTest extends TestCase
|
||||
}',
|
||||
'error_message' => 'LessSpecificReturnStatement',
|
||||
],
|
||||
'impossibleEmptyOnFalsyFunctionCall' => [
|
||||
'code' => '<?php
|
||||
/** @return false|null */
|
||||
function bar() {
|
||||
return rand(0, 5) ? null : false;
|
||||
}
|
||||
|
||||
if (!empty(bar())) {
|
||||
echo "abc";
|
||||
}',
|
||||
'error_message' => 'DocblockTypeContradiction',
|
||||
],
|
||||
'redundantEmptyOnFalsyFunctionCall' => [
|
||||
'code' => '<?php
|
||||
/** @return false|null */
|
||||
function bar() {
|
||||
return rand(0, 5) ? null : false;
|
||||
}
|
||||
|
||||
if (empty(bar())) {
|
||||
echo "abc";
|
||||
}',
|
||||
'error_message' => 'RedundantConditionGivenDocblockType',
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@ -411,7 +411,7 @@ class IssetTest extends TestCase
|
||||
$a = isset($_GET["a"]) ? $_GET["a"] : "";
|
||||
if ($a) {}',
|
||||
'assertions' => [],
|
||||
'ignored_issues' => ['MixedAssignment', 'MixedArrayAccess'],
|
||||
'ignored_issues' => ['MixedAssignment', 'MixedArrayAccess', 'RiskyTruthyFalsyComparison'],
|
||||
],
|
||||
'mixedArrayIssetGetStringVar' => [
|
||||
'code' => '<?php
|
||||
|
@ -68,6 +68,10 @@ class RedundantConditionTest extends TestCase
|
||||
}
|
||||
return $x;
|
||||
}',
|
||||
'assertions' => [],
|
||||
'ignored_issues' => [
|
||||
'RiskyTruthyFalsyComparison',
|
||||
],
|
||||
],
|
||||
'noRedundantConditionAfterAssignment' => [
|
||||
'code' => '<?php
|
||||
@ -101,7 +105,7 @@ class RedundantConditionTest extends TestCase
|
||||
|
||||
switch (get_class($i)) {
|
||||
case A::class:
|
||||
if ($i->foo) {}
|
||||
if ($i->foo !== null) {}
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -182,7 +186,7 @@ class RedundantConditionTest extends TestCase
|
||||
}
|
||||
if ($a) {}',
|
||||
'assertions' => [],
|
||||
'ignored_issues' => ['MixedAssignment', 'MixedArrayAccess'],
|
||||
'ignored_issues' => ['MixedAssignment', 'MixedArrayAccess', 'RiskyTruthyFalsyComparison'],
|
||||
],
|
||||
'noComplaintWithIsNumericThenIsEmpty' => [
|
||||
'code' => '<?php
|
||||
@ -379,7 +383,7 @@ class RedundantConditionTest extends TestCase
|
||||
/** @psalm-suppress PossiblyUndefinedGlobalVariable */
|
||||
$option = $options["option"] ?? false;
|
||||
|
||||
if ($option) {}',
|
||||
if ($option !== false) {}',
|
||||
'assertions' => [],
|
||||
'ignored_issues' => ['MixedAssignment', 'MixedArrayAccess'],
|
||||
],
|
||||
@ -599,7 +603,7 @@ class RedundantConditionTest extends TestCase
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($i) {}',
|
||||
if ($i !== array() && $i !== "" && $i !== "0") {}',
|
||||
],
|
||||
'emptyWithoutKnowingArrayType' => [
|
||||
'code' => '<?php
|
||||
@ -885,7 +889,7 @@ class RedundantConditionTest extends TestCase
|
||||
'code' => '<?php
|
||||
function test(string|int|float|bool $value): bool {
|
||||
if (is_numeric($value) || $value === true) {
|
||||
if ($value) {
|
||||
if ($value === true || (int) $value !== 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -1128,6 +1132,7 @@ class RedundantConditionTest extends TestCase
|
||||
return $a;
|
||||
}',
|
||||
'error_message' => 'RedundantCondition',
|
||||
'ignored_issues' => ['RiskyTruthyFalsyComparison'],
|
||||
],
|
||||
'refineTypeInMethodCall' => [
|
||||
'code' => '<?php
|
||||
|
@ -55,6 +55,8 @@ class TypeAlgebraTest extends TestCase
|
||||
if (!$a) return $b;
|
||||
return $a;
|
||||
}',
|
||||
'assertions' => [],
|
||||
'ignored_issues' => ['RiskyTruthyFalsyComparison'],
|
||||
],
|
||||
'twoVarLogicNotNestedWithAllPathsReturning' => [
|
||||
'code' => '<?php
|
||||
@ -69,6 +71,8 @@ class TypeAlgebraTest extends TestCase
|
||||
}
|
||||
}
|
||||
}',
|
||||
'assertions' => [],
|
||||
'ignored_issues' => ['RiskyTruthyFalsyComparison'],
|
||||
],
|
||||
'twoVarLogicNotNestedWithAssignmentBeforeReturn' => [
|
||||
'code' => '<?php
|
||||
@ -85,6 +89,8 @@ class TypeAlgebraTest extends TestCase
|
||||
|
||||
return $a;
|
||||
}',
|
||||
'assertions' => [],
|
||||
'ignored_issues' => ['RiskyTruthyFalsyComparison'],
|
||||
],
|
||||
'invertedTwoVarLogicNotNested' => [
|
||||
'code' => '<?php
|
||||
@ -98,6 +104,8 @@ class TypeAlgebraTest extends TestCase
|
||||
if (!$a) return $b;
|
||||
return $a;
|
||||
}',
|
||||
'assertions' => [],
|
||||
'ignored_issues' => ['RiskyTruthyFalsyComparison'],
|
||||
],
|
||||
'invertedTwoVarLogicNotNestedWithAssignmentBeforeReturn' => [
|
||||
'code' => '<?php
|
||||
@ -112,6 +120,8 @@ class TypeAlgebraTest extends TestCase
|
||||
if (!$a) return $b;
|
||||
return $a;
|
||||
}',
|
||||
'assertions' => [],
|
||||
'ignored_issues' => ['RiskyTruthyFalsyComparison'],
|
||||
],
|
||||
'twoVarLogicNotNestedWithElseifAndNoNegations' => [
|
||||
'code' => '<?php
|
||||
@ -127,6 +137,8 @@ class TypeAlgebraTest extends TestCase
|
||||
if (!$a) return $b;
|
||||
return $a;
|
||||
}',
|
||||
'assertions' => [],
|
||||
'ignored_issues' => ['RiskyTruthyFalsyComparison'],
|
||||
],
|
||||
'threeVarLogicNotNestedWithNoRedefinitionsWithClasses' => [
|
||||
'code' => '<?php
|
||||
@ -165,6 +177,8 @@ class TypeAlgebraTest extends TestCase
|
||||
if (!$a) return $b;
|
||||
return $a;
|
||||
}',
|
||||
'assertions' => [],
|
||||
'ignored_issues' => ['RiskyTruthyFalsyComparison'],
|
||||
],
|
||||
'threeVarLogicNotNestedAndOrWithNoRedefinitions' => [
|
||||
'code' => '<?php
|
||||
@ -181,6 +195,8 @@ class TypeAlgebraTest extends TestCase
|
||||
if (!$a) return $b;
|
||||
return $a;
|
||||
}',
|
||||
'assertions' => [],
|
||||
'ignored_issues' => ['RiskyTruthyFalsyComparison'],
|
||||
],
|
||||
'twoVarLogicNotNestedWithElseifCorrectlyNegatedInElseIf' => [
|
||||
'code' => '<?php
|
||||
@ -417,6 +433,8 @@ class TypeAlgebraTest extends TestCase
|
||||
}
|
||||
return $arr;
|
||||
}',
|
||||
'assertions' => [],
|
||||
'ignored_issues' => ['RiskyTruthyFalsyComparison'],
|
||||
],
|
||||
'lotsaTruthyStatements' => [
|
||||
'code' => '<?php
|
||||
@ -999,6 +1017,8 @@ class TypeAlgebraTest extends TestCase
|
||||
|
||||
return $b;
|
||||
}',
|
||||
'assertions' => [],
|
||||
'ignored_issues' => ['RiskyTruthyFalsyComparison'],
|
||||
],
|
||||
'cancelOutDifferentStatement' => [
|
||||
'code' => '<?php
|
||||
@ -1013,6 +1033,8 @@ class TypeAlgebraTest extends TestCase
|
||||
|
||||
return $b;
|
||||
}',
|
||||
'assertions' => [],
|
||||
'ignored_issues' => ['RiskyTruthyFalsyComparison'],
|
||||
],
|
||||
'moreChecks' => [
|
||||
'code' => '<?php
|
||||
@ -1187,6 +1209,8 @@ class TypeAlgebraTest extends TestCase
|
||||
|
||||
if ($foo === null) {}
|
||||
}',
|
||||
'assertions' => [],
|
||||
'ignored_issues' => ['RiskyTruthyFalsyComparison'],
|
||||
],
|
||||
'compareToIntInsideIfCNF' => [
|
||||
'code' => '<?php
|
||||
@ -1199,6 +1223,8 @@ class TypeAlgebraTest extends TestCase
|
||||
|
||||
if ($foo === null) {}
|
||||
}',
|
||||
'assertions' => [],
|
||||
'ignored_issues' => ['RiskyTruthyFalsyComparison'],
|
||||
],
|
||||
'ternaryAssertionOnBool' => [
|
||||
'code' => '<?php
|
||||
@ -1305,6 +1331,7 @@ class TypeAlgebraTest extends TestCase
|
||||
return $a;
|
||||
}',
|
||||
'error_message' => 'NullableReturnStatement',
|
||||
'ignored_issues' => ['RiskyTruthyFalsyComparison'],
|
||||
],
|
||||
'invertedTwoVarLogicNotNestedWithElseif' => [
|
||||
'code' => '<?php
|
||||
@ -1321,6 +1348,7 @@ class TypeAlgebraTest extends TestCase
|
||||
return $a;
|
||||
}',
|
||||
'error_message' => 'NullableReturnStatement',
|
||||
'ignored_issues' => ['RiskyTruthyFalsyComparison'],
|
||||
],
|
||||
'threeVarLogicWithElseifAndAnd' => [
|
||||
'code' => '<?php
|
||||
@ -1338,6 +1366,7 @@ class TypeAlgebraTest extends TestCase
|
||||
return $a;
|
||||
}',
|
||||
'error_message' => 'TypeDoesNotContainType',
|
||||
'ignored_issues' => ['RiskyTruthyFalsyComparison'],
|
||||
],
|
||||
'twoVarLogicNotNestedWithElseifIncorrectlyReinforcedInIf' => [
|
||||
'code' => '<?php
|
||||
@ -1354,6 +1383,7 @@ class TypeAlgebraTest extends TestCase
|
||||
return $a;
|
||||
}',
|
||||
'error_message' => 'RedundantCondition',
|
||||
'ignored_issues' => ['RiskyTruthyFalsyComparison'],
|
||||
],
|
||||
'repeatedIfStatements' => [
|
||||
'code' => '<?php
|
||||
@ -1368,6 +1398,7 @@ class TypeAlgebraTest extends TestCase
|
||||
}
|
||||
}',
|
||||
'error_message' => 'TypeDoesNotContainType',
|
||||
'ignored_issues' => ['RiskyTruthyFalsyComparison'],
|
||||
],
|
||||
'repeatedConditionals' => [
|
||||
'code' => '<?php
|
||||
@ -1460,6 +1491,7 @@ class TypeAlgebraTest extends TestCase
|
||||
}
|
||||
}',
|
||||
'error_message' => 'RedundantCondition',
|
||||
'ignored_issues' => ['RiskyTruthyFalsyComparison'],
|
||||
],
|
||||
'dependentTypeInvalidated' => [
|
||||
'code' => '<?php
|
||||
|
@ -104,7 +104,7 @@ class UnusedVariableTest extends TestCase
|
||||
function foo(array $arr) : void {
|
||||
$a = null;
|
||||
foreach ($arr as $a) { }
|
||||
if ($a) {}
|
||||
if ($a !== null) {}
|
||||
}',
|
||||
],
|
||||
'definedInSecondBranchOfCondition' => [
|
||||
@ -130,10 +130,10 @@ class UnusedVariableTest extends TestCase
|
||||
'dummyByRefVar' => [
|
||||
'code' => '<?php
|
||||
function foo(string &$a = null, string $b = null): void {
|
||||
if ($a) {
|
||||
if ($a !== null) {
|
||||
echo $a;
|
||||
}
|
||||
if ($b) {
|
||||
if ($b !== null) {
|
||||
echo $b;
|
||||
}
|
||||
}
|
||||
@ -329,7 +329,7 @@ class UnusedVariableTest extends TestCase
|
||||
echo $e->getMessage();
|
||||
}
|
||||
|
||||
if ($s) {}
|
||||
if ($s !== null) {}
|
||||
}',
|
||||
],
|
||||
'throwWithMessageCallAndAssignmentInCatchAndReference' => [
|
||||
@ -942,7 +942,7 @@ class UnusedVariableTest extends TestCase
|
||||
if ($foo) {}
|
||||
} catch (Exception $e) {}
|
||||
|
||||
if ($foo) {}',
|
||||
if ($foo !== false && $foo !== 0) {}',
|
||||
],
|
||||
'useTryAssignedVariableInsideFinally' => [
|
||||
'code' => '<?php
|
||||
@ -1954,7 +1954,7 @@ class UnusedVariableTest extends TestCase
|
||||
$arr = str_getcsv($value);
|
||||
|
||||
foreach ($arr as &$element) {
|
||||
$element = $element ?: "foo";
|
||||
$element = $element !== null ?: "foo";
|
||||
}
|
||||
|
||||
return $arr;
|
||||
@ -2338,7 +2338,7 @@ class UnusedVariableTest extends TestCase
|
||||
}
|
||||
}',
|
||||
'assertions' => [],
|
||||
'ignored_issues' => [],
|
||||
'ignored_issues' => ['RiskyTruthyFalsyComparison'],
|
||||
'php_version' => '8.0',
|
||||
],
|
||||
'concatWithUnknownProperty' => [
|
||||
@ -3166,7 +3166,7 @@ class UnusedVariableTest extends TestCase
|
||||
$user = $user_id;
|
||||
}
|
||||
|
||||
if ($user) {
|
||||
if ($user !== null && $user !== 0) {
|
||||
$a = 0;
|
||||
for ($i = 1; $i <= 10; $i++) {
|
||||
$a += $i;
|
||||
@ -3186,7 +3186,7 @@ class UnusedVariableTest extends TestCase
|
||||
$user = $user_id;
|
||||
}
|
||||
|
||||
if ($user) {
|
||||
if ($user !== null && $user !== 0) {
|
||||
$a = 0;
|
||||
foreach ([1, 2, 3] as $i) {
|
||||
$a += $i;
|
||||
|
Loading…
Reference in New Issue
Block a user