SyntaxHighlightPrinter::pStmt_Switch()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 8

Duplication

Lines 11
Ratio 100 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 11
loc 11
rs 9.4285
cc 1
eloc 8
nc 1
nop 1
1
<?php
2
3
namespace PhpSchool\PSX;
4
5
use PhpParser\PrettyPrinter\Standard;
6
use PhpParser\Node;
7
use PhpParser\Node\Scalar;
8
use PhpParser\Node\Expr;
9
use PhpParser\Node\Stmt;
10
use PhpParser\Node\Name;
11
12
/**
13
 * Class SyntaxHighlightPrinter
14
 * @package PhpSchool\PSX
15
 * @author Aydin Hassan <[email protected]>
16
 */
17
class SyntaxHighlightPrinter extends Standard
18
{
19
20
    /**
21
     * @var SyntaxHighlighterConfig
22
     */
23
    private $config;
24
25
    /**
26
     * @var ColourAdapterInterface
27
     */
28
    private $colourAdapter;
29
30
    /**
31
     * @param SyntaxHighlighterConfig $config
32
     * @param ColourAdapterInterface  $colourAdapter
33
     * @param array                   $options
34
     */
35
    public function __construct(
36
        SyntaxHighlighterConfig $config,
37
        ColourAdapterInterface $colourAdapter,
38
        array $options = []
39
    ) {
40
        $this->colourAdapter = $colourAdapter;
41
        parent::__construct($options);
42
        $this->config = $config;
43
    }
44
45
    /**
46
     * Pretty prints a file of statements (includes the opening <?php tag if it is required).
47
     *
48
     * @param Node[] $stmts Array of statements
49
     *
50
     * @return string Pretty printed statements
51
     */
52
    public function prettyPrintFile(array $stmts)
53
    {
54
        $p = rtrim($this->prettyPrint($stmts));
55
        $p = preg_replace('/^\?>\n?/', '', $p, -1, $count);
56
        $p = preg_replace('/<\?php$/', '', $p);
57
        if (!$count) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $count of type integer|null is loosely compared to false; this is ambiguous if the integer can be zero. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
58
            $p = sprintf("%s\n\n%s", $this->color('<?php', SyntaxHighlighterConfig::TYPE_OPEN_TAG), $p);
59
        }
60
        return $p;
61
    }
62
63
    /**
64
     * @param Stmt\Echo_ $node
65
     *
66
     * @return string
67
     */
68
    public function pStmt_Echo(Stmt\Echo_ $node)
69
    {
70
        return sprintf(
71
            '%s %s;',
72
            $this->color('echo', SyntaxHighlighterConfig::TYPE_CONSTRUCT),
73
            $this->pCommaSeparated($node->exprs)
74
        );
75
    }
76
77
    /**
78
     * @param Scalar\String_ $node
79
     *
80
     * @return string
81
     */
82
    public function pScalar_String(Scalar\String_ $node)
83
    {
84
        if ($node->hasAttribute('originalValue')) {
85
            $string = $node->getAttribute('originalValue');
86
        } else {
87
            $string = '\'' . $this->pNoIndent(addcslashes($node->value, '\'\\')) . '\'';
88
        }
89
        return $this->color($string, SyntaxHighlighterConfig::TYPE_STRING);
90
    }
91
92
    /**
93
     * @param Node $node
94
     *
95
     * @return string
96
     */
97
    protected function pCallLhs(Node $node)
98
    {
99
        if ($node instanceof Name
100
            || $node instanceof Expr\Variable
101
            || $node instanceof Expr\ArrayDimFetch
102
            || $node instanceof Expr\FuncCall
103
            || $node instanceof Expr\MethodCall
104
            || $node instanceof Expr\StaticCall
105
            || $node instanceof Expr\Array_
106
        ) {
107
            return $this->color($this->p($node), SyntaxHighlighterConfig::TYPE_LHS);
108
        } else {
109
            return '(' . $this->p($node) . ')';
110
        }
111
    }
112
113
    /**
114
     * @param Node $node
115
     *
116
     * @return string
117
     */
118
    protected function pDereferenceLhs(Node $node)
