From 4a7b8b196149c77d9a39a231556321317383d78e Mon Sep 17 00:00:00 2001 From: TomasVotruba Date: Fri, 19 Mar 2021 14:05:59 +0100 Subject: [PATCH] fixing multispace --- .../DoctrineTable/TableWithIndexes.php | 16 ---- .../PhpDocParser/BetterPhpDocParser.php | 88 ++++++------------- .../Printer/MultilineSpaceFormatPreserver.php | 1 + .../Printer/PhpDocInfoPrinter.php | 29 ++++-- .../Printer/WhitespaceDetector.php | 23 +++-- phpstan.neon | 5 ++ .../FixtureUnionType/undesired_int.php.inc | 24 +++++ 7 files changed, 88 insertions(+), 98 deletions(-) delete mode 100644 packages-tests/BetterPhpDocParser/PhpDocParser/TagValueNodeReprint/Fixture/DoctrineTable/TableWithIndexes.php create mode 100644 rules-tests/TypeDeclaration/Rector/FunctionLike/ParamTypeDeclarationRector/FixtureUnionType/undesired_int.php.inc diff --git a/packages-tests/BetterPhpDocParser/PhpDocParser/TagValueNodeReprint/Fixture/DoctrineTable/TableWithIndexes.php b/packages-tests/BetterPhpDocParser/PhpDocParser/TagValueNodeReprint/Fixture/DoctrineTable/TableWithIndexes.php deleted file mode 100644 index a7cb63e8213f..000000000000 --- a/packages-tests/BetterPhpDocParser/PhpDocParser/TagValueNodeReprint/Fixture/DoctrineTable/TableWithIndexes.php +++ /dev/null @@ -1,16 +0,0 @@ -setPhpDocNodeFactories($phpDocNodeFactories); + $this->privatesCaller = new PrivatesCaller(); $this->privatesAccessor = new PrivatesAccessor(); $this->attributeAwareNodeFactory = $attributeAwareNodeFactory; - $this->multilineSpaceFormatPreserver = $multilineSpaceFormatPreserver; $this->currentNodeProvider = $currentNodeProvider; $this->classAnnotationMatcher = $classAnnotationMatcher; $this->annotationContentResolver = $annotationContentResolver; - - $this->setPhpDocNodeFactories($phpDocNodeFactories); $this->stringTagMatchingPhpDocNodeFactories = $stringTagMatchingPhpDocNodeFactories; } @@ -234,26 +220,6 @@ private function parseChildAndStoreItsPositions(TokenIterator $tokenIterator): N $attributeAwareNode = $this->attributeAwareNodeFactory->createFromNode($phpDocNode, $docContent); $attributeAwareNode->setAttribute(Attribute::START_END, $startAndEnd); - $possibleMultilineText = $this->multilineSpaceFormatPreserver->resolveCurrentPhpDocNodeText( - $attributeAwareNode - ); - - if ($possibleMultilineText) { - // add original text, for keeping trimmed spaces - $originalContent = $this->getOriginalContentFromTokenIterator($tokenIterator); - - // we try to match original content without trimmed spaces - $currentTextPattern = '#(?' . preg_quote($possibleMultilineText, '#') . ')#s'; - - $currentTextPattern = Strings::replace($currentTextPattern, self::SPACE_REGEX, '\s+'); - - $match = Strings::match($originalContent, $currentTextPattern); - - if (isset($match['line'])) { - $attributeAwareNode->setAttribute(Attribute::ORIGINAL_CONTENT, $match['line']); - } - } - return $attributeAwareNode; } @@ -330,31 +296,31 @@ private function resolveTokenEnd(TokenIterator $tokenIterator): int return $this->adjustTokenEndToFitClassAnnotation($tokenIterator, $tokenEnd); } - private function getOriginalContentFromTokenIterator(TokenIterator $tokenIterator): string - { - $originalTokens = $this->privatesAccessor->getPrivateProperty($tokenIterator, 'tokens'); - $originalContent = ''; - - foreach ($originalTokens as $originalToken) { - // skip opening - if ($originalToken[1] === Lexer::TOKEN_OPEN_PHPDOC) { - continue; - } - - // skip closing - if ($originalToken[1] === Lexer::TOKEN_CLOSE_PHPDOC) { - continue; - } - - if ($originalToken[1] === Lexer::TOKEN_PHPDOC_EOL) { - $originalToken[0] = PHP_EOL; - } - - $originalContent .= $originalToken[0]; - } - - return trim($originalContent); - } +// private function getOriginalContentFromTokenIterator(TokenIterator $tokenIterator): string +// { +// $originalTokens = $this->privatesAccessor->getPrivateProperty($tokenIterator, 'tokens'); +// $originalContent = ''; +// +// foreach ($originalTokens as $originalToken) { +// // skip opening +// if ($originalToken[1] === Lexer::TOKEN_OPEN_PHPDOC) { +// continue; +// } +// +// // skip closing +// if ($originalToken[1] === Lexer::TOKEN_CLOSE_PHPDOC) { +// continue; +// } +// +// if ($originalToken[1] === Lexer::TOKEN_PHPDOC_EOL) { +// $originalToken[0] = PHP_EOL; +// } +// +// $originalContent .= $originalToken[0]; +// } +// +// return trim($originalContent); +// } /** * @see https://github.com/rectorphp/rector/issues/2158 diff --git a/packages/BetterPhpDocParser/Printer/MultilineSpaceFormatPreserver.php b/packages/BetterPhpDocParser/Printer/MultilineSpaceFormatPreserver.php index 384513e0019d..5c88309cafb8 100644 --- a/packages/BetterPhpDocParser/Printer/MultilineSpaceFormatPreserver.php +++ b/packages/BetterPhpDocParser/Printer/MultilineSpaceFormatPreserver.php @@ -68,6 +68,7 @@ private function restoreOriginalSpacingInText(Node $node): ?Node /** @var string $originalContent */ $originalContent = $node->getAttribute(Attribute::ORIGINAL_CONTENT); $oldSpaces = Strings::matchAll($originalContent, '#\s+#ms'); + $currentText = $this->resolveCurrentPhpDocNodeText($node); if ($currentText === null) { return null; diff --git a/packages/BetterPhpDocParser/Printer/PhpDocInfoPrinter.php b/packages/BetterPhpDocParser/Printer/PhpDocInfoPrinter.php index f57383f0d321..95a84cc1d7bd 100644 --- a/packages/BetterPhpDocParser/Printer/PhpDocInfoPrinter.php +++ b/packages/BetterPhpDocParser/Printer/PhpDocInfoPrinter.php @@ -231,7 +231,7 @@ private function printNode( $this->multilineSpaceFormatPreserver->fixMultilineDescriptions($node); if ($startAndEnd !== null) { - $isLastToken = ($nodeCount === $key); + $isLastToken = $nodeCount === $key; $output = $this->addTokensFromTo( $output, @@ -311,7 +311,6 @@ private function printPhpDocTagNode( string $output ): string { $output .= $phpDocTagNode->name; - $phpDocTagNodeValue = $phpDocTagNode->value; $nodeOutput = $this->printNode($phpDocTagNodeValue, $startAndEnd); @@ -342,7 +341,6 @@ private function printPhpDocTagNode( private function printAttributeWithAsterisk(Node $node): string { $content = (string) $node; - return $this->explodeAndImplode($content, PHP_EOL, self::NEWLINE_ASTERISK); } @@ -351,9 +349,7 @@ private function printAttributeWithAsterisk(Node $node): string */ private function getRemovedNodesPositions(): array { - if ($this->removedNodePositions !== []) { - return $this->removedNodePositions; - } + $removedNodePositions = []; $removedNodes = array_diff( $this->phpDocInfo->getOriginalPhpDocNode() @@ -361,20 +357,34 @@ private function getRemovedNodesPositions(): array $this->attributeAwarePhpDocNode->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 ($this->tokens[$seekPosition][1] !== Lexer::TOKEN_HORIZONTAL_WS) { + + 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; } - $this->removedNodePositions[] = new StartAndEnd($seekPosition - 1, $removedPhpDocNodeInfo->getEnd()); + $lastEndPosition = $removedPhpDocNodeInfo->getEnd(); + + $removedNodePositions[] = new StartAndEnd(max(0, $seekPosition - 1), $removedPhpDocNodeInfo->getEnd()); } - return $this->removedNodePositions; + return $removedNodePositions; } /** @@ -385,6 +395,7 @@ private function appendToOutput(string $output, int $from, int $to, array $posit for ($i = $from; $i < $to; ++$i) { while (isset($positionJumpSet[$i])) { $i = $positionJumpSet[$i]; + continue; } $output .= $this->tokens[$i][0] ?? ''; diff --git a/packages/BetterPhpDocParser/Printer/WhitespaceDetector.php b/packages/BetterPhpDocParser/Printer/WhitespaceDetector.php index db9f6509ded1..f5d7ecd0c7ec 100644 --- a/packages/BetterPhpDocParser/Printer/WhitespaceDetector.php +++ b/packages/BetterPhpDocParser/Printer/WhitespaceDetector.php @@ -8,8 +8,8 @@ use Nette\Utils\Strings; use PHPStan\PhpDocParser\Ast\Node; use PHPStan\PhpDocParser\Lexer\Lexer; -use Rector\BetterPhpDocParser\Contract\Doctrine\DoctrineTagNodeInterface; -use Rector\BetterPhpDocParser\Contract\PhpDocNode\ShortNameAwareTagInterface; +//use Rector\BetterPhpDocParser\Contract\Doctrine\DoctrineTagNodeInterface; +//use Rector\BetterPhpDocParser\Contract\PhpDocNode\ShortNameAwareTagInterface; use Rector\BetterPhpDocParser\ValueObject\StartAndEnd; final class WhitespaceDetector @@ -29,11 +29,6 @@ public function detectOldWhitespaces(Node $node, array $tokens, StartAndEnd $sta $oldWhitespaces = []; $start = $startAndEnd->getStart(); - // this is needed, because of 1 token taken from tokens and added annotation name: "ORM" + "\X" → "ORM\X" - // todo, this might be needed to be dynamic, based on taken tokens count (some Collector?) - if ($node instanceof DoctrineTagNodeInterface) { - --$start; - } for ($i = $start; $i < $startAndEnd->getEnd(); ++$i) { /** @var string $tokenValue */ @@ -42,11 +37,7 @@ public function detectOldWhitespaces(Node $node, array $tokens, StartAndEnd $sta if ($tokens[$i][1] === Lexer::TOKEN_HORIZONTAL_WS) { // give back "\s+\*" as well // do not overlap to previous node - if (($node instanceof DoctrineTagNodeInterface || $node instanceof ShortNameAwareTagInterface) && - $i - 1 > $start && - isset($tokens[$i - 1]) && - $tokens[$i - 1][1] === Lexer::TOKEN_PHPDOC_EOL - ) { + if ($i - 1 > $start && isset($tokens[$i - 1]) && $tokens[$i - 1][1] === Lexer::TOKEN_PHPDOC_EOL) { $previousTokenValue = $tokens[$i - 1][0]; if (Strings::match($previousTokenValue, self::SPACE_BEFORE_ASTERISK_REGEX)) { $tokenValue = $previousTokenValue . $tokenValue; @@ -57,6 +48,14 @@ public function detectOldWhitespaces(Node $node, array $tokens, StartAndEnd $sta continue; } + // fixes phpdoc parser multiline spaces BC break https://github.com/phpstan/phpdoc-parser/commit/b451b2f27a97c8c288de63db79c2a843727d4326 + if ($tokens[$i][1] === Lexer::TOKEN_PHPDOC_EOL) { + $nextToken = $tokens[$i + 1]; + if ($nextToken[1] !== Lexer::TOKEN_HORIZONTAL_WS) { + $oldWhitespaces[] = $tokens[$i][0]; + } + } + // quoted string with spaces? if ($this->isQuotedStringWithSpaces($tokens, $i)) { $matches = Strings::matchAll($tokenValue, '#\s+#m'); diff --git a/phpstan.neon b/phpstan.neon index 5b08e1c40173..6b4c5e6403f8 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -118,6 +118,7 @@ parameters: - message: '#Class cognitive complexity is \d+, keep it under \d+#' paths: + - packages/BetterPhpDocParser/Printer/PhpDocInfoPrinter.php - rules/Php70/EregToPcreTransformer.php - packages/NodeCollector/NodeCollector/NodeRepository.php - packages/NodeTypeResolver/NodeTypeResolver.php @@ -593,3 +594,7 @@ parameters: # PHP 7_4 literal syntax - '#Property PhpParser\\Node\\Scalar\\DNumber\:\:\$value \(float\|int\) does not accept string#' + + - '#Cognitive complexity for "Rector\\BetterPhpDocParser\\Printer\\WhitespaceDetector\:\:detectOldWhitespaces\(\)" is 20, keep it under 9#' + - '#Method Rector\\PHPStanStaticTypeMapper\\TypeMapper\\ArrayTypeMapper\:\:narrowConstantArrayTypeOfUnionType\(\) should return PHPStan\\PhpDocParser\\Ast\\Type\\TypeNode\|null but returns PHPStan\\PhpDocParser\\Ast\\Node#' + - '#Method Rector\\PHPStanStaticTypeMapper\\TypeMapper\\ObjectTypeMapper\:\:mapToPHPStanPhpDocTypeNode\(\) should return PHPStan\\PhpDocParser\\Ast\\Type\\TypeNode but returns PHPStan\\PhpDocParser\\Ast\\Node#' diff --git a/rules-tests/TypeDeclaration/Rector/FunctionLike/ParamTypeDeclarationRector/FixtureUnionType/undesired_int.php.inc b/rules-tests/TypeDeclaration/Rector/FunctionLike/ParamTypeDeclarationRector/FixtureUnionType/undesired_int.php.inc new file mode 100644 index 000000000000..0b9d61e74239 --- /dev/null +++ b/rules-tests/TypeDeclaration/Rector/FunctionLike/ParamTypeDeclarationRector/FixtureUnionType/undesired_int.php.inc @@ -0,0 +1,24 @@ + +----- +