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.
Auf den Verzeichnisnamen klicken, dies zeigt nur das Verzeichnis mit Inhalt an

(Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

MethodScanner.php

Zuletzt modifiziert: 02.04.2025, 15:03 - Dateigröße: 14.67 KiB


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