119
    {
120
        if ($node instanceof Expr\Variable
121
            || $node instanceof Name
122
            || $node instanceof Expr\ArrayDimFetch
123
            || $node instanceof Expr\PropertyFetch
124
            || $node instanceof Expr\StaticPropertyFetch
125
            || $node instanceof Expr\FuncCall
126
            || $node instanceof Expr\MethodCall
127
            || $node instanceof Expr\StaticCall
128
            || $node instanceof Expr\Array_
129
            || $node instanceof Scalar\String_
130
            || $node instanceof Expr\ConstFetch
131
            || $node instanceof Expr\ClassConstFetch
132
        ) {
133
            return $this->color($this->p($node), SyntaxHighlighterConfig::TYPE_LHS);
134
        } else {
135
            return '(' . $this->p($node) . ')';
136
        }
137
    }
138
139
    /**
140
     * @param Stmt\Return_ $node
141
     *
142
     * @return string
143
     */
144 View Code Duplication
    public function pStmt_Return(Stmt\Return_ $node)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
145
    {
146
        return sprintf(
147
            '%s%s;',
148
            $this->color('return', SyntaxHighlighterConfig::TYPE_RETURN_NEW),
149
            (null !== $node->expr ? ' ' . $this->p($node->expr) : '')
150
        );
151
    }
152
153
    // Control flow
154
155
    /**
156
     * @param Stmt\If_ $node
157
     *
158
     * @return string
159
     */
160
    public function pStmt_If(Stmt\If_ $node)
161
    {
162
        return sprintf(
163
            "%s (%s) %s%s\n%s%s%s",
164
            $this->color('if', SyntaxHighlighterConfig::TYPE_KEYWORD),
165
            $this->p($node->cond),
166
            $this->color('{', SyntaxHighlighterConfig::TYPE_BRACE),
167
            $this->pStmts($node->stmts),
168
            $this->color('}', SyntaxHighlighterConfig::TYPE_BRACE),
169
            $this->pImplode($node->elseifs),
170
            (null !== $node->else ? $this->p($node->else) : '')
171
        );
172
    }
173
174
    /**
175
     * @param Stmt\ElseIf_ $node
176
     *
177
     * @return string
178
     */
179 View Code Duplication
    public function pStmt_ElseIf(Stmt\ElseIf_ $node)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
180
    {
181
        return sprintf(
182
            " %s (%s) %s%s\n%s",
183
            $this->color('elseif', SyntaxHighlighterConfig::TYPE_KEYWORD),
184
            $this->p($node->cond),
185
            $this->color('{', SyntaxHighlighterConfig::TYPE_BRACE),
186
            $this->pStmts($node->stmts),
187
            $this->color('}', SyntaxHighlighterConfig::TYPE_BRACE)
188
        );
189
    }
190
191
    /**
192
     * @param Stmt\For_ $node
193
     *
194
     * @return string
195
     */
196
    public function pStmt_For(Stmt\For_ $node)
197
    {
198
        return sprintf(
199
            "%s (%s;%s%s;%s%s) %s%s\n%s",
200
            $this->color('for', SyntaxHighlighterConfig::TYPE_KEYWORD),
201
            $this->pCommaSeparated($node->init),
202
            (!empty($node->cond) ? ' ' : ''),
203
            $this->pCommaSeparated($node->cond),
204
            (!empty($node->loop) ? ' ' : ''),
205
            $this->pCommaSeparated($node->loop),
206
            $this->color('{', SyntaxHighlighterConfig::TYPE_BRACE),
207
            $this->pStmts($node->stmts),
208
            $this->color('}', SyntaxHighlighterConfig::TYPE_BRACE)
209
        );
210
    }
211
212
    /**
213
     * @param Stmt\Foreach_ $node
214
     *
215
     * @return string
216
     */
217
    public function pStmt_Foreach(Stmt\Foreach_ $node)
