use PhpDocInfo by default

This commit is contained in:
TomasVotruba 2020-02-02 19:15:36 +01:00
parent a7b4596fd8
commit 5e238cc3b1
40 changed files with 196 additions and 280 deletions

View File

@ -11,8 +11,11 @@ use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocChildNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagValueNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\ReturnTagValueNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\VarTagValueNode;
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
use PHPStan\Type\Constant\ConstantArrayType;
use PHPStan\Type\MixedType;
use PHPStan\Type\NeverType;
use PHPStan\Type\Type;
use Rector\AttributeAwarePhpDoc\Ast\PhpDoc\AttributeAwareParamTagValueNode;
use Rector\AttributeAwarePhpDoc\Ast\PhpDoc\AttributeAwarePhpDocNode;
@ -308,6 +311,32 @@ final class PhpDocInfo
return $paramTypesByName;
}
public function changeVarType(Type $newType): void
{
// make sure the tags are not identical, e.g imported class vs FQN class
if ($this->typeComparator->areTypesEquals($this->getVarType(), $newType)) {
return;
}
// prevent existing type override by mixed
if (! $this->getVarType() instanceof MixedType && $newType instanceof ConstantArrayType && $newType->getItemType() instanceof NeverType) {
return;
}
// override existing type
$newPHPStanPhpDocType = $this->staticTypeMapper->mapPHPStanTypeToPHPStanPhpDocTypeNode($newType);
$currentVarTagValueNode = $this->getVarTagValue();
if ($currentVarTagValueNode !== null) {
// only change type
$currentVarTagValueNode->type = $newPHPStanPhpDocType;
} else {
// add completely new one
$returnTagValueNode = new AttributeAwareVarTagValueNode($newPHPStanPhpDocType, '', '');
$this->addTagValueNode($returnTagValueNode);
}
}
public function changeReturnType(Type $newType): void
{
// make sure the tags are not identical, e.g imported class vs FQN class
@ -315,7 +344,7 @@ final class PhpDocInfo
return;
}
// overide existing type
// override existing type
$newPHPStanPhpDocType = $this->staticTypeMapper->mapPHPStanTypeToPHPStanPhpDocTypeNode($newType);
$currentReturnTagValueNode = $this->getReturnTagValue();
@ -398,6 +427,8 @@ final class PhpDocInfo
{
if ($phpDocTagValueNode instanceof ReturnTagValueNode) {
$name = '@return';
} elseif ($phpDocTagValueNode instanceof VarTagValueNode) {
$name = '@var';
} else {
throw new NotImplementedException();
}

View File

@ -16,7 +16,7 @@ use PhpParser\Node\Identifier;
use PhpParser\Node\Name\FullyQualified;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Property;
use Rector\NodeTypeResolver\PhpDoc\NodeAnalyzer\DocBlockManipulator;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory;
use Rector\PHPStan\Type\FullyQualifiedObjectType;
final class DoctrineNodeFactory
@ -27,14 +27,14 @@ final class DoctrineNodeFactory
private $builderFactory;
/**
* @var DocBlockManipulator
* @var PhpDocInfoFactory
*/
private $docBlockManipulator;
private $phpDocInfoFactory;
public function __construct(BuilderFactory $builderFactory, DocBlockManipulator $docBlockManipulator)
public function __construct(BuilderFactory $builderFactory, PhpDocInfoFactory $phpDocInfoFactory)
{
$this->builderFactory = $builderFactory;
$this->docBlockManipulator = $docBlockManipulator;
$this->phpDocInfoFactory = $phpDocInfoFactory;
}
/**
@ -56,23 +56,22 @@ final class DoctrineNodeFactory
public function createRepositoryProperty(): Property
{
$repositoryProperty = $this->builderFactory->property('repository')
->makePrivate()
->getNode();
$repositoryPropertyBuilder = $this->builderFactory->property('repository');
$repositoryPropertyBuilder->makePrivate();
$this->docBlockManipulator->changeVarTag(
$repositoryProperty,
new FullyQualifiedObjectType('Doctrine\ORM\EntityRepository')
);
$repositoryProperty = $repositoryPropertyBuilder->getNode();
$phpDocInfo = $this->phpDocInfoFactory->createFromNode($repositoryProperty);
$phpDocInfo->changeVarType(new FullyQualifiedObjectType('Doctrine\ORM\EntityRepository'));
return $repositoryProperty;
}
public function createConstructorWithGetRepositoryAssign(string $entityClass): ClassMethod
{
$param = $this->builderFactory->param('entityManager')
->setType(new FullyQualified(EntityManagerInterface::class))
->getNode();
$paramBuilder = $this->builderFactory->param('entityManager');
$paramBuilder->setType(new FullyQualified(EntityManagerInterface::class));
$param = $paramBuilder->getNode();
$assign = $this->createRepositoryAssign($entityClass);

View File

@ -6,13 +6,14 @@ namespace Rector\CakePHPToSymfony\NodeFactory;
use PhpParser\Builder\Property as PropertyBuilder;
use PhpParser\Node\Stmt\Property;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory;
use Rector\BetterPhpDocParser\PhpDocNode\Doctrine\Property_\JoinColumnTagValueNode;
use Rector\BetterPhpDocParser\PhpDocNode\Doctrine\Property_\ManyToManyTagValueNode;
use Rector\BetterPhpDocParser\PhpDocNode\Doctrine\Property_\ManyToOneTagValueNode;
use Rector\BetterPhpDocParser\PhpDocNode\Doctrine\Property_\OneToManyTagValueNode;
use Rector\BetterPhpDocParser\PhpDocNode\Doctrine\Property_\OneToOneTagValueNode;
use Rector\Exception\ShouldNotHappenException;
use Rector\NodeTypeResolver\PhpDoc\NodeAnalyzer\DocBlockManipulator;
use Rector\PhpParser\Node\Value\ValueResolver;
final class RelationPropertyFactory
@ -23,14 +24,14 @@ final class RelationPropertyFactory
private $valueResolver;
/**
* @var DocBlockManipulator
* @var PhpDocInfoFactory
*/
private $docBlockManipulator;
private $phpDocInfoFactory;
public function __construct(ValueResolver $valueResolver, DocBlockManipulator $docBlockManipulator)
public function __construct(ValueResolver $valueResolver, PhpDocInfoFactory $phpDocInfoFactory)
{
$this->valueResolver = $valueResolver;
$this->docBlockManipulator = $docBlockManipulator;
$this->phpDocInfoFactory = $phpDocInfoFactory;
}
/**
@ -48,11 +49,14 @@ final class RelationPropertyFactory
// add @ORM\ManyToOne
$manyToOneTagValueNode = new ManyToOneTagValueNode($className, null, null, null, null, $className);
$this->docBlockManipulator->addTagValueNodeWithShortName($property, $manyToOneTagValueNode);
$phpDocInfo = $this->phpDocInfoFactory->createFromNode($property);
$phpDocInfo->addTagValueNodeWithShortName($manyToOneTagValueNode);
// add @ORM\JoinColumn
$joinColumnTagValueNode = new JoinColumnTagValueNode($manyToOneConfiguration['foreignKey'], null);
$this->docBlockManipulator->addTagValueNodeWithShortName($property, $joinColumnTagValueNode);
$phpDocInfo->addTagValueNodeWithShortName($joinColumnTagValueNode);
$properties[] = $property;
}
@ -75,7 +79,9 @@ final class RelationPropertyFactory
// add @ORM\ManyToOne
$manyToOneTagValueNode = new OneToOneTagValueNode($className);
$this->docBlockManipulator->addTagValueNodeWithShortName($property, $manyToOneTagValueNode);
$phpDocInfo = $this->phpDocInfoFactory->createFromNode($property);
$phpDocInfo->addTagValueNodeWithShortName($manyToOneTagValueNode);
$properties[] = $property;
}
@ -98,7 +104,9 @@ final class RelationPropertyFactory
// add @ORM\ManyToOne
$manyToOneTagValueNode = new ManyToManyTagValueNode($className);
$this->docBlockManipulator->addTagValueNodeWithShortName($property, $manyToOneTagValueNode);
$phpDocInfo = $this->phpDocInfoFactory->createFromNode($property);
$phpDocInfo->addTagValueNodeWithShortName($manyToOneTagValueNode);
$properties[] = $property;
}
@ -121,7 +129,10 @@ final class RelationPropertyFactory
// add @ORM\OneToMany
$manyToOneTagValueNode = new OneToManyTagValueNode(null, $className);
$this->docBlockManipulator->addTagValueNodeWithShortName($property, $manyToOneTagValueNode);
/** @var PhpDocInfo $phpDocInfo */
$phpDocInfo = $this->phpDocInfoFactory->createFromNode($property);
$phpDocInfo->addTagValueNodeWithShortName($manyToOneTagValueNode);
$properties[] = $property;
}

