Updated to Drupal 8.5. Core Media not yet in use.
[yaffs-website] / vendor / nikic / php-parser / lib / PhpParser / BuilderHelpers.php
1 <?php declare(strict_types=1);
2
3 namespace PhpParser;
4
5 use PhpParser\Node\Expr;
6 use PhpParser\Node\Identifier;
7 use PhpParser\Node\Name;
8 use PhpParser\Node\NullableType;
9 use PhpParser\Node\Scalar;
10 use PhpParser\Node\Stmt;
11
12 /**
13  * This class defines helpers used in the implementation of builders. Don't use it directly.
14  *
15  * @internal
16  */
17 final class BuilderHelpers
18 {
19     /**
20      * Normalizes a node: Converts builder objects to nodes.
21      *
22      * @param Node|Builder $node The node to normalize
23      *
24      * @return Node The normalized node
25      */
26     public static function normalizeNode($node) : Node {
27         if ($node instanceof Builder) {
28             return $node->getNode();
29         } elseif ($node instanceof Node) {
30             return $node;
31         }
32
33         throw new \LogicException('Expected node or builder object');
34     }
35
36     /**
37      * Normalizes a node to a statement.
38      *
39      * Expressions are wrapped in a Stmt\Expression node.
40      *
41      * @param Node|Builder $node The node to normalize
42      *
43      * @return Stmt The normalized statement node
44      */
45     public static function normalizeStmt($node) : Stmt {
46         $node = self::normalizeNode($node);
47         if ($node instanceof Stmt) {
48             return $node;
49         }
50
51         if ($node instanceof Expr) {
52             return new Stmt\Expression($node);
53         }
54
55         throw new \LogicException('Expected statement or expression node');
56     }
57
58     /**
59      * Normalizes strings to Identifier.
60      *
61      * @param string|Identifier $name The identifier to normalize
62      *
63      * @return Identifier The normalized identifier
64      */
65     public static function normalizeIdentifier($name) : Identifier {
66         if ($name instanceof Identifier) {
67             return $name;
68         }
69
70         if (\is_string($name)) {
71             return new Identifier($name);
72         }
73
74         throw new \LogicException('Expected string or instance of Node\Identifier or Node\Expr');
75     }
76
77     /**
78      * Normalizes strings to Identifier, also allowing expressions.
79      *
80      * @param string|Identifier|Expr $name The identifier to normalize
81      *
82      * @return Identifier|Expr The normalized identifier or expression
83      */
84     public static function normalizeIdentifierOrExpr($name) {
85         if ($name instanceof Identifier || $name instanceof Expr) {
86             return $name;
87         }
88
89         if (\is_string($name)) {
90             return new Identifier($name);
91         }
92
93         throw new \LogicException('Expected string or instance of Node\Identifier or Node\Expr');
94     }
95
96     /**
97      * Normalizes a name: Converts string names to Name nodes.
98      *
99      * @param Name|string $name The name to normalize
100      *
101      * @return Name The normalized name
102      */
103     public static function normalizeName($name) : Name {
104         return self::normalizeNameCommon($name, false);
105     }
106
107     /**
108      * Normalizes a name: Converts string names to Name nodes, while also allowing expressions.
109      *
110      * @param Expr|Name|string $name The name to normalize
111      *
112      * @return Name|Expr The normalized name or expression
113      */
114     public static function normalizeNameOrExpr($name) {
115         return self::normalizeNameCommon($name, true);
116     }
117
118     /**
119      * Normalizes a name: Converts string names to Name nodes, optionally allowing expressions.
120      *
121      * @param Expr|Name|string $name      The name to normalize
122      * @param bool             $allowExpr Whether to also allow expressions
123      *
124      * @return Name|Expr The normalized name, or expression (if allowed)
125      */
126     private static function normalizeNameCommon($name, bool $allowExpr) {
127         if ($name instanceof Name) {
128             return $name;
129         } elseif (is_string($name)) {
130             if (!$name) {
131                 throw new \LogicException('Name cannot be empty');
132             }
133
134             if ($name[0] === '\\') {
135                 return new Name\FullyQualified(substr($name, 1));
136             } elseif (0 === strpos($name, 'namespace\\')) {
137                 return new Name\Relative(substr($name, strlen('namespace\\')));
138             } else {
139                 return new Name($name);
140             }
141         }
142
143         if ($allowExpr) {
144             if ($name instanceof Expr) {
145                 return $name;
146             }
147             throw new \LogicException(
148                 'Name must be a string or an instance of Node\Name or Node\Expr'
149             );
150         } else {
151             throw new \LogicException('Name must be a string or an instance of Node\Name');
152         }
153     }
154
155     /**
156      * Normalizes a type: Converts plain-text type names into proper AST representation.
157      *
158      * In particular, builtin types become Identifiers, custom types become Names and nullables
159      * are wrapped in NullableType nodes.
160      *
161      * @param string|Name|Identifier|NullableType $type The type to normalize
162      *
163      * @return Name|Identifier|NullableType The normalized type
164      */
165     public static function normalizeType($type) {
166         if (!is_string($type)) {
167             if (!$type instanceof Name && !$type instanceof Identifier
168                     && !$type instanceof NullableType) {
169                 throw new \LogicException(
170                     'Type must be a string, or an instance of Name, Identifier or NullableType');
171             }
172             return $type;
173         }
174
175         $nullable = false;
176         if (strlen($type) > 0 && $type[0] === '?') {
177             $nullable = true;
178             $type = substr($type, 1);
179         }
180
181         $builtinTypes = [
182             'array', 'callable', 'string', 'int', 'float', 'bool', 'iterable', 'void', 'object'
183         ];
184
185         $lowerType = strtolower($type);
186         if (in_array($lowerType, $builtinTypes)) {
187             $type = new Identifier($lowerType);
188         } else {
189             $type = self::normalizeName($type);
190         }
191
192         if ($nullable && (string) $type === 'void') {
193             throw new \LogicException('void type cannot be nullable');
194         }
195
196         return $nullable ? new Node\NullableType($type) : $type;
197     }
198
199     /**
200      * Normalizes a value: Converts nulls, booleans, integers,
201      * floats, strings and arrays into their respective nodes
202      *
203      * @param Node\Expr|bool|null|int|float|string|array $value The value to normalize
204      *
205      * @return Expr The normalized value
206      */
207     public static function normalizeValue($value) : Expr {
208         if ($value instanceof Node\Expr) {
209             return $value;
210         } elseif (is_null($value)) {
211             return new Expr\ConstFetch(
212                 new Name('null')
213             );
214         } elseif (is_bool($value)) {
215             return new Expr\ConstFetch(
216                 new Name($value ? 'true' : 'false')
217             );
218         } elseif (is_int($value)) {
219             return new Scalar\LNumber($value);
220         } elseif (is_float($value)) {
221             return new Scalar\DNumber($value);
222         } elseif (is_string($value)) {
223             return new Scalar\String_($value);
224         } elseif (is_array($value)) {
225             $items = [];
226             $lastKey = -1;
227             foreach ($value as $itemKey => $itemValue) {
228                 // for consecutive, numeric keys don't generate keys
229                 if (null !== $lastKey && ++$lastKey === $itemKey) {
230                     $items[] = new Expr\ArrayItem(
231                         self::normalizeValue($itemValue)
232                     );
233                 } else {
234                     $lastKey = null;
235                     $items[] = new Expr\ArrayItem(
236                         self::normalizeValue($itemValue),
237                         self::normalizeValue($itemKey)
238                     );
239                 }
240             }
241
242             return new Expr\Array_($items);
243         } else {
244             throw new \LogicException('Invalid value');
245         }
246     }
247
248     /**
249      * Normalizes a doc comment: Converts plain strings to PhpParser\Comment\Doc.
250      *
251      * @param Comment\Doc|string $docComment The doc comment to normalize
252      *
253      * @return Comment\Doc The normalized doc comment
254      */
255     public static function normalizeDocComment($docComment) : Comment\Doc {
256         if ($docComment instanceof Comment\Doc) {
257             return $docComment;
258         } elseif (is_string($docComment)) {
259             return new Comment\Doc($docComment);
260         } else {
261             throw new \LogicException('Doc comment must be a string or an instance of PhpParser\Comment\Doc');
262         }
263     }
264
265     /**
266      * Adds a modifier and returns new modifier bitmask.
267      *
268      * @param int $modifiers Existing modifiers
269      * @param int $modifier  Modifier to set
270      *
271      * @return int New modifiers
272      */
273     public static function addModifier(int $modifiers, int $modifier) : int {
274         Stmt\Class_::verifyModifier($modifiers, $modifier);
275         return $modifiers | $modifier;
276     }
277 }