1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* @author Patsura Dmitry https://github.com/ovr <[email protected]> |
4
|
|
|
*/ |
5
|
|
|
|
6
|
|
|
namespace PHPSA\Definition; |
7
|
|
|
|
8
|
|
|
use PhpParser\Node; |
9
|
|
|
use PHPSA\CompiledExpression; |
10
|
|
|
use PHPSA\Compiler\Parameter; |
11
|
|
|
use PHPSA\Compiler\Types; |
12
|
|
|
use PHPSA\Compiler\Event; |
13
|
|
|
use PHPSA\Context; |
14
|
|
|
use PHPSA\ControlFlow\ControlFlowGraph; |
15
|
|
|
|
16
|
|
|
/** |
17
|
|
|
* Class Method Definition |
18
|
|
|
*/ |
19
|
|
|
class ClassMethod extends AbstractDefinition |
20
|
|
|
{ |
21
|
|
|
/** |
22
|
|
|
* Contains a number representing all modifiers (public, static, ...) |
23
|
|
|
* |
24
|
|
|
* @var int |
25
|
|
|
*/ |
26
|
|
|
protected $type; |
27
|
|
|
|
28
|
|
|
/** |
29
|
|
|
* @var Node\Stmt\ClassMethod |
30
|
|
|
*/ |
31
|
|
|
protected $statement; |
32
|
|
|
|
33
|
|
|
/** |
34
|
|
|
* @var \PHPSA\ControlFlow\ControlFlowGraph |
35
|
|
|
*/ |
36
|
|
|
protected $cfg; |
37
|
|
|
|
38
|
|
|
/** |
39
|
|
|
* Return type |
40
|
|
|
* |
41
|
|
|
* @var int |
42
|
|
|
*/ |
43
|
|
|
protected $returnType = CompiledExpression::UNKNOWN; |
44
|
|
|
|
45
|
|
|
/** |
46
|
|
|
* Array of possible return values |
47
|
|
|
* |
48
|
|
|
* @var array |
49
|
|
|
*/ |
50
|
|
|
protected $possibleReturnValues = []; |
51
|
|
|
|
52
|
|
|
/** |
53
|
|
|
* @param string $name |
54
|
|
|
* @param Node\Stmt\ClassMethod $statement |
55
|
|
|
* @param integer $type |
56
|
|
|
*/ |
57
|
50 |
|
public function __construct($name, Node\Stmt\ClassMethod $statement, $type) |
58
|
|
|
{ |
59
|
50 |
|
$this->name = $name; |
60
|
50 |
|
$this->statement = $statement; |
61
|
50 |
|
$this->type = $type; |
62
|
|
|
|
63
|
|
|
// @todo Better support... |
64
|
50 |
|
$returnType = $statement->getReturnType(); |
65
|
50 |
|
if ($returnType == 'void') { |
66
|
1 |
|
$this->returnType = CompiledExpression::VOID; |
67
|
1 |
|
} |
68
|
50 |
|
} |
69
|
|
|
|
70
|
|
|
/** |
71
|
|
|
* @param Context $context |
72
|
|
|
* @return boolean|null |
73
|
|
|
*/ |
74
|
49 |
|
public function compile(Context $context) |
75
|
|
|
{ |
76
|
49 |
|
$context->getEventManager()->fire( |
77
|
49 |
|
Event\StatementBeforeCompile::EVENT_NAME, |
78
|
49 |
|
new Event\StatementBeforeCompile( |
79
|
49 |
|
$this->statement, |
80
|
|
|
$context |
81
|
49 |
|
) |
82
|
49 |
|
); |
83
|
|
|
|
84
|
49 |
|
$this->compiled = true; |
85
|
49 |
|
$context->scopePointer = $this->getPointer(); |
86
|
|
|
|
87
|
|
|
/** |
88
|
|
|
* It's not needed to compile empty method via it's abstract |
89
|
|
|
*/ |
90
|
49 |
|
if ($this->isAbstract()) { |
91
|
|
|
/** @var ClassDefinition $scope */ |
92
|
1 |
|
$scope = $context->scope; |
93
|
1 |
|
if (!$scope->isAbstract()) { |
94
|
|
|
$context->notice( |
95
|
|
|
'not-abstract-class-with-abstract-method', |
96
|
|
|
'Class must be abstract', |
97
|
|
|
$this->statement |
98
|
|
|
); |
99
|
|
|
} |
100
|
|
|
|
101
|
1 |
|
return true; |
102
|
|
|
} |
103
|
|
|
|
104
|
49 |
|
if ($this->statement->params) { |
|
|
|
|
105
|
6 |
|
foreach ($this->statement->params as $parameter) { |
106
|
6 |
|
$type = CompiledExpression::UNKNOWN; |
107
|
|
|
|
108
|
6 |
|
if ($parameter->type) { |
109
|
|
|
if (is_string($parameter->type)) { |
110
|
|
|
$type = Types::getType($parameter->type); |
111
|
|
|
} elseif ($parameter->type instanceof Node\Name) { |
112
|
|
|
$type = CompiledExpression::OBJECT; |
113
|
|
|
} |
114
|
|
|
} |
115
|
|
|
|
116
|
6 |
|
$context->addVariable( |
117
|
6 |
|
new Parameter($parameter->name, null, $type, $parameter->byRef) |
118
|
6 |
|
); |
119
|
6 |
|
} |
120
|
6 |
|
} |
121
|
|
|
|
122
|
49 |
|
foreach ($this->statement->stmts as $st) { |
123
|
48 |
|
\PHPSA\nodeVisitorFactory($st, $context); |
124
|
49 |
|
} |
125
|
|
|
|
126
|
49 |
|
$this->cfg = new ControlFlowGraph( |
127
|
49 |
|
$this->statement, |
128
|
|
|
$context |
129
|
49 |
|
); |
130
|
49 |
|
} |
131
|
|
|
|
132
|
|
|
/** |
133
|
|
|
* @param Context $context |
134
|
|
|
* @param CompiledExpression[] $args |
135
|
|
|
* @return CompiledExpression |
136
|
|
|
* @throws \PHPSA\Exception\RuntimeException |
137
|
|
|
*/ |
138
|
|
|
public function run(Context $context, array $args = null) |
|
|
|
|
139
|
|
|
{ |
140
|
|
|
return new CompiledExpression(); |
141
|
|
|
} |
142
|
|
|
|
143
|
|
|
/** |
144
|
|
|
* @return bool |
145
|
|
|
*/ |
146
|
49 |
|
public function isAbstract() |
147
|
|
|
{ |
148
|
49 |
|
return (bool) ($this->type & Node\Stmt\Class_::MODIFIER_ABSTRACT); |
149
|
|
|
} |
150
|
|
|
|
151
|
|
|
/** |
152
|
|
|
* @return bool |
153
|
|
|
*/ |
154
|
49 |
|
public function isStatic() |
155
|
|
|
{ |
156
|
49 |
|
return (bool) ($this->type & Node\Stmt\Class_::MODIFIER_STATIC); |
157
|
|
|
} |
158
|
|
|
|
159
|
|
|
/** |
160
|
|
|
* @return bool |
161
|
|
|
*/ |
162
|
|
|
public function isPublic() |
163
|
|
|
{ |
164
|
|
|
return ($this->type & Node\Stmt\Class_::MODIFIER_PUBLIC) !== 0 || $this->type === 0; |
165
|
|
|
} |
166
|
|
|
|
167
|
|
|
/** |
168
|
|
|
* @return bool |
169
|
|
|
*/ |
170
|
|
|
public function isProtected() |
171
|
|
|
{ |
172
|
|
|
return (bool) ($this->type & Node\Stmt\Class_::MODIFIER_PROTECTED); |
173
|
|
|
} |
174
|
|
|
|
175
|
|
|
/** |
176
|
|
|
* @return bool |
177
|
|
|
*/ |
178
|
|
|
public function isPrivate() |
179
|
|
|
{ |
180
|
|
|
return (bool) ($this->type & Node\Stmt\Class_::MODIFIER_PRIVATE); |
181
|
|
|
} |
182
|
|
|
|
183
|
|
|
/** |
184
|
|
|
* @param integer $newType |
185
|
|
|
*/ |
186
|
35 |
|
public function addNewType($newType) |
187
|
|
|
{ |
188
|
35 |
|
if ($this->returnType != CompiledExpression::VOID) { |
189
|
35 |
|
$this->returnType = $this->returnType | $newType; |
190
|
35 |
|
} else { |
191
|
1 |
|
$this->returnType = $newType; |
192
|
|
|
} |
193
|
35 |
|
} |
194
|
|
|
|
195
|
|
|
/** |
196
|
|
|
* @return int |
197
|
|
|
*/ |
198
|
1 |
|
public function getReturnType() |
199
|
|
|
{ |
200
|
1 |
|
return $this->returnType; |
201
|
|
|
} |
202
|
|
|
|
203
|
|
|
/** |
204
|
|
|
* @param $value |
205
|
|
|
*/ |
206
|
35 |
|
public function addReturnPossibleValue($value) |
207
|
|
|
{ |
208
|
35 |
|
$this->possibleReturnValues[] = $value; |
209
|
35 |
|
} |
210
|
|
|
|
211
|
|
|
/** |
212
|
|
|
* @return array |
213
|
|
|
*/ |
214
|
|
|
public function getPossibleReturnValues() |
215
|
|
|
{ |
216
|
|
|
return $this->possibleReturnValues; |
217
|
|
|
} |
218
|
|
|
|
219
|
|
|
/** |
220
|
|
|
* @return Node\Param[] |
221
|
|
|
*/ |
222
|
1 |
|
public function getParams() |
223
|
|
|
{ |
224
|
1 |
|
return $this->statement->params; |
225
|
|
|
} |
226
|
|
|
|
227
|
|
|
/** |
228
|
|
|
* @return int |
229
|
|
|
*/ |
230
|
|
|
public function getModifier() |
231
|
|
|
{ |
232
|
|
|
return $this->type; |
233
|
|
|
} |
234
|
|
|
|
235
|
|
|
/** |
236
|
|
|
* @param int $type |
237
|
|
|
*/ |
238
|
|
|
public function setModifier($type) |
239
|
|
|
{ |
240
|
|
|
$this->type = $type; |
241
|
|
|
} |
242
|
|
|
|
243
|
|
|
/** |
244
|
|
|
* @return \PHPSA\ControlFlow\ControlFlowGraph |
245
|
|
|
*/ |
246
|
|
|
public function getCFG() |
247
|
|
|
{ |
248
|
|
|
return $this->cfg; |
249
|
|
|
} |
250
|
|
|
} |
251
|
|
|
|
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.