Add multiple annotation support on class (#4064)

* add test case for #3230

* position

* add support for multi doc annotations

* [rector] add support for multi doc annotations

* [cs] add support for multi doc annotations

Co-authored-by: rector-bot <tomas@getrector.org>
This commit is contained in:
Tomas Votruba 2020-08-30 01:12:20 +02:00 committed by GitHub
parent 4a2ba04b05
commit f8b485305f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 72 additions and 29 deletions

View File

@ -78,14 +78,16 @@ final class NodeAnnotationReader
{
$classReflection = $this->createClassReflectionFromNode($class);
$annotation = $this->reader->getClassAnnotation($classReflection, $annotationClassName);
if ($annotation === null) {
try {
// covers cases like https://github.com/rectorphp/rector/issues/3046
/** @var object[] $classAnnotations */
$classAnnotations = $this->reader->getClassAnnotations($classReflection);
return $this->matchNextAnnotation($classAnnotations, $annotationClassName, $class);
} catch (AnnotationException $annotationException) {
// unable to load
return null;
}
$this->constantReferenceIdentifierRestorer->restoreObject($annotation);
return $annotation;
}
/**
@ -103,28 +105,11 @@ final class NodeAnnotationReader
/** @var object[] $propertyAnnotations */
$propertyAnnotations = $this->reader->getPropertyAnnotations($propertyReflection);
foreach ($propertyAnnotations as $propertyAnnotation) {
if (! is_a($propertyAnnotation, $annotationClassName, true)) {
continue;
}
$objectHash = md5(spl_object_hash($propertyReflection) . serialize($propertyAnnotation));
if (in_array($objectHash, $this->alreadyProvidedAnnotations, true)) {
continue;
}
$this->alreadyProvidedAnnotations[] = $objectHash;
$this->constantReferenceIdentifierRestorer->restoreObject($propertyAnnotation);
return $propertyAnnotation;
}
return $this->matchNextAnnotation($propertyAnnotations, $annotationClassName, $property);
} catch (AnnotationException $annotationException) {
// unable to laod
// unable to load
return null;
}
return null;
}
/**
@ -173,9 +158,35 @@ final class NodeAnnotationReader
/** @var string $className */
$className = $this->nodeNameResolver->getName($class);
// covers cases like https://github.com/rectorphp/rector/issues/3230#issuecomment-683317288
return new ReflectionClass($className);
}
/**
* @param object[] $annotations
*/
private function matchNextAnnotation(array $annotations, string $annotationClassName, Node $node): ?object
{
foreach ($annotations as $annotatoin) {
if (! is_a($annotatoin, $annotationClassName, true)) {
continue;
}
$objectHash = md5(spl_object_hash($node) . serialize($annotatoin));
if (in_array($objectHash, $this->alreadyProvidedAnnotations, true)) {
continue;
}
$this->alreadyProvidedAnnotations[] = $objectHash;
$this->constantReferenceIdentifierRestorer->restoreObject($annotatoin);
return $annotatoin;
}
return null;
}
private function createPropertyReflectionFromPropertyNode(Property $property): ?ReflectionProperty
{
/** @var string $propertyName */

View File

@ -144,8 +144,8 @@ final class PhpDocInfoPrinter
// node output
$nodeCount = count($attributeAwarePhpDocNode->children);
foreach ($attributeAwarePhpDocNode->children as $i => $phpDocChildNode) {
$output .= $this->printNode($phpDocChildNode, null, $i + 1, $nodeCount);
foreach ($attributeAwarePhpDocNode->children as $key => $phpDocChildNode) {
$output .= $this->printNode($phpDocChildNode, null, $key + 1, $nodeCount);
}
$output = $this->printEnd($output);
@ -171,7 +171,7 @@ final class PhpDocInfoPrinter
private function printNode(
AttributeAwareNodeInterface $attributeAwareNode,
?StartEndValueObject $startEndValueObject = null,
int $i = 0,
int $key = 0,
int $nodeCount = 0
): string {
$output = '';
@ -181,7 +181,7 @@ final class PhpDocInfoPrinter
$attributeAwareNode = $this->multilineSpaceFormatPreserver->fixMultilineDescriptions($attributeAwareNode);
if ($startEndValueObject !== null) {
$isLastToken = ($nodeCount === $i);
$isLastToken = ($nodeCount === $key);
$output = $this->addTokensFromTo(
$output,

View File

@ -0,0 +1,4 @@
/**
* @Route("/", name="homepage")
* @Route("/another-path", name="another-path")
*/

View File

@ -0,0 +1,28 @@
<?php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;
/**
* @Route("/hey", name="hey")
* @Route("/hey-me", name="hey_me")
*/
class DoubleRoute extends AbstractController
{
/**
* @Route("/property", name="property")
* @Route("/property-me", name="property_me")
*/
private $value;
/**
* @Route("/change", name="facility_change")
* @Route("/change-me", name="facility_change_me")
*/
public function index()
{
return [];
}
}