Example #1
0
    protected function scan(array $tokens)
    {
        $annotations     = array();
        $annotationIndex = -1;
        $contentEnd      = false;

        reset($tokens);

        SCANNER_TOP:
        $token = current($tokens);

        switch ($token[0]) {

            case 'ANNOTATION_CLASS':

                $contentEnd = false;
                $annotationIndex++;
                $class                         = substr($token[1], 1);
                $class                         = $this->nameInformation->resolveName($class);
                $annotations[$annotationIndex] = array($class, null);
                goto SCANNER_CONTINUE;

            case 'ANNOTATION_CONTENT_START':

                $annotations[$annotationIndex][1] = '';

            case 'ANNOTATION_CONTENT_END':
            case 'ANNOTATION_CONTENT':
            case 'ANNOTATION_WHITESPACE':
            case 'ANNOTATION_NEWLINE':

                if (!$contentEnd && isset($annotations[$annotationIndex]) && is_string($annotations[$annotationIndex][1])) {
                    $annotations[$annotationIndex][1] .= $token[1];
                }

                if ($token[0] === 'ANNOTATION_CONTENT_END') {
                    $contentEnd = true;
                }

                goto SCANNER_CONTINUE;
        }

        SCANNER_CONTINUE:
        if (next($tokens) === false) {
            goto SCANNER_END;
        }
        goto SCANNER_TOP;

        SCANNER_END:

        foreach ($annotations as $annotation) {
            if ($this->annotationManager->hasAnnotation($annotation[0])) {
                $this->append(
                    $this->annotationManager->createAnnotation($annotation[0], trim($annotation[1], '()'))
                );
            }
        }
    }
 public function testScannerWorks()
 {
     $annotationManager = new AnnotationManager(array($foo = new TestAsset\Annotation\Foo(), $bar = new TestAsset\Annotation\Bar()));
     $docComment = '/**' . "\n" . ' * @Test\\Foo(\'anything I want()' . "\n" . ' * to be\')' . "\n" . ' * @Test\\Bar' . "\n */";
     $nameInfo = new NameInformation();
     $nameInfo->addUse('ZendTest\\Code\\Scanner\\TestAsset\\Annotation', 'Test');
     $annotationScanner = new AnnotationScanner($annotationManager, $docComment, $nameInfo);
     $this->assertEquals(get_class($foo), get_class($annotationScanner[0]));
     $this->assertEquals("'anything I want()\n to be'", $annotationScanner[0]->getContent());
     $this->assertEquals(get_class($bar), get_class($annotationScanner[1]));
 }
 /**
  * @param  array $tokens
  */
 protected function scan(array $tokens)
 {
     $annotations = [];
     $annotationIndex = -1;
     $contentEnd = false;
     reset($tokens);
     SCANNER_TOP:
     $token = current($tokens);
     switch ($token[0]) {
         case 'ANNOTATION_CLASS':
             $contentEnd = false;
             $annotationIndex++;
             $class = substr($token[1], 1);
             $class = $this->nameInformation->resolveName($class);
             $annotations[$annotationIndex] = [$class, null];
             goto SCANNER_CONTINUE;
             // goto no break needed
         // goto no break needed
         case 'ANNOTATION_CONTENT_START':
             $annotations[$annotationIndex][1] = '';
             // fall-through
         // fall-through
         case 'ANNOTATION_CONTENT_END':
         case 'ANNOTATION_CONTENT':
         case 'ANNOTATION_WHITESPACE':
         case 'ANNOTATION_NEWLINE':
             if (!$contentEnd && isset($annotations[$annotationIndex]) && is_string($annotations[$annotationIndex][1])) {
                 $annotations[$annotationIndex][1] .= $token[1];
             }
             if ($token[0] === 'ANNOTATION_CONTENT_END') {
                 $contentEnd = true;
             }
             goto SCANNER_CONTINUE;
             // goto no break needed
     }
     SCANNER_CONTINUE:
     if (next($tokens) === false) {
         goto SCANNER_END;
     }
     goto SCANNER_TOP;
     SCANNER_END:
     foreach ($annotations as $annotation) {
         $annotation[] = '@' . $annotation[0] . $annotation[1];
         $annotationObject = $this->annotationManager->createAnnotation($annotation);
         if ($annotationObject) {
             $this->append($annotationObject);
         }
     }
 }
