Skip to content
Merged
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
1 change: 1 addition & 0 deletions config/set/coding-style/coding-style.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,4 @@ services:

Rector\CodingStyle\Rector\ClassConst\VarConstantCommentRector: ~
Rector\CodingStyle\Rector\Encapsed\EncapsedStringsToSprintfRector: ~
Rector\CodingStyle\Rector\ClassMethod\NewlineBeforeNewAssignSetRector: ~
Original file line number Diff line number Diff line change
@@ -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;
}
}
Original file line number Diff line number Diff line change
@@ -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);
}
}

?>
Original file line number Diff line number Diff line change
@@ -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;
}
}
28 changes: 27 additions & 1 deletion src/PhpParser/Printer/BetterStandardPrinter.php
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,19 @@ public function pArray(
// 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');
}

/**
Expand Down Expand Up @@ -196,4 +208,18 @@ protected function pStmt_Class(Class_ $class): string

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;
}
}