218
    {
219
        return sprintf(
220
            "%s (%s as %s%s%s) %s%s\n%s",
221
            $this->color('foreach', SyntaxHighlighterConfig::TYPE_KEYWORD),
222
            $this->p($node->expr),
223
            (null !== $node->keyVar ? $this->p($node->keyVar) . ' => ' : ''),
224
            ($node->byRef ? '&' : ''),
225
            $this->p($node->valueVar),
226
            $this->color('{', SyntaxHighlighterConfig::TYPE_BRACE),
227
            $this->pStmts($node->stmts),
228
            $this->color('}', SyntaxHighlighterConfig::TYPE_BRACE)
229
        );
230
    }
231
232
    /**
233
     * @param Stmt\While_ $node
234
     *
235
     * @return string
236
     */
237 View Code Duplication
    public function pStmt_While(Stmt\While_ $node)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
238
    {
239
        return sprintf(
240
            "%s (%s) %s%s\n%s",
241
            $this->color('while', SyntaxHighlighterConfig::TYPE_KEYWORD),
242
            $this->p($node->cond),
243
            $this->color('{', SyntaxHighlighterConfig::TYPE_BRACE),
244
            $this->pStmts($node->stmts),
245
            $this->color('}', SyntaxHighlighterConfig::TYPE_BRACE)
246
        );
247
    }
248
249
    /**
250
     * @param Stmt\Do_ $node
251
     *
252
     * @return string
253
     */
254 View Code Duplication
    public function pStmt_Do(Stmt\Do_ $node)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
255
    {
256
        return sprintf(
257
            "%s %s%s \n%s %s (%s);",
258
            $this->color('do', SyntaxHighlighterConfig::TYPE_KEYWORD),
259
            $this->color('{', SyntaxHighlighterConfig::TYPE_BRACE),
260
            $this->pStmts($node->stmts),
261
            $this->color('}', SyntaxHighlighterConfig::TYPE_BRACE),
262
            $this->color('while', SyntaxHighlighterConfig::TYPE_KEYWORD),
263
            $this->p($node->cond)
264
        );
265
    }
266
267
    /**
268
     * @param Stmt\Switch_ $node
269
     *
270
     * @return string
271
     */
272 View Code Duplication
    public function pStmt_Switch(Stmt\Switch_ $node)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
273
    {
274
        return sprintf(
275
            "%s (%s) %s%s\n%s",
276
            $this->color('switch', SyntaxHighlighterConfig::TYPE_KEYWORD),
277
            $this->p($node->cond),
278
            $this->color('{', SyntaxHighlighterConfig::TYPE_BRACE),
279
            $this->pStmts($node->cases),
280
            $this->color('}', SyntaxHighlighterConfig::TYPE_BRACE)
281
        );
282
    }
283
284
    /**
285
     * @param Stmt\Case_ $node
286
     *
287
     * @return string
288
     */
289
    public function pStmt_Case(Stmt\Case_ $node)
290
    {
291
        return sprintf(
292
            "%s:%s",
293
            (null !== $node->cond ? 'case ' . $this->p($node->cond) : 'default'),
294
            $this->pStmts($node->stmts)
295
        );
296
    }
297
298
    /**
299
     * @param Stmt\TryCatch $node
300
     *
301
     * @return string
302
     */
303
    public function pStmt_TryCatch(Stmt\TryCatch $node)
304
    {
305
        if ($node->finallyStmts !== null) {
306
            $finallyStatement = sprintf(
307
                " %s %s%s\n%s",
308
                $this->color('finally', SyntaxHighlighterConfig::TYPE_KEYWORD),
309
                $this->color('{', SyntaxHighlighterConfig::TYPE_BRACE),
310
                $this->pStmts($node->finallyStmts),
311
                $this->color('}', SyntaxHighlighterConfig::TYPE_BRACE)
312
            );
313
        } else {
314
            $finallyStatement = '';
315
        }
316
317
        return sprintf(
318
            "%s %s %s\n%s%s%s",
319
            $this->color('try', SyntaxHighlighterConfig::TYPE_KEYWORD),
320
            $this->color('{', SyntaxHighlighterConfig::TYPE_BRACE),
321
            $this->pStmts($node->stmts),
322
            $this->color('}', SyntaxHighlighterConfig::TYPE_BRACE),
323
            $this->pImplode($node->catches),
324
            $finallyStatement
325
        );
326
    }
327
328
    /**
329
     * @param Stmt\Catch_ $node
330
     *
331
     * @return string
332
     */
