Skip to main content
Drupal API
User account menu
  • Log in

Breadcrumb

  1. Drupal Core 11.1.x
  2. AnnotationHelper.php

class AnnotationHelper

Same name in this branch
  1. 11.1.x vendor/phpstan/phpstan-phpunit/src/Rules/PHPUnit/AnnotationHelper.php \PHPStan\Rules\PHPUnit\AnnotationHelper

@internal

Hierarchy

  • class \SlevomatCodingStandard\Helpers\AnnotationHelper

Expanded class hierarchy of AnnotationHelper

19 files declare their use of AnnotationHelper
AnnotationNameSniff.php in vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/AnnotationNameSniff.php
DeprecatedAnnotationDeclarationSniff.php in vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/DeprecatedAnnotationDeclarationSniff.php
DisallowArrayTypeHintSyntaxSniff.php in vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/DisallowArrayTypeHintSyntaxSniff.php
DisallowMixedTypeHintSniff.php in vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/DisallowMixedTypeHintSniff.php
DocCommentSpacingSniff.php in vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/DocCommentSpacingSniff.php

... See full list

File

vendor/slevomat/coding-standard/SlevomatCodingStandard/Helpers/AnnotationHelper.php, line 35

Namespace

SlevomatCodingStandard\Helpers
View source
class AnnotationHelper {
    public const STATIC_ANALYSIS_PREFIXES = [
        'psalm',
        'phpstan',
    ];
    
    /**
     * @return list<Annotation>
     */
    public static function getAnnotations(File $phpcsFile, int $pointer, ?string $name = null) : array {
        $docCommentOpenPointer = DocCommentHelper::findDocCommentOpenPointer($phpcsFile, $pointer);
        if ($docCommentOpenPointer === null) {
            return [];
        }
        return SniffLocalCache::getAndSetIfNotCached($phpcsFile, sprintf('annotations-%d-%s', $docCommentOpenPointer, $name ?? 'all'), static function () use ($phpcsFile, $docCommentOpenPointer, $name) : array {
            $annotations = [];
            if ($name !== null) {
                foreach (self::getAnnotations($phpcsFile, $docCommentOpenPointer) as $annotation) {
                    if ($annotation->getName() === $name) {
                        $annotations[] = $annotation;
                    }
                }
            }
            else {
                $parsedDocComment = DocCommentHelper::parseDocComment($phpcsFile, $docCommentOpenPointer);
                if ($parsedDocComment !== null) {
                    foreach ($parsedDocComment->getNode()
                        ->getTags() as $node) {
                        $annotationStartPointer = $parsedDocComment->getNodeStartPointer($phpcsFile, $node);
                        $annotations[] = new Annotation($node, $annotationStartPointer, $parsedDocComment->getNodeEndPointer($phpcsFile, $node, $annotationStartPointer));
                    }
                }
            }
            return $annotations;
        });
    }
    
    /**
     * @param class-string $type
     * @return list<Node>
     */
    public static function getAnnotationNodesByType(Node $node, string $type) : array {
        static $visitor;
        static $traverser;
        if ($visitor === null) {
            $visitor = new class  extends AbstractNodeVisitor {
                
                /** @var class-string */
                private $type;
                
                /** @var list<Node> */
                private $nodes = [];
                
                /** @var list<Node> */
                private $nodesToIgnore = [];
                
                /**
                 * @return Node|list<Node>|NodeTraverser::*|null
                 */
                public function enterNode(Node $node) {
                    if ($this->type === IdentifierTypeNode::class) {
                        if ($node instanceof ArrayShapeItemNode || $node instanceof ObjectShapeItemNode) {
                            $this->nodesToIgnore[] = $node->keyName;
                        }
                        elseif ($node instanceof DoctrineArgument) {
                            $this->nodesToIgnore[] = $node->key;
                        }
                    }
                    if ($node instanceof $this->type && !in_array($node, $this->nodesToIgnore, true)) {
                        $this->nodes[] = $node;
                    }
                    return null;
                }
                
                /**
                 * @param class-string $type
                 */
                public function setType(string $type) : void {
                    $this->type = $type;
                }
                public function clean() : void {
                    $this->nodes = [];
                    $this->nodesToIgnore = [];
                }
                
                /**
                 * @return list<Node>
                 */
                public function getNodes() : array {
                    return $this->nodes;
                }

};
        }
        if ($traverser === null) {
            $traverser = new NodeTraverser([
                $visitor,
            ]);
        }
        $visitor->setType($type);
        $visitor->clean();
        $traverser->traverse([
            $node,
        ]);
        return $visitor->getNodes();
    }
    public static function fixAnnotation(ParsedDocComment $parsedDocComment, Annotation $annotation, Node $nodeToFix, Node $fixedNode) : string {
        $originalNode = $annotation->getNode();
        
        /** @var PhpDocNode $newPhpDocNode */
        $newPhpDocNode = PhpDocParserHelper::cloneNode($parsedDocComment->getNode());
        foreach ($newPhpDocNode->getTags() as $node) {
            if ($node->getAttribute(Attribute::ORIGINAL_NODE) === $originalNode) {
                self::changeAnnotationNode($node, $nodeToFix, $fixedNode);
                break;
            }
        }
        return PhpDocParserHelper::getPrinter()->printFormatPreserving($newPhpDocNode, $parsedDocComment->getNode(), $parsedDocComment->getTokens());
    }
    
