PageRenderTime 27ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/monica/monica/vendor/zendframework/zendframework/library/Zend/Code/Scanner/MethodScanner.php

https://bitbucket.org/alexandretaz/maniac_divers
PHP | 537 lines | 311 code | 92 blank | 134 comment | 37 complexity | 2418e7efbee90651ac62a4f69d34ddfe MD5 | raw file
Possible License(s): BSD-3-Clause
  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-2013 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\Exception;
  12. use Zend\Code\NameInformation;
  13. class MethodScanner implements ScannerInterface
  14. {
  15. /**
  16. * @var bool
  17. */
  18. protected $isScanned = false;
  19. /**
  20. * @var string
  21. */
  22. protected $docComment = null;
  23. /**
  24. * @var ClassScanner
  25. */
  26. protected $scannerClass = null;
  27. /**
  28. * @var string
  29. */
  30. protected $class = null;
  31. /**
  32. * @var string
  33. */
  34. protected $name = null;
  35. /**
  36. * @var int
  37. */
  38. protected $lineStart = null;
  39. /**
  40. * @var int
  41. */
  42. protected $lineEnd = null;
  43. /**
  44. * @var bool
  45. */
  46. protected $isFinal = false;
  47. /**
  48. * @var bool
  49. */
  50. protected $isAbstract = false;
  51. /**
  52. * @var bool
  53. */
  54. protected $isPublic = true;
  55. /**
  56. * @var bool
  57. */
  58. protected $isProtected = false;
  59. /**
  60. * @var bool
  61. */
  62. protected $isPrivate = false;
  63. /**
  64. * @var bool
  65. */
  66. protected $isStatic = false;
  67. /**
  68. * @var string
  69. */
  70. protected $body = '';
  71. /**
  72. * @var array
  73. */
  74. protected $tokens = array();
  75. /**
  76. * @var NameInformation
  77. */
  78. protected $nameInformation = null;
  79. /**
  80. * @var array
  81. */
  82. protected $infos = array();
  83. /**
  84. * @param array $methodTokens
  85. * @param NameInformation $nameInformation
  86. */
  87. public function __construct(array $methodTokens, NameInformation $nameInformation = null)
  88. {
  89. $this->tokens = $methodTokens;
  90. $this->nameInformation = $nameInformation;
  91. }
  92. /**
  93. * @param string $class
  94. * @return MethodScanner
  95. */
  96. public function setClass($class)
  97. {
  98. $this->class = (string) $class;
  99. return $this;
  100. }
  101. /**
  102. * @param ClassScanner $scannerClass
  103. * @return MethodScanner
  104. */
  105. public function setScannerClass(ClassScanner $scannerClass)
  106. {
  107. $this->scannerClass = $scannerClass;
  108. return $this;
  109. }
  110. /**
  111. * @return MethodScanner
  112. */
  113. public function getClassScanner()
  114. {
  115. return $this->scannerClass;
  116. }
  117. /**
  118. * @return string
  119. */
  120. public function getName()
  121. {
  122. $this->scan();
  123. return $this->name;
  124. }
  125. /**
  126. * @return int
  127. */
  128. public function getLineStart()
  129. {
  130. $this->scan();
  131. return $this->lineStart;
  132. }
  133. /**
  134. * @return int
  135. */
  136. public function getLineEnd()
  137. {
  138. $this->scan();
  139. return $this->lineEnd;
  140. }
  141. /**
  142. * @return string
  143. */
  144. public function getDocComment()
  145. {
  146. $this->scan();
  147. return $this->docComment;
  148. }
  149. /**
  150. * @param AnnotationManager $annotationManager
  151. * @return AnnotationScanner
  152. */
  153. public function getAnnotations(AnnotationManager $annotationManager)
  154. {
  155. if (($docComment = $this->getDocComment()) == '') {
  156. return false;
  157. }
  158. return new AnnotationScanner($annotationManager, $docComment, $this->nameInformation);
  159. }
  160. /**
  161. * @return bool
  162. */
  163. public function isFinal()
  164. {
  165. $this->scan();
  166. return $this->isFinal;
  167. }
  168. /**
  169. * @return bool
  170. */
  171. public function isAbstract()
  172. {
  173. $this->scan();
  174. return $this->isAbstract;
  175. }
  176. /**
  177. * @return bool
  178. */
  179. public function isPublic()
  180. {
  181. $this->scan();
  182. return $this->isPublic;
  183. }
  184. /**
  185. * @return bool
  186. */
  187. public function isProtected()
  188. {
  189. $this->scan();
  190. return $this->isProtected;
  191. }
  192. /**
  193. * @return bool
  194. */
  195. public function isPrivate()
  196. {
  197. $this->scan();
  198. return $this->isPrivate;
  199. }
  200. /**
  201. * @return bool
  202. */
  203. public function isStatic()
  204. {
  205. $this->scan();
  206. return $this->isStatic;
  207. }
  208. /**
  209. * @return int
  210. */
  211. public function getNumberOfParameters()
  212. {
  213. return count($this->getParameters());
  214. }
  215. /**
  216. * @param bool $returnScanner
  217. * @return array
  218. */
  219. public function getParameters($returnScanner = false)
  220. {
  221. $this->scan();
  222. $return = array();
  223. foreach ($this->infos as $info) {
  224. if ($info['type'] != 'parameter') {
  225. continue;
  226. }
  227. if (!$returnScanner) {
  228. $return[] = $info['name'];
  229. } else {
  230. $return[] = $this->getParameter($info['name']);
  231. }
  232. }
  233. return $return;
  234. }
  235. /**
  236. * @param int|string $parameterNameOrInfoIndex
  237. * @return ParameterScanner
  238. * @throws Exception\InvalidArgumentException
  239. */
  240. public function getParameter($parameterNameOrInfoIndex)
  241. {
  242. $this->scan();
  243. if (is_int($parameterNameOrInfoIndex)) {
  244. $info = $this->infos[$parameterNameOrInfoIndex];
  245. if ($info['type'] != 'parameter') {
  246. throw new Exception\InvalidArgumentException('Index of info offset is not about a parameter');
  247. }
  248. } elseif (is_string($parameterNameOrInfoIndex)) {
  249. foreach ($this->infos as $info) {
  250. if ($info['type'] === 'parameter' && $info['name'] === $parameterNameOrInfoIndex) {
  251. break;
  252. }
  253. unset($info);
  254. }
  255. if (!isset($info)) {
  256. throw new Exception\InvalidArgumentException('Index of info offset is not about a parameter');
  257. }
  258. }
  259. $p = new ParameterScanner(
  260. array_slice($this->tokens, $info['tokenStart'], $info['tokenEnd'] - $info['tokenStart']),
  261. $this->nameInformation
  262. );
  263. $p->setDeclaringFunction($this->name);
  264. $p->setDeclaringScannerFunction($this);
  265. $p->setDeclaringClass($this->class);
  266. $p->setDeclaringScannerClass($this->scannerClass);
  267. $p->setPosition($info['position']);
  268. return $p;
  269. }
  270. /**
  271. * @return string
  272. */
  273. public function getBody()
  274. {
  275. $this->scan();
  276. return $this->body;
  277. }
  278. public static function export()
  279. {
  280. // @todo
  281. }
  282. public function __toString()
  283. {
  284. $this->scan();
  285. return var_export($this, true);
  286. }
  287. protected function scan()
  288. {
  289. if ($this->isScanned) {
  290. return;
  291. }
  292. if (!$this->tokens) {
  293. throw new Exception\RuntimeException('No tokens were provided');
  294. }
  295. /**
  296. * Variables & Setup
  297. */
  298. $tokens = &$this->tokens; // localize
  299. $infos = &$this->infos; // localize
  300. $tokenIndex = null;
  301. $token = null;
  302. $tokenType = null;
  303. $tokenContent = null;
  304. $tokenLine = null;
  305. $infoIndex = 0;
  306. $parentCount = 0;
  307. /*
  308. * MACRO creation
  309. */
  310. $MACRO_TOKEN_ADVANCE = function () use (&$tokens, &$tokenIndex, &$token, &$tokenType, &$tokenContent, &$tokenLine) {
  311. static $lastTokenArray = null;
  312. $tokenIndex = ($tokenIndex === null) ? 0 : $tokenIndex + 1;
  313. if (!isset($tokens[$tokenIndex])) {
  314. $token = false;
  315. $tokenContent = false;
  316. $tokenType = false;
  317. $tokenLine = false;
  318. return false;
  319. }
  320. $token = $tokens[$tokenIndex];
  321. if (is_string($token)) {
  322. $tokenType = null;
  323. $tokenContent = $token;
  324. $tokenLine = $tokenLine + substr_count($lastTokenArray[1],
  325. "\n"); // adjust token line by last known newline count
  326. } else {
  327. list($tokenType, $tokenContent, $tokenLine) = $token;
  328. }
  329. return $tokenIndex;
  330. };
  331. $MACRO_INFO_START = function () use (&$infoIndex, &$infos, &$tokenIndex, &$tokenLine) {
  332. $infos[$infoIndex] = array(
  333. 'type' => 'parameter',
  334. 'tokenStart' => $tokenIndex,
  335. 'tokenEnd' => null,
  336. 'lineStart' => $tokenLine,
  337. 'lineEnd' => $tokenLine,
  338. 'name' => null,
  339. 'position' => $infoIndex + 1, // position is +1 of infoIndex
  340. );
  341. };
  342. $MACRO_INFO_ADVANCE = function () use (&$infoIndex, &$infos, &$tokenIndex, &$tokenLine) {
  343. $infos[$infoIndex]['tokenEnd'] = $tokenIndex;
  344. $infos[$infoIndex]['lineEnd'] = $tokenLine;
  345. $infoIndex++;
  346. return $infoIndex;
  347. };
  348. /**
  349. * START FINITE STATE MACHINE FOR SCANNING TOKENS
  350. */
  351. // Initialize token
  352. $MACRO_TOKEN_ADVANCE();
  353. SCANNER_TOP:
  354. $this->lineStart = ($this->lineStart) ? : $tokenLine;
  355. switch ($tokenType) {
  356. case T_DOC_COMMENT:
  357. $this->lineStart = null;
  358. if ($this->docComment === null && $this->name === null) {
  359. $this->docComment = $tokenContent;
  360. }
  361. goto SCANNER_CONTINUE_SIGNATURE;
  362. case T_FINAL:
  363. $this->isFinal = true;
  364. goto SCANNER_CONTINUE_SIGNATURE;
  365. case T_ABSTRACT:
  366. $this->isAbstract = true;
  367. goto SCANNER_CONTINUE_SIGNATURE;
  368. case T_PUBLIC:
  369. // use defaults
  370. goto SCANNER_CONTINUE_SIGNATURE;
  371. case T_PROTECTED:
  372. $this->isProtected = true;
  373. $this->isPublic = false;
  374. goto SCANNER_CONTINUE_SIGNATURE;
  375. case T_PRIVATE:
  376. $this->isPrivate = true;
  377. $this->isPublic = false;
  378. goto SCANNER_CONTINUE_SIGNATURE;
  379. case T_STATIC:
  380. $this->isStatic = true;
  381. goto SCANNER_CONTINUE_SIGNATURE;
  382. case T_VARIABLE:
  383. case T_STRING:
  384. if ($tokenType === T_STRING && $parentCount === 0) {
  385. $this->name = $tokenContent;
  386. }
  387. if ($parentCount === 1) {
  388. if (!isset($infos[$infoIndex])) {
  389. $MACRO_INFO_START();
  390. }
  391. if ($tokenType === T_VARIABLE) {
  392. $infos[$infoIndex]['name'] = ltrim($tokenContent, '$');
  393. }
  394. }
  395. goto SCANNER_CONTINUE_SIGNATURE;
  396. case null:
  397. switch ($tokenContent) {
  398. case '&':
  399. if (!isset($infos[$infoIndex])) {
  400. $MACRO_INFO_START();
  401. }
  402. goto SCANNER_CONTINUE_SIGNATURE;
  403. case '(':
  404. $parentCount++;
  405. goto SCANNER_CONTINUE_SIGNATURE;
  406. case ')':
  407. $parentCount--;
  408. if ($parentCount === 0) {
  409. if ($infos) {
  410. $MACRO_INFO_ADVANCE();
  411. }
  412. $context = 'body';
  413. }
  414. goto SCANNER_CONTINUE_BODY;
  415. case ',':
  416. if ($parentCount === 1) {
  417. $MACRO_INFO_ADVANCE();
  418. }
  419. goto SCANNER_CONTINUE_SIGNATURE;
  420. }
  421. }
  422. SCANNER_CONTINUE_SIGNATURE:
  423. if ($MACRO_TOKEN_ADVANCE() === false) {
  424. goto SCANNER_END;
  425. }
  426. goto SCANNER_TOP;
  427. SCANNER_CONTINUE_BODY:
  428. $braceCount = 0;
  429. while ($MACRO_TOKEN_ADVANCE() !== false) {
  430. if ($tokenContent == '}') {
  431. $braceCount--;
  432. }
  433. if ($braceCount > 0) {
  434. $this->body .= $tokenContent;
  435. }
  436. if ($tokenContent == '{') {
  437. $braceCount++;
  438. }
  439. $this->lineEnd = $tokenLine;
  440. }
  441. SCANNER_END:
  442. $this->isScanned = true;
  443. return;
  444. }
  445. }