66
77use ArrayAccess ;
88use Countable ;
9- use Generator ;
109use GraphQL \Utils \AST ;
10+ use InvalidArgumentException ;
1111use IteratorAggregate ;
12+ use Traversable ;
1213use function array_merge ;
1314use function array_splice ;
1415use function count ;
1516use function is_array ;
1617
18+ /**
19+ * @template T of Node
20+ * @phpstan-implements ArrayAccess<int|string, T>
21+ * @phpstan-implements IteratorAggregate<T>
22+ */
1723class NodeList implements ArrayAccess, IteratorAggregate, Countable
1824{
19- /** @var Node[]|mixed[] */
25+ /**
26+ * @var Node[]
27+ * @phpstan-var array<T>
28+ */
2029 private $ nodes ;
2130
2231 /**
23- * @param Node[]|mixed[] $nodes
32+ * @param Node[] $nodes
2433 *
25- * @return static
34+ * @phpstan-param array<T> $nodes
35+ * @phpstan-return self<T>
2636 */
27- public static function create (array $ nodes )
37+ public static function create (array $ nodes ) : self
2838 {
2939 return new static ($ nodes );
3040 }
3141
3242 /**
33- * @param Node[]|mixed[] $nodes
43+ * @param Node[] $nodes
44+ *
45+ * @phpstan-param array<T> $nodes
3446 */
3547 public function __construct (array $ nodes )
3648 {
3749 $ this ->nodes = $ nodes ;
3850 }
3951
4052 /**
41- * @param mixed $offset
42- *
43- * @return bool
53+ * @param int|string $offset
4454 */
45- public function offsetExists ($ offset )
55+ public function offsetExists ($ offset ) : bool
4656 {
4757 return isset ($ this ->nodes [$ offset ]);
4858 }
4959
5060 /**
51- * @param mixed $offset
61+ * TODO enable strict typing by changing how the Visitor deals with NodeList.
62+ * Ideally, this function should always return a Node instance.
63+ * However, the Visitor currently allows mutation of the NodeList
64+ * and puts arbitrary values in the NodeList, such as strings.
65+ * We will have to switch to using an array or a less strict
66+ * type instead so we can enable strict typing in this class.
67+ *
68+ * @param int|string $offset
5269 *
53- * @return mixed
70+ * @phpstan- return T
5471 */
55- public function offsetGet ($ offset )
72+ public function offsetGet ($ offset )// : Node
5673 {
5774 $ item = $ this ->nodes [$ offset ];
5875
5976 if (is_array ($ item ) && isset ($ item ['kind ' ])) {
60- $ this ->nodes [$ offset ] = $ item = AST ::fromArray ($ item );
77+ /** @phpstan-var T $node */
78+ $ node = AST ::fromArray ($ item );
79+ $ this ->nodes [$ offset ] = $ node ;
6180 }
6281
63- return $ item ;
82+ return $ this -> nodes [ $ offset ] ;
6483 }
6584
6685 /**
67- * @param mixed $offset
68- * @param mixed $value
86+ * @param int|string $offset
87+ * @param Node|mixed[] $value
88+ *
89+ * @phpstan-param T|mixed[] $value
6990 */
70- public function offsetSet ($ offset , $ value )
91+ public function offsetSet ($ offset , $ value ) : void
7192 {
72- if (is_array ($ value ) && isset ($ value ['kind ' ])) {
73- $ value = AST ::fromArray ($ value );
93+ if (is_array ($ value )) {
94+ if (isset ($ value ['kind ' ])) {
95+ /** @phpstan-var T $node */
96+ $ node = AST ::fromArray ($ value );
97+ $ this ->nodes [$ offset ] = $ node ;
98+
99+ return ;
100+ }
101+
102+ throw new InvalidArgumentException (
103+ 'Expected array value to be valid node data structure, missing key "kind" '
104+ );
74105 }
106+
75107 $ this ->nodes [$ offset ] = $ value ;
76108 }
77109
78110 /**
79- * @param mixed $offset
111+ * @param int|string $offset
80112 */
81- public function offsetUnset ($ offset )
113+ public function offsetUnset ($ offset ) : void
82114 {
83115 unset($ this ->nodes [$ offset ]);
84116 }
85117
86118 /**
87- * @param int $offset
88- * @param int $length
89119 * @param mixed $replacement
90120 *
91- * @return NodeList
121+ * @phpstan- return NodeList<T>
92122 */
93- public function splice ($ offset , $ length , $ replacement = null )
123+ public function splice (int $ offset , int $ length , $ replacement = null ) : NodeList
94124 {
95125 return new NodeList (array_splice ($ this ->nodes , $ offset , $ length , $ replacement ));
96126 }
97127
98128 /**
99129 * @param NodeList|Node[] $list
100130 *
101- * @return NodeList
131+ * @phpstan-param NodeList<T>|array<T> $list
132+ * @phpstan-return NodeList<T>
102133 */
103- public function merge ($ list )
134+ public function merge ($ list ) : NodeList
104135 {
105136 if ($ list instanceof self) {
106137 $ list = $ list ->nodes ;
@@ -109,20 +140,14 @@ public function merge($list)
109140 return new NodeList (array_merge ($ this ->nodes , $ list ));
110141 }
111142
112- /**
113- * @return Generator
114- */
115- public function getIterator ()
143+ public function getIterator () : Traversable
116144 {
117145 foreach ($ this ->nodes as $ key => $ _ ) {
118146 yield $ this ->offsetGet ($ key );
119147 }
120148 }
121149
122- /**
123- * @return int
124- */
125- public function count ()
150+ public function count () : int
126151 {
127152 return count ($ this ->nodes );
128153 }
0 commit comments