Completed
Push — master ( 280baa...f3a461 )
by Дмитрий
16:07 queued 07:04
created

ClassMethod::compile()   C

Complexity

Conditions 8
Paths 16

Size

Total Lines 51
Code Lines 27

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 72

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 51
ccs 0
cts 37
cp 0
rs 6.5979
cc 8
eloc 27
nc 16
nop 1
crap 72

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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\Expression;
11
use PHPSA\Compiler\Parameter;
12
use PHPSA\Context;
13
use PHPSA\ScopePointer;
14
use PHPSA\Variable;
15
16
class ClassMethod extends AbstractDefinition
17
{
18
    protected $type;
19
20
    /**
21
     * @var Node\Stmt\ClassMethod
22
     */
23
    protected $statement;
24
25
    /**
26
     * Return type
27
     *
28
     * @var int
29
     */
30
    protected $returnType = CompiledExpression::VOID;
31
32
    /**
33
     * Array of possible return values
34
     *
35
     * @var array
36
     */
37
    protected $possibleReturnValues = array();
38
39
    /**
40
     * @param $name
41
     * @param Node\Stmt\ClassMethod $statement
42
     * @param $type
43
     */
44 1
    public function __construct($name, Node\Stmt\ClassMethod $statement, $type)
45
    {
46 1
        $this->name = $name;
47 1
        $this->statement = $statement;
48 1
        $this->type = $type;
49 1
    }
50
51
    /**
52
     * @param Context $context
53
     * @return boolean|null
54
     */
55
    public function compile(Context $context)
56
    {
57
        $this->compiled = true;
58
        $context->scopePointer = $this->getPointer();
59
60
        if ($this->statement->getDocComment() === null) {
61
            $context->notice(
62
                'missing-docblock',
63
                sprintf('Missing docblock for %s() method', $this->name),
64
                $this->statement
65
            );
66
        }
67
68
        /**
69
         * It's not needed to compile empty method via it's abstract
70
         */
71
        if ($this->isAbstract()) {
72
            /** @var ClassDefinition $scope */
73
            $scope = $context->scope;
74
            if (!$scope->isAbstract()) {
75
                $context->notice(
76
                    'not-abstract-class-with-abstract-method',
77
                    'Class must be an abstract',
78
                    $this->statement
79
                );
80
            }
81
82
            return true;
83
        }
84
85
        if (count($this->statement->stmts) == 0) {
86
            return $context->notice(
87
                'not-implemented-method',
88
                sprintf('Method %s() is not implemented', $this->name),
89
                $this->statement
90
            );
91
        }
92
93
        if (count($this->statement->params) > 0) {
94
            /** @var  Node\Param $parameter */
95
            foreach ($this->statement->params as $parameter) {
96
                $context->addVariable(
97
                    new Parameter($parameter->name, CompiledExpression::UNKNOWN, null, $parameter->byRef)
98
                );
99
            }
100
        }
101
102
        foreach ($this->statement->stmts as $st) {
103
            \PHPSA\nodeVisitorFactory($st, $context);
104
        }
105
    }
106
107
    public function run(array $args = null, Context $context)
0 ignored issues
show
Coding Style introduced by
Parameters which have default values should be placed at the end.

If you place a parameter with a default value before a parameter with a default value, the default value of the first parameter will never be used as it will always need to be passed anyway:

// $a must always be passed; it's default value is never used.
function someFunction($a = 5, $b) { }
Loading history...
108
    {
109
        if ($args) {
110
            foreach ($args as $argument) {
111
                $expression = new Expression($context);
112
                $arguments[] = $expression->compile($argument->value);
0 ignored issues
show
Coding Style Comprehensibility introduced by
$arguments was never initialized. Although not strictly required by PHP, it is generally a good practice to add $arguments = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
113
            }
114
        }
115
    }
116
117
    /**
118
     * @return bool
119
     */
120
    public function isAbstract()
121
    {
122
        return (bool) ($this->type & Node\Stmt\Class_::MODIFIER_ABSTRACT);
123
    }
124
125
    /**
126
     * @return bool
127
     */
128
    public function isStatic()
129
    {
130
        return (bool) ($this->type & Node\Stmt\Class_::MODIFIER_STATIC);
131
    }
132
133
    /**
134
     * @return bool
135
     */
136
    public function isPublic()
137
    {
138
        return ($this->type & Node\Stmt\Class_::MODIFIER_PUBLIC) !== 0 || $this->type === 0;
139
    }
140
141
    /**
142
     * @return bool
143
     */
144
    public function isProtected()
145
    {
146
        return (bool) ($this->type & Node\Stmt\Class_::MODIFIER_PROTECTED);
147
    }
148
149
    /**
150
     * @return bool
151
     */
152
    public function isPrivate()
153
    {
154
        return (bool) ($this->type & Node\Stmt\Class_::MODIFIER_PRIVATE);
155
    }
156
157
    /**
158
     * @param $newType
159
     */
160
    public function addNewType($newType)
161
    {
162
        if ($this->returnType != CompiledExpression::VOID) {
163
            $this->returnType = $this->returnType | $newType;
164
        } else {
165
            $this->returnType = $newType;
166
        }
167
    }
168
169
    /**
170
     * @return int
171
     */
172
    public function getReturnType()
173
    {
174
        return $this->returnType;
175
    }
176
177
    /**
178
     * @param $value
179
     */
180
    public function addReturnPossibleValue($value)
181
    {
182
        $this->possibleReturnValues[] = $value;
183
    }
184
185
    /**
186
     * @return array
187
     */
188
    public function getPossibleReturnValues()
189
    {
190
        return $this->possibleReturnValues;
191
    }
192
}
193