2019-10-13 07:59:52 +02:00
|
|
|
<?php
|
|
|
|
|
|
|
|
declare(strict_types=1);
|
2019-02-28 22:50:53 +01:00
|
|
|
|
|
|
|
namespace Rector\BetterPhpDocParser\PhpDocInfo;
|
|
|
|
|
|
|
|
use PhpParser\Node;
|
|
|
|
use PHPStan\PhpDocParser\Lexer\Lexer;
|
|
|
|
use PHPStan\PhpDocParser\Parser\PhpDocParser;
|
|
|
|
use PHPStan\PhpDocParser\Parser\TokenIterator;
|
2020-01-12 21:30:57 +01:00
|
|
|
use Rector\AttributeAwarePhpDoc\Ast\PhpDoc\AttributeAwarePhpDocNode;
|
2019-02-28 22:50:53 +01:00
|
|
|
use Rector\BetterPhpDocParser\Attributes\Attribute\Attribute;
|
2019-09-27 16:25:15 +02:00
|
|
|
use Rector\BetterPhpDocParser\Contract\PhpDocNode\AttributeAwareNodeInterface;
|
|
|
|
use Rector\BetterPhpDocParser\Contract\PhpDocNodeFactoryInterface;
|
2020-01-29 14:36:09 +01:00
|
|
|
use Rector\BetterPhpDocParser\ValueObject\StartEndValueObject;
|
2019-08-26 11:37:02 +02:00
|
|
|
use Rector\Configuration\CurrentNodeProvider;
|
2020-01-29 14:36:09 +01:00
|
|
|
use Rector\NodeTypeResolver\Node\AttributeKey;
|
2020-02-02 19:15:36 +01:00
|
|
|
use Rector\NodeTypeResolver\PHPStan\TypeComparator;
|
2019-09-06 12:30:58 +02:00
|
|
|
use Rector\NodeTypeResolver\StaticTypeMapper;
|
2019-02-28 22:50:53 +01:00
|
|
|
|
|
|
|
final class PhpDocInfoFactory
|
|
|
|
{
|
|
|
|
/**
|
|
|
|
* @var PhpDocParser
|
|
|
|
*/
|
|
|
|
private $phpDocParser;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @var Lexer
|
|
|
|
*/
|
|
|
|
private $lexer;
|
|
|
|
|
2019-08-26 11:37:02 +02:00
|
|
|
/**
|
|
|
|
* @var CurrentNodeProvider
|
|
|
|
*/
|
|
|
|
private $currentNodeProvider;
|
|
|
|
|
2019-09-06 12:30:58 +02:00
|
|
|
/**
|
|
|
|
* @var StaticTypeMapper
|
|
|
|
*/
|
|
|
|
private $staticTypeMapper;
|
|
|
|
|
2020-02-02 19:15:36 +01:00
|
|
|
/**
|
|
|
|
* @var TypeComparator
|
|
|
|
*/
|
|
|
|
private $typeComparator;
|
|
|
|
|
2019-02-28 22:50:53 +01:00
|
|
|
public function __construct(
|
|
|
|
PhpDocParser $phpDocParser,
|
|
|
|
Lexer $lexer,
|
2019-09-06 12:30:58 +02:00
|
|
|
CurrentNodeProvider $currentNodeProvider,
|
2020-02-02 19:15:36 +01:00
|
|
|
StaticTypeMapper $staticTypeMapper,
|
|
|
|
TypeComparator $typeComparator
|
2019-02-28 22:50:53 +01:00
|
|
|
) {
|
|
|
|
$this->phpDocParser = $phpDocParser;
|
|
|
|
$this->lexer = $lexer;
|
2019-08-26 11:37:02 +02:00
|
|
|
$this->currentNodeProvider = $currentNodeProvider;
|
2019-09-06 12:30:58 +02:00
|
|
|
$this->staticTypeMapper = $staticTypeMapper;
|
2020-02-02 19:15:36 +01:00
|
|
|
$this->typeComparator = $typeComparator;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function createFromString(Node $node, string $content): PhpDocInfo
|
|
|
|
{
|
|
|
|
$tokens = $this->lexer->tokenize($content);
|
|
|
|
$phpDocNode = $this->parseTokensToPhpDocNode($tokens);
|
|
|
|
|
|
|
|
$phpDocInfo = new PhpDocInfo(
|
|
|
|
$phpDocNode,
|
|
|
|
$tokens,
|
|
|
|
$content,
|
|
|
|
$this->staticTypeMapper,
|
|
|
|
$node,
|
|
|
|
$this->typeComparator
|
|
|
|
);
|
|
|
|
|
|
|
|
$node->setAttribute(AttributeKey::PHP_DOC_INFO, $phpDocInfo);
|
|
|
|
|
|
|
|
return $phpDocInfo;
|
2019-02-28 22:50:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public function createFromNode(Node $node): PhpDocInfo
|
|
|
|
{
|
2020-01-30 22:11:29 +01:00
|
|
|
/** needed for @see PhpDocNodeFactoryInterface */
|
|
|
|
$this->currentNodeProvider->setNode($node);
|
|
|
|
|
|
|
|
if ($node->getDocComment() === null) {
|
2020-02-02 19:15:36 +01:00
|
|
|
if ($node->getComments() !== []) {
|
|
|
|
$content = $this->createCommentsString($node);
|
|
|
|
$tokens = $this->lexer->tokenize($content);
|
|
|
|
$phpDocNode = $this->parseTokensToPhpDocNode($tokens);
|
|
|
|
} else {
|
|
|
|
$content = '';
|
|
|
|
$tokens = [];
|
|
|
|
$phpDocNode = new AttributeAwarePhpDocNode([]);
|
|
|
|
}
|
2020-01-30 22:11:29 +01:00
|
|
|
} else {
|
|
|
|
$content = $node->getDocComment()->getText();
|
|
|
|
$tokens = $this->lexer->tokenize($content);
|
2020-02-02 19:15:36 +01:00
|
|
|
$phpDocNode = $this->parseTokensToPhpDocNode($tokens);
|
|
|
|
$this->setPositionOfLastToken($phpDocNode);
|
2019-09-18 12:22:12 +02:00
|
|
|
}
|
|
|
|
|
2020-02-02 19:15:36 +01:00
|
|
|
$phpDocInfo = new PhpDocInfo(
|
|
|
|
$phpDocNode,
|
|
|
|
$tokens,
|
|
|
|
$content,
|
|
|
|
$this->staticTypeMapper,
|
|
|
|
$node,
|
|
|
|
$this->typeComparator
|
|
|
|
);
|
2020-01-29 14:36:09 +01:00
|
|
|
$node->setAttribute(AttributeKey::PHP_DOC_INFO, $phpDocInfo);
|
2019-09-18 12:22:12 +02:00
|
|
|
|
|
|
|
return $phpDocInfo;
|
2019-02-28 22:50:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Needed for printing
|
|
|
|
*/
|
2020-02-02 19:15:36 +01:00
|
|
|
private function setPositionOfLastToken(AttributeAwarePhpDocNode $attributeAwarePhpDocNode): void
|
|
|
|
{
|
2019-02-28 22:50:53 +01:00
|
|
|
if ($attributeAwarePhpDocNode->children === []) {
|
2020-02-02 19:15:36 +01:00
|
|
|
return;
|
2019-02-28 22:50:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
$phpDocChildNodes = $attributeAwarePhpDocNode->children;
|
2019-07-04 12:26:39 +03:00
|
|
|
/** @var AttributeAwareNodeInterface $lastChildNode */
|
2019-02-28 22:50:53 +01:00
|
|
|
$lastChildNode = array_pop($phpDocChildNodes);
|
|
|
|
|
2020-01-29 14:36:09 +01:00
|
|
|
/** @var StartEndValueObject $startEndValueObject */
|
|
|
|
$startEndValueObject = $lastChildNode->getAttribute(Attribute::START_END);
|
|
|
|
|
|
|
|
if ($startEndValueObject !== null) {
|
|
|
|
$attributeAwarePhpDocNode->setAttribute(Attribute::LAST_TOKEN_POSITION, $startEndValueObject->getEnd());
|
2019-02-28 22:50:53 +01:00
|
|
|
}
|
2020-02-02 19:15:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
private function createCommentsString(Node $node): string
|
|
|
|
{
|
|
|
|
return implode('', $node->getComments());
|
|
|
|
}
|
|
|
|
|
|
|
|
private function parseTokensToPhpDocNode(array $tokens): AttributeAwarePhpDocNode
|
|
|
|
{
|
|
|
|
$tokenIterator = new TokenIterator($tokens);
|
2019-02-28 22:50:53 +01:00
|
|
|
|
2020-02-02 19:15:36 +01:00
|
|
|
return $this->phpDocParser->parse($tokenIterator);
|
2019-02-28 22:50:53 +01:00
|
|
|
}
|
|
|
|
}
|