Skip to content

Commit 4a9202b

Browse files

18 files changed

+655
-0
lines changed

tests/PHPStan/Rules/Classes/ImpossibleInstanceOfRuleTest.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -536,6 +536,12 @@ public function testBug10036(): void
536536
]);
537537
}
538538

539+
public function testBug12267(): void
540+
{
541+
$this->treatPhpDocTypesAsCertain = true;
542+
$this->analyse([__DIR__ . '/data/bug-12267.php'], []);
543+
}
544+
539545
#[RequiresPhp('>= 8.0')]
540546
public function testNewIsAlwaysFinalClass(): void
541547
{
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<?php
2+
3+
namespace Bug12267b;
4+
5+
abstract class Model
6+
{
7+
}
8+
9+
class A11yAudit extends Model
10+
{
11+
}
12+
13+
class A11yPhase extends Model
14+
{
15+
}
16+
17+
/**
18+
* @template TModel of ?Model
19+
*/
20+
class Form
21+
{
22+
/** @var TModel */
23+
protected $model;
24+
}
25+
26+
trait ContainsA11yPhaseResultFields
27+
{
28+
/** @return list<string> */
29+
protected function getFileExistsHelpBlock(string $field): array
30+
{
31+
if (!($this->model instanceof A11yPhase)) {
32+
return [];
33+
}
34+
35+
return [];
36+
}
37+
}
38+
39+
/**
40+
* @extends Form<A11yPhase>
41+
*/
42+
class EditA11yPhaseForm extends Form
43+
{
44+
use ContainsA11yPhaseResultFields;
45+
}
46+
47+
/**
48+
* @extends Form<null>
49+
*/
50+
class SubmitA11yAuditPhaseForm extends Form
51+
{
52+
use ContainsA11yPhaseResultFields;
53+
}

tests/PHPStan/Rules/Comparison/BooleanNotConstantConditionRuleTest.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,12 @@ public function testBug5984(): void
236236
$this->analyse([__DIR__ . '/data/bug-5984.php'], []);
237237
}
238238

239+
public function testBug12267(): void
240+
{
241+
$this->treatPhpDocTypesAsCertain = true;
242+
$this->analyse([__DIR__ . '/data/bug-12267.php'], []);
243+
}
244+
239245
public function testBug6702(): void
240246
{
241247
$this->treatPhpDocTypesAsCertain = true;

tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeFunctionCallRuleTest.php

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1147,6 +1147,50 @@ public function testBug13628(): void
11471147
$this->analyse([__DIR__ . '/data/bug-13628.php'], []);
11481148
}
11491149

1150+
public function testBug13023(): void
1151+
{
1152+
$this->treatPhpDocTypesAsCertain = true;
1153+
$this->analyse([__DIR__ . '/data/bug-13023.php'], []);
1154+
}
1155+
1156+
public function testBug9095(): void
1157+
{
1158+
$this->treatPhpDocTypesAsCertain = true;
1159+
$this->analyse([__DIR__ . '/data/bug-9095.php'], []);
1160+
}
1161+
1162+
#[RequiresPhp('>= 8.1')]
1163+
public function testBug7599(): void
1164+
{
1165+
$this->treatPhpDocTypesAsCertain = true;
1166+
$this->analyse([__DIR__ . '/data/bug-7599.php'], []);
1167+
}
1168+
1169+
public function testBug13474(): void
1170+
{
1171+
$this->treatPhpDocTypesAsCertain = true;
1172+
$this->analyse([__DIR__ . '/data/bug-13474.php'], []);
1173+
}
1174+
1175+
public function testBug13687(): void
1176+
{
1177+
$this->treatPhpDocTypesAsCertain = true;
1178+
$this->analyse([__DIR__ . '/data/bug-13687.php'], []);
1179+
}
1180+
1181+
#[RequiresPhp('>= 8.1')]
1182+
public function testBug12798(): void
1183+
{
1184+
$this->treatPhpDocTypesAsCertain = true;
1185+
$this->analyse([__DIR__ . '/data/bug-12798.php'], []);
1186+
}
1187+
1188+
public function testBug4570(): void
1189+
{
1190+
$this->treatPhpDocTypesAsCertain = true;
1191+
$this->analyse([__DIR__ . '/data/bug-4570.php'], []);
1192+
}
1193+
11501194
public function testBug9666(): void
11511195
{
11521196
$tipText = 'Because the type is coming from a PHPDoc, you can turn off this check by setting <fg=cyan>treatPhpDocTypesAsCertain: false</> in your <fg=cyan>%configurationFile%</>.';

tests/PHPStan/Rules/Comparison/StrictComparisonOfDifferentTypesRuleTest.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1041,6 +1041,21 @@ public function testBug3761(): void
10411041
$this->analyse([__DIR__ . '/data/bug-3761.php'], []);
10421042
}
10431043