333 View Code Duplication
    public function pStmt_Catch(Stmt\Catch_ $node)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
334
    {
335
        return sprintf(
336
            " %s (%s $%s) %s%s\n%s",
337
            $this->color('catch', SyntaxHighlighterConfig::TYPE_KEYWORD),
338
            $this->p($node->type),
339
            $node->var,
340
            $this->color('{', SyntaxHighlighterConfig::TYPE_BRACE),
341
            $this->pStmts($node->stmts),
342
            $this->color('}', SyntaxHighlighterConfig::TYPE_BRACE)
343
        );
344
    }
345
346
    /**
347
     * @param Stmt\Break_ $node
348
     *
349
     * @return string
350
     */
351 View Code Duplication
    public function pStmt_Break(Stmt\Break_ $node)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
352
    {
353
        return sprintf(
354
            '%s%s;',
355
            $this->color('break', SyntaxHighlighterConfig::TYPE_KEYWORD),
356
            ($node->num !== null ? ' ' . $this->p($node->num) : '')
357
        );
358
    }
359
360
    /**
361
     * @param Stmt\Continue_ $node
362
     *
363
     * @return string
364
     */
365 View Code Duplication
    public function pStmt_Continue(Stmt\Continue_ $node)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
366
    {
367
        return sprintf(
368
            '%s%s;',
369
            $this->color('continue', SyntaxHighlighterConfig::TYPE_KEYWORD),
370
            ($node->num !== null ? ' ' . $this->p($node->num) : '')
371
        );
372
    }
373
374
    /**
375
     * @param Stmt\Throw_ $node
376
     *
377
     * @return string
378
     */
379
    public function pStmt_Throw(Stmt\Throw_ $node)
380
    {
381
        return sprintf(
382
            '%s %s;',
383
            $this->color('throw', SyntaxHighlighterConfig::TYPE_KEYWORD),
384
            $this->p($node->expr)
385
        );
386
    }
387
388
    /**
389
     * @param Stmt\Goto_ $node
390
     *
391
     * @return string
392
     */
393
    public function pStmt_Goto(Stmt\Goto_ $node)
394
    {
395
        return sprintf(
396
            '%s %s;',
397
            $this->color('goto', SyntaxHighlighterConfig::TYPE_KEYWORD),
398
            $node->name
399
        );
400
    }
401
402
    //Other
403
404
    /**
405
     * @param Expr\Closure $node
406
     *
407
     * @return string
408
     */
409
    public function pExpr_Closure(Expr\Closure $node)
410
    {
411
        return sprintf(
412
            "%s%s %s(%s)%s%s %s%s\n%s",
413
            ($node->static ? 'static ' : ''),
414
            $this->color('function', SyntaxHighlighterConfig::TYPE_KEYWORD),
415
            ($node->byRef ? '&' : ''),
416
            $this->pCommaSeparated($node->params),
417
            (!empty($node->uses) ? ' use(' . $this->pCommaSeparated($node->uses) . ')': ''),
418
            (null !== $node->returnType ? ' : ' . $this->pType($node->returnType) : ''),
419
            $this->color('{', SyntaxHighlighterConfig::TYPE_BRACE),
420
            $this->pStmts($node->stmts),
421
            $this->color('}', SyntaxHighlighterConfig::TYPE_BRACE)
422
        );
423
    }
424
425
    /**
426
     * @param Stmt\Else_ $node
427
     *
428
     * @return string
429
     */
430 View Code Duplication
    public function pStmt_Else(Stmt\Else_ $node)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
431
    {
432
        return sprintf(
433
            " %s %s%s\n%s",
434
            $this->color('else', SyntaxHighlighterConfig::TYPE_KEYWORD),
435
            $this->color('{', SyntaxHighlighterConfig::TYPE_BRACE),
436
            $this->pStmts($node->stmts),
437
            $this->color('}', SyntaxHighlighterConfig::TYPE_BRACE)
438
        );
439
    }
440
441
    /**
442
     * @param Expr\FuncCall $node
443
     *
444
     * @return string
445
     */
446
    public function pExpr_FuncCall(Expr\FuncCall $node)
