add reference support to ParamTypeDeclarationRector

This commit is contained in:
Tomas Votruba 2019-07-15 21:01:00 +02:00
parent b38f7fa2f8
commit 48449eed0c
3 changed files with 75 additions and 0 deletions

View File

@ -96,6 +96,10 @@ final class AttributeAwareNodeFactory
return $this->createFromPhpDocValueNode($node);
}
if ($node instanceof TypeNode) {
return $this->createFromTypeNode($node);
}
throw new ShouldNotHappenException(sprintf('Node "%s" was missed in "%s".', get_class($node), __METHOD__));
}

View File

@ -3,10 +3,39 @@
namespace Rector\BetterPhpDocParser\Attributes\Ast\PhpDoc;
use PHPStan\PhpDocParser\Ast\PhpDoc\ParamTagValueNode;
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
use Rector\BetterPhpDocParser\Attributes\Attribute\AttributeTrait;
use Rector\BetterPhpDocParser\Attributes\Contract\Ast\AttributeAwareNodeInterface;
final class AttributeAwareParamTagValueNode extends ParamTagValueNode implements AttributeAwareNodeInterface
{
use AttributeTrait;
/**
* @var bool
*/
private $isReference = false;
/**
* The constructor override is needed to add support for reference &
* @see https://github.com/rectorphp/rector/issues/1734
*/
public function __construct(
TypeNode $typeNode,
bool $isVariadic,
string $parameterName,
string $description,
bool $isReference
) {
parent::__construct($typeNode, $isVariadic, $parameterName, $description);
$this->isReference = $isReference;
}
public function __toString(): string
{
$variadic = $this->isVariadic ? '...' : '';
$reference = $this->isReference ? '&' : '';
return trim("{$this->type} {$variadic}{$reference}{$this->parameterName} {$this->description}");
}
}

View File

@ -4,6 +4,8 @@ namespace Rector\BetterPhpDocParser\PhpDocParser;
use Nette\Utils\Strings;
use PHPStan\PhpDocParser\Ast\Node;
use PHPStan\PhpDocParser\Ast\PhpDoc\InvalidTagValueNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\ParamTagValueNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagValueNode;
use PHPStan\PhpDocParser\Lexer\Lexer;
@ -13,6 +15,7 @@ use PHPStan\PhpDocParser\Parser\PhpDocParser;
use PHPStan\PhpDocParser\Parser\TokenIterator;
use PHPStan\PhpDocParser\Parser\TypeParser;
use Rector\BetterPhpDocParser\Attributes\Ast\AttributeAwareNodeFactory;
use Rector\BetterPhpDocParser\Attributes\Ast\PhpDoc\AttributeAwareParamTagValueNode;
use Rector\BetterPhpDocParser\Attributes\Ast\PhpDoc\AttributeAwarePhpDocNode;
use Rector\BetterPhpDocParser\Attributes\Attribute\Attribute;
use Rector\BetterPhpDocParser\Data\StartEndInfo;
@ -100,6 +103,25 @@ final class BetterPhpDocParser extends PhpDocParser
public function parseTagValue(TokenIterator $tokenIterator, string $tag): PhpDocTagValueNode
{
// needed for reference support in params, see https://github.com/rectorphp/rector/issues/1734
if ($tag === '@param') {
try {
$tokenIterator->pushSavePoint();
$tagValue = $this->parseParamTagValue($tokenIterator);
$tokenIterator->dropSavePoint();
} catch (ParserException $parserException) {
$tokenIterator->rollback();
$description = $this->privatesCaller->callPrivateMethod(
$this,
'parseOptionalDescription',
$tokenIterator
);
$tagValue = new InvalidTagValueNode($description, $parserException);
}
return $tagValue;
}
$tagValueNode = parent::parseTagValue($tokenIterator, $tag);
return $this->attributeAwareNodeFactory->createFromNode($tagValueNode);
@ -163,4 +185,24 @@ final class BetterPhpDocParser extends PhpDocParser
return trim($originalContent);
}
/**
* Override of parent private method to allow reference: https://github.com/rectorphp/rector/pull/1735
*/
private function parseParamTagValue(TokenIterator $tokenIterator): ParamTagValueNode
{
$typeParser = $this->privatesAccessor->getPrivateProperty($this, 'typeParser');
$type = $typeParser->parse($tokenIterator);
$isVariadic = $tokenIterator->tryConsumeTokenType(Lexer::TOKEN_VARIADIC);
// extra value over parent
$isReference = $tokenIterator->tryConsumeTokenType(Lexer::TOKEN_REFERENCE);
$parameterName = $this->privatesCaller->callPrivateMethod($this, 'parseRequiredVariableName', $tokenIterator);
$description = $this->privatesCaller->callPrivateMethod($this, 'parseOptionalDescription', $tokenIterator);
return new AttributeAwareParamTagValueNode($type, $isVariadic, $parameterName, $description, $isReference);
}
}