[ Index ]

PHP Cross Reference of phpBB-3.3.2-deutsch

title

Body

[close]

/vendor/zendframework/zend-code/src/Scanner/ -> MethodScanner.php (source)

   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-2016 Zend Technologies USA Inc. (http://www.zend.com)
   7   * @license   http://framework.zend.com/license/new-bsd New BSD License
   8   */
   9  
  10  namespace Zend\Code\Scanner;
  11  
  12  use Zend\Code\Annotation\AnnotationManager;
  13  use Zend\Code\Exception;
  14  use Zend\Code\NameInformation;
  15  
  16  use function array_slice;
  17  use function count;
  18  use function is_int;
  19  use function is_string;
  20  use function ltrim;
  21  use function strtolower;
  22  use function substr_count;
  23  use function var_export;
  24  
  25  class MethodScanner implements ScannerInterface
  26  {
  27      /**
  28       * @var bool
  29       */
  30      protected $isScanned = false;
  31  
  32      /**
  33       * @var string
  34       */
  35      protected $docComment;
  36  
  37      /**
  38       * @var ClassScanner
  39       */
  40      protected $scannerClass;
  41  
  42      /**
  43       * @var string
  44       */
  45      protected $class;
  46  
  47      /**
  48       * @var string
  49       */
  50      protected $name;
  51  
  52      /**
  53       * @var int
  54       */
  55      protected $lineStart;
  56  
  57      /**
  58       * @var int
  59       */
  60      protected $lineEnd;
  61  
  62      /**
  63       * @var bool
  64       */
  65      protected $isFinal = false;
  66  
  67      /**
  68       * @var bool
  69       */
  70      protected $isAbstract = false;
  71  
  72      /**
  73       * @var bool
  74       */
  75      protected $isPublic = true;
  76  
  77      /**
  78       * @var bool
  79       */
  80      protected $isProtected = false;
  81  
  82      /**
  83       * @var bool
  84       */
  85      protected $isPrivate = false;
  86  
  87      /**
  88       * @var bool
  89       */
  90      protected $isStatic = false;
  91  
  92      /**
  93       * @var string
  94       */
  95      protected $body = '';
  96  
  97      /**
  98       * @var array
  99       */
 100      protected $tokens = [];
 101  
 102      /**
 103       * @var NameInformation
 104       */
 105      protected $nameInformation;
 106  
 107      /**
 108       * @var array
 109       */
 110      protected $infos = [];
 111  
 112      /**
 113       * @param  array $methodTokens
 114       * @param NameInformation $nameInformation
 115       */
 116      public function __construct(array $methodTokens, NameInformation $nameInformation = null)
 117      {
 118          $this->tokens          = $methodTokens;
 119          $this->nameInformation = $nameInformation;
 120      }
 121  
 122      /**
 123       * @param  string $class
 124       * @return MethodScanner
 125       */
 126      public function setClass($class)
 127      {
 128          $this->class = (string) $class;
 129          return $this;
 130      }
 131  
 132      /**
 133       * @param  ClassScanner  $scannerClass
 134       * @return MethodScanner
 135       */
 136      public function setScannerClass(ClassScanner $scannerClass)
 137      {
 138          $this->scannerClass = $scannerClass;
 139          return $this;
 140      }
 141  
 142      /**
 143       * @return ClassScanner
 144       */
 145      public function getClassScanner()
 146      {
 147          return $this->scannerClass;
 148      }
 149  
 150      /**
 151       * @return string
 152       */
 153      public function getName()
 154      {
 155          $this->scan();
 156  
 157          return $this->name;
 158      }
 159  
 160      /**
 161       * @return int
 162       */
 163      public function getLineStart()
 164      {
 165          $this->scan();
 166  
 167          return $this->lineStart;
 168      }
 169  
 170      /**
 171       * @return int
 172       */
 173      public function getLineEnd()
 174      {
 175          $this->scan();
 176  
 177          return $this->lineEnd;
 178      }
 179  
 180      /**
 181       * @return string
 182       */
 183      public function getDocComment()
 184      {
 185          $this->scan();
 186  
 187          return $this->docComment;
 188      }
 189  
 190      /**
 191       * @param  AnnotationManager $annotationManager
 192       * @return AnnotationScanner|false
 193       */
 194      public function getAnnotations(AnnotationManager $annotationManager)
 195      {
 196          if (($docComment = $this->getDocComment()) == '') {
 197              return false;
 198          }
 199  
 200          return new AnnotationScanner($annotationManager, $docComment, $this->nameInformation);
 201      }
 202  
 203      /**
 204       * @return bool
 205       */
 206      public function isFinal()
 207      {
 208          $this->scan();
 209  
 210          return $this->isFinal;
 211      }
 212  
 213      /**
 214       * @return bool
 215       */
 216      public function isAbstract()
 217      {
 218          $this->scan();
 219  
 220          return $this->isAbstract;
 221      }
 222  
 223      /**
 224       * @return bool
 225       */
 226      public function isPublic()
 227      {
 228          $this->scan();
 229  
 230          return $this->isPublic;
 231      }
 232  
 233      /**
 234       * @return bool
 235       */
 236      public function isProtected()
 237      {
 238          $this->scan();
 239  
 240          return $this->isProtected;
 241      }
 242  
 243      /**
 244       * @return bool
 245       */
 246      public function isPrivate()
 247      {
 248          $this->scan();
 249  
 250          return $this->isPrivate;
 251      }
 252  
 253      /**
 254       * @return bool
 255       */
 256      public function isStatic()
 257      {
 258          $this->scan();
 259  
 260          return $this->isStatic;
 261      }
 262  
 263      /**
 264       * Override the given name for a method, this is necessary to
 265       * support traits.
 266       *
 267       * @param string $name
 268       * @return self
 269       */
 270      public function setName($name)
 271      {
 272          $this->name = $name;
 273          return $this;
 274      }
 275  
 276      /**
 277       * Visibility must be of T_PUBLIC, T_PRIVATE or T_PROTECTED
 278       * Needed to support traits
 279       *
 280       * @param int $visibility   T_PUBLIC | T_PRIVATE | T_PROTECTED
 281       * @return self
 282       * @throws \Zend\Code\Exception\InvalidArgumentException
 283       */
 284      public function setVisibility($visibility)
 285      {
 286          switch ($visibility) {
 287              case T_PUBLIC:
 288                  $this->isPublic = true;
 289                  $this->isPrivate = false;
 290                  $this->isProtected = false;
 291                  break;
 292  
 293              case T_PRIVATE:
 294                  $this->isPublic = false;
 295                  $this->isPrivate = true;
 296                  $this->isProtected = false;
 297                  break;
 298  
 299              case T_PROTECTED:
 300                  $this->isPublic = false;
 301                  $this->isPrivate = false;
 302                  $this->isProtected = true;
 303                  break;
 304  
 305              default:
 306                  throw new Exception\InvalidArgumentException('Invalid visibility argument passed to setVisibility.');
 307          }
 308  
 309          return $this;
 310      }
 311  
 312      /**
 313       * @return int
 314       */
 315      public function getNumberOfParameters()
 316      {
 317          return count($this->getParameters());
 318      }
 319  
 320      /**
 321       * @param  bool $returnScanner
 322       * @return array
 323       */
 324      public function getParameters($returnScanner = false)
 325      {
 326          $this->scan();
 327  
 328          $return = [];
 329  
 330          foreach ($this->infos as $info) {
 331              if ($info['type'] != 'parameter') {
 332                  continue;
 333              }
 334  
 335              if (! $returnScanner) {
 336                  $return[] = $info['name'];
 337              } else {
 338                  $return[] = $this->getParameter($info['name']);
 339              }
 340          }
 341  
 342          return $return;
 343      }
 344  
 345      /**
 346       * @param  int|string $parameterNameOrInfoIndex
 347       * @return ParameterScanner
 348       * @throws Exception\InvalidArgumentException
 349       */
 350      public function getParameter($parameterNameOrInfoIndex)
 351      {
 352          $this->scan();
 353  
 354          if (is_int($parameterNameOrInfoIndex)) {
 355              $info = $this->infos[$parameterNameOrInfoIndex];
 356              if ($info['type'] != 'parameter') {
 357                  throw new Exception\InvalidArgumentException('Index of info offset is not about a parameter');
 358              }
 359          } elseif (is_string($parameterNameOrInfoIndex)) {
 360              foreach ($this->infos as $info) {
 361                  if ($info['type'] === 'parameter' && $info['name'] === $parameterNameOrInfoIndex) {
 362                      break;
 363                  }
 364                  unset($info);
 365              }
 366              if (! isset($info)) {
 367                  throw new Exception\InvalidArgumentException('Index of info offset is not about a parameter');
 368              }
 369          }
 370  
 371          $p = new ParameterScanner(
 372              array_slice($this->tokens, $info['tokenStart'], $info['tokenEnd'] - $info['tokenStart']),
 373              $this->nameInformation
 374          );
 375          $p->setDeclaringFunction($this->name);
 376          $p->setDeclaringScannerFunction($this);
 377          $p->setDeclaringClass($this->class);
 378          $p->setDeclaringScannerClass($this->scannerClass);
 379          $p->setPosition($info['position']);
 380  
 381          return $p;
 382      }
 383  
 384      /**
 385       * @return string
 386       */
 387      public function getBody()
 388      {
 389          $this->scan();
 390  
 391          return $this->body;
 392      }
 393  
 394      public static function export()
 395      {
 396          // @todo
 397      }
 398  
 399      public function __toString()
 400      {
 401          $this->scan();
 402  
 403          return var_export($this, true);
 404      }
 405  
 406      protected function scan()
 407      {
 408          if ($this->isScanned) {
 409              return;
 410          }
 411  
 412          if (! $this->tokens) {
 413              throw new Exception\RuntimeException('No tokens were provided');
 414          }
 415  
 416          /**
 417           * Variables & Setup
 418           */
 419          $tokens       = &$this->tokens; // localize
 420          $infos        = &$this->infos; // localize
 421          $tokenIndex   = null;
 422          $token        = null;
 423          $tokenType    = null;
 424          $tokenContent = null;
 425          $tokenLine    = null;
 426          $infoIndex    = 0;
 427          $parentCount  = 0;
 428  
 429          /*
 430           * MACRO creation
 431           */
 432          $MACRO_TOKEN_ADVANCE = function () use (
 433              &$tokens,
 434              &$tokenIndex,
 435              &$token,
 436              &$tokenType,
 437              &$tokenContent,
 438              &$tokenLine
 439          ) {
 440              static $lastTokenArray = null;
 441              $tokenIndex = $tokenIndex === null ? 0 : $tokenIndex + 1;
 442              if (! isset($tokens[$tokenIndex])) {
 443                  $token        = false;
 444                  $tokenContent = false;
 445                  $tokenType    = false;
 446                  $tokenLine    = false;
 447  
 448                  return false;
 449              }
 450              $token = $tokens[$tokenIndex];
 451              if (is_string($token)) {
 452                  $tokenType    = null;
 453                  $tokenContent = $token;
 454                  $tokenLine   += substr_count(
 455                      $lastTokenArray[1] ?? '',
 456                      "\n"
 457                  ); // adjust token line by last known newline count
 458              } else {
 459                  $lastTokenArray = $token;
 460                  [$tokenType, $tokenContent, $tokenLine] = $token;
 461              }
 462  
 463              return $tokenIndex;
 464          };
 465          $MACRO_INFO_START    = function () use (&$infoIndex, &$infos, &$tokenIndex, &$tokenLine) {
 466              $infos[$infoIndex] = [
 467                  'type'        => 'parameter',
 468                  'tokenStart'  => $tokenIndex,
 469                  'tokenEnd'    => null,
 470                  'lineStart'   => $tokenLine,
 471                  'lineEnd'     => $tokenLine,
 472                  'name'        => null,
 473                  'position'    => $infoIndex + 1, // position is +1 of infoIndex
 474              ];
 475          };
 476          $MACRO_INFO_ADVANCE  = function () use (&$infoIndex, &$infos, &$tokenIndex, &$tokenLine) {
 477              $infos[$infoIndex]['tokenEnd'] = $tokenIndex;
 478              $infos[$infoIndex]['lineEnd']  = $tokenLine;
 479              $infoIndex++;
 480  
 481              return $infoIndex;
 482          };
 483  
 484          /**
 485           * START FINITE STATE MACHINE FOR SCANNING TOKENS
 486           */
 487          // Initialize token
 488          $MACRO_TOKEN_ADVANCE();
 489  
 490          SCANNER_TOP:
 491  
 492          $this->lineStart = $this->lineStart ? : $tokenLine;
 493  
 494          switch ($tokenType) {
 495              case T_DOC_COMMENT:
 496                  $this->lineStart = null;
 497                  if ($this->docComment === null && $this->name === null) {
 498                      $this->docComment = $tokenContent;
 499                  }
 500                  goto SCANNER_CONTINUE_SIGNATURE;
 501                  // goto (no break needed);
 502  
 503              case T_FINAL:
 504                  $this->isFinal = true;
 505                  goto SCANNER_CONTINUE_SIGNATURE;
 506                  // goto (no break needed);
 507  
 508              case T_ABSTRACT:
 509                  $this->isAbstract = true;
 510                  goto SCANNER_CONTINUE_SIGNATURE;
 511                  // goto (no break needed);
 512  
 513              case T_PUBLIC:
 514                  // use defaults
 515                  goto SCANNER_CONTINUE_SIGNATURE;
 516                  // goto (no break needed);
 517  
 518              case T_PROTECTED:
 519                  $this->setVisibility(T_PROTECTED);
 520                  goto SCANNER_CONTINUE_SIGNATURE;
 521                  // goto (no break needed);
 522  
 523              case T_PRIVATE:
 524                  $this->setVisibility(T_PRIVATE);
 525                  goto SCANNER_CONTINUE_SIGNATURE;
 526                  // goto (no break needed);
 527  
 528              case T_STATIC:
 529                  $this->isStatic = true;
 530                  goto SCANNER_CONTINUE_SIGNATURE;
 531                  // goto (no break needed);
 532  
 533              case T_NS_SEPARATOR:
 534                  if (! isset($infos[$infoIndex])) {
 535                      $MACRO_INFO_START();
 536                  }
 537                  goto SCANNER_CONTINUE_SIGNATURE;
 538                  // goto (no break needed);
 539  
 540              case T_VARIABLE:
 541              case T_STRING:
 542                  if ($tokenType === T_STRING && $parentCount === 0) {
 543                      $this->name = $tokenContent;
 544                  }
 545  
 546                  if ($parentCount === 1) {
 547                      if (! isset($infos[$infoIndex])) {
 548                          $MACRO_INFO_START();
 549                      }
 550                      if ($tokenType === T_VARIABLE) {
 551                          $infos[$infoIndex]['name'] = ltrim($tokenContent, '$');
 552                      }
 553                  }
 554  
 555                  goto SCANNER_CONTINUE_SIGNATURE;
 556                  // goto (no break needed);
 557  
 558              case null:
 559                  switch ($tokenContent) {
 560                      case '&':
 561                          if (! isset($infos[$infoIndex])) {
 562                              $MACRO_INFO_START();
 563                          }
 564                          goto SCANNER_CONTINUE_SIGNATURE;
 565                          // goto (no break needed);
 566                      case '(':
 567                          $parentCount++;
 568                          goto SCANNER_CONTINUE_SIGNATURE;
 569                          // goto (no break needed);
 570                      case ')':
 571                          $parentCount--;
 572                          if ($parentCount > 0) {
 573                              goto SCANNER_CONTINUE_SIGNATURE;
 574                          }
 575                          if ($parentCount === 0) {
 576                              if ($infos) {
 577                                  $MACRO_INFO_ADVANCE();
 578                              }
 579                              $context = 'body';
 580                          }
 581                          goto SCANNER_CONTINUE_BODY;
 582                          // goto (no break needed);
 583                      case ',':
 584                          if ($parentCount === 1) {
 585                              $MACRO_INFO_ADVANCE();
 586                          }
 587                          goto SCANNER_CONTINUE_SIGNATURE;
 588                  }
 589          }
 590  
 591          SCANNER_CONTINUE_SIGNATURE:
 592  
 593          if ($MACRO_TOKEN_ADVANCE() === false) {
 594              goto SCANNER_END;
 595          }
 596          goto SCANNER_TOP;
 597  
 598          SCANNER_CONTINUE_BODY:
 599  
 600          $braceCount = 0;
 601          while ($MACRO_TOKEN_ADVANCE() !== false) {
 602              if ($tokenContent == '}') {
 603                  $braceCount--;
 604              }
 605              if ($braceCount > 0) {
 606                  $this->body .= $tokenContent;
 607              }
 608              if ($tokenContent == '{') {
 609                  $braceCount++;
 610              }
 611              $this->lineEnd = $tokenLine;
 612          }
 613  
 614          SCANNER_END:
 615  
 616          $this->isScanned = true;
 617      }
 618  }


Generated: Wed Nov 11 20:28:18 2020 Cross-referenced by PHPXref 0.7.1