Take tabs indent into account

This commit is contained in:
Tomas Votruba 2019-09-25 11:00:21 +02:00
parent b56cd04af1
commit 97d9f0de91
7 changed files with 98 additions and 6 deletions

View File

@ -5,7 +5,7 @@ services:
Rector\BetterPhpDocParser\:
resource: '../src'
exclude: '../src/{HttpKernel,Data,*/*Info.php,*Info.php,Attributes/Ast/PhpDoc/*,Ast/PhpDoc/*}'
exclude: '../src/{HttpKernel,ValueObject/*,*/*Info.php,*Info.php,Attributes/Ast/PhpDoc/*,Ast/PhpDoc/*}'
PHPStan\PhpDocParser\Lexer\Lexer: ~
PHPStan\PhpDocParser\Parser\TypeParser: ~

View File

@ -20,8 +20,8 @@ use Rector\BetterPhpDocParser\Attributes\Ast\PhpDoc\AttributeAwareParamTagValueN
use Rector\BetterPhpDocParser\Attributes\Ast\PhpDoc\AttributeAwarePhpDocNode;
use Rector\BetterPhpDocParser\Attributes\Attribute\Attribute;
use Rector\BetterPhpDocParser\Contract\PhpDocParserExtensionInterface;
use Rector\BetterPhpDocParser\Data\StartEndInfo;
use Rector\BetterPhpDocParser\Printer\MultilineSpaceFormatPreserver;
use Rector\BetterPhpDocParser\ValueObject\StartEndInfo;
use Symplify\PackageBuilder\Reflection\PrivatesAccessor;
use Symplify\PackageBuilder\Reflection\PrivatesCaller;

View File

@ -6,7 +6,7 @@ use Nette\Utils\Arrays;
use Nette\Utils\Strings;
use PHPStan\PhpDocParser\Ast\Node;
use PHPStan\PhpDocParser\Lexer\Lexer;
use Rector\BetterPhpDocParser\Data\StartEndInfo;
use Rector\BetterPhpDocParser\ValueObject\StartEndInfo;
use Rector\DoctrinePhpDocParser\Contract\Ast\PhpDoc\DoctrineTagNodeInterface;
final class OriginalSpacingRestorer

View File

@ -11,8 +11,8 @@ use PHPStan\PhpDocParser\Lexer\Lexer;
use Rector\BetterPhpDocParser\Attributes\Ast\PhpDoc\AttributeAwarePhpDocNode;
use Rector\BetterPhpDocParser\Attributes\Attribute\Attribute;
use Rector\BetterPhpDocParser\Attributes\Contract\Ast\AttributeAwareNodeInterface;
use Rector\BetterPhpDocParser\Data\StartEndInfo;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
use Rector\BetterPhpDocParser\ValueObject\StartEndInfo;
/**
* @see \Rector\BetterPhpDocParser\Tests\PhpDocInfo\PhpDocInfoPrinter\PhpDocInfoPrinterTest

View File

@ -1,6 +1,6 @@
<?php declare(strict_types=1);
namespace Rector\BetterPhpDocParser\Data;
namespace Rector\BetterPhpDocParser\ValueObject;
final class StartEndInfo
{

View File

@ -54,7 +54,7 @@ final class PhpDocClassRenamer
$this->procesDoctrineRelationTagValueNode($oldToNewClasses, $phpDocInfo);
$this->processSerializerTypeTagValueNode($oldToNewClasses, $phpDocInfo);
if ($this->shouldUpdate === null) {
if ($this->shouldUpdate === false) {
return;
}

View File

@ -10,6 +10,7 @@ use PhpParser\Node\Expr\Yield_;
use PhpParser\Node\Scalar\DNumber;
use PhpParser\Node\Scalar\EncapsedStringPart;
use PhpParser\Node\Scalar\String_;
use PhpParser\Node\Stmt;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Declare_;
@ -18,12 +19,19 @@ use PhpParser\Node\Stmt\Nop;
use PhpParser\Node\Stmt\TraitUse;
use PhpParser\PrettyPrinter\Standard;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Symplify\PackageBuilder\FileSystem\SmartFileInfo;
/**
* @see \Rector\Tests\PhpParser\Printer\BetterStandardPrinterTest
*/
final class BetterStandardPrinter extends Standard
{
/**
* Use space by default
* @var string
*/
private $tabOrSpaceIndentCharacter = ' ';
/**
* @param mixed[] $options
*/
@ -38,6 +46,14 @@ final class BetterStandardPrinter extends Standard
$this->insertionMap['Expr_Closure->returnType'] = [')', false, ': ', null];
}
public function printFormatPreserving(array $stmts, array $origStmts, array $origTokens): string
{
// detect per print
$this->detectTabOrSpaceIndentCharacter($stmts);
return parent::printFormatPreserving($stmts, $origStmts, $origTokens);
}
/**
* @param Node|Node[]|null $node
*/
@ -73,6 +89,50 @@ final class BetterStandardPrinter extends Standard
return $this->print($firstNode) === $this->print($secondNode);
}
/**
* This allows to use both spaces and tabs vs. original space-only
*/
protected function setIndentLevel(int $level): void
{
$this->indentLevel = $level;
$this->nl = "\n" . str_repeat($this->tabOrSpaceIndentCharacter, $level);
}
/**
* This allows to use both spaces and tabs vs. original space-only
*/
protected function indent(): void
{
if ($this->tabOrSpaceIndentCharacter === ' ') {
// 4 spaces
$multiplier = 4;
} else {
// 1 tab
$multiplier = 1;
}
$this->indentLevel += $multiplier;
$this->nl .= str_repeat($this->tabOrSpaceIndentCharacter, $multiplier);
}
/**
* This allows to use both spaces and tabs vs. original space-only
*/
protected function outdent(): void
{
if ($this->tabOrSpaceIndentCharacter === ' ') {
// - 4 spaces
assert($this->indentLevel >= 4);
$this->indentLevel -= 4;
} else {
// - 1 tab
assert($this->indentLevel >= 1);
--$this->indentLevel;
}
$this->nl = "\n" . str_repeat($this->tabOrSpaceIndentCharacter, $this->indentLevel);
}
/**
* @param mixed[] $nodes
* @param mixed[] $origNodes
@ -249,4 +309,36 @@ final class BetterStandardPrinter extends Standard
return false;
}
/**
* Solves https://github.com/rectorphp/rector/issues/1964
*
* Some files have spaces, some have tabs. Keep the original indent if possible.
*
* @param Stmt[] $stmts
*/
private function detectTabOrSpaceIndentCharacter(array $stmts): void
{
// use space by default
$this->tabOrSpaceIndentCharacter = ' ';
foreach ($stmts as $stmt) {
if (! $stmt instanceof Node) {
continue;
}
/** @var SmartFileInfo|null $fileInfo */
$fileInfo = $stmt->getAttribute(AttributeKey::FILE_INFO);
if ($fileInfo === null) {
continue;
}
$whitespacesChars = Strings::matchAll($fileInfo->getContents(), '#^( |\t)#m');
foreach ($whitespacesChars as $whitespacesChar) {
// let the first win
$this->tabOrSpaceIndentCharacter = $whitespacesChar[0];
break;
}
}
}
}