Skip to content

Commit b67c7a1

Browse files
committed
Update to PHPStan 2
1 parent 6686e27 commit b67c7a1

File tree

10 files changed

+43
-14
lines changed

10 files changed

+43
-14
lines changed

composer.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,11 @@
3737
"phpmd/phpmd": "^2.15",
3838
"phpstan/phpstan": "^1.12",
3939
"phpstan/phpstan-phpunit": "^1.4",
40+
"phpstan/phpstan": "^2.1",
41+
"phpstan/phpstan-phpunit": "^2.0",
4042
"phpunit/phpunit": "^10.5",
4143
"slevomat/coding-standard": "^8.15",
42-
"squizlabs/php_codesniffer": "^3.11 || ^4.0"
44+
"squizlabs/php_codesniffer": "^4.0"
4345
},
4446
"config": {
4547
"sort-packages": true,

src/InnerList.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44

55
namespace gapple\StructuredFields;
66

7+
/**
8+
* @method array<TupleInterface|list{mixed,object}> getValue()
9+
*/
710
class InnerList implements TupleInterface
811
{
912
use TupleTrait;

src/Item.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44

55
namespace gapple\StructuredFields;
66

7+
/**
8+
* @method mixed getValue()
9+
*/
710
class Item implements TupleInterface
811
{
912
use TupleTrait;

src/Serializer.php

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -39,27 +39,27 @@ public static function serializeItem(mixed $value, ?object $parameters = null):
3939
}
4040

4141
/**
42-
* @param iterable<TupleInterface|array{mixed, object}> $value
42+
* @param iterable<TupleInterface|list{TupleInterface|list{mixed, object}, object}> $value
4343
*/
4444
public static function serializeList(iterable $value): string
4545
{
4646
if ($value instanceof \Traversable) {
47-
// @todo Checking for Traversable is not required for PHP ^8.2.0.
4847
$value = iterator_to_array($value);
4948
}
5049

5150
$returnValue = array_map(function ($item) {
52-
if ($item instanceof TupleInterface) {
53-
$itemValue = $item->getValue();
54-
$itemParameters = $item->getParameters();
55-
} elseif (is_array($item) && count($item) === 2) {
51+
if (is_array($item) && count($item) === 2) {
5652
$itemValue = $item[0];
5753
$itemParameters = $item[1];
54+
} elseif ($item instanceof TupleInterface) {
55+
$itemValue = $item->getValue();
56+
$itemParameters = $item->getParameters();
5857
} else {
5958
throw new SerializeException("Invalid item in list");
6059
}
6160

6261
if (is_array($itemValue)) {
62+
/** @var array<TupleInterface|list{mixed, object}> $itemValue */
6363
return self::serializeInnerList($itemValue, $itemParameters);
6464
} else {
6565
return self::serializeItem($itemValue, $itemParameters);
@@ -73,8 +73,6 @@ public static function serializeList(iterable $value): string
7373
* Serialize an object as a dictionary.
7474
*
7575
* Either a Traversable object can be provided, or the public properties of the object will be extracted.
76-
*
77-
* @param Dictionary|object $value
7876
*/
7977
public static function serializeDictionary(object $value): string
8078
{
@@ -84,6 +82,10 @@ public static function serializeDictionary(object $value): string
8482
$value = get_object_vars($value);
8583
}
8684

85+
/**
86+
* @var string $key
87+
* @var TupleInterface|list{TupleInterface|list{mixed,object}, object} $item
88+
*/
8789
foreach ($value as $key => $item) {
8890
if (!empty($returnValue)) {
8991
$returnValue .= ', ';
@@ -102,6 +104,7 @@ public static function serializeDictionary(object $value): string
102104
if ($itemValue === true) {
103105
$returnValue .= self::serializeParameters($itemParameters);
104106
} elseif (is_array($itemValue)) {
107+
/** @var array<TupleInterface|list{mixed, object}> $itemValue */
105108
$returnValue .= '=' . self::serializeInnerList($itemValue, $itemParameters);
106109
} else {
107110
$returnValue .= '=' . self::serializeItem($itemValue, $itemParameters);
@@ -189,7 +192,7 @@ private static function serializeDecimal(float $value): string
189192

190193
// Casting to a string loses a digit on long numbers, but is preserved
191194
// by json_encode (e.g. 111111111111.111).
192-
/** @var string $result */
195+
/** @var non-empty-string $result */
193196
$result = json_encode(round($value, 3, PHP_ROUND_HALF_EVEN));
194197

195198
if (!str_contains($result, '.')) {
@@ -250,6 +253,7 @@ private static function serializeParameters(object $value): string
250253
$value = get_object_vars($value);
251254
}
252255

256+
/** @var string $key */
253257
foreach ($value as $key => $item) {
254258
$returnValue .= ';' . self::serializeKey($key);
255259

tests/Httpwg/HttpwgTestBase.php

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,15 @@
66
use gapple\Tests\StructuredFields\RulesetTestBase;
77
use gapple\Tests\StructuredFields\SerializingRulesetTrait;
88

9+
/**
10+
* @phpstan-import-type ExpectedItem from HttpwgRuleExpectedConverter
11+
* @phpstan-import-type ExpectedOuterList from HttpwgRuleExpectedConverter
12+
* @phpstan-import-type ExpectedDictionary from HttpwgRuleExpectedConverter
13+
* @phpstan-type RuleDefinition object{
14+
* header_type: 'item'|'list'|'dictionary',
15+
* expected: ExpectedItem|ExpectedOuterList|ExpectedDictionary
16+
* }
17+
*/
918
abstract class HttpwgTestBase extends RulesetTestBase
1019
{
1120
use SerializingRulesetTrait;
@@ -27,7 +36,7 @@ protected static function rulesetDataProvider(): array
2736
throw new \RuntimeException("Unable to read ruleset JSON file.");
2837
}
2938

30-
/** @var array<\stdClass>|null $rules */
39+
/** @var array<RuleDefinition&\stdClass>|null $rules */
3140
$rules = json_decode($rulesJson);
3241
if (is_null($rules) || json_last_error() !== JSON_ERROR_NONE) {
3342
throw new \RuntimeException("Unable to parse ruleset JSON file.");
@@ -38,8 +47,11 @@ protected static function rulesetDataProvider(): array
3847
if (isset($rawRule->expected)) {
3948
try {
4049
$rawRule->expected = match ($rawRule->header_type) {
50+
// @phpstan-ignore argument.type
4151
'item' => HttpwgRuleExpectedConverter::item($rawRule->expected),
52+
// @phpstan-ignore argument.type
4253
'list' => HttpwgRuleExpectedConverter::list($rawRule->expected),
54+
// @phpstan-ignore argument.type
4355
'dictionary' => HttpwgRuleExpectedConverter::dictionary($rawRule->expected),
4456
default => throw new \UnexpectedValueException('Unknown header type'),
4557
};

tests/ItemTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public function testArraySet(): void
4141
$item[0] = 'Modified Value';
4242
$item[1] = (object) ['paramKey' => 'Modified param value'];
4343
$this->assertEquals('Modified Value', $item[0]);
44-
$this->assertEquals('Modified param value', $item[1]->paramKey); // @phpstan-ignore-line
44+
$this->assertEquals('Modified param value', $item[1]->paramKey);
4545
}
4646

4747
public function testArrayIndexIsset(): void

tests/OuterListTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ public function testIteration(): void
8585
$this->assertIsIterable($list);
8686

8787
$iterated = 0;
88+
/** @var int $key */
8889
foreach ($list as $key => $value) {
8990
$this->assertEquals($listValues[$key], $value);
9091
$iterated++;

tests/ParsingRulesetTrait.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ public static function parseRulesetDataProvider(): array
2323
public function testParsing(Rule $record): void
2424
{
2525
try {
26+
if (is_null($record->raw)) {
27+
throw new \RuntimeException("Raw value not defined for parsing test");
28+
}
2629
$raw = implode(', ', $record->raw);
2730
$parsedValue = Parser::{'parse' . ucfirst($record->header_type)}($raw);
2831

tests/SerializeListTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,6 @@ public function testNestedInnerListObject(): void
140140

141141
$this->expectException(SerializeException::class);
142142
$this->expectExceptionMessage("Inner lists cannot be nested");
143-
Serializer::serializeList($list);
143+
Serializer::serializeList($list); // @phpstan-ignore argument.type
144144
}
145145
}

tests/SerializingRulesetTrait.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,15 @@ public static function serializeRulesetDataProvider(): array
2323
public function testSerializing(Rule $record): void
2424
{
2525
try {
26+
// @phpstan-ignore argument.type
2627
$serializedValue = Serializer::{'serialize' . ucfirst($record->header_type)}($record->expected);
2728

2829
if ($record->must_fail) {
2930
$this->fail('"' . $record->name . '" must fail serializing');
3031
}
3132

3233
$this->assertEquals(
33-
implode(', ', $record->canonical ?? $record->raw),
34+
implode(', ', $record->canonical ?? $record->raw ?? []),
3435
$serializedValue,
3536
'"' . $record->name . '" was not serialized to expected value'
3637
);

0 commit comments

Comments
 (0)