mirror of
https://github.com/rectorphp/rector.git
synced 2025-01-17 21:38:22 +01:00
[PHP 8.0] Make Attribute silent keys explicit, with named args (#4834)
* decouple TagName class * remove attribute aware from data provider tag value node, as unique class * add RequiredTagValueNode * make Attributes explicit, to avoid confusiong
This commit is contained in:
parent
5e609f50fb
commit
eac130e705
@ -8,7 +8,7 @@ use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagValueNode;
|
||||
use Rector\BetterPhpDocParser\Attributes\Attribute\AttributeTrait;
|
||||
use Rector\BetterPhpDocParser\Contract\PhpDocNode\AttributeAwareNodeInterface;
|
||||
|
||||
final class AttributeAwareDataProviderTagValueNode implements PhpDocTagValueNode, AttributeAwareNodeInterface
|
||||
final class DataProviderTagValueNode implements PhpDocTagValueNode, AttributeAwareNodeInterface
|
||||
{
|
||||
use AttributeTrait;
|
||||
|
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\AttributeAwarePhpDoc\Ast\PhpDoc;
|
||||
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagValueNode;
|
||||
use Rector\BetterPhpDocParser\Attributes\Attribute\AttributeTrait;
|
||||
use Rector\BetterPhpDocParser\Contract\PhpDocNode\AttributeAwareNodeInterface;
|
||||
use Rector\PhpAttribute\Contract\PhpAttributableTagNodeInterface;
|
||||
|
||||
final class RequiredTagValueNode implements PhpDocTagValueNode, AttributeAwareNodeInterface, PhpAttributableTagNodeInterface
|
||||
{
|
||||
use AttributeTrait;
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function getShortName(): string
|
||||
{
|
||||
return 'Required';
|
||||
}
|
||||
|
||||
public function getAttributeClassName(): string
|
||||
{
|
||||
return 'Symfony\Contracts\Service\Attribute\Required';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed[]
|
||||
*/
|
||||
public function getAttributableItems(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
@ -9,7 +9,7 @@ use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagValueNode;
|
||||
use PHPStan\PhpDocParser\Parser\ParserException;
|
||||
use PHPStan\PhpDocParser\Parser\PhpDocParser;
|
||||
use PHPStan\PhpDocParser\Parser\TokenIterator;
|
||||
use Rector\AttributeAwarePhpDoc\Ast\PhpDoc\AttributeAwareDataProviderTagValueNode;
|
||||
use Rector\AttributeAwarePhpDoc\Ast\PhpDoc\DataProviderTagValueNode;
|
||||
use Symplify\PackageBuilder\Reflection\PrivatesCaller;
|
||||
|
||||
final class PHPUnitDataProviderDocNodeFactory
|
||||
@ -57,7 +57,7 @@ final class PHPUnitDataProviderDocNodeFactory
|
||||
/**
|
||||
* Override of parent private method to allow reference: https://github.com/rectorphp/rector/pull/1735
|
||||
*/
|
||||
private function parseDataProviderTagValue(TokenIterator $tokenIterator): AttributeAwareDataProviderTagValueNode
|
||||
private function parseDataProviderTagValue(TokenIterator $tokenIterator): DataProviderTagValueNode
|
||||
{
|
||||
$method = $this->privatesCaller->callPrivateMethod(
|
||||
$this->phpDocParser,
|
||||
@ -65,6 +65,6 @@ final class PHPUnitDataProviderDocNodeFactory
|
||||
$tokenIterator
|
||||
);
|
||||
|
||||
return new AttributeAwareDataProviderTagValueNode($method);
|
||||
return new DataProviderTagValueNode($method);
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ use PHPStan\PhpDocParser\Parser\PhpDocParser;
|
||||
use PHPStan\PhpDocParser\Parser\TokenIterator;
|
||||
use PHPStan\PhpDocParser\Parser\TypeParser;
|
||||
use Rector\AttributeAwarePhpDoc\Ast\PhpDoc\AttributeAwarePhpDocNode;
|
||||
use Rector\AttributeAwarePhpDoc\Ast\PhpDoc\RequiredTagValueNode;
|
||||
use Rector\BetterPhpDocParser\Attributes\Ast\AttributeAwareNodeFactory;
|
||||
use Rector\BetterPhpDocParser\Attributes\Attribute\Attribute;
|
||||
use Rector\BetterPhpDocParser\Contract\GenericPhpDocNodeFactoryInterface;
|
||||
@ -26,6 +27,7 @@ use Rector\BetterPhpDocParser\Printer\MultilineSpaceFormatPreserver;
|
||||
use Rector\BetterPhpDocParser\ValueObject\StartAndEnd;
|
||||
use Rector\Core\Configuration\CurrentNodeProvider;
|
||||
use Rector\Core\Exception\ShouldNotHappenException;
|
||||
use Rector\PhpAttribute\ValueObject\TagName;
|
||||
use Symplify\PackageBuilder\Reflection\PrivatesAccessor;
|
||||
use Symplify\PackageBuilder\Reflection\PrivatesCaller;
|
||||
|
||||
@ -186,13 +188,16 @@ final class BetterPhpDocParser extends PhpDocParser
|
||||
throw new ShouldNotHappenException();
|
||||
}
|
||||
|
||||
if (strtolower($tag) === '@param') {
|
||||
$lowercasedTag = strtolower($tag);
|
||||
if ($lowercasedTag === '@param') {
|
||||
// to prevent circular reference of this service
|
||||
$this->paramPhpDocNodeFactory->setPhpDocParser($this);
|
||||
$tagValueNode = $this->paramPhpDocNodeFactory->createFromTokens($tokenIterator);
|
||||
} elseif (strtolower($tag) === '@dataprovider') {
|
||||
} elseif ($lowercasedTag === '@dataprovider') {
|
||||
$this->phpUnitDataProviderDocNodeFactory->setPhpDocParser($this);
|
||||
$tagValueNode = $this->phpUnitDataProviderDocNodeFactory->createFromTokens($tokenIterator);
|
||||
} elseif ($lowercasedTag === '@' . TagName::REQUIRED) {
|
||||
$tagValueNode = new RequiredTagValueNode();
|
||||
} else {
|
||||
// class-annotation
|
||||
$phpDocNodeFactory = $this->matchTagToPhpDocNodeFactory($tag);
|
||||
|
@ -13,5 +13,5 @@ return static function (ContainerConfigurator $containerConfigurator): void {
|
||||
->autoconfigure();
|
||||
|
||||
$services->load('Rector\PhpAttribute\\', __DIR__ . '/../src')
|
||||
->exclude([__DIR__ . '/../src/Contract']);
|
||||
->exclude([__DIR__ . '/../src/Contract', __DIR__ . '/../src/ValueObject']);
|
||||
};
|
||||
|
@ -6,10 +6,8 @@ namespace Rector\PhpAttribute;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Attribute;
|
||||
use PhpParser\Node\AttributeGroup;
|
||||
use PhpParser\Node\Expr\ArrowFunction;
|
||||
use PhpParser\Node\Expr\Closure;
|
||||
use PhpParser\Node\Name\FullyQualified;
|
||||
use PhpParser\Node\Stmt\Class_;
|
||||
use PhpParser\Node\Stmt\ClassMethod;
|
||||
use PhpParser\Node\Stmt\Function_;
|
||||
@ -44,15 +42,7 @@ final class AnnotationToAttributeConverter
|
||||
return null;
|
||||
}
|
||||
|
||||
// special cases without tag value node
|
||||
$hasNewAttrGroups = false;
|
||||
if ($phpDocInfo->hasByName('required')) {
|
||||
$phpDocInfo->removeByName('required');
|
||||
$node->attrGroups[] = new AttributeGroup([
|
||||
new Attribute(new FullyQualified('Symfony\Contracts\Service\Attribute\Required')),
|
||||
]);
|
||||
$hasNewAttrGroups = true;
|
||||
}
|
||||
|
||||
// 0. has 0 nodes, nothing to change
|
||||
/** @var PhpAttributableTagNodeInterface[] $phpAttributableTagNodes */
|
||||
|
@ -11,7 +11,6 @@ use PhpParser\Node\AttributeGroup;
|
||||
use PhpParser\Node\Identifier;
|
||||
use PhpParser\Node\Name;
|
||||
use PhpParser\Node\Name\FullyQualified;
|
||||
use Rector\BetterPhpDocParser\Contract\PhpDocNode\SilentKeyNodeInterface;
|
||||
use Rector\PhpAttribute\Contract\ManyPhpAttributableTagNodeInterface;
|
||||
use Rector\PhpAttribute\Contract\PhpAttributableTagNodeInterface;
|
||||
|
||||
@ -43,13 +42,7 @@ final class PhpAttributteGroupFactory
|
||||
public function printItemsToAttributeArgs(PhpAttributableTagNodeInterface $phpAttributableTagNode): array
|
||||
{
|
||||
$items = $phpAttributableTagNode->getAttributableItems();
|
||||
|
||||
$silentKey = null;
|
||||
if ($phpAttributableTagNode instanceof SilentKeyNodeInterface) {
|
||||
$silentKey = $phpAttributableTagNode->getSilentKey();
|
||||
}
|
||||
|
||||
return $this->createArgsFromItems($items, $silentKey);
|
||||
return $this->createArgsFromItems($items);
|
||||
}
|
||||
|
||||
/**
|
||||
|
15
packages/php-attribute/src/ValueObject/TagName.php
Normal file
15
packages/php-attribute/src/ValueObject/TagName.php
Normal file
@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\PhpAttribute\ValueObject;
|
||||
|
||||
final class TagName
|
||||
{
|
||||
/**
|
||||
* Use by Symfony to autowire dependencies outside constructor,
|
||||
* @see https://symfony.com/doc/current/service_container/autowiring.html#autowiring-other-methods-e-g-setters-and-public-typed-properties
|
||||
* @var string
|
||||
*/
|
||||
public const REQUIRED = 'required';
|
||||
}
|
@ -637,7 +637,7 @@ parameters:
|
||||
-
|
||||
message: '#Do not use scalar or array as constructor parameter\. Use "Symplify\\PackageBuilder\\Parameter\\ParameterProvider" service instead#'
|
||||
paths:
|
||||
- packages/attribute-aware-php-doc/src/Ast/PhpDoc/AttributeAwareDataProviderTagValueNode.php # 22
|
||||
- packages/attribute-aware-php-doc/src/Ast/PhpDoc/DataProviderTagValueNode.php # 22
|
||||
- packages/attribute-aware-php-doc/src/Ast/PhpDoc/AttributeAwareParamTagValueNode.php # 33
|
||||
- packages/attribute-aware-php-doc/src/Ast/PhpDoc/AttributeAwareParamTagValueNode.php # 33
|
||||
- packages/attribute-aware-php-doc/src/Ast/PhpDoc/AttributeAwareParamTagValueNode.php # 33
|
||||
|
@ -16,6 +16,7 @@ use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
use Rector\DeadCode\Comparator\CurrentAndParentClassMethodComparator;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
use Rector\PhpAttribute\ValueObject\TagName;
|
||||
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
|
||||
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
|
||||
|
||||
@ -164,6 +165,6 @@ CODE_SAMPLE
|
||||
return false;
|
||||
}
|
||||
|
||||
return $phpDocInfo->hasByName('required');
|
||||
return $phpDocInfo->hasByName(TagName::REQUIRED);
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
class SymfonyRoute
|
||||
{
|
||||
#[\Symfony\Component\Routing\Annotation\Route('/path', name: 'action')]
|
||||
#[\Symfony\Component\Routing\Annotation\Route(path: '/path', name: 'action')]
|
||||
public function action()
|
||||
{
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
class SymfonyRoute
|
||||
{
|
||||
#[Route('/path', name: 'action')]
|
||||
#[Route(path: '/path', name: 'action')]
|
||||
public function action()
|
||||
{
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ use Nette\Utils\Strings;
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Identifier;
|
||||
use PhpParser\Node\Stmt\Class_;
|
||||
use Rector\AttributeAwarePhpDoc\Ast\PhpDoc\AttributeAwareDataProviderTagValueNode;
|
||||
use Rector\AttributeAwarePhpDoc\Ast\PhpDoc\DataProviderTagValueNode;
|
||||
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
|
||||
use Rector\Core\Rector\AbstractPHPUnitRector;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
@ -107,8 +107,8 @@ CODE_SAMPLE
|
||||
continue;
|
||||
}
|
||||
|
||||
/** @var AttributeAwareDataProviderTagValueNode[] $dataProviderTagValueNodes */
|
||||
$dataProviderTagValueNodes = $phpDocInfo->findAllByType(AttributeAwareDataProviderTagValueNode::class);
|
||||
/** @var DataProviderTagValueNode[] $dataProviderTagValueNodes */
|
||||
$dataProviderTagValueNodes = $phpDocInfo->findAllByType(DataProviderTagValueNode::class);
|
||||
if ($dataProviderTagValueNodes === []) {
|
||||
continue;
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
|
||||
use Rector\Caching\Contract\Rector\ZeroCacheRectorInterface;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
use Rector\PhpAttribute\ValueObject\TagName;
|
||||
use Rector\Privatization\NodeAnalyzer\ClassMethodExternalCallNodeAnalyzer;
|
||||
use Rector\VendorLocker\NodeVendorLocker\ClassMethodVisibilityVendorLockResolver;
|
||||
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
|
||||
@ -161,7 +162,7 @@ CODE_SAMPLE
|
||||
return false;
|
||||
}
|
||||
|
||||
return $phpDocInfo->hasByNames(['api', 'required']);
|
||||
return $phpDocInfo->hasByNames(['api', TagName::REQUIRED]);
|
||||
}
|
||||
|
||||
private function isControllerAction(Class_ $class, ClassMethod $classMethod): bool
|
||||
|
@ -11,6 +11,7 @@ use PhpParser\Node\Stmt\Property;
|
||||
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
use Rector\PhpAttribute\ValueObject\TagName;
|
||||
use Rector\VendorLocker\NodeVendorLocker\PropertyVisibilityVendorLockResolver;
|
||||
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
|
||||
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
|
||||
@ -26,7 +27,7 @@ final class PrivatizeLocalPropertyToPrivatePropertyRector extends AbstractRector
|
||||
private const ANNOTATIONS_REQUIRING_PUBLIC = [
|
||||
'api',
|
||||
// Symfony DI
|
||||
'required',
|
||||
TagName::REQUIRED,
|
||||
// other DI
|
||||
'inject',
|
||||
];
|
||||
|
@ -14,6 +14,7 @@ use Rector\Core\PhpParser\Builder\ParamBuilder;
|
||||
use Rector\Core\PhpParser\Node\NodeFactory;
|
||||
use Rector\Naming\Naming\PropertyNaming;
|
||||
use Rector\NodeTypeResolver\PHPStan\Type\TypeFactory;
|
||||
use Rector\PhpAttribute\ValueObject\TagName;
|
||||
use Rector\SOLID\Rector\Class_\MultiParentingToAbstractDependencyRector;
|
||||
|
||||
final class InjectMethodFactory
|
||||
@ -86,7 +87,7 @@ final class InjectMethodFactory
|
||||
|
||||
if ($framework === MultiParentingToAbstractDependencyRector::FRAMEWORK_SYMFONY) {
|
||||
$phpDocInfo = $this->phpDocInfoFactory->createEmpty($classMethod);
|
||||
$phpDocInfo->addBareTag('required');
|
||||
$phpDocInfo->addBareTag(TagName::REQUIRED);
|
||||
}
|
||||
|
||||
return $classMethod;
|
||||
|
@ -9,6 +9,7 @@ use PhpParser\Node\Identifier;
|
||||
use PhpParser\Node\Stmt\ClassMethod;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
use Rector\PhpAttribute\ValueObject\TagName;
|
||||
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
|
||||
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
|
||||
|
||||
@ -17,11 +18,6 @@ use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
|
||||
*/
|
||||
final class AutoWireWithClassNameSuffixForMethodWithRequiredAnnotationRector extends AbstractRector
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private const REQUIRED_TAG = 'required';
|
||||
|
||||
public function getRuleDefinition(): RuleDefinition
|
||||
{
|
||||
return new RuleDefinition(
|
||||
@ -65,7 +61,7 @@ CODE_SAMPLE
|
||||
*/
|
||||
public function refactor(Node $node): ?Node
|
||||
{
|
||||
if (! $this->hasTagByName($node, self::REQUIRED_TAG)) {
|
||||
if (! $this->hasTagByName($node, TagName::REQUIRED)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,7 @@ use PhpParser\Node\Stmt\Return_;
|
||||
use PHPStan\Type\Constant\ConstantArrayType;
|
||||
use PHPStan\Type\MixedType;
|
||||
use PHPStan\Type\Type;
|
||||
use Rector\AttributeAwarePhpDoc\Ast\PhpDoc\AttributeAwareDataProviderTagValueNode;
|
||||
use Rector\AttributeAwarePhpDoc\Ast\PhpDoc\DataProviderTagValueNode;
|
||||
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
|
||||
use Rector\Core\PhpParser\Node\BetterNodeFinder;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
@ -78,8 +78,8 @@ final class PHPUnitDataProviderParamTypeInferer implements ParamTypeInfererInter
|
||||
return null;
|
||||
}
|
||||
|
||||
/** @var AttributeAwareDataProviderTagValueNode|null $attributeAwareDataProviderTagValueNode */
|
||||
$attributeAwareDataProviderTagValueNode = $phpDocInfo->getByType(AttributeAwareDataProviderTagValueNode::class);
|
||||
/** @var DataProviderTagValueNode|null $attributeAwareDataProviderTagValueNode */
|
||||
$attributeAwareDataProviderTagValueNode = $phpDocInfo->getByType(DataProviderTagValueNode::class);
|
||||
if ($attributeAwareDataProviderTagValueNode === null) {
|
||||
return null;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user