Skip to content

Commit

Permalink
Fix conversion of in() and notIn() to native enums when called wi…
Browse files Browse the repository at this point in the history
…th non-arrays
  • Loading branch information
spawnia committed Aug 21, 2024
1 parent 0f82b99 commit facd826
Show file tree
Hide file tree
Showing 9 changed files with 65 additions and 7 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## Unreleased

## 6.11.1

### Fixed

- Fix conversion of `in()` and `notIn()` to native enums when called with non-arrays

## 6.11.0

### Added
Expand Down
1 change: 1 addition & 0 deletions phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ parameters:
- '#unknown class Illuminate\\Support\\Facades\\Process#'
- '#unknown class Illuminate\\Process#'
- '#invalid type Illuminate\\Process#'
- '#^Attribute class PHPUnit\\Framework\\Attributes\\DataProvider does not exist\.$#' # Only available with newer PHPUnit versions
excludePaths:
- tests/Enums/ToNativeFixtures # Fails with PHP < 8.1
- tests/PHPStan/Fixtures
Expand Down
36 changes: 29 additions & 7 deletions src/Rector/ToNativeUsagesRector.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use BenSampo\Enum\Enum;
use BenSampo\Enum\Tests\Enums\UserType;
use Illuminate\Support\Arr;
use Illuminate\Support\Enumerable;
use PhpParser\Node;
use PhpParser\Node\Arg;
use PhpParser\Node\Expr;
Expand Down Expand Up @@ -565,7 +566,9 @@ protected function refactorMaybeMagicStaticCall(StaticCall $call): ?Node
*/
protected function refactorIsOrIsNot(MethodCall|NullsafeMethodCall $call, bool $is): ?Node
{
$comparison = $is ? Identical::class : NotIdentical::class;
$comparison = $is
? Identical::class
: NotIdentical::class;

if ($call->isFirstClassCallable()) {
$param = new Variable('value');
Expand Down Expand Up @@ -601,19 +604,38 @@ protected function refactorInOrNotIn(MethodCall|NullsafeMethodCall $call, bool $
{
$args = $call->args;
if (isset($args[0]) && $args[0] instanceof Arg) {
$needle = new Arg($call->var);
$haystack = $args[0];
$enumArg = new Arg($call->var);
$valuesArg = $args[0];

$haystackValue = $haystack->value;
if ($haystackValue instanceof Array_) {
foreach ($haystackValue->items as $item) {
$valuesValue = $valuesArg->value;
if ($valuesValue instanceof Array_) {
foreach ($valuesValue->items as $item) {
$item->setAttribute(self::COMPARED_AGAINST_ENUM_INSTANCE, true);
}
}

if ($this->isObjectType($valuesValue, new ObjectType(Enumerable::class))) {
return new MethodCall(
$valuesValue,
new Identifier($in
? 'contains'
: 'doesntContain'),
[$enumArg],
);
}

$haystackArg = $this->getType($valuesValue)->isArray()->yes()
? $valuesArg
: new Arg(
new FuncCall(
new Name('iterator_to_array'),
[$valuesArg],
),
);

$inArray = new FuncCall(
new Name('in_array'),
[$needle, $haystack],
[$enumArg, $haystackArg],
[self::COMPARED_AGAINST_ENUM_INSTANCE => true],
);

Expand Down
4 changes: 4 additions & 0 deletions tests/EnumAnnotateCommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@
namespace BenSampo\Enum\Tests;

use Illuminate\Filesystem\Filesystem;
use PHPUnit\Framework\Attributes\DataProvider;

final class EnumAnnotateCommandTest extends ApplicationTestCase
{
/** @dataProvider classes */
#[DataProvider('classes')]
public function testAnnotateClass(string $class): void
{
$filesystem = $this->filesystem();
Expand All @@ -19,6 +21,7 @@ public function testAnnotateClass(string $class): void
}

/** @dataProvider classes */
#[DataProvider('classes')]
public function testAnnotateClassAlreadyAnnotated(string $class): void
{
$filesystem = $this->filesystem();
Expand Down Expand Up @@ -48,6 +51,7 @@ public static function sources(): iterable
}

/** @dataProvider sources */
#[DataProvider('sources')]
public function testAnnotateFolder(string $source): void
{
$filesystem = $this->filesystem();
Expand Down
5 changes: 5 additions & 0 deletions tests/PHPStan/UniqueValuesRuleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,9 @@ public function testRule(): void
],
);
}

protected function shouldFailOnPhpErrors(): bool
{
return false;
}
}
2 changes: 2 additions & 0 deletions tests/Rector/ToNativeImplementationRectorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@

namespace BenSampo\Enum\Tests\Rector;

use PHPUnit\Framework\Attributes\DataProvider;
use Rector\Testing\PHPUnit\AbstractRectorTestCase;

/** @see \BenSampo\Enum\Rector\ToNativeImplementationRector */
final class ToNativeImplementationRectorTest extends AbstractRectorTestCase
{
/** @dataProvider provideData */
#[DataProvider('provideData')]
public function test(string $filePath): void
{
$this->doTestFile($filePath);
Expand Down
2 changes: 2 additions & 0 deletions tests/Rector/ToNativeUsagesRectorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@

namespace BenSampo\Enum\Tests\Rector;

use PHPUnit\Framework\Attributes\DataProvider;
use Rector\Testing\PHPUnit\AbstractRectorTestCase;

/** @see \BenSampo\Enum\Rector\ToNativeUsagesRector */
final class ToNativeUsagesRectorTest extends AbstractRectorTestCase
{
/** @dataProvider provideData */
#[DataProvider('provideData')]
public function test(string $filePath): void
{
$this->doTestFile($filePath);
Expand Down
8 changes: 8 additions & 0 deletions tests/Rector/Usages/in.php.inc
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ use BenSampo\Enum\Tests\Enums\UserType;
/** @var UserType $userType */
$userType->in([UserType::Administrator, UserType::Subscriber(), null]);
$userType?->in([UserType::Administrator, $userType, null]);
/** @var iterable<UserType> $iterable */
$userType->in($iterable);
/** @var \Illuminate\Support\Collection $collection */
$userType->in($collection);
-----
<?php

Expand All @@ -13,3 +17,7 @@ use BenSampo\Enum\Tests\Enums\UserType;
/** @var UserType $userType */
in_array($userType, [UserType::Administrator, UserType::Subscriber, null]);
in_array($userType, [UserType::Administrator, $userType, null]);
/** @var iterable<UserType> $iterable */
in_array($userType, iterator_to_array($iterable));
/** @var \Illuminate\Support\Collection $collection */
$collection->contains($userType);
8 changes: 8 additions & 0 deletions tests/Rector/Usages/notIn.php.inc
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ use BenSampo\Enum\Tests\Enums\UserType;
/** @var UserType $userType */
$userType->notIn([UserType::Administrator]);
$userType?->notIn([UserType::Administrator, $userType]);
/** @var iterable<UserType> $userTypes */
$userType->notIn($userTypes);
/** @var \Illuminate\Support\Collection $collection */
$userType->notIn($collection);
-----
<?php

Expand All @@ -13,3 +17,7 @@ use BenSampo\Enum\Tests\Enums\UserType;
/** @var UserType $userType */
!in_array($userType, [UserType::Administrator]);
!in_array($userType, [UserType::Administrator, $userType]);
/** @var iterable<UserType> $userTypes */
!in_array($userType, iterator_to_array($userTypes));
/** @var \Illuminate\Support\Collection $collection */
$collection->doesntContain($userType);

0 comments on commit facd826

Please sign in to comment.