-
-
Notifications
You must be signed in to change notification settings - Fork 346
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[TypeDeclarations] Add IncreaseDeclareStrictTypesRector to raise leve…
…l of declare() coverage
- Loading branch information
1 parent
8281a06
commit e884c90
Showing
8 changed files
with
239 additions
and
20 deletions.
There are no files selected for viewing
9 changes: 9 additions & 0 deletions
9
...Interface/IncreaseDeclareStrictTypesRector/Fixture/skip_already_with_strict_types.php.inc
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,9 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Rector\Tests\TypeDeclaration\Rector\StmtsAwareInterface\DeclareStrictTypesRector\Fixture; | ||
|
||
function anotherFunction() | ||
{ | ||
} |
19 changes: 19 additions & 0 deletions
19
...on/Rector/StmtsAwareInterface/IncreaseDeclareStrictTypesRector/Fixture/some_class.php.inc
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,19 @@ | ||
<?php | ||
|
||
namespace Rector\Tests\TypeDeclaration\Rector\StmtsAwareInterface\DeclareStrictTypesRector\Fixture; | ||
|
||
function someFunction() | ||
{ | ||
} | ||
|
||
?> | ||
----- | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Rector\Tests\TypeDeclaration\Rector\StmtsAwareInterface\DeclareStrictTypesRector\Fixture; | ||
|
||
function someFunction() | ||
{ | ||
} |
28 changes: 28 additions & 0 deletions
28
...sAwareInterface/IncreaseDeclareStrictTypesRector/IncreaseDeclareStrictTypesRectorTest.php
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,28 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Rector\Tests\TypeDeclaration\Rector\StmtsAwareInterface\IncreaseDeclareStrictTypesRector; | ||
|
||
use Iterator; | ||
use PHPUnit\Framework\Attributes\DataProvider; | ||
use Rector\Testing\PHPUnit\AbstractRectorTestCase; | ||
|
||
final class IncreaseDeclareStrictTypesRectorTest 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'; | ||
} | ||
} |
9 changes: 9 additions & 0 deletions
9
...on/Rector/StmtsAwareInterface/IncreaseDeclareStrictTypesRector/config/configured_rule.php
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,9 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
use Rector\Config\RectorConfig; | ||
use Rector\TypeDeclaration\Rector\StmtsAwareInterface\IncreaseDeclareStrictTypesRector; | ||
|
||
return RectorConfig::configure() | ||
->withRules([IncreaseDeclareStrictTypesRector::class]); |
28 changes: 28 additions & 0 deletions
28
rules/TypeDeclaration/NodeAnalyzer/DeclareStrictTypeFinder.php
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,28 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Rector\TypeDeclaration\NodeAnalyzer; | ||
|
||
use PhpParser\Node\Stmt; | ||
use PhpParser\Node\Stmt\Declare_; | ||
|
||
final readonly class DeclareStrictTypeFinder | ||
{ | ||
public function hasDeclareStrictTypes(Stmt $stmt): bool | ||
{ | ||
// when first stmt is Declare_, verify if there is strict_types definition already, | ||
// as multiple declare is allowed, with declare(strict_types=1) only allowed on very first stmt | ||
if (! $stmt instanceof Declare_) { | ||
return false; | ||
} | ||
|
||
foreach ($stmt->declares as $declare) { | ||
if ($declare->key->toString() === 'strict_types') { | ||
return true; | ||
} | ||
} | ||
|
||
return false; | ||
} | ||
} |
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
135 changes: 135 additions & 0 deletions
135
rules/TypeDeclaration/Rector/StmtsAwareInterface/IncreaseDeclareStrictTypesRector.php
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,135 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Rector\TypeDeclaration\Rector\StmtsAwareInterface; | ||
|
||
use PhpParser\Node; | ||
use PhpParser\Node\Identifier; | ||
use PhpParser\Node\Scalar\LNumber; | ||
use PhpParser\Node\Stmt\Declare_; | ||
use PhpParser\Node\Stmt\DeclareDeclare; | ||
use PhpParser\Node\Stmt\Nop; | ||
use Rector\ChangesReporting\ValueObject\RectorWithLineChange; | ||
use Rector\Contract\PhpParser\Node\StmtsAwareInterface; | ||
use Rector\Contract\Rector\ConfigurableRectorInterface; | ||
use Rector\PhpParser\Node\CustomNode\FileWithoutNamespace; | ||
use Rector\Rector\AbstractRector; | ||
use Rector\TypeDeclaration\NodeAnalyzer\DeclareStrictTypeFinder; | ||
use Symplify\RuleDocGenerator\ValueObject\CodeSample\ConfiguredCodeSample; | ||
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; | ||
use Webmozart\Assert\Assert; | ||
|
||
/** | ||
* @see \Rector\Tests\TypeDeclaration\Rector\StmtsAwareInterface\IncreaseDeclareStrictTypesRector\IncreaseDeclareStrictTypesRectorTest | ||
*/ | ||
final class IncreaseDeclareStrictTypesRector extends AbstractRector implements ConfigurableRectorInterface | ||
{ | ||
private const LIMIT = 'limit'; | ||
|
||
private int $limit = 10; | ||
|
||
private int $changedItemCount = 0; | ||
|
||
private function __construct( | ||
private DeclareStrictTypeFinder $declareStrictTypeFinder | ||
) { | ||
} | ||
|
||
public function getRuleDefinition(): RuleDefinition | ||
{ | ||
return new RuleDefinition( | ||
'Add declare strict types to a limited amount of classes at a time, to try out in the wild and increase level gradually', | ||
[ | ||
new ConfiguredCodeSample( | ||
<<<'CODE_SAMPLE' | ||
function someFunction() | ||
{ | ||
} | ||
CODE_SAMPLE | ||
, | ||
<<<'CODE_SAMPLE' | ||
declare(strict_types=1); | ||
function someFunction() | ||
{ | ||
} | ||
CODE_SAMPLE | ||
, | ||
[ | ||
self::LIMIT => 10, | ||
], | ||
), | ||
] | ||
); | ||
} | ||
|
||
/** | ||
* @param Node[] $nodes | ||
* @return Node[]|null | ||
*/ | ||
public function beforeTraverse(array $nodes): ?array | ||
{ | ||
parent::beforeTraverse($nodes); | ||
|
||
$newStmts = $this->file->getNewStmts(); | ||
if ($newStmts === []) { | ||
return null; | ||
} | ||
|
||
$rootStmt = \current($newStmts); | ||
$stmt = $rootStmt; | ||
|
||
// skip classes without namespace for safety reasons | ||
if ($rootStmt instanceof FileWithoutNamespace) { | ||
return null; | ||
} | ||
|
||
if ($this->declareStrictTypeFinder->hasDeclareStrictTypes($stmt)) { | ||
return null; | ||
} | ||
|
||
// keep change withing a limit | ||
if ($this->changedItemCount >= $this->limit) { | ||
return null; | ||
} | ||
|
||
++$this->changedItemCount; | ||
|
||
$strictTypesDeclare = $this->creteStrictTypesDeclare(); | ||
|
||
$rectorWithLineChange = new RectorWithLineChange(self::class, $stmt->getLine()); | ||
$this->file->addRectorClassWithLine($rectorWithLineChange); | ||
|
||
return \array_merge([$strictTypesDeclare, new Nop()], $nodes); | ||
} | ||
|
||
/** | ||
* @return array<class-string<Node>> | ||
*/ | ||
public function getNodeTypes(): array | ||
{ | ||
return [StmtsAwareInterface::class]; | ||
} | ||
|
||
/** | ||
* @param StmtsAwareInterface $node | ||
*/ | ||
public function refactor(Node $node): ?Node | ||
{ | ||
// workaround, as Rector now only hooks to specific nodes, not arrays | ||
return null; | ||
} | ||
|
||
public function configure(array $configuration): void | ||
{ | ||
Assert::keyExists($configuration, self::LIMIT); | ||
$this->limit = (int) $configuration[self::LIMIT]; | ||
} | ||
|
||
private function creteStrictTypesDeclare(): Declare_ | ||
{ | ||
$declareDeclare = new DeclareDeclare(new Identifier('strict_types'), new LNumber(1)); | ||
return new Declare_([$declareDeclare]); | ||
} | ||
} |
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