Skip to content

Commit

Permalink
Fixes generics order for PriorityQueue and SplPriorityQueue
Browse files Browse the repository at this point in the history
Closes #71

Previously implemented template order did not match those of native SplPriorityQueue, i.e. \SplPriorityQueue<TPriority, TValue> - instead the templates were back-to-front.

- PriorityQueue order is fixed and a test case added
- PriorityQueue value template renamed from `T` to `TValue`
- SplPriorityQueue order fixed and test case added
- Removes attempt to document internal array priority, adding resulting psalm issues to the baseline. Users will typically insert with an integer priority and shouldn't care that internally an array is used to represent priority - also, an array for \SplPriorityQueue priority is effectively an invalid argument according to stubs - this is better off in the baseline right?

Signed-off-by: George Steel <[email protected]>
  • Loading branch information
gsteel committed Aug 23, 2022
1 parent c5aed3c commit 979df66
Show file tree
Hide file tree
Showing 5 changed files with 108 additions and 29 deletions.
6 changes: 2 additions & 4 deletions psalm-baseline.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<files psalm-version="4.24.0@06dd975cb55d36af80f242561738f16c5f58264f">
<files psalm-version="4.26.0@6998fabb2bf528b65777bf9941920888d23c03ac">
<file src="src/AbstractOptions.php">
<DocblockTypeContradiction occurrences="1">
<code>! is_array($options) &amp;&amp; ! $options instanceof Traversable</code>
Expand Down Expand Up @@ -192,9 +192,7 @@
<InvalidReturnStatement occurrences="1">
<code>$node ? $node['data'] : false</code>
</InvalidReturnStatement>
<MissingClosureReturnType occurrences="2">
<code>static fn($item)</code>
</MissingClosureReturnType>
<MissingClosureReturnType occurrences="1"/>
<MixedInferredReturnType occurrences="1">
<code>next</code>
</MixedInferredReturnType>
Expand Down
32 changes: 16 additions & 16 deletions src/PriorityQueue.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@
* "inner" iterator in the form of an SplPriorityQueue object for performing
* the actual iteration.
*
* @template T
* @template TPriority of int
* @implements IteratorAggregate<array-key, T>
* @template TValue
* @implements IteratorAggregate<array-key, TValue>
*/
class PriorityQueue implements Countable, IteratorAggregate, Serializable
{
Expand All @@ -51,14 +51,14 @@ class PriorityQueue implements Countable, IteratorAggregate, Serializable
* Actual items aggregated in the priority queue. Each item is an array
* with keys "data" and "priority".
*
* @var list<array{data: T, priority: TPriority}>
* @var list<array{data: TValue, priority: TPriority}>
*/
protected $items = [];

/**
* Inner queue object
*
* @var \SplPriorityQueue<TPriority, T>|null
* @var \SplPriorityQueue<TPriority, TValue>|null
*/
protected $queue;

Expand All @@ -67,7 +67,7 @@ class PriorityQueue implements Countable, IteratorAggregate, Serializable
*
* Priority defaults to 1 (low priority) if none provided.
*
* @param T $data
* @param TValue $data
* @param TPriority $priority
* @return $this
*/
Expand Down Expand Up @@ -148,7 +148,7 @@ public function count()
/**
* Peek at the top node in the queue, based on priority.
*
* @return T
* @return TValue
*/
public function top()
{
Expand All @@ -160,7 +160,7 @@ public function top()
/**
* Extract a node from the inner queue and sift up
*
* @return T
* @return TValue
*/
public function extract()
{
Expand Down Expand Up @@ -204,7 +204,7 @@ public function extract()
* retrieves the inner queue object, and clones it for purposes of
* iteration.
*
* @return \SplPriorityQueue<TPriority, T>
* @return \SplPriorityQueue<TPriority, TValue>
*/
#[ReturnTypeWillChange]
public function getIterator()
Expand All @@ -226,7 +226,7 @@ public function serialize()
/**
* Magic method used for serializing of an instance.
*
* @return list<array{data: T, priority: TPriority}>
* @return list<array{data: TValue, priority: TPriority}>
*/
public function __serialize()
{
Expand All @@ -251,15 +251,15 @@ public function unserialize($data)
));
}

/** @psalm-var list<array{data: T, priority: TPriority}> $toUnserialize */
/** @psalm-var list<array{data: TValue, priority: TPriority}> $toUnserialize */

$this->__unserialize($toUnserialize);
}

