[ Index ]

PHP Cross Reference of phpBB-3.3.14-deutsch

title

Body

[close]

/vendor/zendframework/zend-code/src/Scanner/ -> AnnotationScanner.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\AnnotationCollection;
  13  use Zend\Code\Annotation\AnnotationManager;
  14  use Zend\Code\NameInformation;
  15  
  16  use function array_pop;
  17  use function current;
  18  use function in_array;
  19  use function is_string;
  20  use function next;
  21  use function preg_match;
  22  use function reset;
  23  use function strlen;
  24  use function strpos;
  25  use function substr;
  26  use function substr_count;
  27  
  28  class AnnotationScanner extends AnnotationCollection implements ScannerInterface
  29  {
  30      /**
  31       * @var bool
  32       */
  33      protected $isScanned = false;
  34  
  35      /**
  36       * @var string
  37       */
  38      protected $docComment;
  39  
  40      /**
  41       * @var NameInformation
  42       */
  43      protected $nameInformation;
  44  
  45      /**
  46       * @var AnnotationManager
  47       */
  48      protected $annotationManager;
  49  
  50      /**
  51       * @var array
  52       */
  53      protected $annotations = [];
  54  
  55      /**
  56       * @param  AnnotationManager $annotationManager
  57       * @param  string $docComment
  58       * @param  NameInformation $nameInformation
  59       * @return AnnotationScanner
  60       */
  61      public function __construct(
  62          AnnotationManager $annotationManager,
  63          $docComment,
  64          NameInformation $nameInformation = null
  65      ) {
  66          $this->annotationManager = $annotationManager;
  67          $this->docComment        = $docComment;
  68          $this->nameInformation   = $nameInformation;
  69          $this->scan($this->tokenize());
  70      }
  71  
  72      /**
  73       * @param NameInformation $nameInformation
  74       */
  75      public function setNameInformation(NameInformation $nameInformation)
  76      {
  77          $this->nameInformation = $nameInformation;
  78      }
  79  
  80      /**
  81       * @param  array $tokens
  82       */
  83      protected function scan(array $tokens)
  84      {
  85          $annotations     = [];
  86          $annotationIndex = -1;
  87          $contentEnd      = false;
  88  
  89          reset($tokens);
  90  
  91          SCANNER_TOP:
  92          $token = current($tokens);
  93  
  94          switch ($token[0]) {
  95              case 'ANNOTATION_CLASS':
  96                  $contentEnd = false;
  97                  $annotationIndex++;
  98                  $class                         = substr($token[1], 1);
  99                  $class                         = $this->nameInformation->resolveName($class);
 100                  $annotations[$annotationIndex] = [$class, null];
 101                  goto SCANNER_CONTINUE;
 102                  // goto no break needed
 103  
 104              case 'ANNOTATION_CONTENT_START':
 105                  $annotations[$annotationIndex][1] = '';
 106                  // fall-through
 107  
 108              case 'ANNOTATION_CONTENT_END':
 109              case 'ANNOTATION_CONTENT':
 110              case 'ANNOTATION_WHITESPACE':
 111              case 'ANNOTATION_NEWLINE':
 112                  if (! $contentEnd
 113                      && isset($annotations[$annotationIndex])
 114                      && is_string($annotations[$annotationIndex][1])
 115                  ) {
 116                      $annotations[$annotationIndex][1] .= $token[1];
 117                  }
 118  
 119                  if ($token[0] === 'ANNOTATION_CONTENT_END') {
 120                      $contentEnd = true;
 121                  }
 122  
 123                  goto SCANNER_CONTINUE;
 124                  // goto no break needed
 125          }
 126  
 127          SCANNER_CONTINUE:
 128          if (next($tokens) === false) {
 129              goto SCANNER_END;
 130          }
 131          goto SCANNER_TOP;
 132  
 133          SCANNER_END:
 134  
 135          foreach ($annotations as $annotation) {
 136              $annotation[]     = '@' . $annotation[0] . $annotation[1];
 137              $annotationObject = $this->annotationManager->createAnnotation($annotation);
 138              if ($annotationObject) {
 139                  $this->append($annotationObject);
 140              }
 141          }
 142      }
 143  
 144      /**
 145       * @return array
 146       */
 147      protected function tokenize()
 148      {
 149          static $CONTEXT_DOCBLOCK = 0x01;
 150          static $CONTEXT_ASTERISK = 0x02;
 151          static $CONTEXT_CLASS = 0x04;
 152          static $CONTEXT_CONTENT = 0x08;
 153  
 154          $context     = 0x00;
 155          $stream      = $this->docComment;
 156          $streamIndex = null;
 157          $tokens      = [];
 158          $tokenIndex  = null;
 159          $currentChar = null;
 160          $currentWord = null;
 161          $currentLine = null;
 162  
 163          $annotationParentCount = 0;
 164  
 165          $MACRO_STREAM_ADVANCE_CHAR = function ($positionsForward = 1) use (
 166              &$stream,
 167              &$streamIndex,
 168              &$currentChar,
 169              &$currentWord,
 170              &$currentLine
 171          ) {
 172              $positionsForward = $positionsForward > 0 ? $positionsForward : 1;
 173              $streamIndex      = $streamIndex === null ? 0 : $streamIndex + $positionsForward;
 174              if (! isset($stream[$streamIndex])) {
 175                  $currentChar = false;
 176  
 177                  return false;
 178              }
 179              $currentChar = $stream[$streamIndex];
 180              $matches     = [];
 181              $currentLine = preg_match('#(.*?)(?:\n|\r\n?)#', $stream, $matches, null, $streamIndex) === 1
 182                  ? $matches[1]
 183                  : substr($stream, $streamIndex);
 184              if ($currentChar === ' ') {
 185                  $currentWord = preg_match('#( +)#', $currentLine, $matches) === 1 ? $matches[1] : $currentLine;
 186              } else {
 187                  $currentWord = ($matches = strpos($currentLine, ' ')) !== false
 188                      ? substr($currentLine, 0, $matches)
 189                      : $currentLine;
 190              }
 191  
 192              return $currentChar;
 193          };
 194          $MACRO_STREAM_ADVANCE_WORD = function () use (&$currentWord, &$MACRO_STREAM_ADVANCE_CHAR) {
 195              return $MACRO_STREAM_ADVANCE_CHAR(strlen($currentWord));
 196          };
 197          $MACRO_STREAM_ADVANCE_LINE = function () use (&$currentLine, &$MACRO_STREAM_ADVANCE_CHAR) {
 198              return $MACRO_STREAM_ADVANCE_CHAR(strlen($currentLine));
 199          };
 200          $MACRO_TOKEN_ADVANCE       = function () use (&$tokenIndex, &$tokens) {
 201              $tokenIndex          = $tokenIndex === null ? 0 : $tokenIndex + 1;
 202              $tokens[$tokenIndex] = ['ANNOTATION_UNKNOWN', ''];
 203          };
 204          $MACRO_TOKEN_SET_TYPE      = function ($type) use (&$tokenIndex, &$tokens) {
 205              $tokens[$tokenIndex][0] = $type;
 206          };
 207          $MACRO_TOKEN_APPEND_CHAR   = function () use (&$currentChar, &$tokens, &$tokenIndex) {
 208              $tokens[$tokenIndex][1] .= $currentChar;
 209          };
 210          $MACRO_TOKEN_APPEND_WORD   = function () use (&$currentWord, &$tokens, &$tokenIndex) {
 211              $tokens[$tokenIndex][1] .= $currentWord;
 212          };
 213          $MACRO_TOKEN_APPEND_LINE   = function () use (&$currentLine, &$tokens, &$tokenIndex) {
 214              $tokens[$tokenIndex][1] .= $currentLine;
 215          };
 216          $MACRO_HAS_CONTEXT         = function ($which) use (&$context) {
 217              return ($context & $which) === $which;
 218          };
 219  
 220          $MACRO_STREAM_ADVANCE_CHAR();
 221          $MACRO_TOKEN_ADVANCE();
 222  
 223          TOKENIZER_TOP:
 224  
 225          if ($context === 0x00 && $currentChar === '/' && $currentWord === '/**') {
 226              $MACRO_TOKEN_SET_TYPE('ANNOTATION_COMMENTSTART');
 227              $MACRO_TOKEN_APPEND_WORD();
 228              $MACRO_TOKEN_ADVANCE();
 229              $context |= $CONTEXT_DOCBLOCK;
 230              $context |= $CONTEXT_ASTERISK;
 231              if ($MACRO_STREAM_ADVANCE_WORD() === false) {
 232                  goto TOKENIZER_END;
 233              }
 234              goto TOKENIZER_TOP;
 235          }
 236  
 237          if ($MACRO_HAS_CONTEXT($CONTEXT_CLASS)) {
 238              if (in_array($currentChar, [' ', '(', "\n", "\r"])) {
 239                  $context &= ~$CONTEXT_CLASS;
 240                  $MACRO_TOKEN_ADVANCE();
 241              } else {
 242                  $MACRO_TOKEN_APPEND_CHAR();
 243                  if ($MACRO_STREAM_ADVANCE_CHAR() === false) {
 244                      goto TOKENIZER_END;
 245                  }
 246                  goto TOKENIZER_TOP;
 247              }
 248          }
 249  
 250          // Since we don't know what line endings are used in the file, we check for all scenarios. If we find a
 251          // carriage return (\r), we check the next character for a line feed (\n). If so we consume it and act as
 252          // if the carriage return was a line feed.
 253          $lineEnded = $currentChar === "\n";
 254          if ($currentChar === "\r") {
 255              $lineEnded = true;
 256  
 257              $nextChar = $MACRO_STREAM_ADVANCE_CHAR();
 258              if ($nextChar !== "\n") {
 259                  $streamIndex--;
 260              }
 261  
 262              $currentChar = "\n";
 263          }
 264  
 265          if ($lineEnded) {
 266              $MACRO_TOKEN_SET_TYPE('ANNOTATION_NEWLINE');
 267              $MACRO_TOKEN_APPEND_CHAR();
 268              $MACRO_TOKEN_ADVANCE();
 269              $context &= ~$CONTEXT_ASTERISK;
 270              $context &= ~$CONTEXT_CLASS;
 271              if ($MACRO_STREAM_ADVANCE_CHAR() === false) {
 272                  goto TOKENIZER_END;
 273              }
 274              goto TOKENIZER_TOP;
 275          }
 276  
 277          if ($currentChar === ' ') {
 278              $MACRO_TOKEN_SET_TYPE(
 279                  $MACRO_HAS_CONTEXT($CONTEXT_ASTERISK)
 280                  ? 'ANNOTATION_WHITESPACE'
 281                  : 'ANNOTATION_WHITESPACE_INDENT'
 282              );
 283              $MACRO_TOKEN_APPEND_WORD();
 284              $MACRO_TOKEN_ADVANCE();
 285              if ($MACRO_STREAM_ADVANCE_WORD() === false) {
 286                  goto TOKENIZER_END;
 287              }
 288              goto TOKENIZER_TOP;
 289          }
 290  
 291          if ($MACRO_HAS_CONTEXT($CONTEXT_CONTENT) && $MACRO_HAS_CONTEXT($CONTEXT_ASTERISK)) {
 292              $MACRO_TOKEN_SET_TYPE('ANNOTATION_CONTENT');
 293              $annotationParentCount += substr_count($currentWord, '(');
 294              $annotationParentCount -= substr_count($currentWord, ')');
 295  
 296              if ($annotationParentCount === 0) {
 297                  $context &= ~$CONTEXT_CONTENT;
 298                  $MACRO_TOKEN_SET_TYPE('ANNOTATION_CONTENT_END');
 299              }
 300              $MACRO_TOKEN_APPEND_WORD();
 301              $MACRO_TOKEN_ADVANCE();
 302              if ($MACRO_STREAM_ADVANCE_WORD() === false) {
 303                  goto TOKENIZER_END;
 304              }
 305              goto TOKENIZER_TOP;
 306          }
 307  
 308          if ($currentChar === '(' && $tokens[$tokenIndex - 1][0] === 'ANNOTATION_CLASS') {
 309              $context |= $CONTEXT_CONTENT;
 310              $annotationParentCount = 1;
 311              $MACRO_TOKEN_SET_TYPE('ANNOTATION_CONTENT_START');
 312              $MACRO_TOKEN_APPEND_CHAR();
 313              $MACRO_TOKEN_ADVANCE();
 314              if ($MACRO_STREAM_ADVANCE_CHAR() === false) {
 315                  goto TOKENIZER_END;
 316              }
 317              goto TOKENIZER_TOP;
 318          }
 319  
 320          if ($MACRO_HAS_CONTEXT($CONTEXT_DOCBLOCK) && $currentWord === '*/') {
 321              $MACRO_TOKEN_SET_TYPE('ANNOTATION_COMMENTEND');
 322              $MACRO_TOKEN_APPEND_WORD();
 323              $MACRO_TOKEN_ADVANCE();
 324              $context &= ~$CONTEXT_DOCBLOCK;
 325              if ($MACRO_STREAM_ADVANCE_WORD() === false) {
 326                  goto TOKENIZER_END;
 327              }
 328              goto TOKENIZER_TOP;
 329          }
 330  
 331          if ($currentChar === '*') {
 332              if ($MACRO_HAS_CONTEXT($CONTEXT_DOCBLOCK) && ($MACRO_HAS_CONTEXT($CONTEXT_ASTERISK))) {
 333                  $MACRO_TOKEN_SET_TYPE('ANNOTATION_IGNORE');
 334              } else {
 335                  $MACRO_TOKEN_SET_TYPE('ANNOTATION_ASTERISK');
 336                  $context |= $CONTEXT_ASTERISK;
 337              }
 338              $MACRO_TOKEN_APPEND_CHAR();
 339              $MACRO_TOKEN_ADVANCE();
 340              if ($MACRO_STREAM_ADVANCE_CHAR() === false) {
 341                  goto TOKENIZER_END;
 342              }
 343              goto TOKENIZER_TOP;
 344          }
 345  
 346          if ($currentChar === '@') {
 347              $MACRO_TOKEN_SET_TYPE('ANNOTATION_CLASS');
 348              $context |= $CONTEXT_CLASS;
 349              $MACRO_TOKEN_APPEND_CHAR();
 350              if ($MACRO_STREAM_ADVANCE_CHAR() === false) {
 351                  goto TOKENIZER_END;
 352              }
 353              goto TOKENIZER_TOP;
 354          }
 355  
 356          TOKENIZER_CONTINUE:
 357  
 358          if ($context && $CONTEXT_CONTENT) {
 359              $MACRO_TOKEN_APPEND_CHAR();
 360              if ($MACRO_STREAM_ADVANCE_CHAR() === false) {
 361                  goto TOKENIZER_END;
 362              }
 363          } else {
 364              $MACRO_TOKEN_SET_TYPE('ANNOTATION_IGNORE');
 365              $MACRO_TOKEN_APPEND_LINE();
 366              $MACRO_TOKEN_ADVANCE();
 367              if ($MACRO_STREAM_ADVANCE_LINE() === false) {
 368                  goto TOKENIZER_END;
 369              }
 370          }
 371          goto TOKENIZER_TOP;
 372  
 373          TOKENIZER_END:
 374  
 375          array_pop($tokens);
 376  
 377          return $tokens;
 378      }
 379  }


Generated: Mon Nov 25 19:05:08 2024 Cross-referenced by PHPXref 0.7.1