    /**
     * @param array<int, string> $traversableTypeHints
     */
    public static function isAnnotationUseless(File $phpcsFile, int $functionPointer, ?TypeHint $typeHint, Annotation $annotation, array $traversableTypeHints, bool $enableUnionTypeHint = false, bool $enableIntersectionTypeHint = false, bool $enableStandaloneNullTrueFalseTypeHints = false) : bool {
        if ($annotation->isInvalid()) {
            return false;
        }
        if ($typeHint === null) {
            return false;
        }
        
        /** @var ParamTagValueNode|TypelessParamTagValueNode|ReturnTagValueNode|VarTagValueNode $annotationValue */
        $annotationValue = $annotation->getValue();
        if ($annotationValue->description !== '') {
            return false;
        }
        if ($annotationValue instanceof TypelessParamTagValueNode) {
            return true;
        }
        $annotationType = $annotationValue->type;
        if (TypeHintHelper::isTraversableType(TypeHintHelper::getFullyQualifiedTypeHint($phpcsFile, $functionPointer, $typeHint->getTypeHintWithoutNullabilitySymbol()), $traversableTypeHints) && !($annotationType instanceof IdentifierTypeNode && TypeHintHelper::isSimpleIterableTypeHint(strtolower($annotationType->name)))) {
            return false;
        }
        if (AnnotationTypeHelper::containsStaticOrThisType($annotationType)) {
            return false;
        }
        if (AnnotationTypeHelper::containsJustTwoTypes($annotationType) || $enableUnionTypeHint && ($annotationType instanceof UnionTypeNode || $annotationType instanceof IdentifierTypeNode && TypeHintHelper::isUnofficialUnionTypeHint($annotationType->name)) || $enableIntersectionTypeHint && $annotationType instanceof IntersectionTypeNode) {
            $annotationTypeHint = AnnotationTypeHelper::print($annotationType);
            return TypeHintHelper::typeHintEqualsAnnotation($phpcsFile, $functionPointer, $typeHint->getTypeHint(), $annotationTypeHint);
        }
        if ($annotationType instanceof ObjectShapeNode) {
            return false;
        }
        if ($annotationType instanceof ConstTypeNode) {
            return false;
        }
        if ($annotationType instanceof GenericTypeNode) {
            return false;
        }
        if ($annotationType instanceof CallableTypeNode) {
            return false;
        }
        if ($annotationType instanceof ConditionalTypeNode) {
            return false;
        }
        if ($annotationType instanceof ConditionalTypeForParameterNode) {
            return false;
        }
        if ($annotationType instanceof IdentifierTypeNode) {
            if (in_array(strtolower($annotationType->name), [
                'true',
                'false',
                'null',
            ], true)) {
                return $enableStandaloneNullTrueFalseTypeHints;
            }
            if (in_array(strtolower($annotationType->name), [
                'class-string',
                'trait-string',
                'callable-string',
                'numeric-string',
                'non-empty-string',
                'non-falsy-string',
                'literal-string',
                'positive-int',
                'negative-int',
            ], true)) {
                return false;
            }
        }
        $annotationTypeHint = AnnotationTypeHelper::getTypeHintFromOneType($annotationType);
        return TypeHintHelper::typeHintEqualsAnnotation($phpcsFile, $functionPointer, $typeHint->getTypeHintWithoutNullabilitySymbol(), $annotationTypeHint);
    }
    private static function changeAnnotationNode(PhpDocTagNode $tagNode, Node $nodeToChange, Node $changedNode) : PhpDocTagNode {
        static $visitor;
        static $traverser;
        if ($visitor === null) {
            $visitor = new class  extends AbstractNodeVisitor {
                
                /** @var Node */
                private $nodeToChange;
                
                /** @var Node */
                private $changedNode;
                
                /**
                 * @return Node|list<Node>|NodeTraverser::*|null
                 */
                public function enterNode(Node $node) {
                    if ($node->getAttribute(Attribute::ORIGINAL_NODE) === $this->nodeToChange) {
                        return $this->changedNode;
                    }
                    return null;
                }
                public function setNodeToChange(Node $nodeToChange) : void {
                    $this->nodeToChange = $nodeToChange;
                }
                public function setChangedNode(Node $changedNode) : void {
                    $this->changedNode = $changedNode;
                }

};
        }
        if ($traverser === null) {
            $traverser = new NodeTraverser([
                $visitor,
            ]);
        }
        $visitor->setNodeToChange($nodeToChange);
        $visitor->setChangedNode($changedNode);
        [
            $changedTagNode,
        ] = $traverser->traverse([
            $tagNode,
        ]);
        return $changedTagNode;
    }

}

Members

Title Sort descending Modifiers Object type Summary
AnnotationHelper::changeAnnotationNode private static function
AnnotationHelper::fixAnnotation public static function
AnnotationHelper::getAnnotationNodesByType public static function *
AnnotationHelper::getAnnotations public static function *
AnnotationHelper::isAnnotationUseless public static function *
AnnotationHelper::STATIC_ANALYSIS_PREFIXES public constant

API Navigation

  • Drupal Core 11.1.x
  • Topics
  • Classes
  • Functions
  • Constants
  • Globals
  • Files
  • Namespaces
  • Deprecated
  • Services
RSS feed
Powered by Drupal