Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Static Analysis Checks: Common Operations (II) (#109)
* SA Check: Filter * SA Check: First * SA Check: Head * SA Check: Last + annotations tweaks * Revert first annotation removal
- Loading branch information
1 parent
366c79b
commit ee3bf3b
Showing
9 changed files
with
282 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
<?php | ||
|
||
/** | ||
* For the full copyright and license information, please view | ||
* the LICENSE file that was distributed with this source code. | ||
*/ | ||
|
||
declare(strict_types=1); | ||
|
||
include __DIR__ . '/../../vendor/autoload.php'; | ||
|
||
use loophp\collection\Collection; | ||
use loophp\collection\Contract\Collection as CollectionInterface; | ||
|
||
/** | ||
* @param CollectionInterface<int, int> $collection | ||
*/ | ||
function filter_checkList(CollectionInterface $collection): void | ||
{ | ||
} | ||
/** | ||
* @param CollectionInterface<string, string> $collection | ||
*/ | ||
function filter_checkMap(CollectionInterface $collection): void | ||
{ | ||
} | ||
|
||
$intValueCallback = static fn (int $value): bool => $value % 2 === 0; | ||
$intValueCallback2 = static fn (int $value): bool => 2 < $value; | ||
$intKeyValueCallback1 = static fn (int $value, int $key): bool => $value % 2 === 0 && $key % 2 === 0; | ||
$intKeyValueCallback2 = static fn (int $value, int $key): bool => 2 < $value && 2 < $key; | ||
|
||
$stringValueCallback = static fn (string $value): bool => 'bar' === $value; | ||
$stringValueCallback2 = static fn (string $value): bool => '' === $value; | ||
$stringKeyValueCallback1 = static fn (string $value, string $key): bool => 'bar' !== $value && 'foo' !== $key; | ||
$stringKeyValueCallback2 = static fn (string $value, string $key): bool => 'bar' !== $value && '' === $key; | ||
|
||
filter_checkList(Collection::fromIterable([1, 2, 3])->filter()); | ||
filter_checkList(Collection::fromIterable([1, 2, 3])->filter($intValueCallback)); | ||
filter_checkList(Collection::fromIterable([1, 2, 3])->filter($intValueCallback, $intValueCallback2)); | ||
filter_checkList(Collection::fromIterable([1, 2, 3])->filter($intKeyValueCallback1)); | ||
filter_checkList(Collection::fromIterable([1, 2, 3])->filter($intKeyValueCallback1, $intKeyValueCallback2)); | ||
|
||
filter_checkMap(Collection::fromIterable(['foo' => 'bar', 'baz' => ''])->filter()); | ||
filter_checkMap(Collection::fromIterable(['foo' => 'bar', 'baz' => ''])->filter($stringValueCallback)); | ||
filter_checkMap(Collection::fromIterable(['foo' => 'bar', 'baz' => ''])->filter($stringValueCallback, $stringValueCallback2)); | ||
filter_checkMap(Collection::fromIterable(['foo' => 'bar', 'baz' => ''])->filter($stringKeyValueCallback1)); | ||
filter_checkMap(Collection::fromIterable(['foo' => 'bar', 'baz' => ''])->filter($stringKeyValueCallback1, $stringKeyValueCallback2)); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
<?php | ||
|
||
/** | ||
* For the full copyright and license information, please view | ||
* the LICENSE file that was distributed with this source code. | ||
*/ | ||
|
||
declare(strict_types=1); | ||
|
||
include __DIR__ . '/../../vendor/autoload.php'; | ||
|
||
use loophp\collection\Collection; | ||
use loophp\collection\Contract\Collection as CollectionInterface; | ||
|
||
/** | ||
* @param CollectionInterface<int, int> $collection | ||
*/ | ||
function first_checkList(CollectionInterface $collection): void | ||
{ | ||
} | ||
/** | ||
* @param CollectionInterface<string, string> $collection | ||
*/ | ||
function first_checkMap(CollectionInterface $collection): void | ||
{ | ||
} | ||
function first_checkIntElement(int $value): void | ||
{ | ||
} | ||
function first_checkNullableInt(?int $value): void | ||
{ | ||
} | ||
function first_checkStringElement(string $value): void | ||
{ | ||
} | ||
function first_checkNullableString(?string $value): void | ||
{ | ||
} | ||
|
||
first_checkList(Collection::fromIterable([1, 2, 3])->first()); | ||
first_checkMap(Collection::fromIterable(['foo' => 'bar', 'baz' => 'bar'])->first()); | ||
|
||
first_checkList(Collection::empty()->first()); | ||
first_checkMap(Collection::empty()->first()); | ||
|
||
first_checkNullableInt(Collection::fromIterable([1, 2, 3])->first()->current()); | ||
first_checkNullableString(Collection::fromIterable(['foo' => 'bar', 'baz' => 'bar'])->first()->current()); | ||
|
||
// This retrieval method doesn't cause static analysis complaints | ||
// but is not always reliable because of that. | ||
first_checkIntElement(Collection::fromIterable([1, 2, 3])->first()->all()[0]); | ||
first_checkStringElement(Collection::fromIterable(['foo' => 'bar', 'baz' => 'bar'])->first()->all()['foo']); | ||
first_checkStringElement(Collection::fromIterable(['foo' => 'bar', 'baz' => 'bar'])->first()->all()['baz']); | ||
|
||
// VALID failures - `current` returns T|null | ||
/** @psalm-suppress PossiblyNullArgument @phpstan-ignore-next-line */ | ||
first_checkIntElement(Collection::fromIterable([1, 2, 3])->first()->current()); | ||
/** @psalm-suppress PossiblyNullArgument @phpstan-ignore-next-line */ | ||
first_checkStringElement(Collection::fromIterable(['foo' => 'bar'])->first()->current()); | ||
|
||
// VALID failures - these keys don't exist | ||
/** @psalm-suppress InvalidArrayOffset */ | ||
first_checkIntElement(Collection::fromIterable([1, 2, 3])->first()->all()[4]); | ||
/** @psalm-suppress InvalidArrayOffset @phpstan-ignore-next-line */ | ||
first_checkStringElement(Collection::fromIterable(['foo' => 'bar', 'baz' => 'bar'])->first()->all()[0]); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
<?php | ||
|
||
/** | ||
* For the full copyright and license information, please view | ||
* the LICENSE file that was distributed with this source code. | ||
*/ | ||
|
||
declare(strict_types=1); | ||
|
||
include __DIR__ . '/../../vendor/autoload.php'; | ||
|
||
use loophp\collection\Collection; | ||
use loophp\collection\Contract\Collection as CollectionInterface; | ||
|
||
/** | ||
* @param CollectionInterface<int, int> $collection | ||
*/ | ||
function head_checkList(CollectionInterface $collection): void | ||
{ | ||
} | ||
/** | ||
* @param CollectionInterface<string, string> $collection | ||
*/ | ||
function head_checkMap(CollectionInterface $collection): void | ||
{ | ||
} | ||
function head_checkIntElement(int $value): void | ||
{ | ||
} | ||
function head_checkNullableInt(?int $value): void | ||
{ | ||
} | ||
function head_checkStringElement(string $value): void | ||
{ | ||
} | ||
function head_checkNullableString(?string $value): void | ||
{ | ||
} | ||
|
||
head_checkList(Collection::fromIterable([1, 2, 3])->head()); | ||
head_checkMap(Collection::fromIterable(['foo' => 'bar', 'baz' => 'bar'])->head()); | ||
|
||
head_checkList(Collection::empty()->head()); | ||
head_checkMap(Collection::empty()->head()); | ||
|
||
head_checkNullableInt(Collection::fromIterable([1, 2, 3])->head()->current()); | ||
head_checkNullableString(Collection::fromIterable(['foo' => 'bar', 'baz' => 'bar'])->head()->current()); | ||
|
||
// This retrieval method doesn't cause static analysis complaints | ||
// but is not always reliable because of that. | ||
head_checkIntElement(Collection::fromIterable([1, 2, 3])->head()->all()[0]); | ||
head_checkStringElement(Collection::fromIterable(['foo' => 'bar', 'baz' => 'bar'])->head()->all()['foo']); | ||
head_checkStringElement(Collection::fromIterable(['foo' => 'bar', 'baz' => 'bar'])->head()->all()['baz']); | ||
|
||
// VALID failures - `current` returns T|null | ||
/** @psalm-suppress PossiblyNullArgument @phpstan-ignore-next-line */ | ||
head_checkIntElement(Collection::fromIterable([1, 2, 3])->head()->current()); | ||
/** @psalm-suppress PossiblyNullArgument @phpstan-ignore-next-line */ | ||
head_checkStringElement(Collection::fromIterable(['foo' => 'bar'])->head()->current()); | ||
|
||
// VALID failures - these keys don't exist | ||
/** @psalm-suppress InvalidArrayOffset */ | ||
head_checkIntElement(Collection::fromIterable([1, 2, 3])->head()->all()[4]); | ||
/** @psalm-suppress InvalidArrayOffset @phpstan-ignore-next-line */ | ||
head_checkStringElement(Collection::fromIterable(['foo' => 'bar', 'baz' => 'bar'])->head()->all()[0]); |
Oops, something went wrong.