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
|
|
|
/** |
25
|
|
|
* MethodGenerator constructor. |
26
|
|
|
* |
27
|
|
|
* @param AbstractGenerator $parent Parent generator |
28
|
|
|
*/ |
29
|
|
|
public function __construct(AbstractGenerator $parent = null) |
30
|
|
|
{ |
31
|
|
|
$this->parent = $parent; |
32
|
|
|
} |
33
|
|
|
|
34
|
|
|
/** |
35
|
|
|
* Increase indentation. |
36
|
|
|
* |
37
|
|
|
* @return $this|AbstractGenerator |
38
|
|
|
*/ |
39
|
|
|
public function increaseIndentation() : AbstractGenerator |
40
|
|
|
{ |
41
|
|
|
$this->indentation++; |
42
|
|
|
|
43
|
|
|
return $this; |
44
|
|
|
} |
45
|
|
|
|
46
|
|
|
/** |
47
|
|
|
* Decrease indentation. |
48
|
|
|
* |
49
|
|
|
* @return $this|AbstractGenerator |
50
|
|
|
*/ |
51
|
|
|
public function decreaseIndentation() : AbstractGenerator |
52
|
|
|
{ |
53
|
|
|
$this->indentation--; |
54
|
|
|
|
55
|
|
|
return $this; |
56
|
|
|
} |
57
|
|
|
|
58
|
|
|
/** |
59
|
|
|
* Close current generator and return parent. |
60
|
|
|
* |
61
|
|
|
* @return AbstractGenerator|ClassGenerator|FunctionGenerator|MethodGenerator|PropertyGenerator|ClassConstantGenerator |
62
|
|
|
*/ |
63
|
|
|
public function end() : AbstractGenerator |
64
|
|
|
{ |
65
|
|
|
// Create array item |
66
|
|
|
$class = get_class($this); |
67
|
|
|
if (!array_key_exists($class, $this->parent->generatedCode)) { |
68
|
|
|
$this->parent->generatedCode[$class] = ''; |
69
|
|
|
} |
70
|
|
|
|
71
|
|
|
// Pass generated code to parent |
72
|
|
|
$this->parent->generatedCode[$class] .= $this->code($this->indentation); |
73
|
|
|
|
74
|
|
|
return $this->parent; |
75
|
|
|
} |
76
|
|
|
|
77
|
|
|
/** |
78
|
|
|
* Generate code. |
79
|
|
|
* |
80
|
|
|
* @param int $indentation Code level |
81
|
|
|
* |
82
|
|
|
* @return string Generated code |
83
|
|
|
*/ |
84
|
|
|
abstract public function code(int $indentation = 0) : string; |
85
|
|
|
|
86
|
|
|
/** |
87
|
|
|
* Set Comments block. |
88
|
|
|
* |
89
|
|
|
* @return CommentsGenerator Comments block generator |
90
|
|
|
*/ |
91
|
|
|
public function defComment() : CommentsGenerator |
92
|
|
|
{ |
93
|
|
|
return (new CommentsGenerator($this))->setIndentation($this->indentation); |
94
|
|
|
} |
95
|
|
|
|
96
|
|
|
/** |
97
|
|
|
* Decrease indentation. |
98
|
|
|
* |
99
|
|
|
* @param int $indentation |
100
|
|
|
* |
101
|
|
|
* @return $this|AbstractGenerator|ClassGenerator |
102
|
|
|
*/ |
103
|
|
|
public function setIndentation(int $indentation) : AbstractGenerator |
104
|
|
|
{ |
105
|
|
|
$this->indentation = $indentation; |
106
|
|
|
|
107
|
|
|
return $this; |
108
|
|
|
} |
109
|
|
|
|
110
|
|
|
/** |
111
|
|
|
* Get indentation string. |
112
|
|
|
* |
113
|
|
|
* @param int $indentation Code level |
114
|
|
|
* |
115
|
|
|
* @return string Indentation string |
116
|
|
|
*/ |
117
|
|
|
protected function indentation(int $indentation = 0) : string |
118
|
|
|
{ |
119
|
|
|
return implode('', $indentation > 0 ? array_fill(0, $indentation, ' ') : []); |
120
|
|
|
} |
121
|
|
|
|
122
|
|
|
/** |
123
|
|
|
* Generate correct value. |
124
|
|
|
* |
125
|
|
|
* Method handles arrays, numerics, strings and constants. |
126
|
|
|
* |
127
|
|
|
* @param mixed $value Value |
128
|
|
|
* |
129
|
|
|
* @return mixed Value |
130
|
|
|
*/ |
131
|
|
|
protected function parseValue($value) |
132
|
|
|
{ |
133
|
|
|
// If item value is array - recursion |
134
|
|
|
if (is_array($value)) { |
135
|
|
|
return $this->arrayValue($value); |
136
|
|
|
} elseif (is_numeric($value) || is_float($value)) { |
137
|
|
|
return $value; |
138
|
|
|
} elseif ($value === null) { |
139
|
|
|
return null; |
140
|
|
|
} else { |
141
|
|
|
try { // Try to evaluate |
142
|
|
|
eval('$value2 = ' . $value . ';'); |
143
|
|
|
return $value; |
144
|
|
|
} catch (\Throwable $e) { // Consider it as a string |
|
|
|
|
145
|
|
|
return '\''.$value.'\''; |
146
|
|
|
} |
147
|
|
|
} |
148
|
|
|
} |
149
|
|
|
|
150
|
|
|
/** |
151
|
|
|
* Get array values definition. |
152
|
|
|
* |
153
|
|
|
* @param array $items Array key-value pairs collection |
154
|
|
|
* |
155
|
|
|
* @return string Array value definition |
156
|
|
|
*/ |
157
|
|
|
protected function arrayValue(array $items = array()) |
158
|
|
|
{ |
159
|
|
|
$result = ['[']; |
160
|
|
|
if (count($items)) { |
161
|
|
|
$this->increaseIndentation(); |
162
|
|
|
|
163
|
|
|
// Iterate array items |
164
|
|
|
foreach ($items as $key => $value) { |
165
|
|
|
// Start array key definition |
166
|
|
|
$result[] = "\n" |
167
|
|
|
. $this->indentation($this->indentation) |
168
|
|
|
. $this->parseValue($key) |
169
|
|
|
. ' => ' |
170
|
|
|
. $this->parseValue($value) |
171
|
|
|
. ','; |
172
|
|
|
} |
173
|
|
|
|
174
|
|
|
$this->decreaseIndentation(); |
175
|
|
|
} |
176
|
|
|
$result[] = "\n".$this->indentation($this->indentation).']'; |
177
|
|
|
|
178
|
|
|
return implode('', $result); |
179
|
|
|
} |
180
|
|
|
} |
181
|
|
|
|
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
orexit
statements that have been added for debug purposes.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.