View File

@ -15,6 +15,7 @@ use PhpParser\Node\Stmt\Property;
use PhpParser\NodeTraverser;
use PHPStan\Type\MixedType;
use PHPStan\Type\Type;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\NodeTypeResolver\PHPStan\Type\TypeFactory;
use Rector\Rector\AbstractRector;
@ -211,16 +212,20 @@ PHP
$property = $this->nodeFactory->createPublicProperty($propertyName);
// fallback to doc type in PHP 7.4
/** @var PhpDocInfo $phpDocInfo */
$phpDocInfo = $property->getAttribute(AttributeKey::PHP_DOC_INFO);
if ($this->isAtLeastPhpVersion(PhpVersionFeature::TYPED_PROPERTIES)) {
$phpStanNode = $this->staticTypeMapper->mapPHPStanTypeToPhpParserNode($propertyType);
if ($phpStanNode !== null) {
$property->type = $phpStanNode;
} else {
// fallback to doc type in PHP 7.4
$this->docBlockManipulator->changeVarTag($property, $propertyType);
$phpDocInfo->changeVarType($propertyType);
}
} else {
$this->docBlockManipulator->changeVarTag($property, $propertyType);
$phpDocInfo->changeVarType($propertyType);
}
$newProperties[] = $property;

View File

@ -7,6 +7,8 @@ namespace Rector\CodingStyle\Rector\ClassConst;
use PhpParser\Node;
use PhpParser\Node\Stmt\ClassConst;
use PHPStan\Type\MixedType;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\Rector\AbstractRector;
use Rector\RectorDefinition\CodeSample;
use Rector\RectorDefinition\RectorDefinition;
@ -62,7 +64,9 @@ PHP
return null;
}
$this->docBlockManipulator->changeVarTag($node, $constStaticType);
/** @var PhpDocInfo $phpDocInfo */
$phpDocInfo = $node->getAttribute(AttributeKey::PHP_DOC_INFO);
$phpDocInfo->changeVarType($constStaticType);
return $node;
}

View File

@ -151,11 +151,9 @@ PHP
$this->removeNode($parentNode);
/** @var PhpDocInfo|null $phpDocInfo */
/** @var PhpDocInfo $phpDocInfo */
$phpDocInfo = $classMethod->getAttribute(AttributeKey::PHP_DOC_INFO);
if ($phpDocInfo instanceof PhpDocInfo) {
$phpDocInfo->removeByType(ReturnTagValueNode::class);
}
$phpDocInfo->removeByType(ReturnTagValueNode::class);
// change return typehint
$classMethod->returnType = new FullyQualified(Iterator::class);