Example #4
0
 public function testNamespaceResolverCorrectlyResolvesNames()
 {
     $nr = new NameInformation();
     $nr->setNamespace('Zend\\MagicComponent');
     $nr->setUses(array('ArrayObject', 'Zend\\OtherMagicComponent\\Foo', 'Zend\\SuperMagic' => 'SM'));
     // test against namespace
     $this->assertEquals('Zend\\MagicComponent\\Bar', $nr->resolveName('Bar'));
     // test against uses
     $this->assertEquals('ArrayObject', $nr->resolveName('ArrayObject'));
     $this->assertEquals('ArrayObject', $nr->resolveName('\\ArrayObject'));
     $this->assertEquals('Zend\\OtherMagicComponent\\Foo', $nr->resolveName('Foo'));
     $this->assertEquals('Zend\\SuperMagic', $nr->resolveName('SM'));
     $this->assertEquals('Zend\\SuperMagic\\Bar', $nr->resolveName('SM\\Bar'));
 }
Example #5
0
 /**
  * Scan
  *
  * @return void
  */
 protected function scan()
 {
     if ($this->isScanned) {
         return;
     }
     $tokens =& $this->tokens;
     reset($tokens);
     SCANNER_TOP:
     $token = current($tokens);
     if (is_string($token)) {
         // check pass by ref
         if ($token === '&') {
             $this->isPassedByReference = true;
             goto SCANNER_CONTINUE;
         }
         if ($token === '=') {
             $this->isOptional = true;
             $this->isDefaultValueAvailable = true;
             goto SCANNER_CONTINUE;
         }
     } else {
         if ($this->name === null && ($token[0] === T_STRING || $token[0] === T_NS_SEPARATOR)) {
             $this->class .= $token[1];
             goto SCANNER_CONTINUE;
         }
         if ($token[0] === T_VARIABLE) {
             $this->name = ltrim($token[1], '$');
             goto SCANNER_CONTINUE;
         }
     }
     if ($this->name !== null) {
         $this->defaultValue .= is_string($token) ? $token : $token[1];
     }
     SCANNER_CONTINUE:
     if (next($this->tokens) === false) {
         goto SCANNER_END;
     }
     goto SCANNER_TOP;
     SCANNER_END:
     if ($this->class && $this->nameInformation) {
         $this->class = $this->nameInformation->resolveName($this->class);
     }
     $this->isScanned = true;
 }
