Skip to content

Commit 75ca7d5

Browse files
committed
Cover EmptyRule
1 parent 4e1889b commit 75ca7d5

File tree

5 files changed

+85
-12
lines changed

5 files changed

+85
-12
lines changed

Diff for: src/Rules/IssetCheck.php

+9-6
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
use PHPStan\Rules\Properties\PropertyReflectionFinder;
1111
use PHPStan\Type\NeverType;
1212
use PHPStan\Type\Type;
13-
use PHPStan\Type\TypeCombinator;
1413
use PHPStan\Type\VerbosityLevel;
1514
use function is_string;
1615
use function sprintf;
@@ -150,16 +149,20 @@ public function check(Expr $expr, Scope $scope, string $operatorDescription, str
150149
&& $expr->name instanceof Node\Identifier
151150
&& $expr->var instanceof Expr\Variable
152151
&& $expr->var->name === 'this'
153-
&& !TypeCombinator::containsNull($propertyReflection->getNativeType())
152+
&& $propertyReflection->getNativeType()->isNull()->no()
154153
&& $scope->hasExpressionType(new PropertyInitializationExpr($propertyReflection->getName()))->yes()
155154
) {
156-
return RuleErrorBuilder::message(
155+
return $this->generateError(
156+
$propertyReflection->getNativeType(),
157157
sprintf(
158-
'%s cannot be null or uninitialized %s.',
158+
'%s %s',
159159
$this->propertyDescriptor->describeProperty($propertyReflection, $scope, $expr),
160160
$operatorDescription,
161161
),
162-
)->identifier(sprintf('%s.neverNullOrUninitialized', $identifier))->build();
162+
$typeMessageCallback,
163+
$identifier,
164+
'propertyNeverNullOrUninitialized',
165+
);
163166
}
164167

165168
if (!$scope->hasExpressionType($expr)->yes()) {
@@ -299,7 +302,7 @@ private function checkUndefined(Expr $expr, Scope $scope, string $operatorDescri
299302
/**
300303
* @param callable(Type): ?string $typeMessageCallback
301304
* @param ErrorIdentifier $identifier
302-
* @param 'variable'|'offset'|'property'|'expr' $identifierSecondPart
305+
* @param 'variable'|'offset'|'property'|'expr'|'propertyNeverNullOrUninitialized' $identifierSecondPart
303306
*/
304307
private function generateError(Type $type, string $message, callable $typeMessageCallback, string $identifier, string $identifierSecondPart): ?IdentifierRuleError
305308
{

Diff for: tests/PHPStan/Rules/Variables/EmptyRuleTest.php

+21
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@ protected function shouldTreatPhpDocTypesAsCertain(): bool
3232
return $this->treatPhpDocTypesAsCertain;
3333
}
3434

35+
public function shouldNarrowMethodScopeFromConstructor(): bool
36+
{
37+
return true;
38+
}
39+
3540
public function testRule(): void
3641
{
3742
$this->treatPhpDocTypesAsCertain = true;
@@ -206,4 +211,20 @@ public function testBug12658(): void
206211
$this->analyse([__DIR__ . '/data/bug-12658.php'], []);
207212
}
208213

214+
public function testIssetAfterRememberedConstructor(): void
215+
{
216+
$this->treatPhpDocTypesAsCertain = true;
217+
218+
$this->analyse([__DIR__ . '/data/isset-after-remembered-constructor.php'], [
219+
[
220+
'Property IssetOrCoalesceOnNonNullableInitializedProperty\MoreEmptyCases::$false in empty() is always falsy.',
221+
94,
222+
],
223+
[
224+
'Property IssetOrCoalesceOnNonNullableInitializedProperty\MoreEmptyCases::$true in empty() is not falsy.',
225+
96,
226+
],
227+
]);
228+
}
229+
209230
}

Diff for: tests/PHPStan/Rules/Variables/IssetRuleTest.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -491,7 +491,7 @@ public function testIssetAfterRememberedConstructor(): void
491491

492492
$this->analyse([__DIR__ . '/data/isset-after-remembered-constructor.php'], [
493493
[
494-
'Property IssetOrCoalesceOnNonNullableInitializedProperty\User::$string cannot be null or uninitialized in isset().',
494+
'Property IssetOrCoalesceOnNonNullableInitializedProperty\User::$string in isset() is not nullable.',
495495
36,
496496
],
497497
]);

Diff for: tests/PHPStan/Rules/Variables/NullCoalesceRuleTest.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,7 @@ public function testIssetAfterRememberedConstructor(): void
367367

368368
$this->analyse([__DIR__ . '/data/isset-after-remembered-constructor.php'], [
369369
[
370-
'Property IssetOrCoalesceOnNonNullableInitializedProperty\User::$string cannot be null or uninitialized on left side of ??.',
370+
'Property IssetOrCoalesceOnNonNullableInitializedProperty\User::$string on left side of ?? is not nullable.',
371371
48,
372372
],
373373
]);

Diff for: tests/PHPStan/Rules/Variables/data/isset-after-remembered-constructor.php

+53-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<?php // lint >= 7.4
1+
<?php // lint >= 8.2
22

33
namespace IssetOrCoalesceOnNonNullableInitializedProperty;
44

@@ -12,9 +12,9 @@ class User
1212

1313
private $untyped;
1414

15-
public function __construct(
16-
) {
17-
if (rand(0,1)) {
15+
public function __construct()
16+
{
17+
if (rand(0, 1)) {
1818
$this->nullableString = 'hello';
1919
$this->string = 'world';
2020
$this->maybeUninitializedString = 'something';
@@ -48,4 +48,53 @@ public function doBar(): void
4848
echo $this->string ?? 'default';
4949
echo $this->untyped ?? 'default';
5050
}
51+
52+
public function doFooBar(): void
53+
{
54+
if (empty($this->maybeUninitializedString)) {
55+
echo $this->maybeUninitializedString;
56+
}
57+
if (empty($this->nullableString)) {
58+
echo $this->nullableString;
59+
}
60+
if (empty($this->string)) {
61+
echo $this->string;
62+
}
63+
if (empty($this->untyped)) {
64+
echo $this->untyped;
65+
}
66+
}
67+
}
68+
69+
class MoreEmptyCases
70+
{
71+
private false|string $union;
72+
private false $false;
73+
private true $true;
74+
private bool $bool;
75+
76+
public function __construct()
77+
{
78+
if (rand(0, 1)) {
79+
$this->union = 'nope';
80+
$this->bool = true;
81+
} elseif (rand(10, 20)) {
82+
$this->union = false;
83+
$this->bool = false;
84+
}
85+
$this->false = false;
86+
$this->true = true;
87+
}
88+
89+
public function doFoo(): void
90+
{
91+
if (empty($this->union)) {
92+
}
93+
if (empty($this->bool)) {
94+
}
95+
if (empty($this->false)) {
96+
}
97+
if (empty($this->true)) {
98+
}
99+
}
51100
}

0 commit comments

Comments
 (0)