Current File : /var/www/prestashop/modules/ps_metrics/vendor/friendsofphp/php-cs-fixer/src/DocBlock/Annotation.php
<?php

declare (strict_types=1);
/*
 * This file is part of PHP CS Fixer.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *     Dariusz Rumiński <dariusz.ruminski@gmail.com>
 *
 * This source file is subject to the MIT license that is bundled
 * with this source code in the file LICENSE.
 */
namespace ps_metrics_module_v4_0_6\PhpCsFixer\DocBlock;

use ps_metrics_module_v4_0_6\PhpCsFixer\Preg;
use ps_metrics_module_v4_0_6\PhpCsFixer\Tokenizer\Analyzer\Analysis\NamespaceAnalysis;
use ps_metrics_module_v4_0_6\PhpCsFixer\Tokenizer\Analyzer\Analysis\NamespaceUseAnalysis;
/**
 * This represents an entire annotation from a docblock.
 *
 * @author Graham Campbell <hello@gjcampbell.co.uk>
 * @author Dariusz Rumiński <dariusz.ruminski@gmail.com>
 */
final class Annotation
{
    /**
     * All the annotation tag names with types.
     *
     * @var string[]
     */
    private static $tags = ['method', 'param', 'property', 'property-read', 'property-write', 'return', 'throws', 'type', 'var'];
    /**
     * The lines that make up the annotation.
     *
     * @var Line[]
     */
    private $lines;
    /**
     * The position of the first line of the annotation in the docblock.
     *
     * @var int
     */
    private $start;
    /**
     * The position of the last line of the annotation in the docblock.
     *
     * @var int
     */
    private $end;
    /**
     * The associated tag.
     *
     * @var null|Tag
     */
    private $tag;
    /**
     * Lazy loaded, cached types content.
     *
     * @var null|string
     */
    private $typesContent;
    /**
     * The cached types.
     *
     * @var null|string[]
     */
    private $types;
    /**
     * @var null|NamespaceAnalysis
     */
    private $namespace;
    /**
     * @var NamespaceUseAnalysis[]
     */
    private $namespaceUses;
    /**
     * Create a new line instance.
     *
     * @param Line[]                 $lines
     * @param null|NamespaceAnalysis $namespace
     * @param NamespaceUseAnalysis[] $namespaceUses
     */
    public function __construct(array $lines, $namespace = null, array $namespaceUses = [])
    {
        $this->lines = \array_values($lines);
        $this->namespace = $namespace;
        $this->namespaceUses = $namespaceUses;
        $keys = \array_keys($lines);
        $this->start = $keys[0];
        $this->end = \end($keys);
    }
    /**
     * Get the string representation of object.
     */
    public function __toString() : string
    {
        return $this->getContent();
    }
    /**
     * Get all the annotation tag names with types.
     *
     * @return string[]
     */
    public static function getTagsWithTypes() : array
    {
        return self::$tags;
    }
    /**
     * Get the start position of this annotation.
     */
    public function getStart() : int
    {
        return $this->start;
    }
    /**
     * Get the end position of this annotation.
     */
    public function getEnd() : int
    {
        return $this->end;
    }
    /**
     * Get the associated tag.
     */
    public function getTag() : Tag
    {
        if (null === $this->tag) {
            $this->tag = new Tag($this->lines[0]);
        }
        return $this->tag;
    }
    /**
     * @internal
     */
    public function getTypeExpression() : TypeExpression
    {
        return new TypeExpression($this->getTypesContent(), $this->namespace, $this->namespaceUses);
    }
    /**
     * @return null|string
     *
     * @internal
     */
    public function getVariableName()
    {
        $type = \preg_quote($this->getTypesContent(), '/');
        $regex = "/@{$this->tag->getName()}\\s+{$type}\\s+(?<variable>\\\$.+?)(?:[\\s*]|\$)/";
        if (Preg::match($regex, $this->lines[0]->getContent(), $matches)) {
            return $matches['variable'];
        }
        return null;
    }
    /**
     * Get the types associated with this annotation.
     *
     * @return string[]
     */
    public function getTypes() : array
    {
        if (null === $this->types) {
            $this->types = $this->getTypeExpression()->getTypes();
        }
        return $this->types;
    }
    /**
     * Set the types associated with this annotation.
     *
     * @param string[] $types
     */
    public function setTypes(array $types) : void
    {
        $pattern = '/' . \preg_quote($this->getTypesContent(), '/') . '/';
        $this->lines[0]->setContent(Preg::replace($pattern, \implode('|', $types), $this->lines[0]->getContent(), 1));
        $this->clearCache();
    }
    /**
     * Get the normalized types associated with this annotation, so they can easily be compared.
     *
     * @return string[]
     */
    public function getNormalizedTypes() : array
    {
        $normalized = \array_map(static function (string $type) : string {
            return \strtolower($type);
        }, $this->getTypes());
        \sort($normalized);
        return $normalized;
    }
    /**
     * Remove this annotation by removing all its lines.
     */
    public function remove() : void
    {
        foreach ($this->lines as $line) {
            if ($line->isTheStart() && $line->isTheEnd()) {
                // Single line doc block, remove entirely
                $line->remove();
            } elseif ($line->isTheStart()) {
                // Multi line doc block, but start is on the same line as the first annotation, keep only the start
                $content = Preg::replace('#(\\s*/\\*\\*).*#', '$1', $line->getContent());
                $line->setContent($content);
            } elseif ($line->isTheEnd()) {
                // Multi line doc block, but end is on the same line as the last annotation, keep only the end
                $content = Preg::replace('#(\\s*)\\S.*(\\*/.*)#', '$1$2', $line->getContent());
                $line->setContent($content);
            } else {
                // Multi line doc block, neither start nor end on this line, can be removed safely
                $line->remove();
            }
        }
        $this->clearCache();
    }
    /**
     * Get the annotation content.
     */
    public function getContent() : string
    {
        return \implode('', $this->lines);
    }
    public function supportTypes() : bool
    {
        return \in_array($this->getTag()->getName(), self::$tags, \true);
    }
    /**
     * Get the current types content.
     *
     * Be careful modifying the underlying line as that won't flush the cache.
     */
    private function getTypesContent() : string
    {
        if (null === $this->typesContent) {
            $name = $this->getTag()->getName();
            if (!$this->supportTypes()) {
                throw new \RuntimeException('This tag does not support types.');
            }
            $matchingResult = Preg::match('{^(?:\\s*\\*|/\\*\\*)\\s*@' . $name . '\\s+' . TypeExpression::REGEX_TYPES . '(?:[*\\h\\v].*)?\\r?$}sx', $this->lines[0]->getContent(), $matches);
            $this->typesContent = 1 === $matchingResult ? $matches['types'] : '';
        }
        return $this->typesContent;
    }
    private function clearCache() : void
    {
        $this->types = null;
        $this->typesContent = null;
    }
}