Example #6
0
 /**
  * Scan tokens
  *
  * @return void
  * @throws Exception\RuntimeException
  */
 protected function scan()
 {
     if ($this->isScanned) {
         return;
     }
     if (!$this->tokens) {
         throw new Exception\RuntimeException('No tokens were provided');
     }
     /**
      * Variables & Setup
      */
     $tokens =& $this->tokens;
     // localize
     $infos =& $this->infos;
     // localize
     $tokenIndex = null;
     $token = null;
     $tokenType = null;
     $tokenContent = null;
     $tokenLine = null;
     $namespace = null;
     $infoIndex = 0;
     $braceCount = 0;
     /*
      * MACRO creation
      */
     $MACRO_TOKEN_ADVANCE = function () use(&$tokens, &$tokenIndex, &$token, &$tokenType, &$tokenContent, &$tokenLine) {
         static $lastTokenArray = null;
         $tokenIndex = $tokenIndex === null ? 0 : $tokenIndex + 1;
         if (!isset($tokens[$tokenIndex])) {
             $token = false;
             $tokenContent = false;
             $tokenType = false;
             $tokenLine = false;
             return false;
         }
         $token = $tokens[$tokenIndex];
         if (is_string($token)) {
             $tokenType = null;
             $tokenContent = $token;
             $tokenLine = $tokenLine + substr_count($lastTokenArray[1], "\n");
             // adjust token line by last known newline count
         } else {
             $lastTokenArray = $token;
             list($tokenType, $tokenContent, $tokenLine) = $token;
         }
         return $tokenIndex;
     };
     $MACRO_INFO_ADVANCE = function () use(&$infoIndex, &$infos, &$tokenIndex, &$tokenLine) {
         $infos[$infoIndex]['tokenEnd'] = $tokenIndex;
         $infos[$infoIndex]['lineEnd'] = $tokenLine;
         $infoIndex++;
         return $infoIndex;
     };
     /**
      * START FINITE STATE MACHINE FOR SCANNING TOKENS
      */
     // Initialize token
     $MACRO_TOKEN_ADVANCE();
     SCANNER_TOP:
     switch ($tokenType) {
         case T_DOC_COMMENT:
             $this->docComment = $tokenContent;
             goto SCANNER_CONTINUE;
             //goto no break needed
         //goto no break needed
         case T_FINAL:
         case T_ABSTRACT:
         case T_CLASS:
         case T_INTERFACE:
             // CLASS INFORMATION
             $classContext = null;
             $classInterfaceIndex = 0;
             SCANNER_CLASS_INFO_TOP:
             if (is_string($tokens[$tokenIndex + 1]) && $tokens[$tokenIndex + 1] === '{') {
                 goto SCANNER_CLASS_INFO_END;
             }
             $this->lineStart = $tokenLine;
             switch ($tokenType) {
                 case T_FINAL:
                     $this->isFinal = true;
                     goto SCANNER_CLASS_INFO_CONTINUE;
                     //goto no break needed
                 //goto no break needed
                 case T_ABSTRACT:
                     $this->isAbstract = true;
                     goto SCANNER_CLASS_INFO_CONTINUE;
                     //goto no break needed
                 //goto no break needed
                 case T_INTERFACE:
                     $this->isInterface = true;
                     //fall-through
                 //fall-through
                 case T_CLASS:
                     $this->shortName = $tokens[$tokenIndex + 2][1];
                     if ($this->nameInformation && $this->nameInformation->hasNamespace()) {
                         $this->name = $this->nameInformation->getNamespace() . '\\' . $this->shortName;
                     } else {
                         $this->name = $this->shortName;
                     }
                     goto SCANNER_CLASS_INFO_CONTINUE;
                     //goto no break needed
                 //goto no break needed
                 case T_NS_SEPARATOR:
                 case T_STRING:
                     switch ($classContext) {
                         case T_EXTENDS:
                             $this->shortParentClass .= $tokenContent;
                             break;
                         case T_IMPLEMENTS:
                             $this->shortInterfaces[$classInterfaceIndex] .= $tokenContent;
                             break;
                     }
                     goto SCANNER_CLASS_INFO_CONTINUE;
                     //goto no break needed
                 //goto no break needed
                 case T_EXTENDS:
                 case T_IMPLEMENTS:
                     $classContext = $tokenType;
                     if ($this->isInterface && $classContext === T_EXTENDS || $classContext === T_IMPLEMENTS) {
                         $this->shortInterfaces[$classInterfaceIndex] = '';
                     } elseif (!$this->isInterface && $classContext === T_EXTENDS) {
                         $this->shortParentClass = '';
                     }
                     goto SCANNER_CLASS_INFO_CONTINUE;
                     //goto no break needed
                 //goto no break needed
                 case null:
                     if ($classContext == T_IMPLEMENTS && $tokenContent == ',') {
                         $classInterfaceIndex++;
                         $this->shortInterfaces[$classInterfaceIndex] = '';
                     }
             }
             SCANNER_CLASS_INFO_CONTINUE:
             if ($MACRO_TOKEN_ADVANCE() === false) {
                 goto SCANNER_END;
             }
             goto SCANNER_CLASS_INFO_TOP;
             SCANNER_CLASS_INFO_END:
             goto SCANNER_CONTINUE;
     }
     if ($tokenType === null && $tokenContent === '{' && $braceCount === 0) {
         $braceCount++;
         if ($MACRO_TOKEN_ADVANCE() === false) {
             goto SCANNER_END;
         }
         SCANNER_CLASS_BODY_TOP:
         if ($braceCount === 0) {
             goto SCANNER_CLASS_BODY_END;
         }
         switch ($tokenType) {
             case T_CONST:
                 $infos[$infoIndex] = array('type' => 'constant', 'tokenStart' => $tokenIndex, 'tokenEnd' => null, 'lineStart' => $tokenLine, 'lineEnd' => null, 'name' => null, 'value' => null);
                 SCANNER_CLASS_BODY_CONST_TOP:
                 if ($tokenContent === ';') {
                     goto SCANNER_CLASS_BODY_CONST_END;
                 }
                 if ($tokenType === T_STRING && null === $infos[$infoIndex]['name']) {
                     $infos[$infoIndex]['name'] = $tokenContent;
                 }
                 SCANNER_CLASS_BODY_CONST_CONTINUE:
                 if ($MACRO_TOKEN_ADVANCE() === false) {
                     goto SCANNER_END;
                 }
                 goto SCANNER_CLASS_BODY_CONST_TOP;
                 SCANNER_CLASS_BODY_CONST_END:
                 $MACRO_INFO_ADVANCE();
                 goto SCANNER_CLASS_BODY_CONTINUE;
                 //goto no break needed
             //goto no break needed
             case T_DOC_COMMENT:
             case T_PUBLIC:
             case T_PROTECTED:
             case T_PRIVATE:
             case T_ABSTRACT:
             case T_FINAL:
             case T_VAR:
             case T_FUNCTION:
                 $infos[$infoIndex] = array('type' => null, 'tokenStart' => $tokenIndex, 'tokenEnd' => null, 'lineStart' => $tokenLine, 'lineEnd' => null, 'name' => null);
                 $memberContext = null;
                 $methodBodyStarted = false;
                 SCANNER_CLASS_BODY_MEMBER_TOP:
                 if ($memberContext === 'method') {
                     switch ($tokenContent) {
                         case '{':
                             $methodBodyStarted = true;
                             $braceCount++;
                             goto SCANNER_CLASS_BODY_MEMBER_CONTINUE;
                             //goto no break needed
                         //goto no break needed
                         case '}':
                             $braceCount--;
                             goto SCANNER_CLASS_BODY_MEMBER_CONTINUE;
                     }
                 }
                 if ($memberContext !== null) {
                     if ($memberContext === 'property' && $tokenContent === ';' || $memberContext === 'method' && $methodBodyStarted && $braceCount === 1 || $memberContext === 'method' && $this->isInterface && $tokenContent === ';') {
                         goto SCANNER_CLASS_BODY_MEMBER_END;
                     }
                 }
                 switch ($tokenType) {
                     case T_CONST:
                         $memberContext = 'constant';
                         $infos[$infoIndex]['type'] = 'constant';
                         goto SCANNER_CLASS_BODY_CONST_CONTINUE;
                         //goto no break needed
                     //goto no break needed
                     case T_VARIABLE:
                         if ($memberContext === null) {
                             $memberContext = 'property';
                             $infos[$infoIndex]['type'] = 'property';
                             $infos[$infoIndex]['name'] = ltrim($tokenContent, '$');
                         }
                         goto SCANNER_CLASS_BODY_MEMBER_CONTINUE;
                         //goto no break needed
                     //goto no break needed
                     case T_FUNCTION:
                         $memberContext = 'method';
                         $infos[$infoIndex]['type'] = 'method';
                         goto SCANNER_CLASS_BODY_MEMBER_CONTINUE;
                         //goto no break needed
                     //goto no break needed
                     case T_STRING:
                         if ($memberContext === 'method' && null === $infos[$infoIndex]['name']) {
                             $infos[$infoIndex]['name'] = $tokenContent;
                         }
                         goto SCANNER_CLASS_BODY_MEMBER_CONTINUE;
                         //goto no break needed
                 }
                 SCANNER_CLASS_BODY_MEMBER_CONTINUE:
                 if ($MACRO_TOKEN_ADVANCE() === false) {
                     goto SCANNER_END;
                 }
                 goto SCANNER_CLASS_BODY_MEMBER_TOP;
                 SCANNER_CLASS_BODY_MEMBER_END:
                 $memberContext = null;
                 $MACRO_INFO_ADVANCE();
                 goto SCANNER_CLASS_BODY_CONTINUE;
                 //goto no break needed
             //goto no break needed
             case null:
                 // no type, is a string
                 switch ($tokenContent) {
                     case '{':
                         $braceCount++;
                         goto SCANNER_CLASS_BODY_CONTINUE;
                         //fall-through
                     //fall-through
                     case '}':
                         $braceCount--;
                         goto SCANNER_CLASS_BODY_CONTINUE;
                 }
         }
         SCANNER_CLASS_BODY_CONTINUE:
         if ($braceCount === 0 || $MACRO_TOKEN_ADVANCE() === false) {
             goto SCANNER_CONTINUE;
         }
         goto SCANNER_CLASS_BODY_TOP;
         SCANNER_CLASS_BODY_END:
         goto SCANNER_CONTINUE;
     }
     SCANNER_CONTINUE:
     if ($tokenContent === '}') {
         $this->lineEnd = $tokenLine;
     }
     if ($MACRO_TOKEN_ADVANCE() === false) {
         goto SCANNER_END;
     }
     goto SCANNER_TOP;
     SCANNER_END:
     // process short names
     if ($this->nameInformation) {
         if ($this->shortParentClass) {
             $this->parentClass = $this->nameInformation->resolveName($this->shortParentClass);
         }
         if ($this->shortInterfaces) {
             foreach ($this->shortInterfaces as $siIndex => $si) {
                 $this->interfaces[$siIndex] = $this->nameInformation->resolveName($si);
             }
         }
     } else {
         $this->parentClass = $this->shortParentClass;
         $this->interfaces = $this->shortInterfaces;
     }
     $this->isScanned = true;
     return;
 }
 /**
  * Scan tokens
  *
  * @return void
  * @throws Exception\RuntimeException
  */
 protected function scan()
 {
     if ($this->isScanned) {
         return;
     }
     if (!$this->tokens) {
         throw new Exception\RuntimeException('No tokens were provided');
     }
     /**
      * Variables & Setup
      */
     $tokens =& $this->tokens;
     // localize
     $infos =& $this->infos;
     // localize
     $tokenIndex = null;
     $token = null;
     $tokenType = null;
     $tokenContent = null;
     $tokenLine = null;
     $namespace = null;
     $infoIndex = 0;
     $braceCount = 0;
     /*
      * MACRO creation
      */
     $MACRO_TOKEN_ADVANCE = function () use(&$tokens, &$tokenIndex, &$token, &$tokenType, &$tokenContent, &$tokenLine) {
         static $lastTokenArray = null;
         $tokenIndex = $tokenIndex === null ? 0 : $tokenIndex + 1;
         if (!isset($tokens[$tokenIndex])) {
             $token = false;
             $tokenContent = false;
             $tokenType = false;
             $tokenLine = false;
             return false;
         }
         $token = $tokens[$tokenIndex];
         if (is_string($token)) {
             $tokenType = null;
             $tokenContent = $token;
             $tokenLine = $tokenLine + substr_count($lastTokenArray[1], "\n");
             // adjust token line by last known newline count
         } else {
             $lastTokenArray = $token;
             list($tokenType, $tokenContent, $tokenLine) = $token;
         }
         return $tokenIndex;
     };
     $MACRO_INFO_ADVANCE = function () use(&$infoIndex, &$infos, &$tokenIndex, &$tokenLine) {
         $infos[$infoIndex]['tokenEnd'] = $tokenIndex;
         $infos[$infoIndex]['lineEnd'] = $tokenLine;
         $infoIndex++;
         return $infoIndex;
     };
     /**
      * START FINITE STATE MACHINE FOR SCANNING TOKENS
      */
     // Initialize token
     $MACRO_TOKEN_ADVANCE();
     SCANNER_TOP:
     switch ($tokenType) {
         case T_DOC_COMMENT:
             $this->docComment = $tokenContent;
             goto SCANNER_CONTINUE;
             //goto no break needed
         //goto no break needed
         case T_FINAL:
         case T_ABSTRACT:
         case T_CLASS:
         case T_INTERFACE:
         case T_TRAIT:
             // CLASS INFORMATION
             $classContext = null;
             $classInterfaceIndex = 0;
             SCANNER_CLASS_INFO_TOP:
             if (is_string($tokens[$tokenIndex + 1]) && $tokens[$tokenIndex + 1] === '{') {
                 goto SCANNER_CLASS_INFO_END;
             }
             $this->lineStart = $tokenLine;
             switch ($tokenType) {
                 case T_FINAL:
                     $this->isFinal = true;
                     goto SCANNER_CLASS_INFO_CONTINUE;
                     // goto no break needed
                 // goto no break needed
                 case T_ABSTRACT:
                     $this->isAbstract = true;
                     goto SCANNER_CLASS_INFO_CONTINUE;
                     // goto no break needed
                 // goto no break needed
                 case T_TRAIT:
                     $this->isTrait = true;
                     $this->shortName = $tokens[$tokenIndex + 2][1];
                     if ($this->nameInformation && $this->nameInformation->hasNamespace()) {
                         $this->name = $this->nameInformation->getNamespace() . '\\' . $this->shortName;
                     } else {
                         $this->name = $this->shortName;
                     }
                     goto SCANNER_CLASS_INFO_CONTINUE;
                 case T_INTERFACE:
                     $this->isInterface = true;
                     //fall-through
                 //fall-through
                 case T_CLASS:
                     $this->shortName = $tokens[$tokenIndex + 2][1];
                     if ($this->nameInformation && $this->nameInformation->hasNamespace()) {
                         $this->name = $this->nameInformation->getNamespace() . '\\' . $this->shortName;
                     } else {
                         $this->name = $this->shortName;
                     }
                     goto SCANNER_CLASS_INFO_CONTINUE;
                     //goto no break needed
                 //goto no break needed
                 case T_NS_SEPARATOR:
                 case T_STRING:
                     switch ($classContext) {
                         case T_EXTENDS:
                             $this->shortParentClass .= $tokenContent;
                             break;
                         case T_IMPLEMENTS:
                             $this->shortInterfaces[$classInterfaceIndex] .= $tokenContent;
                             break;
                     }
                     goto SCANNER_CLASS_INFO_CONTINUE;
                     //goto no break needed
                 //goto no break needed
                 case T_EXTENDS:
                 case T_IMPLEMENTS:
                     $classContext = $tokenType;
                     if ($this->isInterface && $classContext === T_EXTENDS || $classContext === T_IMPLEMENTS) {
                         $this->shortInterfaces[$classInterfaceIndex] = '';
                     } elseif (!$this->isInterface && $classContext === T_EXTENDS) {
                         $this->shortParentClass = '';
                     }
                     goto SCANNER_CLASS_INFO_CONTINUE;
                     //goto no break needed
                 //goto no break needed
                 case null:
                     if ($classContext == T_IMPLEMENTS && $tokenContent == ',') {
                         $classInterfaceIndex++;
                         $this->shortInterfaces[$classInterfaceIndex] = '';
                     }
             }
             SCANNER_CLASS_INFO_CONTINUE:
             if ($MACRO_TOKEN_ADVANCE() === false) {
                 goto SCANNER_END;
             }
             goto SCANNER_CLASS_INFO_TOP;
             SCANNER_CLASS_INFO_END:
             goto SCANNER_CONTINUE;
     }
     if ($tokenType === null && $tokenContent === '{' && $braceCount === 0) {
         $braceCount++;
         if ($MACRO_TOKEN_ADVANCE() === false) {
             goto SCANNER_END;
         }
         SCANNER_CLASS_BODY_TOP:
         if ($braceCount === 0) {
             goto SCANNER_CLASS_BODY_END;
         }
         switch ($tokenType) {
             case T_CONST:
                 $infos[$infoIndex] = ['type' => 'constant', 'tokenStart' => $tokenIndex, 'tokenEnd' => null, 'lineStart' => $tokenLine, 'lineEnd' => null, 'name' => null, 'value' => null];
                 SCANNER_CLASS_BODY_CONST_TOP:
                 if ($tokenContent === ';') {
                     goto SCANNER_CLASS_BODY_CONST_END;
                 }
                 if ($tokenType === T_STRING && null === $infos[$infoIndex]['name']) {
                     $infos[$infoIndex]['name'] = $tokenContent;
                 }
                 SCANNER_CLASS_BODY_CONST_CONTINUE:
                 if ($MACRO_TOKEN_ADVANCE() === false) {
                     goto SCANNER_END;
                 }
                 goto SCANNER_CLASS_BODY_CONST_TOP;
                 SCANNER_CLASS_BODY_CONST_END:
                 $MACRO_INFO_ADVANCE();
                 goto SCANNER_CLASS_BODY_CONTINUE;
                 // goto no break needed
             // goto no break needed
             case T_USE:
                 // ensure php backwards compatibility
                 if (!defined('T_INSTEADOF')) {
                     define('T_INSTEADOF', 24000);
                 }
                 $infos[$infoIndex] = ['type' => 'use', 'tokenStart' => $tokenIndex, 'tokenEnd' => null, 'lineStart' => $tokens[$tokenIndex][2], 'lineEnd' => null, 'name' => $namespace, 'use_statements' => [0 => null], 'aliases' => [0 => null]];
                 $isOriginalName = [T_STRING, T_DOUBLE_COLON];
                 $isAlias = [T_STRING];
                 $isVisibility = [T_PRIVATE, T_PROTECTED, T_PUBLIC, T_STATIC];
                 $isAliasType = [T_AS, T_INSTEADOF];
                 $isValidAlias = array_merge($isOriginalName, $isAlias, $isVisibility, $isAliasType);
                 $useStatementIndex = 0;
                 $aliasStatementIndex = 0;
                 $useAliasContext = false;
                 $useAsContext = false;
                 // start processing with next token
                 if ($MACRO_TOKEN_ADVANCE() === false) {
                     goto SCANNER_END;
                 }
                 SCANNER_USE_TOP:
                 if ($tokenType === null) {
                     if ($tokenContent === "{") {
                         $useStatementIndex = 0;
                         $useAliasContext = true;
                         $infos[$infoIndex]['aliases'][$useStatementIndex] = ['original' => null, 'alias' => null, 'visibility' => null, 'type' => 'as'];
                     } elseif ($tokenContent === "}") {
                         $useAliasContext = false;
                         goto SCANNER_USE_END;
                     } elseif ($tokenContent === ';') {
                         if ($useAliasContext === true) {
                             $useStatementIndex++;
                             $useAsContext = false;
                         }
                         // only end if we aren't inside braces
                         if (false === $useAliasContext) {
                             goto SCANNER_USE_END;
                         }
                     } elseif ($tokenContent === ',') {
                         $useStatementIndex++;
                         $infos[$infoIndex]['use_statements'][$useStatementIndex] = '';
                     }
                 }
                 // ANALYZE
                 if ($tokenType !== null) {
                     // use context
                     if (false === $useAliasContext) {
                         if ($tokenType == T_NS_SEPARATOR || $tokenType == T_STRING) {
                             $infos[$infoIndex]['use_statements'][$useStatementIndex] .= $tokenContent;
                         }
                     } else {
                         if (in_array($tokenType, $isValidAlias) && empty($infos[$infoIndex]['aliases'][$useStatementIndex])) {
                             $infos[$infoIndex]['aliases'][$useStatementIndex] = ['original' => null, 'visibility' => null, 'alias' => null, 'type' => null];
                         }
                         if ($tokenType == T_AS || $tokenType == T_INSTEADOF) {
                             $useAsContext = true;
                             $infos[$infoIndex]['aliases'][$useStatementIndex]['type'] = $tokenType == T_INSTEADOF ? 'insteadof' : 'as';
                             goto SCANNER_USE_CONTINUE;
                         }
                         // in alias context
                         if ($useAsContext === true && in_array($tokenType, $isAlias)) {
                             $infos[$infoIndex]['aliases'][$useStatementIndex]['alias'] = $tokenContent;
                         } elseif (in_array($tokenType, $isOriginalName)) {
                             $infos[$infoIndex]['aliases'][$useStatementIndex]['original'] .= $tokenContent;
                         } elseif (in_array($tokenType, $isVisibility)) {
                             //add whitespace (will trim later)
                             $infos[$infoIndex]['aliases'][$useStatementIndex]['visibility'] = $tokenType;
                         }
                     }
                 }
                 SCANNER_USE_CONTINUE:
                 if ($MACRO_TOKEN_ADVANCE() === false) {
                     goto SCANNER_END;
                 }
                 goto SCANNER_USE_TOP;
                 SCANNER_USE_END:
                 $MACRO_INFO_ADVANCE();
                 goto SCANNER_CLASS_BODY_CONTINUE;
             case T_DOC_COMMENT:
             case T_PUBLIC:
             case T_PROTECTED:
             case T_PRIVATE:
             case T_ABSTRACT:
             case T_FINAL:
             case T_VAR:
             case T_FUNCTION:
                 $infos[$infoIndex] = ['type' => null, 'tokenStart' => $tokenIndex, 'tokenEnd' => null, 'lineStart' => $tokenLine, 'lineEnd' => null, 'name' => null];
                 $memberContext = null;
                 $methodBodyStarted = false;
                 SCANNER_CLASS_BODY_MEMBER_TOP:
                 if ($memberContext === 'method') {
                     switch ($tokenContent) {
                         case '{':
                             $methodBodyStarted = true;
                             $braceCount++;
                             goto SCANNER_CLASS_BODY_MEMBER_CONTINUE;
                             // goto no break needed
                         // goto no break needed
                         case '}':
                             $braceCount--;
                             goto SCANNER_CLASS_BODY_MEMBER_CONTINUE;
                         case ';':
                             $infos[$infoIndex]['tokenEnd'] = $tokenIndex;
                             goto SCANNER_CLASS_BODY_MEMBER_CONTINUE;
                     }
                 }
                 if ($memberContext !== null) {
                     if ($memberContext === 'property' && $tokenContent === ';' || $memberContext === 'method' && $methodBodyStarted && $braceCount === 1 || $memberContext === 'method' && $this->isInterface && $tokenContent === ';') {
                         goto SCANNER_CLASS_BODY_MEMBER_END;
                     }
                 }
                 switch ($tokenType) {
                     case T_CONST:
                         $memberContext = 'constant';
                         $infos[$infoIndex]['type'] = 'constant';
                         goto SCANNER_CLASS_BODY_CONST_CONTINUE;
                         //goto no break needed
                     //goto no break needed
                     case T_VARIABLE:
                         if ($memberContext === null) {
                             $memberContext = 'property';
                             $infos[$infoIndex]['type'] = 'property';
                             $infos[$infoIndex]['name'] = ltrim($tokenContent, '$');
                         }
                         goto SCANNER_CLASS_BODY_MEMBER_CONTINUE;
                         // goto no break needed
                     // goto no break needed
                     case T_FUNCTION:
                         $memberContext = 'method';
                         $infos[$infoIndex]['type'] = 'method';
                         goto SCANNER_CLASS_BODY_MEMBER_CONTINUE;
                         // goto no break needed
                     // goto no break needed
                     case T_STRING:
                         if ($memberContext === 'method' && null === $infos[$infoIndex]['name']) {
                             $infos[$infoIndex]['name'] = $tokenContent;
                         }
                         goto SCANNER_CLASS_BODY_MEMBER_CONTINUE;
                         // goto no break needed
                 }
                 SCANNER_CLASS_BODY_MEMBER_CONTINUE:
                 if ($MACRO_TOKEN_ADVANCE() === false) {
                     goto SCANNER_END;
                 }
                 goto SCANNER_CLASS_BODY_MEMBER_TOP;
                 SCANNER_CLASS_BODY_MEMBER_END:
                 $memberContext = null;
                 $MACRO_INFO_ADVANCE();
                 goto SCANNER_CLASS_BODY_CONTINUE;
                 // goto no break needed
             // goto no break needed
             case null:
                 // no type, is a string
                 switch ($tokenContent) {
                     case '{':
                         $braceCount++;
                         goto SCANNER_CLASS_BODY_CONTINUE;
                         // goto no break needed
                     // goto no break needed
                     case '}':
                         $braceCount--;
                         goto SCANNER_CLASS_BODY_CONTINUE;
                 }
         }
         SCANNER_CLASS_BODY_CONTINUE:
         if ($braceCount === 0 || $MACRO_TOKEN_ADVANCE() === false) {
             goto SCANNER_CONTINUE;
         }
         goto SCANNER_CLASS_BODY_TOP;
         SCANNER_CLASS_BODY_END:
         goto SCANNER_CONTINUE;
     }
     SCANNER_CONTINUE:
     if ($tokenContent === '}') {
         $this->lineEnd = $tokenLine;
     }
     if ($MACRO_TOKEN_ADVANCE() === false) {
         goto SCANNER_END;
     }
     goto SCANNER_TOP;
     SCANNER_END:
     // process short names
     if ($this->nameInformation) {
         if ($this->shortParentClass) {
             $this->parentClass = $this->nameInformation->resolveName($this->shortParentClass);
         }
         if ($this->shortInterfaces) {
             foreach ($this->shortInterfaces as $siIndex => $si) {
                 $this->interfaces[$siIndex] = $this->nameInformation->resolveName($si);
             }
         }
     } else {
         $this->parentClass = $this->shortParentClass;
         $this->interfaces = $this->shortInterfaces;
     }
     $this->isScanned = true;
     return;
 }
Example #8
0
 /**
  * Resolve the types provided via an @param or @return annotation
  *
  * @param  string $value
  * @return string
  */
 protected function resolveTypes($value)
 {
     $values = explode('|', trim($value));
     array_walk($values, 'trim');
     $nameInformation = new NameInformation($this->getNamespace(), $this->getUses());
     foreach ($values as $index => $value) {
         // Is it an internal type?
         if (in_array(strtolower($value), $this->internalTypes)) {
             continue;
         }
         $values[$index] = $nameInformation->resolveName($value);
     }
     return implode('|', $values);
 }