GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

Expression   F
last analyzed

Complexity

Total Complexity 56

Size/Duplication

Total Lines 632
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 33

Importance

Changes 0
Metric Value
wmc 56
lcom 2
cbo 33
dl 0
loc 632
rs 1.2208
c 0
b 0
f 0

49 Methods

Rating   Name   Duplication   Size   Complexity  
A getType() 0 4 1
A simplifyAll() 0 11 2
A isNormalSyntaxName() 0 4 1
traverse() 0 1 ?
A asEvaluator() 0 4 1
A cannotEvaluate() 0 6 1
A evaluate() 0 4 1
A simplify() 0 4 1
A hash() 0 4 1
A __toString() 0 4 1
__clone() 0 1 ?
A equals() 0 4 1
A hashAll() 0 4 1
A compileAll() 0 9 1
A compile() 0 7 1
compileCode() 0 1 ?
B allOfType() 0 12 5
A cloneAll() 0 9 2
A assign() 0 7 1
A binaryOperation() 0 7 1
A unaryOperation() 0 4 1
A newExpression() 0 4 1
A methodCall() 0 7 1
A field() 0 4 1
A index() 0 4 1
A invocation() 0 4 1
A cast() 0 4 1
A emptyExpression() 0 4 1
A issetExpression() 0 4 1
A unsetExpression() 0 4 1
A functionCall() 0 4 1
A staticMethodCall() 0 7 1
A staticField() 0 6 1
A ternary() 0 7 1
A returnExpression() 0 4 1
A throwExpression() 0 4 1
A value() 0 4 1
A constant() 0 4 1
A classConstant() 0 4 1
A variable() 0 4 1
A arrayExpression() 0 4 1
A arrayItem() 0 4 1
A closure() 0 14 1
A getExpressionTypeName() 0 4 1
A verifyAll() 0 14 3
A compileDebug() 0 16 3
A parameter() 0 14 1
A argument() 0 6 1
A closureUsedVariable() 0 4 1

How to fix   Complexity   

Complex Class

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
2
3
namespace Pinq\Expressions;
4
5
use Pinq\PinqException;
6
use Pinq\Utilities;
7
8
/**
9
 * The base class for object expressions.
10
 *
11
 * @author Elliot Levin <[email protected]>
12
 */
13
abstract class Expression implements \Serializable
14
{
15
    const EXPRESSION_TYPE = __CLASS__;
16
17
    /**
18
     * Gets the class name as a string.
19
     *
20
     * @return string
21
     */
22
    final public static function getType()
23
    {
24
        return get_called_class();
25
    }
26
27
    /**
28
     * Gets a string representing the name of the expression.
29
     *
30
     * For instance \Pinq\Expressions\BinaryOperationExpression::getExpressionTypeName()
31
     * returns 'BinaryOperation'
32
     *
33
     * @return string
34
     */
35
    final public static function getExpressionTypeName()
36
    {
37
        return substr(get_called_class(), strlen(__NAMESPACE__) + 1, -strlen('Expression'));
38
    }
39
40
    /**
41
     * @param Expression[]       $expressions
42
     * @param IEvaluationContext $context
43
     *
44
     * @return Expression[]
45
     */
46
    final public static function simplifyAll(
47
            array $expressions,
48
            IEvaluationContext $context = null
49
    ) {
50
        $simplifiedExpressions = [];
51
        foreach ($expressions as $expression) {
52
            $simplifiedExpressions[] = $expression->simplify($context);
53
        }
54
55
        return $simplifiedExpressions;
56
    }
57
58
    /**
59
     * Returns whether the supplied name is considered normal name syntax
60
     * and can be used plainly in code.
61
     * Example:
62
     * 'foo' -> yes: $foo
63
     * 'foo bar' -> no: ${'foo bar'}
64
     *
65
     * @param string $name The field, function, method or variable name
66
     *
67
     * @return boolean
68
     */
69
    final protected static function isNormalSyntaxName($name)
70
    {
71
        return preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $name);
72
    }
73
74
    /**
75
     * Verifies the supplied array only contains expressions
76
     * of the supplied type.
77
     *
78
     * @param mixed[] $expressions
79
     * @param string  $type
80
     *
81
     * @return Expression[]
82
     * @throws PinqException If the array contains invalid expressions.
83
     */
84
    final protected static function verifyAll(array $expressions, $type = __CLASS__)
85
    {
86
        foreach ($expressions as $key => $expression) {
87
            if (!($expression instanceof $type)) {
88
                throw new PinqException(
89
                        'Invalid array of expressions: invalid expression of type %s at index %s, expecting %s',
90
                        Utilities::getTypeOrClass($expression),
91
                        $key,
92
                        $type);
93
            }
94
        }
95
96
        return $expressions;
97
    }
