Patched to Drupal 8.4.8 level. See https://www.drupal.org/sa-core-2018-004 and patch...
[yaffs-website] / vendor / nikic / php-parser / lib / PhpParser / BuilderAbstract.php
1 <?php
2
3 namespace PhpParser;
4
5 use PhpParser\Comment;
6 use PhpParser\Node\Expr;
7 use PhpParser\Node\Name;
8 use PhpParser\Node\NullableType;
9 use PhpParser\Node\Scalar;
10 use PhpParser\Node\Stmt;
11
12 abstract class BuilderAbstract implements Builder {
13     /**
14      * Normalizes a node: Converts builder objects to nodes.
15      *
16      * @param Node|Builder $node The node to normalize
17      *
18      * @return Node The normalized node
19      */
20     protected function normalizeNode($node) {
21         if ($node instanceof Builder) {
22             return $node->getNode();
23         } elseif ($node instanceof Node) {
24             return $node;
25         }
26
27         throw new \LogicException('Expected node or builder object');
28     }
29
30     /**
31      * Normalizes a name: Converts plain string names to PhpParser\Node\Name.
32      *
33      * @param Name|string $name The name to normalize
34      *
35      * @return Name The normalized name
36      */
37     protected function normalizeName($name) {
38         if ($name instanceof Name) {
39             return $name;
40         } elseif (is_string($name)) {
41             if (!$name) {
42                 throw new \LogicException('Name cannot be empty');
43             }
44
45             if ($name[0] == '\\') {
46                 return new Name\FullyQualified(substr($name, 1));
47             } elseif (0 === strpos($name, 'namespace\\')) {
48                 return new Name\Relative(substr($name, strlen('namespace\\')));
49             } else {
50                 return new Name($name);
51             }
52         }
53
54         throw new \LogicException('Name must be a string or an instance of PhpParser\Node\Name');
55     }
56
57     /**
58      * Normalizes a type: Converts plain-text type names into proper AST representation.
59      *
60      * In particular, builtin types are left as strings, custom types become Names and nullables
61      * are wrapped in NullableType nodes.
62      *
63      * @param Name|string|NullableType $type The type to normalize
64      *
65      * @return Name|string|NullableType The normalized type
66      */
67     protected function normalizeType($type) {
68         if (!is_string($type)) {
69             if (!$type instanceof Name && !$type instanceof NullableType) {
70                 throw new \LogicException(
71                     'Type must be a string, or an instance of Name or NullableType');
72             }
73             return $type;
74         }
75
76         $nullable = false;
77         if (strlen($type) > 0 && $type[0] === '?') {
78             $nullable = true;
79             $type = substr($type, 1);
80         }
81
82         $builtinTypes = array(
83             'array', 'callable', 'string', 'int', 'float', 'bool', 'iterable', 'void', 'object'
84         );
85
86         $lowerType = strtolower($type);
87         if (in_array($lowerType, $builtinTypes)) {
88             $type = $lowerType;
89         } else {
90             $type = $this->normalizeName($type);
91         }
92
93         if ($nullable && $type === 'void') {
94             throw new \LogicException('void type cannot be nullable');
95         }
96
97         return $nullable ? new Node\NullableType($type) : $type;
98     }
99
100     /**
101      * Normalizes a value: Converts nulls, booleans, integers,
102      * floats, strings and arrays into their respective nodes
103      *
104      * @param mixed $value The value to normalize
105      *
106      * @return Expr The normalized value
107      */
108     protected function normalizeValue($value) {
109         if ($value instanceof Node) {
110             return $value;
111         } elseif (is_null($value)) {
112             return new Expr\ConstFetch(
113                 new Name('null')
114             );
115         } elseif (is_bool($value)) {
116             return new Expr\ConstFetch(
117                 new Name($value ? 'true' : 'false')
118             );
119         } elseif (is_int($value)) {
120             return new Scalar\LNumber($value);
121         } elseif (is_float($value)) {
122             return new Scalar\DNumber($value);
123         } elseif (is_string($value)) {
124             return new Scalar\String_($value);
125         } elseif (is_array($value)) {
126             $items = array();
127             $lastKey = -1;
128             foreach ($value as $itemKey => $itemValue) {
129                 // for consecutive, numeric keys don't generate keys
130                 if (null !== $lastKey && ++$lastKey === $itemKey) {
131                     $items[] = new Expr\ArrayItem(
132                         $this->normalizeValue($itemValue)
133                     );
134                 } else {
135                     $lastKey = null;
136                     $items[] = new Expr\ArrayItem(
137                         $this->normalizeValue($itemValue),
138                         $this->normalizeValue($itemKey)
139                     );
140                 }
141             }
142
143             return new Expr\Array_($items);
144         } else {
145             throw new \LogicException('Invalid value');
146         }
147     }
148
149     /**
150      * Normalizes a doc comment: Converts plain strings to PhpParser\Comment\Doc.
151      *
152      * @param Comment\Doc|string $docComment The doc comment to normalize
153      *
154      * @return Comment\Doc The normalized doc comment
155      */
156     protected function normalizeDocComment($docComment) {
157         if ($docComment instanceof Comment\Doc) {
158             return $docComment;
159         } else if (is_string($docComment)) {
160             return new Comment\Doc($docComment);
161         } else {
162             throw new \LogicException('Doc comment must be a string or an instance of PhpParser\Comment\Doc');
163         }
164     }
165
166     /**
167      * Sets a modifier in the $this->type property.
168      *
169      * @param int $modifier Modifier to set
170      */
171     protected function setModifier($modifier) {
172         Stmt\Class_::verifyModifier($this->flags, $modifier);
173         $this->flags |= $modifier;
174     }
175 }