Skip to content

Commit

Permalink
[TypeDeclaration] Add StrictArrayParamDimFetchRector (#4384)
Browse files Browse the repository at this point in the history
  • Loading branch information
TomasVotruba committed Jun 30, 2023
1 parent 205df90 commit 8324cf4
Show file tree
Hide file tree
Showing 8 changed files with 222 additions and 2 deletions.
23 changes: 21 additions & 2 deletions build/target-repository/docs/rector_rules_overview.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# 369 Rules Overview
# 370 Rules Overview

<br>

Expand Down Expand Up @@ -54,7 +54,7 @@

- [Transform](#transform) (22)

- [TypeDeclaration](#typedeclaration) (41)
- [TypeDeclaration](#typedeclaration) (42)

- [Visibility](#visibility) (3)

Expand Down Expand Up @@ -8368,6 +8368,25 @@ Add return method return type based on strict typed property

<br>

### StrictArrayParamDimFetchRector

Add array type based on array dim fetch use

- class: [`Rector\TypeDeclaration\Rector\ClassMethod\StrictArrayParamDimFetchRector`](../rules/TypeDeclaration/Rector/ClassMethod/StrictArrayParamDimFetchRector.php)

```diff
class SomeClass
{
- public function resolve($item)
+ public function resolve(array $item)
{
return $item['name'];
}
}
```

<br>

### TypedPropertyFromAssignsRector

Add typed property from assigned types
Expand Down
2 changes: 2 additions & 0 deletions config/set/type-declaration.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
use Rector\TypeDeclaration\Rector\ClassMethod\ReturnTypeFromStrictNewArrayRector;
use Rector\TypeDeclaration\Rector\ClassMethod\ReturnTypeFromStrictTypedCallRector;
use Rector\TypeDeclaration\Rector\ClassMethod\ReturnTypeFromStrictTypedPropertyRector;
use Rector\TypeDeclaration\Rector\ClassMethod\StrictArrayParamDimFetchRector;
use Rector\TypeDeclaration\Rector\Closure\AddClosureReturnTypeRector;
use Rector\TypeDeclaration\Rector\Empty_\EmptyOnNullableObjectToInstanceOfRector;
use Rector\TypeDeclaration\Rector\FunctionLike\AddParamTypeSplFixedArrayRector;
Expand Down Expand Up @@ -76,5 +77,6 @@
ReturnTypeFromStrictTernaryRector::class,
BoolReturnTypeFromStrictScalarReturnsRector::class,
NumericReturnTypeFromStrictScalarReturnsRector::class,
StrictArrayParamDimFetchRector::class,
]);
};
1 change: 1 addition & 0 deletions packages/Config/RectorConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ public function rule(string $rectorClass): void
public function rules(array $rectorClasses): void
{
Assert::allString($rectorClasses);
Assert::uniqueValues($rectorClasses);

foreach ($rectorClasses as $rectorClass) {
$this->rule($rectorClass);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\StrictArrayParamDimFetchRector\Fixture;

final class SkipBehindIsArray
{
public function resolve($item)
{
if (is_array($item)) {
return $item['name'];
}

return $item;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\StrictArrayParamDimFetchRector\Fixture;

class SomeClass
{
public function resolve($item)
{
return $item['name'];
}
}

?>
-----
<?php

namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\StrictArrayParamDimFetchRector\Fixture;

class SomeClass
{
public function resolve(array $item)
{
return $item['name'];
}
}

?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

declare(strict_types=1);

namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\StrictArrayParamDimFetchRector;

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

final class StrictArrayParamDimFetchRectorTest extends AbstractRectorTestCase
{
#[DataProvider('provideData')]
public function test(string $filePath): void
{
$this->doTestFile($filePath);
}

public static function provideData(): Iterator
{
return self::yieldFilesFromDirectory(__DIR__ . '/Fixture');
}

public function provideConfigFilePath(): string
{
return __DIR__ . '/config/configured_rule.php';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

declare(strict_types=1);

use Rector\Config\RectorConfig;
use Rector\TypeDeclaration\Rector\ClassMethod\StrictArrayParamDimFetchRector;

return static function (RectorConfig $rectorConfig): void {
$rectorConfig->rule(StrictArrayParamDimFetchRector::class);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
<?php

declare(strict_types=1);

namespace Rector\TypeDeclaration\Rector\ClassMethod;

use PhpParser\Node;
use PhpParser\Node\Expr\ArrayDimFetch;
use PhpParser\Node\Expr\FuncCall;
use PhpParser\Node\Identifier;
use PhpParser\Node\Param;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Function_;
use PhpParser\NodeTraverser;
use Rector\Core\Rector\AbstractRector;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;

/**
* @see \Rector\Tests\TypeDeclaration\Rector\ClassMethod\StrictArrayParamDimFetchRector\StrictArrayParamDimFetchRectorTest
*/
final class StrictArrayParamDimFetchRector extends AbstractRector
{
public function getRuleDefinition(): RuleDefinition
{
return new RuleDefinition('Add array type based on array dim fetch use', [
new CodeSample(
<<<'CODE_SAMPLE'
class SomeClass
{
public function resolve($item)
{
return $item['name'];
}
}
CODE_SAMPLE

,
<<<'CODE_SAMPLE'
class SomeClass
{
public function resolve(array $item)
{
return $item['name'];
}
}
CODE_SAMPLE
),
]);
}

/**
* @return array<class-string<Node>>
*/
public function getNodeTypes(): array
{
return [ClassMethod::class, Function_::class];
}

/**
* @param ClassMethod|Function_ $node
*/
public function refactor(Node $node): ?Node
{
$hasChanged = false;

foreach ($node->getParams() as $param) {
if ($param->type instanceof Node) {
continue;
}

if (! $this->isParamAccessedArrayDimFetch($param, $node)) {
continue;
}

$param->type = new Identifier('array');
$hasChanged = true;
}

if ($hasChanged) {
return $node;
}

return null;
}

private function isParamAccessedArrayDimFetch(Param $param, ClassMethod|Function_ $functionLike): bool
{
$paramName = $this->getName($param);

$isParamAccessedArrayDimFetch = false;

$this->traverseNodesWithCallable($functionLike, function (Node $node) use (
$paramName,
&$isParamAccessedArrayDimFetch
): int|null {
if ($node instanceof FuncCall && $this->isName($node, 'is_array')) {
$firstArg = $node->getArgs()[0];
if ($this->isName($firstArg->value, $paramName)) {
return NodeTraverser::STOP_TRAVERSAL;
}
}

if (! $node instanceof ArrayDimFetch) {
return null;
}

if (! $this->isName($node->var, $paramName)) {
return null;
}

$isParamAccessedArrayDimFetch = true;
return null;
});

return $isParamAccessedArrayDimFetch;
}
}

0 comments on commit 8324cf4

Please sign in to comment.