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;
}
}