Test Failed
Pull Request — master (#124)
by Andrii
12:57
created

PhpPrinter   A

Complexity

Total Complexity 23

Size/Duplication

Total Lines 146
Duplicated Lines 0 %

Importance

Changes 2
Bugs 1 Features 1
Metric Value
wmc 23
eloc 39
c 2
b 1
f 1
dl 0
loc 146
rs 10

15 Methods

Rating   Name   Duplication   Size   Complexity  
A pExpr_ArrowFunction() 0 3 1
A pExpr_Include() 0 3 1
A my_hasNodeWithComments() 0 7 4
A resolveTokens() 0 12 3
A pScalar_MagicConst_Dir() 0 2 1
A pExpr_MethodCall() 0 3 1
A pExpr_Eval() 0 3 1
A pExpr_New() 0 3 1
A pStmt_Function() 0 3 1
A pScalar_MagicConst_File() 0 2 1
A pExpr_StaticCall() 0 12 2
A pExpr_Closure() 0 3 1
A my_pMaybeMultiline() 0 5 2
A pStmt_ClassMethod() 0 3 1
A tokenize() 0 10 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Composer\Config\Util;
6
7
use PhpParser\Node\Expr;
8
use PhpParser\Node\Scalar\MagicConst;
9
use PhpParser\Node\Stmt;
10
use PhpParser\PrettyPrinter\Standard;
11
12
class PhpPrinter extends Standard
13
{
14
    private bool $isBuildtime = false;
15
16
    protected function pExpr_MethodCall(Expr\MethodCall $node)
17
    {
18
        return $this->tokenize(parent::pExpr_MethodCall($node));
19
    }
20
21
    protected function pExpr_StaticCall(Expr\StaticCall $node)
22
    {
23
        $class = $this->pDereferenceLhs($node->class);
24
        if ('Buildtime' === $class) {
25
            $this->isBuildtime = true;
26
            $res = $this->my_pMaybeMultiline($node->args);
27
            $this->isBuildtime = false;
28
29
            return $res;
30
        }
31
32
        return $this->tokenize(parent::pExpr_StaticCall($node));
33
    }
34
35
    protected function pExpr_Eval(Expr\Eval_ $node)
36
    {
37
        return $this->tokenize(parent::pExpr_Eval($node));
38
    }
39
40
    protected function pExpr_Include(Expr\Include_ $node)
41
    {
42
        return $this->tokenize(parent::pExpr_Include($node));
43
    }
44
45
    // XXX Did not find it useful. What is it for?
46
    //protected function pExpr_ArrayItem(Expr\ArrayItem $node)
47
    //{
48
    //    $code = ($node->byRef ? '&' : '')
49
    //        . ($node->unpack ? '...' : '')
50
    //        . $this->p($node->value);
51
52
    //    if (isset($node->value) && $node->value instanceof Expr\FuncCall) {
53
    //        $code = $this->tokenize($code);
54
    //    }
55
56
    //    return (null !== $node->key ? $this->p($node->key) . ' => ' : '')
57
    //        . $code;
58
    //}
59
60
    protected function pExpr_Closure(Expr\Closure $node)
61
    {
62
        return $this->tokenize(parent::pExpr_Closure($node));
63
    }
64
65
    protected function pExpr_ArrowFunction(Expr\ArrowFunction $node)
66
    {
67
        return $this->tokenize(parent::pExpr_ArrowFunction($node));
68
    }
69
70
    protected function pExpr_New(Expr\New_ $node)
71
    {
72
        return $this->tokenize(parent::pExpr_New($node));
73
    }
74
75
    // XXX Can we get rid of `ReverseBlockMerge`
76
    //protected function pExpr_New(Expr\New_ $node) {
77
    //    if ($node->class instanceof Stmt\Class_) {
78
    //        $args = $node->args ? '(' . $this->pMaybeMultiline($node->args) . ')' : '';
79
    //        $code = 'new ' . $this->pClassCommon($node->class, $args);
80
    //        $token = '\'__' . md5($code) . '__\'';
81
    //        $this->options['builder']->closures[$token] = $code;
82
    //        return $token;
83
    //    }
84
    //    $code = 'new ' . $this->pNewVariable($node->class)
85
    //        . '(' . $this->pMaybeMultiline($node->args) . ')';
86
    //    if($this->pNewVariable($node->class) == 'ReverseBlockMerge'){
87
    //        return $code;
88
    //    }
89
    //    $token = '\'__' . md5($code) . '__\'';
90
    //    $this->options['builder']->closures[$token] = $code;
91
    //    return $token;
92
    //}
93
94
    protected function pStmt_ClassMethod(Stmt\ClassMethod $node)
95
    {
96
        return $this->tokenize(parent::pStmt_ClassMethod($node));
97
    }
98
99
    protected function pStmt_Function(Stmt\Function_ $node)
100
    {
101
        return $this->tokenize(parent::pStmt_Function($node));
102
    }
103
104
    protected function pScalar_MagicConst_Dir(MagicConst\Dir $node) {
105
        return "'{$this->options['THE_DIR']}'";
106
    }
107
108
    protected function pScalar_MagicConst_File(MagicConst\File $node) {
109
        return "'{$this->options['THE_FILE']}'";
110
    }
111
112
    private static array $tokens = [];
113
114
    protected function tokenize(string $code): string
115
    {
116
        if ($this->isBuildtime) {
117
            return $code;
118
        }
119
120
        $token = "'__" . md5($code) . "__'";
121
        static::$tokens[$token] = $code;
0 ignored issues
show
Bug introduced by
Since $tokens is declared private, accessing it with static will lead to errors in possible sub-classes; you can either use self, or increase the visibility of $tokens to at least protected.
Loading history...
122
123
        return $token;
124
    }
125
126
    public static function resolveTokens(string $output): string
127
    {
128
        $limit = 10;
129
        while (preg_match('~\'__(\w+)__\'~', $output)) {
130
            // TODO will be fixed soon
131
            if (--$limit<1) {
132
                throw new \Exception('too much');
133
            }
134
            $output = strtr($output, static::$tokens);
0 ignored issues
show
Bug introduced by
Since $tokens is declared private, accessing it with static will lead to errors in possible sub-classes; you can either use self, or increase the visibility of $tokens to at least protected.
Loading history...
135
        }
136
137
        return $output;
138
    }
139
140
    /**
141
     * XXX could these methods be converted to protected in php-parser?
142
     */
143
    protected function my_pMaybeMultiline(array $nodes, bool $trailingComma = false) {
144
        if (!$this->my_hasNodeWithComments($nodes)) {
145
            return $this->pCommaSeparated($nodes);
146
        } else {
147
            return $this->pCommaSeparatedMultiline($nodes, $trailingComma) . $this->nl;
148
        }
149
    }
150
151
    protected function my_hasNodeWithComments(array $nodes) {
152
        foreach ($nodes as $node) {
153
            if ($node && $node->getComments()) {
154
                return true;
155
            }
156
        }
157
        return false;
158
    }
159
}
160