1044+
public function testBug8060(): void
1045+
{
1046+
$this->analyse([__DIR__ . '/data/bug-8060.php'], []);
1047+
}
1048+
1049+
public function testBug9515(): void
1050+
{
1051+
$this->analyse([__DIR__ . '/data/bug-9515.php'], []);
1052+
}
1053+
1054+
public function testBug4121(): void
1055+
{
1056+
$this->analyse([__DIR__ . '/data/bug-4121.php'], []);
1057+
}
1058+
10441059
public function testBug13208(): void
10451060
{
10461061
$this->analyse([__DIR__ . '/data/bug-13208.php'], []);

tests/PHPStan/Rules/Comparison/TernaryOperatorConstantConditionRuleTest.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,12 @@ public function testBug7580(): void
106106
$this->analyse([__DIR__ . '/data/bug-7580.php'], []);
107107
}
108108

109+
public function testBug11949(): void
110+
{
111+
$this->treatPhpDocTypesAsCertain = true;
112+
$this->analyse([__DIR__ . '/data/bug-11949.php'], []);
113+
}
114+
109115
public function testBug3370(): void
110116
{
111117
$this->treatPhpDocTypesAsCertain = true;
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<?php
2+
3+
namespace Bug11949;
4+
5+
function trans(string $key): string
6+
{
7+
return $key;
8+
}
9+
10+
trait EnumString
11+
{
12+
13+
/** @var array<string, string> */
14+
static protected ?array $_translatedValues;
15+
16+
static public function getValueIndex(string $value): int
17+
{
18+
return ($i = array_search($value, self::NAMES)) === false ? -1 : $i;
19+
}
20+
21+
/** @return array<string, string> */
22+
static public function getTranslatedValues(): array
23+
{
24+
return self::$_translatedValues ??= array_map(static::getTranslatedValue(...), array_combine(self::NAMES, self::NAMES));
25+
}
26+
27+
static public function getTranslatedValue(string $value): string
28+
{
29+
return self::TRANSLATION ? trans(self::TRANSLATION . $value) : $value;
30+
}
31+
32+
}
33+
34+
abstract class UserStatus
35+
{
36+
37+
use EnumString;
38+
39+
const ACTIVE = 'active';
40+
const PENDING = 'pending';
41+
const BLOCKED = 'blocked';
42+
43+
protected const NAMES = [
44+
self::ACTIVE,
45+
self::PENDING,
46+
self::BLOCKED,
47+
];
48+
49+
protected const TRANSLATION = 'users.statuses.';
50+
51+
}
52+
53+
abstract class SystemCheckStatus
54+
{
55+
56+
use EnumString;
57+
58+
const SUCCESS = 'success';
59+
const FAILURE = 'failure';
60+
61+
protected const NAMES = [
62+
self::SUCCESS,
63+
self::FAILURE,
64+
];
65+
66+
protected const TRANSLATION = '';
67+
68+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php
2+
3+
namespace Bug12267;
4+
5+
/**
6+
* @template TModel = mixed
7+
*/
8+
trait PrintSomething
9+
{
10+
/** @var TModel */
11+
protected $model;
12+
13+
public function printIt(): void
14+
{
15+
if (!$this->model) {
16+
return;
17+
}
18+
19+
echo $this->model;
20+
}
21+
}
22+
23+
class Class1
24+
{
25+
/** @use PrintSomething<null> */
26+
use PrintSomething;
27+
28+
public function what(): void
29+
{
30+
$this->printIt();
31+
}
32+
}
33+
34+
class Class2
35+
{
36+
/** @use PrintSomething<\Exception> */
37+
use PrintSomething;
38+
39+
public function what(): void
40+
{
41+
$this->printIt();
42+
}
43+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<?php // lint >= 8.1
2+
3+
declare(strict_types = 1);
4+
5+
namespace Bug12798;
6+
7+
interface Colorable
8+
{
9+
public function color(): string;
10+
}
11+
12+
trait HasColors
13+
{
14+
/** @return array<string|int, string> */
15+
public static function colors(): array
16+
{
17+
/** @phpstan-ignore return.type */
18+
return array_reduce(self::cases(), function (array $colors, self $case) {
19+
$key = is_subclass_of($case, \BackedEnum::class) ? $case->value : $case->name;
20+
$color = is_subclass_of($case, Colorable::class) ? $case->color() : 'gray';
21+
22+
$colors[$key] = $color;
23+
return $colors;
24+
}, []);
25+
}
26+
}
27+
28+
enum AlertLevelBacked: int implements Colorable
29+
{
30+
use HasColors;
31+
32+
case Low = 1;
33+
case Medium = 2;
34+
case Critical = 3;
35+
36+
public function color(): string
37+
{
38+
return match ($this) {
39+
self::Low => 'green',
40+
self::Medium => 'yellow',
41+
self::Critical => 'red',
42+
};
43+
}
44+
}
45+
46+
enum AlertLevel
47+
{
48+
use HasColors;
49+
50+
case Low;
51+
case Medium;
52+
case Critical;
53+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
namespace Bug13023;
4+
5+
class SomeClass
6+
{
7+
use MyTrait;
8+
}
9+
10+
class SomeClass2
11+
{
12+
use MyTrait;
13+
}
14+
15+
trait MyTrait
16+
{
17+
public function getRandom(): int
18+
{
19+
$value = random_int(1, 100);
20+
if (is_a($this, SomeClass::class)) {
21+
return $value * $value;
22+
}
23+
return $value;
24+
}
25+
}

0 commit comments

Comments
 (0)