diff --git a/ecs.yaml b/ecs.yaml index 04467c01588..d6348df7e65 100644 --- a/ecs.yaml +++ b/ecs.yaml @@ -76,6 +76,7 @@ parameters: - 'src/Rector/AbstractRector.php' Symplify\CodingStandard\Sniffs\CleanCode\CognitiveComplexitySniff: + - 'packages/NodeTypeResolver/src/PhpDoc/NodeAnalyzer/DocBlockManipulator.php' - 'packages/MinimalScope/src/Rector/Class_/ChangeLocalPropertyToVariableRector.php' - 'packages/CodingStyle/src/Rector/ClassMethod/NewlineBeforeNewAssignSetRector.php' # solve later diff --git a/packages/NodeTypeResolver/src/PhpDoc/NodeAnalyzer/DocBlockManipulator.php b/packages/NodeTypeResolver/src/PhpDoc/NodeAnalyzer/DocBlockManipulator.php index f457380724d..a95f9866e4d 100644 --- a/packages/NodeTypeResolver/src/PhpDoc/NodeAnalyzer/DocBlockManipulator.php +++ b/packages/NodeTypeResolver/src/PhpDoc/NodeAnalyzer/DocBlockManipulator.php @@ -16,7 +16,6 @@ use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocChildNode; use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocNode; use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode; use PHPStan\PhpDocParser\Ast\PhpDoc\ReturnTagValueNode; -use PHPStan\PhpDocParser\Ast\PhpDoc\VarTagValueNode; use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode; use PHPStan\Type\Constant\ConstantArrayType; use PHPStan\Type\MixedType; @@ -35,7 +34,6 @@ use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo; use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory; use Rector\BetterPhpDocParser\PhpDocNode\AbstractTagValueNode; use Rector\BetterPhpDocParser\Printer\PhpDocInfoPrinter; -use Rector\NodeTypeResolver\Exception\MissingTagException; use Rector\NodeTypeResolver\Node\AttributeKey; use Rector\NodeTypeResolver\PHPStan\TypeComparator; use Rector\NodeTypeResolver\StaticTypeMapper; @@ -237,15 +235,14 @@ final class DocBlockManipulator return; } - if ($this->hasTag($node, '@var')) { - // just change the type - $varTag = $this->getTagByName($node, '@var'); - - /** @var VarTagValueNode $varTagValueNode */ - $varTagValueNode = $varTag->value; - - $phpDocType = $this->staticTypeMapper->mapPHPStanTypeToPHPStanPhpDocTypeNode($newType); - $varTagValueNode->type = $phpDocType; + if ($phpDocInfo !== null) { + $currentVarTagValue = $phpDocInfo->getVarTagValue(); + if ($currentVarTagValue !== null) { + $phpDocType = $this->staticTypeMapper->mapPHPStanTypeToPHPStanPhpDocTypeNode($newType); + $currentVarTagValue->type = $phpDocType; + } else { + $this->addTypeSpecificTag($node, 'var', $newType); + } } else { $this->addTypeSpecificTag($node, 'var', $newType); } @@ -285,20 +282,6 @@ final class DocBlockManipulator $returnTagValueNode->type = $newPHPStanPhpDocType; } - /** - * @final - */ - public function getTagByName(Node $node, string $name): PhpDocTagNode - { - if (! $this->hasTag($node, $name)) { - throw new MissingTagException(sprintf('Tag "%s" was not found at "%s" node.', $name, get_class($node))); - } - - /** @var PhpDocTagNode[] $foundTags */ - $foundTags = $this->getTagsByName($node, $name); - return array_shift($foundTags); - } - public function replaceTagByAnother(PhpDocNode $phpDocNode, string $oldTag, string $newTag): void { $oldTag = AnnotationNaming::normalizeName($oldTag); @@ -489,6 +472,9 @@ final class DocBlockManipulator // create completely new docblock $varDocComment = sprintf("/**\n * @%s %s\n */", $name, $docStringType); $node->setDocComment(new Doc($varDocComment)); + + // bind new content with node + $this->phpDocInfoFactory->createFromNode($node); } } } diff --git a/packages/PHPStan/src/Rector/Node/RemoveNonExistingVarAnnotationRector.php b/packages/PHPStan/src/Rector/Node/RemoveNonExistingVarAnnotationRector.php index b444d34812a..6659332ccff 100644 --- a/packages/PHPStan/src/Rector/Node/RemoveNonExistingVarAnnotationRector.php +++ b/packages/PHPStan/src/Rector/Node/RemoveNonExistingVarAnnotationRector.php @@ -19,7 +19,6 @@ 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\NodeTypeResolver\Node\AttributeKey; use Rector\Rector\AbstractRector; @@ -28,6 +27,7 @@ use Rector\RectorDefinition\RectorDefinition; /** * @see \Rector\PHPStan\Tests\Rector\Node\RemoveNonExistingVarAnnotationRector\RemoveNonExistingVarAnnotationRectorTest + * * @see https://github.com/phpstan/phpstan/commit/d17e459fd9b45129c5deafe12bca56f30ea5ee99#diff-9f3541876405623b0d18631259763dc1 */ final class RemoveNonExistingVarAnnotationRector extends AbstractRector @@ -74,22 +74,29 @@ PHP return null; } - $variableName = $this->getVarTagVariableName($node); + /** @var PhpDocInfo|null $phpDocInfo */ + $phpDocInfo = $node->getAttribute(AttributeKey::PHP_DOC_INFO); + if ($phpDocInfo === null) { + return null; + } + + $varTagValue = $phpDocInfo->getVarTagValue(); + if ($varTagValue === null) { + return null; + } + + $variableName = $varTagValue->variableName; if ($variableName === null) { return null; } - $nodeContent = $this->print($node); - // clear phpdoc - @see https://regex101.com/r/uwY5KW/1 - $nodeContentWithoutPhpDoc = Strings::replace($nodeContent, '#\/\*\*(.*?)*\/#'); + $nodeContentWithoutPhpDoc = $this->printWithoutComments($node); // it's there if (Strings::match($nodeContentWithoutPhpDoc, '#' . preg_quote($variableName, '#') . '\b#')) { return null; } - /** @var PhpDocInfo $phpDocInfo */ - $phpDocInfo = $node->getAttribute(AttributeKey::PHP_DOC_INFO); $phpDocInfo->removeByType(VarTagValueNode::class); return $node; @@ -110,18 +117,4 @@ PHP && ! $node instanceof Switch_ && ! $node instanceof Nop; } - - private function getVarTagVariableName(Node $node): ?string - { - if (! $this->docBlockManipulator->hasTag($node, 'var')) { - return null; - } - - $varTag = $this->docBlockManipulator->getTagByName($node, 'var'); - - /** @var AttributeAwareVarTagValueNode $varTagValue */ - $varTagValue = $varTag->value; - - return $varTagValue->variableName; - } } diff --git a/src/Rector/AbstractRector/BetterStandardPrinterTrait.php b/src/Rector/AbstractRector/BetterStandardPrinterTrait.php index 0ac658b4036..35d56514468 100644 --- a/src/Rector/AbstractRector/BetterStandardPrinterTrait.php +++ b/src/Rector/AbstractRector/BetterStandardPrinterTrait.php @@ -44,6 +44,14 @@ trait BetterStandardPrinterTrait return $this->betterStandardPrinter->print($node); } + /** + * @param Node|Node[]|null $node + */ + public function printWithoutComments($node): string + { + return $this->betterStandardPrinter->printWithoutComments($node); + } + /** * @param Node|Node[]|null $node */