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

ClassMethod::run()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 5
c 1
b 0
f 0
nc 2
nop 2
dl 0
loc 10
ccs 0
cts 7
cp 0
crap 12
rs 9.4285
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