Annotation.php 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. <?php
  2. /*
  3. * This file is part of the PHP CS utility.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * This source file is subject to the MIT license that is bundled
  8. * with this source code in the file LICENSE.
  9. */
  10. namespace Symfony\CS\DocBlock;
  11. /**
  12. * This represents an entire annotation from a docblock.
  13. *
  14. * @author Graham Campbell <graham@mineuk.com>
  15. */
  16. class Annotation
  17. {
  18. /**
  19. * All the annotation tag names with types.
  20. *
  21. * @var string[]
  22. */
  23. private static $tags = array(
  24. 'method',
  25. 'param',
  26. 'property',
  27. 'property-read',
  28. 'property-write',
  29. 'return',
  30. 'throws',
  31. 'type',
  32. 'var',
  33. );
  34. /**
  35. * The lines that make up the annotation.
  36. *
  37. * @var Line[]
  38. */
  39. private $lines;
  40. /**
  41. * The position of the first line of the annotation in the docblock.
  42. *
  43. * @var int
  44. */
  45. private $start;
  46. /**
  47. * The position of the last line of the annotation in the docblock.
  48. *
  49. * @var int
  50. */
  51. private $end;
  52. /**
  53. * The associated tag.
  54. *
  55. * @var Tag|null
  56. */
  57. private $tag;
  58. /**
  59. * The cached types content.
  60. *
  61. * @var string|null
  62. */
  63. private $typesContent;
  64. /**
  65. * Create a new line instance.
  66. *
  67. * @param Line[] $lines
  68. */
  69. public function __construct(array $lines)
  70. {
  71. $this->lines = array_values($lines);
  72. $keys = array_keys($lines);
  73. $this->start = $keys[0];
  74. $this->end = end($keys);
  75. }
  76. /**
  77. * Get all the annotation tag names with types.
  78. *
  79. * @return string[]
  80. */
  81. public static function getTagsWithTypes()
  82. {
  83. return self::$tags;
  84. }
  85. /**
  86. * Get the start position of this annotation.
  87. *
  88. * @return int
  89. */
  90. public function getStart()
  91. {
  92. return $this->start;
  93. }
  94. /**
  95. * Get the end position of this annotation.
  96. *
  97. * @return int
  98. */
  99. public function getEnd()
  100. {
  101. return $this->end;
  102. }
  103. /**
  104. * Get the associated tag.
  105. *
  106. * @return Tag
  107. */
  108. public function getTag()
  109. {
  110. if (null === $this->tag) {
  111. $this->tag = new Tag($this->lines[0]);
  112. }
  113. return $this->tag;
  114. }
  115. /**
  116. * Get the current types content.
  117. *
  118. * Be careful modifying the underlying line as that won't flush the cache.
  119. *
  120. * @return string
  121. */
  122. private function getTypesContent()
  123. {
  124. if (null === $this->typesContent) {
  125. $name = $this->getTag()->getName();
  126. if (!in_array($name, self::$tags, true)) {
  127. throw new \RuntimeException('This tag does not support types');
  128. }
  129. $tagSplit = preg_split('/\s*\@'.$name.'\s*/', $this->lines[0]->getContent(), 2);
  130. $spaceSplit = preg_split('/\s/', $tagSplit[1], 2);
  131. $this->typesContent = $spaceSplit[0];
  132. }
  133. return $this->typesContent;
  134. }
  135. /**
  136. * Get the types associated with this annotation.
  137. *
  138. * @return string[]
  139. */
  140. public function getTypes()
  141. {
  142. return explode('|', $this->getTypesContent());
  143. }
  144. /**
  145. * Set the types associated with this annotation.
  146. *
  147. * @param string[] $types
  148. */
  149. public function setTypes(array $types)
  150. {
  151. $pattern = '/'.preg_quote($this->getTypesContent()).'/';
  152. $this->lines[0]->setContent(preg_replace($pattern, implode('|', $types), $this->lines[0]->getContent(), 1));
  153. $this->typesContent = null;
  154. }
  155. /**
  156. * Remove this annotation by removing all its lines.
  157. */
  158. public function remove()
  159. {
  160. foreach ($this->lines as $line) {
  161. $line->remove();
  162. }
  163. }
  164. /**
  165. * Get the annotation content.
  166. *
  167. * @return string
  168. */
  169. public function getContent()
  170. {
  171. return implode($this->lines);
  172. }
  173. /**
  174. * Get the string representation of object.
  175. *
  176. * @return string
  177. */
  178. public function __toString()
  179. {
  180. return $this->getContent();
  181. }
  182. }