[ Index ] |
PHP Cross Reference of phpBB-3.3.14-deutsch |
[Summary view] [Print] [Text view]
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 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Mon Nov 25 19:05:08 2024 | Cross-referenced by PHPXref 0.7.1 |