Misc node printing improvements (#6034)

Co-authored-by: kaizen-ci <info@kaizen-ci.org>
This commit is contained in:
Tomas Votruba 2021-04-04 17:07:52 +02:00 committed by GitHub
parent 6fe05c462c
commit 74dc172b74
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 88 additions and 62 deletions

View File

@ -5,8 +5,8 @@ declare(strict_types=1);
use Rector\Core\Configuration\Option;
use Rector\Core\ValueObject\PhpVersion;
use Rector\DowngradePhp72\Rector\ClassMethod\DowngradeParameterTypeWideningRector;
use Rector\DowngradePhp72\Rector\FunctionLike\DowngradeObjectTypeDeclarationRector;
use Rector\DowngradePhp72\Rector\FuncCall\DowngradePregUnmatchedAsNullConstantRector;
use Rector\DowngradePhp72\Rector\FunctionLike\DowngradeObjectTypeDeclarationRector;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return static function (ContainerConfigurator $containerConfigurator): void {

View File

@ -5,7 +5,6 @@ declare(strict_types=1);
namespace Rector\BetterPhpDocParser\Printer;
use Nette\Utils\Strings;
use PHPStan\PhpDocParser\Ast\Node;
use PHPStan\PhpDocParser\Ast\PhpDoc\ParamTagValueNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocChildNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocNode;
@ -88,11 +87,6 @@ final class PhpDocInfoPrinter
*/
private $tokens = [];
/**
* @var StartAndEnd[]
*/
private $removedNodePositions = [];
/**
* @var PhpDocNode
*/
@ -113,10 +107,19 @@ final class PhpDocInfoPrinter
*/
private $docBlockInliner;
public function __construct(EmptyPhpDocDetector $emptyPhpDocDetector, DocBlockInliner $docBlockInliner)
{
/**
* @var RemoveNodesStartAndEndResolver
*/
private $removeNodesStartAndEndResolver;
public function __construct(
EmptyPhpDocDetector $emptyPhpDocDetector,
DocBlockInliner $docBlockInliner,
RemoveNodesStartAndEndResolver $removeNodesStartAndEndResolver
) {
$this->emptyPhpDocDetector = $emptyPhpDocDetector;
$this->docBlockInliner = $docBlockInliner;
$this->removeNodesStartAndEndResolver = $removeNodesStartAndEndResolver;
}
public function printNew(PhpDocInfo $phpDocInfo): string
@ -161,7 +164,6 @@ final class PhpDocInfoPrinter
$this->phpDocInfo = $phpDocInfo;
$this->currentTokenPosition = 0;
$this->removedNodePositions = [];
$phpDocString = $this->printPhpDocNode($this->phpDocNode);
$phpDocString = $this->removeExtraSpacesAfterAsterisk($phpDocString);
@ -303,8 +305,15 @@ final class PhpDocInfoPrinter
{
// skip removed nodes
$positionJumpSet = [];
foreach ($this->getRemovedNodesPositions() as $startAndEnd) {
$positionJumpSet[$startAndEnd->getStart()] = $startAndEnd->getEnd();
$removedStartAndEnds = $this->removeNodesStartAndEndResolver->resolve(
$this->phpDocInfo->getOriginalPhpDocNode(),
$this->phpDocNode,
$this->tokens
);
foreach ($removedStartAndEnds as $removedStartAndEnd) {
$positionJumpSet[$removedStartAndEnd->getStart()] = $removedStartAndEnd->getEnd();
}
// include also space before, in case of inlined docs
@ -324,55 +333,7 @@ final class PhpDocInfoPrinter
}
/**
* @return StartAndEnd[]
*/
private function getRemovedNodesPositions(): array
{
if ($this->removedNodePositions !== []) {
return $this->removedNodePositions;
}
$removedNodes = array_diff(
$this->phpDocInfo->getOriginalPhpDocNode()
->children,
$this->phpDocNode->children
);
$lastEndPosition = null;
foreach ($removedNodes as $removedNode) {
/** @var StartAndEnd $removedPhpDocNodeInfo */
$removedPhpDocNodeInfo = $removedNode->getAttribute(Attribute::START_END);
// change start position to start of the line, so the whole line is removed
$seekPosition = $removedPhpDocNodeInfo->getStart();
while ($seekPosition >= 0 && $this->tokens[$seekPosition][1] !== Lexer::TOKEN_HORIZONTAL_WS) {
if ($this->tokens[$seekPosition][1] === Lexer::TOKEN_PHPDOC_EOL) {
break;
}
// do not colide
if ($lastEndPosition < $seekPosition) {
break;
}
--$seekPosition;
}
$lastEndPosition = $removedPhpDocNodeInfo->getEnd();
$this->removedNodePositions[] = new StartAndEnd(max(
0,
$seekPosition - 1
), $removedPhpDocNodeInfo->getEnd());
}
return $this->removedNodePositions;
}
/**
* @param int[] $positionJumpSet
* @param array<int, int> $positionJumpSet
*/
private function appendToOutput(string $output, int $from, int $to, array $positionJumpSet): string
{

View File

@ -0,0 +1,55 @@
<?php
declare(strict_types=1);
namespace Rector\BetterPhpDocParser\Printer;
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocChildNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocNode;
use PHPStan\PhpDocParser\Lexer\Lexer;
use Rector\BetterPhpDocParser\Attributes\Attribute\Attribute;
use Rector\BetterPhpDocParser\ValueObject\StartAndEnd;
final class RemoveNodesStartAndEndResolver
{
/**
* @param mixed[] $tokens
* @return StartAndEnd[]
*/
public function resolve(PhpDocNode $originalPhpDocNode, PhpDocNode $currentPhpDocNode, array $tokens): array
{
$removedNodePositions = [];
/** @var PhpDocChildNode[] $removedChildNodes */
$removedChildNodes = array_diff($originalPhpDocNode->children, $currentPhpDocNode->children);
$lastEndPosition = null;
foreach ($removedChildNodes as $removedChildNode) {
/** @var StartAndEnd $removedPhpDocNodeInfo */
$removedPhpDocNodeInfo = $removedChildNode->getAttribute(Attribute::START_END);
// change start position to start of the line, so the whole line is removed
$seekPosition = $removedPhpDocNodeInfo->getStart();
while ($seekPosition >= 0 && $tokens[$seekPosition][1] !== Lexer::TOKEN_HORIZONTAL_WS) {
if ($tokens[$seekPosition][1] === Lexer::TOKEN_PHPDOC_EOL) {
break;
}
// do not colide
if ($lastEndPosition < $seekPosition) {
break;
}
--$seekPosition;
}
$lastEndPosition = $removedPhpDocNodeInfo->getEnd();
$removedNodePositions[] = new StartAndEnd(max(0, $seekPosition - 1), $removedPhpDocNodeInfo->getEnd());
}
return $removedNodePositions;
}
}

View File

@ -37,4 +37,13 @@ final class StartAndEnd
{
return $this->end;
}
public function contains(int $position): bool
{
if ($position < $this->start) {
return false;
}
return $position < $this->end;
}
}

View File

@ -267,7 +267,8 @@ final class NodeFactory
// add @inject
$phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($property);
$phpDocInfo->addPhpDocTagNode(new PhpDocTagNode('injet', new GenericTagValueNode('')));
$phpDocInfo->addPhpDocTagNode(new PhpDocTagNode('@inject', new GenericTagValueNode('')));
$phpDocInfo->makeMultiLined();
return $property;
}