Skip to content
Draft
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
72 changes: 72 additions & 0 deletions src/Rector/Laravel/DisallowedLegacyCollectionArraySyntaxRector.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?php

declare(strict_types=1);

namespace Worksome\CodingStyle\Rector\Laravel;

use PhpParser\Comment\Doc;
use PhpParser\Node;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Property;
use Rector\Rector\AbstractRector;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;

class DisallowedLegacyCollectionArraySyntaxRector extends AbstractRector
{
public function getRuleDefinition(): RuleDefinition
{
return new RuleDefinition(
'PHPDoc `Collection` types must not use the legacy array syntax.',
[
new CodeSample(
<<<PHP
/** @property Collection|Model[] \$models */
class MyClass {}
PHP,
<<<PHP
/** @property Collection<int, Model> \$models */
class MyClass {}
PHP,
),
]
);
}

/** {@inheritdoc} */
public function getNodeTypes(): array
{
return [Property::class, ClassMethod::class, Class_::class];
}

/** {@inheritdoc} */
public function refactor(Node $node): Node|null
{
$docComment = $node->getDocComment();

if (null === $docComment) {
return null;
}

$originalText = $docComment->getText();
$transformedText = $this->transformDocComment($originalText);

if ($originalText === $transformedText) {
return null;
}

$node->setDocComment(new Doc($transformedText));

return $node;
}

protected function transformDocComment(string $docComment): string
{
return preg_replace(
pattern: '#(\\\\?(?:Illuminate\\\\Database\\\\Eloquent\\\\)?Collection)\|([^\s\[\]]+)\[]#',
replacement: '$1<int, $2>',
subject: $docComment
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

it('can replace disallowed Collection syntax', function () {
$this->doTestFile(
__DIR__ . '/Fixture/class_with_disallowed_collection_syntax.php.inc'
);
});

it('does not replace allowed Collection syntax', function () {
$this->doTestFile(
__DIR__ . '/Fixture/class_with_allowed_collection_syntax.php.inc'
);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

namespace Worksome\CodingStyle\Tests\Rector\DisallowedAttributesRector\Fixture;

use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;

/** @property Collection<int, Model> $models */
class ClassWithAllowedCollectionSyntax {}

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

namespace Worksome\CodingStyle\Tests\Rector\DisallowedAttributesRector\Fixture;

use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Collection as EloquentCollection;
use Illuminate\Database\Eloquent\Model;

/**
* @property Collection<int, Model> $models_valid (ensures valid syntax is not touched)
* @property Collection|Model[] $models_invalid_a
* @property \Illuminate\Database\Eloquent\Collection|Model[] $models_invalid_b
* @property EloquentCollection|Model[] $models_invalid_c
*/
class ClassWithAllowedCollectionSyntax {}

?>
-----
<?php

namespace Worksome\CodingStyle\Tests\Rector\DisallowedAttributesRector\Fixture;

use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Collection as EloquentCollection;
use Illuminate\Database\Eloquent\Model;

/**
* @property Collection<int, Model> $models_valid (ensures valid syntax is not touched)
* @property Collection<int, Model> $models_invalid_a
* @property \Illuminate\Database\Eloquent\Collection<int, Model> $models_invalid_b
* @property EloquentCollection<int, Model> $models_invalid_c
*/
class ClassWithAllowedCollectionSyntax {}

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

declare(strict_types=1);

use Rector\Config\RectorConfig;
use Worksome\CodingStyle\Rector\Laravel\DisallowedLegacyCollectionArraySyntaxRector;

return static function (RectorConfig $rectorConfig): void {
$rectorConfig
->rule(DisallowedLegacyCollectionArraySyntaxRector::class);
};