Mercurial > hg > isophonics-drupal-site
comparison vendor/nikic/php-parser/lib/PhpParser/PrettyPrinter/Standard.php @ 0:4c8ae668cc8c
Initial import (non-working)
author | Chris Cannam |
---|---|
date | Wed, 29 Nov 2017 16:09:58 +0000 |
parents | |
children | 7a779792577d |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4c8ae668cc8c |
---|---|
1 <?php | |
2 | |
3 namespace PhpParser\PrettyPrinter; | |
4 | |
5 use PhpParser\Node; | |
6 use PhpParser\Node\Expr; | |
7 use PhpParser\Node\Expr\AssignOp; | |
8 use PhpParser\Node\Expr\BinaryOp; | |
9 use PhpParser\Node\Expr\Cast; | |
10 use PhpParser\Node\Name; | |
11 use PhpParser\Node\Scalar; | |
12 use PhpParser\Node\Scalar\MagicConst; | |
13 use PhpParser\Node\Stmt; | |
14 use PhpParser\PrettyPrinterAbstract; | |
15 | |
16 class Standard extends PrettyPrinterAbstract | |
17 { | |
18 // Special nodes | |
19 | |
20 protected function pParam(Node\Param $node) { | |
21 return ($node->type ? $this->pType($node->type) . ' ' : '') | |
22 . ($node->byRef ? '&' : '') | |
23 . ($node->variadic ? '...' : '') | |
24 . '$' . $node->name | |
25 . ($node->default ? ' = ' . $this->p($node->default) : ''); | |
26 } | |
27 | |
28 protected function pArg(Node\Arg $node) { | |
29 return ($node->byRef ? '&' : '') . ($node->unpack ? '...' : '') . $this->p($node->value); | |
30 } | |
31 | |
32 protected function pConst(Node\Const_ $node) { | |
33 return $node->name . ' = ' . $this->p($node->value); | |
34 } | |
35 | |
36 protected function pNullableType(Node\NullableType $node) { | |
37 return '?' . $this->pType($node->type); | |
38 } | |
39 | |
40 // Names | |
41 | |
42 protected function pName(Name $node) { | |
43 return implode('\\', $node->parts); | |
44 } | |
45 | |
46 protected function pName_FullyQualified(Name\FullyQualified $node) { | |
47 return '\\' . implode('\\', $node->parts); | |
48 } | |
49 | |
50 protected function pName_Relative(Name\Relative $node) { | |
51 return 'namespace\\' . implode('\\', $node->parts); | |
52 } | |
53 | |
54 // Magic Constants | |
55 | |
56 protected function pScalar_MagicConst_Class(MagicConst\Class_ $node) { | |
57 return '__CLASS__'; | |
58 } | |
59 | |
60 protected function pScalar_MagicConst_Dir(MagicConst\Dir $node) { | |
61 return '__DIR__'; | |
62 } | |
63 | |
64 protected function pScalar_MagicConst_File(MagicConst\File $node) { | |
65 return '__FILE__'; | |
66 } | |
67 | |
68 protected function pScalar_MagicConst_Function(MagicConst\Function_ $node) { | |
69 return '__FUNCTION__'; | |
70 } | |
71 | |
72 protected function pScalar_MagicConst_Line(MagicConst\Line $node) { | |
73 return '__LINE__'; | |
74 } | |
75 | |
76 protected function pScalar_MagicConst_Method(MagicConst\Method $node) { | |
77 return '__METHOD__'; | |
78 } | |
79 | |
80 protected function pScalar_MagicConst_Namespace(MagicConst\Namespace_ $node) { | |
81 return '__NAMESPACE__'; | |
82 } | |
83 | |
84 protected function pScalar_MagicConst_Trait(MagicConst\Trait_ $node) { | |
85 return '__TRAIT__'; | |
86 } | |
87 | |
88 // Scalars | |
89 | |
90 protected function pScalar_String(Scalar\String_ $node) { | |
91 $kind = $node->getAttribute('kind', Scalar\String_::KIND_SINGLE_QUOTED); | |
92 switch ($kind) { | |
93 case Scalar\String_::KIND_NOWDOC: | |
94 $label = $node->getAttribute('docLabel'); | |
95 if ($label && !$this->containsEndLabel($node->value, $label)) { | |
96 if ($node->value === '') { | |
97 return $this->pNoIndent("<<<'$label'\n$label") . $this->docStringEndToken; | |
98 } | |
99 | |
100 return $this->pNoIndent("<<<'$label'\n$node->value\n$label") | |
101 . $this->docStringEndToken; | |
102 } | |
103 /* break missing intentionally */ | |
104 case Scalar\String_::KIND_SINGLE_QUOTED: | |
105 return '\'' . $this->pNoIndent(addcslashes($node->value, '\'\\')) . '\''; | |
106 case Scalar\String_::KIND_HEREDOC: | |
107 $label = $node->getAttribute('docLabel'); | |
108 if ($label && !$this->containsEndLabel($node->value, $label)) { | |
109 if ($node->value === '') { | |
110 return $this->pNoIndent("<<<$label\n$label") . $this->docStringEndToken; | |
111 } | |
112 | |
113 $escaped = $this->escapeString($node->value, null); | |
114 return $this->pNoIndent("<<<$label\n" . $escaped ."\n$label") | |
115 . $this->docStringEndToken; | |
116 } | |
117 /* break missing intentionally */ | |
118 case Scalar\String_::KIND_DOUBLE_QUOTED: | |
119 return '"' . $this->escapeString($node->value, '"') . '"'; | |
120 } | |
121 throw new \Exception('Invalid string kind'); | |
122 } | |
123 | |
124 protected function pScalar_Encapsed(Scalar\Encapsed $node) { | |
125 if ($node->getAttribute('kind') === Scalar\String_::KIND_HEREDOC) { | |
126 $label = $node->getAttribute('docLabel'); | |
127 if ($label && !$this->encapsedContainsEndLabel($node->parts, $label)) { | |
128 if (count($node->parts) === 1 | |
129 && $node->parts[0] instanceof Scalar\EncapsedStringPart | |
130 && $node->parts[0]->value === '' | |
131 ) { | |
132 return $this->pNoIndent("<<<$label\n$label") . $this->docStringEndToken; | |
133 } | |
134 | |
135 return $this->pNoIndent( | |
136 "<<<$label\n" . $this->pEncapsList($node->parts, null) . "\n$label" | |
137 ) . $this->docStringEndToken; | |
138 } | |
139 } | |
140 return '"' . $this->pEncapsList($node->parts, '"') . '"'; | |
141 } | |
142 | |
143 protected function pScalar_LNumber(Scalar\LNumber $node) { | |
144 if ($node->value === -\PHP_INT_MAX-1) { | |
145 // PHP_INT_MIN cannot be represented as a literal, | |
146 // because the sign is not part of the literal | |
147 return '(-' . \PHP_INT_MAX . '-1)'; | |
148 } | |
149 | |
150 $kind = $node->getAttribute('kind', Scalar\LNumber::KIND_DEC); | |
151 if (Scalar\LNumber::KIND_DEC === $kind) { | |
152 return (string) $node->value; | |
153 } | |
154 | |
155 $sign = $node->value < 0 ? '-' : ''; | |
156 $str = (string) $node->value; | |
157 switch ($kind) { | |
158 case Scalar\LNumber::KIND_BIN: | |
159 return $sign . '0b' . base_convert($str, 10, 2); | |
160 case Scalar\LNumber::KIND_OCT: | |
161 return $sign . '0' . base_convert($str, 10, 8); | |
162 case Scalar\LNumber::KIND_HEX: | |
163 return $sign . '0x' . base_convert($str, 10, 16); | |
164 } | |
165 throw new \Exception('Invalid number kind'); | |
166 } | |
167 | |
168 protected function pScalar_DNumber(Scalar\DNumber $node) { | |
169 if (!is_finite($node->value)) { | |
170 if ($node->value === \INF) { | |
171 return '\INF'; | |
172 } elseif ($node->value === -\INF) { | |
173 return '-\INF'; | |
174 } else { | |
175 return '\NAN'; | |
176 } | |
177 } | |
178 | |
179 // Try to find a short full-precision representation | |
180 $stringValue = sprintf('%.16G', $node->value); | |
181 if ($node->value !== (double) $stringValue) { | |
182 $stringValue = sprintf('%.17G', $node->value); | |
183 } | |
184 | |
185 // %G is locale dependent and there exists no locale-independent alternative. We don't want | |
186 // mess with switching locales here, so let's assume that a comma is the only non-standard | |
187 // decimal separator we may encounter... | |
188 $stringValue = str_replace(',', '.', $stringValue); | |
189 | |
190 // ensure that number is really printed as float | |
191 return preg_match('/^-?[0-9]+$/', $stringValue) ? $stringValue . '.0' : $stringValue; | |
192 } | |
193 | |
194 // Assignments | |
195 | |
196 protected function pExpr_Assign(Expr\Assign $node) { | |
197 return $this->pInfixOp('Expr_Assign', $node->var, ' = ', $node->expr); | |
198 } | |
199 | |
200 protected function pExpr_AssignRef(Expr\AssignRef $node) { | |
201 return $this->pInfixOp('Expr_AssignRef', $node->var, ' =& ', $node->expr); | |
202 } | |
203 | |
204 protected function pExpr_AssignOp_Plus(AssignOp\Plus $node) { | |
205 return $this->pInfixOp('Expr_AssignOp_Plus', $node->var, ' += ', $node->expr); | |
206 } | |
207 | |
208 protected function pExpr_AssignOp_Minus(AssignOp\Minus $node) { | |
209 return $this->pInfixOp('Expr_AssignOp_Minus', $node->var, ' -= ', $node->expr); | |
210 } | |
211 | |
212 protected function pExpr_AssignOp_Mul(AssignOp\Mul $node) { | |
213 return $this->pInfixOp('Expr_AssignOp_Mul', $node->var, ' *= ', $node->expr); | |
214 } | |
215 | |
216 protected function pExpr_AssignOp_Div(AssignOp\Div $node) { | |
217 return $this->pInfixOp('Expr_AssignOp_Div', $node->var, ' /= ', $node->expr); | |
218 } | |
219 | |
220 protected function pExpr_AssignOp_Concat(AssignOp\Concat $node) { | |
221 return $this->pInfixOp('Expr_AssignOp_Concat', $node->var, ' .= ', $node->expr); | |
222 } | |
223 | |
224 protected function pExpr_AssignOp_Mod(AssignOp\Mod $node) { | |
225 return $this->pInfixOp('Expr_AssignOp_Mod', $node->var, ' %= ', $node->expr); | |
226 } | |
227 | |
228 protected function pExpr_AssignOp_BitwiseAnd(AssignOp\BitwiseAnd $node) { | |
229 return $this->pInfixOp('Expr_AssignOp_BitwiseAnd', $node->var, ' &= ', $node->expr); | |
230 } | |
231 | |
232 protected function pExpr_AssignOp_BitwiseOr(AssignOp\BitwiseOr $node) { | |
233 return $this->pInfixOp('Expr_AssignOp_BitwiseOr', $node->var, ' |= ', $node->expr); | |
234 } | |
235 | |
236 protected function pExpr_AssignOp_BitwiseXor(AssignOp\BitwiseXor $node) { | |
237 return $this->pInfixOp('Expr_AssignOp_BitwiseXor', $node->var, ' ^= ', $node->expr); | |
238 } | |
239 | |
240 protected function pExpr_AssignOp_ShiftLeft(AssignOp\ShiftLeft $node) { | |
241 return $this->pInfixOp('Expr_AssignOp_ShiftLeft', $node->var, ' <<= ', $node->expr); | |
242 } | |
243 | |
244 protected function pExpr_AssignOp_ShiftRight(AssignOp\ShiftRight $node) { | |
245 return $this->pInfixOp('Expr_AssignOp_ShiftRight', $node->var, ' >>= ', $node->expr); | |
246 } | |
247 | |
248 protected function pExpr_AssignOp_Pow(AssignOp\Pow $node) { | |
249 return $this->pInfixOp('Expr_AssignOp_Pow', $node->var, ' **= ', $node->expr); | |
250 } | |
251 | |
252 // Binary expressions | |
253 | |
254 protected function pExpr_BinaryOp_Plus(BinaryOp\Plus $node) { | |
255 return $this->pInfixOp('Expr_BinaryOp_Plus', $node->left, ' + ', $node->right); | |
256 } | |
257 | |
258 protected function pExpr_BinaryOp_Minus(BinaryOp\Minus $node) { | |
259 return $this->pInfixOp('Expr_BinaryOp_Minus', $node->left, ' - ', $node->right); | |
260 } | |
261 | |
262 protected function pExpr_BinaryOp_Mul(BinaryOp\Mul $node) { | |
263 return $this->pInfixOp('Expr_BinaryOp_Mul', $node->left, ' * ', $node->right); | |
264 } | |
265 | |
266 protected function pExpr_BinaryOp_Div(BinaryOp\Div $node) { | |
267 return $this->pInfixOp('Expr_BinaryOp_Div', $node->left, ' / ', $node->right); | |
268 } | |
269 | |
270 protected function pExpr_BinaryOp_Concat(BinaryOp\Concat $node) { | |
271 return $this->pInfixOp('Expr_BinaryOp_Concat', $node->left, ' . ', $node->right); | |
272 } | |
273 | |
274 protected function pExpr_BinaryOp_Mod(BinaryOp\Mod $node) { | |
275 return $this->pInfixOp('Expr_BinaryOp_Mod', $node->left, ' % ', $node->right); | |
276 } | |
277 | |
278 protected function pExpr_BinaryOp_BooleanAnd(BinaryOp\BooleanAnd $node) { | |
279 return $this->pInfixOp('Expr_BinaryOp_BooleanAnd', $node->left, ' && ', $node->right); | |
280 } | |
281 | |
282 protected function pExpr_BinaryOp_BooleanOr(BinaryOp\BooleanOr $node) { | |
283 return $this->pInfixOp('Expr_BinaryOp_BooleanOr', $node->left, ' || ', $node->right); | |
284 } | |
285 | |
286 protected function pExpr_BinaryOp_BitwiseAnd(BinaryOp\BitwiseAnd $node) { | |
287 return $this->pInfixOp('Expr_BinaryOp_BitwiseAnd', $node->left, ' & ', $node->right); | |
288 } | |
289 | |
290 protected function pExpr_BinaryOp_BitwiseOr(BinaryOp\BitwiseOr $node) { | |
291 return $this->pInfixOp('Expr_BinaryOp_BitwiseOr', $node->left, ' | ', $node->right); | |
292 } | |
293 | |
294 protected function pExpr_BinaryOp_BitwiseXor(BinaryOp\BitwiseXor $node) { | |
295 return $this->pInfixOp('Expr_BinaryOp_BitwiseXor', $node->left, ' ^ ', $node->right); | |
296 } | |
297 | |
298 protected function pExpr_BinaryOp_ShiftLeft(BinaryOp\ShiftLeft $node) { | |
299 return $this->pInfixOp('Expr_BinaryOp_ShiftLeft', $node->left, ' << ', $node->right); | |
300 } | |
301 | |
302 protected function pExpr_BinaryOp_ShiftRight(BinaryOp\ShiftRight $node) { | |
303 return $this->pInfixOp('Expr_BinaryOp_ShiftRight', $node->left, ' >> ', $node->right); | |
304 } | |
305 | |
306 protected function pExpr_BinaryOp_Pow(BinaryOp\Pow $node) { | |
307 return $this->pInfixOp('Expr_BinaryOp_Pow', $node->left, ' ** ', $node->right); | |
308 } | |
309 | |
310 protected function pExpr_BinaryOp_LogicalAnd(BinaryOp\LogicalAnd $node) { | |
311 return $this->pInfixOp('Expr_BinaryOp_LogicalAnd', $node->left, ' and ', $node->right); | |
312 } | |
313 | |
314 protected function pExpr_BinaryOp_LogicalOr(BinaryOp\LogicalOr $node) { | |
315 return $this->pInfixOp('Expr_BinaryOp_LogicalOr', $node->left, ' or ', $node->right); | |
316 } | |
317 | |
318 protected function pExpr_BinaryOp_LogicalXor(BinaryOp\LogicalXor $node) { | |
319 return $this->pInfixOp('Expr_BinaryOp_LogicalXor', $node->left, ' xor ', $node->right); | |
320 } | |
321 | |
322 protected function pExpr_BinaryOp_Equal(BinaryOp\Equal $node) { | |
323 return $this->pInfixOp('Expr_BinaryOp_Equal', $node->left, ' == ', $node->right); | |
324 } | |
325 | |
326 protected function pExpr_BinaryOp_NotEqual(BinaryOp\NotEqual $node) { | |
327 return $this->pInfixOp('Expr_BinaryOp_NotEqual', $node->left, ' != ', $node->right); | |
328 } | |
329 | |
330 protected function pExpr_BinaryOp_Identical(BinaryOp\Identical $node) { | |
331 return $this->pInfixOp('Expr_BinaryOp_Identical', $node->left, ' === ', $node->right); | |
332 } | |
333 | |
334 protected function pExpr_BinaryOp_NotIdentical(BinaryOp\NotIdentical $node) { | |
335 return $this->pInfixOp('Expr_BinaryOp_NotIdentical', $node->left, ' !== ', $node->right); | |
336 } | |
337 | |
338 protected function pExpr_BinaryOp_Spaceship(BinaryOp\Spaceship $node) { | |
339 return $this->pInfixOp('Expr_BinaryOp_Spaceship', $node->left, ' <=> ', $node->right); | |
340 } | |
341 | |
342 protected function pExpr_BinaryOp_Greater(BinaryOp\Greater $node) { | |
343 return $this->pInfixOp('Expr_BinaryOp_Greater', $node->left, ' > ', $node->right); | |
344 } | |
345 | |
346 protected function pExpr_BinaryOp_GreaterOrEqual(BinaryOp\GreaterOrEqual $node) { | |
347 return $this->pInfixOp('Expr_BinaryOp_GreaterOrEqual', $node->left, ' >= ', $node->right); | |
348 } | |
349 | |
350 protected function pExpr_BinaryOp_Smaller(BinaryOp\Smaller $node) { | |
351 return $this->pInfixOp('Expr_BinaryOp_Smaller', $node->left, ' < ', $node->right); | |
352 } | |
353 | |
354 protected function pExpr_BinaryOp_SmallerOrEqual(BinaryOp\SmallerOrEqual $node) { | |
355 return $this->pInfixOp('Expr_BinaryOp_SmallerOrEqual', $node->left, ' <= ', $node->right); | |
356 } | |
357 | |
358 protected function pExpr_BinaryOp_Coalesce(BinaryOp\Coalesce $node) { | |
359 return $this->pInfixOp('Expr_BinaryOp_Coalesce', $node->left, ' ?? ', $node->right); | |
360 } | |
361 | |
362 protected function pExpr_Instanceof(Expr\Instanceof_ $node) { | |
363 return $this->pInfixOp('Expr_Instanceof', $node->expr, ' instanceof ', $node->class); | |
364 } | |
365 | |
366 // Unary expressions | |
367 | |
368 protected function pExpr_BooleanNot(Expr\BooleanNot $node) { | |
369 return $this->pPrefixOp('Expr_BooleanNot', '!', $node->expr); | |
370 } | |
371 | |
372 protected function pExpr_BitwiseNot(Expr\BitwiseNot $node) { | |
373 return $this->pPrefixOp('Expr_BitwiseNot', '~', $node->expr); | |
374 } | |
375 | |
376 protected function pExpr_UnaryMinus(Expr\UnaryMinus $node) { | |
377 return $this->pPrefixOp('Expr_UnaryMinus', '-', $node->expr); | |
378 } | |
379 | |
380 protected function pExpr_UnaryPlus(Expr\UnaryPlus $node) { | |
381 return $this->pPrefixOp('Expr_UnaryPlus', '+', $node->expr); | |
382 } | |
383 | |
384 protected function pExpr_PreInc(Expr\PreInc $node) { | |
385 return $this->pPrefixOp('Expr_PreInc', '++', $node->var); | |
386 } | |
387 | |
388 protected function pExpr_PreDec(Expr\PreDec $node) { | |
389 return $this->pPrefixOp('Expr_PreDec', '--', $node->var); | |
390 } | |
391 | |
392 protected function pExpr_PostInc(Expr\PostInc $node) { | |
393 return $this->pPostfixOp('Expr_PostInc', $node->var, '++'); | |
394 } | |
395 | |
396 protected function pExpr_PostDec(Expr\PostDec $node) { | |
397 return $this->pPostfixOp('Expr_PostDec', $node->var, '--'); | |
398 } | |
399 | |
400 protected function pExpr_ErrorSuppress(Expr\ErrorSuppress $node) { | |
401 return $this->pPrefixOp('Expr_ErrorSuppress', '@', $node->expr); | |
402 } | |
403 | |
404 protected function pExpr_YieldFrom(Expr\YieldFrom $node) { | |
405 return $this->pPrefixOp('Expr_YieldFrom', 'yield from ', $node->expr); | |
406 } | |
407 | |
408 protected function pExpr_Print(Expr\Print_ $node) { | |
409 return $this->pPrefixOp('Expr_Print', 'print ', $node->expr); | |
410 } | |
411 | |
412 // Casts | |
413 | |
414 protected function pExpr_Cast_Int(Cast\Int_ $node) { | |
415 return $this->pPrefixOp('Expr_Cast_Int', '(int) ', $node->expr); | |
416 } | |
417 | |
418 protected function pExpr_Cast_Double(Cast\Double $node) { | |
419 return $this->pPrefixOp('Expr_Cast_Double', '(double) ', $node->expr); | |
420 } | |
421 | |
422 protected function pExpr_Cast_String(Cast\String_ $node) { | |
423 return $this->pPrefixOp('Expr_Cast_String', '(string) ', $node->expr); | |
424 } | |
425 | |
426 protected function pExpr_Cast_Array(Cast\Array_ $node) { | |
427 return $this->pPrefixOp('Expr_Cast_Array', '(array) ', $node->expr); | |
428 } | |
429 | |
430 protected function pExpr_Cast_Object(Cast\Object_ $node) { | |
431 return $this->pPrefixOp('Expr_Cast_Object', '(object) ', $node->expr); | |
432 } | |
433 | |
434 protected function pExpr_Cast_Bool(Cast\Bool_ $node) { | |
435 return $this->pPrefixOp('Expr_Cast_Bool', '(bool) ', $node->expr); | |
436 } | |
437 | |
438 protected function pExpr_Cast_Unset(Cast\Unset_ $node) { | |
439 return $this->pPrefixOp('Expr_Cast_Unset', '(unset) ', $node->expr); | |
440 } | |
441 | |
442 // Function calls and similar constructs | |
443 | |
444 protected function pExpr_FuncCall(Expr\FuncCall $node) { | |
445 return $this->pCallLhs($node->name) | |
446 . '(' . $this->pMaybeMultiline($node->args) . ')'; | |
447 } | |
448 | |
449 protected function pExpr_MethodCall(Expr\MethodCall $node) { | |
450 return $this->pDereferenceLhs($node->var) . '->' . $this->pObjectProperty($node->name) | |
451 . '(' . $this->pMaybeMultiline($node->args) . ')'; | |
452 } | |
453 | |
454 protected function pExpr_StaticCall(Expr\StaticCall $node) { | |
455 return $this->pDereferenceLhs($node->class) . '::' | |
456 . ($node->name instanceof Expr | |
457 ? ($node->name instanceof Expr\Variable | |
458 ? $this->p($node->name) | |
459 : '{' . $this->p($node->name) . '}') | |
460 : $node->name) | |
461 . '(' . $this->pMaybeMultiline($node->args) . ')'; | |
462 } | |
463 | |
464 protected function pExpr_Empty(Expr\Empty_ $node) { | |
465 return 'empty(' . $this->p($node->expr) . ')'; | |
466 } | |
467 | |
468 protected function pExpr_Isset(Expr\Isset_ $node) { | |
469 return 'isset(' . $this->pCommaSeparated($node->vars) . ')'; | |
470 } | |
471 | |
472 protected function pExpr_Eval(Expr\Eval_ $node) { | |
473 return 'eval(' . $this->p($node->expr) . ')'; | |
474 } | |
475 | |
476 protected function pExpr_Include(Expr\Include_ $node) { | |
477 static $map = array( | |
478 Expr\Include_::TYPE_INCLUDE => 'include', | |
479 Expr\Include_::TYPE_INCLUDE_ONCE => 'include_once', | |
480 Expr\Include_::TYPE_REQUIRE => 'require', | |
481 Expr\Include_::TYPE_REQUIRE_ONCE => 'require_once', | |
482 ); | |
483 | |
484 return $map[$node->type] . ' ' . $this->p($node->expr); | |
485 } | |
486 | |
487 protected function pExpr_List(Expr\List_ $node) { | |
488 return 'list(' . $this->pCommaSeparated($node->items) . ')'; | |
489 } | |
490 | |
491 // Other | |
492 | |
493 protected function pExpr_Error(Expr\Error $node) { | |
494 throw new \LogicException('Cannot pretty-print AST with Error nodes'); | |
495 } | |
496 | |
497 protected function pExpr_Variable(Expr\Variable $node) { | |
498 if ($node->name instanceof Expr) { | |
499 return '${' . $this->p($node->name) . '}'; | |
500 } else { | |
501 return '$' . $node->name; | |
502 } | |
503 } | |
504 | |
505 protected function pExpr_Array(Expr\Array_ $node) { | |
506 $syntax = $node->getAttribute('kind', | |
507 $this->options['shortArraySyntax'] ? Expr\Array_::KIND_SHORT : Expr\Array_::KIND_LONG); | |
508 if ($syntax === Expr\Array_::KIND_SHORT) { | |
509 return '[' . $this->pMaybeMultiline($node->items, true) . ']'; | |
510 } else { | |
511 return 'array(' . $this->pMaybeMultiline($node->items, true) . ')'; | |
512 } | |
513 } | |
514 | |
515 protected function pExpr_ArrayItem(Expr\ArrayItem $node) { | |
516 return (null !== $node->key ? $this->p($node->key) . ' => ' : '') | |
517 . ($node->byRef ? '&' : '') . $this->p($node->value); | |
518 } | |
519 | |
520 protected function pExpr_ArrayDimFetch(Expr\ArrayDimFetch $node) { | |
521 return $this->pDereferenceLhs($node->var) | |
522 . '[' . (null !== $node->dim ? $this->p($node->dim) : '') . ']'; | |
523 } | |
524 | |
525 protected function pExpr_ConstFetch(Expr\ConstFetch $node) { | |
526 return $this->p($node->name); | |
527 } | |
528 | |
529 protected function pExpr_ClassConstFetch(Expr\ClassConstFetch $node) { | |
530 return $this->p($node->class) . '::' | |
531 . (is_string($node->name) ? $node->name : $this->p($node->name)); | |
532 } | |
533 | |
534 protected function pExpr_PropertyFetch(Expr\PropertyFetch $node) { | |
535 return $this->pDereferenceLhs($node->var) . '->' . $this->pObjectProperty($node->name); | |
536 } | |
537 | |
538 protected function pExpr_StaticPropertyFetch(Expr\StaticPropertyFetch $node) { | |
539 return $this->pDereferenceLhs($node->class) . '::$' . $this->pObjectProperty($node->name); | |
540 } | |
541 | |
542 protected function pExpr_ShellExec(Expr\ShellExec $node) { | |
543 return '`' . $this->pEncapsList($node->parts, '`') . '`'; | |
544 } | |
545 | |
546 protected function pExpr_Closure(Expr\Closure $node) { | |
547 return ($node->static ? 'static ' : '') | |
548 . 'function ' . ($node->byRef ? '&' : '') | |
549 . '(' . $this->pCommaSeparated($node->params) . ')' | |
550 . (!empty($node->uses) ? ' use(' . $this->pCommaSeparated($node->uses) . ')': '') | |
551 . (null !== $node->returnType ? ' : ' . $this->pType($node->returnType) : '') | |
552 . ' {' . $this->pStmts($node->stmts) . "\n" . '}'; | |
553 } | |
554 | |
555 protected function pExpr_ClosureUse(Expr\ClosureUse $node) { | |
556 return ($node->byRef ? '&' : '') . '$' . $node->var; | |
557 } | |
558 | |
559 protected function pExpr_New(Expr\New_ $node) { | |
560 if ($node->class instanceof Stmt\Class_) { | |
561 $args = $node->args ? '(' . $this->pMaybeMultiline($node->args) . ')' : ''; | |
562 return 'new ' . $this->pClassCommon($node->class, $args); | |
563 } | |
564 return 'new ' . $this->p($node->class) . '(' . $this->pMaybeMultiline($node->args) . ')'; | |
565 } | |
566 | |
567 protected function pExpr_Clone(Expr\Clone_ $node) { | |
568 return 'clone ' . $this->p($node->expr); | |
569 } | |
570 | |
571 protected function pExpr_Ternary(Expr\Ternary $node) { | |
572 // a bit of cheating: we treat the ternary as a binary op where the ?...: part is the operator. | |
573 // this is okay because the part between ? and : never needs parentheses. | |
574 return $this->pInfixOp('Expr_Ternary', | |
575 $node->cond, ' ?' . (null !== $node->if ? ' ' . $this->p($node->if) . ' ' : '') . ': ', $node->else | |
576 ); | |
577 } | |
578 | |
579 protected function pExpr_Exit(Expr\Exit_ $node) { | |
580 $kind = $node->getAttribute('kind', Expr\Exit_::KIND_DIE); | |
581 return ($kind === Expr\Exit_::KIND_EXIT ? 'exit' : 'die') | |
582 . (null !== $node->expr ? '(' . $this->p($node->expr) . ')' : ''); | |
583 } | |
584 | |
585 protected function pExpr_Yield(Expr\Yield_ $node) { | |
586 if ($node->value === null) { | |
587 return 'yield'; | |
588 } else { | |
589 // this is a bit ugly, but currently there is no way to detect whether the parentheses are necessary | |
590 return '(yield ' | |
591 . ($node->key !== null ? $this->p($node->key) . ' => ' : '') | |
592 . $this->p($node->value) | |
593 . ')'; | |
594 } | |
595 } | |
596 | |
597 // Declarations | |
598 | |
599 protected function pStmt_Namespace(Stmt\Namespace_ $node) { | |
600 if ($this->canUseSemicolonNamespaces) { | |
601 return 'namespace ' . $this->p($node->name) . ';' . "\n" . $this->pStmts($node->stmts, false); | |
602 } else { | |
603 return 'namespace' . (null !== $node->name ? ' ' . $this->p($node->name) : '') | |
604 . ' {' . $this->pStmts($node->stmts) . "\n" . '}'; | |
605 } | |
606 } | |
607 | |
608 protected function pStmt_Use(Stmt\Use_ $node) { | |
609 return 'use ' . $this->pUseType($node->type) | |
610 . $this->pCommaSeparated($node->uses) . ';'; | |
611 } | |
612 | |
613 protected function pStmt_GroupUse(Stmt\GroupUse $node) { | |
614 return 'use ' . $this->pUseType($node->type) . $this->pName($node->prefix) | |
615 . '\{' . $this->pCommaSeparated($node->uses) . '};'; | |
616 } | |
617 | |
618 protected function pStmt_UseUse(Stmt\UseUse $node) { | |
619 return $this->pUseType($node->type) . $this->p($node->name) | |
620 . ($node->name->getLast() !== $node->alias ? ' as ' . $node->alias : ''); | |
621 } | |
622 | |
623 protected function pUseType($type) { | |
624 return $type === Stmt\Use_::TYPE_FUNCTION ? 'function ' | |
625 : ($type === Stmt\Use_::TYPE_CONSTANT ? 'const ' : ''); | |
626 } | |
627 | |
628 protected function pStmt_Interface(Stmt\Interface_ $node) { | |
629 return 'interface ' . $node->name | |
630 . (!empty($node->extends) ? ' extends ' . $this->pCommaSeparated($node->extends) : '') | |
631 . "\n" . '{' . $this->pStmts($node->stmts) . "\n" . '}'; | |
632 } | |
633 | |
634 protected function pStmt_Class(Stmt\Class_ $node) { | |
635 return $this->pClassCommon($node, ' ' . $node->name); | |
636 } | |
637 | |
638 protected function pStmt_Trait(Stmt\Trait_ $node) { | |
639 return 'trait ' . $node->name | |
640 . "\n" . '{' . $this->pStmts($node->stmts) . "\n" . '}'; | |
641 } | |
642 | |
643 protected function pStmt_TraitUse(Stmt\TraitUse $node) { | |
644 return 'use ' . $this->pCommaSeparated($node->traits) | |
645 . (empty($node->adaptations) | |
646 ? ';' | |
647 : ' {' . $this->pStmts($node->adaptations) . "\n" . '}'); | |
648 } | |
649 | |
650 protected function pStmt_TraitUseAdaptation_Precedence(Stmt\TraitUseAdaptation\Precedence $node) { | |
651 return $this->p($node->trait) . '::' . $node->method | |
652 . ' insteadof ' . $this->pCommaSeparated($node->insteadof) . ';'; | |
653 } | |
654 | |
655 protected function pStmt_TraitUseAdaptation_Alias(Stmt\TraitUseAdaptation\Alias $node) { | |
656 return (null !== $node->trait ? $this->p($node->trait) . '::' : '') | |
657 . $node->method . ' as' | |
658 . (null !== $node->newModifier ? ' ' . rtrim($this->pModifiers($node->newModifier), ' ') : '') | |
659 . (null !== $node->newName ? ' ' . $node->newName : '') | |
660 . ';'; | |
661 } | |
662 | |
663 protected function pStmt_Property(Stmt\Property $node) { | |
664 return (0 === $node->flags ? 'var ' : $this->pModifiers($node->flags)) . $this->pCommaSeparated($node->props) . ';'; | |
665 } | |
666 | |
667 protected function pStmt_PropertyProperty(Stmt\PropertyProperty $node) { | |
668 return '$' . $node->name | |
669 . (null !== $node->default ? ' = ' . $this->p($node->default) : ''); | |
670 } | |
671 | |
672 protected function pStmt_ClassMethod(Stmt\ClassMethod $node) { | |
673 return $this->pModifiers($node->flags) | |
674 . 'function ' . ($node->byRef ? '&' : '') . $node->name | |
675 . '(' . $this->pCommaSeparated($node->params) . ')' | |
676 . (null !== $node->returnType ? ' : ' . $this->pType($node->returnType) : '') | |
677 . (null !== $node->stmts | |
678 ? "\n" . '{' . $this->pStmts($node->stmts) . "\n" . '}' | |
679 : ';'); | |
680 } | |
681 | |
682 protected function pStmt_ClassConst(Stmt\ClassConst $node) { | |
683 return $this->pModifiers($node->flags) | |
684 . 'const ' . $this->pCommaSeparated($node->consts) . ';'; | |
685 } | |
686 | |
687 protected function pStmt_Function(Stmt\Function_ $node) { | |
688 return 'function ' . ($node->byRef ? '&' : '') . $node->name | |
689 . '(' . $this->pCommaSeparated($node->params) . ')' | |
690 . (null !== $node->returnType ? ' : ' . $this->pType($node->returnType) : '') | |
691 . "\n" . '{' . $this->pStmts($node->stmts) . "\n" . '}'; | |
692 } | |
693 | |
694 protected function pStmt_Const(Stmt\Const_ $node) { | |
695 return 'const ' . $this->pCommaSeparated($node->consts) . ';'; | |
696 } | |
697 | |
698 protected function pStmt_Declare(Stmt\Declare_ $node) { | |
699 return 'declare (' . $this->pCommaSeparated($node->declares) . ')' | |
700 . (null !== $node->stmts ? ' {' . $this->pStmts($node->stmts) . "\n" . '}' : ';'); | |
701 } | |
702 | |
703 protected function pStmt_DeclareDeclare(Stmt\DeclareDeclare $node) { | |
704 return $node->key . '=' . $this->p($node->value); | |
705 } | |
706 | |
707 // Control flow | |
708 | |
709 protected function pStmt_If(Stmt\If_ $node) { | |
710 return 'if (' . $this->p($node->cond) . ') {' | |
711 . $this->pStmts($node->stmts) . "\n" . '}' | |
712 . $this->pImplode($node->elseifs) | |
713 . (null !== $node->else ? $this->p($node->else) : ''); | |
714 } | |
715 | |
716 protected function pStmt_ElseIf(Stmt\ElseIf_ $node) { | |
717 return ' elseif (' . $this->p($node->cond) . ') {' | |
718 . $this->pStmts($node->stmts) . "\n" . '}'; | |
719 } | |
720 | |
721 protected function pStmt_Else(Stmt\Else_ $node) { | |
722 return ' else {' . $this->pStmts($node->stmts) . "\n" . '}'; | |
723 } | |
724 | |
725 protected function pStmt_For(Stmt\For_ $node) { | |
726 return 'for (' | |
727 . $this->pCommaSeparated($node->init) . ';' . (!empty($node->cond) ? ' ' : '') | |
728 . $this->pCommaSeparated($node->cond) . ';' . (!empty($node->loop) ? ' ' : '') | |
729 . $this->pCommaSeparated($node->loop) | |
730 . ') {' . $this->pStmts($node->stmts) . "\n" . '}'; | |
731 } | |
732 | |
733 protected function pStmt_Foreach(Stmt\Foreach_ $node) { | |
734 return 'foreach (' . $this->p($node->expr) . ' as ' | |
735 . (null !== $node->keyVar ? $this->p($node->keyVar) . ' => ' : '') | |
736 . ($node->byRef ? '&' : '') . $this->p($node->valueVar) . ') {' | |
737 . $this->pStmts($node->stmts) . "\n" . '}'; | |
738 } | |
739 | |
740 protected function pStmt_While(Stmt\While_ $node) { | |
741 return 'while (' . $this->p($node->cond) . ') {' | |
742 . $this->pStmts($node->stmts) . "\n" . '}'; | |
743 } | |
744 | |
745 protected function pStmt_Do(Stmt\Do_ $node) { | |
746 return 'do {' . $this->pStmts($node->stmts) . "\n" | |
747 . '} while (' . $this->p($node->cond) . ');'; | |
748 } | |
749 | |
750 protected function pStmt_Switch(Stmt\Switch_ $node) { | |
751 return 'switch (' . $this->p($node->cond) . ') {' | |
752 . $this->pStmts($node->cases) . "\n" . '}'; | |
753 } | |
754 | |
755 protected function pStmt_Case(Stmt\Case_ $node) { | |
756 return (null !== $node->cond ? 'case ' . $this->p($node->cond) : 'default') . ':' | |
757 . $this->pStmts($node->stmts); | |
758 } | |
759 | |
760 protected function pStmt_TryCatch(Stmt\TryCatch $node) { | |
761 return 'try {' . $this->pStmts($node->stmts) . "\n" . '}' | |
762 . $this->pImplode($node->catches) | |
763 . ($node->finally !== null ? $this->p($node->finally) : ''); | |
764 } | |
765 | |
766 protected function pStmt_Catch(Stmt\Catch_ $node) { | |
767 return ' catch (' . $this->pImplode($node->types, '|') . ' $' . $node->var . ') {' | |
768 . $this->pStmts($node->stmts) . "\n" . '}'; | |
769 } | |
770 | |
771 protected function pStmt_Finally(Stmt\Finally_ $node) { | |
772 return ' finally {' . $this->pStmts($node->stmts) . "\n" . '}'; | |
773 } | |
774 | |
775 protected function pStmt_Break(Stmt\Break_ $node) { | |
776 return 'break' . ($node->num !== null ? ' ' . $this->p($node->num) : '') . ';'; | |
777 } | |
778 | |
779 protected function pStmt_Continue(Stmt\Continue_ $node) { | |
780 return 'continue' . ($node->num !== null ? ' ' . $this->p($node->num) : '') . ';'; | |
781 } | |
782 | |
783 protected function pStmt_Return(Stmt\Return_ $node) { | |
784 return 'return' . (null !== $node->expr ? ' ' . $this->p($node->expr) : '') . ';'; | |
785 } | |
786 | |
787 protected function pStmt_Throw(Stmt\Throw_ $node) { | |
788 return 'throw ' . $this->p($node->expr) . ';'; | |
789 } | |
790 | |
791 protected function pStmt_Label(Stmt\Label $node) { | |
792 return $node->name . ':'; | |
793 } | |
794 | |
795 protected function pStmt_Goto(Stmt\Goto_ $node) { | |
796 return 'goto ' . $node->name . ';'; | |
797 } | |
798 | |
799 // Other | |
800 | |
801 protected function pStmt_Echo(Stmt\Echo_ $node) { | |
802 return 'echo ' . $this->pCommaSeparated($node->exprs) . ';'; | |
803 } | |
804 | |
805 protected function pStmt_Static(Stmt\Static_ $node) { | |
806 return 'static ' . $this->pCommaSeparated($node->vars) . ';'; | |
807 } | |
808 | |
809 protected function pStmt_Global(Stmt\Global_ $node) { | |
810 return 'global ' . $this->pCommaSeparated($node->vars) . ';'; | |
811 } | |
812 | |
813 protected function pStmt_StaticVar(Stmt\StaticVar $node) { | |
814 return '$' . $node->name | |
815 . (null !== $node->default ? ' = ' . $this->p($node->default) : ''); | |
816 } | |
817 | |
818 protected function pStmt_Unset(Stmt\Unset_ $node) { | |
819 return 'unset(' . $this->pCommaSeparated($node->vars) . ');'; | |
820 } | |
821 | |
822 protected function pStmt_InlineHTML(Stmt\InlineHTML $node) { | |
823 $newline = $node->getAttribute('hasLeadingNewline', true) ? "\n" : ''; | |
824 return '?>' . $this->pNoIndent($newline . $node->value) . '<?php '; | |
825 } | |
826 | |
827 protected function pStmt_HaltCompiler(Stmt\HaltCompiler $node) { | |
828 return '__halt_compiler();' . $node->remaining; | |
829 } | |
830 | |
831 protected function pStmt_Nop(Stmt\Nop $node) { | |
832 return ''; | |
833 } | |
834 | |
835 // Helpers | |
836 | |
837 protected function pType($node) { | |
838 return is_string($node) ? $node : $this->p($node); | |
839 } | |
840 | |
841 protected function pClassCommon(Stmt\Class_ $node, $afterClassToken) { | |
842 return $this->pModifiers($node->flags) | |
843 . 'class' . $afterClassToken | |
844 . (null !== $node->extends ? ' extends ' . $this->p($node->extends) : '') | |
845 . (!empty($node->implements) ? ' implements ' . $this->pCommaSeparated($node->implements) : '') | |
846 . "\n" . '{' . $this->pStmts($node->stmts) . "\n" . '}'; | |
847 } | |
848 | |
849 protected function pObjectProperty($node) { | |
850 if ($node instanceof Expr) { | |
851 return '{' . $this->p($node) . '}'; | |
852 } else { | |
853 return $node; | |
854 } | |
855 } | |
856 | |
857 protected function pModifiers($modifiers) { | |
858 return ($modifiers & Stmt\Class_::MODIFIER_PUBLIC ? 'public ' : '') | |
859 . ($modifiers & Stmt\Class_::MODIFIER_PROTECTED ? 'protected ' : '') | |
860 . ($modifiers & Stmt\Class_::MODIFIER_PRIVATE ? 'private ' : '') | |
861 . ($modifiers & Stmt\Class_::MODIFIER_STATIC ? 'static ' : '') | |
862 . ($modifiers & Stmt\Class_::MODIFIER_ABSTRACT ? 'abstract ' : '') | |
863 . ($modifiers & Stmt\Class_::MODIFIER_FINAL ? 'final ' : ''); | |
864 } | |
865 | |
866 protected function pEncapsList(array $encapsList, $quote) { | |
867 $return = ''; | |
868 foreach ($encapsList as $element) { | |
869 if ($element instanceof Scalar\EncapsedStringPart) { | |
870 $return .= $this->escapeString($element->value, $quote); | |
871 } else { | |
872 $return .= '{' . $this->p($element) . '}'; | |
873 } | |
874 } | |
875 | |
876 return $return; | |
877 } | |
878 | |
879 protected function escapeString($string, $quote) { | |
880 if (null === $quote) { | |
881 // For doc strings, don't escape newlines | |
882 $escaped = addcslashes($string, "\t\f\v$\\"); | |
883 } else { | |
884 $escaped = addcslashes($string, "\n\r\t\f\v$" . $quote . "\\"); | |
885 } | |
886 | |
887 // Escape other control characters | |
888 return preg_replace_callback('/([\0-\10\16-\37])(?=([0-7]?))/', function ($matches) { | |
889 $oct = decoct(ord($matches[1])); | |
890 if ($matches[2] !== '') { | |
891 // If there is a trailing digit, use the full three character form | |
892 return '\\' . str_pad($oct, 3, '0', STR_PAD_LEFT); | |
893 } | |
894 return '\\' . $oct; | |
895 }, $escaped); | |
896 } | |
897 | |
898 protected function containsEndLabel($string, $label, $atStart = true, $atEnd = true) { | |
899 $start = $atStart ? '(?:^|[\r\n])' : '[\r\n]'; | |
900 $end = $atEnd ? '(?:$|[;\r\n])' : '[;\r\n]'; | |
901 return false !== strpos($string, $label) | |
902 && preg_match('/' . $start . $label . $end . '/', $string); | |
903 } | |
904 | |
905 protected function encapsedContainsEndLabel(array $parts, $label) { | |
906 foreach ($parts as $i => $part) { | |
907 $atStart = $i === 0; | |
908 $atEnd = $i === count($parts) - 1; | |
909 if ($part instanceof Scalar\EncapsedStringPart | |
910 && $this->containsEndLabel($part->value, $label, $atStart, $atEnd) | |
911 ) { | |
912 return true; | |
913 } | |
914 } | |
915 return false; | |
916 } | |
917 | |
918 protected function pDereferenceLhs(Node $node) { | |
919 if ($node instanceof Expr\Variable | |
920 || $node instanceof Name | |
921 || $node instanceof Expr\ArrayDimFetch | |
922 || $node instanceof Expr\PropertyFetch | |
923 || $node instanceof Expr\StaticPropertyFetch | |
924 || $node instanceof Expr\FuncCall | |
925 || $node instanceof Expr\MethodCall | |
926 || $node instanceof Expr\StaticCall | |
927 || $node instanceof Expr\Array_ | |
928 || $node instanceof Scalar\String_ | |
929 || $node instanceof Expr\ConstFetch | |
930 || $node instanceof Expr\ClassConstFetch | |
931 ) { | |
932 return $this->p($node); | |
933 } else { | |
934 return '(' . $this->p($node) . ')'; | |
935 } | |
936 } | |
937 | |
938 protected function pCallLhs(Node $node) { | |
939 if ($node instanceof Name | |
940 || $node instanceof Expr\Variable | |
941 || $node instanceof Expr\ArrayDimFetch | |
942 || $node instanceof Expr\FuncCall | |
943 || $node instanceof Expr\MethodCall | |
944 || $node instanceof Expr\StaticCall | |
945 || $node instanceof Expr\Array_ | |
946 ) { | |
947 return $this->p($node); | |
948 } else { | |
949 return '(' . $this->p($node) . ')'; | |
950 } | |
951 } | |
952 | |
953 private function hasNodeWithComments(array $nodes) { | |
954 foreach ($nodes as $node) { | |
955 if ($node && $node->getAttribute('comments')) { | |
956 return true; | |
957 } | |
958 } | |
959 return false; | |
960 } | |
961 | |
962 private function pMaybeMultiline(array $nodes, $trailingComma = false) { | |
963 if (!$this->hasNodeWithComments($nodes)) { | |
964 return $this->pCommaSeparated($nodes); | |
965 } else { | |
966 return $this->pCommaSeparatedMultiline($nodes, $trailingComma) . "\n"; | |
967 } | |
968 } | |
969 } |