View File

@ -58,11 +58,8 @@ final class DoctrineEntityManipulator
public function resolveOtherProperty(Property $property): ?string
{
/** @var PhpDocInfo|null $phpDocInfo */
/** @var PhpDocInfo $phpDocInfo */
$phpDocInfo = $property->getAttribute(AttributeKey::PHP_DOC_INFO);
if ($phpDocInfo === null) {
return null;
}
$relationTagValueNode = $phpDocInfo->getByType(DoctrineRelationTagValueNodeInterface::class);
if ($relationTagValueNode === null) {
@ -105,12 +102,8 @@ final class DoctrineEntityManipulator
public function removeMappedByOrInversedByFromProperty(Property $property): void
{
/** @var PhpDocInfo|null $phpDocInfo */
/** @var PhpDocInfo $phpDocInfo */
$phpDocInfo = $property->getAttribute(AttributeKey::PHP_DOC_INFO);
if ($phpDocInfo === null) {
return;
}
$relationTagValueNode = $phpDocInfo->getByType(DoctrineRelationTagValueNodeInterface::class);
$shouldUpdate = false;

View File

@ -52,7 +52,8 @@ final class AddUuidAnnotationsToIdPropertyRector extends AbstractRector
/** @var PhpDocInfo $phpDocInfo */
$phpDocInfo = $node->getAttribute(AttributeKey::PHP_DOC_INFO);
$this->changeVarToUuidInterface($node);
$uuidObjectType = new FullyQualifiedObjectType(UuidInterface::class);
$phpDocInfo->changeVarType($uuidObjectType);
$phpDocInfo->removeByType(GeneratedValueTagValueNode::class);
$this->changeColumnTypeToUuidBinary($phpDocInfo);
@ -61,13 +62,6 @@ final class AddUuidAnnotationsToIdPropertyRector extends AbstractRector
return $node;
}
private function changeVarToUuidInterface(Property $property): void
{
$uuidObjectType = new FullyQualifiedObjectType(UuidInterface::class);
$this->docBlockManipulator->changeVarTag($property, $uuidObjectType);
}
private function changeColumnTypeToUuidBinary(PhpDocInfo $phpDocInfo): void
{
$columnTagValueNode = $phpDocInfo->getByType(ColumnTagValueNode::class);

View File

@ -9,6 +9,7 @@ use PhpParser\Node\Name\FullyQualified;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\Namespace_;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory;
use Rector\BetterPhpDocParser\PhpDocNode\Gedmo\LocaleTagValueNode;
use Rector\BetterPhpDocParser\PhpDocNode\Gedmo\TranslatableTagValueNode;
use Rector\Doctrine\PhpDocParser\Ast\PhpDoc\PhpDocTagNodeFactory;
@ -40,10 +41,19 @@ final class TranslationBehaviorRector extends AbstractRector
*/
private $phpDocTagNodeFactory;
public function __construct(ClassManipulator $classManipulator, PhpDocTagNodeFactory $phpDocTagNodeFactory)
{
/**
* @var PhpDocInfoFactory
*/
private $phpDocInfoFactory;
public function __construct(
ClassManipulator $classManipulator,
PhpDocTagNodeFactory $phpDocTagNodeFactory,
PhpDocInfoFactory $phpDocInfoFactory
) {
$this->classManipulator = $classManipulator;
$this->phpDocTagNodeFactory = $phpDocTagNodeFactory;
$this->phpDocInfoFactory = $phpDocInfoFactory;
}
public function getDefinition(): RectorDefinition
@ -256,7 +266,11 @@ PHP
$class->implements[] = new FullyQualified('Knp\DoctrineBehaviors\Contract\Entity\TranslationInterface');
$this->classManipulator->addAsFirstTrait($class, 'Knp\DoctrineBehaviors\Model\Translatable\TranslationTrait');
$this->docBlockManipulator->addTag($class, $this->phpDocTagNodeFactory->createEntityTag());
$phpDocInfo = $this->phpDocInfoFactory->createFromNode($class);
$entityTag = $this->phpDocTagNodeFactory->createEntityTag();
$phpDocInfo->addPhpDocTagNode($entityTag);
// $this->docBlockManipulator->addTag($class, $this->phpDocTagNodeFactory->createEntityTag());
foreach ($translatedPropertyToPhpDocInfos as $translatedPropertyName => $translatedPhpDocInfo) {
$property = $this->nodeFactory->createPrivateProperty($translatedPropertyName);

View File

@ -15,13 +15,11 @@ use PhpParser\Node\Identifier;
use PhpParser\Node\Name;
use PhpParser\Node\Name\FullyQualified;
use PhpParser\Node\Stmt\ClassMethod;
use PHPStan\PhpDocParser\Ast\PhpDoc\GenericTagValueNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode;
use PHPStan\Type\BooleanType;
use Prophecy\Doubler\Generator\Node\MethodNode;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\NodeTypeResolver\NodeTypeResolver;
use Rector\NodeTypeResolver\PhpDoc\NodeAnalyzer\DocBlockManipulator;
use Rector\NodeTypeResolver\TypeAnalyzer\StringTypeAnalyzer;
use Rector\PhpParser\Node\Commander\NodeAddingCommander;
use Rector\PhpParser\Node\Commander\NodeRemovingCommander;
@ -76,11 +74,6 @@ final class AssertManipulator
*/
private $nodeRemovingCommander;
/**
* @var DocBlockManipulator
*/
private $docBlockManipulator;
/**
* @var StringTypeAnalyzer
*/
@ -92,7 +85,6 @@ final class AssertManipulator
ValueResolver $valueResolver,
NodeAddingCommander $nodeAddingCommander,
NodeRemovingCommander $nodeRemovingCommander,
DocBlockManipulator $docBlockManipulator,
StringTypeAnalyzer $stringTypeAnalyzer
) {
$this->nameResolver = $nameResolver;
@ -100,7 +92,6 @@ final class AssertManipulator
$this->valueResolver = $valueResolver;
$this->nodeAddingCommander = $nodeAddingCommander;
$this->nodeRemovingCommander = $nodeRemovingCommander;
$this->docBlockManipulator = $docBlockManipulator;
$this->stringTypeAnalyzer = $stringTypeAnalyzer;
}
@ -257,8 +248,9 @@ final class AssertManipulator
return;
}
$phpDocTagNode = new PhpDocTagNode('@doesNotPerformAssertions', new GenericTagValueNode(''));
$this->docBlockManipulator->addTag($methodNode, $phpDocTagNode);
/** @var PhpDocInfo $phpDocInfo */
$phpDocInfo = $methodNode->getAttribute(AttributeKey::PHP_DOC_INFO);
$phpDocInfo->addBareTag('@doesNotPerformAssertions');
}
/**

View File

@ -133,11 +133,8 @@ final class ParamTypeResolver implements PerNodeTypeResolverInterface
/** @var string $paramName */
$paramName = $this->nameResolver->getName($param);
/** @var PhpDocInfo|null $phpDocInfo */
/** @var PhpDocInfo $phpDocInfo */
$phpDocInfo = $parentNode->getAttribute(AttributeKey::PHP_DOC_INFO);
if ($phpDocInfo === null) {
return new MixedType();
}
return $phpDocInfo->getParamType($paramName);
}

View File

@ -12,25 +12,17 @@ use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocChildNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode;
use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
use PHPStan\Type\Constant\ConstantArrayType;
use PHPStan\Type\MixedType;
use PHPStan\Type\NeverType;
use PHPStan\Type\ObjectType;
use PHPStan\Type\Type;
use Rector\AttributeAwarePhpDoc\Ast\PhpDoc\AttributeAwarePhpDocTagNode;
use Rector\AttributeAwarePhpDoc\Ast\PhpDoc\AttributeAwareVarTagValueNode;
use Rector\AttributeAwarePhpDoc\Ast\Type\AttributeAwareIdentifierTypeNode;
use Rector\BetterPhpDocParser\Annotation\AnnotationNaming;
use Rector\BetterPhpDocParser\Ast\PhpDocNodeTraverser;
use Rector\BetterPhpDocParser\Attributes\Ast\AttributeAwareNodeFactory;
use Rector\BetterPhpDocParser\Attributes\Ast\PhpDoc\SpacelessPhpDocTagNode;
use Rector\BetterPhpDocParser\Contract\Doctrine\DoctrineRelationTagValueNodeInterface;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory;
use Rector\BetterPhpDocParser\PhpDocNode\AbstractTagValueNode;
use Rector\BetterPhpDocParser\Printer\PhpDocInfoPrinter;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\NodeTypeResolver\PHPStan\TypeComparator;
use Rector\NodeTypeResolver\StaticTypeMapper;
/**
@ -68,25 +60,13 @@ final class DocBlockManipulator
*/
private $docBlockNameImporter;
/**
* @var PhpDocInfoFactory
*/
private $phpDocInfoFactory;
/**
* @var TypeComparator
*/
private $typeComparator;
public function __construct(
PhpDocInfoPrinter $phpDocInfoPrinter,
AttributeAwareNodeFactory $attributeAwareNodeFactory,
PhpDocNodeTraverser $phpDocNodeTraverser,
StaticTypeMapper $staticTypeMapper,
DocBlockClassRenamer $docBlockClassRenamer,
DocBlockNameImporter $docBlockNameImporter,
PhpDocInfoFactory $phpDocInfoFactory,
TypeComparator $typeComparator
DocBlockNameImporter $docBlockNameImporter
) {
$this->phpDocInfoPrinter = $phpDocInfoPrinter;
$this->attributeAwareNodeFactory = $attributeAwareNodeFactory;
@ -94,8 +74,6 @@ final class DocBlockManipulator
$this->staticTypeMapper = $staticTypeMapper;
$this->docBlockClassRenamer = $docBlockClassRenamer;
$this->docBlockNameImporter = $docBlockNameImporter;
$this->phpDocInfoFactory = $phpDocInfoFactory;
$this->typeComparator = $typeComparator;
}
public function hasTag(Node $node, string $name): bool
@ -121,16 +99,19 @@ final class DocBlockManipulator
return $phpDocInfo->hasByType($name);
}
/**
* @deprecated
* Use
* @see PhpDocInfo::addBareTag()
* @see PhpDocInfo::addPhpDocTagNode()
* @see PhpDocInfo::addTagValueNode()
*/
public function addTag(Node $node, PhpDocChildNode $phpDocChildNode): void
{
$phpDocChildNode = $this->attributeAwareNodeFactory->createFromNode($phpDocChildNode);
/** @var PhpDocInfo|null $phpDocInfo */
/** @var PhpDocInfo $phpDocInfo */
$phpDocInfo = $node->getAttribute(AttributeKey::PHP_DOC_INFO);
if ($phpDocInfo === null) {
$phpDocInfo = $this->phpDocInfoFactory->createFromNode($node);
}
$phpDocInfo->addPhpDocTagNode($phpDocChildNode);
}
@ -154,51 +135,12 @@ final class DocBlockManipulator
public function replaceAnnotationInNode(Node $node, string $oldAnnotation, string $newAnnotation): void
{
/** @var PhpDocInfo|null $phpDocInfo */
/** @var PhpDocInfo $phpDocInfo */
$phpDocInfo = $node->getAttribute(AttributeKey::PHP_DOC_INFO);
if ($phpDocInfo === null) {
return;
}
$this->replaceTagByAnother($phpDocInfo->getPhpDocNode(), $oldAnnotation, $newAnnotation);
}
public function changeVarTag(Node $node, Type $newType): void
{
/** @var PhpDocInfo|null $phpDocInfo */
$phpDocInfo = $node->getAttribute(AttributeKey::PHP_DOC_INFO);
if ($phpDocInfo instanceof PhpDocInfo) {
$currentVarType = $phpDocInfo->getVarType();
} else {
$currentVarType = new MixedType();
}
// make sure the tags are not identical, e.g imported class vs FQN class
if ($this->typeComparator->areTypesEquals($currentVarType, $newType)) {
return;
}
// prevent existing type override by mixed
if (! $currentVarType instanceof MixedType && $newType instanceof ConstantArrayType && $newType->getItemType() instanceof NeverType) {
return;
}
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);
}
// to invoke the node override
$node->setAttribute(AttributeKey::ORIGINAL_NODE, null);
}
public function replaceTagByAnother(PhpDocNode $phpDocNode, string $oldTag, string $newTag): void
{
$oldTag = AnnotationNaming::normalizeName($oldTag);
@ -330,11 +272,8 @@ final class DocBlockManipulator
public function getDoctrineFqnTargetEntity(Node $node): ?string
{
/** @var PhpDocInfo|null $phpDocInfo */
/** @var PhpDocInfo $phpDocInfo */
$phpDocInfo = $node->getAttribute(AttributeKey::PHP_DOC_INFO);
if ($phpDocInfo === null) {
return null;
}
$relationTagValueNode = $phpDocInfo->getByType(DoctrineRelationTagValueNodeInterface::class);
if ($relationTagValueNode === null) {
@ -344,38 +283,6 @@ final class DocBlockManipulator
return $relationTagValueNode->getFqnTargetEntity();
}
/**
* All class-type tags are FQN by default to keep default convention through the code.
* Some people prefer FQN, some short. FQN can be shorten with \Rector\CodingStyle\Rector\Namespace_\ImportFullyQualifiedNamesRector later, while short prolonged not
*/
private function addTypeSpecificTag(Node $node, string $name, Type $type): void
{
$docStringType = $this->staticTypeMapper->mapPHPStanTypeToDocString($type);
if ($docStringType === '') {
return;
}
/** @var PhpDocInfo|null $phpDocInfo */
$phpDocInfo = $node->getAttribute(AttributeKey::PHP_DOC_INFO);
// there might be no phpdoc at all
if ($phpDocInfo !== null) {
$varTagValueNode = new AttributeAwareVarTagValueNode(new AttributeAwareIdentifierTypeNode(
$docStringType
), '', '');
$varTagValueNode = new AttributeAwarePhpDocTagNode('@' . $name, $varTagValueNode);
$phpDocInfo->addPhpDocTagNode($varTagValueNode);
} else {
// 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);
}
}
private function printPhpDocInfoToString(PhpDocInfo $phpDocInfo): string
{
// new node, needs to be reparsed

View File

@ -74,11 +74,8 @@ PHP
return null;
}
/** @var PhpDocInfo|null $phpDocInfo */
/** @var PhpDocInfo $phpDocInfo */
$phpDocInfo = $node->getAttribute(AttributeKey::PHP_DOC_INFO);
if ($phpDocInfo === null) {
return null;
}
$varTagValue = $phpDocInfo->getVarTagValue();
if ($varTagValue === null) {

View File

@ -6,15 +6,30 @@ namespace Rector\PHPStanStaticTypeMapper\TypeMapper;
use PhpParser\Node;
use PhpParser\Node\Identifier;
use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
use PHPStan\Type\CallableType;
use PHPStan\Type\Type;
use PHPStan\Type\VerbosityLevel;
use Rector\Exception\NotImplementedException;
use Rector\AttributeAwarePhpDoc\Ast\Type\AttributeAwareCallableTypeNode;
use Rector\PHPStanStaticTypeMapper\Contract\TypeMapperInterface;
use Rector\PHPStanStaticTypeMapper\PHPStanStaticTypeMapper;
final class CallableTypeMapper implements TypeMapperInterface
{
/**
* @var PHPStanStaticTypeMapper
*/
private $phpStanStaticTypeMapper;
/**
* @required
*/
public function autowireIterableTypeMapper(PHPStanStaticTypeMapper $phpStanStaticTypeMapper): void
{
$this->phpStanStaticTypeMapper = $phpStanStaticTypeMapper;
}
public function getNodeClass(): string
{
return CallableType::class;
@ -25,7 +40,9 @@ final class CallableTypeMapper implements TypeMapperInterface
*/
public function mapToPHPStanPhpDocTypeNode(Type $type): TypeNode
{
throw new NotImplementedException();
$returnTypeNode = $this->phpStanStaticTypeMapper->mapToPHPStanPhpDocTypeNode($type->getReturnType());
return new AttributeAwareCallableTypeNode(new IdentifierTypeNode('callable'), [], $returnTypeNode);
}
/**

View File

@ -33,6 +33,14 @@ final class ObjectTypeMapper implements TypeMapperInterface
*/
public function mapToPHPStanPhpDocTypeNode(Type $type): TypeNode
{
if ($type instanceof ShortenedObjectType) {
return new IdentifierTypeNode($type->getClassName());
}
if ($type instanceof AliasedObjectType) {
return new IdentifierTypeNode($type->getClassName());
}
return new IdentifierTypeNode('\\' . $type->getClassName());
}

View File

@ -71,11 +71,8 @@ PHP
return null;
}
/** @var PhpDocInfo|null $phpDocInfo */
/** @var PhpDocInfo $phpDocInfo */
$phpDocInfo = $node->getAttribute(AttributeKey::PHP_DOC_INFO);
if ($phpDocInfo === null) {
return null;
}
$phpDocNode = $phpDocInfo->getPhpDocNode();
foreach ($phpDocNode->children as $phpDocChildNode) {

View File

@ -99,11 +99,8 @@ PHP
private function renameDataProviderAnnotationsAndCollectRenamedMethods(Class_ $class): void
{
foreach ($class->getMethods() as $classMethod) {
/** @var PhpDocInfo|null $phpDocInfo */
/** @var PhpDocInfo $phpDocInfo */
$phpDocInfo = $classMethod->getAttribute(AttributeKey::PHP_DOC_INFO);
if ($phpDocInfo === null) {
continue;
}
$dataProviderTags = $phpDocInfo->getTagsByName('dataProvider');
if ($dataProviderTags === []) {

View File

@ -7,10 +7,7 @@ namespace Rector\PHPUnit\Rector\Class_;
use PhpParser\Node;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\Property;
use PHPStan\PhpDocParser\Ast\PhpDoc\GenericTagValueNode;
use Rector\AttributeAwarePhpDoc\Ast\PhpDoc\AttributeAwarePhpDocTagNode;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
use Rector\Exception\ShouldNotHappenException;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\PhpParser\Node\Manipulator\ClassManipulator;
use Rector\PHPUnit\Manipulator\OnContainerGetCallManipulator;
@ -153,15 +150,9 @@ PHP
private function addInjectAnnotationToProperty(Property $privateProperty): void
{
/** @var PhpDocInfo|null $phpDocInfo */
/** @var PhpDocInfo $phpDocInfo */
$phpDocInfo = $privateProperty->getAttribute(AttributeKey::PHP_DOC_INFO);
if ($phpDocInfo === null) {
throw new ShouldNotHappenException();
}
$injectTag = new AttributeAwarePhpDocTagNode('@inject', new GenericTagValueNode(''));
$phpDocInfo->addPhpDocTagNode($injectTag);
$phpDocInfo->addBareTag('@inject');
}
/**

View File

@ -83,11 +83,8 @@ PHP
return null;
}
/** @var PhpDocInfo|null $phpDocInfo */
/** @var PhpDocInfo $phpDocInfo */
$phpDocInfo = $node->getAttribute(AttributeKey::PHP_DOC_INFO);
if ($phpDocInfo === null) {
return null;
}
foreach ($this->annotationToMethod as $annotation => $method) {
if (! $phpDocInfo->hasByName($annotation)) {

View File

@ -15,7 +15,9 @@ use PhpParser\Node\Param;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassMethod;
use PHPStan\Type\ObjectType;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
use Rector\Naming\PropertyNaming;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\Rector\AbstractRector;
use Rector\RectorDefinition\ConfiguredCodeSample;
use Rector\RectorDefinition\RectorDefinition;
@ -154,7 +156,10 @@ PHP
$setEntityFactoryMethod = $this->createSetEntityFactoryClassMethod($variableName, $param, $assign);
$entityFactoryProperty = $this->nodeFactory->createPrivateProperty($variableName);
$this->docBlockManipulator->changeVarTag($entityFactoryProperty, $objectType);
/** @var PhpDocInfo $phpDocInfo */
$phpDocInfo = $entityFactoryProperty->getAttribute(AttributeKey::PHP_DOC_INFO);
$phpDocInfo->changeVarType($objectType);
$class->stmts = array_merge([$entityFactoryProperty, $setEntityFactoryMethod], $class->stmts);

View File

@ -18,9 +18,10 @@ use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Property;
use PhpParser\Node\Stmt\Return_;
use PHPStan\Type\ObjectType;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
use Rector\Exception\ShouldNotHappenException;
use Rector\Naming\PropertyNaming;
use Rector\NodeTypeResolver\PhpDoc\NodeAnalyzer\DocBlockManipulator;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\NodeTypeResolver\StaticTypeMapper;
use Rector\PhpParser\Node\NodeFactory;
use Rector\PhpParser\Node\Resolver\NameResolver;
@ -42,11 +43,6 @@ final class UniqueObjectFactoryFactory
*/
private $propertyNaming;
/**
* @var DocBlockManipulator
*/
private $docBlockManipulator;
/**
* @var StaticTypeMapper
*/
@ -61,14 +57,12 @@ final class UniqueObjectFactoryFactory
NameResolver $nameResolver,
BuilderFactory $builderFactory,
PropertyNaming $propertyNaming,
DocBlockManipulator $docBlockManipulator,
StaticTypeMapper $staticTypeMapper,
NodeFactory $nodeFactory
) {
$this->nameResolver = $nameResolver;
$this->builderFactory = $builderFactory;
$this->propertyNaming = $propertyNaming;
$this->docBlockManipulator = $docBlockManipulator;
$this->staticTypeMapper = $staticTypeMapper;
$this->nodeFactory = $nodeFactory;
}
@ -120,7 +114,10 @@ final class UniqueObjectFactoryFactory
$propertyName = $this->propertyNaming->fqnToVariableName($objectType);
$property = $this->nodeFactory->createPrivateProperty($propertyName);
$this->docBlockManipulator->changeVarTag($property, $objectType);
/** @var PhpDocInfo $phpDocInfo */
$phpDocInfo = $property->getAttribute(AttributeKey::PHP_DOC_INFO);
$phpDocInfo->changeVarType($objectType);
$properties[] = $property;

View File

@ -18,7 +18,6 @@ use PhpParser\Node\Stmt\Property;
use PhpParser\Node\Stmt\Use_;
use PhpParser\Node\Stmt\UseUse;
use PHPStan\Type\ObjectType;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
use Rector\CodingStyle\Naming\ClassNaming;
use Rector\NodeTypeResolver\ClassExistenceStaticHelper;
use Rector\NodeTypeResolver\Node\AttributeKey;
@ -150,12 +149,6 @@ PHP
*/
private function refactorPhpDoc(Node $node): void
{
/** @var PhpDocInfo|null $phpDocInfo */
$phpDocInfo = $node->getAttribute(AttributeKey::PHP_DOC_INFO);
if ($phpDocInfo === null) {
return;
}
if (! $this->docBlockManipulator->hasNodeTypeTags($node)) {
return;
}

View File

@ -114,11 +114,9 @@ PHP
$this->updateReturnType($classMethod);
$this->refactorClassMethod($classMethod, $sensioTemplateTagValueNode);
/** @var PhpDocInfo|null $phpDocInfo */
/** @var PhpDocInfo $phpDocInfo */
$phpDocInfo = $classMethod->getAttribute(AttributeKey::PHP_DOC_INFO);
if ($phpDocInfo instanceof PhpDocInfo) {
$phpDocInfo->removeByType(SensioTemplateTagValueNode::class);
}
$phpDocInfo->removeByType(SensioTemplateTagValueNode::class);
return $classMethod;
}

View File

@ -105,11 +105,8 @@ PHP
return null;
}
/** @var PhpDocInfo|null $phpDocInfo */
/** @var PhpDocInfo $phpDocInfo */
$phpDocInfo = $node->getAttribute(AttributeKey::PHP_DOC_INFO);
if ($phpDocInfo === null) {
return null;
}
$paramWithTypes = $phpDocInfo->getParamTypesByName();
// no tags, nothing to complete here

View File

@ -7,6 +7,8 @@ namespace Rector\TypeDeclaration\Rector\Property;
use PhpParser\Node;
use PhpParser\Node\Stmt\Property;
use PHPStan\Type\MixedType;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\Rector\AbstractRector;
use Rector\RectorDefinition\CodeSample;
use Rector\RectorDefinition\RectorDefinition;
@ -79,7 +81,9 @@ PHP
return null;
}
$this->docBlockManipulator->changeVarTag($node, $propertyType);
/** @var PhpDocInfo $phpDocInfo */
$phpDocInfo = $node->getAttribute(AttributeKey::PHP_DOC_INFO);
$phpDocInfo->changeVarType($propertyType);
return $node;
}

View File

@ -53,15 +53,9 @@ final class PropertyTypeDeclarationRector extends AbstractRector
}
// is already set
/** @var PhpDocInfo|null $phpDocInfo */
/** @var PhpDocInfo $phpDocInfo */
$phpDocInfo = $node->getAttribute(AttributeKey::PHP_DOC_INFO);
if ($phpDocInfo instanceof PhpDocInfo) {
$currentVarType = $phpDocInfo->getVarType();
} else {
$currentVarType = new MixedType();
}
if (! $currentVarType instanceof MixedType) {
if (! $phpDocInfo->getVarType() instanceof MixedType) {
return null;
}
@ -70,7 +64,7 @@ final class PropertyTypeDeclarationRector extends AbstractRector
return null;
}
$this->docBlockManipulator->changeVarTag($node, $type);
$phpDocInfo->changeVarType($type);
return $node;
}

View File

@ -72,11 +72,8 @@ final class GetterNodeParamTypeInferer extends AbstractTypeInferer implements Pa
return null;
}
/** @var PhpDocInfo|null $phpDocInfo */
/** @var PhpDocInfo $phpDocInfo */
$phpDocInfo = $methodNode->getAttribute(AttributeKey::PHP_DOC_INFO);
if ($phpDocInfo === null) {
return null;
}
$methodReturnType = $phpDocInfo->getReturnType();
if ($methodReturnType instanceof MixedType) {

View File

@ -79,11 +79,8 @@ final class DoctrineColumnPropertyTypeInferer implements PropertyTypeInfererInte
public function inferProperty(Property $property): Type
{
/** @var PhpDocInfo|null $phpDocInfo */
/** @var PhpDocInfo $phpDocInfo */
$phpDocInfo = $property->getAttribute(AttributeKey::PHP_DOC_INFO);
if ($phpDocInfo === null) {
return new MixedType();
}
$doctrineColumnTagValueNode = $phpDocInfo->getByType(ColumnTagValueNode::class);
if ($doctrineColumnTagValueNode === null) {

View File

@ -38,11 +38,8 @@ final class DoctrineRelationPropertyTypeInferer implements PropertyTypeInfererIn
public function inferProperty(Property $property): Type
{
/** @var PhpDocInfo|null $phpDocInfo */
/** @var PhpDocInfo $phpDocInfo */
$phpDocInfo = $property->getAttribute(AttributeKey::PHP_DOC_INFO);
if ($phpDocInfo === null) {
return new MixedType();
}
$relationTagValueNode = $phpDocInfo->getByType(DoctrineRelationTagValueNodeInterface::class);
if ($relationTagValueNode === null) {

View File

@ -5,7 +5,6 @@ declare(strict_types=1);
namespace Rector\TypeDeclaration\TypeInferer\PropertyTypeInferer;
use PhpParser\Node\Stmt\Property;
use PHPStan\Type\MixedType;
use PHPStan\Type\Type;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
use Rector\NodeTypeResolver\Node\AttributeKey;
@ -15,10 +14,10 @@ final class VarDocPropertyTypeInferer implements PropertyTypeInfererInterface
{
public function inferProperty(Property $property): Type
{
/** @var PhpDocInfo|null $phpDocInfo */
/** @var PhpDocInfo $phpDocInfo */
$phpDocInfo = $property->getAttribute(AttributeKey::PHP_DOC_INFO);
return $phpDocInfo !== null ? $phpDocInfo->getVarType() : new MixedType();
return $phpDocInfo->getVarType();
}
public function getPriority(): int

View File

@ -8,7 +8,6 @@ use PhpParser\Node\Expr\Closure;
use PhpParser\Node\FunctionLike;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Function_;
use PHPStan\Type\MixedType;
use PHPStan\Type\Type;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
use Rector\NodeTypeResolver\Node\AttributeKey;
@ -22,11 +21,8 @@ final class ReturnTagReturnTypeInferer extends AbstractTypeInferer implements Re
*/
public function inferFunctionLike(FunctionLike $functionLike): Type
{
/** @var PhpDocInfo|null $phpDocInfo */
/** @var PhpDocInfo $phpDocInfo */
$phpDocInfo = $functionLike->getAttribute(AttributeKey::PHP_DOC_INFO);
if ($phpDocInfo === null) {
return new MixedType();
}
return $phpDocInfo->getReturnType();
}

View File

@ -583,7 +583,7 @@ class Command
*/
protected static $defaultName;
/**
* @var \Symfony\Component\Console\Application
* @var Application
*/
private $application;
/**
@ -627,7 +627,7 @@ class Command
*/
private $code;
/**
* @var \Symfony\Component\Console\Helper\HelperSet
* @var HelperSet
*/
private $helperSet;
/**

View File

@ -45,7 +45,7 @@ use Symfony\Component\Console\Helper\HelperSet;
class SymfonyConsoleHelperSet
{
/**
* @var \Symfony\Component\Console\Helper\HelperSet
* @var HelperSet
*/
private $helperSet;

View File

@ -34,7 +34,7 @@ class ConstructorParam
*/
private $stringValue;
/**
* @var \stdClass
* @var stdClass
*/
private $docBlockService;

View File

@ -21,11 +21,8 @@ final class PhpDocClassRenamer
*/
public function changeTypeInAnnotationTypes(Node $node, array $oldToNewClasses): void
{
/** @var PhpDocInfo|null $phpDocInfo */
/** @var PhpDocInfo $phpDocInfo */
$phpDocInfo = $node->getAttribute(AttributeKey::PHP_DOC_INFO);
if ($phpDocInfo === null) {
return;
}
$this->processAssertChoiceTagValueNode($oldToNewClasses, $phpDocInfo);
$this->processDoctrineRelationTagValueNode($oldToNewClasses, $phpDocInfo);

View File

@ -263,9 +263,10 @@ final class NodeFactory
$propertyBuilder->makePrivate();
$property = $propertyBuilder->getNode();
$this->decorateParentPropertyProperty($property);
$this->phpDocInfoFactory->createFromNode($property);
return $property;
}
@ -275,9 +276,10 @@ final class NodeFactory
$propertyBuilder->makePublic();
$property = $propertyBuilder->getNode();
$this->decorateParentPropertyProperty($property);
$this->phpDocInfoFactory->createFromNode($property);
return $property;
}

View File

@ -92,11 +92,8 @@ PHP
private function shouldSkipProperty(Node $node): bool
{
/** @var PhpDocInfo|null $phpDocInfo */
/** @var PhpDocInfo $phpDocInfo */
$phpDocInfo = $node->getAttribute(AttributeKey::PHP_DOC_INFO);
if ($phpDocInfo === null) {
return true;
}
if (! $phpDocInfo->hasByName(self::INJECT_ANNOTATION)) {
return true;

View File

@ -102,11 +102,9 @@ PHP
throw new ShouldNotHappenException();
}
/** @var PhpDocInfo|null $phpDocInfo */
/** @var PhpDocInfo $phpDocInfo */
$phpDocInfo = $methodNode->getAttribute(AttributeKey::PHP_DOC_INFO);
if ($phpDocInfo instanceof PhpDocInfo) {
$phpDocInfo->removeByType(ReturnTagValueNode::class);
}
$phpDocInfo->removeByType(ReturnTagValueNode::class);
return null;
}

View File

@ -207,12 +207,10 @@ PHP
return null;
}
$this->docBlockManipulator->changeVarTag($property, $type);
/** @var PhpDocInfo $phpDocInfo */
$phpDocInfo = $property->getAttribute(AttributeKey::PHP_DOC_INFO);
if ($phpDocInfo instanceof PhpDocInfo) {
$phpDocInfo->removeByType($tagClass);
}
$phpDocInfo->changeVarType($type);
$phpDocInfo->removeByType($tagClass);
$classNode = $property->getAttribute(AttributeKey::CLASS_NODE);
if (! $classNode instanceof Class_) {

View File

@ -31,6 +31,7 @@ class SomeController
* @var \Rector\Symfony\Tests\Rector\FrameworkBundle\AbstractToConstructorInjectionRectorSource\SomeEntityManager
*/
private $entityManager;
/**
* @var \Rector\Symfony\Tests\Rector\FrameworkBundle\AbstractToConstructorInjectionRectorSource\SomeTranslatorInterface
*/