Complex classes like Expression often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use Expression, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
20 | class Expression |
||
|
|||
21 | { |
||
22 | /** |
||
23 | * @var Context |
||
24 | */ |
||
25 | protected $context; |
||
26 | |||
27 | /** |
||
28 | * @var EventManager |
||
29 | */ |
||
30 | protected $eventManager; |
||
31 | |||
32 | /** |
||
33 | * @param Context $context |
||
34 | */ |
||
35 | 738 | public function __construct(Context $context, EventManager $eventManager) |
|
40 | |||
41 | /** |
||
42 | * @param $expr |
||
43 | * @return ExpressionCompilerInterface|AbstractExpressionCompiler |
||
44 | */ |
||
45 | 721 | protected function factory($expr) |
|
46 | { |
||
47 | 721 | switch (get_class($expr)) { |
|
48 | /** |
||
49 | * Call(s) |
||
50 | */ |
||
51 | 721 | case Node\Expr\MethodCall::class: |
|
52 | return new Expression\MethodCall(); |
||
53 | 721 | case Node\Expr\FuncCall::class: |
|
54 | 10 | return new Expression\FunctionCall(); |
|
55 | 713 | case Node\Expr\StaticCall::class: |
|
56 | return new Expression\StaticCall(); |
||
57 | /** |
||
58 | * Operators |
||
59 | */ |
||
60 | 713 | case Node\Expr\New_::class: |
|
61 | 2 | return new Expression\Operators\NewOp(); |
|
62 | 711 | case Node\Expr\Instanceof_::class: |
|
63 | return new Expression\Operators\InstanceOfOp(); |
||
64 | /** |
||
65 | * AssignOp |
||
66 | */ |
||
67 | 711 | case Node\Expr\AssignOp\Pow::class: |
|
68 | 21 | return new Expression\AssignOp\Pow(); |
|
69 | 690 | case Node\Expr\AssignOp\Plus::class: |
|
70 | 17 | return new Expression\AssignOp\Plus(); |
|
71 | 673 | case Node\Expr\AssignOp\Minus::class: |
|
72 | 20 | return new Expression\AssignOp\Minus(); |
|
73 | 653 | case Node\Expr\AssignOp\Mul::class: |
|
74 | 20 | return new Expression\AssignOp\Mul(); |
|
75 | 633 | case Node\Expr\AssignOp\Div::class: |
|
76 | 18 | return new Expression\AssignOp\Div(); |
|
77 | 615 | case Node\Expr\AssignOp\Mod::class: |
|
78 | 11 | return new Expression\AssignOp\Mod(); |
|
79 | 604 | case Node\Expr\AssignOp\BitwiseOr::class: |
|
80 | 12 | return new Expression\AssignOp\BitwiseOr(); |
|
81 | 592 | case Node\Expr\AssignOp\BitwiseAnd::class: |
|
82 | 12 | return new Expression\AssignOp\BitwiseAnd(); |
|
83 | 580 | case Node\Expr\AssignOp\BitwiseXor::class: |
|
84 | 12 | return new Expression\AssignOp\BitwiseXor(); |
|
85 | 568 | case Node\Expr\AssignOp\Concat::class: |
|
86 | 14 | return new Expression\AssignOp\Concat(); |
|
87 | 554 | case Node\Expr\AssignOp\ShiftLeft::class: |
|
88 | 12 | return new Expression\AssignOp\ShiftLeft(); |
|
89 | 542 | case Node\Expr\AssignOp\ShiftRight::class: |
|
90 | 12 | return new Expression\AssignOp\ShiftRight(); |
|
91 | |||
92 | /** |
||
93 | * BinaryOp |
||
94 | */ |
||
95 | 530 | case Node\Expr\BinaryOp\Identical::class: |
|
96 | 28 | return new Expression\BinaryOp\Identical(); |
|
97 | 502 | case Node\Expr\BinaryOp\Concat::class: |
|
98 | 1 | return new Expression\Operators\Concat(); |
|
99 | 501 | case Node\Expr\BinaryOp\NotIdentical::class: |
|
100 | 14 | return new Expression\BinaryOp\NotIdentical(); |
|
101 | 487 | case Node\Expr\BinaryOp\Equal::class: |
|
102 | 34 | return new Expression\BinaryOp\Equal(); |
|
103 | 453 | case Node\Expr\BinaryOp\NotEqual::class: |
|
104 | 17 | return new Expression\BinaryOp\NotEqual(); |
|
105 | 436 | case Node\Expr\BinaryOp\Spaceship::class: |
|
106 | 11 | return new Expression\BinaryOp\SpaceShip(); |
|
107 | |||
108 | /** |
||
109 | * @link http://php.net/manual/en/language.operators.increment.php |
||
110 | */ |
||
111 | 425 | case Node\Expr\PostInc::class: |
|
112 | 8 | return new Expression\Operators\PostInc(); |
|
113 | 417 | case Node\Expr\PostDec::class: |
|
114 | 8 | return new Expression\Operators\PostDec(); |
|
115 | 409 | case Node\Expr\PreInc::class: |
|
116 | 8 | return new Expression\Operators\PreInc(); |
|
117 | 401 | case Node\Expr\PreDec::class: |
|
118 | 8 | return new Expression\Operators\PreDec(); |
|
119 | /** |
||
120 | * Arithmetical |
||
121 | */ |
||
122 | 393 | case Node\Expr\BinaryOp\Div::class: |
|
123 | 37 | return new Expression\Operators\Arithmetical\Div(); |
|
124 | 356 | case Node\Expr\BinaryOp\Plus::class: |
|
125 | 45 | return new Expression\Operators\Arithmetical\Plus(); |
|
126 | 311 | case Node\Expr\BinaryOp\Minus::class: |
|
127 | 18 | return new Expression\Operators\Arithmetical\Minus(); |
|
128 | 293 | case Node\Expr\BinaryOp\Mul::class: |
|
129 | 35 | return new Expression\Operators\Arithmetical\Mul(); |
|
130 | 258 | case Node\Expr\BinaryOp\Mod::class: |
|
131 | 35 | return new Expression\Operators\Arithmetical\Mod(); |
|
132 | 223 | case Node\Expr\BinaryOp\Pow::class: |
|
133 | 21 | return new Expression\Operators\Arithmetical\Pow(); |
|
134 | |||
135 | /** |
||
136 | * Bitwise |
||
137 | * @link http://php.net/manual/ru/language.operators.bitwise.php |
||
138 | */ |
||
139 | 202 | case Node\Expr\BinaryOp\BitwiseOr::class: |
|
140 | 12 | return new Expression\Operators\Bitwise\BitwiseOr(); |
|
141 | 190 | case Node\Expr\BinaryOp\BitwiseXor::class: |
|
142 | 12 | return new Expression\Operators\Bitwise\BitwiseXor(); |
|
143 | 178 | case Node\Expr\BinaryOp\BitwiseAnd::class: |
|
144 | 12 | return new Expression\Operators\Bitwise\BitwiseAnd(); |
|
145 | 166 | case Node\Expr\BinaryOp\ShiftRight::class: |
|
146 | 12 | return new Expression\Operators\Bitwise\ShiftRight(); |
|
147 | 154 | case Node\Expr\BinaryOp\ShiftLeft::class: |
|
148 | 12 | return new Expression\Operators\Bitwise\ShiftLeft(); |
|
149 | 142 | case Node\Expr\BitwiseNot::class: |
|
150 | 5 | return new Expression\Operators\Bitwise\BitwiseNot(); |
|
151 | /** |
||
152 | * Logical |
||
153 | */ |
||
154 | 137 | case Node\Expr\BinaryOp\BooleanOr::class: |
|
155 | 10 | return new Expression\Operators\Logical\BooleanOr(); |
|
156 | 127 | case Node\Expr\BinaryOp\BooleanAnd::class: |
|
157 | 5 | return new Expression\Operators\Logical\BooleanAnd(); |
|
158 | 122 | case Node\Expr\BooleanNot::class: |
|
159 | 5 | return new Expression\Operators\Logical\BooleanNot(); |
|
160 | 117 | case Node\Expr\BinaryOp\LogicalAnd::class: |
|
161 | 15 | return new Expression\Operators\Logical\LogicalAnd(); |
|
162 | 102 | case Node\Expr\BinaryOp\LogicalOr::class: |
|
163 | 17 | return new Expression\Operators\Logical\LogicalOr(); |
|
164 | 85 | case Node\Expr\BinaryOp\LogicalXor::class: |
|
165 | 17 | return new Expression\Operators\Logical\LogicalXor(); |
|
166 | |||
167 | /** |
||
168 | * Comparison |
||
169 | */ |
||
170 | 68 | case Node\Expr\BinaryOp\Greater::class: |
|
171 | 12 | return new Expression\Operators\Comparison\Greater(); |
|
172 | 56 | case Node\Expr\BinaryOp\GreaterOrEqual::class: |
|
173 | 12 | return new Expression\Operators\Comparison\GreaterOrEqual(); |
|
174 | 44 | case Node\Expr\BinaryOp\Smaller::class: |
|
175 | 12 | return new Expression\Operators\Comparison\Smaller(); |
|
176 | 32 | case Node\Expr\BinaryOp\SmallerOrEqual::class: |
|
177 | 12 | return new Expression\Operators\Comparison\SmallerOrEqual(); |
|
178 | |||
179 | /** |
||
180 | * Casts |
||
181 | */ |
||
182 | 20 | case Node\Expr\Cast\Array_::class: |
|
183 | 1 | return new Expression\Casts\ArrayCast(); |
|
184 | 20 | case Node\Expr\Cast\Bool_::class: |
|
185 | 1 | return new Expression\Casts\BoolCast(); |
|
186 | 20 | case Node\Expr\Cast\Int_::class: |
|
187 | 1 | return new Expression\Casts\IntCast(); |
|
188 | 20 | case Node\Expr\Cast\Double::class: |
|
189 | 1 | return new Expression\Casts\DoubleCast(); |
|
190 | 20 | case Node\Expr\Cast\Object_::class: |
|
191 | 1 | return new Expression\Casts\ObjectCast(); |
|
192 | 20 | case Node\Expr\Cast\String_::class: |
|
193 | 1 | return new Expression\Casts\StringCast(); |
|
194 | 20 | case Node\Expr\Cast\Unset_::class: |
|
195 | 1 | return new Expression\Casts\UnsetCast(); |
|
196 | |||
197 | |||
198 | /** |
||
199 | * Other |
||
200 | */ |
||
201 | 19 | case Node\Expr\Closure::class: |
|
202 | return new Expression\Closure(); |
||
203 | 19 | case Node\Expr\UnaryMinus::class: |
|
204 | 9 | return new Expression\Operators\UnaryMinus(); |
|
205 | 10 | case Node\Expr\UnaryPlus::class: |
|
206 | 9 | return new Expression\Operators\UnaryPlus(); |
|
207 | 1 | } |
|
208 | |||
209 | 1 | return false; |
|
210 | } |
||
211 | |||
212 | /** |
||
213 | * @param object|string $expr |
||
214 | * @return CompiledExpression |
||
215 | */ |
||
216 | 738 | public function compile($expr) |
|
217 | { |
||
218 | 738 | if (is_string($expr)) { |
|
219 | 12 | return new CompiledExpression(CompiledExpression::STRING, $expr); |
|
220 | } |
||
221 | |||
222 | 738 | if (is_null($expr)) { |
|
223 | 8 | return new CompiledExpression(CompiledExpression::NULL); |
|
224 | } |
||
225 | |||
226 | 738 | if (!is_object($expr)) { |
|
227 | throw new InvalidArgumentException('$expr must be string/object/null'); |
||
228 | } |
||
229 | |||
230 | 738 | $this->eventManager->fire( |
|
231 | 738 | ExpressionBeforeCompile::EVENT_NAME, |
|
232 | 738 | new ExpressionBeforeCompile( |
|
233 | 738 | $expr, |
|
234 | 738 | $this->context |
|
235 | 738 | ) |
|
236 | 738 | ); |
|
237 | |||
238 | 738 | $className = get_class($expr); |
|
239 | switch ($className) { |
||
240 | 738 | case Node\Arg::class: |
|
241 | /** |
||
242 | * @todo Better compile |
||
243 | */ |
||
244 | 2 | return $this->compile($expr->value); |
|
245 | 738 | case Node\Expr\PropertyFetch::class: |
|
246 | return $this->passPropertyFetch($expr); |
||
247 | 738 | case Node\Stmt\Property::class: |
|
248 | return $this->passProperty($expr); |
||
249 | 738 | case Node\Expr\ClassConstFetch::class: |
|
250 | return $this->passConstFetch($expr); |
||
251 | 738 | case Node\Expr\Assign::class: |
|
252 | 12 | return $this->passSymbol($expr); |
|
253 | 738 | case Node\Expr\AssignRef::class: |
|
254 | 1 | return $this->passSymbolByRef($expr); |
|
255 | 738 | case Node\Expr\Variable::class: |
|
256 | 8 | return $this->passExprVariable($expr); |
|
257 | |||
258 | /** |
||
259 | * Expressions |
||
260 | */ |
||
261 | 738 | case Node\Expr\Array_::class: |
|
262 | 26 | return $this->getArray($expr); |
|
263 | 737 | case Node\Expr\ConstFetch::class: |
|
264 | 5 | return $this->constFetch($expr); |
|
265 | 737 | case Node\Name::class: |
|
266 | 11 | return $this->getNodeName($expr); |
|
267 | 737 | case Node\Name\FullyQualified::class: |
|
268 | return $this->getFullyQualifiedNodeName($expr); |
||
269 | |||
270 | /** |
||
271 | * Simple Scalar(s) |
||
272 | */ |
||
273 | 737 | case \PHPSA\Node\Scalar\Nil::class: |
|
274 | 21 | return new CompiledExpression(CompiledExpression::NULL); |
|
275 | 736 | case Node\Scalar\LNumber::class: |
|
276 | 467 | return new CompiledExpression(CompiledExpression::INTEGER, $expr->value); |
|
277 | 729 | case Node\Scalar\DNumber::class: |
|
278 | 197 | return new CompiledExpression(CompiledExpression::DOUBLE, $expr->value); |
|
279 | 728 | case Node\Scalar\String_::class: |
|
280 | 29 | return new CompiledExpression(CompiledExpression::STRING, $expr->value); |
|
281 | 723 | case \PHPSA\Node\Scalar\Boolean::class: |
|
282 | 217 | return new CompiledExpression(CompiledExpression::BOOLEAN, $expr->value); |
|
283 | 721 | case \PHPSA\Node\Scalar\Fake::class: |
|
284 | 71 | return new CompiledExpression($expr->type, $expr->value); |
|
285 | } |
||
286 | |||
287 | 721 | $expressionCompiler = $this->factory($expr); |
|
288 | 721 | if (!$expressionCompiler) { |
|
289 | 1 | $this->context->debug("Expression compiler is not implemented for {$className}"); |
|
290 | 1 | return new CompiledExpression(CompiledExpression::UNIMPLEMENTED); |
|
291 | } |
||
292 | |||
293 | 721 | $result = $expressionCompiler->pass($expr, $this->context); |
|
294 | 721 | if (!$result instanceof CompiledExpression) { |
|
295 | throw new RuntimeException('Please return CompiledExpression from ' . get_class($expressionCompiler)); |
||
296 | } |
||
297 | |||
298 | 721 | return $result; |
|
299 | } |
||
300 | |||
301 | /** |
||
302 | * @todo Implement |
||
303 | * |
||
304 | * @param Node\Stmt\Property $st |
||
305 | * @return CompiledExpression |
||
306 | */ |
||
307 | public function passProperty(Node\Stmt\Property $st) |
||
308 | { |
||
309 | $docBlock = $st->getDocComment(); |
||
310 | if (!$docBlock) { |
||
311 | $this->context->notice( |
||
312 | 'missing-docblock', |
||
313 | sprintf('Missing docblock for $%s property', $st->props[0]->name), |
||
314 | $st |
||
315 | ); |
||
316 | |||
317 | return new CompiledExpression(); |
||
318 | } |
||
319 | |||
320 | $phpdoc = new \phpDocumentor\Reflection\DocBlock($docBlock->getText()); |
||
321 | |||
322 | $varTags = $phpdoc->getTagsByName('var'); |
||
323 | if ($varTags) { |
||
324 | /** @var \phpDocumentor\Reflection\DocBlock\Tag\VarTag $varTag */ |
||
325 | $varTag = current($varTags); |
||
326 | |||
327 | $typeResolver = new \phpDocumentor\Reflection\TypeResolver(); |
||
328 | |||
329 | try { |
||
330 | $type = $typeResolver->resolve($varTag->getType()); |
||
331 | } catch (\InvalidArgumentException $e) { |
||
332 | return new CompiledExpression(); |
||
333 | } |
||
334 | |||
335 | if ($type) { |
||
336 | switch (get_class($type)) { |
||
337 | case \phpDocumentor\Reflection\Types\Object_::class: |
||
338 | return new CompiledExpression( |
||
339 | CompiledExpression::OBJECT |
||
340 | ); |
||
341 | case \phpDocumentor\Reflection\Types\Integer::class: |
||
342 | return new CompiledExpression( |
||
343 | CompiledExpression::INTEGER |
||
344 | ); |
||
345 | case \phpDocumentor\Reflection\Types\String_::class: |
||
346 | return new CompiledExpression( |
||
347 | CompiledExpression::STRING |
||
348 | ); |
||
349 | case \phpDocumentor\Reflection\Types\Float_::class: |
||
350 | return new CompiledExpression( |
||
351 | CompiledExpression::DOUBLE |
||
352 | ); |
||
353 | case \phpDocumentor\Reflection\Types\Null_::class: |
||
354 | return new CompiledExpression( |
||
355 | CompiledExpression::NULL |
||
356 | ); |
||
357 | case \phpDocumentor\Reflection\Types\Boolean::class: |
||
358 | return new CompiledExpression( |
||
359 | CompiledExpression::BOOLEAN |
||
360 | ); |
||
361 | } |
||
362 | } |
||
363 | } |
||
364 | |||
365 | return new CompiledExpression(); |
||
366 | } |
||
367 | |||
368 | /** |
||
369 | * @param Node\Expr\Variable $expr |
||
370 | * @return CompiledExpression |
||
371 | */ |
||
372 | 1 | public function declareVariable(Node\Expr\Variable $expr) |
|
373 | { |
||
374 | 1 | $variable = $this->context->getSymbol($expr->name); |
|
375 | 1 | if (!$variable) { |
|
376 | $variable = new Variable($expr->name, null, CompiledExpression::UNKNOWN, $this->context->getCurrentBranch()); |
||
377 | $this->context->addVariable($variable); |
||
378 | } |
||
379 | |||
380 | 1 | return new CompiledExpression($variable->getType(), $variable->getValue(), $variable); |
|
381 | } |
||
382 | |||
383 | /** |
||
384 | * @param Node\Name\FullyQualified $expr |
||
385 | * @return CompiledExpression |
||
386 | */ |
||
387 | public function getFullyQualifiedNodeName(Node\Name\FullyQualified $expr) |
||
388 | { |
||
389 | $this->context->debug('Unimplemented FullyQualified', $expr); |
||
390 | |||
391 | return new CompiledExpression; |
||
392 | } |
||
393 | |||
394 | /** |
||
395 | * @param Node\Name $expr |
||
396 | * @return CompiledExpression |
||
397 | */ |
||
398 | 11 | public function getNodeName(Node\Name $expr) |
|
399 | { |
||
400 | 11 | $nodeString = $expr->toString(); |
|
401 | 11 | if ($nodeString === 'null') { |
|
402 | 1 | return new CompiledExpression(CompiledExpression::NULL); |
|
403 | } |
||
404 | |||
405 | 10 | if (in_array($nodeString, ['parent'], true)) { |
|
406 | /** @var ClassDefinition $scope */ |
||
407 | $scope = $this->context->scope; |
||
408 | assert($scope instanceof ClassDefinition); |
||
409 | |||
410 | if ($scope->getExtendsClass()) { |
||
411 | $definition = $scope->getExtendsClassDefinition(); |
||
412 | if ($definition) { |
||
413 | return new CompiledExpression(CompiledExpression::OBJECT, $definition); |
||
414 | } |
||
415 | } else { |
||
416 | $this->context->notice( |
||
417 | 'no-parent', |
||
418 | 'Cannot access parent:: when current class scope has no parent', |
||
419 | $expr |
||
420 | ); |
||
421 | } |
||
422 | } |
||
423 | |||
424 | 10 | if (in_array($nodeString, ['self', 'static'], true)) { |
|
425 | return CompiledExpression::fromZvalValue($this->context->scope); |
||
426 | } |
||
427 | |||
428 | 10 | if (defined($nodeString)) { |
|
429 | 1 | return CompiledExpression::fromZvalValue(constant($expr)); |
|
430 | } |
||
431 | |||
432 | 10 | return new CompiledExpression(CompiledExpression::STRING, $expr->toString()); |
|
433 | } |
||
434 | |||
435 | /** |
||
436 | * @param Node\Expr\PropertyFetch $expr |
||
437 | * @return CompiledExpression |
||
438 | */ |
||
439 | protected function passPropertyFetch(Node\Expr\PropertyFetch $expr) |
||
440 | { |
||
441 | $propertNameCE = $this->compile($expr->name); |
||
442 | |||
443 | $scopeExpression = $this->compile($expr->var); |
||
444 | if ($scopeExpression->isObject()) { |
||
445 | $scopeExpressionValue = $scopeExpression->getValue(); |
||
446 | if ($scopeExpressionValue instanceof ClassDefinition) { |
||
447 | $propertyName = $propertNameCE->isString() ? $propertNameCE->getValue() : false; |
||
448 | if ($propertyName) { |
||
449 | if ($scopeExpressionValue->hasProperty($propertyName, true)) { |
||
450 | $property = $scopeExpressionValue->getProperty($propertyName, true); |
||
451 | return $this->compile($property); |
||
452 | } else { |
||
453 | $this->context->notice( |
||
454 | 'undefined-property', |
||
455 | sprintf( |
||
456 | 'Property %s does not exist in %s scope', |
||
457 | $propertyName, |
||
458 | $scopeExpressionValue->getName() |
||
459 | ), |
||
460 | $expr |
||
461 | ); |
||
462 | } |
||
463 | } |
||
464 | } |
||
465 | |||
466 | return new CompiledExpression(CompiledExpression::UNKNOWN); |
||
467 | } elseif (!$scopeExpression->canBeObject()) { |
||
468 | return new CompiledExpression(CompiledExpression::UNKNOWN); |
||
469 | } |
||
470 | |||
471 | $this->context->notice( |
||
472 | 'property-fetch-on-non-object', |
||
473 | "It's not possible to fetch property on not object", |
||
474 | $expr, |
||
475 | Check::CHECK_BETA |
||
476 | ); |
||
477 | |||
478 | return new CompiledExpression(CompiledExpression::UNKNOWN); |
||
479 | } |
||
480 | |||
481 | /** |
||
482 | * @param Node\Expr\ClassConstFetch $expr |
||
483 | * @return CompiledExpression |
||
484 | */ |
||
485 | protected function passConstFetch(Node\Expr\ClassConstFetch $expr) |
||
486 | { |
||
487 | $leftCE = $this->compile($expr->class); |
||
488 | if ($leftCE->isObject()) { |
||
489 | $leftCEValue = $leftCE->getValue(); |
||
490 | if ($leftCEValue instanceof ClassDefinition) { |
||
491 | if (!$leftCEValue->hasConst($expr->name, true)) { |
||
492 | $this->context->notice( |
||
493 | 'undefined-const', |
||
494 | sprintf('Constant %s does not exist in %s scope', $expr->name, $expr->class), |
||
495 | $expr |
||
496 | ); |
||
497 | return new CompiledExpression(CompiledExpression::UNKNOWN); |
||
498 | } |
||
499 | |||
500 | return new CompiledExpression(); |
||
501 | } |
||
502 | } |
||
503 | |||
504 | $this->context->debug('Unknown const fetch', $expr); |
||
505 | return new CompiledExpression(); |
||
506 | } |
||
507 | |||
508 | /** |
||
509 | * @param Node\Expr\Assign $expr |
||
510 | * @return CompiledExpression |
||
511 | */ |
||
512 | 12 | protected function passSymbol(Node\Expr\Assign $expr) |
|
513 | { |
||
514 | 12 | $compiledExpression = $this->compile($expr->expr); |
|
515 | |||
516 | 12 | if ($expr->var instanceof Node\Expr\List_) { |
|
517 | $isCorrectType = false; |
||
518 | |||
519 | switch ($compiledExpression->getType()) { |
||
520 | case CompiledExpression::ARR: |
||
521 | $isCorrectType = true; |
||
522 | break; |
||
523 | } |
||
524 | |||
525 | if ($expr->var->vars) { |
||
526 | foreach ($expr->var->vars as $key => $var) { |
||
527 | if ($var instanceof Node\Expr\Variable) { |
||
528 | $name = $expr->var->name; |
||
529 | |||
530 | $symbol = $this->context->getSymbol($name); |
||
531 | if (!$symbol) { |
||
532 | $symbol = new Variable( |
||
533 | $name, |
||
534 | null, |
||
535 | CompiledExpression::UNKNOWN, |
||
536 | $this->context->getCurrentBranch() |
||
537 | ); |
||
538 | $this->context->addVariable($symbol); |
||
539 | } |
||
540 | |||
541 | if (!$isCorrectType) { |
||
542 | $symbol->modify(CompiledExpression::NULL, null); |
||
543 | } |
||
544 | |||
545 | $symbol->incSets(); |
||
546 | } |
||
547 | } |
||
548 | } |
||
549 | |||
550 | return new CompiledExpression(); |
||
551 | } |
||
552 | |||
553 | |||
554 | 12 | if ($expr->var instanceof Node\Expr\Variable) { |
|
555 | 12 | $compiledExpressionName = $this->compile($expr->var->name); |
|
556 | 12 | switch ($compiledExpressionName->getType()) { |
|
557 | 12 | case CompiledExpression::STRING: |
|
558 | 12 | break; |
|
559 | default: |
||
560 | $this->context->debug('Unexpected type of Variable name after compile'); |
||
561 | return new CompiledExpression(); |
||
562 | 12 | } |
|
563 | |||
564 | 12 | $symbol = $this->context->getSymbol($compiledExpressionName->getValue()); |
|
565 | 12 | if ($symbol) { |
|
566 | 2 | $symbol->modify($compiledExpression->getType(), $compiledExpression->getValue()); |
|
567 | 2 | $this->context->modifyReferencedVariables( |
|
568 | 2 | $symbol, |
|
569 | 2 | $compiledExpression->getType(), |
|
570 | 2 | $compiledExpression->getValue() |
|
571 | 2 | ); |
|
572 | 2 | } else { |
|
573 | 12 | $symbol = new Variable( |
|
574 | 12 | $compiledExpressionName->getValue(), |
|
575 | 12 | $compiledExpression->getValue(), |
|
576 | 12 | $compiledExpression->getType(), |
|
577 | 12 | $this->context->getCurrentBranch() |
|
578 | 12 | ); |
|
579 | 12 | $this->context->addVariable($symbol); |
|
580 | } |
||
581 | |||
582 | 12 | $symbol->incSets(); |
|
583 | 12 | return $compiledExpression; |
|
584 | } |
||
585 | |||
586 | 1 | if ($expr->var instanceof Node\Expr\PropertyFetch) { |
|
587 | 1 | $compiledExpression = $this->compile($expr->var->var); |
|
588 | 1 | if ($compiledExpression->getType() == CompiledExpression::OBJECT) { |
|
589 | 1 | $objectDefinition = $compiledExpression->getValue(); |
|
590 | 1 | if ($objectDefinition instanceof ClassDefinition) { |
|
591 | 1 | if (is_string($expr->var->name)) { |
|
592 | 1 | if ($objectDefinition->hasProperty($expr->var->name)) { |
|
593 | return $this->compile($objectDefinition->getProperty($expr->var->name)); |
||
594 | } |
||
595 | 1 | } |
|
596 | 1 | } |
|
597 | 1 | } |
|
598 | 1 | } |
|
599 | |||
600 | 1 | $this->context->debug('Unknown how to pass symbol'); |
|
601 | 1 | return new CompiledExpression(); |
|
602 | } |
||
603 | |||
604 | /** |
||
605 | * @param Node\Expr\AssignRef $expr |
||
606 | * @return CompiledExpression |
||
607 | */ |
||
608 | 1 | protected function passSymbolByRef(Node\Expr\AssignRef $expr) |
|
647 | |||
648 | /** |
||
649 | * @param Node\Expr\Variable $expr |
||
650 | * @return CompiledExpression |
||
651 | */ |
||
652 | 8 | protected function passExprVariable(Node\Expr\Variable $expr) |
|
668 | |||
669 | /** |
||
670 | * Compile Array_ expression to CompiledExpression |
||
671 | * |
||
672 | * @param Node\Expr\Array_ $expr |
||
673 | * @return CompiledExpression |
||
674 | */ |
||
675 | 26 | protected function getArray(Node\Expr\Array_ $expr) |
|
676 | { |
||
677 | 26 | if ($expr->items === []) { |
|
678 | 17 | return new CompiledExpression(CompiledExpression::ARR, []); |
|
679 | } |
||
680 | |||
681 | 10 | $resultArray = []; |
|
682 | |||
683 | 10 | foreach ($expr->items as $item) { |
|
684 | 10 | $compiledValueResult = $this->compile($item->value); |
|
685 | 10 | if ($item->key) { |
|
686 | 3 | $compiledKeyResult = $this->compile($item->key); |
|
687 | 3 | switch ($compiledKeyResult->getType()) { |
|
688 | 3 | case CompiledExpression::INTEGER: |
|
689 | 3 | case CompiledExpression::DOUBLE: |
|
690 | 3 | case CompiledExpression::BOOLEAN: |
|
691 | 3 | case CompiledExpression::NULL: |
|
692 | 3 | case CompiledExpression::STRING: |
|
693 | 3 | $resultArray[$compiledKeyResult->getValue()] = $compiledValueResult->getValue(); |
|
694 | 3 | break; |
|
695 | 1 | default: |
|
696 | 1 | $this->context->debug("Type {$compiledKeyResult->getType()} is not supported for key value"); |
|
697 | 1 | return new CompiledExpression(CompiledExpression::ARR); |
|
698 | break; |
||
699 | 3 | } |
|
700 | 3 | } else { |
|
701 | 7 | $resultArray[] = $compiledValueResult->getValue(); |
|
702 | } |
||
703 | 10 | } |
|
704 | |||
705 | 10 | return new CompiledExpression(CompiledExpression::ARR, $resultArray); |
|
706 | } |
||
707 | |||
708 | /** |
||
709 | * Convert const fetch expr to CompiledExpression |
||
710 | * |
||
711 | * @param Node\Expr\ConstFetch $expr |
||
712 | * @return CompiledExpression |
||
713 | */ |
||
714 | 5 | protected function constFetch(Node\Expr\ConstFetch $expr) |
|
731 | } |
||
732 |
The class complexity is the sum of the complexity of all methods. A very high value is usually an indication that your class does not follow the single reponsibility principle and does more than one job.
Some resources for further reading:
You can also find more detailed suggestions for refactoring in the “Code” section of your repository.