98
99
    /**
100
     * @param ExpressionWalker $walker
101
     *
102
     * @return Expression
103
     */
104
    abstract public function traverse(ExpressionWalker $walker);
105
106
    /**
107
     * Creates an expression evaluator for the expression with
108
     * the supplied context.
109
     *
110
     * @param IEvaluationContext|null $context
111
     *
112
     * @return IEvaluator
113
     */
114
    public function asEvaluator(IEvaluationContext $context = null)
115
    {
116
        return CompiledEvaluator::fromExpressions([Expression::returnExpression($this)], $context);
117
    }
118
119
    final protected static function cannotEvaluate()
120
    {
121
        return new PinqException(
122
                'Cannot evaluate expression of type %s',
123
                get_called_class());
124
    }
125
126
    /**
127
     * Evaluates the expression tree in the supplied context
128
     * and returns the resulting value.
129
     *
130
     * @param IEvaluationContext|null $context
131
     *
132
     * @return mixed
133
     */
134
    public function evaluate(IEvaluationContext $context = null)
135
    {
136
        return $this->asEvaluator($context)->evaluate();
137
    }
138
139
    /**
140
     * Simplifies the expression tree in the supplied context.
141
     * Example:
142
     * <code>
143
     * -2 + 4
144
     * </code>
145
     * Will become:
146
     * <code>
147
     * 2
148
     * </code>
149
     *
150
     * @param IEvaluationContext|null $context
151
     *
152
     * @return Expression
153
     */
154
    public function simplify(IEvaluationContext $context = null)
155
    {
156
        return Expression::value($this->evaluate($context));
157
    }
158
159
    /**
160
     * Returns a value hash for the expression.
161
     *
162
     * @return string
163
     */
164
    final public function hash()
165
    {
166
        return md5($this->compile());
167
    }
168
169
    final public function __toString()
170
    {
171
        return $this->compile();
172
    }
173
174
    abstract public function __clone();
175
176
    /**
177
     * Returns whether the expression is equivalent to the supplied expression.
178
     *
179
     * @param Expression $expression
180
     *
181
     * @return boolean
182
     */
183
    public function equals(Expression $expression)
184
    {
185
        return $this == $expression;
186
    }
187
188
    /**
189
     * Returns a value hash for the supplied expressions.
190
     *
191
     * @param Expression[] $expressions
192
     *
193
     * @return string
194
     */
195
    final public static function hashAll(array $expressions)
196
    {
197
        return md5(implode('~', self::compileAll($expressions)));
198
    }
199
200
    /**
201
     * Compiles into equivalent PHP code
202
     *
203
     * @param Expression[] $expressions
204
     *
205
     * @return string[]
206
     */
207
    final public static function compileAll(array $expressions)
208
    {
209
        return array_map(
210
                function (Expression $expression) {
211
                    return $expression->compile();
212
                },
213
                $expressions
214
        );
215
    }
216
217
    /**
218
     * Compiles the expression tree into equivalent PHP code.
219
     *
220
     * @return string
221
     */
222
    final public function compile()
223
    {
224
        $code = '';
225
        $this->compileCode($code);
226
227
        return $code;
228
    }
229
230
    /**
231
     * Compiles the expression tree into debug code.
232
     *
233
     * @return string
234
     */
235
    final public function compileDebug()
236
    {
237
        return (new DynamicExpressionWalker([
238
                ValueExpression::getType() =>
239
                        function (ValueExpression $expression) {
240
                            $value = $expression->getValue();
241
242
                            return !is_scalar($value) && $value !== null ?
243
                                    Expression::constant(
244
                                            '{' . Utilities::getTypeOrClass($expression->getValue()) . '}'
245
                                    ) : $expression;
246
                        }
247
        ]))
248
                ->walk($this)
249
                ->compile();
250
    }
251
252
    abstract protected function compileCode(&$code);
253
254
    /**
255
     * Returns whether the expressions are all of the supplied type.
256
     *
257
     * @param Expression[] $expressions
258
     * @param string       $type
259
     * @param boolean      $allowNull
260
     *
261
     * @return boolean
262
     */
263
    final public static function allOfType(array $expressions, $type, $allowNull = false)
264
    {
265
        foreach ($expressions as $expression) {
266
            if ($expression instanceof $type || $expression === null && $allowNull) {
267
                continue;
268
            }
269
270
            return false;
271
        }
272
273
        return true;
274
    }
275
276
    /**
277
     * @param Expression|null[] $expressions
278
     *
279
     * @return Expression|null[]
280
     */
281
    final public static function cloneAll(array $expressions)
282
    {
283
        return array_map(
284
                function (Expression $expression = null) {
285
                    return $expression === null ? null : clone $expression;
286
                },
287
                $expressions
288
        );
289
    }
