Test Failed
Push — master ( c730e0...935351 )
by Vitaly
02:29
created

AbstractGenerator   A

Complexity

Total Complexity 24

Size/Duplication

Total Lines 208
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 1

Test Coverage

Coverage 61.4%

Importance

Changes 0
Metric Value
wmc 24
lcom 2
cbo 1
dl 0
loc 208
ccs 35
cts 57
cp 0.614
rs 10
c 0
b 0
f 0

12 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
B end() 0 22 4
code() 0 1 ?
A defComment() 0 4 1
A setIndentation() 0 6 1
A buildNestedCode() 0 9 2
A getNestedCode() 0 8 2
B parseValue() 0 18 6
A arrayValue() 0 23 3
A increaseIndentation() 0 4 1
A indentation() 0 4 2
A decreaseIndentation() 0 4 1
1
<?php declare(strict_types=1);
2
/**
3
 * Created by Vitaly Iegorov <[email protected]>.
4
 * on 03.09.16 at 11:37
5
 */
6
namespace samsonframework\generator;
7
8
/**
9
 * Abstract code generator.
10
 *
11
 * @author Vitaly Egorov <[email protected]>
12
 */
13
abstract class AbstractGenerator
14
{
15
    /** @var AbstractGenerator Parent class generator */
16
    protected $parent;
17
18
    /** @var array Generated code grouped by generator class name */
19
    protected $generatedCode = [];
20
21
    /** @var int Indentation level */
22
    protected $indentation = 0;
23
24
    /** @var bool Flag that class has already had generated its code */
25
    protected $isGenerated = false;
26
27
    /**
28
     * AbstractGenerator constructor.
29
     *
30
     * @param AbstractGenerator $parent Parent generator
31
     */
32 50
    public function __construct(AbstractGenerator $parent = null)
33
    {
34 50
        $this->parent = $parent;
35 50
    }
36
37
    /**
38
     * Close current generator and return parent.
39
     *
40
     * @return AbstractGenerator|ClassGenerator|FunctionGenerator|MethodGenerator|PropertyGenerator|ClassConstantGenerator|ConditionGenerator|IfGenerator
41
     */
42 9
    public function end() : AbstractGenerator
43
    {
44
        // Generate code
45 9
        $generatedCode = $this->code();
46
47
        // Avoid creating empty strings
48 9
        if (!$this->isGenerated && $generatedCode !== '') {
49
            // Create array item
50 9
            $class = get_class($this);
51 9
            if (!array_key_exists($class, $this->parent->generatedCode)) {
52 9
                $this->parent->generatedCode[$class] = [];
53
            }
54
55
            // Pass generated code to parent
56 9
            $this->parent->generatedCode[$class][] = $generatedCode;
57
58
            // Set flag that we already generated code for this class
59 9
            $this->isGenerated = true;
60
        }
61
62 9
        return $this->parent;
63
    }
64
65
    /**
66
     * Generate code.
67
     *
68
     * @return string Generated code
69
     */
70
    abstract public function code(): string;
71
72
    /**
73
     * Set Comments block.
74
     *
75
     * @return CommentsGenerator Comments block generator
76
     */
77 1
    public function defComment() : CommentsGenerator
78
    {
79 1
        return (new CommentsGenerator($this))->setIndentation($this->indentation);
80
    }
81
82
    /**
83
     * Decrease indentation.
84
     *
85
     * @param int $indentation
86
     *
87
     * @return $this|AbstractGenerator|ClassGenerator
88
     */
89 21
    public function setIndentation(int $indentation): AbstractGenerator
90
    {
91 21
        $this->indentation = $indentation;
92
93 21
        return $this;
94
    }
95
96
    /**
97
     * Build nested class code array.
98
     *
99
     * @param string $className     Nested class name
100
     * @param array  $formattedCode Collection of code
101
     *
102
     * @return array Collection of code with added nested class code
103
     */
104 20
    protected function buildNestedCode(string $className, array $formattedCode = []): array
105
    {
106 20
        $code = $this->getNestedCode($className);
107 20
        if ($code !== '') {
108 7
            $formattedCode[] = $code;
109
        }
110
111 20
        return $formattedCode;
112
    }
113
114
    /**
115
     * Get generated nested code.
116
     *
117
     * @param string $className Nested class name
118
     *
119
     * @return string Generated nested code or empty string
120
     */
121 29
    protected function getNestedCode(string $className): string
122
    {
123 29
        if (array_key_exists($className, $this->generatedCode)) {
124 9
            return ltrim(implode("", $this->generatedCode[$className]), "\n");
125
        } else {
126 27
            return '';
127
        }
128
    }
129
130
    /**
131
     * Generate correct value.
132
     *
133
     * Method handles arrays, numerics, strings and constants.
134
     *
135
     * @param mixed $value Value
136
     *
137
     * @return mixed Value
138
     */
139 4
    protected function parseValue($value)
140
    {
141
        // If item value is array - recursion
142 4
        if (is_array($value)) {
143
            return $this->arrayValue($value);
144 4
        } elseif (is_numeric($value) || is_float($value)) {
145
            return $value;
146 4
        } elseif ($value === null) {
147 4
            return null;
148
        } else {
149
            try { // Try to evaluate
150
                eval('$value2 = ' . $value . ';');
151
                return $value;
152
            } catch (\Throwable $e) { // Consider it as a string
0 ignored issues
show
Unused Code introduced by
catch (\Throwable $e) { ...'\'' . $value . '\''; } does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
Bug introduced by
The class Throwable does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
153
                return '\''.$value.'\'';
154
            }
155
        }
156
    }
157
158
    /**
159
     * Get array values definition.
160
     *
161
     * @param array $items Array key-value pairs collection
162
     *
163
     * @return string Array value definition
164
     */
165
    protected function arrayValue(array $items = array())
166
    {
167
        $result = ['['];
168
        if (count($items)) {
169
            $this->increaseIndentation();
170
171
            // Iterate array items
172
            foreach ($items as $key => $value) {
173
                // Start array key definition
174
                $result[] = "\n"
175
                    . $this->indentation($this->indentation)
176
                    . $this->parseValue($key)
177
                    . ' => '
178
                    . $this->parseValue($value)
179
                    . ',';
180
            }
181
182
            $this->decreaseIndentation();
183
        }
184
        $result[] = "\n".$this->indentation($this->indentation).']';
185
186
        return implode('', $result);
187
    }
188
189
    /**
190
     * Increase indentation.
191
     *
192
     * @return $this|AbstractGenerator
193
     */
194 6
    public function increaseIndentation(): AbstractGenerator
195
    {
196 6
        return $this->setIndentation($this->indentation + 1);
197
    }
198
199
    /**
200
     * Get indentation string.
201
     *
202
     * @param int $indentation Code level
203
     *
204
     * @return string Indentation string
205
     */
206 41
    protected function indentation(int $indentation = 0): string
207
    {
208 41
        return implode('', $indentation > 0 ? array_fill(0, $indentation, '    ') : []);
209
    }
210
211
    /**
212
     * Decrease indentation.
213
     *
214
     * @return $this|AbstractGenerator
215
     */
216
    public function decreaseIndentation(): AbstractGenerator
217
    {
218
        return $this->setIndentation($this->indentation - 1);
219
    }
220
}
221