[ Index ]

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


Generated: Wed Nov 11 20:33:01 2020 Cross-referenced by PHPXref 0.7.1