Completed
Push — master ( d93213...2ca6bd )
by Дмитрий
02:41
created

ClassMethod::compile()   C

Complexity

Conditions 11
Paths 14

Size

Total Lines 68
Code Lines 38

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 17
CRAP Score 46.8572

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 11
eloc 38
c 3
b 0
f 0
nc 14
nop 1
dl 0
loc 68
ccs 17
cts 51
cp 0.3333
crap 46.8572
rs 5.8371

How to fix   Long Method    Complexity   

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\Compiler\Types;
13
use PHPSA\Compiler\Event;
14
use PHPSA\Context;
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 string $name
41
     * @param Node\Stmt\ClassMethod $statement
42
     * @param integer $type
43
     */
44 8
    public function __construct($name, Node\Stmt\ClassMethod $statement, $type)
45
    {
46 8
        $this->name = $name;
47 8
        $this->statement = $statement;
48 8
        $this->type = $type;
49 8
    }
50
51
    /**
52
     * @param Context $context
53
     * @return boolean|null
54
     */
55 7
    public function compile(Context $context)
56
    {
57 7
        $context->getEventManager()->fire(
58 7
            Event\StatementBeforeCompile::EVENT_NAME,
59 7
            new Event\StatementBeforeCompile(
60 7
                $this->statement,
61
                $context
62 7
            )
63 7
        );
64
65 7
        $this->compiled = true;
66 7
        $context->scopePointer = $this->getPointer();
67
68 7
        if ($this->statement->getDocComment() === null) {
69
            $context->notice(
70
                'missing-docblock',
71
                sprintf('Missing docblock for %s() method', $this->name),
72
                $this->statement
73
            );
74
        }
75
76
        /**
77
         * It's not needed to compile empty method via it's abstract
78
         */
79 7
        if ($this->isAbstract()) {
80
            /** @var ClassDefinition $scope */
81
            $scope = $context->scope;
82
            if (!$scope->isAbstract()) {
83
                $context->notice(
84
                    'not-abstract-class-with-abstract-method',
85
                    'Class must be an abstract',
86
                    $this->statement
87
                );
88
            }
89
90
            return true;
91
        }
92
93 7
        if (count($this->statement->stmts) == 0) {
94
            return $context->notice(
95
                'not-implemented-method',
96
                sprintf('Method %s() is not implemented', $this->name),
97
                $this->statement
98
            );
99
        }
100
101 7
        if ($this->statement->params) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->statement->params of type PhpParser\Node\Param[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

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.

Loading history...
102
            foreach ($this->statement->params as $parameter) {
103
                $type = CompiledExpression::UNKNOWN;
104
105
                if ($parameter->type) {
106
                    if (is_string($parameter->type)) {
107
                        $type = Types::getType($parameter->type);
108
                    } elseif ($parameter->type instanceof Node\Name\FullyQualified) {
109
                        $type = CompiledExpression::OBJECT;
110
                    }
111
                }
112
113
                $context->addVariable(
114
                    new Parameter($parameter->name, null, $type, $parameter->byRef)
115
                );
116
            }
117
        }
118
119 7
        foreach ($this->statement->stmts as $st) {
120 7
            \PHPSA\nodeVisitorFactory($st, $context);
121 7
        }
122 7
    }
123
124
    /**
125
     * @param Context $context
126
     * @param Node\Arg[] $args
127
     * @return CompiledExpression
128
     * @throws \PHPSA\Exception\RuntimeException
129
     */
130
    public function run(Context $context, array $args = null)
131
    {
132
        if ($args) {
133
            foreach ($args as $argument) {
134
                $arguments[] = $context->getExpressionCompiler()->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...
135
            }
136
        }
137
138
        return new CompiledExpression();
139
    }
140
141
    /**
142
     * @return bool
143
     */
144 7
    public function isAbstract()
145
    {
146 7
        return (bool) ($this->type & Node\Stmt\Class_::MODIFIER_ABSTRACT);
147
    }
148
149
    /**
150
     * @return bool
151
     */
152 7
    public function isStatic()
153
    {
154 7
        return (bool) ($this->type & Node\Stmt\Class_::MODIFIER_STATIC);
155
    }
156
157
    /**
158
     * @return bool
159
     */
160
    public function isPublic()
161
    {
162
        return ($this->type & Node\Stmt\Class_::MODIFIER_PUBLIC) !== 0 || $this->type === 0;
163
    }
164
165
    /**
166
     * @return bool
167
     */
168
    public function isProtected()
169
    {
170
        return (bool) ($this->type & Node\Stmt\Class_::MODIFIER_PROTECTED);
171
    }
172
173
    /**
174
     * @return bool
175
     */
176
    public function isPrivate()
177
    {
178
        return (bool) ($this->type & Node\Stmt\Class_::MODIFIER_PRIVATE);
179
    }
180
181
    /**
182
     * @param integer $newType
183
     */
184 7
    public function addNewType($newType)
185
    {
186 7
        if ($this->returnType != CompiledExpression::VOID) {
187
            $this->returnType = $this->returnType | $newType;
188
        } else {
189 7
            $this->returnType = $newType;
190
        }
191 7
    }
192
193
    /**
194
     * @return int
195
     */
196
    public function getReturnType()
197
    {
198
        return $this->returnType;
199
    }
200
201
    /**
202
     * @param $value
203
     */
204 7
    public function addReturnPossibleValue($value)
205
    {
206 7
        $this->possibleReturnValues[] = $value;
207 7
    }
208
209
    /**
210
     * @return array
211
     */
212
    public function getPossibleReturnValues()
213
    {
214
        return $this->possibleReturnValues;
215
    }
216
217
    /**
218
    * @return array
219
    */
220 1
    public function getParams()
221
    {
222 1
        return $this->statement->params;
223
    }
224
}
225