Verzeichnisstruktur phpBB-3.3.15
- Veröffentlicht
- 28.08.2024
So funktioniert es
|
Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück |
Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis. |
|
(Beispiel Datei-Icons)
|
Auf das Icon klicken um den Quellcode anzuzeigen |
MethodScanner.php
001 <?php
002 /**
003 * Zend Framework (http://framework.zend.com/)
004 *
005 * @link http://github.com/zendframework/zf2 for the canonical source repository
006 * @copyright Copyright (c) 2005-2016 Zend Technologies USA Inc. (http://www.zend.com)
007 * @license http://framework.zend.com/license/new-bsd New BSD License
008 */
009
010 namespace Zend\Code\Scanner;
011
012 use Zend\Code\Annotation\AnnotationManager;
013 use Zend\Code\Exception;
014 use Zend\Code\NameInformation;
015
016 use function array_slice;
017 use function count;
018 use function is_int;
019 use function is_string;
020 use function ltrim;
021 use function strtolower;
022 use function substr_count;
023 use function var_export;
024
025 class MethodScanner implements ScannerInterface
026 {
027 /**
028 * @var bool
029 */
030 protected $isScanned = false;
031
032 /**
033 * @var string
034 */
035 protected $docComment;
036
037 /**
038 * @var ClassScanner
039 */
040 protected $scannerClass;
041
042 /**
043 * @var string
044 */
045 protected $class;
046
047 /**
048 * @var string
049 */
050 protected $name;
051
052 /**
053 * @var int
054 */
055 protected $lineStart;
056
057 /**
058 * @var int
059 */
060 protected $lineEnd;
061
062 /**
063 * @var bool
064 */
065 protected $isFinal = false;
066
067 /**
068 * @var bool
069 */
070 protected $isAbstract = false;
071
072 /**
073 * @var bool
074 */
075 protected $isPublic = true;
076
077 /**
078 * @var bool
079 */
080 protected $isProtected = false;
081
082 /**
083 * @var bool
084 */
085 protected $isPrivate = false;
086
087 /**
088 * @var bool
089 */
090 protected $isStatic = false;
091
092 /**
093 * @var string
094 */
095 protected $body = '';
096
097 /**
098 * @var array
099 */
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 }
619