[CodingStyle] Add NewlineBeforeNewAssignSetRector

This commit is contained in:
Tomas Votruba 2019-07-14 14:54:02 +02:00
parent 212ad921b2
commit 473460e1e5
5 changed files with 190 additions and 1 deletions

View File

@ -24,3 +24,4 @@ services:
Rector\CodingStyle\Rector\ClassConst\VarConstantCommentRector: ~
Rector\CodingStyle\Rector\Encapsed\EncapsedStringsToSprintfRector: ~
Rector\CodingStyle\Rector\ClassMethod\NewlineBeforeNewAssignSetRector: ~

View File

@ -0,0 +1,109 @@
<?php declare(strict_types=1);
namespace Rector\CodingStyle\Rector\ClassMethod;
use PhpParser\Node;
use PhpParser\Node\Expr\Assign;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Stmt\Expression;
use PhpParser\Node\Stmt\Nop;
use Rector\Rector\AbstractRector;
use Rector\RectorDefinition\CodeSample;
use Rector\RectorDefinition\RectorDefinition;
/**
* @see \Rector\CodingStyle\Tests\Rector\ClassMethod\NewlineBeforeNewAssignSetRector\NewlineBeforeNewAssignSetRectorTest
*/
final class NewlineBeforeNewAssignSetRector extends AbstractRector
{
public function getDefinition(): RectorDefinition
{
return new RectorDefinition('Add extra space before new assign set', [
new CodeSample(
<<<'CODE_SAMPLE'
final class SomeClass
{
public function run()
{
$value = new Value;
$value->setValue(5);
$value2 = new Value;
$value2->setValue(1);
}
}
CODE_SAMPLE
,
<<<'CODE_SAMPLE'
final class SomeClass
{
public function run()
{
$value = new Value;
$value->setValue(5);
$value2 = new Value;
$value2->setValue(1);
}
}
CODE_SAMPLE
),
]);
}
/**
* @return string[]
*/
public function getNodeTypes(): array
{
return [Node\Stmt\ClassMethod::class, Node\Stmt\Function_::class, Node\Expr\Closure::class];
}
/**
* @param Node\Stmt\ClassMethod|Node\Stmt\Function_|Node\Expr\Closure $node
*/
public function refactor(Node $node): ?Node
{
$previousStmtVariableName = null;
if ($node->stmts === null) {
return null;
}
foreach ($node->stmts as $key => $stmt) {
$currentStmtVariableName = null;
if ($stmt instanceof Expression) {
$stmt = $stmt->expr;
}
if ($stmt instanceof Assign || $stmt instanceof MethodCall) {
if ($stmt->var instanceof Variable) {
$currentStmtVariableName = $this->getName($stmt->var);
}
}
if ($this->isNewVariableThanBefore($previousStmtVariableName, $currentStmtVariableName)) {
// insert newline before
array_splice($node->stmts, $key, 0, [new Nop()]);
}
$previousStmtVariableName = $currentStmtVariableName;
}
return $node;
}
private function isNewVariableThanBefore(?string $previousStmtVariableName, ?string $currentStmtVariableName): bool
{
if ($previousStmtVariableName === null) {
return false;
}
if ($currentStmtVariableName === null) {
return false;
}
return $previousStmtVariableName !== $currentStmtVariableName;
}
}

View File

@ -0,0 +1,34 @@
<?php
namespace Rector\CodingStyle\Tests\Rector\ClassMethod\NewlineBeforeNewAssignSetRector\Fixture;
final class SomeClass
{
public function run()
{
$value = new Value;
$value->setValue(5);
$value2 = new Value;
$value2->setValue(1);
}
}
?>
-----
<?php
namespace Rector\CodingStyle\Tests\Rector\ClassMethod\NewlineBeforeNewAssignSetRector\Fixture;
final class SomeClass
{
public function run()
{
$value = new Value;
$value->setValue(5);
$value2 = new Value;
$value2->setValue(1);
}
}
?>

View File

@ -0,0 +1,19 @@
<?php declare(strict_types=1);
namespace Rector\CodingStyle\Tests\Rector\ClassMethod\NewlineBeforeNewAssignSetRector;
use Rector\CodingStyle\Rector\ClassMethod\NewlineBeforeNewAssignSetRector;
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
final class NewlineBeforeNewAssignSetRectorTest extends AbstractRectorTestCase
{
public function test(): void
{
$this->doTestFiles([__DIR__ . '/Fixture/fixture.php.inc']);
}
protected function getRectorClass(): string
{
return NewlineBeforeNewAssignSetRector::class;
}
}

View File

@ -84,7 +84,19 @@ final class BetterStandardPrinter extends Standard
// reindex positions for printer
$nodes = array_values($nodes);
return parent::pArray($nodes, $origNodes, $pos, $indentAdjustment, $parentNodeType, $subNodeName, $fixup);
$content = parent::pArray($nodes, $origNodes, $pos, $indentAdjustment, $parentNodeType, $subNodeName, $fixup);
if ($content === null) {
return $content;
}
if (! $this->containsNop($nodes)) {
return $content;
}
// remove extra spaces before new Nop_ nodes, @see https://regex101.com/r/iSvroO/1
return Strings::replace($content, '#^[ \t]+$#m');
return Strings::replace($content, '#^[ \t]+$#m');
}
/**
@ -196,4 +208,18 @@ final class BetterStandardPrinter extends Standard
return parent::pStmt_Class($class);
}
/**
* @param Node[] $nodes
*/
private function containsNop(array $nodes): bool
{
foreach ($nodes as $node) {
if ($node instanceof Node\Stmt\Nop) {
return true;
}
}
return false;
}
}