Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support ReadableCollection #126

Merged
merged 6 commits into from
Oct 9, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,18 @@
"require": {
"php": "^7.2 || ^8",
"composer/semver": "^1.4 || ^2.0 || ^3.0",
"vimeo/psalm": "^4.9",
"vimeo/psalm": "^4.28",
"phpstan/phpdoc-parser": "~1.5.0"
},
"conflict": {
"doctrine/collections": "<1.6",
"doctrine/collections": "<1.8",
"doctrine/orm": "<2.6",
"doctrine/persistence": "<2.0"
},
"require-dev": {
"codeception/codeception": "^4.0",
"doctrine/coding-standard": "^9.0",
"doctrine/collections": "^1.0",
"doctrine/collections": "^1.8 || ^2.0",
"doctrine/doctrine-bundle": "^1.11 || ^2.0",
"doctrine/orm": "^2.6",
"doctrine/persistence": "^2.0",
Expand Down
21 changes: 13 additions & 8 deletions src/Provider/ReturnTypeProvider/CollectionFirstAndLast.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@ class CollectionFirstAndLast implements MethodReturnTypeProviderInterface
*/
public static function getClassLikeNames(): array
{
return ['Doctrine\Common\Collections\Collection'];
return [
'Doctrine\Common\Collections\Collection',
'Doctrine\Common\Collections\ReadableCollection',
];
}

public static function getMethodReturnType(MethodReturnTypeProviderEvent $event): ?Type\Union
Expand All @@ -50,16 +53,18 @@ public static function getMethodReturnType(MethodReturnTypeProviderEvent $event)
$varParts[] = $varStmt->name;
$scopedVarName = '$' . implode('->', array_reverse($varParts)) . '->isempty()';

if ($event->getMethodNameLowercase() === 'add') {
$event->getContext()->vars_in_scope[$scopedVarName] = Type::getFalse();
if ($event->getFqClasslikeName() === 'Doctrine\Common\Collections\Collection') {
if ($event->getMethodNameLowercase() === 'add') {
$event->getContext()->vars_in_scope[$scopedVarName] = Type::getFalse();

return null;
}
return null;
}

if ($event->getMethodNameLowercase() === 'remove' || $event->getMethodNameLowercase() === 'removeelement') {
$event->getContext()->remove($scopedVarName);
if ($event->getMethodNameLowercase() === 'remove' || $event->getMethodNameLowercase() === 'removeelement') {
$event->getContext()->remove($scopedVarName);

return null;
return null;
}
}

if (
Expand Down
86 changes: 54 additions & 32 deletions stubs/Collections.phpstub
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ use ArrayAccess;
* @template TKey as array-key
* @template TValue
*
* @template-extends IteratorAggregate<TKey,TValue>
* @template-extends ReadableCollection<TKey,TValue>
* @template-extends ArrayAccess<TKey|null,TValue>
*/
interface Collection extends Countable, IteratorAggregate, ArrayAccess
interface Collection extends ReadableCollection, ArrayAccess
{

/**
Expand All @@ -36,28 +36,57 @@ interface Collection extends Countable, IteratorAggregate, ArrayAccess
public function clear();

/**
* @param TValue $element
* @return bool
* @param TKey $key
* @return TValue|null
*/
public function contains($element);
public function remove($key);

/**
* @param TValue $element
* @return bool
* @psalm-mutation-free
*/
public function isEmpty();
public function removeElement($element);

/**
* @param TKey $key
* @return TValue|null
* @param TValue $value
* @return void
*/
public function remove($key);
public function set($key, $value);

/**
* @param Closure(TValue=):bool $p
* @return Collection<TKey,TValue>
*/
public function filter(Closure $p);

/**
* @param Closure(TKey=,TValue=):bool $p
* @return array{0:Collection<TKey,TValue>,1:Collection<TKey,TValue>}
*/
public function partition(Closure $p);
}

/**
* @template TKey as array-key
* @template-covariant TValue
*
* @template-extends IteratorAggregate<TKey,TValue>
*/
interface ReadableCollection extends Countable, IteratorAggregate
{

/**
* @param TValue $element
* @return bool
*/
public function removeElement($element);
public function contains($element);

/**
* @return bool
* @psalm-mutation-free
*/
public function isEmpty();

/**
* @param TKey $key
Expand All @@ -81,13 +110,6 @@ interface Collection extends Countable, IteratorAggregate, ArrayAccess
*/
public function getValues();

/**
* @param TKey $key
* @param TValue $value
* @return void
*/
public function set($key, $value);

/**
* @return array<TKey,TValue>
*/
Expand Down Expand Up @@ -118,6 +140,13 @@ interface Collection extends Countable, IteratorAggregate, ArrayAccess
*/
public function next();

/**
* @param int $offset
* @param int|null $length
* @return array<TKey,TValue>
*/
public function slice($offset, $length = null);

/**
* @param Closure(TKey=,TValue=):bool $p
* @return bool
Expand All @@ -126,16 +155,10 @@ interface Collection extends Countable, IteratorAggregate, ArrayAccess

/**
* @param Closure(TValue=):bool $p
* @return Collection<TKey,TValue>
* @return ReadableCollection<TKey,TValue>
*/
public function filter(Closure $p);

/**
* @param Closure(TKey=,TValue=):bool $p
* @return bool
*/
public function forAll(Closure $p);

/**
* @template T
* @param Closure(TValue=):T $func
Expand All @@ -145,22 +168,21 @@ interface Collection extends Countable, IteratorAggregate, ArrayAccess

/**
* @param Closure(TKey=,TValue=):bool $p
* @return array{0:Collection<TKey,TValue>,1:Collection<TKey,TValue>}
* @return array{0:ReadableCollection<TKey,TValue>,1:ReadableCollection<TKey,TValue>}
*/
public function partition(Closure $p);

/**
* @param TValue $element
* @return false|TKey
* @param Closure(TKey=,TValue=):bool $p
* @return bool
*/
public function indexOf($element);
public function forAll(Closure $p);

/**
* @param int $offset
* @param int|null $length
* @return array<TKey,TValue>
* @param TValue $element
* @return false|TKey
*/
public function slice($offset, $length = null);
public function indexOf($element);
}

/**
Expand Down
Loading