Source of file MethodScanner.php
Size: 12,840 Bytes - Last Modified: 2014-03-12T23:21:18+01:00
/home/theseer/Downloads/ZendFramework-2.3.0/library/Zend/Code/Scanner/MethodScanner.php
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541 | <?php /** * Zend Framework (http://framework.zend.com/) * * @link http://github.com/zendframework/zf2 for the canonical source repository * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ namespace Zend\Code\Scanner; use Zend\Code\Annotation\AnnotationManager; use Zend\Code\Exception; use Zend\Code\NameInformation; class MethodScanner implements ScannerInterface { /** * @var bool */ protected $isScanned = false; /** * @var string */ protected $docComment = null; /** * @var ClassScanner */ protected $scannerClass = null; /** * @var string */ protected $class = null; /** * @var string */ protected $name = null; /** * @var int */ protected $lineStart = null; /** * @var int */ protected $lineEnd = null; /** * @var bool */ protected $isFinal = false; /** * @var bool */ protected $isAbstract = false; /** * @var bool */ protected $isPublic = true; /** * @var bool */ protected $isProtected = false; /** * @var bool */ protected $isPrivate = false; /** * @var bool */ protected $isStatic = false; /** * @var string */ protected $body = ''; /** * @var array */ protected $tokens = array(); /** * @var NameInformation */ protected $nameInformation = null; /** * @var array */ protected $infos = array(); /** * @param array $methodTokens * @param NameInformation $nameInformation */ public function __construct(array $methodTokens, NameInformation $nameInformation = null) { $this->tokens = $methodTokens; $this->nameInformation = $nameInformation; } /** * @param string $class * @return MethodScanner */ public function setClass($class) { $this->class = (string) $class; return $this; } /** * @param ClassScanner $scannerClass * @return MethodScanner */ public function setScannerClass(ClassScanner $scannerClass) { $this->scannerClass = $scannerClass; return $this; } /** * @return MethodScanner */ public function getClassScanner() { return $this->scannerClass; } /** * @return string */ public function getName() { $this->scan(); return $this->name; } /** * @return int */ public function getLineStart() { $this->scan(); return $this->lineStart; } /** * @return int */ public function getLineEnd() { $this->scan(); return $this->lineEnd; } /** * @return string */ public function getDocComment() { $this->scan(); return $this->docComment; } /** * @param AnnotationManager $annotationManager * @return AnnotationScanner */ public function getAnnotations(AnnotationManager $annotationManager) { if (($docComment = $this->getDocComment()) == '') { return false; } return new AnnotationScanner($annotationManager, $docComment, $this->nameInformation); } /** * @return bool */ public function isFinal() { $this->scan(); return $this->isFinal; } /** * @return bool */ public function isAbstract() { $this->scan(); return $this->isAbstract; } /** * @return bool */ public function isPublic() { $this->scan(); return $this->isPublic; } /** * @return bool */ public function isProtected() { $this->scan(); return $this->isProtected; } /** * @return bool */ public function isPrivate() { $this->scan(); return $this->isPrivate; } /** * @return bool */ public function isStatic() { $this->scan(); return $this->isStatic; } /** * @return int */ public function getNumberOfParameters() { return count($this->getParameters()); } /** * @param bool $returnScanner * @return array */ public function getParameters($returnScanner = false) { $this->scan(); $return = array(); foreach ($this->infos as $info) { if ($info['type'] != 'parameter') { continue; } if (!$returnScanner) { $return[] = $info['name']; } else { $return[] = $this->getParameter($info['name']); } } return $return; } /** * @param int|string $parameterNameOrInfoIndex * @return ParameterScanner * @throws Exception\InvalidArgumentException */ public function getParameter($parameterNameOrInfoIndex) { $this->scan(); if (is_int($parameterNameOrInfoIndex)) { $info = $this->infos[$parameterNameOrInfoIndex]; if ($info['type'] != 'parameter') { throw new Exception\InvalidArgumentException('Index of info offset is not about a parameter'); } } elseif (is_string($parameterNameOrInfoIndex)) { foreach ($this->infos as $info) { if ($info['type'] === 'parameter' && $info['name'] === $parameterNameOrInfoIndex) { break; } unset($info); } if (!isset($info)) { throw new Exception\InvalidArgumentException('Index of info offset is not about a parameter'); } } $p = new ParameterScanner( array_slice($this->tokens, $info['tokenStart'], $info['tokenEnd'] - $info['tokenStart']), $this->nameInformation ); $p->setDeclaringFunction($this->name); $p->setDeclaringScannerFunction($this); $p->setDeclaringClass($this->class); $p->setDeclaringScannerClass($this->scannerClass); $p->setPosition($info['position']); return $p; } /** * @return string */ public function getBody() { $this->scan(); return $this->body; } public static function export() { // @todo } public function __toString() { $this->scan(); return var_export($this, true); } protected function scan() { if ($this->isScanned) { return; } if (!$this->tokens) { throw new Exception\RuntimeException('No tokens were provided'); } /** * Variables & Setup */ $tokens = &$this->tokens; // localize $infos = &$this->infos; // localize $tokenIndex = null; $token = null; $tokenType = null; $tokenContent = null; $tokenLine = null; $infoIndex = 0; $parentCount = 0; /* * MACRO creation */ $MACRO_TOKEN_ADVANCE = function () use (&$tokens, &$tokenIndex, &$token, &$tokenType, &$tokenContent, &$tokenLine) { static $lastTokenArray = null; $tokenIndex = ($tokenIndex === null) ? 0 : $tokenIndex + 1; if (!isset($tokens[$tokenIndex])) { $token = false; $tokenContent = false; $tokenType = false; $tokenLine = false; return false; } $token = $tokens[$tokenIndex]; if (is_string($token)) { $tokenType = null; $tokenContent = $token; $tokenLine = $tokenLine + substr_count($lastTokenArray[1], "\n"); // adjust token line by last known newline count } else { list($tokenType, $tokenContent, $tokenLine) = $token; } return $tokenIndex; }; $MACRO_INFO_START = function () use (&$infoIndex, &$infos, &$tokenIndex, &$tokenLine) { $infos[$infoIndex] = array( 'type' => 'parameter', 'tokenStart' => $tokenIndex, 'tokenEnd' => null, 'lineStart' => $tokenLine, 'lineEnd' => $tokenLine, 'name' => null, 'position' => $infoIndex + 1, // position is +1 of infoIndex ); }; $MACRO_INFO_ADVANCE = function () use (&$infoIndex, &$infos, &$tokenIndex, &$tokenLine) { $infos[$infoIndex]['tokenEnd'] = $tokenIndex; $infos[$infoIndex]['lineEnd'] = $tokenLine; $infoIndex++; return $infoIndex; }; /** * START FINITE STATE MACHINE FOR SCANNING TOKENS */ // Initialize token $MACRO_TOKEN_ADVANCE(); SCANNER_TOP: $this->lineStart = ($this->lineStart) ? : $tokenLine; switch ($tokenType) { case T_DOC_COMMENT: $this->lineStart = null; if ($this->docComment === null && $this->name === null) { $this->docComment = $tokenContent; } goto SCANNER_CONTINUE_SIGNATURE; case T_FINAL: $this->isFinal = true; goto SCANNER_CONTINUE_SIGNATURE; case T_ABSTRACT: $this->isAbstract = true; goto SCANNER_CONTINUE_SIGNATURE; case T_PUBLIC: // use defaults goto SCANNER_CONTINUE_SIGNATURE; case T_PROTECTED: $this->isProtected = true; $this->isPublic = false; goto SCANNER_CONTINUE_SIGNATURE; case T_PRIVATE: $this->isPrivate = true; $this->isPublic = false; goto SCANNER_CONTINUE_SIGNATURE; case T_STATIC: $this->isStatic = true; goto SCANNER_CONTINUE_SIGNATURE; case T_VARIABLE: case T_STRING: if ($tokenType === T_STRING && $parentCount === 0) { $this->name = $tokenContent; } if ($parentCount === 1) { if (!isset($infos[$infoIndex])) { $MACRO_INFO_START(); } if ($tokenType === T_VARIABLE) { $infos[$infoIndex]['name'] = ltrim($tokenContent, '$'); } } goto SCANNER_CONTINUE_SIGNATURE; case null: switch ($tokenContent) { case '&': if (!isset($infos[$infoIndex])) { $MACRO_INFO_START(); } goto SCANNER_CONTINUE_SIGNATURE; case '(': $parentCount++; goto SCANNER_CONTINUE_SIGNATURE; case ')': $parentCount--; if($parentCount > 0) { goto SCANNER_CONTINUE_SIGNATURE; } if ($parentCount === 0) { if ($infos) { $MACRO_INFO_ADVANCE(); } $context = 'body'; } goto SCANNER_CONTINUE_BODY; case ',': if ($parentCount === 1) { $MACRO_INFO_ADVANCE(); } goto SCANNER_CONTINUE_SIGNATURE; } } SCANNER_CONTINUE_SIGNATURE: if ($MACRO_TOKEN_ADVANCE() === false) { goto SCANNER_END; } goto SCANNER_TOP; SCANNER_CONTINUE_BODY: $braceCount = 0; while ($MACRO_TOKEN_ADVANCE() !== false) { if ($tokenContent == '}') { $braceCount--; } if ($braceCount > 0) { $this->body .= $tokenContent; } if ($tokenContent == '{') { $braceCount++; } $this->lineEnd = $tokenLine; } SCANNER_END: $this->isScanned = true; return; } } |