Skip to content

Commit

Permalink
fixing multispace
Browse files Browse the repository at this point in the history
  • Loading branch information
TomasVotruba committed Mar 19, 2021
1 parent 207326d commit 4a7b8b1
Show file tree
Hide file tree
Showing 7 changed files with 88 additions and 98 deletions.

This file was deleted.

88 changes: 27 additions & 61 deletions packages/BetterPhpDocParser/PhpDocParser/BetterPhpDocParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
use Rector\BetterPhpDocParser\Contract\SpecificPhpDocNodeFactoryInterface;
use Rector\BetterPhpDocParser\Contract\StringTagMatchingPhpDocNodeFactoryInterface;
use Rector\BetterPhpDocParser\PhpDocNodeFactory\MultiPhpDocNodeFactory;
use Rector\BetterPhpDocParser\Printer\MultilineSpaceFormatPreserver;
use Rector\BetterPhpDocParser\ValueObject\StartAndEnd;
use Rector\Core\Configuration\CurrentNodeProvider;
use Rector\Core\Exception\ShouldNotHappenException;
Expand All @@ -40,12 +39,6 @@ final class BetterPhpDocParser extends PhpDocParser
*/
private const TAG_REGEX = '#@(var|param|return|throws|property|deprecated)#';

/**
* @see https://regex101.com/r/iCJqCv/1
* @var string
*/
private const SPACE_REGEX = '#\s+#';

/**
* @var PhpDocNodeFactoryInterface[]
*/
Expand All @@ -66,11 +59,6 @@ final class BetterPhpDocParser extends PhpDocParser
*/
private $attributeAwareNodeFactory;

/**
* @var MultilineSpaceFormatPreserver
*/
private $multilineSpaceFormatPreserver;

/**
* @var CurrentNodeProvider
*/
Expand Down Expand Up @@ -99,7 +87,6 @@ public function __construct(
TypeParser $typeParser,
ConstExprParser $constExprParser,
AttributeAwareNodeFactory $attributeAwareNodeFactory,
MultilineSpaceFormatPreserver $multilineSpaceFormatPreserver,
CurrentNodeProvider $currentNodeProvider,
ClassAnnotationMatcher $classAnnotationMatcher,
AnnotationContentResolver $annotationContentResolver,
Expand All @@ -108,15 +95,14 @@ public function __construct(
) {
parent::__construct($typeParser, $constExprParser);

$this->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;
}

Expand Down Expand Up @@ -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 = '#(?<line>' . 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;
}

Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
29 changes: 20 additions & 9 deletions packages/BetterPhpDocParser/Printer/PhpDocInfoPrinter.php
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ private function printNode(
$this->multilineSpaceFormatPreserver->fixMultilineDescriptions($node);

if ($startAndEnd !== null) {
$isLastToken = ($nodeCount === $key);
$isLastToken = $nodeCount === $key;

$output = $this->addTokensFromTo(
$output,
Expand Down Expand Up @@ -311,7 +311,6 @@ private function printPhpDocTagNode(
string $output
): string {
$output .= $phpDocTagNode->name;

$phpDocTagNodeValue = $phpDocTagNode->value;

$nodeOutput = $this->printNode($phpDocTagNodeValue, $startAndEnd);
Expand Down Expand Up @@ -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);
}

Expand All @@ -351,30 +349,42 @@ private function printAttributeWithAsterisk(Node $node): string
*/
private function getRemovedNodesPositions(): array
{
if ($this->removedNodePositions !== []) {
return $this->removedNodePositions;
}
$removedNodePositions = [];

$removedNodes = array_diff(
$this->phpDocInfo->getOriginalPhpDocNode()
->children,
$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;
}

/**
Expand All @@ -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] ?? '';
Expand Down
23 changes: 11 additions & 12 deletions packages/BetterPhpDocParser/Printer/WhitespaceDetector.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 */
Expand All @@ -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;
Expand All @@ -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');
Expand Down
5 changes: 5 additions & 0 deletions phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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#'
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

namespace Rector\Tests\TypeDeclaration\Rector\FunctionLike\ParamTypeDeclarationRector\FixtureUnionType;

/**
* @param int $b
* @param int|void $c
*/
function someFunction($b, $c) {
}

?>
-----
<?php

namespace Rector\Tests\TypeDeclaration\Rector\FunctionLike\ParamTypeDeclarationRector\FixtureUnionType;

/**
* @param int|void $c
*/
function someFunction(int $b, $c) {
}

?>

0 comments on commit 4a7b8b1

Please sign in to comment.