mirror of
https://github.com/rectorphp/rector.git
synced 2024-06-01 08:50:50 +00:00
[CS] Fix dynamic and broken indent detection, allow to configure spacing via RectorConfig::indent() method (#2442)
This commit is contained in:
parent
1c64bb1fb0
commit
38a9718b52
|
@ -64,6 +64,7 @@ return static function (RectorConfig $rectorConfig): void {
|
|||
|
||||
$rectorConfig->disableImportNames();
|
||||
$rectorConfig->importShortClasses();
|
||||
$rectorConfig->indent(' ', 4);
|
||||
|
||||
$rectorConfig->fileExtensions(['php']);
|
||||
$rectorConfig->nestedChainMethodCallLimit(60);
|
||||
|
|
|
@ -72,8 +72,12 @@ final class ClassAnnotationMatcher
|
|||
/**
|
||||
* @param Use_[]|GroupUse[] $uses
|
||||
*/
|
||||
private function resolveFullyQualifiedClass(array $uses, Node $node, string $tag, bool $returnNullOnUnknownClass): ?string
|
||||
{
|
||||
private function resolveFullyQualifiedClass(
|
||||
array $uses,
|
||||
Node $node,
|
||||
string $tag,
|
||||
bool $returnNullOnUnknownClass
|
||||
): ?string {
|
||||
$scope = $node->getAttribute(AttributeKey::SCOPE);
|
||||
|
||||
if ($scope instanceof Scope) {
|
||||
|
@ -88,7 +92,7 @@ final class ClassAnnotationMatcher
|
|||
return $this->resolveAsAliased($uses, $tag, $returnNullOnUnknownClass);
|
||||
}
|
||||
|
||||
if (str_starts_with($tag, '\\') && $this->reflectionProvider->hasClass($tag)) {
|
||||
if ($this->isPreslashedExistingClass($tag)) {
|
||||
// Global or absolute Class
|
||||
return $tag;
|
||||
}
|
||||
|
@ -127,10 +131,20 @@ final class ClassAnnotationMatcher
|
|||
|
||||
private function resolveClass(?string $class, bool $returnNullOnUnknownClass): ?string
|
||||
{
|
||||
if (null === $class) {
|
||||
if ($class === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$resolvedClass = $this->reflectionProvider->hasClass($class) ? $class : null;
|
||||
return $returnNullOnUnknownClass ? $resolvedClass : $class;
|
||||
}
|
||||
|
||||
private function isPreslashedExistingClass(string $tag): bool
|
||||
{
|
||||
if (! str_starts_with($tag, '\\')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->reflectionProvider->hasClass($tag);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -230,4 +230,14 @@ final class RectorConfig extends ContainerConfigurator
|
|||
$parameters = $this->parameters();
|
||||
$parameters->set(Option::CACHE_CLASS, $cacheClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see https://github.com/nikic/PHP-Parser/issues/723#issuecomment-712401963
|
||||
*/
|
||||
public function indent(string $character, int $count): void
|
||||
{
|
||||
$parameters = $this->parameters();
|
||||
$parameters->set(Option::INDENT_CHAR, $character);
|
||||
$parameters->set(Option::INDENT_SIZE, $count);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,14 +4,14 @@ namespace Rector\Tests\DeadCode\Rector\MethodCall\RemoveEmptyMethodCallRector\Fi
|
|||
|
||||
final class FixtureRemoveMethodCallOnThis
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
$this->validateLineLengths();
|
||||
}
|
||||
public function __construct()
|
||||
{
|
||||
$this->validateLineLengths();
|
||||
}
|
||||
|
||||
protected function validateLineLengths(): void
|
||||
{
|
||||
}
|
||||
protected function validateLineLengths(): void
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
|
@ -22,13 +22,13 @@ namespace Rector\Tests\DeadCode\Rector\MethodCall\RemoveEmptyMethodCallRector\Fi
|
|||
|
||||
final class FixtureRemoveMethodCallOnThis
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
protected function validateLineLengths(): void
|
||||
{
|
||||
}
|
||||
protected function validateLineLengths(): void
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
|
|
|
@ -4,17 +4,17 @@ namespace Rector\Tests\DeadCode\Rector\MethodCall\RemoveEmptyMethodCallRector\Fi
|
|||
|
||||
abstract class Validator
|
||||
{
|
||||
protected function validateLineLengths(): void
|
||||
{
|
||||
}
|
||||
protected function validateLineLengths(): void
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
final class GeneratorStubUseAbstract extends Validator
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
$this->validateLineLengths();
|
||||
}
|
||||
public function __construct()
|
||||
{
|
||||
$this->validateLineLengths();
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
|
@ -25,16 +25,16 @@ namespace Rector\Tests\DeadCode\Rector\MethodCall\RemoveEmptyMethodCallRector\Fi
|
|||
|
||||
abstract class Validator
|
||||
{
|
||||
protected function validateLineLengths(): void
|
||||
{
|
||||
}
|
||||
protected function validateLineLengths(): void
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
final class GeneratorStubUseAbstract extends Validator
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
|
|
|
@ -9,23 +9,23 @@ class Z {}
|
|||
|
||||
final class CopyDoc
|
||||
{
|
||||
public Y $y;
|
||||
public Y $y;
|
||||
|
||||
/**
|
||||
* @var Z[]
|
||||
* @Assert\Valid()
|
||||
* @Assert\NotBlank()
|
||||
*/
|
||||
public array $z = [];
|
||||
/**
|
||||
* @var Z[]
|
||||
* @Assert\Valid()
|
||||
* @Assert\NotBlank()
|
||||
*/
|
||||
public array $z = [];
|
||||
|
||||
/**
|
||||
* @param Z[] $z
|
||||
*/
|
||||
public function __construct(Y $y, array $z = [])
|
||||
{
|
||||
$this->y = $y;
|
||||
$this->z = $z;
|
||||
}
|
||||
/**
|
||||
* @param Z[] $z
|
||||
*/
|
||||
public function __construct(Y $y, array $z = [])
|
||||
{
|
||||
$this->y = $y;
|
||||
$this->z = $z;
|
||||
}
|
||||
}
|
||||
?>
|
||||
-----
|
||||
|
@ -40,18 +40,18 @@ class Z {}
|
|||
|
||||
final class CopyDoc
|
||||
{
|
||||
/**
|
||||
* @param Z[] $z
|
||||
*/
|
||||
public function __construct(
|
||||
public Y $y,
|
||||
/**
|
||||
* @Assert\Valid()
|
||||
* @Assert\NotBlank()
|
||||
*/
|
||||
public array $z = []
|
||||
)
|
||||
{
|
||||
}
|
||||
/**
|
||||
* @param Z[] $z
|
||||
*/
|
||||
public function __construct(
|
||||
public Y $y,
|
||||
/**
|
||||
* @Assert\Valid()
|
||||
* @Assert\NotBlank()
|
||||
*/
|
||||
public array $z = []
|
||||
)
|
||||
{
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
|
|
@ -7,18 +7,18 @@ namespace Rector\Tests\Php80\Rector\Class_\ClassPropertyAssignToConstructorPromo
|
|||
*/
|
||||
final class Generic
|
||||
{
|
||||
/**
|
||||
* @var T
|
||||
*/
|
||||
public mixed $value;
|
||||
/**
|
||||
* @var T
|
||||
*/
|
||||
public mixed $value;
|
||||
|
||||
/**
|
||||
* @param T $value
|
||||
*/
|
||||
public function __construct(mixed $value)
|
||||
{
|
||||
$this->value = $value;
|
||||
}
|
||||
/**
|
||||
* @param T $value
|
||||
*/
|
||||
public function __construct(mixed $value)
|
||||
{
|
||||
$this->value = $value;
|
||||
}
|
||||
}
|
||||
?>
|
||||
-----
|
||||
|
@ -31,11 +31,11 @@ namespace Rector\Tests\Php80\Rector\Class_\ClassPropertyAssignToConstructorPromo
|
|||
*/
|
||||
final class Generic
|
||||
{
|
||||
/**
|
||||
* @param T $value
|
||||
*/
|
||||
public function __construct(public mixed $value)
|
||||
{
|
||||
}
|
||||
/**
|
||||
* @param T $value
|
||||
*/
|
||||
public function __construct(public mixed $value)
|
||||
{
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
|
|
@ -4,18 +4,18 @@ namespace Rector\Tests\Php80\Rector\Class_\ClassPropertyAssignToConstructorPromo
|
|||
|
||||
class IterableTyped
|
||||
{
|
||||
/**
|
||||
* @var iterable<string>
|
||||
*/
|
||||
private iterable $property;
|
||||
/**
|
||||
* @var iterable<string>
|
||||
*/
|
||||
private iterable $property;
|
||||
|
||||
/**
|
||||
* @param iterable<string> $property
|
||||
*/
|
||||
public function __construct(iterable $property)
|
||||
{
|
||||
$this->property = $property;
|
||||
}
|
||||
/**
|
||||
* @param iterable<string> $property
|
||||
*/
|
||||
public function __construct(iterable $property)
|
||||
{
|
||||
$this->property = $property;
|
||||
}
|
||||
}
|
||||
?>
|
||||
-----
|
||||
|
@ -25,11 +25,11 @@ namespace Rector\Tests\Php80\Rector\Class_\ClassPropertyAssignToConstructorPromo
|
|||
|
||||
class IterableTyped
|
||||
{
|
||||
/**
|
||||
* @param iterable<string> $property
|
||||
*/
|
||||
public function __construct(private iterable $property)
|
||||
{
|
||||
}
|
||||
/**
|
||||
* @param iterable<string> $property
|
||||
*/
|
||||
public function __construct(private iterable $property)
|
||||
{
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
|
|
@ -10,20 +10,20 @@ class Z {}
|
|||
|
||||
final class UnionFullyQualified
|
||||
{
|
||||
public Y $y;
|
||||
public Y $y;
|
||||
|
||||
public Z $z;
|
||||
public Z $z;
|
||||
|
||||
public function __construct(Y $y, Z $z)
|
||||
{
|
||||
$this->y = $y;
|
||||
$this->z = $z;
|
||||
}
|
||||
public function __construct(Y $y, Z $z)
|
||||
{
|
||||
$this->y = $y;
|
||||
$this->z = $z;
|
||||
}
|
||||
|
||||
public function getX(): X
|
||||
{
|
||||
return $this->y;
|
||||
}
|
||||
public function getX(): X
|
||||
{
|
||||
return $this->y;
|
||||
}
|
||||
}
|
||||
?>
|
||||
-----
|
||||
|
@ -39,13 +39,13 @@ class Z {}
|
|||
|
||||
final class UnionFullyQualified
|
||||
{
|
||||
public function __construct(public Y $y, public Z $z)
|
||||
{
|
||||
}
|
||||
public function __construct(public Y $y, public Z $z)
|
||||
{
|
||||
}
|
||||
|
||||
public function getX(): X
|
||||
{
|
||||
return $this->y;
|
||||
}
|
||||
public function getX(): X
|
||||
{
|
||||
return $this->y;
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
|
|
@ -7,12 +7,12 @@ use DateTime;
|
|||
|
||||
final class UnionTyped
|
||||
{
|
||||
public stdClass|DateTime $property;
|
||||
public stdClass|DateTime $property;
|
||||
|
||||
public function __construct(stdClass|DateTime $property)
|
||||
{
|
||||
$this->property = $property;
|
||||
}
|
||||
public function __construct(stdClass|DateTime $property)
|
||||
{
|
||||
$this->property = $property;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
|
@ -26,9 +26,9 @@ use DateTime;
|
|||
|
||||
final class UnionTyped
|
||||
{
|
||||
public function __construct(public stdClass|DateTime $property)
|
||||
{
|
||||
}
|
||||
public function __construct(public stdClass|DateTime $property)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
|
|
|
@ -222,4 +222,16 @@ final class Option
|
|||
* @var string
|
||||
*/
|
||||
public const MEMORY_LIMIT = 'memory-limit';
|
||||
|
||||
/**
|
||||
* @deprecated Use @see \Rector\Config\RectorConfig::indent() method
|
||||
* @var string
|
||||
*/
|
||||
public const INDENT_CHAR = 'indent-char';
|
||||
|
||||
/**
|
||||
* @deprecated Use @see \Rector\Config\RectorConfig::indent() method
|
||||
* @var string
|
||||
*/
|
||||
public const INDENT_SIZE = 'indent-size';
|
||||
}
|
||||
|
|
|
@ -31,4 +31,14 @@ final class RectorConfigProvider
|
|||
{
|
||||
return $this->parameterProvider->provideStringParameter(Option::SYMFONY_CONTAINER_XML_PATH_PARAMETER);
|
||||
}
|
||||
|
||||
public function getIndentChar(): string
|
||||
{
|
||||
return $this->parameterProvider->provideStringParameter(Option::INDENT_CHAR);
|
||||
}
|
||||
|
||||
public function getIndentSize(): int
|
||||
{
|
||||
return $this->parameterProvider->provideIntParameter(Option::INDENT_SIZE);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,9 +27,9 @@ use PhpParser\Node\Stmt\TraitUse;
|
|||
use PhpParser\Node\Stmt\Use_;
|
||||
use PhpParser\PrettyPrinter\Standard;
|
||||
use Rector\Comments\NodeDocBlock\DocBlockUpdater;
|
||||
use Rector\Core\Configuration\RectorConfigProvider;
|
||||
use Rector\Core\Contract\PhpParser\NodePrinterInterface;
|
||||
use Rector\Core\PhpParser\Node\CustomNode\FileWithoutNamespace;
|
||||
use Rector\Core\PhpParser\Printer\Whitespace\IndentCharacterDetector;
|
||||
use Rector\Core\Util\StringUtils;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
|
||||
|
@ -80,8 +80,8 @@ final class BetterStandardPrinter extends Standard implements NodePrinterInterfa
|
|||
* @param mixed[] $options
|
||||
*/
|
||||
public function __construct(
|
||||
private readonly IndentCharacterDetector $indentCharacterDetector,
|
||||
private readonly DocBlockUpdater $docBlockUpdater,
|
||||
private readonly RectorConfigProvider $rectorConfigProvider,
|
||||
array $options = []
|
||||
) {
|
||||
parent::__construct($options);
|
||||
|
@ -103,8 +103,7 @@ final class BetterStandardPrinter extends Standard implements NodePrinterInterfa
|
|||
{
|
||||
$newStmts = $this->resolveNewStmts($stmts);
|
||||
|
||||
// detect per print
|
||||
$this->tabOrSpaceIndentCharacter = $this->indentCharacterDetector->detect($origTokens);
|
||||
$this->tabOrSpaceIndentCharacter = $this->rectorConfigProvider->getIndentChar();
|
||||
|
||||
$content = parent::printFormatPreserving($newStmts, $origStmts, $origTokens);
|
||||
|
||||
|
|
|
@ -1,34 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Core\PhpParser\Printer\Whitespace;
|
||||
|
||||
use Nette\Utils\Strings;
|
||||
|
||||
final class IndentCharacterDetector
|
||||
{
|
||||
/**
|
||||
* Solves https://github.com/rectorphp/rector/issues/1964
|
||||
*
|
||||
* Some files have spaces, some have tabs. Keep the original indent if possible.
|
||||
*
|
||||
* @param mixed[] $tokens
|
||||
*/
|
||||
public function detect(array $tokens): string
|
||||
{
|
||||
foreach ($tokens as $token) {
|
||||
if ($token[0] === T_WHITESPACE) {
|
||||
$tokenContent = $token[1];
|
||||
|
||||
$tabMatches = Strings::matchAll($tokenContent, '#^\t#m');
|
||||
if ($tabMatches !== []) {
|
||||
return "\t";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// use space by default
|
||||
return ' ';
|
||||
}
|
||||
}
|
|
@ -1,12 +1,14 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Core\Tests\Issues\DoNotReplaceUnknownClasses;
|
||||
|
||||
use Iterator;
|
||||
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
|
||||
use Symplify\SmartFileSystem\SmartFileInfo;
|
||||
|
||||
class DoNotReplaceUnknownClassesTest extends AbstractRectorTestCase
|
||||
final class DoNotReplaceUnknownClassesTest extends AbstractRectorTestCase
|
||||
{
|
||||
/**
|
||||
* @dataProvider provideData()
|
||||
|
|
Loading…
Reference in New Issue
Block a user