/**
* Magic method used to rebuild an instance.
*
* @param list<array{data: T, priority: TPriority}> $data Data array.
* @param list<array{data: TValue, priority: TPriority}> $data Data array.
* @return void
*/
public function __unserialize($data)
Expand All @@ -278,10 +278,10 @@ public function __unserialize($data)
* @param int $flag
* @return array<array-key, mixed>
* @psalm-return ($flag is self::EXTR_BOTH
* ? list<array{data: T, priority: TPriority}>
* ? list<array{data: TValue, priority: TPriority}>
* : $flag is self::EXTR_PRIORITY
* ? list<TPriority>
* : list<T>
* : list<TValue>
* )
*/
public function toArray($flag = self::EXTR_DATA)
Expand Down Expand Up @@ -316,7 +316,7 @@ public function setInternalQueueClass($class)
/**
* Does the queue contain the given datum?
*
* @param T $datum
* @param TValue $datum
* @return bool
*/
public function contains($datum)
Expand Down Expand Up @@ -349,15 +349,15 @@ public function hasPriority($priority)
* Get the inner priority queue instance
*
* @throws Exception\DomainException
* @return \SplPriorityQueue<TPriority, T>
* @return \SplPriorityQueue<TPriority, TValue>
* @psalm-assert !null $this->queue
*/
protected function getQueue()
{
if (null === $this->queue) {
/** @psalm-suppress UnsafeInstantiation */
$queue = new $this->queueClass();
/** @psalm-var \SplPriorityQueue<TPriority, T> $queue */
/** @psalm-var \SplPriorityQueue<TPriority, TValue> $queue */
$this->queue = $queue;
/** @psalm-suppress DocblockTypeContradiction, MixedArgument */
if (! $this->queue instanceof \SplPriorityQueue) {
Expand Down
13 changes: 4 additions & 9 deletions src/SplPriorityQueue.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,8 @@
* Also, provides predictable heap order for datums added with the same priority
* (i.e., they will be emitted in the same order they are enqueued).
*
* @psalm-type InternalPriority = array{0: mixed, 1: int}
* @template TPriority of int
* @template TValue
* @template TPriority of InternalPriority
* @extends \SplPriorityQueue<TPriority, TValue>
*/
class SplPriorityQueue extends \SplPriorityQueue implements Serializable
Expand All @@ -40,8 +39,8 @@ class SplPriorityQueue extends \SplPriorityQueue implements Serializable
* Utilizes {@var $serial} to ensure that values of equal priority are
* emitted in the same order in which they are inserted.
*
* @param TValue $datum
* @param TPriority|mixed $priority
* @param TValue $datum
* @param TPriority $priority
* @return void
*/
public function insert($datum, $priority)
Expand All @@ -50,8 +49,6 @@ public function insert($datum, $priority)
$priority = [$priority, $this->serial--];
}

/** @psalm-var TPriority $priority */

parent::insert($datum, $priority);
}

Expand Down Expand Up @@ -120,7 +117,7 @@ public function unserialize($data)
/**
* Magic method used to rebuild an instance.
*
* @param array $data Data array.
* @param array<array-key, mixed> $data Data array.
* @return void
*/
public function __unserialize($data)
Expand Down Expand Up @@ -148,8 +145,6 @@ public function __unserialize($data)
$priority = (int) $item['priority'];
}

/** @psalm-var TValue $item['data'] */

$this->insert($item['data'], $priority);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

declare(strict_types=1);

namespace LaminasTest\Stdlib\StaticAnalysis;

use Laminas\Stdlib\PriorityQueue;
use SplPriorityQueue;

use function array_values;
use function iterator_to_array;

final class PriorityQueueGenericsShouldMatchSplPriorityQueue
{
/** @var PriorityQueue<int, string> */
private PriorityQueue $laminas;
/** @var SplPriorityQueue<int, string> */
private SplPriorityQueue $native;

/**
* @param PriorityQueue<int, string> $laminas
* @param SplPriorityQueue<int, string> $native
*/
public function __construct(
PriorityQueue $laminas,
SplPriorityQueue $native
) {
$this->laminas = $laminas;
$this->native = $native;
}

/** @return list<string> */
public function laminasList(): array
{
return array_values(iterator_to_array($this->laminas));
}

/** @return list<string> */
public function nativeList(): array
{
return array_values(iterator_to_array($this->native));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

declare(strict_types=1);

namespace LaminasTest\Stdlib\StaticAnalysis;

use Laminas\Stdlib\SplPriorityQueue;
use SplPriorityQueue as NativeSplPriorityQueue;

use function array_values;
use function iterator_to_array;

final class SplPriorityQueueGenericsShouldMatchNativeSplPriorityQueue
{
/** @var SplPriorityQueue<int, string> */
private SplPriorityQueue $laminas;
/** @var NativeSplPriorityQueue<int, string> */
private NativeSplPriorityQueue $native;

/**
* @param SplPriorityQueue<int, string> $laminas
* @param NativeSplPriorityQueue<int, string> $native
*/
public function __construct(
SplPriorityQueue $laminas,
NativeSplPriorityQueue $native
) {
$this->laminas = $laminas;
$this->native = $native;
}

/** @return list<string> */
public function laminasList(): array
{
return array_values(iterator_to_array($this->laminas));
}

/** @return list<string> */
public function nativeList(): array
{
return array_values(iterator_to_array($this->native));
}
}

0 comments on commit 979df66

Please sign in to comment.