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); } } }
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')); }
/** * 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; }
/** * 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; }
/** * 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); }