24 if ($this->isScanned) {
29 throw new \Zend\Code\Exception\RuntimeException(
'No tokens were provided');
35 if (!defined(
'T_TRAIT')) {
36 define(
'T_TRAIT', 42001);
44 $infos = &$this->infos;
47 $this->tokenType =
null;
51 $docCommentIndex =
false;
57 $macroTokenAdvance =
function () use (&
$tokens, &$tokenIndex, &
$token, &$tokenContent, &$tokenLine) {
58 $tokenIndex = ($tokenIndex ===
null) ? 0 : $tokenIndex + 1;
59 if (!isset(
$tokens[$tokenIndex])) {
61 $tokenContent =
false;
62 $this->tokenType =
false;
67 if (is_string(
$tokens[$tokenIndex]) &&
$tokens[$tokenIndex] ===
'"') {
70 }
while (!(is_string(
$tokens[$tokenIndex]) &&
$tokens[$tokenIndex] ===
'"'));
74 list($this->tokenType, $tokenContent, $tokenLine) =
$token;
76 $this->tokenType =
null;
82 $macroTokenLogicalStartIndex =
function () use (&$tokenIndex, &$docCommentIndex) {
83 return ($docCommentIndex ===
false) ? $tokenIndex : $docCommentIndex;
85 $macroDocCommentStart =
function () use (&$tokenIndex, &$docCommentIndex) {
86 $docCommentIndex = $tokenIndex;
88 return $docCommentIndex;
90 $macroDocCommentValidate =
function () use (&$docCommentIndex) {
91 static $validTrailingTokens =
null;
92 if ($validTrailingTokens ===
null) {
93 $validTrailingTokens = [T_WHITESPACE, T_FINAL, T_ABSTRACT, T_INTERFACE, T_CLASS, T_FUNCTION];
95 if ($docCommentIndex !==
false && !in_array($this->tokenType, $validTrailingTokens)) {
96 $docCommentIndex =
false;
99 return $docCommentIndex;
101 $macroInfoAdvance =
function () use (&$infoIndex, &$infos, &$tokenIndex, &$tokenLine) {
102 $infos[$infoIndex][
'tokenEnd'] = $tokenIndex;
103 $infos[$infoIndex][
'lineEnd'] = $tokenLine;
114 $macroTokenAdvance();
123 $macroDocCommentValidate();
125 switch ($this->tokenType) {
127 $macroDocCommentStart();
128 goto SCANNER_CONTINUE;
132 $infos[$infoIndex] = [
133 'type' =>
'namespace',
134 'tokenStart' => $macroTokenLogicalStartIndex(),
142 if ($macroTokenAdvance() ===
false) {
146 SCANNER_NAMESPACE_TOP:
148 if ($this->tokenType ===
null && $tokenContent ===
';' || $tokenContent ===
'{') {
149 goto SCANNER_NAMESPACE_END;
152 if ($this->tokenType === T_WHITESPACE) {
153 goto SCANNER_NAMESPACE_CONTINUE;
156 if ($this->tokenType === T_NS_SEPARATOR || $this->tokenType === T_STRING) {
157 $infos[$infoIndex][
'namespace'] .= $tokenContent;
160 SCANNER_NAMESPACE_CONTINUE:
162 if ($macroTokenAdvance() ===
false) {
165 goto SCANNER_NAMESPACE_TOP;
167 SCANNER_NAMESPACE_END:
169 $namespace = $infos[$infoIndex][
'namespace'];
172 goto SCANNER_CONTINUE;
176 $infos[$infoIndex] = [
178 'tokenStart' => $macroTokenLogicalStartIndex(),
180 'lineStart' =>
$tokens[$tokenIndex][2],
182 'namespace' => $namespace,
183 'statements' => [0 => [
'use' =>
null,
'as' =>
null]],
186 $useStatementIndex = 0;
187 $useAsContext =
false;
190 if ($macroTokenAdvance() ===
false) {
196 if ($this->tokenType ===
null) {
197 if ($tokenContent ===
';') {
198 goto SCANNER_USE_END;
199 }
elseif ($tokenContent ===
',') {
200 $useAsContext =
false;
201 $useStatementIndex++;
202 $infos[$infoIndex][
'statements'][$useStatementIndex] = [
'use' =>
null,
'as' =>
null];
207 if ($this->tokenType !==
null) {
208 if ($this->tokenType == T_AS) {
209 $useAsContext =
true;
210 goto SCANNER_USE_CONTINUE;
213 if ($this->tokenType == T_NS_SEPARATOR || $this->tokenType == T_STRING) {
214 if ($useAsContext ==
false) {
215 $infos[$infoIndex][
'statements'][$useStatementIndex][
'use'] .= $tokenContent;
217 $infos[$infoIndex][
'statements'][$useStatementIndex][
'as'] = $tokenContent;
222 SCANNER_USE_CONTINUE:
224 if ($macroTokenAdvance() ===
false) {
227 goto SCANNER_USE_TOP;
232 goto SCANNER_CONTINUE;
240 static $includeTypes = [
241 T_INCLUDE =>
'include',
242 T_INCLUDE_ONCE =>
'include_once',
243 T_REQUIRE =>
'require',
244 T_REQUIRE_ONCE =>
'require_once' 247 $infos[$infoIndex] = [
249 'tokenStart' => $macroTokenLogicalStartIndex(),
251 'lineStart' =>
$tokens[$tokenIndex][2],
253 'includeType' => $includeTypes[
$tokens[$tokenIndex][0]],
258 if ($macroTokenAdvance() ===
false) {
264 if ($this->tokenType ===
null && $tokenContent ===
';') {
265 goto SCANNER_INCLUDE_END;
268 $infos[$infoIndex][
'path'] .= $tokenContent;
270 SCANNER_INCLUDE_CONTINUE:
272 if ($macroTokenAdvance() ===
false) {
275 goto SCANNER_INCLUDE_TOP;
280 goto SCANNER_CONTINUE;
289 $infos[$infoIndex] = [
290 'type' => ($this->tokenType === T_FUNCTION) ?
'function' :
'class',
291 'tokenStart' => $macroTokenLogicalStartIndex(),
293 'lineStart' =>
$tokens[$tokenIndex][2],
295 'namespace' => $namespace,
296 'uses' => $this->getUsesNoScan($namespace),
301 $classBraceCount = 0;
308 if ($infos[$infoIndex][
'shortName'] ==
'' 309 && (($this->tokenType === T_CLASS
310 || $this->tokenType === T_INTERFACE
311 || $this->tokenType === T_TRAIT
313 && $infos[$infoIndex][
'type'] ===
'class' &&
$tokens[$tokenIndex - 1][0] !== T_DOUBLE_COLON
314 || ($this->tokenType === T_FUNCTION && $infos[$infoIndex][
'type'] ===
'function'))
316 $infos[$infoIndex][
'shortName'] =
$tokens[$tokenIndex + 2][1];
317 $infos[$infoIndex][
'name'] = (($namespace !==
null)
319 :
'') . $infos[$infoIndex][
'shortName'];
322 if ($this->tokenType ===
null) {
323 if ($tokenContent ==
'{') {
326 if ($tokenContent ==
'}') {
328 if ($classBraceCount === 0) {
329 goto SCANNER_CLASS_END;
334 SCANNER_CLASS_CONTINUE:
336 if ($macroTokenAdvance() ===
false) {
339 goto SCANNER_CLASS_TOP;
344 goto SCANNER_CONTINUE;
349 if ($macroTokenAdvance() ===
false) {
359 $this->isScanned =
true;
elseif(isset( $params[ 'redirect_parent']))