diff --git a/src/BetterPhpDocParser/DataProvider/CurrentTokenIteratorProvider.php b/src/BetterPhpDocParser/DataProvider/CurrentTokenIteratorProvider.php index 64b575e5275..467566809f0 100644 --- a/src/BetterPhpDocParser/DataProvider/CurrentTokenIteratorProvider.php +++ b/src/BetterPhpDocParser/DataProvider/CurrentTokenIteratorProvider.php @@ -4,24 +4,24 @@ namespace Rector\BetterPhpDocParser\DataProvider; -use Rector\BetterPhpDocParser\ValueObject\Parser\BetterTokenIterator; +use PHPStan\PhpDocParser\Parser\TokenIterator; use Rector\Exception\ShouldNotHappenException; final class CurrentTokenIteratorProvider { - private ?BetterTokenIterator $betterTokenIterator = null; + private ?TokenIterator $tokenIterator = null; - public function setBetterTokenIterator(BetterTokenIterator $betterTokenIterator): void + public function setTokenIterator(TokenIterator $tokenIterator): void { - $this->betterTokenIterator = $betterTokenIterator; + $this->tokenIterator = $tokenIterator; } - public function provide(): BetterTokenIterator + public function provide(): TokenIterator { - if (! $this->betterTokenIterator instanceof BetterTokenIterator) { + if (! $this->tokenIterator instanceof TokenIterator) { throw new ShouldNotHappenException(); } - return $this->betterTokenIterator; + return $this->tokenIterator; } } diff --git a/src/BetterPhpDocParser/NodeDecorator/DoctrineAnnotationDecorator.php b/src/BetterPhpDocParser/NodeDecorator/DoctrineAnnotationDecorator.php index 8ffdeb580a2..7cb5d8a707d 100644 --- a/src/BetterPhpDocParser/NodeDecorator/DoctrineAnnotationDecorator.php +++ b/src/BetterPhpDocParser/NodeDecorator/DoctrineAnnotationDecorator.php @@ -426,7 +426,7 @@ private function processDescriptionAsSpacelessPhpDoctagNode( private function isClosedContent(string $composedContent): bool { $composedTokenIterator = $this->tokenIteratorFactory->create($composedContent); - $tokenCount = $composedTokenIterator->count(); + $tokenCount = $composedTokenIterator->getTokenCount(); $openBracketCount = 0; $closeBracketCount = 0; @@ -455,7 +455,7 @@ private function isClosedContent(string $composedContent): bool } $composedTokenIterator->next(); - } while ($composedTokenIterator->currentPosition() < ($tokenCount - 1)); + } while ($composedTokenIterator->currentTokenIndex() < ($tokenCount - 1)); return $openBracketCount === $closeBracketCount; } diff --git a/src/BetterPhpDocParser/PhpDocInfo/PhpDocInfo.php b/src/BetterPhpDocParser/PhpDocInfo/PhpDocInfo.php index 491c7c50df7..2f946d7ebdf 100644 --- a/src/BetterPhpDocParser/PhpDocInfo/PhpDocInfo.php +++ b/src/BetterPhpDocParser/PhpDocInfo/PhpDocInfo.php @@ -24,6 +24,7 @@ use PHPStan\PhpDocParser\Ast\Type\ConstTypeNode; use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode; use PHPStan\PhpDocParser\Lexer\Lexer; +use PHPStan\PhpDocParser\Parser\TokenIterator; use PHPStan\Type\MixedType; use PHPStan\Type\Type; use Rector\BetterPhpDocParser\Annotation\AnnotationNaming; @@ -31,7 +32,6 @@ use Rector\BetterPhpDocParser\PhpDoc\DoctrineAnnotationTagValueNode; use Rector\BetterPhpDocParser\PhpDoc\SpacelessPhpDocTagNode; use Rector\BetterPhpDocParser\PhpDocNodeFinder\PhpDocNodeByTypeFinder; -use Rector\BetterPhpDocParser\ValueObject\Parser\BetterTokenIterator; use Rector\BetterPhpDocParser\ValueObject\PhpDocAttributeKey; use Rector\BetterPhpDocParser\ValueObject\Type\ShortenedIdentifierTypeNode; use Rector\Exception\ShouldNotHappenException; @@ -70,7 +70,7 @@ final class PhpDocInfo public function __construct( private readonly PhpDocNode $phpDocNode, - private readonly BetterTokenIterator $betterTokenIterator, + private readonly TokenIterator $tokenIterator, private readonly StaticTypeMapper $staticTypeMapper, private readonly \PhpParser\Node $node, private readonly AnnotationNaming $annotationNaming, @@ -79,7 +79,7 @@ public function __construct( ) { $this->originalPhpDocNode = clone $phpDocNode; - if (! $betterTokenIterator->containsTokenType(Lexer::TOKEN_PHPDOC_EOL)) { + if (! in_array(Lexer::TOKEN_PHPDOC_EOL, array_column($tokenIterator->getTokens(), Lexer::TYPE_OFFSET), true)) { $this->isSingleLine = true; } } @@ -109,12 +109,12 @@ public function getOriginalPhpDocNode(): PhpDocNode */ public function getTokens(): array { - return $this->betterTokenIterator->getTokens(); + return $this->tokenIterator->getTokens(); } public function getTokenCount(): int { - return $this->betterTokenIterator->count(); + return $this->tokenIterator->getTokenCount(); } public function getVarTagValueNode(string $tagName = '@var'): ?VarTagValueNode @@ -349,7 +349,7 @@ public function isNewNode(): bool return false; } - return $this->betterTokenIterator->count() === 0; + return $this->tokenIterator->getTokenCount() === 0; } public function isSingleLine(): bool diff --git a/src/BetterPhpDocParser/PhpDocInfo/PhpDocInfoFactory.php b/src/BetterPhpDocParser/PhpDocInfo/PhpDocInfoFactory.php index 094448fe8cb..e267e8b4bf7 100644 --- a/src/BetterPhpDocParser/PhpDocInfo/PhpDocInfoFactory.php +++ b/src/BetterPhpDocParser/PhpDocInfo/PhpDocInfoFactory.php @@ -8,11 +8,11 @@ use PhpParser\Node; use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocNode; use PHPStan\PhpDocParser\Lexer\Lexer; +use PHPStan\PhpDocParser\Parser\TokenIterator; use Rector\BetterPhpDocParser\Annotation\AnnotationNaming; use Rector\BetterPhpDocParser\PhpDocNodeFinder\PhpDocNodeByTypeFinder; use Rector\BetterPhpDocParser\PhpDocNodeMapper; use Rector\BetterPhpDocParser\PhpDocParser\BetterPhpDocParser; -use Rector\BetterPhpDocParser\ValueObject\Parser\BetterTokenIterator; use Rector\BetterPhpDocParser\ValueObject\PhpDocAttributeKey; use Rector\BetterPhpDocParser\ValueObject\StartAndEnd; use Rector\NodeTypeResolver\Node\AttributeKey; @@ -68,11 +68,11 @@ public function createFromNode(Node $node): ?PhpDocInfo } // create empty node - $tokenIterator = new BetterTokenIterator([]); + $tokenIterator = new TokenIterator([]); $phpDocNode = new PhpDocNode([]); } else { $tokens = $this->lexer->tokenize($docComment->getText()); - $tokenIterator = new BetterTokenIterator($tokens); + $tokenIterator = new TokenIterator($tokens); $phpDocNode = $this->betterPhpDocParser->parseWithNode($tokenIterator, $node); $this->setPositionOfLastToken($phpDocNode); @@ -87,7 +87,7 @@ public function createFromNode(Node $node): ?PhpDocInfo public function createEmpty(Node $node): PhpDocInfo { $phpDocNode = new PhpDocNode([]); - $phpDocInfo = $this->createFromPhpDocNode($phpDocNode, new BetterTokenIterator([]), $node); + $phpDocInfo = $this->createFromPhpDocNode($phpDocNode, new TokenIterator([]), $node); // multiline by default $phpDocInfo->makeMultiLined(); @@ -115,14 +115,14 @@ private function setPositionOfLastToken(PhpDocNode $phpDocNode): void private function createFromPhpDocNode( PhpDocNode $phpDocNode, - BetterTokenIterator $betterTokenIterator, + TokenIterator $tokenIterator, Node $node ): PhpDocInfo { - $phpDocNode = $this->phpDocNodeMapper->transform($phpDocNode, $betterTokenIterator); + $phpDocNode = $this->phpDocNodeMapper->transform($phpDocNode, $tokenIterator); $phpDocInfo = new PhpDocInfo( $phpDocNode, - $betterTokenIterator, + $tokenIterator, $this->staticTypeMapper, $node, $this->annotationNaming, diff --git a/src/BetterPhpDocParser/PhpDocInfo/TokenIteratorFactory.php b/src/BetterPhpDocParser/PhpDocInfo/TokenIteratorFactory.php index 06f969eaffd..6f5a5b07637 100644 --- a/src/BetterPhpDocParser/PhpDocInfo/TokenIteratorFactory.php +++ b/src/BetterPhpDocParser/PhpDocInfo/TokenIteratorFactory.php @@ -6,7 +6,6 @@ use PHPStan\PhpDocParser\Lexer\Lexer; use PHPStan\PhpDocParser\Parser\TokenIterator; -use Rector\BetterPhpDocParser\ValueObject\Parser\BetterTokenIterator; final readonly class TokenIteratorFactory { @@ -15,22 +14,9 @@ public function __construct( ) { } - public function create(string $content): BetterTokenIterator + public function create(string $content): TokenIterator { $tokens = $this->lexer->tokenize($content); - return new BetterTokenIterator($tokens); - } - - public function createFromTokenIterator(TokenIterator $tokenIterator): BetterTokenIterator - { - if ($tokenIterator instanceof BetterTokenIterator) { - return $tokenIterator; - } - - // keep original tokens and index position - $tokens = $tokenIterator->getTokens(); - $currentIndex = $tokenIterator->currentTokenIndex(); - - return new BetterTokenIterator($tokens, $currentIndex); + return new TokenIterator($tokens); } } diff --git a/src/BetterPhpDocParser/PhpDocNodeMapper.php b/src/BetterPhpDocParser/PhpDocNodeMapper.php index 5f37c191184..0fbb680f623 100644 --- a/src/BetterPhpDocParser/PhpDocNodeMapper.php +++ b/src/BetterPhpDocParser/PhpDocNodeMapper.php @@ -6,9 +6,9 @@ use PHPStan\PhpDocParser\Ast\NodeTraverser; use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocNode; +use PHPStan\PhpDocParser\Parser\TokenIterator; use Rector\BetterPhpDocParser\Contract\BasePhpDocNodeVisitorInterface; use Rector\BetterPhpDocParser\DataProvider\CurrentTokenIteratorProvider; -use Rector\BetterPhpDocParser\ValueObject\Parser\BetterTokenIterator; use Rector\PhpDocParser\PhpDocParser\PhpDocNodeVisitor\CloningPhpDocNodeVisitor; use Rector\PhpDocParser\PhpDocParser\PhpDocNodeVisitor\ParentConnectingPhpDocNodeVisitor; use Webmozart\Assert\Assert; @@ -38,9 +38,9 @@ public function __construct( ]); } - public function transform(PhpDocNode $phpDocNode, BetterTokenIterator $betterTokenIterator): PhpDocNode + public function transform(PhpDocNode $phpDocNode, TokenIterator $tokenIterator): PhpDocNode { - $this->currentTokenIteratorProvider->setBetterTokenIterator($betterTokenIterator); + $this->currentTokenIteratorProvider->setTokenIterator($tokenIterator); [$phpDocNode] = $this->phpDocNodeTraverser->traverse([$phpDocNode]); Assert::isInstanceOf($phpDocNode, PhpDocNode::class); diff --git a/src/BetterPhpDocParser/PhpDocNodeVisitor/TemplatePhpDocNodeVisitor.php b/src/BetterPhpDocParser/PhpDocNodeVisitor/TemplatePhpDocNodeVisitor.php index 5e0a6343ba6..cd910fcb8a4 100644 --- a/src/BetterPhpDocParser/PhpDocNodeVisitor/TemplatePhpDocNodeVisitor.php +++ b/src/BetterPhpDocParser/PhpDocNodeVisitor/TemplatePhpDocNodeVisitor.php @@ -9,10 +9,10 @@ use PHPStan\PhpDocParser\Ast\Node; use PHPStan\PhpDocParser\Ast\PhpDoc\TemplateTagValueNode; use PHPStan\PhpDocParser\Lexer\Lexer; +use PHPStan\PhpDocParser\Parser\TokenIterator; 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\Exception\ShouldNotHappenException; @@ -34,7 +34,7 @@ public function enterNode(Node $node): ?Node return null; } - $betterTokenIterator = $this->currentTokenIteratorProvider->provide(); + $tokenIterator = $this->currentTokenIteratorProvider->provide(); $startIndex = $node->getAttribute(Attribute::START_INDEX); $endIndex = $node->getAttribute(Attribute::END_INDEX); @@ -42,7 +42,7 @@ public function enterNode(Node $node): ?Node throw new ShouldNotHappenException(); } - $prepositions = $this->resolvePreposition($betterTokenIterator, $startIndex, $endIndex); + $prepositions = $this->resolvePreposition($tokenIterator, $startIndex, $endIndex); $spacingAwareTemplateTagValueNode = new SpacingAwareTemplateTagValueNode( $node->name, $node->bound, @@ -56,11 +56,11 @@ public function enterNode(Node $node): ?Node } private function resolvePreposition( - BetterTokenIterator $betterTokenIterator, + TokenIterator $tokenIterator, int $startIndex, int $endIndex ): string { - $partialTokens = $betterTokenIterator->partialTokens($startIndex, $endIndex); + $partialTokens = array_slice($tokenIterator->getTokens(), $startIndex, $endIndex - $startIndex + 1); foreach ($partialTokens as $partialToken) { if ($partialToken[1] !== Lexer::TOKEN_IDENTIFIER) { diff --git a/src/BetterPhpDocParser/PhpDocNodeVisitor/UnionTypeNodePhpDocNodeVisitor.php b/src/BetterPhpDocParser/PhpDocNodeVisitor/UnionTypeNodePhpDocNodeVisitor.php index 6b6110b571d..62e2618d8ba 100644 --- a/src/BetterPhpDocParser/PhpDocNodeVisitor/UnionTypeNodePhpDocNodeVisitor.php +++ b/src/BetterPhpDocParser/PhpDocNodeVisitor/UnionTypeNodePhpDocNodeVisitor.php @@ -8,10 +8,10 @@ use PHPStan\PhpDocParser\Ast\Node; use PHPStan\PhpDocParser\Ast\Type\UnionTypeNode; use PHPStan\PhpDocParser\Lexer\Lexer; +use PHPStan\PhpDocParser\Parser\TokenIterator; 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\PhpDocAttributeKey; use Rector\BetterPhpDocParser\ValueObject\StartAndEnd; use Rector\BetterPhpDocParser\ValueObject\Type\BracketsAwareUnionTypeNode; @@ -45,9 +45,9 @@ public function enterNode(Node $node): ?Node ); } - $betterTokenProvider = $this->currentTokenIteratorProvider->provide(); + $tokenIterator = $this->currentTokenIteratorProvider->provide(); - $isWrappedInCurlyBrackets = $this->isWrappedInCurlyBrackets($betterTokenProvider, $startAndEnd); + $isWrappedInCurlyBrackets = $this->isWrappedInCurlyBrackets($tokenIterator, $startAndEnd); $bracketsAwareUnionTypeNode = new BracketsAwareUnionTypeNode($node->types, $isWrappedInCurlyBrackets); $this->attributeMirrorer->mirror($node, $bracketsAwareUnionTypeNode); @@ -55,7 +55,7 @@ public function enterNode(Node $node): ?Node return $bracketsAwareUnionTypeNode; } - private function isWrappedInCurlyBrackets(BetterTokenIterator $betterTokenProvider, StartAndEnd $startAndEnd): bool + private function isWrappedInCurlyBrackets(TokenIterator $tokenIterator, StartAndEnd $startAndEnd): bool { $previousPosition = $startAndEnd->getStart() - 1; $nextPosition = $startAndEnd->getEnd() + 1; @@ -63,8 +63,10 @@ private function isWrappedInCurlyBrackets(BetterTokenIterator $betterTokenProvid // A union is wrapped only when BOTH parens flank it. Either alone may be unrelated — // e.g. an `@method`'s parameter-list `(` before a first-position union, or the matching // `)` after a last-position union — neither belongs to the union type itself. - return $betterTokenProvider->isTokenTypeOnPosition(Lexer::TOKEN_OPEN_PARENTHESES, $previousPosition) - && $betterTokenProvider->isTokenTypeOnPosition(Lexer::TOKEN_CLOSE_PARENTHESES, $nextPosition); + $tokens = $tokenIterator->getTokens(); + + return ($tokens[$previousPosition][Lexer::TYPE_OFFSET] ?? null) === Lexer::TOKEN_OPEN_PARENTHESES + && ($tokens[$nextPosition][Lexer::TYPE_OFFSET] ?? null) === Lexer::TOKEN_CLOSE_PARENTHESES; } private function resolveStartAndEnd(UnionTypeNode $unionTypeNode): ?StartAndEnd diff --git a/src/BetterPhpDocParser/PhpDocParser/BetterPhpDocParser.php b/src/BetterPhpDocParser/PhpDocParser/BetterPhpDocParser.php index e9111c1c46a..420e9fc7921 100644 --- a/src/BetterPhpDocParser/PhpDocParser/BetterPhpDocParser.php +++ b/src/BetterPhpDocParser/PhpDocParser/BetterPhpDocParser.php @@ -24,11 +24,8 @@ use Rector\BetterPhpDocParser\NodeDecorator\ConstExprClassNameDecorator; use Rector\BetterPhpDocParser\NodeDecorator\DoctrineAnnotationDecorator; use Rector\BetterPhpDocParser\NodeDecorator\PhpDocTagGenericUsesDecorator; -use Rector\BetterPhpDocParser\PhpDocInfo\TokenIteratorFactory; -use Rector\BetterPhpDocParser\ValueObject\Parser\BetterTokenIterator; use Rector\BetterPhpDocParser\ValueObject\PhpDocAttributeKey; use Rector\BetterPhpDocParser\ValueObject\StartAndEnd; -use Rector\Exception\ShouldNotHappenException; use Rector\Util\Reflection\PrivatesAccessor; /** @@ -55,7 +52,6 @@ public function __construct( ParserConfig $parserConfig, TypeParser $typeParser, ConstExprParser $constExprParser, - private readonly TokenIteratorFactory $tokenIteratorFactory, ConstExprClassNameDecorator $constExprClassNameDecorator, DoctrineAnnotationDecorator $doctrineAnnotationDecorator, ArrayItemClassNameDecorator $arrayItemClassNameDecorator, @@ -83,24 +79,24 @@ public function __construct( ); } - public function parseWithNode(BetterTokenIterator $betterTokenIterator, Node $node): PhpDocNode + public function parseWithNode(TokenIterator $tokenIterator, Node $node): PhpDocNode { - $betterTokenIterator->consumeTokenType(Lexer::TOKEN_OPEN_PHPDOC); - $betterTokenIterator->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL); + $tokenIterator->consumeTokenType(Lexer::TOKEN_OPEN_PHPDOC); + $tokenIterator->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL); $children = []; - if (! $betterTokenIterator->isCurrentTokenType(Lexer::TOKEN_CLOSE_PHPDOC)) { - $children[] = $this->parseChildAndStoreItsPositions($betterTokenIterator); + if (! $tokenIterator->isCurrentTokenType(Lexer::TOKEN_CLOSE_PHPDOC)) { + $children[] = $this->parseChildAndStoreItsPositions($tokenIterator); - while ($betterTokenIterator->tryConsumeTokenType( + while ($tokenIterator->tryConsumeTokenType( Lexer::TOKEN_PHPDOC_EOL - ) && ! $betterTokenIterator->isCurrentTokenType(Lexer::TOKEN_CLOSE_PHPDOC)) { - $children[] = $this->parseChildAndStoreItsPositions($betterTokenIterator); + ) && ! $tokenIterator->isCurrentTokenType(Lexer::TOKEN_CLOSE_PHPDOC)) { + $children[] = $this->parseChildAndStoreItsPositions($tokenIterator); } } // might be in the middle of annotations - $betterTokenIterator->tryConsumeTokenType(Lexer::TOKEN_CLOSE_PHPDOC); + $tokenIterator->tryConsumeTokenType(Lexer::TOKEN_CLOSE_PHPDOC); $phpDocNode = new PhpDocNode($children); foreach ($this->phpDocNodeDecorators as $phpDocNodeDecorator) { @@ -112,28 +108,20 @@ public function parseWithNode(BetterTokenIterator $betterTokenIterator, Node $no public function parseTag(TokenIterator $tokenIterator): PhpDocTagNode { - // replace generic nodes with DoctrineAnnotations - if (! $tokenIterator instanceof BetterTokenIterator) { - throw new ShouldNotHappenException(); - } - $tag = $this->resolveTag($tokenIterator); $phpDocTagValueNode = $this->parseTagValue($tokenIterator, $tag); return new PhpDocTagNode($tag, $phpDocTagValueNode); } - /** - * @param BetterTokenIterator $tokenIterator - */ public function parseTagValue(TokenIterator $tokenIterator, string $tag): PhpDocTagValueNode { $isPrecededByHorizontalWhitespace = $tokenIterator->isPrecededByHorizontalWhitespace(); - $startPosition = $tokenIterator->currentPosition(); + $startPosition = $tokenIterator->currentTokenIndex(); $phpDocTagValueNode = parent::parseTagValue($tokenIterator, $tag); - $endPosition = $tokenIterator->currentPosition(); + $endPosition = $tokenIterator->currentTokenIndex(); if ($isPrecededByHorizontalWhitespace && property_exists($phpDocTagValueNode, 'description')) { $phpDocTagValueNode->description = Strings::replace( @@ -162,18 +150,16 @@ public function parseTagValue(TokenIterator $tokenIterator, string $tag): PhpDoc */ private function parseChildAndStoreItsPositions(TokenIterator $tokenIterator): PhpDocChildNode { - $betterTokenIterator = $this->tokenIteratorFactory->createFromTokenIterator($tokenIterator); - - $startPosition = $betterTokenIterator->currentPosition(); + $startPosition = $tokenIterator->currentTokenIndex(); try { /** @var PhpDocTextNode|PhpDocTagNode $phpDocNode */ - $phpDocNode = $this->privatesAccessor->callPrivateMethod($this, 'parseChild', [$betterTokenIterator]); + $phpDocNode = $this->privatesAccessor->callPrivateMethod($this, 'parseChild', [$tokenIterator]); } catch (ParserException) { $phpDocNode = new PhpDocTextNode(''); } - $endPosition = $betterTokenIterator->currentPosition(); + $endPosition = $tokenIterator->currentTokenIndex(); $startAndEnd = new StartAndEnd($startPosition, $endPosition); $phpDocNode->setAttribute(PhpDocAttributeKey::START_AND_END, $startAndEnd); @@ -181,7 +167,7 @@ private function parseChildAndStoreItsPositions(TokenIterator $tokenIterator): P return $phpDocNode; } - private function resolveTag(BetterTokenIterator $tokenIterator): string + private function resolveTag(TokenIterator $tokenIterator): string { $tag = $tokenIterator->currentTokenValue(); $tokenIterator->next(); diff --git a/src/BetterPhpDocParser/PhpDocParser/StaticDoctrineAnnotationParser.php b/src/BetterPhpDocParser/PhpDocParser/StaticDoctrineAnnotationParser.php index 9060082495c..e5b3794ecad 100644 --- a/src/BetterPhpDocParser/PhpDocParser/StaticDoctrineAnnotationParser.php +++ b/src/BetterPhpDocParser/PhpDocParser/StaticDoctrineAnnotationParser.php @@ -7,12 +7,13 @@ use PhpParser\Node; use PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprNode; use PHPStan\PhpDocParser\Lexer\Lexer; +use PHPStan\PhpDocParser\Parser\TokenIterator; use Rector\BetterPhpDocParser\PhpDoc\ArrayItemNode; use Rector\BetterPhpDocParser\PhpDoc\DoctrineAnnotationTagValueNode; use Rector\BetterPhpDocParser\PhpDoc\StringNode; use Rector\BetterPhpDocParser\PhpDocParser\StaticDoctrineAnnotationParser\ArrayParser; +use Rector\BetterPhpDocParser\PhpDocParser\StaticDoctrineAnnotationParser\NextTokenType; use Rector\BetterPhpDocParser\PhpDocParser\StaticDoctrineAnnotationParser\PlainValueParser; -use Rector\BetterPhpDocParser\ValueObject\Parser\BetterTokenIterator; use Rector\BetterPhpDocParser\ValueObject\PhpDoc\DoctrineAnnotation\CurlyListNode; /** @@ -32,7 +33,7 @@ public function __construct( * * @return ArrayItemNode[] */ - public function resolveAnnotationMethodCall(BetterTokenIterator $tokenIterator, Node $currentPhpNode): array + public function resolveAnnotationMethodCall(TokenIterator $tokenIterator, Node $currentPhpNode): array { if (! $tokenIterator->isCurrentTokenType(Lexer::TOKEN_OPEN_PARENTHESES)) { return []; @@ -53,14 +54,14 @@ public function resolveAnnotationMethodCall(BetterTokenIterator $tokenIterator, * @return CurlyListNode|string|array|ConstExprNode|DoctrineAnnotationTagValueNode|StringNode */ public function resolveAnnotationValue( - BetterTokenIterator $tokenIterator, + TokenIterator $tokenIterator, Node $currentPhpNode ): CurlyListNode|string|array|ConstExprNode|DoctrineAnnotationTagValueNode|StringNode { // skips dummy tokens like newlines $tokenIterator->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL); // no assign - if (! $tokenIterator->isNextTokenType(Lexer::TOKEN_EQUAL)) { + if (! NextTokenType::is($tokenIterator, Lexer::TOKEN_EQUAL)) { // 1. plain value - mimics https://github.com/doctrine/annotations/blob/0cb0cd2950a5c6cdbf22adbe2bfd5fd1ea68588f/lib/Doctrine/Common/Annotations/DocParser.php#L1234-L1282 return $this->parseValue($tokenIterator, $currentPhpNode); } @@ -84,7 +85,7 @@ public function resolveAnnotationValue( * * @return ArrayItemNode[] */ - private function resolveAnnotationValues(BetterTokenIterator $tokenIterator, Node $currentPhpNode): array + private function resolveAnnotationValues(TokenIterator $tokenIterator, Node $currentPhpNode): array { $values = []; $resolvedValue = $this->resolveAnnotationValue($tokenIterator, $currentPhpNode); @@ -99,7 +100,7 @@ private function resolveAnnotationValues(BetterTokenIterator $tokenIterator, Nod $tokenIterator->next(); // if is next item just closing brackets - if ($tokenIterator->isNextTokenType(Lexer::TOKEN_CLOSE_PARENTHESES)) { + if (NextTokenType::is($tokenIterator, Lexer::TOKEN_CLOSE_PARENTHESES)) { continue; } @@ -123,7 +124,7 @@ private function resolveAnnotationValues(BetterTokenIterator $tokenIterator, Nod * @return CurlyListNode|string|array|ConstExprNode|DoctrineAnnotationTagValueNode|StringNode */ private function parseValue( - BetterTokenIterator $tokenIterator, + TokenIterator $tokenIterator, Node $currentPhpNode ): CurlyListNode|string|array|ConstExprNode|DoctrineAnnotationTagValueNode|StringNode { if ($tokenIterator->isCurrentTokenType(Lexer::TOKEN_OPEN_CURLY_BRACKET)) { diff --git a/src/BetterPhpDocParser/PhpDocParser/StaticDoctrineAnnotationParser/ArrayParser.php b/src/BetterPhpDocParser/PhpDocParser/StaticDoctrineAnnotationParser/ArrayParser.php index ad0c5b2955e..a839dff7c9d 100644 --- a/src/BetterPhpDocParser/PhpDocParser/StaticDoctrineAnnotationParser/ArrayParser.php +++ b/src/BetterPhpDocParser/PhpDocParser/StaticDoctrineAnnotationParser/ArrayParser.php @@ -8,9 +8,9 @@ use PhpParser\Node\Scalar\String_; use PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprIntegerNode; use PHPStan\PhpDocParser\Lexer\Lexer; +use PHPStan\PhpDocParser\Parser\TokenIterator; use Rector\BetterPhpDocParser\PhpDoc\ArrayItemNode; use Rector\BetterPhpDocParser\PhpDoc\StringNode; -use Rector\BetterPhpDocParser\ValueObject\Parser\BetterTokenIterator; /** * @see \Rector\Tests\BetterPhpDocParser\PhpDocParser\StaticDoctrineAnnotationParser\ArrayParserTest @@ -27,7 +27,7 @@ public function __construct( * * @return ArrayItemNode[] */ - public function parseCurlyArray(BetterTokenIterator $tokenIterator, Node $currentPhpNode): array + public function parseCurlyArray(TokenIterator $tokenIterator, Node $currentPhpNode): array { $values = []; @@ -58,7 +58,7 @@ public function parseCurlyArray(BetterTokenIterator $tokenIterator, Node $curren } $values[] = $this->resolveArrayItem($tokenIterator, $currentPhpNode); - if ($tokenIterator->isNextTokenType(Lexer::TOKEN_CLOSE_CURLY_BRACKET)) { + if (NextTokenType::is($tokenIterator, Lexer::TOKEN_CLOSE_CURLY_BRACKET)) { break; } @@ -109,7 +109,7 @@ public function createArrayFromValues(array $values): array * Mimics https://github.com/doctrine/annotations/blob/c66f06b7c83e9a2a7523351a9d5a4b55f885e574/lib/Doctrine/Common/Annotations/DocParser.php#L1354-L1385 * @return array{mixed, mixed} */ - private function resolveArrayItem(BetterTokenIterator $tokenIterator, Node $currentPhpNode): array + private function resolveArrayItem(TokenIterator $tokenIterator, Node $currentPhpNode): array { // skip newlines $tokenIterator->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL); @@ -117,7 +117,7 @@ private function resolveArrayItem(BetterTokenIterator $tokenIterator, Node $curr $key = null; // join "ClassName::CONSTANT_REFERENCE" to identifier - if ($tokenIterator->isNextTokenTypes([Lexer::TOKEN_DOUBLE_COLON])) { + if (NextTokenType::is($tokenIterator, Lexer::TOKEN_DOUBLE_COLON)) { $key = $tokenIterator->currentTokenValue(); // "::" @@ -139,13 +139,13 @@ private function resolveArrayItem(BetterTokenIterator $tokenIterator, Node $curr if ( $tokenIterator->isCurrentTokenType(Lexer::TOKEN_EQUAL, Lexer::TOKEN_COLON) || - $tokenIterator->isNextTokenTypes([Lexer::TOKEN_EQUAL, Lexer::TOKEN_COLON]) + NextTokenType::is($tokenIterator, Lexer::TOKEN_EQUAL, Lexer::TOKEN_COLON) ) { $tokenIterator->tryConsumeTokenType(Lexer::TOKEN_EQUAL); $tokenIterator->tryConsumeTokenType(Lexer::TOKEN_COLON); if ($key === null) { - if ($tokenIterator->isNextTokenType(Lexer::TOKEN_IDENTIFIER)) { + if (NextTokenType::is($tokenIterator, Lexer::TOKEN_IDENTIFIER)) { $key = $this->plainValueParser->parseValue($tokenIterator, $currentPhpNode); } else { $tokenIterator->tryConsumeTokenType(Lexer::TOKEN_COMMA); diff --git a/src/BetterPhpDocParser/PhpDocParser/StaticDoctrineAnnotationParser/NextTokenType.php b/src/BetterPhpDocParser/PhpDocParser/StaticDoctrineAnnotationParser/NextTokenType.php new file mode 100644 index 00000000000..49d2b08688c --- /dev/null +++ b/src/BetterPhpDocParser/PhpDocParser/StaticDoctrineAnnotationParser/NextTokenType.php @@ -0,0 +1,28 @@ +getTokens()[$tokenIterator->currentTokenIndex() + 1])) { + return false; + } + + $tokenIterator->pushSavePoint(); + $tokenIterator->next(); + + $isNextTokenType = $tokenIterator->isCurrentTokenType(...$tokenTypes); + $tokenIterator->rollback(); + + return $isNextTokenType; + } +} diff --git a/src/BetterPhpDocParser/PhpDocParser/StaticDoctrineAnnotationParser/PlainValueParser.php b/src/BetterPhpDocParser/PhpDocParser/StaticDoctrineAnnotationParser/PlainValueParser.php index 01d876dcc68..36e353bade3 100644 --- a/src/BetterPhpDocParser/PhpDocParser/StaticDoctrineAnnotationParser/PlainValueParser.php +++ b/src/BetterPhpDocParser/PhpDocParser/StaticDoctrineAnnotationParser/PlainValueParser.php @@ -11,11 +11,11 @@ use PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprTrueNode; use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode; use PHPStan\PhpDocParser\Lexer\Lexer; +use PHPStan\PhpDocParser\Parser\TokenIterator; use Rector\BetterPhpDocParser\PhpDoc\DoctrineAnnotationTagValueNode; use Rector\BetterPhpDocParser\PhpDoc\StringNode; use Rector\BetterPhpDocParser\PhpDocParser\ClassAnnotationMatcher; use Rector\BetterPhpDocParser\PhpDocParser\StaticDoctrineAnnotationParser; -use Rector\BetterPhpDocParser\ValueObject\Parser\BetterTokenIterator; use Rector\BetterPhpDocParser\ValueObject\PhpDocAttributeKey; final class PlainValueParser @@ -41,7 +41,7 @@ public function autowire( * @return string|mixed[]|ConstExprNode|DoctrineAnnotationTagValueNode|StringNode */ public function parseValue( - BetterTokenIterator $tokenIterator, + TokenIterator $tokenIterator, Node $currentPhpNode ): string|array|ConstExprNode|DoctrineAnnotationTagValueNode|StringNode { $currentTokenValue = $tokenIterator->currentTokenValue(); @@ -76,7 +76,7 @@ public function parseValue( ); } - $start = $tokenIterator->currentPosition(); + $start = $tokenIterator->currentTokenIndex(); // from "quote to quote" if ($currentTokenValue === '"') { @@ -85,15 +85,15 @@ public function parseValue( } while (! str_contains($tokenIterator->currentTokenValue(), '"')); } - $end = $tokenIterator->currentPosition(); + $end = $tokenIterator->currentTokenIndex(); if ($start + 1 < $end) { - return new StringNode($tokenIterator->printFromTo($start, $end)); + return new StringNode($tokenIterator->getContentBetween($start, $end)); } return $currentTokenValue; } - private function parseStringValue(BetterTokenIterator $tokenIterator, string $currentTokenValue): string + private function parseStringValue(TokenIterator $tokenIterator, string $currentTokenValue): string { if ( // start with a quote but doesn't end with one @@ -113,7 +113,7 @@ private function parseStringValue(BetterTokenIterator $tokenIterator, string $cu } private function parseMultilineOrWhiteSpacedString( - BetterTokenIterator $tokenIterator, + TokenIterator $tokenIterator, string $currentTokenValue ): string { while (str_starts_with($currentTokenValue, '"') && ! str_ends_with($currentTokenValue, '"')) { @@ -148,7 +148,7 @@ private function parseMultilineOrWhiteSpacedString( private function parseNestedDoctrineAnnotationTagValueNode( string $currentTokenValue, - BetterTokenIterator $tokenIterator, + TokenIterator $tokenIterator, Node $currentPhpNode ): DoctrineAnnotationTagValueNode { // @todo diff --git a/src/BetterPhpDocParser/ValueObject/Parser/BetterTokenIterator.php b/src/BetterPhpDocParser/ValueObject/Parser/BetterTokenIterator.php deleted file mode 100644 index 54d37f3ea2c..00000000000 --- a/src/BetterPhpDocParser/ValueObject/Parser/BetterTokenIterator.php +++ /dev/null @@ -1,118 +0,0 @@ - $tokens - */ - public function __construct(array $tokens, int $index = 0) - { - if ($tokens === []) { - $index = 0; - } - - parent::__construct($tokens, $index); - } - - /** - * @param int[] $types - */ - public function isNextTokenTypes(array $types): bool - { - return array_any($types, fn (int $type): bool => $this->isNextTokenType($type)); - } - - public function isTokenTypeOnPosition(int $tokenType, int $position): bool - { - $tokens = $this->getTokens(); - $token = $tokens[$position] ?? null; - - if ($token === null) { - return false; - } - - return $token[1] === $tokenType; - } - - public function isNextTokenType(int $tokenType): bool - { - if ($this->nextTokenType() === null) { - return false; - } - - return $this->nextTokenType() === $tokenType; - } - - public function printFromTo(int $from, int $to): string - { - if ($to < $from) { - throw new ShouldNotHappenException('Arguments are flipped'); - } - - $tokens = $this->getTokens(); - - $content = ''; - - foreach ($tokens as $key => $token) { - if ($key < $from) { - continue; - } - - if ($key >= $to) { - continue; - } - - $content .= $token[0]; - } - - return $content; - } - - public function currentPosition(): int - { - return $this->currentTokenIndex(); - } - - public function count(): int - { - return count($this->getTokens()); - } - - /** - * @return array - */ - public function partialTokens(int $start, int $end): array - { - return array_slice($this->getTokens(), $start, $end - $start + 1); - } - - public function containsTokenType(int $type): bool - { - return array_any($this->getTokens(), fn (array $token): bool => $token[1] === $type); - } - - private function nextTokenType(): ?int - { - $tokens = $this->getTokens(); - - // does next token exist? - $nextIndex = $this->currentPosition() + 1; - if (! isset($tokens[$nextIndex])) { - return null; - } - - $this->pushSavePoint(); - $this->next(); - $nextTokenType = $this->currentTokenType(); - $this->rollback(); - - return $nextTokenType; - } -} diff --git a/tests/BetterPhpDocParser/PhpDocNodeMapperTest.php b/tests/BetterPhpDocParser/PhpDocNodeMapperTest.php index 38d38f98df0..42c126a06e3 100644 --- a/tests/BetterPhpDocParser/PhpDocNodeMapperTest.php +++ b/tests/BetterPhpDocParser/PhpDocNodeMapperTest.php @@ -9,8 +9,8 @@ use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode; use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode; use PHPStan\PhpDocParser\Ast\Type\NullableTypeNode; +use PHPStan\PhpDocParser\Parser\TokenIterator; use Rector\BetterPhpDocParser\PhpDocNodeMapper; -use Rector\BetterPhpDocParser\ValueObject\Parser\BetterTokenIterator; use Rector\Testing\PHPUnit\AbstractLazyTestCase; final class PhpDocNodeMapperTest extends AbstractLazyTestCase @@ -28,7 +28,7 @@ public function testParamTag(): void { $phpDocNode = $this->createParamDocNode(); - $phpDocNode = $this->phpDocNodeMapper->transform($phpDocNode, new BetterTokenIterator([])); + $phpDocNode = $this->phpDocNodeMapper->transform($phpDocNode, new TokenIterator([])); $childNode = $phpDocNode->children[0]; $this->assertInstanceOf(PhpDocTagNode::class, $childNode); diff --git a/tests/BetterPhpDocParser/PhpDocParser/StaticDoctrineAnnotationParser/ArrayParserTest.php b/tests/BetterPhpDocParser/PhpDocParser/StaticDoctrineAnnotationParser/ArrayParserTest.php index bb3cbe47a77..51aa1f4cb16 100644 --- a/tests/BetterPhpDocParser/PhpDocParser/StaticDoctrineAnnotationParser/ArrayParserTest.php +++ b/tests/BetterPhpDocParser/PhpDocParser/StaticDoctrineAnnotationParser/ArrayParserTest.php @@ -33,11 +33,11 @@ protected function setUp(): void #[DataProvider('provideData')] public function test(string $docContent, array $expectedArrayItemNodes): void { - $betterTokenIterator = $this->tokenIteratorFactory->create($docContent); + $tokenIterator = $this->tokenIteratorFactory->create($docContent); $string = new String_('some_node'); - $arrayItemNodes = $this->arrayParser->parseCurlyArray($betterTokenIterator, $string); + $arrayItemNodes = $this->arrayParser->parseCurlyArray($tokenIterator, $string); $this->assertEquals($expectedArrayItemNodes, $arrayItemNodes); } diff --git a/tests/BetterPhpDocParser/PhpDocParser/StaticDoctrineAnnotationParser/StaticDoctrineAnnotationParserTest.php b/tests/BetterPhpDocParser/PhpDocParser/StaticDoctrineAnnotationParser/StaticDoctrineAnnotationParserTest.php index d9d19c030fc..8350fc6a359 100644 --- a/tests/BetterPhpDocParser/PhpDocParser/StaticDoctrineAnnotationParser/StaticDoctrineAnnotationParserTest.php +++ b/tests/BetterPhpDocParser/PhpDocParser/StaticDoctrineAnnotationParser/StaticDoctrineAnnotationParserTest.php @@ -34,10 +34,10 @@ protected function setUp(): void #[DataProvider('provideData')] public function test(string $docContent, CurlyListNode|array $expectedValue): void { - $betterTokenIterator = $this->tokenIteratorFactory->create($docContent); + $tokenIterator = $this->tokenIteratorFactory->create($docContent); $string = new String_('some_node'); - $value = $this->staticDoctrineAnnotationParser->resolveAnnotationValue($betterTokenIterator, $string); + $value = $this->staticDoctrineAnnotationParser->resolveAnnotationValue($tokenIterator, $string); // "equals" on purpose to compare 2 object with same content $this->assertEquals($expectedValue, $value);