File tree 5 files changed +136
-5
lines changed
5 files changed +136
-5
lines changed Original file line number Diff line number Diff line change @@ -19,7 +19,7 @@ final class FunctionReturnTypeProvider implements FunctionReturnTypeProviderInte
19
19
public static function getFunctionIds (): array
20
20
{
21
21
return [
22
- 'psl\str \count ' ,
22
+ 'psl\iter \count ' ,
23
23
];
24
24
}
25
25
@@ -56,7 +56,22 @@ public static function getFunctionReturnType(FunctionReturnTypeProviderEvent $ev
56
56
57
57
// array{foo: bar} -> literal-int(1)
58
58
if ($ array_argument_type instanceof Type \Atomic \TKeyedArray) {
59
- return Type::getInt (false , count ($ array_argument_type ->properties ));
59
+ // Psalm allows extra properties in keyed arrays, so we can't return a literal integer
60
+ // for this.
61
+ //
62
+ // return Type::getInt(false, count($array_argument_type->properties));
63
+
64
+ if (count ($ array_argument_type ->properties ) >= 1 ) {
65
+ return Type::getPositiveInt ();
66
+ }
67
+
68
+ return Type::getInt ();
69
+ }
70
+
71
+ if ($ array_argument_type instanceof Type \Atomic \TArray) {
72
+ if ($ array_argument_type ->type_params [0 ]->isEmpty () && $ array_argument_type ->type_params [1 ]->isEmpty ()) {
73
+ return Type::getInt (false , 0 );
74
+ }
60
75
}
61
76
62
77
return Type::getInt ();
Original file line number Diff line number Diff line change
1
+ <?php
2
+
3
+ declare (strict_types=1 );
4
+
5
+ namespace Psl \Psalm \EventHandler \Iter \FirstKey ;
6
+
7
+ use Psalm \Plugin \EventHandler \Event \FunctionReturnTypeProviderEvent ;
8
+ use Psalm \Plugin \EventHandler \FunctionReturnTypeProviderInterface ;
9
+ use Psalm \Type ;
10
+ use Psl \Psalm \Argument ;
11
+
12
+ final class FunctionReturnTypeProvider implements FunctionReturnTypeProviderInterface
13
+ {
14
+ /**
15
+ * @return non-empty-list<lowercase-string>
16
+ */
17
+ public static function getFunctionIds (): array
18
+ {
19
+ return [
20
+ 'psl\iter\first_key ' ,
21
+ ];
22
+ }
23
+
24
+ public static function getFunctionReturnType (FunctionReturnTypeProviderEvent $ event ): ?Type \Union
25
+ {
26
+ $ argument_type = Argument::getType ($ event ->getCallArgs (), $ event ->getStatementsSource (), 0 );
27
+ if (null === $ argument_type ) {
28
+ return null ;
29
+ }
30
+
31
+ $ array_argument_type = $ argument_type ->getAtomicTypes ()['array ' ] ?? null ;
32
+ if (null === $ array_argument_type ) {
33
+ return null ;
34
+ }
35
+
36
+ if ($ array_argument_type instanceof Type \Atomic \TNonEmptyArray) {
37
+ return clone $ array_argument_type ->type_params [0 ];
38
+ }
39
+
40
+ if ($ array_argument_type instanceof Type \Atomic \TNonEmptyList) {
41
+ return Type::getInt ();
42
+ }
43
+
44
+ if ($ array_argument_type instanceof Type \Atomic \TKeyedArray) {
45
+ // TODO(azjezz): add support for this once psalm starts enforcing the shape order ( if ever ).
46
+ //
47
+ // foreach ($properties as $property) {
48
+ // return clone $property;
49
+ // }
50
+ return clone $ array_argument_type ->getGenericKeyType ();
51
+ }
52
+
53
+ return null ;
54
+ }
55
+ }
Original file line number Diff line number Diff line change
1
+ <?php
2
+
3
+ declare (strict_types=1 );
4
+
5
+ namespace Psl \Psalm \EventHandler \Iter \LastKey ;
6
+
7
+ use Psalm \Plugin \EventHandler \Event \FunctionReturnTypeProviderEvent ;
8
+ use Psalm \Plugin \EventHandler \FunctionReturnTypeProviderInterface ;
9
+ use Psalm \Type ;
10
+ use Psl \Psalm \Argument ;
11
+
12
+ final class FunctionReturnTypeProvider implements FunctionReturnTypeProviderInterface
13
+ {
14
+ /**
15
+ * @return non-empty-list<lowercase-string>
16
+ */
17
+ public static function getFunctionIds (): array
18
+ {
19
+ return [
20
+ 'psl\iter\last_key ' ,
21
+ ];
22
+ }
23
+
24
+ public static function getFunctionReturnType (FunctionReturnTypeProviderEvent $ event ): ?Type \Union
25
+ {
26
+ $ argument_type = Argument::getType ($ event ->getCallArgs (), $ event ->getStatementsSource (), 0 );
27
+ if (null === $ argument_type ) {
28
+ return null ;
29
+ }
30
+
31
+ $ array_argument_type = $ argument_type ->getAtomicTypes ()['array ' ] ?? null ;
32
+ if (null === $ array_argument_type ) {
33
+ return null ;
34
+ }
35
+
36
+ if ($ array_argument_type instanceof Type \Atomic \TNonEmptyArray) {
37
+ return clone $ array_argument_type ->type_params [0 ];
38
+ }
39
+
40
+ if ($ array_argument_type instanceof Type \Atomic \TNonEmptyList) {
41
+ return Type::getInt ();
42
+ }
43
+
44
+ if ($ array_argument_type instanceof Type \Atomic \TKeyedArray) {
45
+ // TODO(azjezz): add support for this once psalm starts enforcing the shape order ( if ever ).
46
+ //
47
+ // $properties = $array_argument_type->properties;
48
+ // $last_property = null;
49
+ // foreach ($properties as $property) {
50
+ // $last_property = $property;
51
+ // }
52
+ //
53
+ // return clone $last_property;
54
+ return clone $ array_argument_type ->getGenericKeyType ();
55
+ }
56
+
57
+ return null ;
58
+ }
59
+ }
Original file line number Diff line number Diff line change @@ -26,7 +26,7 @@ public static function getFunctionIds(): array
26
26
public static function getFunctionReturnType (FunctionReturnTypeProviderEvent $ event ): ?Type \Union
27
27
{
28
28
$ argument_type = Argument::getType ($ event ->getCallArgs (), $ event ->getStatementsSource (), 0 );
29
- if ($ argument_type === null || ! $ argument_type -> hasLowercaseString () ) {
29
+ if ($ argument_type === null ) {
30
30
return Type::getString ();
31
31
}
32
32
@@ -43,12 +43,12 @@ public static function getFunctionReturnType(FunctionReturnTypeProviderEvent $ev
43
43
return new Type \Union ([new Type \Atomic \TLowercaseString ()]);
44
44
}
45
45
46
- if ($ string_argument_type instanceof Type \ Atomic \TLiteralString ) {
46
+ if ($ argument_type -> hasLiteralString () ) {
47
47
$ multiplier_argument_type = Argument::getType ($ event ->getCallArgs (), $ event ->getStatementsSource (), 1 );
48
48
if (null !== $ multiplier_argument_type && $ multiplier_argument_type ->hasLiteralInt ()) {
49
49
/** @psalm-suppress MissingThrowsDocblock */
50
50
return Type::getString (str_repeat (
51
- $ string_argument_type ->value ,
51
+ $ argument_type -> getSingleStringLiteral () ->value ,
52
52
$ multiplier_argument_type ->getSingleIntLiteral ()->value
53
53
));
54
54
}
Original file line number Diff line number Diff line change @@ -31,7 +31,9 @@ private function getHooks(): iterable
31
31
{
32
32
// Psl\Iter hooks
33
33
yield EventHandler \Iter \First \FunctionReturnTypeProvider::class;
34
+ yield EventHandler \Iter \FirstKey \FunctionReturnTypeProvider::class;
34
35
yield EventHandler \Iter \Last \FunctionReturnTypeProvider::class;
36
+ yield EventHandler \Iter \LastKey \FunctionReturnTypeProvider::class;
35
37
yield EventHandler \Iter \Count \FunctionReturnTypeProvider::class;
36
38
37
39
// Psl\Regex hooks
You can’t perform that action at this time.
0 commit comments