protected function parseLiteralValue(AnnotationTokenCursor $cursor, NamespaceContext $context) { $token = $cursor->current(); $cursor->next(); if ($token->is(AnnotationToken::T_IDENTIFIER)) { $cursor->consume(AnnotationToken::T_DOUBLE_COLON); $cursor->consume(AnnotationToken::T_CLASS); return $context->lookup($token->getText()); } switch ($token->getType()) { case AnnotationToken::T_DECIMAL: return floatval($token->getText()); case AnnotationToken::T_FALSE: return false; case AnnotationToken::T_INTEGER: return (int) $token->getText(); case AnnotationToken::T_NULL: return NULL; case AnnotationToken::T_STRING: return $token->getText(); case AnnotationToken::T_TRUE: return true; } throw new AnnotationException(sprintf('Invalid literal token (%u: %s)', $token->getType(), AnnotationToken::getTypeName($token->getType()))); }
protected function parseTypeInfo($input, NamespaceContext $context) { $input = trim(preg_replace("'\\s+'", ' ', $input)); $buffer = ''; $genericBuffer = ''; $generics = []; $nesting = 0; for ($count = strlen($input), $i = 0; $i < $count; $i++) { if ($input[$i] == '<') { $nesting++; if ($nesting == 1) { continue; } } elseif ($input[$i] == '>') { $nesting--; if ($nesting < 1) { continue; } } elseif ($input[$i] == ',' && $nesting == 1) { $generics[] = $genericBuffer; $genericBuffer = ''; continue; } elseif ($input[$i] == ' ' && $nesting < 1) { break; } if ($nesting < 1) { $buffer .= $input[$i]; } else { $genericBuffer .= $input[$i]; } } if ($nesting != 0) { throw new \RuntimeException(sprintf('Invalid type definition in doc block: "%s"', $input)); } if (trim($genericBuffer) != '') { $generics[] = $genericBuffer; } $typeName = NULL; switch (strtolower($buffer)) { case 'mixed': case 'object': $type = MetaType::TYPE_MIXED; break; case 'bool': case 'boolean': $type = MetaType::TYPE_BOOLEAN; break; case 'int': case 'integer': $type = MetaType::TYPE_INTEGER; break; case 'float': case 'double': case 'decimal': $type = MetaType::TYPE_FLOAT; break; case 'string': $type = MetaType::TYPE_STRING; break; case 'callable': $type = MetaType::TYPE_CALLABLE; break; case 'array': $type = MetaType::TYPE_ARRAY; break; default: $type = MetaType::TYPE_OBJECT; $typeName = ltrim($context->lookup($buffer), '\\'); break; } switch (count($generics)) { case 0: return new MetaType($type, $typeName); case 1: $valueType = $this->parseTypeInfo($generics[0], $context); return new MetaGenericListType($type, $valueType, $typeName); case 2: $keyType = $this->parseTypeInfo($generics[0], $context); $valueType = $this->parseTypeInfo($generics[1], $context); return new MetaGenericMapType($type, $keyType, $valueType, $typeName); } throw new \RuntimeException(sprintf('Unsupported number of generic params in "%s"', $input)); }
/** * Expand all unqualified names using the given namespace context in the given source code tokens. * * @param array $tokens * @param NamespaceContext $context * @return string */ protected function expandNamesInternal(array &$tokens, $typeName, NamespaceContext $context) { $buffer = ''; for ($size = count($tokens), $i = 0; $i < $size; $i++) { if (is_array($tokens[$i]) && ($tokens[$i][0] == T_STRING || $tokens[$i][0] == T_NS_SEPARATOR || $tokens[$i][0] == T_NEW)) { $isNew = $tokens[$i][0] == T_NEW; if ($isNew) { $buffer .= 'new '; $name = ''; } else { $name = $tokens[$i][1]; } $i++; for (; $i < $size; $i++) { if (is_array($tokens[$i])) { switch ($tokens[$i][0]) { case T_WHITESPACE: case T_COMMENT: case T_DOC_COMMENT: continue 2; case T_NS_SEPARATOR: case T_STRING: $name .= $tokens[$i][1]; continue 2; } } break; } if ($isNew) { if ($name != '') { $buffer .= '\\' . ltrim($context->lookup($name), '\\'); } } else { if ($i < $size && is_array($tokens[$i]) && $tokens[$i][0] == T_DOUBLE_COLON) { if (trim(strtolower($name)) == 'self') { $buffer .= '\\' . $typeName; } else { $buffer .= '\\' . ltrim($context->lookup($name), '\\'); } } else { $buffer .= $name; } } } if ($i < $size) { if (is_array($tokens[$i])) { $buffer .= $tokens[$i][1]; } else { $buffer .= $tokens[$i]; } } } return $buffer; }
/** * Read a PHP import statement and register it with the given namespace context. * * @param array $tokens * @param integer $i * @param NamespaceContext $context */ protected function readImport(array $tokens, &$i, NamespaceContext $context) { $import = ''; for ($size = count($tokens); $i < $size; $i++) { if (is_array($tokens[$i])) { switch ($tokens[$i][0]) { case T_WHITESPACE: case T_COMMENT: case T_DOC_COMMENT: continue 2; case T_NS_SEPARATOR: case T_STRING: $import .= $tokens[$i][1]; continue 2; } } break; } if (is_array($tokens[$i]) && $tokens[$i][0] == T_AS) { $i++; $alias = ''; for ($size = count($tokens); $i < $size; $i++) { if (is_array($tokens[$i])) { switch ($tokens[$i][0]) { case T_WHITESPACE: case T_COMMENT: case T_DOC_COMMENT: continue 2; case T_STRING: $alias .= $tokens[$i][1]; continue 2; } } break; } $context->addAliasedImport($alias, $import); } else { $context->addImport($import); } }