Completed
Push — master ( 124462...3bbcdb )
by Дмитрий
02:56
created

FunctionCall   B

Complexity

Total Complexity 45

Size/Duplication

Total Lines 235
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 13

Test Coverage

Coverage 36.63%

Importance

Changes 8
Bugs 0 Features 0
Metric Value
c 8
b 0
f 0
dl 0
loc 235
ccs 63
cts 172
cp 0.3663
rs 8.3673
wmc 45
lcom 0
cbo 13

2 Methods

Rating   Name   Duplication   Size   Complexity  
F compile() 0 210 43
A parseArgs() 0 10 2

How to fix   Complexity   

Complex Class

Complex classes like FunctionCall 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 FunctionCall, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * PHP Smart Analysis project 2015-2016
4
 *
5
 * @author Patsura Dmitry https://github.com/ovr <[email protected]>
6
 */
7
8
namespace PHPSA\Compiler\Expression;
9
10
use Ovr\PHPReflection\Reflector;
11
use PHPSA\CompiledExpression;
12
use PHPSA\Context;
13
use PHPSA\Compiler\Expression;
14
use PHPSA\Definition\ClosureDefinition;
15
16
class FunctionCall extends AbstractExpressionCompiler
17
{
18
    protected $name = 'PhpParser\Node\Expr\FuncCall';
19
20
    /**
21
     * @param \PhpParser\Node\Expr\FuncCall $expr
22
     * @param Context $context
23
     * @return CompiledExpression
24
     */
25 7
    protected function compile($expr, Context $context)
0 ignored issues
show
Complexity introduced by
This operation has 173952 execution paths which exceeds the configured maximum of 200.

A high number of execution paths generally suggests many nested conditional statements and make the code less readible. This can usually be fixed by splitting the method into several smaller methods.

You can also find more information in the “Code” section of your repository.

Loading history...
26
    {
27 7
        $expressionCompiler = $context->getExpressionCompiler();
28 7
        $fNameExpression = $expressionCompiler->compile($expr->name);
29
30 7
        if ($fNameExpression->isCallable()) {
31
            $value = $fNameExpression->getValue();
32
            if ($value && $value instanceof ClosureDefinition) {
33
                return $value->run($this->parseArgs($expr, clone $context), $context);
34
            }
35
        }
36
37 7
        if ($fNameExpression->isString() && $fNameExpression->isCorrectValue()) {
38 7
            $name = $fNameExpression->getValue();
39 7
        } else {
40 1
            $context->debug(
41
                'Unexpected function name type ' . $fNameExpression->getTypeName(),
42
                $expr->name
43
            );
44
45
            return new CompiledExpression;
46
        }
47
48 7
        $compiler = $context->application->compiler;
49
50 7
        $exists = false;
51 7
        $namespace = null;
52
53 7
        if ($context->scope) {
54 7
            $namespace = $context->scope->getNamespace();
55 7
        }
56
57 7
        if ($namespace === null) {
58
            $functionDefinition = $compiler->getFunction($name);
59
        } else {
60 7
            $functionDefinition = $compiler->getFunctionNS($name, $namespace);
61
        }
62
63 7
        if (!$functionDefinition) {
64 7
            $exists = function_exists($name);
65 7
        }
66
67 7
        if ($functionDefinition) {
68
            if (!$functionDefinition->isCompiled()) {
69
                $functionDefinition->compile(clone $context);
70
            }
71
72
            $exists = true;
73
        }
74
75 7
        $arguments = $this->parseArgs($expr, clone $context);
76
77 7
        if (!$functionDefinition) {
78 7
            $reflector = new Reflector(Reflector::manuallyFactory());
79 7
            $functionReflection = $reflector->getFunction($name);
80 7
            if ($functionReflection) {
81 3
                $argumentsSuccessPass = true;
82
83 3
                if (count($arguments) > 0) {
84 3
                    foreach ($arguments as $key => $argument) {
85 3
                        $parameter = $functionReflection->getParameter($key);
86 3
                        if (!$parameter) {
87
                            $argumentsSuccessPass = false;
88
89
                            /**
90
                             * @todo Think a little bit more about it
91
                             */
92
                            continue;
93
                        }
94
95 3
                        switch ($parameter->getType()) {
96 3
                            case CompiledExpression::MIXED:
97
                                //continue
98 2
                                break;
99 2
                            case CompiledExpression::INTEGER:
100 2
                                switch ($argument->getType()) {
101 2
                                    case CompiledExpression::INTEGER:
102 2
                                        break;
103
                                    default:
104
                                        $argumentsSuccessPass = false;
105
                                        break;
106 2
                                }
107 2
                                break;
108
                            case CompiledExpression::DOUBLE:
109
                                switch ($argument->getType()) {
110
                                    case CompiledExpression::DOUBLE:
111
                                        break;
112
                                    default:
113
                                        $argumentsSuccessPass = false;
114
                                        break;
115
                                }
116
                                break;
117
                            case CompiledExpression::NUMBER:
118
                                switch ($argument->getType()) {
119
                                    case CompiledExpression::INTEGER:
120
                                    case CompiledExpression::STRING:
121
                                    case CompiledExpression::NUMBER:
122
                                        break;
123
                                    default:
124
                                        $argumentsSuccessPass = false;
125
                                        break;
126
                                }
127
                                break;
128
                            case CompiledExpression::RESOURCE:
129
                                switch ($argument->getType()) {
130
                                    case CompiledExpression::RESOURCE:
131
                                        break;
132
                                    default:
133
                                        $argumentsSuccessPass = false;
134
                                        break;
135
                                }
136
                                break;
137
                            case CompiledExpression::ARR:
138
                                switch ($argument->getType()) {
139
                                    case CompiledExpression::ARR:
140
                                        break;
141
                                    default:
142
                                        $argumentsSuccessPass = false;
143
                                        break;
144
                                }
145
                                break;
146
                            case CompiledExpression::STRING:
147
                                switch ($argument->getType()) {
148
                                    case CompiledExpression::STRING:
149
                                        break;
150
                                    default:
151
                                        $argumentsSuccessPass = false;
152
                                        break;
153
                                }
154
                                break;
155
                            case CompiledExpression::OBJECT:
156
                                switch ($argument->getType()) {
157
                                    case CompiledExpression::OBJECT:
158
                                        break;
159
                                    default:
160
                                        $argumentsSuccessPass = false;
161
                                        break;
162
                                }
163
                                break;
164
                            case CompiledExpression::BOOLEAN:
165
                                switch ($argument->getType()) {
166
                                    case CompiledExpression::OBJECT:
167
                                        break;
168
                                    default:
169
                                        $argumentsSuccessPass = false;
170
                                        break;
171
                                }
172
                                break;
173
                            case CompiledExpression::CALLABLE_TYPE:
174
                                switch ($argument->getType()) {
175
                                    case CompiledExpression::CALLABLE_TYPE:
176
                                        break;
177
                                    case CompiledExpression::STRING:
178
                                        /**
179
                                         * @todo We need additional check on it
180
                                         */
181
                                        break;
182
                                    /**
183
                                     * array($this, 'method')
184
                                     */
185
                                    case CompiledExpression::ARR:
186
                                        /**
187
                                         * @todo We need additional check on it
188
                                         */
189
                                        break;
190
                                    default:
191
                                        $argumentsSuccessPass = false;
192
                                        break;
193
                                }
194
                                break;
195
                            default:
196
                                $argumentsSuccessPass = false;
197
                                break;
198 3
                        }
199 3
                    }
200 3
                }
201
202 3
                if (count($arguments) < $functionReflection->getNumberOfRequiredParameters()) {
203
                    $argumentsSuccessPass = false;
204
                }
205
206 3
                if ($argumentsSuccessPass && $functionReflection->isRunnable()) {
207 3
                    array_walk(
208 3
                        $arguments,
209 3
                        function (&$item) {
210
                            /** @var CompiledExpression $item */
211 3
                            $item = $item->getValue();
212 3
                        }
213 3
                    );
214
215 3
                    return new CompiledExpression(
216 3
                        $functionReflection->getReturnType(),
217 3
                        $functionReflection->run($arguments)
218 3
                    );
219
                }
220
221
                return new CompiledExpression($functionReflection->getReturnType());
222
            }
223 6
        }
224
225 6
        if (!$exists) {
226
            $context->notice(
227
                'undefined-fcall',
228
                sprintf('Function %s() does not exist', $expr->name->parts[0]),
229
                $expr
230
            );
231
        }
232
233 6
        return new CompiledExpression();
234
    }
235
236
    /**
237
     * @param \PhpParser\Node\Expr\FuncCall $expr
238
     * @return CompiledExpression[]
239
     */
240 7
    protected function parseArgs($expr, Context $context)
241
    {
242 7
        $arguments = array();
243
244 7
        foreach ($expr->args as $argument) {
245 6
            $arguments[] = $context->getExpressionCompiler()->compile($argument->value);
246 7
        }
247
248 7
        return $arguments;
249
    }
250
}
251