PageRenderTime 42ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/vendor/zendframework/zend-code/src/Scanner/DocBlockScanner.php

https://gitlab.com/yousafsyed/easternglamor
PHP | 326 lines | 223 code | 47 blank | 56 comment | 35 complexity | 011b3b1271b053f30d809a704c801110 MD5 | raw file
  1. <?php
  2. /**
  3. * Zend Framework (http://framework.zend.com/)
  4. *
  5. * @link http://github.com/zendframework/zf2 for the canonical source repository
  6. * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
  7. * @license http://framework.zend.com/license/new-bsd New BSD License
  8. */
  9. namespace Zend\Code\Scanner;
  10. use Zend\Code\Annotation\AnnotationManager;
  11. use Zend\Code\NameInformation;
  12. class DocBlockScanner implements ScannerInterface
  13. {
  14. /**
  15. * @var bool
  16. */
  17. protected $isScanned = false;
  18. /**
  19. * @var string
  20. */
  21. protected $docComment = null;
  22. /**
  23. * @var NameInformation
  24. */
  25. protected $nameInformation = null;
  26. /**
  27. * @var AnnotationManager
  28. */
  29. protected $annotationManager = null;
  30. /**
  31. * @var string
  32. */
  33. protected $shortDescription = null;
  34. /**
  35. * @var string
  36. */
  37. protected $longDescription = '';
  38. /**
  39. * @var array
  40. */
  41. protected $tags = array();
  42. /**
  43. * @var array
  44. */
  45. protected $annotations = array();
  46. /**
  47. * @param string $docComment
  48. * @param null|NameInformation $nameInformation
  49. */
  50. public function __construct($docComment, NameInformation $nameInformation = null)
  51. {
  52. $this->docComment = $docComment;
  53. $this->nameInformation = $nameInformation;
  54. }
  55. /**
  56. * @return string
  57. */
  58. public function getShortDescription()
  59. {
  60. $this->scan();
  61. return $this->shortDescription;
  62. }
  63. /**
  64. * @return string
  65. */
  66. public function getLongDescription()
  67. {
  68. $this->scan();
  69. return $this->longDescription;
  70. }
  71. /**
  72. * @return array
  73. */
  74. public function getTags()
  75. {
  76. $this->scan();
  77. return $this->tags;
  78. }
  79. /**
  80. * @return array
  81. */
  82. public function getAnnotations()
  83. {
  84. $this->scan();
  85. return $this->annotations;
  86. }
  87. /**
  88. * @return void
  89. */
  90. protected function scan()
  91. {
  92. if ($this->isScanned) {
  93. return;
  94. }
  95. $mode = 1;
  96. $tokens = $this->tokenize();
  97. $tagIndex = null;
  98. reset($tokens);
  99. SCANNER_TOP:
  100. $token = current($tokens);
  101. switch ($token[0]) {
  102. case 'DOCBLOCK_NEWLINE':
  103. if ($this->shortDescription != '' && $tagIndex === null) {
  104. $mode = 2;
  105. } else {
  106. $this->longDescription .= $token[1];
  107. }
  108. goto SCANNER_CONTINUE;
  109. //goto no break needed
  110. case 'DOCBLOCK_WHITESPACE':
  111. case 'DOCBLOCK_TEXT':
  112. if ($tagIndex !== null) {
  113. $this->tags[$tagIndex]['value'] .= ($this->tags[$tagIndex]['value'] == '') ? $token[1] : ' ' . $token[1];
  114. goto SCANNER_CONTINUE;
  115. } elseif ($mode <= 2) {
  116. if ($mode == 1) {
  117. $this->shortDescription .= $token[1];
  118. } else {
  119. $this->longDescription .= $token[1];
  120. }
  121. goto SCANNER_CONTINUE;
  122. }
  123. //gotos no break needed
  124. case 'DOCBLOCK_TAG':
  125. array_push($this->tags, array('name' => $token[1],
  126. 'value' => ''));
  127. end($this->tags);
  128. $tagIndex = key($this->tags);
  129. $mode = 3;
  130. goto SCANNER_CONTINUE;
  131. //goto no break needed
  132. case 'DOCBLOCK_COMMENTEND':
  133. goto SCANNER_END;
  134. }
  135. SCANNER_CONTINUE:
  136. if (next($tokens) === false) {
  137. goto SCANNER_END;
  138. }
  139. goto SCANNER_TOP;
  140. SCANNER_END:
  141. $this->shortDescription = trim($this->shortDescription);
  142. $this->longDescription = trim($this->longDescription);
  143. $this->isScanned = true;
  144. }
  145. /**
  146. * @return array
  147. */
  148. protected function tokenize()
  149. {
  150. static $CONTEXT_INSIDE_DOCBLOCK = 0x01;
  151. static $CONTEXT_INSIDE_ASTERISK = 0x02;
  152. $context = 0x00;
  153. $stream = $this->docComment;
  154. $streamIndex = null;
  155. $tokens = array();
  156. $tokenIndex = null;
  157. $currentChar = null;
  158. $currentWord = null;
  159. $currentLine = null;
  160. $MACRO_STREAM_ADVANCE_CHAR = function ($positionsForward = 1) use (&$stream, &$streamIndex, &$currentChar, &$currentWord, &$currentLine) {
  161. $positionsForward = ($positionsForward > 0) ? $positionsForward : 1;
  162. $streamIndex = ($streamIndex === null) ? 0 : $streamIndex + $positionsForward;
  163. if (!isset($stream[$streamIndex])) {
  164. $currentChar = false;
  165. return false;
  166. }
  167. $currentChar = $stream[$streamIndex];
  168. $matches = array();
  169. $currentLine = (preg_match('#(.*?)\r?\n#', $stream, $matches, null, $streamIndex) === 1) ? $matches[1] : substr($stream, $streamIndex);
  170. if ($currentChar === ' ') {
  171. $currentWord = (preg_match('#( +)#', $currentLine, $matches) === 1) ? $matches[1] : $currentLine;
  172. } else {
  173. $currentWord = (($matches = strpos($currentLine, ' ')) !== false) ? substr($currentLine, 0, $matches) : $currentLine;
  174. }
  175. return $currentChar;
  176. };
  177. $MACRO_STREAM_ADVANCE_WORD = function () use (&$currentWord, &$MACRO_STREAM_ADVANCE_CHAR) {
  178. return $MACRO_STREAM_ADVANCE_CHAR(strlen($currentWord));
  179. };
  180. $MACRO_STREAM_ADVANCE_LINE = function () use (&$currentLine, &$MACRO_STREAM_ADVANCE_CHAR) {
  181. return $MACRO_STREAM_ADVANCE_CHAR(strlen($currentLine));
  182. };
  183. $MACRO_TOKEN_ADVANCE = function () use (&$tokenIndex, &$tokens) {
  184. $tokenIndex = ($tokenIndex === null) ? 0 : $tokenIndex + 1;
  185. $tokens[$tokenIndex] = array('DOCBLOCK_UNKNOWN', '');
  186. };
  187. $MACRO_TOKEN_SET_TYPE = function ($type) use (&$tokenIndex, &$tokens) {
  188. $tokens[$tokenIndex][0] = $type;
  189. };
  190. $MACRO_TOKEN_APPEND_CHAR = function () use (&$currentChar, &$tokens, &$tokenIndex) {
  191. $tokens[$tokenIndex][1] .= $currentChar;
  192. };
  193. $MACRO_TOKEN_APPEND_WORD = function () use (&$currentWord, &$tokens, &$tokenIndex) {
  194. $tokens[$tokenIndex][1] .= $currentWord;
  195. };
  196. $MACRO_TOKEN_APPEND_WORD_PARTIAL = function ($length) use (&$currentWord, &$tokens, &$tokenIndex) {
  197. $tokens[$tokenIndex][1] .= substr($currentWord, 0, $length);
  198. };
  199. $MACRO_TOKEN_APPEND_LINE = function () use (&$currentLine, &$tokens, &$tokenIndex) {
  200. $tokens[$tokenIndex][1] .= $currentLine;
  201. };
  202. $MACRO_STREAM_ADVANCE_CHAR();
  203. $MACRO_TOKEN_ADVANCE();
  204. TOKENIZER_TOP:
  205. if ($context === 0x00 && $currentChar === '/' && $currentWord === '/**') {
  206. $MACRO_TOKEN_SET_TYPE('DOCBLOCK_COMMENTSTART');
  207. $MACRO_TOKEN_APPEND_WORD();
  208. $MACRO_TOKEN_ADVANCE();
  209. $context |= $CONTEXT_INSIDE_DOCBLOCK;
  210. $context |= $CONTEXT_INSIDE_ASTERISK;
  211. if ($MACRO_STREAM_ADVANCE_WORD() === false) {
  212. goto TOKENIZER_END;
  213. }
  214. goto TOKENIZER_TOP;
  215. }
  216. if ($context & $CONTEXT_INSIDE_DOCBLOCK && $currentWord === '*/') {
  217. $MACRO_TOKEN_SET_TYPE('DOCBLOCK_COMMENTEND');
  218. $MACRO_TOKEN_APPEND_WORD();
  219. $MACRO_TOKEN_ADVANCE();
  220. $context &= ~$CONTEXT_INSIDE_DOCBLOCK;
  221. if ($MACRO_STREAM_ADVANCE_WORD() === false) {
  222. goto TOKENIZER_END;
  223. }
  224. goto TOKENIZER_TOP;
  225. }
  226. if ($currentChar === ' ' || $currentChar === "\t") {
  227. $MACRO_TOKEN_SET_TYPE(($context & $CONTEXT_INSIDE_ASTERISK) ? 'DOCBLOCK_WHITESPACE' : 'DOCBLOCK_WHITESPACE_INDENT');
  228. $MACRO_TOKEN_APPEND_WORD();
  229. $MACRO_TOKEN_ADVANCE();
  230. if ($MACRO_STREAM_ADVANCE_WORD() === false) {
  231. goto TOKENIZER_END;
  232. }
  233. goto TOKENIZER_TOP;
  234. }
  235. if ($currentChar === '*') {
  236. if (($context & $CONTEXT_INSIDE_DOCBLOCK) && ($context & $CONTEXT_INSIDE_ASTERISK)) {
  237. $MACRO_TOKEN_SET_TYPE('DOCBLOCK_TEXT');
  238. } else {
  239. $MACRO_TOKEN_SET_TYPE('DOCBLOCK_ASTERISK');
  240. $context |= $CONTEXT_INSIDE_ASTERISK;
  241. }
  242. $MACRO_TOKEN_APPEND_CHAR();
  243. $MACRO_TOKEN_ADVANCE();
  244. if ($MACRO_STREAM_ADVANCE_CHAR() === false) {
  245. goto TOKENIZER_END;
  246. }
  247. goto TOKENIZER_TOP;
  248. }
  249. if ($currentChar === '@') {
  250. $MACRO_TOKEN_SET_TYPE('DOCBLOCK_TAG');
  251. $MACRO_TOKEN_APPEND_WORD();
  252. $MACRO_TOKEN_ADVANCE();
  253. if ($MACRO_STREAM_ADVANCE_WORD() === false) {
  254. goto TOKENIZER_END;
  255. }
  256. goto TOKENIZER_TOP;
  257. }
  258. if ($currentChar === "\n") {
  259. $MACRO_TOKEN_SET_TYPE('DOCBLOCK_NEWLINE');
  260. $MACRO_TOKEN_APPEND_CHAR();
  261. $MACRO_TOKEN_ADVANCE();
  262. $context &= ~$CONTEXT_INSIDE_ASTERISK;
  263. if ($MACRO_STREAM_ADVANCE_CHAR() === false) {
  264. goto TOKENIZER_END;
  265. }
  266. goto TOKENIZER_TOP;
  267. }
  268. $MACRO_TOKEN_SET_TYPE('DOCBLOCK_TEXT');
  269. $MACRO_TOKEN_APPEND_LINE();
  270. $MACRO_TOKEN_ADVANCE();
  271. if ($MACRO_STREAM_ADVANCE_LINE() === false) {
  272. goto TOKENIZER_END;
  273. }
  274. goto TOKENIZER_TOP;
  275. TOKENIZER_END:
  276. array_pop($tokens);
  277. return $tokens;
  278. }
  279. }