annotate vendor/nikic/php-parser/lib/PhpParser/PrettyPrinter/Standard.php @ 19:fa3358dc1485 tip

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