Skip to content

Commit

Permalink
[Rules] Enable NoEmptyOnObjectRule and make same logic on possible un…
Browse files Browse the repository at this point in the history
…defined variable (#15)
  • Loading branch information
samsonasik committed Jun 17, 2024
1 parent 539b542 commit 5d4f437
Show file tree
Hide file tree
Showing 7 changed files with 133 additions and 0 deletions.
1 change: 1 addition & 0 deletions config/extension.neon
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ rules:
- Rector\TypePerfect\Rules\NoParamTypeRemovalRule
- Rector\TypePerfect\Rules\NoArrayAccessOnObjectRule
- Rector\TypePerfect\Rules\NoIssetOnObjectRule
- Rector\TypePerfect\Rules\NoEmptyOnObjectRule

# turn on by the group name

Expand Down
13 changes: 13 additions & 0 deletions src/Rules/NoEmptyOnObjectRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\ArrayDimFetch;
use PhpParser\Node\Expr\Empty_;
use PhpParser\Node\Expr\Variable;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\Rule;
use PHPStan\Type\TypeCombinator;

/**
* @implements Rule<Empty_>
Expand Down Expand Up @@ -48,7 +50,18 @@ private function shouldSkipVariable(Expr $expr, Scope $scope): bool
return true;
}

if ($expr instanceof Variable) {
if ($expr->name instanceof Expr) {
return true;
}

if (! $scope->hasVariableType($expr->name)->yes()) {
return true;
}
}

$varType = $scope->getType($expr);
$varType = TypeCombinator::removeNull($varType);
return $varType->getObjectClassNames() === [];
}
}
23 changes: 23 additions & 0 deletions tests/Rules/NoEmptyOnObjectRule/Fixture/EmptyOnObject.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

declare(strict_types=1);

namespace Rector\TypePerfect\Tests\Rules\NoEmptyOnObjectRule\Fixture;

use stdClass;

final class EmptyOnObject
{
public function run()
{
$object = null;

if (mt_rand(0, 100)) {
$object = new stdClass();
}

if (!empty($object)) {
return $object;
}
}
}
15 changes: 15 additions & 0 deletions tests/Rules/NoEmptyOnObjectRule/Fixture/SkipEmptyOnArray.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

declare(strict_types=1);

namespace Rector\TypePerfect\Tests\Rules\NoEmptyOnObjectRule\Fixture;

final class SkipEmptyOnArray
{
public function run(array $values)
{
if (!empty($values[9])) {
return $values[9];
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

declare(strict_types=1);

namespace Rector\TypePerfect\Tests\Rules\NoEmptyOnObjectRule\Fixture;

use PhpParser\Node\Expr\MethodCall;

final class SkipEmptyOnArrayNestedOnObject
{
public function run(MethodCall $methodCall)
{
if (!empty($methodCall->args[9])) {
return $methodCall->args[9];
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

declare(strict_types=1);

namespace Rector\TypePerfect\Tests\Rules\NoIssetOnObjectRule\Fixture;

final class SkipPossibleUndefinedVariable
{
public function run(bool $condition)
{
if ($condition) {
$object = new \stdClass();
}

if (!empty($object)) {
$object->foo = 'bar';
}
}
}
45 changes: 45 additions & 0 deletions tests/Rules/NoEmptyOnObjectRule/NoEmptyOnObjectRuleTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php

declare(strict_types=1);

namespace Rector\TypePerfect\Tests\Rules\NoEmptyOnObjectRule;

use Iterator;
use PHPStan\Rules\Rule;
use PHPStan\Testing\RuleTestCase;
use PHPUnit\Framework\Attributes\DataProvider;
use Rector\TypePerfect\Rules\NoEmptyOnObjectRule;

final class NoEmptyOnObjectRuleTest extends RuleTestCase
{
/**
* @param mixed[] $expectedErrorMessagesWithLines
*/
#[DataProvider('provideData')]
public function testRule(string $filePath, array $expectedErrorMessagesWithLines): void
{
$this->analyse([$filePath], $expectedErrorMessagesWithLines);
}

public static function provideData(): Iterator
{
yield [__DIR__ . '/Fixture/EmptyOnObject.php', [[NoEmptyOnObjectRule::ERROR_MESSAGE, 19]]];

yield [__DIR__ . '/Fixture/SkipEmptyOnArray.php', []];
yield [__DIR__ . '/Fixture/SkipEmptyOnArrayNestedOnObject.php', []];
yield [__DIR__ . '/Fixture/SkipPossibleUndefinedVariable.php', []];
}

/**
* @return string[]
*/
public static function getAdditionalConfigFiles(): array
{
return [__DIR__ . '/../../../config/extension.neon'];
}

protected function getRule(): Rule
{
return self::getContainer()->getByType(NoEmptyOnObjectRule::class);
}
}

0 comments on commit 5d4f437

Please sign in to comment.