290
291
    /**
292
     * @param Expression $assignToValue
293
     * @param string     $assignmentOperator
294
     * @param Expression $assignmentValue
295
     *
296
     * @return AssignmentExpression
297
     */
298
    final public static function assign(Expression $assignToValue, $assignmentOperator, Expression $assignmentValue)
299
    {
300
        return new AssignmentExpression(
301
                $assignToValue,
302
                $assignmentOperator,
303
                $assignmentValue);
304
    }
305
306
    /**
307
     * @param Expression $leftOperand
308
     * @param string     $operator
309
     * @param Expression $rightOperand
310
     *
311
     * @return BinaryOperationExpression
312
     */
313
    final public static function binaryOperation(Expression $leftOperand, $operator, Expression $rightOperand)
314
    {
315
        return new BinaryOperationExpression(
316
                $leftOperand,
317
                $operator,
318
                $rightOperand);
319
    }
320
321
    /**
322
     * @param string     $unaryOperator
323
     * @param Expression $operand
324
     *
325
     * @return UnaryOperationExpression
326
     */
327
    final public static function unaryOperation($unaryOperator, Expression $operand)
328
    {
329
        return new UnaryOperationExpression($unaryOperator, $operand);
330
    }
331
332
    /**
333
     * @param Expression           $classType
334
     * @param ArgumentExpression[] $arguments
335
     *
336
     * @return NewExpression
337
     */
338
    final public static function newExpression(Expression $classType, array $arguments = [])
339
    {
340
        return new NewExpression($classType, $arguments);
341
    }
342
343
    /**
344
     * @param Expression           $value
345
     * @param Expression           $name
346
     * @param ArgumentExpression[] $arguments
347
     *
348
     * @return MethodCallExpression
349
     */
350
    final public static function methodCall(Expression $value, Expression $name, array $arguments = [])
351
    {
352
        return new MethodCallExpression(
353
                $value,
354
                $name,
355
                $arguments);
356
    }
357
358
    /**
359
     * @param Expression $value
360
     * @param Expression $name
361
     *
362
     * @return FieldExpression
363
     */
364
    final public static function field(Expression $value, Expression $name)
365
    {
366
        return new FieldExpression($value, $name);
367
    }
368
369
    /**
370
     * @param Expression      $value
371
     * @param Expression|null $index
372
     *
373
     * @return IndexExpression
374
     */
375
    final public static function index(Expression $value, Expression $index = null)
376
    {
377
        return new IndexExpression($value, $index);
378
    }
379
380
    /**
381
     * @param Expression           $valueExpression
382
     * @param ArgumentExpression[] $arguments
383
     *
384
     * @return InvocationExpression
385
     */
386
    final public static function invocation(Expression $valueExpression, array $arguments = [])
387
    {
388
        return new InvocationExpression($valueExpression, $arguments);
389
    }
390
391
    /**
392
     * @param string     $castType
393
     * @param Expression $castValue
394
     *
395
     * @return CastExpression
396
     */
397
    final public static function cast($castType, Expression $castValue)
398
    {
399
        return new CastExpression($castType, $castValue);
400
    }
401
402
    // <editor-fold desc="Factory Methods">
403
404
    /**
405
     * @param Expression $value
406
     *
407
     * @return EmptyExpression
408
     */
409
    final public static function emptyExpression(Expression $value)
410
    {
411
        return new EmptyExpression($value);
412
    }
413
414
    /**
415
     * @param Expression[] $values
416
     *
417
     * @return IssetExpression
418
     */
419
    final public static function issetExpression(array $values)
420
    {
421
        return new IssetExpression($values);
422
    }
423
424
    /**
425
     * @param Expression[] $values
426
     *
427
     * @return UnsetExpression
428
     */
429
    final public static function unsetExpression(array $values)
430
    {
431
        return new UnsetExpression($values);
432
    }
433
434
    /**
435
     * @param Expression           $name
436
     * @param ArgumentExpression[] $arguments
437
     *
438
     * @return FunctionCallExpression
439
     */
440
    final public static function functionCall(Expression $name, array $arguments = [])
441
    {
442
        return new FunctionCallExpression($name, $arguments);
443
    }
444
445
    /**
446
     * @param Expression           $class
447
     * @param Expression           $name
448
     * @param ArgumentExpression[] $arguments
449
     *
450
     * @return StaticMethodCallExpression
451
     */
452
    final public static function staticMethodCall(Expression $class, Expression $name, array $arguments = [])
453
    {
454
        return new StaticMethodCallExpression(
455
                $class,
456
                $name,
457
                $arguments);
458
    }
459
460
    /**
461
     * @param Expression $class
462
     * @param Expression $name
463
     *
464
     * @return StaticFieldExpression
465
     */