447
    {
448
        return sprintf(
449
            '%s%s%s%s',
450
            $this->pCallLhs($node->name),
451
            $this->color('(', SyntaxHighlighterConfig::TYPE_CALL_PARENTHESIS),
452
            $this->pCommaSeparated($node->args),
453
            $this->color(')', SyntaxHighlighterConfig::TYPE_CALL_PARENTHESIS)
454
        );
455
    }
456
457
    /**
458
     * @param Expr\MethodCall $node
459
     *
460
     * @return string
461
     */
462
    public function pExpr_MethodCall(Expr\MethodCall $node)
463
    {
464
        return sprintf(
465
            '%s%s%s%s%s%s',
466
            $this->pDereferenceLhs($node->var),
467
            $this->color('->', SyntaxHighlighterConfig::TYPE_VAR_DEREF),
468
            $this->pObjectProperty($node->name),
469
            $this->color('(', SyntaxHighlighterConfig::TYPE_CALL_PARENTHESIS),
470
            $this->pCommaSeparated($node->args),
471
            $this->color(')', SyntaxHighlighterConfig::TYPE_CALL_PARENTHESIS)
472
        );
473
    }
474
475
    /**
476
     * @param Expr\New_ $node
477
     *
478
     * @return string
479
     */
480
    public function pExpr_New(Expr\New_ $node)
481
    {
482
        if ($node->class instanceof Stmt\Class_) {
483
            $args = $node->args ? '(' . $this->pCommaSeparated($node->args) . ')' : '';
484
            return 'new ' . $this->pClassCommon($node->class, $args);
485
        }
486
        return sprintf(
487
            '%s %s%s%s%s',
488
            $this->color('new', SyntaxHighlighterConfig::TYPE_RETURN_NEW),
489
            $this->color($this->p($node->class), SyntaxHighlighterConfig::TYPE_CLASS),
490
            $this->color('(', SyntaxHighlighterConfig::TYPE_CALL_PARENTHESIS),
491
            $this->pCommaSeparated($node->args),
492
            $this->color(')', SyntaxHighlighterConfig::TYPE_CALL_PARENTHESIS)
493
        );
494
    }
495
496
    /**
497
     * @param Expr\Array_ $node
498
     * @return string
499
     */
500
    public function pExpr_Array(Expr\Array_ $node)
501
    {
502
        if ($this->options['shortArraySyntax'] || !$node->hasAttribute('traditionalArray')) {
503
            return '[' . $this->pArrayList($node, $node->items) . ']';
504
        } else {
505
            return 'array(' . $this->pArrayList($node, $node->items) . ')';
506
        }
507
    }
508
509
    /**
510
     * @param Expr\Array_ $parent
511
     * @param Expr\ArrayItem[] $nodes
512
     * @return string
513
     */
514
    public function pArrayList(Expr\Array_ $parent, array $nodes)
515
    {
516
        $lineNumbers = [$parent->getAttribute('startLine', null)];
517
        foreach ($nodes as $node) {
518
            $lineNumbers[] = $node->getAttribute('startLine', null);
519
        }
520
        
521
        //all the same line
522
        if (count(array_unique($lineNumbers)) == 1) {
523
            return $this->pCommaSeparated($nodes);
524
        }
525
        
526
        $output = "\n";
527
        foreach ($nodes as $key => $node) {
528
            $output .= sprintf("    %s,\n", $this->p($node));
529
        }
530
        return $output;
531
    }
532
533
    /**
534
     * @param Expr\Exit_ $node
535
     * @return string
536
     */
537
    public function pExpr_Exit(Expr\Exit_ $node)
538
    {
539
        $construct = 'exit';
540
        if ($node->getAttribute('isDie', false)) {
541
            $construct = 'die';
542
        }
543
        
544
        return $construct . (null !== $node->expr ? '(' . $this->p($node->expr) . ')' : '');
545
    }
546
547
    /**
548
     * @param string $string
549
     * @param string $type
550
     *
551
     * @return string
552
     */
553
    protected function color($string, $type)
554
    {
555
        return $this->colourAdapter->colour(
556
            $string,
557
            $this->config->getColorForType($type)
558
        );
559
    }
560
}
561