PluginProbe
Elementor Website Builder – more than just a page builder / 3.25.3
Elementor Website Builder – more than just a page builder v3.25.3
4.3.0-beta3 4.3.0-beta2 4.3.0-beta1 4.2.4 4.2.3 4.2.2 4.2.1 4.2.0 4.1.5 4.2.0-beta2 4.2.0-dev2 4.2.0-beta1 4.1.4 4.1.3 4.1.2 4.1.1 4.1.0 4.1.0-beta3 4.1.0-dev3 4.0.9 4.1.0-beta2 4.1.0-dev2 4.0.8 4.1.0-beta1 4.1.0-dev1 All 452 releases
elementor / vendor_prefixed / php-di / phpdoc-reader / src / PhpDocReader / PhpParser / TokenParser.php

TokenParser.php in Elementor Website Builder – more than just a page builder 3.25.3, at vendor_prefixed/php-di/phpdoc-reader/src/PhpDocReader/PhpParser/TokenParser.php

155 lines 5.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 declare (strict_types=1);
4 namespace ElementorDeps\PhpDocReader\PhpParser;
5
6 /**
7 * Parses a file for namespaces/use/class declarations.
8 *
9 * Class taken and adapted from doctrine/annotations to avoid pulling the whole package.
10 *
11 * @author Fabien Potencier <fabien@symfony.com>
12 * @author Christian Kaps <christian.kaps@mohiva.com>
13 */
14 class TokenParser
15 {
16 /**
17 * The token list.
18 *
19 * @var list<mixed[]>
20 */
21 private $tokens;
22 /**
23 * The number of tokens.
24 *
25 * @var int
26 */
27 private $numTokens;
28 /**
29 * The current array pointer.
30 *
31 * @var int
32 */
33 private $pointer = 0;
34 /**
35 * @param string $contents
36 */
37 public function __construct($contents)
38 {
39 $this->tokens = \token_get_all($contents);
40 // The PHP parser sets internal compiler globals for certain things. Annoyingly, the last docblock comment it
41 // saw gets stored in doc_comment. When it comes to compile the next thing to be include()d this stored
42 // doc_comment becomes owned by the first thing the compiler sees in the file that it considers might have a
43 // docblock. If the first thing in the file is a class without a doc block this would cause calls to
44 // getDocBlock() on said class to return our long lost doc_comment. Argh.
45 // To workaround, cause the parser to parse an empty docblock. Sure getDocBlock() will return this, but at least
46 // it's harmless to us.
47 \token_get_all("<?php\n/**\n *\n */");
48 $this->numTokens = \count($this->tokens);
49 }
50 /**
51 * Gets all use statements.
52 *
53 * @param string $namespaceName The namespace name of the reflected class.
54 *
55 * @return array<string, string> A list with all found use statements.
56 */
57 public function parseUseStatements($namespaceName)
58 {
59 $statements = [];
60 while ($token = $this->next()) {
61 if ($token[0] === \T_USE) {
62 $statements = \array_merge($statements, $this->parseUseStatement());
63 continue;
64 }
65 if ($token[0] !== \T_NAMESPACE || $this->parseNamespace() !== $namespaceName) {
66 continue;
67 }
68 // Get fresh array for new namespace. This is to prevent the parser to collect the use statements
69 // for a previous namespace with the same name. This is the case if a namespace is defined twice
70 // or if a namespace with the same name is commented out.
71 $statements = [];
72 }
73 return $statements;
74 }
75 /**
76 * Gets the next non whitespace and non comment token.
77 *
78 * @param bool $docCommentIsComment If TRUE then a doc comment is considered a comment and skipped.
79 * If FALSE then only whitespace and normal comments are skipped.
80 *
81 * @return mixed[]|string|null The token if exists, null otherwise.
82 */
83 private function next($docCommentIsComment = \true)
84 {
85 for ($i = $this->pointer; $i < $this->numTokens; $i++) {
86 $this->pointer++;
87 if ($this->tokens[$i][0] === \T_WHITESPACE || $this->tokens[$i][0] === \T_COMMENT || $docCommentIsComment && $this->tokens[$i][0] === \T_DOC_COMMENT) {
88 continue;
89 }
90 return $this->tokens[$i];
91 }
92 return null;
93 }
94 /**
95 * Parses a single use statement.
96 *
97 * @return array<string, string> A list with all found class names for a use statement.
98 */
99 private function parseUseStatement()
100 {
101 $groupRoot = '';
102 $class = '';
103 $alias = '';
104 $statements = [];
105 $explicitAlias = \false;
106 while ($token = $this->next()) {
107 if (!$explicitAlias && $token[0] === \T_STRING) {
108 $class .= $token[1];
109 $alias = $token[1];
110 } elseif ($explicitAlias && $token[0] === \T_STRING) {
111 $alias = $token[1];
112 } elseif (\PHP_VERSION_ID >= 80000 && ($token[0] === \T_NAME_QUALIFIED || $token[0] === \T_NAME_FULLY_QUALIFIED)) {
113 $class .= $token[1];
114 $classSplit = \explode('\\', $token[1]);
115 $alias = $classSplit[\count($classSplit) - 1];
116 } elseif ($token[0] === \T_NS_SEPARATOR) {
117 $class .= '\\';
118 $alias = '';
119 } elseif ($token[0] === \T_AS) {
120 $explicitAlias = \true;
121 $alias = '';
122 } elseif ($token === ',') {
123 $statements[\strtolower($alias)] = $groupRoot . $class;
124 $class = '';
125 $alias = '';
126 $explicitAlias = \false;
127 } elseif ($token === ';') {
128 $statements[\strtolower($alias)] = $groupRoot . $class;
129 break;
130 } elseif ($token === '{') {
131 $groupRoot = $class;
132 $class = '';
133 } elseif ($token === '}') {
134 continue;
135 } else {
136 break;
137 }
138 }
139 return $statements;
140 }
141 /**
142 * Gets the namespace.
143 *
144 * @return string The found namespace.
145 */
146 private function parseNamespace()
147 {
148 $name = '';
149 while (($token = $this->next()) && ($token[0] === \T_STRING || $token[0] === \T_NS_SEPARATOR || \PHP_VERSION_ID >= 80000 && ($token[0] === \T_NAME_QUALIFIED || $token[0] === \T_NAME_FULLY_QUALIFIED))) {
150 $name .= $token[1];
151 }
152 return $name;
153 }
154 }
155