466
    final public static function staticField(Expression $class, Expression $name)
467
    {
468
        return new StaticFieldExpression(
469
                $class,
470
                $name);
471
    }
472
473
    /**
474
     * @param Expression $condition
475
     * @param Expression $ifTrue
476
     * @param Expression $ifFalse
477
     *
478
     * @return TernaryExpression
479
     */
480
    final public static function ternary(Expression $condition, Expression $ifTrue = null, Expression $ifFalse)
481
    {
482
        return new TernaryExpression(
483
                $condition,
484
                $ifTrue,
485
                $ifFalse);
486
    }
487
488
    /**
489
     * @param Expression|null $value
490
     *
491
     * @return ReturnExpression
492
     */
493
    final public static function returnExpression(Expression $value = null)
494
    {
495
        return new ReturnExpression($value);
496
    }
497
498
    /**
499
     * @param Expression $exception
500
     *
501
     * @return ThrowExpression
502
     */
503
    final public static function throwExpression(Expression $exception)
504
    {
505
        return new ThrowExpression($exception);
506
    }
507
508
    /**
509
     * @param string      $name
510
     * @param string|null $typeHint
511
     * @param Expression  $defaultValue
512
     * @param boolean     $isPassedByReference
513
     * @param boolean     $isVariadic
514
     *
515
     * @return ParameterExpression
516
     */
517
    final public static function parameter(
518
            $name,
519
            $typeHint = null,
520
            Expression $defaultValue = null,
521
            $isPassedByReference = false,
522
            $isVariadic = false
523
    ) {
524
        return new ParameterExpression(
525
                $name,
526
                $typeHint,
527
                $defaultValue,
528
                $isPassedByReference,
529
                $isVariadic);
530
    }
531
532
    /**
533
     * @param Expression $value
534
     * @param boolean    $isUnpacked
535
     *
536
     * @return ArgumentExpression
537
     */
538
    final public static function argument(
539
            Expression $value,
540
            $isUnpacked = false
541
    ) {
542
        return new ArgumentExpression($value, $isUnpacked);
543
    }
544
545
    /**
546
     * @param mixed $value
547
     *
548
     * @return ValueExpression
549
     */
550
    final public static function value($value)
551
    {
552
        return new ValueExpression($value);
553
    }
554
555
    /**
556
     * @param string $name
557
     *
558
     * @return ConstantExpression
559
     */
560
    final public static function constant($name)
561
    {
562
        return new ConstantExpression($name);
563
    }
564
565
    /**
566
     * @param Expression $class
567
     * @param string     $name
568
     *
569
     * @return ClassConstantExpression
570
     */
571
    final public static function classConstant(Expression $class, $name)
572
    {
573
        return new ClassConstantExpression($class, $name);
574
    }
575
576
    /**
577
     * @param Expression $name
578
     *
579
     * @return VariableExpression
580
     */
581
    final public static function variable(Expression $name)
582
    {
583
        return new VariableExpression($name);
584
    }
585
586
    /**
587
     * @param ArrayItemExpression[] $items
588
     *
589
     * @return ArrayExpression
590
     */
591
    final public static function arrayExpression(array $items)
592
    {
593
        return new ArrayExpression($items);
594
    }
595
596
    /**
597
     * @param Expression $key
598
     * @param Expression $value
599
     * @param boolean    $isReference
600
     *
601
     * @return ArrayItemExpression
602
     */
603
    final public static function arrayItem(Expression $key = null, Expression $value, $isReference = false)
604
    {
605
        return new ArrayItemExpression($key, $value, $isReference);
606
    }
607
608
    /**
609
     * @param boolean                         $returnsReference
610
     * @param boolean                         $isStatic
611
     * @param ParameterExpression[]           $parameterExpressions
612
     * @param ClosureUsedVariableExpression[] $usedVariables
613
     * @param Expression[]                    $bodyExpressions
614
     *
615
     * @return ClosureExpression
616
     */
617
    final public static function closure(
618
            $returnsReference,
619
            $isStatic,
620
            array $parameterExpressions,
621
            array $usedVariables,
622
            array $bodyExpressions
623
    ) {
624
        return new ClosureExpression(
625
                $returnsReference,
626
                $isStatic,
627
                $parameterExpressions,
628
                $usedVariables,
629
                $bodyExpressions);
630
    }
631
632
    /**
633
     * @param string  $name
634
     * @param boolean $isReference
635
     *
636
     * @return ClosureUsedVariableExpression
637
     */
638
    final public static function closureUsedVariable($name, $isReference = false)
639
    {
640
        return new ClosureUsedVariableExpression($name, $isReference);
641
    }
642
643
    // </editor-fold>
644
}
645