Skip to content

Commit 578f552

Browse files
committed
Level up psalm checks
1 parent d6b5291 commit 578f552

27 files changed

+113
-19
lines changed

src/FqsenResolver.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@
1919
use function implode;
2020
use function strpos;
2121

22+
/**
23+
* Resolver for Fqsen using Context information
24+
*
25+
* @psalm-immutable
26+
*/
2227
class FqsenResolver
2328
{
2429
/** @var string Definition of the NAMESPACE operator in PHP */

src/Type.php

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

1414
namespace phpDocumentor\Reflection;
1515

16+
/**
17+
* @psalm-immutable
18+
*/
1619
interface Type
1720
{
1821
/**

src/TypeResolver.php

Lines changed: 50 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,10 @@ final class TypeResolver
9393
'iterable' => Iterable_::class,
9494
];
9595

96-
/** @var FqsenResolver */
96+
/**
97+
* @var FqsenResolver
98+
* @psalm-readonly
99+
*/
97100
private $fqsenResolver;
98101

99102
/**
@@ -119,6 +122,8 @@ public function __construct(?FqsenResolver $fqsenResolver = null)
119122
* @uses Context::getNamespace() to determine with what to prefix the type name.
120123
*
121124
* @param string $type The relative or absolute type.
125+
*
126+
* @psalm-pure
122127
*/
123128
public function resolve(string $type, ?Context $context = null) : Type
124129
{
@@ -143,6 +148,7 @@ public function resolve(string $type, ?Context $context = null) : Type
143148
throw new InvalidArgumentException('Unable to split the type string "' . $type . '" into tokens');
144149
}
145150

151+
/** @var ArrayIterator<int, string|null> $tokenIterator */
146152
$tokenIterator = new ArrayIterator($tokens);
147153

148154
return $this->parseTypes($tokenIterator, $context, self::PARSER_IN_COMPOUND);
@@ -151,18 +157,23 @@ public function resolve(string $type, ?Context $context = null) : Type
151157
/**
152158
* Analyse each tokens and creates types
153159
*
154-
* @param ArrayIterator<int, string> $tokens the iterator on tokens
160+
* @param ArrayIterator<int, string|null> $tokens the iterator on tokens
155161
* @param int $parserContext on of self::PARSER_* constants, indicating
156162
* the context where we are in the parsing
163+
*
164+
* @psalm-pure
157165
*/
158166
private function parseTypes(ArrayIterator $tokens, Context $context, int $parserContext) : Type
159167
{
160168
$types = [];
161169
$token = '';
162170
while ($tokens->valid()) {
163171
$token = $tokens->current();
164-
165-
if ($token === '|') {
172+
if ($token === null) {
173+
throw new RuntimeException(
174+
'Unexpected nullable character'
175+
);
176+
} elseif ($token === '|') {
166177
if (count($types) === 0) {
167178
throw new RuntimeException(
168179
'A type is missing before a type separator'
@@ -287,6 +298,8 @@ private function parseTypes(ArrayIterator $tokens, Context $context, int $parser
287298
* @param string $type the type string, representing a single type
288299
*
289300
* @return Type|Array_|Object_
301+
*
302+
* @psalm-pure
290303
*/
291304
private function resolveSingleType(string $type, Context $context) : object
292305
{
@@ -338,6 +351,8 @@ public function addKeyword(string $keyword, string $typeClassName) : void
338351
* Detects whether the given type represents an array.
339352
*
340353
* @param string $type A relative or absolute type as defined in the phpDocumentor documentation.
354+
*
355+
* @psalm-pure
341356
*/
342357
private function isTypedArray(string $type) : bool
343358
{
@@ -348,6 +363,8 @@ private function isTypedArray(string $type) : bool
348363
* Detects whether the given type represents a PHPDoc keyword.
349364
*
350365
* @param string $type A relative or absolute type as defined in the phpDocumentor documentation.
366+
*
367+
* @psalm-pure
351368
*/
352369
private function isKeyword(string $type) : bool
353370
{
@@ -358,6 +375,8 @@ private function isKeyword(string $type) : bool
358375
* Detects whether the given type represents a relative structural element name.
359376
*
360377
* @param string $type A relative or absolute type as defined in the phpDocumentor documentation.
378+
*
379+
* @psalm-pure
361380
*/
362381
private function isPartialStructuralElementName(string $type) : bool
363382
{
@@ -366,6 +385,8 @@ private function isPartialStructuralElementName(string $type) : bool
366385

367386
/**
368387
* Tests whether the given type is a Fully Qualified Structural Element Name.
388+
*
389+
* @psalm-pure
369390
*/
370391
private function isFqsen(string $type) : bool
371392
{
@@ -374,6 +395,8 @@ private function isFqsen(string $type) : bool
374395

375396
/**
376397
* Resolves the given typed array string (i.e. `string[]`) into an Array object with the right types set.
398+
*
399+
* @psalm-pure
377400
*/
378401
private function resolveTypedArray(string $type, Context $context) : Array_
379402
{
@@ -382,6 +405,8 @@ private function resolveTypedArray(string $type, Context $context) : Array_
382405

383406
/**
384407
* Resolves the given keyword (such as `string`) into a Type object representing that keyword.
408+
*
409+
* @psalm-pure
385410
*/
386411
private function resolveKeyword(string $type) : Type
387412
{
@@ -392,6 +417,8 @@ private function resolveKeyword(string $type) : Type
392417

393418
/**
394419
* Resolves the given FQSEN string into an FQSEN object.
420+
*
421+
* @psalm-pure
395422
*/
396423
private function resolveTypedObject(string $type, ?Context $context = null) : Object_
397424
{
@@ -401,7 +428,9 @@ private function resolveTypedObject(string $type, ?Context $context = null) : Ob
401428
/**
402429
* Resolves class string
403430
*
404-
* @param ArrayIterator<int, string> $tokens
431+
* @param ArrayIterator<int, null|string> $tokens
432+
*
433+
* @psalm-pure
405434
*/
406435
private function resolveClassString(ArrayIterator $tokens, Context $context) : Type
407436
{
@@ -415,15 +444,16 @@ private function resolveClassString(ArrayIterator $tokens, Context $context) : T
415444
);
416445
}
417446

418-
if ($tokens->current() !== '>') {
419-
if (empty($tokens->current())) {
447+
$token = $tokens->current();
448+
if ($token !== '>') {
449+
if (empty($token)) {
420450
throw new RuntimeException(
421451
'class-string: ">" is missing'
422452
);
423453
}
424454

425455
throw new RuntimeException(
426-
'Unexpected character "' . $tokens->current() . '", ">" is missing'
456+
'Unexpected character "' . $token . '", ">" is missing'
427457
);
428458
}
429459

@@ -433,9 +463,11 @@ private function resolveClassString(ArrayIterator $tokens, Context $context) : T
433463
/**
434464
* Resolves the collection values and keys
435465
*
436-
* @param ArrayIterator<int, string> $tokens
466+
* @param ArrayIterator<int, null|string> $tokens
437467
*
438468
* @return Array_|Iterable_|Collection
469+
*
470+
* @psalm-mutation-free
439471
*/
440472
private function resolveCollection(ArrayIterator $tokens, Type $classType, Context $context) : Type
441473
{
@@ -455,7 +487,8 @@ private function resolveCollection(ArrayIterator $tokens, Type $classType, Conte
455487
$valueType = $this->parseTypes($tokens, $context, self::PARSER_IN_COLLECTION_EXPRESSION);
456488
$keyType = null;
457489

458-
if ($tokens->current() !== null && trim($tokens->current()) === ',') {
490+
$token = $tokens->current();
491+
if ($token !== null && trim($token) === ',') {
459492
// if we have a comma, then we just parsed the key type, not the value type
460493
$keyType = $valueType;
461494
if ($isArray) {
@@ -488,15 +521,16 @@ private function resolveCollection(ArrayIterator $tokens, Type $classType, Conte
488521
$valueType = $this->parseTypes($tokens, $context, self::PARSER_IN_COLLECTION_EXPRESSION);
489522
}
490523

491-
if ($tokens->current() !== '>') {
492-
if (empty($tokens->current())) {
524+
$token = $tokens->current();
525+
if ($token !== '>') {
526+
if (empty($token)) {
493527
throw new RuntimeException(
494528
'Collection: ">" is missing'
495529
);
496530
}
497531

498532
throw new RuntimeException(
499-
'Unexpected character "' . $tokens->current() . '", ">" is missing'
533+
'Unexpected character "' . $token . '", ">" is missing'
500534
);
501535
}
502536

@@ -515,6 +549,9 @@ private function resolveCollection(ArrayIterator $tokens, Type $classType, Conte
515549
throw new RuntimeException('Invalid $classType provided');
516550
}
517551

552+
/**
553+
* @psalm-pure
554+
*/
518555
private function makeCollectionFromObject(Object_ $object, Type $valueType, ?Type $keyType = null) : Collection
519556
{
520557
return new Collection($object->getFqsen(), $valueType, $keyType);

src/Types/AbstractList.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717

1818
/**
1919
* Represents a list of values. This is an abstract class for Array_ and Collection.
20+
*
21+
* @psalm-immutable
2022
*/
2123
abstract class AbstractList implements Type
2224
{

src/Types/Array_.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
* 1. Untyped (`array`), where the key and value type is unknown and hence classified as 'Mixed_'.
2222
* 2. Types (`string[]`), where the value type is provided by preceding an opening and closing square bracket with a
2323
* type name.
24+
*
25+
* @psalm-immutable
2426
*/
2527
final class Array_ extends AbstractList
2628
{

src/Types/Boolean.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717

1818
/**
1919
* Value Object representing a Boolean type.
20+
*
21+
* @psalm-immutable
2022
*/
2123
final class Boolean implements Type
2224
{

src/Types/Callable_.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717

1818
/**
1919
* Value Object representing a Callable type.
20+
*
21+
* @psalm-immutable
2022
*/
2123
final class Callable_ implements Type
2224
{

src/Types/ClassString.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818

1919
/**
2020
* Value Object representing the type 'string'.
21+
*
22+
* @psalm-immutable
2123
*/
2224
final class ClassString implements Type
2325
{

src/Types/Collection.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
*
2727
* - ACollectionObject can be 'array' or an object that can act as an array
2828
* - aValueType and aKeyType can be any type expression
29+
*
30+
* @psalm-immutable
2931
*/
3032
final class Collection extends AbstractList
3133
{

src/Types/Compound.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,15 @@
2626
* using an OR operator (`|`). This combination of types signifies that whatever is associated with this compound type
2727
* may contain a value with any of the given types.
2828
*
29+
* @psalm-immutable
2930
* @template-implements IteratorAggregate<int, Type>
3031
*/
3132
final class Compound implements Type, IteratorAggregate
3233
{
33-
/** @var array<int, Type> */
34+
/**
35+
* @psalm-allow-private-mutation
36+
* @var array<int, Type>
37+
*/
3438
private $types = [];
3539

3640
/**

0 commit comments

Comments
 (0)