mirror of
https://github.com/rectorphp/rector.git
synced 2024-06-17 00:22:24 +00:00
Improve token iterator usage (#6046)
* use token iterator * add spaceless tag * [ci-review] Rector Rectify Co-authored-by: kaizen-ci <info@kaizen-ci.org>
This commit is contained in:
parent
b7af3d58f1
commit
b03536c0f5
|
@ -14,7 +14,7 @@ expectedArguments(
|
|||
\PHPStan\PhpDocParser\Ast\Node::getAttribute(),
|
||||
0,
|
||||
PhpDocAttributeKey::START_AND_END,
|
||||
PhpDocAttributeKey::LAST_TOKEN_POSITION,
|
||||
PhpDocAttributeKey::LAST_PHP_DOC_TOKEN_POSITION,
|
||||
PhpDocAttributeKey::PARENT,
|
||||
);
|
||||
|
||||
|
@ -22,7 +22,7 @@ expectedArguments(
|
|||
\PHPStan\PhpDocParser\Ast\Node::setAttribute(),
|
||||
0,
|
||||
PhpDocAttributeKey::START_AND_END,
|
||||
PhpDocAttributeKey::LAST_TOKEN_POSITION,
|
||||
PhpDocAttributeKey::LAST_PHP_DOC_TOKEN_POSITION,
|
||||
PhpDocAttributeKey::PARENT,
|
||||
);
|
||||
|
||||
|
@ -30,7 +30,7 @@ expectedArguments(
|
|||
\PHPStan\PhpDocParser\Ast\Node::hasAttribute(),
|
||||
0,
|
||||
PhpDocAttributeKey::START_AND_END,
|
||||
PhpDocAttributeKey::LAST_TOKEN_POSITION,
|
||||
PhpDocAttributeKey::LAST_PHP_DOC_TOKEN_POSITION,
|
||||
PhpDocAttributeKey::PARENT,
|
||||
);
|
||||
|
||||
|
|
|
@ -16,12 +16,14 @@ use PHPStan\PhpDocParser\Ast\PhpDoc\PropertyTagValueNode;
|
|||
use PHPStan\PhpDocParser\Ast\PhpDoc\ReturnTagValueNode;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\TemplateTagValueNode;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\VarTagValueNode;
|
||||
use PHPStan\PhpDocParser\Lexer\Lexer;
|
||||
use PHPStan\Type\MixedType;
|
||||
use PHPStan\Type\Type;
|
||||
use Rector\BetterPhpDocParser\Annotation\AnnotationNaming;
|
||||
use Rector\BetterPhpDocParser\PhpDoc\DoctrineAnnotationTagValueNode;
|
||||
use Rector\BetterPhpDocParser\PhpDoc\SpacelessPhpDocTagNode;
|
||||
use Rector\BetterPhpDocParser\PhpDocNodeVisitor\ChangedPhpDocNodeVisitor;
|
||||
use Rector\BetterPhpDocParser\ValueObject\Parser\BetterTokenIterator;
|
||||
use Rector\ChangesReporting\Collector\RectorChangeCollector;
|
||||
use Rector\Core\Configuration\CurrentNodeProvider;
|
||||
use Rector\Core\Exception\NotImplementedYetException;
|
||||
|
@ -45,21 +47,11 @@ final class PhpDocInfo
|
|||
PropertyTagValueNode::class => '@property',
|
||||
];
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $originalContent;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $isSingleLine = false;
|
||||
|
||||
/**
|
||||
* @var mixed[]
|
||||
*/
|
||||
private $tokens = [];
|
||||
|
||||
/**
|
||||
* @var PhpDocNode
|
||||
*/
|
||||
|
@ -101,12 +93,13 @@ final class PhpDocInfo
|
|||
private $rectorChangeCollector;
|
||||
|
||||
/**
|
||||
* @param mixed[] $tokens
|
||||
* @var BetterTokenIterator
|
||||
*/
|
||||
private $betterTokenIterator;
|
||||
|
||||
public function __construct(
|
||||
PhpDocNode $phpDocNode,
|
||||
array $tokens,
|
||||
string $originalContent,
|
||||
BetterTokenIterator $betterTokenIterator,
|
||||
StaticTypeMapper $staticTypeMapper,
|
||||
\PhpParser\Node $node,
|
||||
AnnotationNaming $annotationNaming,
|
||||
|
@ -114,11 +107,10 @@ final class PhpDocInfo
|
|||
RectorChangeCollector $rectorChangeCollector
|
||||
) {
|
||||
$this->phpDocNode = $phpDocNode;
|
||||
$this->tokens = $tokens;
|
||||
$this->betterTokenIterator = $betterTokenIterator;
|
||||
$this->originalPhpDocNode = clone $phpDocNode;
|
||||
$this->originalContent = $originalContent;
|
||||
|
||||
if ($this->originalContent !== null && ! Strings::match(trim($this->originalContent), "#\n#")) {
|
||||
if (! $betterTokenIterator->containsTokenType(Lexer::TOKEN_PHPDOC_EOL)) {
|
||||
$this->isSingleLine = true;
|
||||
}
|
||||
|
||||
|
@ -129,11 +121,6 @@ final class PhpDocInfo
|
|||
$this->rectorChangeCollector = $rectorChangeCollector;
|
||||
}
|
||||
|
||||
public function getOriginalContent(): string
|
||||
{
|
||||
return $this->originalContent;
|
||||
}
|
||||
|
||||
public function addPhpDocTagNode(PhpDocChildNode $phpDocChildNode): void
|
||||
{
|
||||
$this->phpDocNode->children[] = $phpDocChildNode;
|
||||
|
@ -156,12 +143,12 @@ final class PhpDocInfo
|
|||
*/
|
||||
public function getTokens(): array
|
||||
{
|
||||
return $this->tokens;
|
||||
return $this->betterTokenIterator->getTokens();
|
||||
}
|
||||
|
||||
public function getTokenCount(): int
|
||||
{
|
||||
return count($this->tokens);
|
||||
return $this->betterTokenIterator->count();
|
||||
}
|
||||
|
||||
public function getVarTagValueNode(): ?VarTagValueNode
|
||||
|
@ -417,7 +404,7 @@ final class PhpDocInfo
|
|||
return false;
|
||||
}
|
||||
|
||||
return $this->tokens === [];
|
||||
return $this->betterTokenIterator->count() === 0;
|
||||
}
|
||||
|
||||
public function makeSingleLined(): void
|
||||
|
|
|
@ -115,17 +115,18 @@ final class PhpDocInfoFactory
|
|||
|
||||
// create empty node
|
||||
$content = '';
|
||||
$tokens = [];
|
||||
$tokenIterator = new BetterTokenIterator([]);
|
||||
$phpDocNode = new PhpDocNode([]);
|
||||
} else {
|
||||
$content = $docComment->getText();
|
||||
$tokens = $this->lexer->tokenize($content);
|
||||
$tokenIterator = new BetterTokenIterator($tokens);
|
||||
|
||||
$phpDocNode = $this->parseTokensToPhpDocNode($tokens);
|
||||
$phpDocNode = $this->betterPhpDocParser->parse($tokenIterator);
|
||||
$this->setPositionOfLastToken($phpDocNode);
|
||||
}
|
||||
|
||||
$phpDocInfo = $this->createFromPhpDocNode($phpDocNode, $content, $tokens, $node);
|
||||
$phpDocInfo = $this->createFromPhpDocNode($phpDocNode, $tokenIterator, $node);
|
||||
$this->phpDocInfosByObjectHash[$objectHash] = $phpDocInfo;
|
||||
|
||||
return $phpDocInfo;
|
||||
|
@ -137,7 +138,7 @@ final class PhpDocInfoFactory
|
|||
$this->currentNodeProvider->setNode($node);
|
||||
|
||||
$phpDocNode = new PhpDocNode([]);
|
||||
$phpDocInfo = $this->createFromPhpDocNode($phpDocNode, '', [], $node);
|
||||
$phpDocInfo = $this->createFromPhpDocNode($phpDocNode, new BetterTokenIterator([]), $node);
|
||||
|
||||
// multiline by default
|
||||
$phpDocInfo->makeMultiLined();
|
||||
|
@ -145,15 +146,6 @@ final class PhpDocInfoFactory
|
|||
return $phpDocInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed[][] $tokens
|
||||
*/
|
||||
private function parseTokensToPhpDocNode(array $tokens): PhpDocNode
|
||||
{
|
||||
$tokenIterator = new BetterTokenIterator($tokens);
|
||||
return $this->betterPhpDocParser->parse($tokenIterator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Needed for printing
|
||||
*/
|
||||
|
@ -166,29 +158,23 @@ final class PhpDocInfoFactory
|
|||
$phpDocChildNodes = $phpDocNode->children;
|
||||
$lastChildNode = array_pop($phpDocChildNodes);
|
||||
|
||||
/** @var StartAndEnd $startAndEnd */
|
||||
$startAndEnd = $lastChildNode->getAttribute(PhpDocAttributeKey::START_AND_END);
|
||||
|
||||
if ($startAndEnd !== null) {
|
||||
$phpDocNode->setAttribute(PhpDocAttributeKey::LAST_TOKEN_POSITION, $startAndEnd->getEnd());
|
||||
if ($startAndEnd instanceof StartAndEnd) {
|
||||
$phpDocNode->setAttribute(PhpDocAttributeKey::LAST_PHP_DOC_TOKEN_POSITION, $startAndEnd->getEnd());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed[] $tokens
|
||||
*/
|
||||
private function createFromPhpDocNode(
|
||||
PhpDocNode $phpDocNode,
|
||||
string $content,
|
||||
array $tokens,
|
||||
BetterTokenIterator $betterTokenIterator,
|
||||
Node $node
|
||||
): PhpDocInfo {
|
||||
$this->phpDocNodeMapper->transform($phpDocNode, new BetterTokenIterator($tokens));
|
||||
$this->phpDocNodeMapper->transform($phpDocNode, $betterTokenIterator);
|
||||
|
||||
$phpDocInfo = new PhpDocInfo(
|
||||
$phpDocNode,
|
||||
$tokens,
|
||||
$content,
|
||||
$betterTokenIterator,
|
||||
$this->staticTypeMapper,
|
||||
$node,
|
||||
$this->annotationNaming,
|
||||
|
|
|
@ -7,10 +7,10 @@ namespace Rector\BetterPhpDocParser;
|
|||
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocNode;
|
||||
use Rector\BetterPhpDocParser\Contract\BasePhpDocNodeVisitorInterface;
|
||||
use Rector\BetterPhpDocParser\DataProvider\CurrentTokenIteratorProvider;
|
||||
use Rector\BetterPhpDocParser\PhpDocNodeVisitor\CloningPhpDocNodeVisitor;
|
||||
use Rector\BetterPhpDocParser\ValueObject\Parser\BetterTokenIterator;
|
||||
use Symplify\SimplePhpDocParser\Contract\PhpDocNodeVisitorInterface;
|
||||
use Symplify\SimplePhpDocParser\PhpDocNodeTraverser;
|
||||
use Symplify\SimplePhpDocParser\PhpDocNodeVisitor\CloningPhpDocNodeVisitor;
|
||||
use Symplify\SimplePhpDocParser\PhpDocNodeVisitor\ParentConnectingPhpDocNodeVisitor;
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\BetterPhpDocParser\PhpDocNodeVisitor;
|
||||
|
||||
use PHPStan\PhpDocParser\Ast\Node;
|
||||
use Rector\BetterPhpDocParser\ValueObject\PhpDocAttributeKey;
|
||||
use Symplify\SimplePhpDocParser\PhpDocNodeVisitor\AbstractPhpDocNodeVisitor;
|
||||
|
||||
/**
|
||||
* Mirror too https://github.com/nikic/PHP-Parser/blob/d520bc9e1d6203c35a1ba20675b79a051c821a9e/lib/PhpParser/NodeVisitor/CloningVisitor.php
|
||||
*/
|
||||
final class CloningPhpDocNodeVisitor extends AbstractPhpDocNodeVisitor
|
||||
{
|
||||
public function enterNode(Node $origNode): ?Node
|
||||
{
|
||||
$node = clone $origNode;
|
||||
$node->setAttribute(PhpDocAttributeKey::ORIG_NODE, $origNode);
|
||||
return $node;
|
||||
}
|
||||
}
|
|
@ -6,9 +6,11 @@ namespace Rector\BetterPhpDocParser\PhpDocNodeVisitor;
|
|||
|
||||
use PHPStan\PhpDocParser\Ast\Node;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\TemplateTagValueNode;
|
||||
use PHPStan\PhpDocParser\Lexer\Lexer;
|
||||
use Rector\BetterPhpDocParser\Attributes\AttributeMirrorer;
|
||||
use Rector\BetterPhpDocParser\Contract\BasePhpDocNodeVisitorInterface;
|
||||
use Rector\BetterPhpDocParser\DataProvider\CurrentTokenIteratorProvider;
|
||||
use Rector\BetterPhpDocParser\ValueObject\Parser\BetterTokenIterator;
|
||||
use Rector\BetterPhpDocParser\ValueObject\PhpDoc\SpacingAwareTemplateTagValueNode;
|
||||
use Rector\BetterPhpDocParser\ValueObject\PhpDocAttributeKey;
|
||||
use Rector\BetterPhpDocParser\ValueObject\StartAndEnd;
|
||||
|
@ -52,17 +54,35 @@ final class TemplatePhpDocNodeVisitor extends AbstractPhpDocNodeVisitor implemen
|
|||
throw new ShouldNotHappenException();
|
||||
}
|
||||
|
||||
$docContent = $betterTokenIterator->printFromTo($startAndEnd->getStart(), $startAndEnd->getEnd());
|
||||
|
||||
$prepositions = $this->resolvePreposition($betterTokenIterator, $startAndEnd);
|
||||
$spacingAwareTemplateTagValueNode = new SpacingAwareTemplateTagValueNode(
|
||||
$node->name,
|
||||
$node->bound,
|
||||
$node->description,
|
||||
$docContent
|
||||
$prepositions
|
||||
);
|
||||
|
||||
$this->attributeMirrorer->mirror($node, $spacingAwareTemplateTagValueNode);
|
||||
|
||||
return $spacingAwareTemplateTagValueNode;
|
||||
}
|
||||
|
||||
private function resolvePreposition(BetterTokenIterator $betterTokenIterator, StartAndEnd $startAndEnd): string
|
||||
{
|
||||
$partialTokens = $betterTokenIterator->partialTokens($startAndEnd->getStart(), $startAndEnd->getEnd());
|
||||
|
||||
foreach ($partialTokens as $partialToken) {
|
||||
if ($partialToken[1] !== Lexer::TOKEN_IDENTIFIER) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (! in_array($partialToken[0], ['as', 'of'], true)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return $partialToken[0];
|
||||
}
|
||||
|
||||
return 'of';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,9 @@ use PhpParser\Node;
|
|||
use PHPStan\PhpDocParser\Ast\PhpDoc\GenericTagValueNode;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocNode;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode;
|
||||
use Rector\BetterPhpDocParser\Attributes\AttributeMirrorer;
|
||||
use Rector\BetterPhpDocParser\PhpDoc\DoctrineAnnotationTagValueNode;
|
||||
use Rector\BetterPhpDocParser\PhpDoc\SpacelessPhpDocTagNode;
|
||||
use Rector\BetterPhpDocParser\PhpDocInfo\TokenIteratorFactory;
|
||||
use Rector\BetterPhpDocParser\ValueObject\DoctrineAnnotation\SilentKeyMap;
|
||||
use Rector\BetterPhpDocParser\ValueObject\PhpDocAttributeKey;
|
||||
|
@ -45,16 +47,23 @@ final class DoctrineAnnotationDecorator
|
|||
*/
|
||||
private $tokenIteratorFactory;
|
||||
|
||||
/**
|
||||
* @var AttributeMirrorer
|
||||
*/
|
||||
private $attributeMirrorer;
|
||||
|
||||
public function __construct(
|
||||
CurrentNodeProvider $currentNodeProvider,
|
||||
ClassAnnotationMatcher $classAnnotationMatcher,
|
||||
StaticDoctrineAnnotationParser $staticDoctrineAnnotationParser,
|
||||
TokenIteratorFactory $tokenIteratorFactory
|
||||
TokenIteratorFactory $tokenIteratorFactory,
|
||||
AttributeMirrorer $attributeMirrorer
|
||||
) {
|
||||
$this->currentNodeProvider = $currentNodeProvider;
|
||||
$this->classAnnotationMatcher = $classAnnotationMatcher;
|
||||
$this->staticDoctrineAnnotationParser = $staticDoctrineAnnotationParser;
|
||||
$this->tokenIteratorFactory = $tokenIteratorFactory;
|
||||
$this->attributeMirrorer = $attributeMirrorer;
|
||||
}
|
||||
|
||||
public function decorate(PhpDocNode $phpDocNode): void
|
||||
|
@ -67,7 +76,7 @@ final class DoctrineAnnotationDecorator
|
|||
// merge split doctrine nested tags
|
||||
$this->mergeNestedDoctrineAnnotations($phpDocNode);
|
||||
|
||||
foreach ($phpDocNode->children as $phpDocChildNode) {
|
||||
foreach ($phpDocNode->children as $key => $phpDocChildNode) {
|
||||
if (! $phpDocChildNode instanceof PhpDocTagNode) {
|
||||
continue;
|
||||
}
|
||||
|
@ -104,7 +113,13 @@ final class DoctrineAnnotationDecorator
|
|||
);
|
||||
$doctrineAnnotationTagValueNode->setAttribute(PhpDocAttributeKey::START_AND_END, $formerStartEnd);
|
||||
|
||||
$phpDocChildNode->value = $doctrineAnnotationTagValueNode;
|
||||
$spacelessPhpDocTagNode = new SpacelessPhpDocTagNode(
|
||||
$phpDocChildNode->name,
|
||||
$doctrineAnnotationTagValueNode
|
||||
);
|
||||
|
||||
$this->attributeMirrorer->mirror($phpDocChildNode, $spacelessPhpDocTagNode);
|
||||
$phpDocNode->children[$key] = $spacelessPhpDocTagNode;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -237,7 +237,7 @@ final class PhpDocInfoPrinter
|
|||
}
|
||||
|
||||
if ($phpDocChildNode->value instanceof DoctrineAnnotationTagValueNode && $shouldReprintChildNode) {
|
||||
$printedNode = $phpDocChildNode->name . $phpDocChildNode->value;
|
||||
$printedNode = (string) $phpDocChildNode;
|
||||
|
||||
// remove extra space between tags
|
||||
$printedNode = Strings::replace($printedNode, self::TAG_AND_SPACE_REGEX, '$1(');
|
||||
|
@ -277,7 +277,7 @@ final class PhpDocInfoPrinter
|
|||
private function printEnd(string $output): string
|
||||
{
|
||||
$lastTokenPosition = $this->phpDocNode->getAttribute(
|
||||
PhpDocAttributeKey::LAST_TOKEN_POSITION
|
||||
PhpDocAttributeKey::LAST_PHP_DOC_TOKEN_POSITION
|
||||
) ?: $this->currentTokenPosition;
|
||||
if ($lastTokenPosition === 0) {
|
||||
$lastTokenPosition = 1;
|
||||
|
@ -345,8 +345,8 @@ final class PhpDocInfoPrinter
|
|||
}
|
||||
|
||||
$startTokenPosition = $startAndEnd->getStart();
|
||||
$tokens = $this->phpDocInfo->getTokens();
|
||||
|
||||
$tokens = $this->phpDocInfo->getTokens();
|
||||
if (! isset($tokens[$startTokenPosition - 1])) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -56,7 +56,7 @@ final class BetterTokenIterator extends TokenIterator
|
|||
|
||||
public function isTokenTypeOnPosition(int $tokenType, int $position): bool
|
||||
{
|
||||
$tokens = $this->privatesAccessor->getPrivateProperty($this, self::TOKENS);
|
||||
$tokens = $this->getTokens();
|
||||
$token = $tokens[$position] ?? null;
|
||||
|
||||
if ($token === null) {
|
||||
|
@ -81,7 +81,7 @@ final class BetterTokenIterator extends TokenIterator
|
|||
throw new ShouldNotHappenException('Arguments are flipped');
|
||||
}
|
||||
|
||||
$tokens = $this->privatesAccessor->getPrivateProperty($this, self::TOKENS);
|
||||
$tokens = $this->getTokens();
|
||||
|
||||
$content = '';
|
||||
|
||||
|
@ -102,10 +102,8 @@ final class BetterTokenIterator extends TokenIterator
|
|||
|
||||
public function print(): string
|
||||
{
|
||||
$tokens = $this->privatesAccessor->getPrivateProperty($this, self::TOKENS);
|
||||
|
||||
$content = '';
|
||||
foreach ($tokens as $token) {
|
||||
foreach ($this->getTokens() as $token) {
|
||||
$content .= $token[0];
|
||||
}
|
||||
|
||||
|
@ -116,7 +114,7 @@ final class BetterTokenIterator extends TokenIterator
|
|||
{
|
||||
$this->pushSavePoint();
|
||||
|
||||
$tokens = $this->privatesAccessor->getPrivateProperty($this, self::TOKENS);
|
||||
$tokens = $this->getTokens();
|
||||
$index = $this->privatesAccessor->getPrivateProperty($this, self::INDEX);
|
||||
|
||||
// does next token exist?
|
||||
|
@ -136,4 +134,43 @@ final class BetterTokenIterator extends TokenIterator
|
|||
{
|
||||
return $this->privatesAccessor->getPrivateProperty($this, self::INDEX);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed[]
|
||||
*/
|
||||
public function getTokens(): array
|
||||
{
|
||||
return $this->privatesAccessor->getPrivateProperty($this, self::TOKENS);
|
||||
}
|
||||
|
||||
public function count(): int
|
||||
{
|
||||
return count($this->getTokens());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed[]
|
||||
*/
|
||||
public function partialTokens(int $start, int $end): array
|
||||
{
|
||||
$tokens = $this->getTokens();
|
||||
|
||||
$chunkTokens = [];
|
||||
for ($i = $start; $i <= $end; ++$i) {
|
||||
$chunkTokens[$i] = $tokens[$i];
|
||||
}
|
||||
|
||||
return $chunkTokens;
|
||||
}
|
||||
|
||||
public function containsTokenType(int $type): bool
|
||||
{
|
||||
foreach ($this->getTokens() as $token) {
|
||||
if ($token[1] === $type) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,29 +4,20 @@ declare(strict_types=1);
|
|||
|
||||
namespace Rector\BetterPhpDocParser\ValueObject\PhpDoc;
|
||||
|
||||
use Nette\Utils\Strings;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\TemplateTagValueNode;
|
||||
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
|
||||
|
||||
final class SpacingAwareTemplateTagValueNode extends TemplateTagValueNode
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
* @see https://regex101.com/r/4WtsUS/1
|
||||
*/
|
||||
private const AS_OF_PREPOSITOIN_REGEX = '#\s+(?<preposition>as|of)\s+#';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $preposition;
|
||||
|
||||
public function __construct(string $name, ?TypeNode $typeNode, string $description, string $originalContent)
|
||||
public function __construct(string $name, ?TypeNode $typeNode, string $description, string $preposition)
|
||||
{
|
||||
parent::__construct($name, $typeNode, $description);
|
||||
|
||||
$matches = Strings::match($originalContent, self::AS_OF_PREPOSITOIN_REGEX);
|
||||
$this->preposition = $matches['preposition'] ?? 'of';
|
||||
$this->preposition = $preposition;
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
|
|
|
@ -4,6 +4,8 @@ declare(strict_types=1);
|
|||
|
||||
namespace Rector\BetterPhpDocParser\ValueObject;
|
||||
|
||||
use Symplify\SimplePhpDocParser\ValueObject\PhpDocAttributeKey as NativePhpDocAttributeKey;
|
||||
|
||||
final class PhpDocAttributeKey
|
||||
{
|
||||
/**
|
||||
|
@ -14,15 +16,15 @@ final class PhpDocAttributeKey
|
|||
/**
|
||||
* @var string
|
||||
*/
|
||||
public const PARENT = 'parent';
|
||||
public const PARENT = NativePhpDocAttributeKey::PARENT;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public const LAST_TOKEN_POSITION = 'last_token_position';
|
||||
public const LAST_PHP_DOC_TOKEN_POSITION = 'last_token_position';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public const ORIG_NODE = 'orig_node';
|
||||
public const ORIG_NODE = NativePhpDocAttributeKey::ORIG_NODE;
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ namespace Rector\NodeTypeResolver\PhpDoc\NodeAnalyzer;
|
|||
|
||||
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
|
||||
use Rector\NodeTypeResolver\PhpDocNodeVisitor\ClassRenamePhpDocNodeVisitor;
|
||||
use Rector\NodeTypeResolver\ValueObject\OldToNewType;
|
||||
use Symplify\SimplePhpDocParser\PhpDocNodeTraverser;
|
||||
|
||||
final class DocBlockClassRenamer
|
||||
|
@ -21,17 +22,17 @@ final class DocBlockClassRenamer
|
|||
}
|
||||
|
||||
/**
|
||||
* @param array<string, string> $oldToNewClasses
|
||||
* @param OldToNewType[] $oldToNewTypes
|
||||
*/
|
||||
public function renamePhpDocType(PhpDocInfo $phpDocInfo, array $oldToNewClasses): void
|
||||
public function renamePhpDocType(PhpDocInfo $phpDocInfo, array $oldToNewTypes): void
|
||||
{
|
||||
if ($oldToNewClasses === []) {
|
||||
if ($oldToNewTypes === []) {
|
||||
return;
|
||||
}
|
||||
|
||||
$phpDocNodeTraverser = new PhpDocNodeTraverser();
|
||||
|
||||
$this->classRenamePhpDocNodeVisitor->setOldToNewClasses($oldToNewClasses);
|
||||
$this->classRenamePhpDocNodeVisitor->setOldToNewTypes($oldToNewTypes);
|
||||
$phpDocNodeTraverser->addPhpDocNodeVisitor($this->classRenamePhpDocNodeVisitor);
|
||||
$phpDocNodeTraverser->traverse($phpDocInfo->getPhpDocNode());
|
||||
}
|
||||
|
|
|
@ -11,8 +11,8 @@ use PHPStan\Type\ObjectType;
|
|||
use Rector\BetterPhpDocParser\ValueObject\PhpDocAttributeKey;
|
||||
use Rector\Core\Configuration\CurrentNodeProvider;
|
||||
use Rector\Core\Exception\ShouldNotHappenException;
|
||||
use Rector\NodeTypeResolver\ValueObject\OldToNewType;
|
||||
use Rector\StaticTypeMapper\StaticTypeMapper;
|
||||
use Rector\StaticTypeMapper\ValueObject\Type\FullyQualifiedObjectType;
|
||||
use Rector\StaticTypeMapper\ValueObject\Type\ShortenedObjectType;
|
||||
use Symplify\SimplePhpDocParser\PhpDocNodeVisitor\AbstractPhpDocNodeVisitor;
|
||||
|
||||
|
@ -29,9 +29,9 @@ final class ClassRenamePhpDocNodeVisitor extends AbstractPhpDocNodeVisitor
|
|||
private $currentNodeProvider;
|
||||
|
||||
/**
|
||||
* @var array<string, string>
|
||||
* @var OldToNewType[]
|
||||
*/
|
||||
private $oldToNewClasses = [];
|
||||
private $oldToNewTypes = [];
|
||||
|
||||
public function __construct(StaticTypeMapper $staticTypeMapper, CurrentNodeProvider $currentNodeProvider)
|
||||
{
|
||||
|
@ -41,7 +41,7 @@ final class ClassRenamePhpDocNodeVisitor extends AbstractPhpDocNodeVisitor
|
|||
|
||||
public function beforeTraverse(Node $node): void
|
||||
{
|
||||
if ($this->oldToNewClasses === []) {
|
||||
if ($this->oldToNewTypes === []) {
|
||||
throw new ShouldNotHappenException('Configure "$oldToNewClasses" first');
|
||||
}
|
||||
}
|
||||
|
@ -64,15 +64,12 @@ final class ClassRenamePhpDocNodeVisitor extends AbstractPhpDocNodeVisitor
|
|||
$staticType = new ObjectType($staticType->getFullyQualifiedName());
|
||||
}
|
||||
|
||||
foreach ($this->oldToNewClasses as $oldClass => $newClass) {
|
||||
$oldType = new ObjectType($oldClass);
|
||||
$newType = new FullyQualifiedObjectType($newClass);
|
||||
|
||||
if (! $staticType->equals($oldType)) {
|
||||
foreach ($this->oldToNewTypes as $oldToNewType) {
|
||||
if (! $staticType->equals($oldToNewType->getOldType())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$newTypeNode = $this->staticTypeMapper->mapPHPStanTypeToPHPStanPhpDocTypeNode($newType);
|
||||
$newTypeNode = $this->staticTypeMapper->mapPHPStanTypeToPHPStanPhpDocTypeNode($oldToNewType->getNewType());
|
||||
|
||||
$parentType = $node->getAttribute(PhpDocAttributeKey::PARENT);
|
||||
if ($parentType instanceof TypeNode) {
|
||||
|
@ -87,10 +84,10 @@ final class ClassRenamePhpDocNodeVisitor extends AbstractPhpDocNodeVisitor
|
|||
}
|
||||
|
||||
/**
|
||||
* @param array<string, string> $oldToNewClasses
|
||||
* @param OldToNewType[] $oldToNewTypes
|
||||
*/
|
||||
public function setOldToNewClasses(array $oldToNewClasses): void
|
||||
public function setOldToNewTypes(array $oldToNewTypes): void
|
||||
{
|
||||
$this->oldToNewClasses = $oldToNewClasses;
|
||||
$this->oldToNewTypes = $oldToNewTypes;
|
||||
}
|
||||
}
|
||||
|
|
36
packages/NodeTypeResolver/ValueObject/OldToNewType.php
Normal file
36
packages/NodeTypeResolver/ValueObject/OldToNewType.php
Normal file
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\NodeTypeResolver\ValueObject;
|
||||
|
||||
use PHPStan\Type\Type;
|
||||
|
||||
final class OldToNewType
|
||||
{
|
||||
/**
|
||||
* @var Type
|
||||
*/
|
||||
private $oldType;
|
||||
|
||||
/**
|
||||
* @var Type
|
||||
*/
|
||||
private $newType;
|
||||
|
||||
public function __construct(Type $oldType, Type $newType)
|
||||
{
|
||||
$this->oldType = $oldType;
|
||||
$this->newType = $newType;
|
||||
}
|
||||
|
||||
public function getOldType(): Type
|
||||
{
|
||||
return $this->oldType;
|
||||
}
|
||||
|
||||
public function getNewType(): Type
|
||||
{
|
||||
return $this->newType;
|
||||
}
|
||||
}
|
|
@ -17,6 +17,7 @@ use PhpParser\Node\Stmt\UseUse;
|
|||
use PHPStan\Analyser\Scope;
|
||||
use PHPStan\Reflection\ClassReflection;
|
||||
use PHPStan\Reflection\ReflectionProvider;
|
||||
use PHPStan\Type\ObjectType;
|
||||
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory;
|
||||
use Rector\BetterPhpDocParser\PhpDocManipulator\PhpDocClassRenamer;
|
||||
use Rector\BetterPhpDocParser\ValueObject\NodeTypes;
|
||||
|
@ -27,6 +28,8 @@ use Rector\NodeNameResolver\NodeNameResolver;
|
|||
use Rector\NodeRemoval\NodeRemover;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
use Rector\NodeTypeResolver\PhpDoc\NodeAnalyzer\DocBlockClassRenamer;
|
||||
use Rector\NodeTypeResolver\ValueObject\OldToNewType;
|
||||
use Rector\StaticTypeMapper\ValueObject\Type\FullyQualifiedObjectType;
|
||||
use Symplify\Astral\NodeTraverser\SimpleCallableNodeTraverser;
|
||||
use Symplify\PackageBuilder\Parameter\ParameterProvider;
|
||||
|
||||
|
@ -116,7 +119,12 @@ final class ClassRenamer
|
|||
*/
|
||||
public function renameNode(Node $node, array $oldToNewClasses): ?Node
|
||||
{
|
||||
$this->refactorPhpDoc($node, $oldToNewClasses);
|
||||
$oldToNewTypes = [];
|
||||
foreach ($oldToNewClasses as $oldClass => $newClass) {
|
||||
$oldToNewTypes[] = new OldToNewType(new ObjectType($oldClass), new FullyQualifiedObjectType($newClass));
|
||||
}
|
||||
|
||||
$this->refactorPhpDoc($node, $oldToNewTypes, $oldToNewClasses);
|
||||
|
||||
if ($node instanceof Name) {
|
||||
return $this->refactorName($node, $oldToNewClasses);
|
||||
|
@ -134,12 +142,10 @@ final class ClassRenamer
|
|||
}
|
||||
|
||||
/**
|
||||
* Replace types in @var/@param/@return/@throws,
|
||||
* Doctrine @ORM entity targetClass, Serialize, Assert etc.
|
||||
*
|
||||
* @param OldToNewType[] $oldToNewTypes
|
||||
* @param array<string, string> $oldToNewClasses
|
||||
*/
|
||||
private function refactorPhpDoc(Node $node, array $oldToNewClasses): void
|
||||
private function refactorPhpDoc(Node $node, array $oldToNewTypes, array $oldToNewClasses): void
|
||||
{
|
||||
$phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($node);
|
||||
if (! $phpDocInfo->hasByTypes(NodeTypes::TYPE_AWARE_NODES) && ! $phpDocInfo->hasByAnnotationClasses(
|
||||
|
@ -148,7 +154,7 @@ final class ClassRenamer
|
|||
return;
|
||||
}
|
||||
|
||||
$this->docBlockClassRenamer->renamePhpDocType($phpDocInfo, $oldToNewClasses);
|
||||
$this->docBlockClassRenamer->renamePhpDocType($phpDocInfo, $oldToNewTypes);
|
||||
|
||||
$this->phpDocClassRenamer->changeTypeInAnnotationTypes($node, $phpDocInfo, $oldToNewClasses);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user