fix calendar css, take 2. (#213)
[openemr.git] / interface / modules / zend_modules / library / Zend / Code / Scanner / MethodScanner.php
blobe2c299f6a8267231ab0ffa6e769b213a167f7aeb
1 <?php
2 /**
3 * Zend Framework (http://framework.zend.com/)
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 */
10 namespace Zend\Code\Scanner;
12 use Zend\Code\Annotation\AnnotationManager;
13 use Zend\Code\Exception;
14 use Zend\Code\NameInformation;
16 class MethodScanner implements ScannerInterface
18 /**
19 * @var bool
21 protected $isScanned = false;
23 /**
24 * @var string
26 protected $docComment = null;
28 /**
29 * @var ClassScanner
31 protected $scannerClass = null;
33 /**
34 * @var string
36 protected $class = null;
38 /**
39 * @var string
41 protected $name = null;
43 /**
44 * @var int
46 protected $lineStart = null;
48 /**
49 * @var int
51 protected $lineEnd = null;
53 /**
54 * @var bool
56 protected $isFinal = false;
58 /**
59 * @var bool
61 protected $isAbstract = false;
63 /**
64 * @var bool
66 protected $isPublic = true;
68 /**
69 * @var bool
71 protected $isProtected = false;
73 /**
74 * @var bool
76 protected $isPrivate = false;
78 /**
79 * @var bool
81 protected $isStatic = false;
83 /**
84 * @var string
86 protected $body = '';
88 /**
89 * @var array
91 protected $tokens = array();
93 /**
94 * @var NameInformation
96 protected $nameInformation = null;
98 /**
99 * @var array
101 protected $infos = array();
104 * @param array $methodTokens
105 * @param NameInformation $nameInformation
107 public function __construct(array $methodTokens, NameInformation $nameInformation = null)
109 $this->tokens = $methodTokens;
110 $this->nameInformation = $nameInformation;
114 * @param string $class
115 * @return MethodScanner
117 public function setClass($class)
119 $this->class = (string) $class;
120 return $this;
124 * @param ClassScanner $scannerClass
125 * @return MethodScanner
127 public function setScannerClass(ClassScanner $scannerClass)
129 $this->scannerClass = $scannerClass;
130 return $this;
134 * @return MethodScanner
136 public function getClassScanner()
138 return $this->scannerClass;
142 * @return string
144 public function getName()
146 $this->scan();
148 return $this->name;
152 * @return int
154 public function getLineStart()
156 $this->scan();
158 return $this->lineStart;
162 * @return int
164 public function getLineEnd()
166 $this->scan();
168 return $this->lineEnd;
172 * @return string
174 public function getDocComment()
176 $this->scan();
178 return $this->docComment;
182 * @param AnnotationManager $annotationManager
183 * @return AnnotationScanner
185 public function getAnnotations(AnnotationManager $annotationManager)
187 if (($docComment = $this->getDocComment()) == '') {
188 return false;
191 return new AnnotationScanner($annotationManager, $docComment, $this->nameInformation);
195 * @return bool
197 public function isFinal()
199 $this->scan();
201 return $this->isFinal;
205 * @return bool
207 public function isAbstract()
209 $this->scan();
211 return $this->isAbstract;
215 * @return bool
217 public function isPublic()
219 $this->scan();
221 return $this->isPublic;
225 * @return bool
227 public function isProtected()
229 $this->scan();
231 return $this->isProtected;
235 * @return bool
237 public function isPrivate()
239 $this->scan();
241 return $this->isPrivate;
245 * @return bool
247 public function isStatic()
249 $this->scan();
251 return $this->isStatic;
255 * Override the given name for a method, this is necessary to
256 * support traits.
258 * @param $name
259 * @return self
261 public function setName($name)
263 $this->name = $name;
264 return $this;
268 * Visibility must be of T_PUBLIC, T_PRIVATE or T_PROTECTED
269 * Needed to support traits
271 * @param $visibility T_PUBLIC | T_PRIVATE | T_PROTECTED
272 * @return self
273 * @throws \Zend\Code\Exception
275 public function setVisibility($visibility)
277 switch (strtolower($visibility)) {
278 case T_PUBLIC:
279 $this->isPublic = true;
280 $this->isPrivate = false;
281 $this->isProtected = false;
282 break;
284 case T_PRIVATE:
285 $this->isPublic = false;
286 $this->isPrivate = true;
287 $this->isProtected = false;
288 break;
290 case T_PROTECTED:
291 $this->isPublic = false;
292 $this->isPrivate = false;
293 $this->isProtected = true;
294 break;
296 default:
297 throw new Exception("Invalid visibility argument passed to setVisibility.");
300 return $this;
304 * @return int
306 public function getNumberOfParameters()
308 return count($this->getParameters());
312 * @param bool $returnScanner
313 * @return array
315 public function getParameters($returnScanner = false)
317 $this->scan();
319 $return = array();
321 foreach ($this->infos as $info) {
322 if ($info['type'] != 'parameter') {
323 continue;
326 if (!$returnScanner) {
327 $return[] = $info['name'];
328 } else {
329 $return[] = $this->getParameter($info['name']);
333 return $return;
337 * @param int|string $parameterNameOrInfoIndex
338 * @return ParameterScanner
339 * @throws Exception\InvalidArgumentException
341 public function getParameter($parameterNameOrInfoIndex)
343 $this->scan();
345 if (is_int($parameterNameOrInfoIndex)) {
346 $info = $this->infos[$parameterNameOrInfoIndex];
347 if ($info['type'] != 'parameter') {
348 throw new Exception\InvalidArgumentException('Index of info offset is not about a parameter');
350 } elseif (is_string($parameterNameOrInfoIndex)) {
351 foreach ($this->infos as $info) {
352 if ($info['type'] === 'parameter' && $info['name'] === $parameterNameOrInfoIndex) {
353 break;
355 unset($info);
357 if (!isset($info)) {
358 throw new Exception\InvalidArgumentException('Index of info offset is not about a parameter');
362 $p = new ParameterScanner(
363 array_slice($this->tokens, $info['tokenStart'], $info['tokenEnd'] - $info['tokenStart']),
364 $this->nameInformation
366 $p->setDeclaringFunction($this->name);
367 $p->setDeclaringScannerFunction($this);
368 $p->setDeclaringClass($this->class);
369 $p->setDeclaringScannerClass($this->scannerClass);
370 $p->setPosition($info['position']);
372 return $p;
376 * @return string
378 public function getBody()
380 $this->scan();
382 return $this->body;
385 public static function export()
387 // @todo
390 public function __toString()
392 $this->scan();
394 return var_export($this, true);
397 protected function scan()
399 if ($this->isScanned) {
400 return;
403 if (!$this->tokens) {
404 throw new Exception\RuntimeException('No tokens were provided');
408 * Variables & Setup
411 $tokens = &$this->tokens; // localize
412 $infos = &$this->infos; // localize
413 $tokenIndex = null;
414 $token = null;
415 $tokenType = null;
416 $tokenContent = null;
417 $tokenLine = null;
418 $infoIndex = 0;
419 $parentCount = 0;
422 * MACRO creation
424 $MACRO_TOKEN_ADVANCE = function () use (
425 &$tokens,
426 &$tokenIndex,
427 &$token,
428 &$tokenType,
429 &$tokenContent,
430 &$tokenLine
432 static $lastTokenArray = null;
433 $tokenIndex = ($tokenIndex === null) ? 0 : $tokenIndex + 1;
434 if (!isset($tokens[$tokenIndex])) {
435 $token = false;
436 $tokenContent = false;
437 $tokenType = false;
438 $tokenLine = false;
440 return false;
442 $token = $tokens[$tokenIndex];
443 if (is_string($token)) {
444 $tokenType = null;
445 $tokenContent = $token;
446 $tokenLine = $tokenLine + substr_count(
447 $lastTokenArray[1],
448 "\n"
449 ); // adjust token line by last known newline count
450 } else {
451 list($tokenType, $tokenContent, $tokenLine) = $token;
454 return $tokenIndex;
456 $MACRO_INFO_START = function () use (&$infoIndex, &$infos, &$tokenIndex, &$tokenLine) {
457 $infos[$infoIndex] = array(
458 'type' => 'parameter',
459 'tokenStart' => $tokenIndex,
460 'tokenEnd' => null,
461 'lineStart' => $tokenLine,
462 'lineEnd' => $tokenLine,
463 'name' => null,
464 'position' => $infoIndex + 1, // position is +1 of infoIndex
467 $MACRO_INFO_ADVANCE = function () use (&$infoIndex, &$infos, &$tokenIndex, &$tokenLine) {
468 $infos[$infoIndex]['tokenEnd'] = $tokenIndex;
469 $infos[$infoIndex]['lineEnd'] = $tokenLine;
470 $infoIndex++;
472 return $infoIndex;
476 * START FINITE STATE MACHINE FOR SCANNING TOKENS
479 // Initialize token
480 $MACRO_TOKEN_ADVANCE();
482 SCANNER_TOP:
484 $this->lineStart = ($this->lineStart) ? : $tokenLine;
486 switch ($tokenType) {
487 case T_DOC_COMMENT:
488 $this->lineStart = null;
489 if ($this->docComment === null && $this->name === null) {
490 $this->docComment = $tokenContent;
492 goto SCANNER_CONTINUE_SIGNATURE;
493 //goto (no break needed);
495 case T_FINAL:
496 $this->isFinal = true;
497 goto SCANNER_CONTINUE_SIGNATURE;
498 //goto (no break needed);
500 case T_ABSTRACT:
501 $this->isAbstract = true;
502 goto SCANNER_CONTINUE_SIGNATURE;
503 //goto (no break needed);
505 case T_PUBLIC:
506 // use defaults
507 goto SCANNER_CONTINUE_SIGNATURE;
508 //goto (no break needed);
510 case T_PROTECTED:
511 $this->setVisibility(T_PROTECTED);
512 goto SCANNER_CONTINUE_SIGNATURE;
513 //goto (no break needed);
515 case T_PRIVATE:
516 $this->setVisibility(T_PRIVATE);
517 goto SCANNER_CONTINUE_SIGNATURE;
518 //goto (no break needed);
520 case T_STATIC:
521 $this->isStatic = true;
522 goto SCANNER_CONTINUE_SIGNATURE;
523 //goto (no break needed);
525 case T_VARIABLE:
526 case T_STRING:
528 if ($tokenType === T_STRING && $parentCount === 0) {
529 $this->name = $tokenContent;
532 if ($parentCount === 1) {
533 if (!isset($infos[$infoIndex])) {
534 $MACRO_INFO_START();
536 if ($tokenType === T_VARIABLE) {
537 $infos[$infoIndex]['name'] = ltrim($tokenContent, '$');
541 goto SCANNER_CONTINUE_SIGNATURE;
542 //goto (no break needed);
544 case null:
546 switch ($tokenContent) {
547 case '&':
548 if (!isset($infos[$infoIndex])) {
549 $MACRO_INFO_START();
551 goto SCANNER_CONTINUE_SIGNATURE;
552 //goto (no break needed);
553 case '(':
554 $parentCount++;
555 goto SCANNER_CONTINUE_SIGNATURE;
556 //goto (no break needed);
557 case ')':
558 $parentCount--;
559 if ($parentCount > 0) {
560 goto SCANNER_CONTINUE_SIGNATURE;
562 if ($parentCount === 0) {
563 if ($infos) {
564 $MACRO_INFO_ADVANCE();
566 $context = 'body';
568 goto SCANNER_CONTINUE_BODY;
569 //goto (no break needed);
570 case ',':
571 if ($parentCount === 1) {
572 $MACRO_INFO_ADVANCE();
574 goto SCANNER_CONTINUE_SIGNATURE;
578 SCANNER_CONTINUE_SIGNATURE:
580 if ($MACRO_TOKEN_ADVANCE() === false) {
581 goto SCANNER_END;
583 goto SCANNER_TOP;
585 SCANNER_CONTINUE_BODY:
587 $braceCount = 0;
588 while ($MACRO_TOKEN_ADVANCE() !== false) {
589 if ($tokenContent == '}') {
590 $braceCount--;
592 if ($braceCount > 0) {
593 $this->body .= $tokenContent;
595 if ($tokenContent == '{') {
596 $braceCount++;
598 $this->lineEnd = $tokenLine;
601 SCANNER_END:
603 $this->isScanned = true;
605 return;