3 namespace PhpDocReader\PhpParser;
6 * Parses a file for namespaces/use/class declarations.
8 * Class taken and adapted from doctrine/annotations to avoid pulling the whole package.
10 * @author Fabien Potencier <fabien@symfony.com>
11 * @author Christian Kaps <christian.kaps@mohiva.com>
23 * The number of tokens.
30 * The current array pointer.
37 * @param string $contents
39 public function __construct($contents)
41 $this->tokens = token_get_all($contents);
43 // The PHP parser sets internal compiler globals for certain things. Annoyingly, the last docblock comment it
44 // saw gets stored in doc_comment. When it comes to compile the next thing to be include()d this stored
45 // doc_comment becomes owned by the first thing the compiler sees in the file that it considers might have a
46 // docblock. If the first thing in the file is a class without a doc block this would cause calls to
47 // getDocBlock() on said class to return our long lost doc_comment. Argh.
48 // To workaround, cause the parser to parse an empty docblock. Sure getDocBlock() will return this, but at least
49 // it's harmless to us.
50 token_get_all("<?php\n/**\n *\n */");
52 $this->numTokens = count($this->tokens);
56 * Gets all use statements.
58 * @param string $namespaceName The namespace name of the reflected class.
60 * @return array A list with all found use statements.
62 public function parseUseStatements($namespaceName)
64 $statements = array();
65 while (($token = $this->next())) {
66 if ($token[0] === T_USE) {
67 $statements = array_merge($statements, $this->parseUseStatement());
70 if ($token[0] !== T_NAMESPACE || $this->parseNamespace() != $namespaceName) {
74 // Get fresh array for new namespace. This is to prevent the parser to collect the use statements
75 // for a previous namespace with the same name. This is the case if a namespace is defined twice
76 // or if a namespace with the same name is commented out.
77 $statements = array();
84 * Gets the next non whitespace and non comment token.
86 * @param boolean $docCommentIsComment If TRUE then a doc comment is considered a comment and skipped.
87 * If FALSE then only whitespace and normal comments are skipped.
89 * @return array|null The token if exists, null otherwise.
91 private function next($docCommentIsComment = true)
93 for ($i = $this->pointer; $i < $this->numTokens; $i++) {
95 if ($this->tokens[$i][0] === T_WHITESPACE ||
96 $this->tokens[$i][0] === T_COMMENT ||
97 ($docCommentIsComment && $this->tokens[$i][0] === T_DOC_COMMENT)) {
102 return $this->tokens[$i];
109 * Parses a single use statement.
111 * @return array A list with all found class names for a use statement.
113 private function parseUseStatement()
117 $statements = array();
118 $explicitAlias = false;
119 while (($token = $this->next())) {
120 $isNameToken = $token[0] === T_STRING || $token[0] === T_NS_SEPARATOR;
121 if (!$explicitAlias && $isNameToken) {
124 } elseif ($explicitAlias && $isNameToken) {
126 } elseif ($token[0] === T_AS) {
127 $explicitAlias = true;
129 } elseif ($token === ',') {
130 $statements[strtolower($alias)] = $class;
133 $explicitAlias = false;
134 } elseif ($token === ';') {
135 $statements[strtolower($alias)] = $class;
146 * Gets the namespace.
148 * @return string The found namespace.
150 private function parseNamespace()
153 while (($token = $this->next()) && ($token[0] === T_STRING || $token[0] === T_NS_SEPARATOR)) {