mirror of
https://github.com/rectorphp/rector.git
synced 2025-01-18 05:48:21 +01:00
doc block manipulator refactoring to object
This commit is contained in:
parent
9f7030c5ce
commit
b32ab6c01e
@ -38,6 +38,7 @@ expectedArguments(
|
||||
\Rector\NodeTypeResolver\Node\AttributeKey::START_TOKEN_POSITION,
|
||||
\Rector\NodeTypeResolver\Node\AttributeKey::ORIGINAL_NODE,
|
||||
\Rector\NodeTypeResolver\Node\AttributeKey::IS_UNREACHABLE,
|
||||
\Rector\NodeTypeResolver\Node\AttributeKey::PHP_DOC_INFO,
|
||||
);
|
||||
|
||||
expectedArguments(
|
||||
@ -61,4 +62,5 @@ expectedArguments(
|
||||
\Rector\NodeTypeResolver\Node\AttributeKey::START_TOKEN_POSITION,
|
||||
\Rector\NodeTypeResolver\Node\AttributeKey::ORIGINAL_NODE,
|
||||
\Rector\NodeTypeResolver\Node\AttributeKey::IS_UNREACHABLE,
|
||||
\Rector\NodeTypeResolver\Node\AttributeKey::PHP_DOC_INFO,
|
||||
);
|
||||
|
@ -4,6 +4,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace Rector\BetterPhpDocParser\Attributes\Attribute;
|
||||
|
||||
use Rector\BetterPhpDocParser\ValueObject\StartEndValueObject;
|
||||
|
||||
final class Attribute
|
||||
{
|
||||
/**
|
||||
@ -12,9 +14,10 @@ final class Attribute
|
||||
public const HAS_DESCRIPTION_WITH_ORIGINAL_SPACES = 'has_description_with_restored_spaces';
|
||||
|
||||
/**
|
||||
* @experiment
|
||||
* @var string
|
||||
*/
|
||||
public const PHP_DOC_NODE_INFO = 'php_doc_node_info';
|
||||
public const START_END = StartEndValueObject::class;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
|
@ -6,6 +6,7 @@ namespace Rector\BetterPhpDocParser\PhpDocInfo;
|
||||
|
||||
use Nette\Utils\Strings;
|
||||
use PhpParser\Node;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocChildNode;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagValueNode;
|
||||
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
|
||||
@ -16,7 +17,9 @@ use Rector\AttributeAwarePhpDoc\Ast\PhpDoc\AttributeAwarePhpDocNode;
|
||||
use Rector\AttributeAwarePhpDoc\Ast\PhpDoc\AttributeAwareReturnTagValueNode;
|
||||
use Rector\AttributeAwarePhpDoc\Ast\PhpDoc\AttributeAwareVarTagValueNode;
|
||||
use Rector\BetterPhpDocParser\Annotation\AnnotationNaming;
|
||||
use Rector\BetterPhpDocParser\Attributes\Ast\PhpDoc\SpacelessPhpDocTagNode;
|
||||
use Rector\BetterPhpDocParser\Contract\PhpDocNode\AttributeAwareNodeInterface;
|
||||
use Rector\BetterPhpDocParser\PhpDocNode\AbstractTagValueNode;
|
||||
use Rector\Exception\ShouldNotHappenException;
|
||||
use Rector\NodeTypeResolver\StaticTypeMapper;
|
||||
|
||||
@ -78,6 +81,17 @@ final class PhpDocInfo
|
||||
return $this->originalContent;
|
||||
}
|
||||
|
||||
public function addPhpDocTagNode(PhpDocChildNode $phpDocChildNode): void
|
||||
{
|
||||
$this->phpDocNode->children[] = $phpDocChildNode;
|
||||
}
|
||||
|
||||
public function addTagValueNodeWithShortName(AbstractTagValueNode $tagValueNode): void
|
||||
{
|
||||
$spacelessPhpDocTagNode = new SpacelessPhpDocTagNode($tagValueNode::SHORT_NAME, $tagValueNode);
|
||||
$this->addPhpDocTagNode($spacelessPhpDocTagNode);
|
||||
}
|
||||
|
||||
public function getPhpDocNode(): AttributeAwarePhpDocNode
|
||||
{
|
||||
return $this->phpDocNode;
|
||||
|
@ -12,8 +12,9 @@ use Rector\AttributeAwarePhpDoc\Ast\PhpDoc\AttributeAwarePhpDocNode;
|
||||
use Rector\BetterPhpDocParser\Attributes\Attribute\Attribute;
|
||||
use Rector\BetterPhpDocParser\Contract\PhpDocNode\AttributeAwareNodeInterface;
|
||||
use Rector\BetterPhpDocParser\Contract\PhpDocNodeFactoryInterface;
|
||||
use Rector\BetterPhpDocParser\ValueObject\StartEndValueObject;
|
||||
use Rector\Configuration\CurrentNodeProvider;
|
||||
use Rector\Exception\ShouldNotHappenException;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
use Rector\NodeTypeResolver\StaticTypeMapper;
|
||||
|
||||
final class PhpDocInfoFactory
|
||||
@ -38,11 +39,6 @@ final class PhpDocInfoFactory
|
||||
*/
|
||||
private $staticTypeMapper;
|
||||
|
||||
/**
|
||||
* @var PhpDocInfo[]
|
||||
*/
|
||||
private $phpDocInfoByObjectHash = [];
|
||||
|
||||
public function __construct(
|
||||
PhpDocParser $phpDocParser,
|
||||
Lexer $lexer,
|
||||
@ -57,41 +53,16 @@ final class PhpDocInfoFactory
|
||||
|
||||
public function createFromNode(Node $node): PhpDocInfo
|
||||
{
|
||||
$hash = $this->createUniqueDocNodeHash($node);
|
||||
|
||||
if (isset($this->phpDocInfoByObjectHash[$hash])) {
|
||||
return $this->phpDocInfoByObjectHash[$hash];
|
||||
if ($node->hasAttribute(AttributeKey::PHP_DOC_INFO)) {
|
||||
return $node->getAttribute(AttributeKey::PHP_DOC_INFO);
|
||||
}
|
||||
|
||||
/** needed for @see PhpDocNodeFactoryInterface */
|
||||
$this->currentNodeProvider->setNode($node);
|
||||
|
||||
$content = $node->getDocComment()->getText();
|
||||
$tokens = $this->lexer->tokenize($content);
|
||||
|
||||
$tokenIterator = new TokenIterator($tokens);
|
||||
|
||||
/** @var AttributeAwarePhpDocNode $phpDocNode */
|
||||
$phpDocNode = $this->phpDocParser->parse($tokenIterator);
|
||||
$phpDocNode = $this->setPositionOfLastToken($phpDocNode);
|
||||
|
||||
$phpDocInfo = new PhpDocInfo($phpDocNode, $tokens, $content, $this->staticTypeMapper, $node);
|
||||
$this->phpDocInfoByObjectHash[$hash] = $phpDocInfo;
|
||||
$phpDocInfo = $this->createPhpDocInfo($node);
|
||||
$node->setAttribute(AttributeKey::PHP_DOC_INFO, $phpDocInfo);
|
||||
|
||||
return $phpDocInfo;
|
||||
}
|
||||
|
||||
private function createUniqueDocNodeHash(Node $node): string
|
||||
{
|
||||
$this->ensureNodeHasDocComment($node);
|
||||
|
||||
$objectHash = spl_object_hash($node);
|
||||
$docCommentHash = spl_object_hash($node->getDocComment());
|
||||
$docCommentContentHash = sha1($node->getDocComment()->getText());
|
||||
|
||||
return $objectHash . $docCommentHash . $docCommentContentHash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Needed for printing
|
||||
*/
|
||||
@ -106,20 +77,30 @@ final class PhpDocInfoFactory
|
||||
/** @var AttributeAwareNodeInterface $lastChildNode */
|
||||
$lastChildNode = array_pop($phpDocChildNodes);
|
||||
|
||||
$phpDocNodeInfo = $lastChildNode->getAttribute(Attribute::PHP_DOC_NODE_INFO);
|
||||
if ($phpDocNodeInfo !== null) {
|
||||
$attributeAwarePhpDocNode->setAttribute(Attribute::LAST_TOKEN_POSITION, $phpDocNodeInfo->getEnd());
|
||||
/** @var StartEndValueObject $startEndValueObject */
|
||||
$startEndValueObject = $lastChildNode->getAttribute(Attribute::START_END);
|
||||
|
||||
if ($startEndValueObject !== null) {
|
||||
$attributeAwarePhpDocNode->setAttribute(Attribute::LAST_TOKEN_POSITION, $startEndValueObject->getEnd());
|
||||
}
|
||||
|
||||
return $attributeAwarePhpDocNode;
|
||||
}
|
||||
|
||||
private function ensureNodeHasDocComment(Node $node): void
|
||||
private function createPhpDocInfo(Node $node): PhpDocInfo
|
||||
{
|
||||
if ($node->getDocComment() !== null) {
|
||||
return;
|
||||
}
|
||||
/** needed for @see PhpDocNodeFactoryInterface */
|
||||
$this->currentNodeProvider->setNode($node);
|
||||
|
||||
throw new ShouldNotHappenException(sprintf('"%s" is missing a DocComment node', get_class($node)));
|
||||
$content = $node->getDocComment()->getText();
|
||||
$tokens = $this->lexer->tokenize($content);
|
||||
|
||||
$tokenIterator = new TokenIterator($tokens);
|
||||
|
||||
/** @var AttributeAwarePhpDocNode $phpDocNode */
|
||||
$phpDocNode = $this->phpDocParser->parse($tokenIterator);
|
||||
$phpDocNode = $this->setPositionOfLastToken($phpDocNode);
|
||||
|
||||
return new PhpDocInfo($phpDocNode, $tokens, $content, $this->staticTypeMapper, $node);
|
||||
}
|
||||
}
|
||||
|
@ -31,6 +31,11 @@ abstract class AbstractTagValueNode implements AttributeAwareNodeInterface, PhpD
|
||||
*/
|
||||
protected $hasNewlineAfterOpening = false;
|
||||
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
protected $originalContent;
|
||||
|
||||
/**
|
||||
* @param mixed[] $item
|
||||
*/
|
||||
@ -60,6 +65,10 @@ abstract class AbstractTagValueNode implements AttributeAwareNodeInterface, PhpD
|
||||
}
|
||||
|
||||
if ($contentItems === []) {
|
||||
if ($this->originalContent !== null && Strings::endsWith($this->originalContent, '()')) {
|
||||
return '()';
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
@ -131,6 +140,7 @@ abstract class AbstractTagValueNode implements AttributeAwareNodeInterface, PhpD
|
||||
return;
|
||||
}
|
||||
|
||||
$this->originalContent = $originalContent;
|
||||
$this->orderedVisibleItems = ArrayItemStaticHelper::resolveAnnotationItemsOrder($originalContent);
|
||||
$this->hasNewlineAfterOpening = (bool) Strings::match($originalContent, '#^\(\s+#m');
|
||||
$this->hasNewlineBeforeClosing = (bool) Strings::match($originalContent, '#\s+\)$#m');
|
||||
|
@ -18,9 +18,10 @@ final class InheritanceTypeTagValueNode extends AbstractDoctrineTagValueNode
|
||||
*/
|
||||
private $value;
|
||||
|
||||
public function __construct(?string $value)
|
||||
public function __construct(?string $value, ?string $originalContent)
|
||||
{
|
||||
$this->value = $value;
|
||||
$this->resolveOriginalContentSpacingAndOrder($originalContent);
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
@ -29,6 +30,10 @@ final class InheritanceTypeTagValueNode extends AbstractDoctrineTagValueNode
|
||||
return '';
|
||||
}
|
||||
|
||||
return '("' . $this->value . '")';
|
||||
if ($this->originalContent && ! in_array('value', (array) $this->orderedVisibleItems, true)) {
|
||||
return '("' . $this->value . '")';
|
||||
}
|
||||
|
||||
return '(value="' . $this->value . '")';
|
||||
}
|
||||
}
|
||||
|
@ -110,7 +110,11 @@ final class TableTagValueNode extends AbstractDoctrineTagValueNode
|
||||
$contentItems = [];
|
||||
|
||||
if ($this->name !== null) {
|
||||
$contentItems['name'] = sprintf('name="%s"', $this->name);
|
||||
if ($this->originalContent !== null && ! in_array('name', (array) $this->orderedVisibleItems, true)) {
|
||||
$contentItems[] = '"' . $this->name . '"';
|
||||
} else {
|
||||
$contentItems['name'] = sprintf('name="%s"', $this->name);
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->schema !== null) {
|
||||
|
@ -83,10 +83,6 @@ final class JoinColumnTagValueNode extends AbstractDoctrineTagValueNode implemen
|
||||
{
|
||||
$contentItems = [];
|
||||
|
||||
if ($this->nullable !== null) {
|
||||
$contentItems['nullable'] = sprintf('nullable=%s', $this->nullable ? 'true' : 'false');
|
||||
}
|
||||
|
||||
if ($this->name) {
|
||||
$contentItems['name'] = sprintf('name="%s"', $this->name);
|
||||
}
|
||||
@ -95,7 +91,12 @@ final class JoinColumnTagValueNode extends AbstractDoctrineTagValueNode implemen
|
||||
$contentItems['referencedColumnName'] = sprintf('referencedColumnName="%s"', $this->referencedColumnName);
|
||||
}
|
||||
|
||||
if ($this->unique !== null) {
|
||||
if ($this->nullable !== null) {
|
||||
$contentItems['nullable'] = sprintf('nullable=%s', $this->nullable ? 'true' : 'false');
|
||||
}
|
||||
|
||||
// skip default value
|
||||
if ($this->unique !== null && $this->unique) {
|
||||
$contentItems['unique'] = sprintf('unique=%s', $this->unique ? 'true' : 'false');
|
||||
}
|
||||
|
||||
@ -134,13 +135,13 @@ final class JoinColumnTagValueNode extends AbstractDoctrineTagValueNode implemen
|
||||
return $this->nullable;
|
||||
}
|
||||
|
||||
public function changeName(string $newName): void
|
||||
{
|
||||
$this->name = $newName;
|
||||
}
|
||||
|
||||
public function getTag(): ?string
|
||||
{
|
||||
return $this->tag ?: self::SHORT_NAME;
|
||||
}
|
||||
|
||||
public function getUnique(): ?bool
|
||||
{
|
||||
return $this->unique;
|
||||
}
|
||||
}
|
||||
|
@ -46,14 +46,15 @@ final class JMSInjectTagValueNode extends AbstractTagValueNode
|
||||
$itemContents = [];
|
||||
|
||||
if ($this->serviceName) {
|
||||
$itemContents[] = $this->serviceName;
|
||||
$itemContents[] = '"' . $this->serviceName . '"';
|
||||
}
|
||||
|
||||
if ($this->required !== null) {
|
||||
$itemContents[] = sprintf('required=%s', $this->required ? 'true' : 'false');
|
||||
}
|
||||
|
||||
if ($this->strict !== null) {
|
||||
// skip default
|
||||
if (! $this->strict) {
|
||||
$itemContents[] = sprintf('strict=%s', $this->strict ? 'true' : 'false');
|
||||
}
|
||||
|
||||
@ -61,9 +62,7 @@ final class JMSInjectTagValueNode extends AbstractTagValueNode
|
||||
return '';
|
||||
}
|
||||
|
||||
$stringContent = implode(', ', $itemContents);
|
||||
|
||||
return '(' . $stringContent . ')';
|
||||
return $this->printContentItems($itemContents);
|
||||
}
|
||||
|
||||
public function getServiceName(): ?string
|
||||
|
@ -32,6 +32,8 @@ final class InheritanceTypePhpDocNodeFactory extends AbstractPhpDocNodeFactory
|
||||
return null;
|
||||
}
|
||||
|
||||
return new InheritanceTypeTagValueNode($inheritanceType->value);
|
||||
$annotationContent = $this->resolveContentFromTokenIterator($tokenIterator);
|
||||
|
||||
return new InheritanceTypeTagValueNode($inheritanceType->value, $annotationContent);
|
||||
}
|
||||
}
|
||||
|
@ -206,7 +206,7 @@ final class BetterPhpDocParser extends PhpDocParser
|
||||
$startEndValueObject = new StartEndValueObject($tokenStart, $tokenEnd);
|
||||
|
||||
$attributeAwareNode = $this->attributeAwareNodeFactory->createFromNode($phpDocNode);
|
||||
$attributeAwareNode->setAttribute(Attribute::PHP_DOC_NODE_INFO, $startEndValueObject);
|
||||
$attributeAwareNode->setAttribute(Attribute::START_END, $startEndValueObject);
|
||||
|
||||
$possibleMultilineText = $this->multilineSpaceFormatPreserver->resolveCurrentPhpDocNodeText(
|
||||
$attributeAwareNode
|
||||
|
@ -113,7 +113,15 @@ final class PhpDocInfoPrinter
|
||||
$output .= $this->printNode($phpDocChildNode, null, $i + 1, $nodeCount, $shouldSkipEmptyLinesAbove);
|
||||
}
|
||||
|
||||
return $this->printEnd($output);
|
||||
$output = $this->printEnd($output);
|
||||
|
||||
// @see
|
||||
// fix missing start
|
||||
if (! Strings::match($output, '#^(\/\/|\/\*\*|\/\*)#') && $output) {
|
||||
$output = '/**' . $output;
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
private function isPhpDocNodeEmpty(PhpDocNode $phpDocNode): bool
|
||||
@ -145,12 +153,11 @@ final class PhpDocInfoPrinter
|
||||
$output = '';
|
||||
|
||||
/** @var StartEndValueObject|null $startEndValueObject */
|
||||
$startEndValueObject = $attributeAwareNode->getAttribute(Attribute::PHP_DOC_NODE_INFO) ?: $startEndValueObject;
|
||||
$startEndValueObject = $attributeAwareNode->getAttribute(Attribute::START_END) ?: $startEndValueObject;
|
||||
$attributeAwareNode = $this->multilineSpaceFormatPreserver->fixMultilineDescriptions($attributeAwareNode);
|
||||
|
||||
if ($startEndValueObject !== null) {
|
||||
$isLastToken = ($nodeCount === $i);
|
||||
|
||||
$output = $this->addTokensFromTo(
|
||||
$output,
|
||||
$this->currentTokenPosition,
|
||||
@ -271,7 +278,7 @@ final class PhpDocInfoPrinter
|
||||
);
|
||||
|
||||
foreach ($removedNodes as $removedNode) {
|
||||
$removedPhpDocNodeInfo = $removedNode->getAttribute(Attribute::PHP_DOC_NODE_INFO);
|
||||
$removedPhpDocNodeInfo = $removedNode->getAttribute(Attribute::START_END);
|
||||
|
||||
// change start position to start of the line, so the whole line is removed
|
||||
$seekPosition = $removedPhpDocNodeInfo->getStart();
|
||||
|
@ -1,6 +1,6 @@
|
||||
/**
|
||||
* @ORM\Entity(readOnly=true, repositoryClass="Rector\BetterPhpDocParser\Tests\PhpDocParser\OrmTagParser\Class_\Source\ExistingRepositoryClass")
|
||||
* @ORM\Entity
|
||||
* @ORM\Entity
|
||||
* @ORM\Entity()
|
||||
* @ORM\Table(name="answer")
|
||||
*/
|
@ -96,6 +96,7 @@ PHP
|
||||
|
||||
/** @var string $class */
|
||||
$class = $this->getName($node);
|
||||
|
||||
// properties are accessed via magic, nothing we can do
|
||||
if (method_exists($class, '__set') || method_exists($class, '__get')) {
|
||||
return null;
|
||||
|
@ -18,7 +18,7 @@ use Rector\RectorDefinition\RectorDefinition;
|
||||
final class FunctionCallToConstantRector extends AbstractRector
|
||||
{
|
||||
/**
|
||||
* @var string[]string
|
||||
* @var string[]
|
||||
*/
|
||||
private $functionsToConstants = [];
|
||||
|
||||
|
@ -29,7 +29,7 @@ use Rector\RectorDefinition\RectorDefinition;
|
||||
final class VersionCompareFuncCallToConstantRector extends AbstractRector
|
||||
{
|
||||
/**
|
||||
* @var string[]string
|
||||
* @var string[]
|
||||
*/
|
||||
private $operatorToComparison = [
|
||||
'=' => Identical::class,
|
||||
|
@ -13,7 +13,6 @@ final class SkipAlreadyHas
|
||||
* - "[package-name] "Message => package-name
|
||||
* - "[aliased-package-name] "Message => aliased-package-name
|
||||
* - "[Aliased\PackageName] "Message => Aliased\PackageName
|
||||
* - "[Aliased\PackageName] "Message => Aliased\PackageName
|
||||
*/
|
||||
public const PACKAGE_NAME_PATTERN = '#\[(?<package>[-\w\\\\]+)\]( ){1,}#';
|
||||
}
|
||||
|
@ -3,7 +3,6 @@
|
||||
namespace Rector\CodingStyle\Tests\Rector\Namespace_\ImportFullyQualifiedNamesRector\Fixture;
|
||||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
/**
|
||||
* @ORM\Table("Table_Name")
|
||||
@ -12,13 +11,6 @@ use Symfony\Component\Routing\Annotation\Route;
|
||||
*/
|
||||
class ShouldKeepAllDocBlocksAnnotationsParameters
|
||||
{
|
||||
/**
|
||||
* @Route(
|
||||
* "/{arg1}/{arg2}",
|
||||
* defaults={"arg1"=null, "arg2"=""},
|
||||
* requirements={"arg1"="\d+", "arg2"=".*"}
|
||||
* )
|
||||
*/
|
||||
public function nothing(): void
|
||||
{
|
||||
}
|
||||
|
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace Rector\CodingStyle\Tests\Rector\Namespace_\ImportFullyQualifiedNamesRector\Fixture;
|
||||
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
class SymfonyRoute
|
||||
{
|
||||
/**
|
||||
* @Route(
|
||||
* "/{arg1}/{arg2}",
|
||||
* defaults={"arg1"=null, "arg2"=""},
|
||||
* requirements={"arg1"="\d+", "arg2"=".*"}
|
||||
* )
|
||||
*/
|
||||
public function nothing(): void
|
||||
{
|
||||
}
|
||||
}
|
@ -13,9 +13,11 @@ use PHPStan\Type\ObjectType;
|
||||
use Rector\BetterPhpDocParser\Contract\Doctrine\DoctrineRelationTagValueNodeInterface;
|
||||
use Rector\BetterPhpDocParser\Contract\Doctrine\InversedByNodeInterface;
|
||||
use Rector\BetterPhpDocParser\Contract\Doctrine\MappedByNodeInterface;
|
||||
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
|
||||
use Rector\BetterPhpDocParser\PhpDocNode\Doctrine\Class_\EntityTagValueNode;
|
||||
use Rector\BetterPhpDocParser\PhpDocNode\Doctrine\Class_\InheritanceTypeTagValueNode;
|
||||
use Rector\Doctrine\PhpDocParser\DoctrineDocBlockResolver;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
use Rector\NodeTypeResolver\NodeTypeResolver;
|
||||
use Rector\NodeTypeResolver\PhpDoc\NodeAnalyzer\DocBlockManipulator;
|
||||
use Rector\PhpParser\Node\Resolver\NameResolver;
|
||||
@ -56,12 +58,12 @@ final class DoctrineEntityManipulator
|
||||
|
||||
public function resolveOtherProperty(Property $property): ?string
|
||||
{
|
||||
if ($property->getDocComment() === null) {
|
||||
/** @var PhpDocInfo|null $phpDocInfo */
|
||||
$phpDocInfo = $property->getAttribute(AttributeKey::PHP_DOC_INFO);
|
||||
if ($phpDocInfo === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$phpDocInfo = $this->docBlockManipulator->createPhpDocInfoFromNode($property);
|
||||
|
||||
$relationTagValueNode = $phpDocInfo->getByType(DoctrineRelationTagValueNodeInterface::class);
|
||||
if ($relationTagValueNode === null) {
|
||||
return null;
|
||||
@ -103,12 +105,11 @@ final class DoctrineEntityManipulator
|
||||
|
||||
public function removeMappedByOrInversedByFromProperty(Property $property): void
|
||||
{
|
||||
$doc = $property->getDocComment();
|
||||
if ($doc === null) {
|
||||
return;
|
||||
$phpDocInfo = $property->getAttribute(AttributeKey::PHP_DOC_INFO);
|
||||
if ($phpDocInfo === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$phpDocInfo = $this->docBlockManipulator->createPhpDocInfoFromNode($property);
|
||||
$relationTagValueNode = $phpDocInfo->getByType(DoctrineRelationTagValueNodeInterface::class);
|
||||
|
||||
$shouldUpdate = false;
|
||||
@ -125,8 +126,6 @@ final class DoctrineEntityManipulator
|
||||
if (! $shouldUpdate) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->docBlockManipulator->updateNodeWithPhpDocInfo($property, $phpDocInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -268,9 +268,15 @@ PHP
|
||||
VariableNodeUseInfo $nodeByTypeAndPosition
|
||||
): bool {
|
||||
// this node was just used, skip to next one
|
||||
return $previousNode !== null && ($previousNode->isType(
|
||||
VariableNodeUseInfo::TYPE_ASSIGN
|
||||
) && $nodeByTypeAndPosition->isType(VariableNodeUseInfo::TYPE_USE));
|
||||
if ($previousNode === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! $previousNode->isType(VariableNodeUseInfo::TYPE_ASSIGN)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $nodeByTypeAndPosition->isType(VariableNodeUseInfo::TYPE_USE);
|
||||
}
|
||||
|
||||
private function shouldRemoveAssignNode(
|
||||
@ -301,7 +307,7 @@ PHP
|
||||
$isVariableAssigned = (bool) $this->betterNodeFinder->findFirst($assignNode->expr, function (Node $node) use (
|
||||
$nodeByTypeAndPosition
|
||||
): bool {
|
||||
return $this->areNodesEqual($node, $nodeByTypeAndPosition->getVariableNode());
|
||||
return $this->areNodesWithoutCommentsEqual($node, $nodeByTypeAndPosition->getVariableNode());
|
||||
});
|
||||
|
||||
return ! $isVariableAssigned;
|
||||
|
@ -66,6 +66,7 @@ PHP
|
||||
}
|
||||
|
||||
$isDeadAfterReturn = false;
|
||||
$isDeadAfterReturnRemoved = false;
|
||||
|
||||
foreach ($node->stmts as $key => $stmt) {
|
||||
if ($isDeadAfterReturn) {
|
||||
@ -75,6 +76,7 @@ PHP
|
||||
}
|
||||
|
||||
unset($node->stmts[$key]);
|
||||
$isDeadAfterReturnRemoved = true;
|
||||
}
|
||||
|
||||
if ($stmt instanceof Return_) {
|
||||
@ -83,6 +85,10 @@ PHP
|
||||
}
|
||||
}
|
||||
|
||||
if ($isDeadAfterReturnRemoved === false) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $node;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace Rector\DeadCode\Tests\Rector\ClassMethod\RemoveOverriddenValuesRector\Fixture;
|
||||
|
||||
use Nette\Utils\Strings;
|
||||
use PhpParser\Node\Stmt\Class_;
|
||||
use PhpParser\Node\Stmt\ClassMethod;
|
||||
use Rector\Util\RectorStrings;
|
||||
|
||||
class KeepPresenterName
|
||||
{
|
||||
public function resolvePathFromClassAndMethodNodes(Class_ $classNode, ClassMethod $classMethod): string
|
||||
{
|
||||
/** @var string $presenterName */
|
||||
$presenterName = $this->getName($classNode);
|
||||
|
||||
/** @var string $presenterPart */
|
||||
$presenterPart = Strings::after($presenterName, '\\', -1);
|
||||
|
||||
/** @var string $presenterPart */
|
||||
$presenterPart = Strings::substring($presenterPart, 0, -Strings::length('Presenter'));
|
||||
$presenterPart = RectorStrings::camelCaseToDashes($presenterPart);
|
||||
|
||||
$match = (array) Strings::match($this->getName($classMethod), '#^(action|render)(?<short_action_name>.*?$)#sm');
|
||||
$actionPart = lcfirst($match['short_action_name']);
|
||||
|
||||
return $presenterPart . '/' . $actionPart;
|
||||
}
|
||||
}
|
@ -2,53 +2,125 @@
|
||||
|
||||
namespace Rector\DeadCode\Tests\Rector\ClassMethod\RemoveOverriddenValuesRector\Fixture;
|
||||
|
||||
final class ReferenceUse
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\Assign;
|
||||
use PhpParser\Node\Stmt\If_;
|
||||
use PhpParser\Node\Stmt\Return_;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
use Rector\PhpParser\Node\Manipulator\IfManipulator;
|
||||
use Rector\PhpParser\Node\Manipulator\StmtsManipulator;
|
||||
use Rector\Rector\AbstractRector;
|
||||
use Rector\RectorDefinition\CodeSample;
|
||||
use Rector\RectorDefinition\RectorDefinition;
|
||||
|
||||
/**
|
||||
* @see https://engineering.helpscout.com/reducing-complexity-with-guard-clauses-in-php-and-javascript-74600fd865c7
|
||||
*
|
||||
* @see \Rector\SOLID\Tests\Rector\If_\ChangeIfElseValueAssignToEarlyReturnRector\ChangeIfElseValueAssignToEarlyReturnRectorTest
|
||||
*/
|
||||
final class ChangeIfElseValueAssignToEarlyReturnRector extends AbstractRector
|
||||
{
|
||||
public function run(&$directories)
|
||||
/**
|
||||
* @var IfManipulator
|
||||
*/
|
||||
private $ifManipulator;
|
||||
|
||||
/**
|
||||
* @var StmtsManipulator
|
||||
*/
|
||||
private $stmtsManipulator;
|
||||
|
||||
public function __construct(IfManipulator $ifManipulator, StmtsManipulator $stmtsManipulator)
|
||||
{
|
||||
$directories = 1;
|
||||
$directories = 4;
|
||||
$directories = 5;
|
||||
$this->ifManipulator = $ifManipulator;
|
||||
$this->stmtsManipulator = $stmtsManipulator;
|
||||
}
|
||||
|
||||
public function plusRun(&$directories)
|
||||
public function getDefinition(): RectorDefinition
|
||||
{
|
||||
$directories = 1;
|
||||
$directories += 4;
|
||||
}
|
||||
return new RectorDefinition('Change if/else value to early return', [
|
||||
new CodeSample(
|
||||
<<<'PHP'
|
||||
class SomeClass
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
if ($this->hasDocBlock($tokens, $index)) {
|
||||
$docToken = $tokens[$this->getDocBlockIndex($tokens, $index)];
|
||||
} else {
|
||||
$docToken = null;
|
||||
}
|
||||
|
||||
public function get(&$directories)
|
||||
{
|
||||
$directories = 1;
|
||||
$directories = 4;
|
||||
return $directories;
|
||||
return $docToken;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\DeadCode\Tests\Rector\ClassMethod\RemoveOverriddenValuesRector\Fixture;
|
||||
|
||||
final class ReferenceUse
|
||||
PHP
|
||||
,
|
||||
<<<'PHP'
|
||||
class SomeClass
|
||||
{
|
||||
public function run(&$directories)
|
||||
public function run()
|
||||
{
|
||||
$directories = 5;
|
||||
}
|
||||
|
||||
public function plusRun(&$directories)
|
||||
{
|
||||
$directories = 1;
|
||||
$directories += 4;
|
||||
}
|
||||
|
||||
public function get(&$directories)
|
||||
{
|
||||
$directories = 4;
|
||||
return $directories;
|
||||
if ($this->hasDocBlock($tokens, $index)) {
|
||||
return $tokens[$this->getDocBlockIndex($tokens, $index)];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
PHP
|
||||
|
||||
?>
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function getNodeTypes(): array
|
||||
{
|
||||
return [If_::class];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param If_ $node
|
||||
*/
|
||||
public function refactor(Node $node): ?Node
|
||||
{
|
||||
$nextNode = $node->getAttribute(AttributeKey::NEXT_NODE);
|
||||
if (! $nextNode instanceof Return_) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($nextNode->expr === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (! $this->ifManipulator->isIfAndElseWithSameVariableAssignAsLastStmts($node, $nextNode->expr)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$lastIfStmtKey = array_key_last($node->stmts);
|
||||
|
||||
/** @var Assign $assign */
|
||||
$assign = $this->stmtsManipulator->getUnwrappedLastStmt($node->stmts);
|
||||
|
||||
$node->stmts[$lastIfStmtKey] = new Return_($assign->expr);
|
||||
|
||||
/** @var Assign $assign */
|
||||
$assign = $this->stmtsManipulator->getUnwrappedLastStmt($node->else->stmts);
|
||||
$lastElseStmtKey = array_key_last($node->else->stmts);
|
||||
|
||||
$elseStmts = $node->else->stmts;
|
||||
$elseStmts[$lastElseStmtKey] = new Return_($assign->expr);
|
||||
|
||||
$node->else = null;
|
||||
|
||||
foreach ($elseStmts as $elseStmt) {
|
||||
$this->addNodeAfterNode($elseStmt, $node);
|
||||
}
|
||||
|
||||
$this->removeNode($nextNode);
|
||||
|
||||
return $node;
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,6 @@ use PhpParser\Node\Stmt\Class_;
|
||||
use PhpParser\Node\Stmt\ClassLike;
|
||||
use PhpParser\Node\Stmt\Property;
|
||||
use Rector\BetterPhpDocParser\Contract\Doctrine\DoctrineRelationTagValueNodeInterface;
|
||||
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
|
||||
use Rector\BetterPhpDocParser\PhpDocNode\Doctrine\Class_\EntityTagValueNode;
|
||||
use Rector\BetterPhpDocParser\PhpDocNode\Doctrine\Property_\ColumnTagValueNode;
|
||||
use Rector\BetterPhpDocParser\PhpDocNode\Doctrine\Property_\IdTagValueNode;
|
||||
@ -18,24 +17,17 @@ use Rector\Exception\ShouldNotHappenException;
|
||||
use Rector\NodeContainer\ParsedNodesByType;
|
||||
use Rector\NodeTypeResolver\ClassExistenceStaticHelper;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
use Rector\NodeTypeResolver\PhpDoc\NodeAnalyzer\DocBlockManipulator;
|
||||
use ReflectionClass;
|
||||
|
||||
final class DoctrineDocBlockResolver
|
||||
{
|
||||
/**
|
||||
* @var DocBlockManipulator
|
||||
*/
|
||||
private $docBlockManipulator;
|
||||
|
||||
/**
|
||||
* @var ParsedNodesByType
|
||||
*/
|
||||
private $parsedNodesByType;
|
||||
|
||||
public function __construct(DocBlockManipulator $docBlockManipulator, ParsedNodesByType $parsedNodesByType)
|
||||
public function __construct(ParsedNodesByType $parsedNodesByType)
|
||||
{
|
||||
$this->docBlockManipulator = $docBlockManipulator;
|
||||
$this->parsedNodesByType = $parsedNodesByType;
|
||||
}
|
||||
|
||||
@ -45,12 +37,12 @@ final class DoctrineDocBlockResolver
|
||||
public function isDoctrineEntityClass($class): bool
|
||||
{
|
||||
if ($class instanceof Class_) {
|
||||
$classPhpDocInfo = $this->getPhpDocInfo($class);
|
||||
if ($classPhpDocInfo === null) {
|
||||
$phpDocInfo = $class->getAttribute(AttributeKey::PHP_DOC_INFO);
|
||||
if ($phpDocInfo === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $classPhpDocInfo->hasByType(EntityTagValueNode::class);
|
||||
return $phpDocInfo->hasByType(EntityTagValueNode::class);
|
||||
}
|
||||
|
||||
if (is_string($class)) {
|
||||
@ -103,36 +95,36 @@ final class DoctrineDocBlockResolver
|
||||
|
||||
public function hasPropertyDoctrineIdTag(Property $property): bool
|
||||
{
|
||||
$propertyPhpDocInfo = $this->getPhpDocInfo($property);
|
||||
if ($propertyPhpDocInfo === null) {
|
||||
$phpDocInfo = $property->getAttribute(AttributeKey::PHP_DOC_INFO);
|
||||
if ($phpDocInfo === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $propertyPhpDocInfo->hasByType(IdTagValueNode::class);
|
||||
return $phpDocInfo->hasByType(IdTagValueNode::class);
|
||||
}
|
||||
|
||||
public function getDoctrineRelationTagValueNode(Property $property): ?DoctrineRelationTagValueNodeInterface
|
||||
{
|
||||
$propertyPhpDocInfo = $this->getPhpDocInfo($property);
|
||||
if ($propertyPhpDocInfo === null) {
|
||||
$phpDocInfo = $property->getAttribute(AttributeKey::PHP_DOC_INFO);
|
||||
if ($phpDocInfo === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $propertyPhpDocInfo->getByType(DoctrineRelationTagValueNodeInterface::class);
|
||||
return $phpDocInfo->getByType(DoctrineRelationTagValueNodeInterface::class);
|
||||
}
|
||||
|
||||
public function isDoctrineProperty(Property $property): bool
|
||||
{
|
||||
$propertyPhpDocInfo = $this->getPhpDocInfo($property);
|
||||
if ($propertyPhpDocInfo === null) {
|
||||
$phpDocInfo = $property->getAttribute(AttributeKey::PHP_DOC_INFO);
|
||||
if ($phpDocInfo === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($propertyPhpDocInfo->hasByType(ColumnTagValueNode::class)) {
|
||||
if ($phpDocInfo->hasByType(ColumnTagValueNode::class)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return $propertyPhpDocInfo->hasByType(DoctrineRelationTagValueNodeInterface::class);
|
||||
return $phpDocInfo->hasByType(DoctrineRelationTagValueNodeInterface::class);
|
||||
}
|
||||
|
||||
public function isInDoctrineEntityClass(Node $node): bool
|
||||
@ -145,13 +137,4 @@ final class DoctrineDocBlockResolver
|
||||
|
||||
return $this->isDoctrineEntityClass($classNode);
|
||||
}
|
||||
|
||||
private function getPhpDocInfo(Node $node): ?PhpDocInfo
|
||||
{
|
||||
if ($node->getDocComment() === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->docBlockManipulator->createPhpDocInfoFromNode($node);
|
||||
}
|
||||
}
|
||||
|
@ -126,7 +126,7 @@ final class AddUuidMirrorForRelationPropertyRector extends AbstractRector
|
||||
$propertyWithUuid = clone $property;
|
||||
|
||||
// this is needed to keep old property name
|
||||
$this->updateDocComment($propertyWithUuid);
|
||||
$this->mirrorPhpDocInfoToUuid($propertyWithUuid);
|
||||
|
||||
// name must be changed after the doc comment update, because the reflection annotation needed for update of doc comment
|
||||
// would miss non existing *Uuid property
|
||||
@ -152,21 +152,21 @@ final class AddUuidMirrorForRelationPropertyRector extends AbstractRector
|
||||
return false;
|
||||
}
|
||||
|
||||
private function updateDocComment(Property $property): void
|
||||
private function mirrorPhpDocInfoToUuid(Property $property): void
|
||||
{
|
||||
/** @var PhpDocInfo $propertyPhpDocInfo */
|
||||
$propertyPhpDocInfo = $this->getPhpDocInfo($property);
|
||||
|
||||
$newPropertyPhpDocInfo = clone $propertyPhpDocInfo;
|
||||
|
||||
/** @var DoctrineRelationTagValueNodeInterface $doctrineRelationTagValueNode */
|
||||
$doctrineRelationTagValueNode = $this->getDoctrineRelationTagValueNode($property);
|
||||
|
||||
if ($doctrineRelationTagValueNode instanceof ToManyTagNodeInterface) {
|
||||
$this->refactorToManyPropertyPhpDocInfo($propertyPhpDocInfo, $property);
|
||||
$this->refactorToManyPropertyPhpDocInfo($newPropertyPhpDocInfo, $property);
|
||||
} elseif ($doctrineRelationTagValueNode instanceof ToOneTagNodeInterface) {
|
||||
$this->refactorToOnePropertyPhpDocInfo($propertyPhpDocInfo);
|
||||
$this->refactorToOnePropertyPhpDocInfo($newPropertyPhpDocInfo);
|
||||
}
|
||||
|
||||
$this->docBlockManipulator->updateNodeWithPhpDocInfo($property, $propertyPhpDocInfo);
|
||||
}
|
||||
|
||||
private function addNewPropertyToCollector(
|
||||
@ -197,22 +197,28 @@ final class AddUuidMirrorForRelationPropertyRector extends AbstractRector
|
||||
}
|
||||
|
||||
$joinTableTagNode = $this->phpDocTagNodeFactory->createJoinTableTagNode($property);
|
||||
$propertyPhpDocInfo->getPhpDocNode()->children[] = $joinTableTagNode;
|
||||
$propertyPhpDocInfo->addPhpDocTagNode($joinTableTagNode);
|
||||
}
|
||||
|
||||
private function refactorToOnePropertyPhpDocInfo(PhpDocInfo $propertyPhpDocInfo): void
|
||||
{
|
||||
/** @var JoinColumnTagValueNode $joinColumnTagValueNode */
|
||||
/** @var JoinColumnTagValueNode|null $joinColumnTagValueNode */
|
||||
$joinColumnTagValueNode = $propertyPhpDocInfo->getByType(JoinColumnTagValueNode::class);
|
||||
|
||||
if ($joinColumnTagValueNode) {
|
||||
$joinColumnTagValueNode->changeName('');
|
||||
$joinColumnTagValueNode->changeNullable(true);
|
||||
$joinColumnTagValueNode->changeReferencedColumnName('uuid');
|
||||
} else {
|
||||
$propertyPhpDocInfo->getPhpDocNode()->children[] = $this->phpDocTagNodeFactory->createJoinColumnTagNode(
|
||||
if ($joinColumnTagValueNode !== null) {
|
||||
// remove first
|
||||
$propertyPhpDocInfo->removeByType(JoinColumnTagValueNode::class);
|
||||
|
||||
$mirrorJoinColumnTagValueNode = new JoinColumnTagValueNode(
|
||||
'',
|
||||
'uuid',
|
||||
$joinColumnTagValueNode->getUnique(),
|
||||
true
|
||||
);
|
||||
} else {
|
||||
$mirrorJoinColumnTagValueNode = $this->phpDocTagNodeFactory->createJoinColumnTagNode(true);
|
||||
}
|
||||
|
||||
$propertyPhpDocInfo->addTagValueNodeWithShortName($mirrorJoinColumnTagValueNode);
|
||||
}
|
||||
}
|
||||
|
@ -72,7 +72,6 @@ PHP
|
||||
$doctrineEntityTag->removeRepositoryClass();
|
||||
|
||||
// save the entity tag
|
||||
$this->docBlockManipulator->updateNodeWithPhpDocInfo($node, $phpDocInfo);
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
@ -48,23 +48,22 @@ final class AddUuidAnnotationsToIdPropertyRector extends AbstractRector
|
||||
return null;
|
||||
}
|
||||
|
||||
$this->changeVarToUuidInterface($node);
|
||||
|
||||
/** @var PhpDocInfo $phpDocInfo */
|
||||
$phpDocInfo = $this->getPhpDocInfo($node);
|
||||
|
||||
$this->changeVarToUuidInterface($node);
|
||||
|
||||
$phpDocInfo->removeByType(GeneratedValueTagValueNode::class);
|
||||
$this->changeColumnTypeToUuidBinary($phpDocInfo);
|
||||
$this->changeSerializerTypeToString($phpDocInfo);
|
||||
|
||||
$this->docBlockManipulator->updateNodeWithPhpDocInfo($node, $phpDocInfo);
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
private function changeVarToUuidInterface(Property $property): void
|
||||
{
|
||||
$uuidObjectType = new FullyQualifiedObjectType(UuidInterface::class);
|
||||
|
||||
$this->docBlockManipulator->changeVarTag($property, $uuidObjectType);
|
||||
}
|
||||
|
||||
|
@ -58,8 +58,8 @@ class ManyToManyWithExtraName
|
||||
private $itemRole;
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="Rector\Doctrine\Tests\Rector\Class_\AddUuidMirrorForRelationPropertyRector\Fixture\BarEntity")
|
||||
* @ORM\JoinColumn(referencedColumnName="uuid", nullable=true)
|
||||
* @Serializer\Type("Rector\Doctrine\Tests\Rector\Class_\AddUuidMirrorForRelationPropertyRector\Fixture\BarEntity")
|
||||
* @ORM\JoinColumn(referencedColumnName="uuid", nullable=true)
|
||||
*/
|
||||
private $itemRoleUuid;
|
||||
}
|
@ -101,7 +101,6 @@ PHP
|
||||
}
|
||||
|
||||
$classPhpDocInfo->removeByType(LoggableTagValueNode::class);
|
||||
$this->docBlockManipulator->updateNodeWithPhpDocInfo($node, $classPhpDocInfo);
|
||||
|
||||
// remove tag from properties
|
||||
$this->removeVersionedTagFromProperties($node);
|
||||
@ -126,7 +125,6 @@ PHP
|
||||
}
|
||||
|
||||
$propertyPhpDocInfo->removeByType(VersionedTagValueNode::class);
|
||||
$this->docBlockManipulator->updateNodeWithPhpDocInfo($property, $propertyPhpDocInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -110,7 +110,6 @@ PHP
|
||||
$node->implements[] = new FullyQualified('Knp\DoctrineBehaviors\Contract\Entity\SoftDeletableInterface');
|
||||
|
||||
$classPhpDocInfo->removeByType(SoftDeleteableTagValueNode::class);
|
||||
$this->docBlockManipulator->updateNodeWithPhpDocInfo($node, $classPhpDocInfo);
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
@ -261,7 +261,7 @@ PHP
|
||||
|
||||
foreach ($translatedPropertyToPhpDocInfos as $translatedPropertyName => $translatedPhpDocInfo) {
|
||||
$property = $this->nodeFactory->createPrivateProperty($translatedPropertyName);
|
||||
$this->docBlockManipulator->updateNodeWithPhpDocInfo($property, $translatedPhpDocInfo);
|
||||
$property->setAttribute(AttributeKey::PHP_DOC_INFO, $translatedPhpDocInfo);
|
||||
|
||||
$class->stmts[] = $property;
|
||||
}
|
||||
|
@ -148,7 +148,6 @@ PHP
|
||||
|
||||
// we're in a tree entity
|
||||
$classPhpDocInfo->removeByType(TreeTagValueNode::class);
|
||||
$this->docBlockManipulator->updateNodeWithPhpDocInfo($node, $classPhpDocInfo);
|
||||
|
||||
$node->implements[] = new FullyQualified('Knp\DoctrineBehaviors\Contract\Entity\TreeNodeInterface');
|
||||
$this->classManipulator->addAsFirstTrait($node, 'Knp\DoctrineBehaviors\Model\Tree\TreeNodeTrait');
|
||||
|
@ -335,8 +335,10 @@ PHP
|
||||
{
|
||||
/** @var string $presenterName */
|
||||
$presenterName = $this->getName($classNode);
|
||||
|
||||
/** @var string $presenterPart */
|
||||
$presenterPart = Strings::after($presenterName, '\\', -1);
|
||||
|
||||
/** @var string $presenterPart */
|
||||
$presenterPart = Strings::substring($presenterPart, 0, -Strings::length('Presenter'));
|
||||
$presenterPart = RectorStrings::camelCaseToDashes($presenterPart);
|
||||
|
@ -4,12 +4,20 @@ declare(strict_types=1);
|
||||
|
||||
namespace Rector\NodeTypeResolver\Node;
|
||||
|
||||
use PhpParser\Node\Stmt\ClassLike;
|
||||
use PhpParser\Node\Stmt\ClassMethod;
|
||||
use PhpParser\Node\Stmt\Function_;
|
||||
use PhpParser\Node\Stmt\Namespace_;
|
||||
use PHPStan\Analyser\Scope;
|
||||
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
|
||||
use Symplify\SmartFileSystem\SmartFileInfo;
|
||||
|
||||
final class AttributeKey
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public const SCOPE = 'scope';
|
||||
public const SCOPE = Scope::class;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
@ -19,7 +27,7 @@ final class AttributeKey
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public const NAMESPACE_NODE = 'namespaceNode';
|
||||
public const NAMESPACE_NODE = Namespace_::class;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
@ -35,7 +43,7 @@ final class AttributeKey
|
||||
* @todo split Class node, interface node and trait node, to be compatible with other SpecificNode|null, values
|
||||
* @var string
|
||||
*/
|
||||
public const CLASS_NODE = 'classNode';
|
||||
public const CLASS_NODE = ClassLike::class;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
@ -50,7 +58,7 @@ final class AttributeKey
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public const METHOD_NODE = 'methodNode';
|
||||
public const METHOD_NODE = ClassMethod::class;
|
||||
|
||||
/**
|
||||
* Internal php-parser name.
|
||||
@ -96,7 +104,7 @@ final class AttributeKey
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public const FILE_INFO = 'fileInfo';
|
||||
public const FILE_INFO = SmartFileInfo::class;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
@ -117,5 +125,10 @@ final class AttributeKey
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public const FUNCTION_NODE = 'function_node';
|
||||
public const FUNCTION_NODE = Function_::class;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public const PHP_DOC_INFO = PhpDocInfo::class;
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ use Rector\NodeTypeResolver\NodeVisitor\FunctionMethodAndClassNodeVisitor;
|
||||
use Rector\NodeTypeResolver\NodeVisitor\NamespaceNodeVisitor;
|
||||
use Rector\NodeTypeResolver\NodeVisitor\NodeCollectorNodeVisitor;
|
||||
use Rector\NodeTypeResolver\NodeVisitor\ParentAndNextNodeVisitor;
|
||||
use Rector\NodeTypeResolver\NodeVisitor\PhpDocInfoNodeVisitor;
|
||||
use Rector\NodeTypeResolver\NodeVisitor\StatementNodeVisitor;
|
||||
use Rector\NodeTypeResolver\PHPStan\Scope\NodeScopeResolver;
|
||||
|
||||
@ -64,6 +65,11 @@ final class NodeScopeAndMetadataDecorator
|
||||
*/
|
||||
private $configuration;
|
||||
|
||||
/**
|
||||
* @var PhpDocInfoNodeVisitor
|
||||
*/
|
||||
private $phpDocInfoNodeVisitor;
|
||||
|
||||
public function __construct(
|
||||
NodeScopeResolver $nodeScopeResolver,
|
||||
ParentAndNextNodeVisitor $parentAndNextNodeVisitor,
|
||||
@ -73,6 +79,7 @@ final class NodeScopeAndMetadataDecorator
|
||||
StatementNodeVisitor $statementNodeVisitor,
|
||||
FileInfoNodeVisitor $fileInfoNodeVisitor,
|
||||
NodeCollectorNodeVisitor $nodeCollectorNodeVisitor,
|
||||
PhpDocInfoNodeVisitor $phpDocInfoNodeVisitor,
|
||||
Configuration $configuration
|
||||
) {
|
||||
$this->nodeScopeResolver = $nodeScopeResolver;
|
||||
@ -84,6 +91,7 @@ final class NodeScopeAndMetadataDecorator
|
||||
$this->fileInfoNodeVisitor = $fileInfoNodeVisitor;
|
||||
$this->nodeCollectorNodeVisitor = $nodeCollectorNodeVisitor;
|
||||
$this->configuration = $configuration;
|
||||
$this->phpDocInfoNodeVisitor = $phpDocInfoNodeVisitor;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -117,6 +125,7 @@ final class NodeScopeAndMetadataDecorator
|
||||
$nodeTraverser->addVisitor($this->parentAndNextNodeVisitor);
|
||||
$nodeTraverser->addVisitor($this->functionMethodAndClassNodeVisitor);
|
||||
$nodeTraverser->addVisitor($this->namespaceNodeVisitor);
|
||||
$nodeTraverser->addVisitor($this->phpDocInfoNodeVisitor);
|
||||
|
||||
$nodes = $nodeTraverser->traverse($nodes);
|
||||
|
||||
|
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\NodeTypeResolver\NodeVisitor;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\NodeVisitorAbstract;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
use Rector\NodeTypeResolver\PhpDoc\NodeAnalyzer\DocBlockManipulator;
|
||||
|
||||
final class PhpDocInfoNodeVisitor extends NodeVisitorAbstract
|
||||
{
|
||||
/**
|
||||
* @var DocBlockManipulator
|
||||
*/
|
||||
private $docBlockManipulator;
|
||||
|
||||
public function __construct(DocBlockManipulator $docBlockManipulator)
|
||||
{
|
||||
$this->docBlockManipulator = $docBlockManipulator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int|Node|void|null
|
||||
*/
|
||||
public function enterNode(Node $node)
|
||||
{
|
||||
if (empty($node->getComments())) {
|
||||
$node->setAttribute(AttributeKey::PHP_DOC_INFO, null);
|
||||
return;
|
||||
}
|
||||
|
||||
$phpDocInfo = $this->docBlockManipulator->createPhpDocInfoFromNode($node);
|
||||
$node->setAttribute(AttributeKey::PHP_DOC_INFO, $phpDocInfo);
|
||||
|
||||
return $node;
|
||||
}
|
||||
}
|
@ -61,4 +61,9 @@ final class TypeHasher
|
||||
|
||||
return $this->phpStanStaticTypeMapper->mapToDocString($type);
|
||||
}
|
||||
|
||||
public function areTypesEqual(Type $firstType, Type $secondType): bool
|
||||
{
|
||||
return $this->createTypeHash($firstType) === $this->createTypeHash($secondType);
|
||||
}
|
||||
}
|
||||
|
@ -151,7 +151,6 @@ final class DocBlockManipulator
|
||||
$phpDocInfo = $this->createPhpDocInfoFromNode($node);
|
||||
$phpDocNode = $phpDocInfo->getPhpDocNode();
|
||||
$phpDocNode->children[] = $phpDocChildNode;
|
||||
$this->updateNodeWithPhpDocInfo($node, $phpDocInfo);
|
||||
} else {
|
||||
$phpDocNode = new AttributeAwarePhpDocNode([$phpDocChildNode]);
|
||||
$node->setDocComment(new Doc($phpDocNode->__toString()));
|
||||
@ -164,16 +163,18 @@ final class DocBlockManipulator
|
||||
$this->addTag($node, $spacelessPhpDocTagNode);
|
||||
}
|
||||
|
||||
public function removeTagFromNode(Node $node, string $name, bool $shouldSkipEmptyLinesAbove = false): void
|
||||
/**
|
||||
* @deprecated
|
||||
* Use @see PhpDocInfo::removeByType(x) directly
|
||||
*/
|
||||
public function removeTagFromNode(Node $node, string $name): void
|
||||
{
|
||||
if ($node->getDocComment() === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$phpDocInfo = $this->createPhpDocInfoFromNode($node);
|
||||
|
||||
$this->removeTagByName($phpDocInfo, $name);
|
||||
$this->updateNodeWithPhpDocInfo($node, $phpDocInfo, $shouldSkipEmptyLinesAbove);
|
||||
}
|
||||
|
||||
public function changeType(Node $node, Type $oldType, Type $newType): void
|
||||
@ -183,16 +184,8 @@ final class DocBlockManipulator
|
||||
}
|
||||
|
||||
$phpDocInfo = $this->createPhpDocInfoFromNode($node);
|
||||
$hasNodeChanged = $this->docBlockClassRenamer->renamePhpDocType(
|
||||
$phpDocInfo->getPhpDocNode(),
|
||||
$oldType,
|
||||
$newType,
|
||||
$node
|
||||
);
|
||||
|
||||
if ($hasNodeChanged) {
|
||||
$this->updateNodeWithPhpDocInfo($node, $phpDocInfo);
|
||||
}
|
||||
$this->docBlockClassRenamer->renamePhpDocType($phpDocInfo->getPhpDocNode(), $oldType, $newType, $node);
|
||||
}
|
||||
|
||||
public function replaceAnnotationInNode(Node $node, string $oldAnnotation, string $newAnnotation): void
|
||||
@ -203,8 +196,6 @@ final class DocBlockManipulator
|
||||
|
||||
$phpDocInfo = $this->createPhpDocInfoFromNode($node);
|
||||
$this->replaceTagByAnother($phpDocInfo->getPhpDocNode(), $oldAnnotation, $newAnnotation);
|
||||
|
||||
$this->updateNodeWithPhpDocInfo($node, $phpDocInfo);
|
||||
}
|
||||
|
||||
public function getReturnType(Node $node): Type
|
||||
@ -284,10 +275,6 @@ final class DocBlockManipulator
|
||||
|
||||
$phpDocType = $this->staticTypeMapper->mapPHPStanTypeToPHPStanPhpDocTypeNode($newType);
|
||||
$varTagValueNode->type = $phpDocType;
|
||||
|
||||
// update doc :)
|
||||
$phpDocInfo = $this->createPhpDocInfoFromNode($node);
|
||||
$this->updateNodeWithPhpDocInfo($node, $phpDocInfo);
|
||||
} else {
|
||||
$this->addTypeSpecificTag($node, 'var', $newType);
|
||||
}
|
||||
@ -314,7 +301,6 @@ final class DocBlockManipulator
|
||||
$newPHPStanPhpDocType = $this->staticTypeMapper->mapPHPStanTypeToPHPStanPhpDocTypeNode($newType);
|
||||
$returnTagValueNode->type = $newPHPStanPhpDocType;
|
||||
|
||||
$this->updateNodeWithPhpDocInfo($node, $phpDocInfo);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -412,11 +398,7 @@ final class DocBlockManipulator
|
||||
}
|
||||
|
||||
$phpDocInfo = $this->createPhpDocInfoFromNode($node);
|
||||
$hasNodeChanged = $this->docBlockNameImporter->importNames($phpDocInfo, $node);
|
||||
|
||||
if ($hasNodeChanged) {
|
||||
$this->updateNodeWithPhpDocInfo($node, $phpDocInfo);
|
||||
}
|
||||
$this->docBlockNameImporter->importNames($phpDocInfo, $node);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -467,8 +449,6 @@ final class DocBlockManipulator
|
||||
if (! $this->hasPhpDocChanged) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->updateNodeWithPhpDocInfo($node, $phpDocInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -502,26 +482,30 @@ final class DocBlockManipulator
|
||||
return false;
|
||||
}
|
||||
|
||||
public function updateNodeWithPhpDocInfo(
|
||||
Node $node,
|
||||
PhpDocInfo $phpDocInfo,
|
||||
bool $shouldSkipEmptyLinesAbove = false
|
||||
): bool {
|
||||
$phpDoc = $this->phpDocInfoPrinter->printFormatPreserving($phpDocInfo, $shouldSkipEmptyLinesAbove);
|
||||
if ($phpDoc !== '') {
|
||||
// no change, don't save it
|
||||
if ($node->getDocComment() && $node->getDocComment()->getText() === $phpDoc) {
|
||||
return false;
|
||||
}
|
||||
public function updateNodeWithPhpDocInfo(Node $node, bool $shouldSkipEmptyLinesAbove = false): void
|
||||
{
|
||||
$phpDocInfo = $node->getAttribute(AttributeKey::PHP_DOC_INFO);
|
||||
|
||||
$node->setDocComment(new Doc($phpDoc));
|
||||
return true;
|
||||
// nothing to change
|
||||
if ($phpDocInfo === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// no comments, null
|
||||
$node->setAttribute('comments', null);
|
||||
$phpDoc = $this->phpDocInfoPrinter->printFormatPreserving($phpDocInfo, $shouldSkipEmptyLinesAbove);
|
||||
if ($phpDoc === '') {
|
||||
// no comments, null
|
||||
$node->setAttribute('comments', null);
|
||||
return;
|
||||
}
|
||||
|
||||
return true;
|
||||
// no change, don't save it
|
||||
// this is needed to prevent short classes override with FQN with same value → people don't like that for some reason
|
||||
|
||||
if ($node->getDocComment() && $node->getDocComment()->getText() === $phpDoc) {
|
||||
return;
|
||||
}
|
||||
|
||||
$node->setDocComment(new Doc($phpDoc));
|
||||
}
|
||||
|
||||
public function getDoctrineFqnTargetEntity(Node $node): ?string
|
||||
@ -574,10 +558,7 @@ final class DocBlockManipulator
|
||||
return true;
|
||||
}
|
||||
|
||||
$firstTypeHash = $this->typeHasher->createTypeHash($firstType);
|
||||
$secondTypeHash = $this->typeHasher->createTypeHash($secondType);
|
||||
|
||||
if ($firstTypeHash === $secondTypeHash) {
|
||||
if ($this->typeHasher->areTypesEqual($firstType, $secondType)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -604,8 +585,6 @@ final class DocBlockManipulator
|
||||
$docStringType
|
||||
), '', '');
|
||||
$phpDocNode->children[] = new AttributeAwarePhpDocTagNode('@' . $name, $varTagValueNode);
|
||||
|
||||
$this->updateNodeWithPhpDocInfo($node, $phpDocInfo);
|
||||
} else {
|
||||
// create completely new docblock
|
||||
$varDocComment = sprintf("/**\n * @%s %s\n */", $name, $docStringType);
|
||||
|
@ -30,7 +30,7 @@ array(
|
||||
5: RandomProperty
|
||||
)
|
||||
attributes: array(
|
||||
classNode: null
|
||||
PhpParser\Node\Stmt\ClassLike: null
|
||||
className: null
|
||||
methodName: null
|
||||
)
|
||||
@ -41,7 +41,7 @@ array(
|
||||
name: Identifier #3(
|
||||
name: foo
|
||||
attributes: array(
|
||||
classNode: Stmt_Class #2
|
||||
PhpParser\Node\Stmt\ClassLike: Stmt_Class #2
|
||||
className: Rector\NodeTypeResolver\Tests\NodeVisitor\FunctionMethodAndClassNodeVisitorTest\RandomProperty\foo
|
||||
methodName: null
|
||||
)
|
||||
@ -53,7 +53,7 @@ array(
|
||||
name: Identifier #5(
|
||||
name: bar
|
||||
attributes: array(
|
||||
classNode: Stmt_Class #2
|
||||
PhpParser\Node\Stmt\ClassLike: Stmt_Class #2
|
||||
className: Rector\NodeTypeResolver\Tests\NodeVisitor\FunctionMethodAndClassNodeVisitorTest\RandomProperty\foo
|
||||
methodName: bar
|
||||
)
|
||||
@ -70,32 +70,32 @@ array(
|
||||
name: Identifier #10(
|
||||
name: baz
|
||||
attributes: array(
|
||||
classNode: Stmt_Class #8
|
||||
PhpParser\Node\Stmt\ClassLike: Stmt_Class #8
|
||||
className: null
|
||||
methodName: baz
|
||||
)
|
||||
)
|
||||
attributes: array(
|
||||
classNode: Stmt_Class #8
|
||||
PhpParser\Node\Stmt\ClassLike: Stmt_Class #8
|
||||
className: null
|
||||
methodName: baz
|
||||
)
|
||||
)
|
||||
)
|
||||
attributes: array(
|
||||
classNode: Stmt_Class #8
|
||||
PhpParser\Node\Stmt\ClassLike: Stmt_Class #8
|
||||
className: null
|
||||
methodName: bar
|
||||
)
|
||||
)
|
||||
attributes: array(
|
||||
classNode: Stmt_Class #2
|
||||
PhpParser\Node\Stmt\ClassLike: Stmt_Class #2
|
||||
className: Rector\NodeTypeResolver\Tests\NodeVisitor\FunctionMethodAndClassNodeVisitorTest\RandomProperty\foo
|
||||
methodName: bar
|
||||
)
|
||||
)
|
||||
attributes: array(
|
||||
classNode: Stmt_Class #2
|
||||
PhpParser\Node\Stmt\ClassLike: Stmt_Class #2
|
||||
className: Rector\NodeTypeResolver\Tests\NodeVisitor\FunctionMethodAndClassNodeVisitorTest\RandomProperty\foo
|
||||
methodName: bar
|
||||
)
|
||||
@ -107,40 +107,40 @@ array(
|
||||
0: moreCode
|
||||
)
|
||||
attributes: array(
|
||||
classNode: Stmt_Class #2
|
||||
PhpParser\Node\Stmt\ClassLike: Stmt_Class #2
|
||||
className: Rector\NodeTypeResolver\Tests\NodeVisitor\FunctionMethodAndClassNodeVisitorTest\RandomProperty\foo
|
||||
methodName: baz
|
||||
)
|
||||
)
|
||||
attributes: array(
|
||||
classNode: Stmt_Class #2
|
||||
PhpParser\Node\Stmt\ClassLike: Stmt_Class #2
|
||||
className: Rector\NodeTypeResolver\Tests\NodeVisitor\FunctionMethodAndClassNodeVisitorTest\RandomProperty\foo
|
||||
methodName: baz
|
||||
)
|
||||
)
|
||||
attributes: array(
|
||||
classNode: Stmt_Class #2
|
||||
PhpParser\Node\Stmt\ClassLike: Stmt_Class #2
|
||||
className: Rector\NodeTypeResolver\Tests\NodeVisitor\FunctionMethodAndClassNodeVisitorTest\RandomProperty\foo
|
||||
methodName: baz
|
||||
)
|
||||
)
|
||||
)
|
||||
attributes: array(
|
||||
classNode: Stmt_Class #2
|
||||
PhpParser\Node\Stmt\ClassLike: Stmt_Class #2
|
||||
className: Rector\NodeTypeResolver\Tests\NodeVisitor\FunctionMethodAndClassNodeVisitorTest\RandomProperty\foo
|
||||
methodName: bar
|
||||
)
|
||||
)
|
||||
)
|
||||
attributes: array(
|
||||
classNode: Stmt_Class #2
|
||||
PhpParser\Node\Stmt\ClassLike: Stmt_Class #2
|
||||
className: Rector\NodeTypeResolver\Tests\NodeVisitor\FunctionMethodAndClassNodeVisitorTest\RandomProperty\foo
|
||||
methodName: null
|
||||
)
|
||||
)
|
||||
)
|
||||
attributes: array(
|
||||
classNode: null
|
||||
PhpParser\Node\Stmt\ClassLike: null
|
||||
className: null
|
||||
methodName: null
|
||||
)
|
||||
|
@ -23,7 +23,7 @@ array(
|
||||
5: Simple
|
||||
)
|
||||
attributes: array(
|
||||
classNode: null
|
||||
PhpParser\Node\Stmt\ClassLike: null
|
||||
className: null
|
||||
methodName: null
|
||||
)
|
||||
@ -34,7 +34,7 @@ array(
|
||||
name: Identifier #3(
|
||||
name: foo
|
||||
attributes: array(
|
||||
classNode: Stmt_Class #2
|
||||
PhpParser\Node\Stmt\ClassLike: Stmt_Class #2
|
||||
className: Rector\NodeTypeResolver\Tests\NodeVisitor\FunctionMethodAndClassNodeVisitorTest\Simple\foo
|
||||
methodName: null
|
||||
)
|
||||
@ -46,27 +46,27 @@ array(
|
||||
name: Identifier #5(
|
||||
name: bar
|
||||
attributes: array(
|
||||
classNode: Stmt_Class #2
|
||||
PhpParser\Node\Stmt\ClassLike: Stmt_Class #2
|
||||
className: Rector\NodeTypeResolver\Tests\NodeVisitor\FunctionMethodAndClassNodeVisitorTest\Simple\foo
|
||||
methodName: bar
|
||||
)
|
||||
)
|
||||
attributes: array(
|
||||
classNode: Stmt_Class #2
|
||||
PhpParser\Node\Stmt\ClassLike: Stmt_Class #2
|
||||
className: Rector\NodeTypeResolver\Tests\NodeVisitor\FunctionMethodAndClassNodeVisitorTest\Simple\foo
|
||||
methodName: bar
|
||||
)
|
||||
)
|
||||
)
|
||||
attributes: array(
|
||||
classNode: Stmt_Class #2
|
||||
PhpParser\Node\Stmt\ClassLike: Stmt_Class #2
|
||||
className: Rector\NodeTypeResolver\Tests\NodeVisitor\FunctionMethodAndClassNodeVisitorTest\Simple\foo
|
||||
methodName: null
|
||||
)
|
||||
)
|
||||
)
|
||||
attributes: array(
|
||||
classNode: null
|
||||
PhpParser\Node\Stmt\ClassLike: null
|
||||
className: null
|
||||
methodName: null
|
||||
)
|
||||
|
@ -18,7 +18,9 @@ use PhpParser\Node\Stmt\Static_;
|
||||
use PhpParser\Node\Stmt\Switch_;
|
||||
use PhpParser\Node\Stmt\Throw_;
|
||||
use PhpParser\Node\Stmt\While_;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\VarTagValueNode;
|
||||
use Rector\AttributeAwarePhpDoc\Ast\PhpDoc\AttributeAwareVarTagValueNode;
|
||||
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
|
||||
use Rector\Rector\AbstractRector;
|
||||
use Rector\RectorDefinition\CodeSample;
|
||||
use Rector\RectorDefinition\RectorDefinition;
|
||||
@ -76,12 +78,18 @@ PHP
|
||||
return null;
|
||||
}
|
||||
|
||||
$nodeContent = $this->print($node);
|
||||
// clear phpdoc - @see https://regex101.com/r/uwY5KW/1
|
||||
$nodeContentWithoutPhpDoc = Strings::replace($nodeContent, '#\/\*\*(.*?)*\/#');
|
||||
|
||||
// it's there
|
||||
if (Strings::match($this->print($node), '#' . preg_quote($variableName, '#') . '\b#')) {
|
||||
if (Strings::match($nodeContentWithoutPhpDoc, '#' . preg_quote($variableName, '#') . '\b#')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$this->docBlockManipulator->removeTagFromNode($node, 'var');
|
||||
/** @var PhpDocInfo $phpDocInfo */
|
||||
$phpDocInfo = $this->getPhpDocInfo($node);
|
||||
$phpDocInfo->removeByType(VarTagValueNode::class);
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
@ -155,8 +155,6 @@ PHP
|
||||
$phpDocNode->children[] = new AttributeAwarePhpDocTagNode('@doesNotPerformAssertion', new GenericTagValueNode(
|
||||
''
|
||||
));
|
||||
|
||||
$this->docBlockManipulator->updateNodeWithPhpDocInfo($classMethod, $phpDocInfo);
|
||||
}
|
||||
|
||||
private function containsAssertCall(ClassMethod $classMethod): bool
|
||||
|
@ -165,7 +165,5 @@ PHP
|
||||
$phpDocInfo = $this->getPhpDocInfo($privateProperty);
|
||||
$phpDocNode = $phpDocInfo->getPhpDocNode();
|
||||
$phpDocNode->children[] = new AttributeAwarePhpDocTagNode('@inject', new GenericTagValueNode(''));
|
||||
|
||||
$this->docBlockManipulator->updateNodeWithPhpDocInfo($privateProperty, $phpDocInfo);
|
||||
}
|
||||
}
|
||||
|
@ -139,7 +139,6 @@ PHP
|
||||
}
|
||||
|
||||
$propertyPhpDocInfo->removeByType(VarTagValueNode::class);
|
||||
$this->docBlockManipulator->updateNodeWithPhpDocInfo($property, $propertyPhpDocInfo);
|
||||
}
|
||||
|
||||
private function isNonBasicArrayType(Property $property, VarTagValueNode $varTagValueNode): bool
|
||||
|
@ -101,10 +101,11 @@ PHP
|
||||
return null;
|
||||
}
|
||||
|
||||
$lastIfStmtKey = array_key_last($node->stmts);
|
||||
|
||||
/** @var Assign $assign */
|
||||
$assign = $this->stmtsManipulator->getUnwrappedLastStmt($node->stmts);
|
||||
|
||||
$lastIfStmtKey = array_key_last($node->stmts);
|
||||
$node->stmts[$lastIfStmtKey] = new Return_($assign->expr);
|
||||
|
||||
/** @var Assign $assign */
|
||||
|
@ -73,13 +73,13 @@ PHP
|
||||
*/
|
||||
public function refactor(Node $node): ?Node
|
||||
{
|
||||
$phpDocInfo = $this->getPhpDocInfo($node);
|
||||
if ($phpDocInfo === null) {
|
||||
// skip properties
|
||||
if ($node instanceof Property) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// skip properties
|
||||
if ($node instanceof Property) {
|
||||
$phpDocInfo = $this->getPhpDocInfo($node);
|
||||
if ($phpDocInfo === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -133,6 +133,7 @@ PHP
|
||||
if (! $node instanceof Expression) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! $node->expr instanceof Assign) {
|
||||
return false;
|
||||
}
|
||||
@ -149,7 +150,7 @@ PHP
|
||||
|
||||
private function refactorFreshlyCreatedNode(Node $node, PhpDocInfo $phpDocInfo, Variable $variable): ?Node
|
||||
{
|
||||
$node->setAttribute('comments', []);
|
||||
$node->setAttribute('comments', null);
|
||||
$type = $phpDocInfo->getVarType();
|
||||
|
||||
$assertFuncCall = $this->createFuncCallBasedOnType($type, $variable);
|
||||
@ -157,7 +158,8 @@ PHP
|
||||
return null;
|
||||
}
|
||||
|
||||
$this->removeVarAnnotation($variable, $phpDocInfo);
|
||||
$phpDocInfo->removeByType(VarTagValueNode::class);
|
||||
|
||||
$this->addNodeBeforeNode($assertFuncCall, $node);
|
||||
|
||||
return $node;
|
||||
@ -166,7 +168,6 @@ PHP
|
||||
private function refactorAlreadyCreatedNode(Node $node, PhpDocInfo $phpDocInfo, Variable $variable): ?Node
|
||||
{
|
||||
$varTagValue = $phpDocInfo->getVarTagValue();
|
||||
|
||||
$phpStanType = $this->staticTypeMapper->mapPHPStanPhpDocTypeNodeToPHPStanType(
|
||||
$varTagValue->type,
|
||||
$variable
|
||||
@ -177,7 +178,6 @@ PHP
|
||||
return null;
|
||||
}
|
||||
|
||||
$this->removeVarAnnotation($variable, $phpDocInfo);
|
||||
$this->addNodeAfterNode($assertFuncCall, $node);
|
||||
|
||||
return $node;
|
||||
@ -212,11 +212,4 @@ PHP
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private function removeVarAnnotation(Node $node, PhpDocInfo $phpDocInfo): void
|
||||
{
|
||||
$phpDocInfo->removeByType(VarTagValueNode::class);
|
||||
|
||||
$this->docBlockManipulator->updateNodeWithPhpDocInfo($node, $phpDocInfo);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace Rector\StrictCodeQuality\Tests\Rector\Stmt\VarInlineAnnotationToAssertRector\Fixture;
|
||||
|
||||
class SingleScalarAssert
|
||||
{
|
||||
public function run($value)
|
||||
{
|
||||
/** @var int $value */
|
||||
$value->call();
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\StrictCodeQuality\Tests\Rector\Stmt\VarInlineAnnotationToAssertRector\Fixture;
|
||||
|
||||
class SingleScalarAssert
|
||||
{
|
||||
public function run($value)
|
||||
{
|
||||
assert(is_int($value));
|
||||
$value->call();
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
@ -102,8 +102,6 @@ PHP
|
||||
|
||||
$phpDocInfo->removeTagValueNodeFromNode($symfonyMethodPhpDocTagValueNode);
|
||||
|
||||
$this->docBlockManipulator->updateNodeWithPhpDocInfo($node, $phpDocInfo);
|
||||
|
||||
return $node;
|
||||
}
|
||||
}
|
||||
|
@ -7,30 +7,18 @@ namespace Rector\TypeDeclaration\TypeInferer\PropertyTypeInferer;
|
||||
use PhpParser\Node\Stmt\Property;
|
||||
use PHPStan\Type\MixedType;
|
||||
use PHPStan\Type\Type;
|
||||
use Rector\NodeTypeResolver\PhpDoc\NodeAnalyzer\DocBlockManipulator;
|
||||
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
use Rector\TypeDeclaration\Contract\TypeInferer\PropertyTypeInfererInterface;
|
||||
|
||||
final class VarDocPropertyTypeInferer implements PropertyTypeInfererInterface
|
||||
{
|
||||
/**
|
||||
* @var DocBlockManipulator
|
||||
*/
|
||||
private $docBlockManipulator;
|
||||
|
||||
public function __construct(DocBlockManipulator $docBlockManipulator)
|
||||
{
|
||||
$this->docBlockManipulator = $docBlockManipulator;
|
||||
}
|
||||
|
||||
public function inferProperty(Property $property): Type
|
||||
{
|
||||
if ($property->getDocComment() === null) {
|
||||
return new MixedType();
|
||||
}
|
||||
/** @var PhpDocInfo|null $phpDocInfo */
|
||||
$phpDocInfo = $property->getAttribute(AttributeKey::PHP_DOC_INFO);
|
||||
|
||||
$phpDocInfo = $this->docBlockManipulator->createPhpDocInfoFromNode($property);
|
||||
|
||||
return $phpDocInfo->getVarType();
|
||||
return $phpDocInfo ? $phpDocInfo->getVarType() : new MixedType();
|
||||
}
|
||||
|
||||
public function getPriority(): int
|
||||
|
@ -233,3 +233,6 @@ parameters:
|
||||
- '#Parameter \#1 \$node of method PHPStan\\Analyser\\Scope\:\:getType\(\) expects PhpParser\\Node\\Expr, PhpParser\\Node given#'
|
||||
|
||||
- '#Parameter \#2 \$name of class PhpParser\\Node\\Expr\\MethodCall constructor expects PhpParser\\Node\\Expr\|PhpParser\\Node\\Identifier\|string, string\|null given#'
|
||||
- '#Ternary operator condition is always false#'
|
||||
|
||||
- '#Parameter \#1 \$tagValueNode of method Rector\\BetterPhpDocParser\\PhpDocInfo\\PhpDocInfo\:\:addTagValueNodeWithShortName\(\) expects Rector\\BetterPhpDocParser\\PhpDocNode\\AbstractTagValueNode, PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocTagNode\|Rector\\BetterPhpDocParser\\PhpDocNode\\Doctrine\\Property_\\JoinColumnTagValueNode given#'
|
||||
|
@ -1,21 +1,30 @@
|
||||
parameters:
|
||||
sets:
|
||||
- 'coding-style'
|
||||
- 'code-quality'
|
||||
- 'dead-code'
|
||||
- 'nette-utils-code-quality'
|
||||
services:
|
||||
Rector\DeadCode\Rector\ClassMethod\RemoveOverriddenValuesRector: null
|
||||
Rector\CodingStyle\Rector\Use_\RemoveUnusedAliasRector: null
|
||||
|
||||
paths:
|
||||
- 'src'
|
||||
- 'packages'
|
||||
- 'tests'
|
||||
|
||||
exclude_paths:
|
||||
- '/Fixture/'
|
||||
- '/Source/'
|
||||
- '/Expected/'
|
||||
|
||||
exclude_rectors:
|
||||
# @todo needs to check for "autoload-dev" local dependency
|
||||
- 'Rector\Php55\Rector\String_\StringClassNameToClassConstantRector'
|
||||
- 'Rector\CodingStyle\Rector\String_\SplitStringClassConstantToClassConstFetchRector'
|
||||
# Rector\CodeQuality\Rector\If_\RemoveAlwaysTrueConditionSetInConstructorRector: null
|
||||
# Rector\CodingStyle\Rector\ClassMethod\NewlineBeforeNewAssignSetRector: null
|
||||
#
|
||||
#
|
||||
#parameters:
|
||||
# sets:
|
||||
# - 'coding-style'
|
||||
## - 'code-quality'
|
||||
# - 'dead-code'
|
||||
## - 'nette-utils-code-quality'
|
||||
#
|
||||
# paths:
|
||||
# - 'src'
|
||||
# - 'packages'
|
||||
# - 'tests'
|
||||
#
|
||||
# exclude_paths:
|
||||
# - '/Fixture/'
|
||||
# - '/Source/'
|
||||
# - '/Expected/'
|
||||
#
|
||||
# exclude_rectors:
|
||||
# # @todo needs to check for "autoload-dev" local dependency
|
||||
# - 'Rector\Php55\Rector\String_\StringClassNameToClassConstantRector'
|
||||
# - 'Rector\CodingStyle\Rector\String_\SplitStringClassConstantToClassConstFetchRector'
|
||||
## - 'Rector\DeadCode\Rector\ClassMethod\RemoveOverriddenValuesRector'
|
||||
|
@ -23,10 +23,10 @@ final class AppliedRectorCollector
|
||||
*/
|
||||
public function getRectorClasses(SmartFileInfo $smartFileInfo): array
|
||||
{
|
||||
if (isset($this->rectorClassesByFile[$smartFileInfo->getRealPath()])) {
|
||||
return array_unique($this->rectorClassesByFile[$smartFileInfo->getRealPath()]);
|
||||
if (! isset($this->rectorClassesByFile[$smartFileInfo->getRealPath()])) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return [];
|
||||
return array_unique($this->rectorClassesByFile[$smartFileInfo->getRealPath()]);
|
||||
}
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ use PhpParser\Node\Stmt\Nop;
|
||||
use PhpParser\Node\Stmt\TraitUse;
|
||||
use PhpParser\PrettyPrinter\Standard;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
use Rector\NodeTypeResolver\PhpDoc\NodeAnalyzer\DocBlockManipulator;
|
||||
use Symplify\SmartFileSystem\SmartFileInfo;
|
||||
|
||||
/**
|
||||
@ -34,6 +35,11 @@ final class BetterStandardPrinter extends Standard
|
||||
*/
|
||||
private $tabOrSpaceIndentCharacter = ' ';
|
||||
|
||||
/**
|
||||
* @var DocBlockManipulator
|
||||
*/
|
||||
private $docBlockManipulator;
|
||||
|
||||
/**
|
||||
* @param mixed[] $options
|
||||
*/
|
||||
@ -48,6 +54,14 @@ final class BetterStandardPrinter extends Standard
|
||||
$this->insertionMap['Expr_Closure->returnType'] = [')', false, ': ', null];
|
||||
}
|
||||
|
||||
/**
|
||||
* @required
|
||||
*/
|
||||
public function autowireBetterStandardPrinter(DocBlockManipulator $docBlockManipulator): void
|
||||
{
|
||||
$this->docBlockManipulator = $docBlockManipulator;
|
||||
}
|
||||
|
||||
public function printFormatPreserving(array $stmts, array $origStmts, array $origTokens): string
|
||||
{
|
||||
// detect per print
|
||||
@ -60,6 +74,17 @@ final class BetterStandardPrinter extends Standard
|
||||
return Strings::replace($clearContent, '#\<\?php(\s+)\?\>#');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Node|Node[]|null $node
|
||||
*/
|
||||
public function printWithoutComments($node): string
|
||||
{
|
||||
$printerNode = $this->print($node);
|
||||
|
||||
$nodeWithoutComments = $this->removeComments($printerNode);
|
||||
return trim($nodeWithoutComments);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Node|Node[]|null $node
|
||||
*/
|
||||
@ -73,12 +98,6 @@ final class BetterStandardPrinter extends Standard
|
||||
return 'UNABLE_TO_PRINT_ENCAPSED_STRING';
|
||||
}
|
||||
|
||||
// remove comments, for value compare
|
||||
if ($node instanceof Node) {
|
||||
$node = clone $node;
|
||||
$node->setAttribute('comments', null);
|
||||
}
|
||||
|
||||
if (! is_array($node)) {
|
||||
$node = [$node];
|
||||
}
|
||||
@ -95,6 +114,15 @@ final class BetterStandardPrinter extends Standard
|
||||
return $this->print($firstNode) === $this->print($secondNode);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Node|Node[]|null $firstNode
|
||||
* @param Node|Node[]|null $secondNode
|
||||
*/
|
||||
public function areNodesWithoutCommentsEqual($firstNode, $secondNode): bool
|
||||
{
|
||||
return $this->printWithoutComments($firstNode) === $this->printWithoutComments($secondNode);
|
||||
}
|
||||
|
||||
/**
|
||||
* This allows to use both spaces and tabs vs. original space-only
|
||||
*/
|
||||
@ -150,6 +178,8 @@ final class BetterStandardPrinter extends Standard
|
||||
// reindex positions for printer
|
||||
$nodes = array_values($nodes);
|
||||
|
||||
$this->moveCommentsFromAttributeObjectToCommentsAttribute($nodes);
|
||||
|
||||
$content = parent::pArray($nodes, $origNodes, $pos, $indentAdjustment, $parentNodeType, $subNodeName, $fixup);
|
||||
|
||||
if ($content === null) {
|
||||
@ -191,11 +221,16 @@ final class BetterStandardPrinter extends Standard
|
||||
}
|
||||
|
||||
/**
|
||||
* Add space after "use ("
|
||||
* Add space:
|
||||
* "use("
|
||||
* ↓
|
||||
* "use ("
|
||||
*/
|
||||
protected function pExpr_Closure(Closure $closure): string
|
||||
{
|
||||
return Strings::replace(parent::pExpr_Closure($closure), '#( use)\(#', '$1 (');
|
||||
$closureContent = parent::pExpr_Closure($closure);
|
||||
|
||||
return Strings::replace($closureContent, '#( use)\(#', '$1 (');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -246,6 +281,16 @@ final class BetterStandardPrinter extends Standard
|
||||
return parent::pScalar_String($node);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Node[] $nodes
|
||||
*/
|
||||
protected function pStmts(array $nodes, bool $indent = true): string
|
||||
{
|
||||
$this->moveCommentsFromAttributeObjectToCommentsAttribute($nodes);
|
||||
|
||||
return parent::pStmts($nodes, $indent);
|
||||
}
|
||||
|
||||
/**
|
||||
* "...$params) : ReturnType"
|
||||
* ↓
|
||||
@ -339,4 +384,25 @@ final class BetterStandardPrinter extends Standard
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo decopule
|
||||
*/
|
||||
private function moveCommentsFromAttributeObjectToCommentsAttribute(array $nodes): void
|
||||
{
|
||||
// move phpdoc from node to "comment" attirbute
|
||||
foreach ($nodes as $node) {
|
||||
if (! $node instanceof Node) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->docBlockManipulator->updateNodeWithPhpDocInfo($node);
|
||||
}
|
||||
}
|
||||
|
||||
private function removeComments(string $printerNode): string
|
||||
{
|
||||
$printerNode = Strings::replace($printerNode, '#\/*\*(.*?)\*\/#');
|
||||
return Strings::replace($printerNode, '#\/\/(.*?)$#m');
|
||||
}
|
||||
}
|
||||
|
@ -14,9 +14,13 @@ use PhpParser\Node\Stmt\Class_;
|
||||
use PhpParser\Node\Stmt\Expression;
|
||||
use PhpParser\NodeVisitorAbstract;
|
||||
use PHPStan\Analyser\Scope;
|
||||
use Rector\BetterPhpDocParser\Printer\PhpDocInfoPrinter;
|
||||
use Rector\CodingStyle\Rector\ClassMethod\NewlineBeforeNewAssignSetRector;
|
||||
use Rector\CodingStyle\Rector\Namespace_\ImportFullyQualifiedNamesRector;
|
||||
use Rector\Commander\CommanderCollector;
|
||||
use Rector\Contract\PhpParser\Node\CommanderInterface;
|
||||
use Rector\Contract\Rector\PhpRectorInterface;
|
||||
use Rector\DeadCode\Rector\FunctionLike\RemoveCodeAfterReturnRector;
|
||||
use Rector\Exclusion\ExclusionManager;
|
||||
use Rector\NodeTypeResolver\FileSystem\CurrentFileInfoProvider;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
@ -60,6 +64,11 @@ abstract class AbstractRector extends NodeVisitorAbstract implements PhpRectorIn
|
||||
*/
|
||||
private $currentFileInfoProvider;
|
||||
|
||||
/**
|
||||
* @var PhpDocInfoPrinter
|
||||
*/
|
||||
protected $phpDocInfoPrinter;
|
||||
|
||||
/**
|
||||
* Run once in the every end of one processed file
|
||||
*/
|
||||
@ -76,7 +85,8 @@ abstract class AbstractRector extends NodeVisitorAbstract implements PhpRectorIn
|
||||
BuilderFactory $builderFactory,
|
||||
ExclusionManager $exclusionManager,
|
||||
CommanderCollector $commanderCollector,
|
||||
CurrentFileInfoProvider $currentFileInfoProvider
|
||||
CurrentFileInfoProvider $currentFileInfoProvider,
|
||||
PhpDocInfoPrinter $phpDocInfoPrinter
|
||||
): void {
|
||||
$this->symfonyStyle = $symfonyStyle;
|
||||
$this->phpVersionProvider = $phpVersionProvider;
|
||||
@ -84,6 +94,7 @@ abstract class AbstractRector extends NodeVisitorAbstract implements PhpRectorIn
|
||||
$this->exclusionManager = $exclusionManager;
|
||||
$this->commanderCollector = $commanderCollector;
|
||||
$this->currentFileInfoProvider = $currentFileInfoProvider;
|
||||
$this->phpDocInfoPrinter = $phpDocInfoPrinter;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -127,10 +138,6 @@ abstract class AbstractRector extends NodeVisitorAbstract implements PhpRectorIn
|
||||
$this->updateAttributes($node);
|
||||
$this->keepFileInfoAttribute($node, $originalNode);
|
||||
$this->notifyNodeChangeFileInfo($node);
|
||||
|
||||
// doc block has changed
|
||||
} elseif ($node->getComments() !== $originalComment || $node->getDocComment() !== $originalDocComment) {
|
||||
$this->notifyNodeChangeFileInfo($node);
|
||||
}
|
||||
|
||||
// if stmt ("$value;") was replaced by expr ("$value"), add the ending ";" (Expression) to prevent breaking the code
|
||||
@ -275,6 +282,10 @@ abstract class AbstractRector extends NodeVisitorAbstract implements PhpRectorIn
|
||||
|
||||
private function hasNodeChanged(Node $originalNode, Node $node): bool
|
||||
{
|
||||
if ($this->isNameIdentical($node, $originalNode)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ! $this->areNodesEqual($originalNode, $node);
|
||||
}
|
||||
|
||||
@ -314,4 +325,18 @@ abstract class AbstractRector extends NodeVisitorAbstract implements PhpRectorIn
|
||||
$this->addNodeAfterNode($ifStmt, $node);
|
||||
}
|
||||
}
|
||||
|
||||
private function isNameIdentical(Node $node, Node $originalNode): bool
|
||||
{
|
||||
if (static::class !== ImportFullyQualifiedNamesRector::class) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! $originalNode instanceof Name) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// names are the same
|
||||
return $this->areNodesEqual($originalNode->getAttribute('originalName'), $node);
|
||||
}
|
||||
}
|
||||
|
@ -63,6 +63,15 @@ trait BetterStandardPrinterTrait
|
||||
return $this->betterStandardPrinter->areNodesEqual($firstNode, $secondNode);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Node|Node[]|null $firstNode
|
||||
* @param Node|Node[]|null $secondNode
|
||||
*/
|
||||
protected function areNodesWithoutCommentsEqual($firstNode, $secondNode): bool
|
||||
{
|
||||
return $this->betterStandardPrinter->areNodesWithoutCommentsEqual($firstNode, $secondNode);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Node[] $availableNodes
|
||||
*/
|
||||
|
@ -6,6 +6,7 @@ namespace Rector\Rector\AbstractRector;
|
||||
|
||||
use PhpParser\Node;
|
||||
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
use Rector\NodeTypeResolver\PhpDoc\NodeAnalyzer\DocBlockManipulator;
|
||||
use Rector\NodeTypeResolver\StaticTypeMapper;
|
||||
|
||||
@ -38,10 +39,18 @@ trait DocBlockManipulatorTrait
|
||||
|
||||
protected function getPhpDocInfo(Node $node): ?PhpDocInfo
|
||||
{
|
||||
if ($node->getAttribute(AttributeKey::PHP_DOC_INFO)) {
|
||||
return $node->getAttribute(AttributeKey::PHP_DOC_INFO);
|
||||
}
|
||||
|
||||
// @todo always use PhpDocInfo even for empty nodes, for consisteny object API; same way Nop node does
|
||||
if ($node->getDocComment() === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->docBlockManipulator->createPhpDocInfoFromNode($node);
|
||||
$phpDocInfo = $this->docBlockManipulator->createPhpDocInfoFromNode($node);
|
||||
$node->setAttribute(AttributeKey::PHP_DOC_INFO, $phpDocInfo);
|
||||
|
||||
return $phpDocInfo;
|
||||
}
|
||||
}
|
||||
|
@ -101,6 +101,8 @@ trait NodeFactoryTrait
|
||||
*/
|
||||
protected function createFunction(string $name, array $arguments = []): FuncCall
|
||||
{
|
||||
$arguments = $this->createArgs($arguments);
|
||||
|
||||
return new FuncCall(new Name($name), $arguments);
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,7 @@ namespace Rector\Rector\Property;
|
||||
|
||||
use DI\Annotation\Inject as PHPDIInject;
|
||||
use JMS\DiExtraBundle\Annotation\Inject as JMSInject;
|
||||
use Nette\Utils\Strings;
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Stmt\Class_;
|
||||
use PhpParser\Node\Stmt\Property;
|
||||
@ -139,7 +140,12 @@ PHP
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($this->isParameterInject($injectTagValueNode)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$type = $this->resolveType($node, $injectTagValueNode);
|
||||
|
||||
return $this->refactorPropertyWithAnnotation($node, $type, $tagClass);
|
||||
}
|
||||
|
||||
@ -233,4 +239,18 @@ PHP
|
||||
|
||||
return new MixedType();
|
||||
}
|
||||
|
||||
private function isParameterInject(PhpDocTagValueNode $phpDocTagValueNode): bool
|
||||
{
|
||||
if (! $phpDocTagValueNode instanceof JMSInjectTagValueNode) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$serviceName = $phpDocTagValueNode->getServiceName();
|
||||
if ($serviceName === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (bool) Strings::match($serviceName, '#%(.*?)%#');
|
||||
}
|
||||
}
|
||||
|
@ -15,11 +15,6 @@ class SomeController
|
||||
* @DI\Inject("translator", strict = false, required = false)
|
||||
*/
|
||||
private $translator;
|
||||
|
||||
/**
|
||||
* @DI\Inject("%kernel.cache_dir%")
|
||||
*/
|
||||
private $cacheDir;
|
||||
}
|
||||
|
||||
?>
|
||||
@ -36,16 +31,10 @@ class SomeController
|
||||
* @var \Rector\Symfony\Tests\Rector\FrameworkBundle\AbstractToConstructorInjectionRectorSource\SomeEntityManager
|
||||
*/
|
||||
private $entityManager;
|
||||
|
||||
/**
|
||||
* @var \Rector\Symfony\Tests\Rector\FrameworkBundle\AbstractToConstructorInjectionRectorSource\SomeTranslatorInterface
|
||||
*/
|
||||
private $translator;
|
||||
|
||||
/**
|
||||
* @DI\Inject("%kernel.cache_dir%")
|
||||
*/
|
||||
private $cacheDir;
|
||||
public function __construct(\Rector\Symfony\Tests\Rector\FrameworkBundle\AbstractToConstructorInjectionRectorSource\SomeEntityManager $entityManager, \Rector\Symfony\Tests\Rector\FrameworkBundle\AbstractToConstructorInjectionRectorSource\SomeTranslatorInterface $translator)
|
||||
{
|
||||
$this->entityManager = $entityManager;
|
||||
|
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\Rector\Property\InjectAnnotationClassRector\Fixture;
|
||||
|
||||
use JMS\DiExtraBundle\Annotation as DI;
|
||||
|
||||
class SkipParameterInject
|
||||
{
|
||||
/**
|
||||
* @DI\Inject("%kernel.cache_dir%")
|
||||
*/
|
||||
private $cacheDir;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user