Completed
Push — master ( 79fae7...f16f1c )
by Alexander
07:00
created

ReflectionFunctionLikeTrait::isVariadic()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 3.576
Metric Value
dl 0
loc 10
ccs 3
cts 5
cp 0.6
rs 9.4285
cc 3
eloc 5
nc 3
nop 0
crap 3.576
1
<?php
2
/**
3
 * Parser Reflection API
4
 *
5
 * @copyright Copyright 2015, Lisachenko Alexander <[email protected]>
6
 *
7
 * This source file is subject to the license that is bundled
8
 * with this source code in the file LICENSE.
9
 */
10
11
namespace Go\ParserReflection\Traits;
12
13
14
use Go\ParserReflection\NodeVisitor\GeneratorDetector;
15
use Go\ParserReflection\NodeVisitor\StaticVariablesCollector;
16
use Go\ParserReflection\ReflectionFileNamespace;
17
use Go\ParserReflection\ReflectionParameter;
18
use Go\ParserReflection\ReflectionType;
19
use PhpParser\Node\Expr\Closure;
20
use PhpParser\Node\FunctionLike;
21
use PhpParser\Node\Stmt\ClassMethod;
22
use PhpParser\Node\Stmt\Function_;
23
use PhpParser\NodeTraverser;
24
25
/**
26
 * General trait for all function-like reflections
27
 */
28
trait ReflectionFunctionLikeTrait
29
{
30
    use InitializationTrait;
31
32
    /**
33
     * @var FunctionLike
34
     */
35
    protected $functionLikeNode;
36
37
    /**
38
     * Namespace name
39
     *
40
     * @var string
41
     */
42
    protected $namespaceName = '';
43
44
    /**
45
     * @var array|ReflectionParameter[]
46
     */
47
    protected $parameters;
48
49
    /**
50
     * {@inheritDoc}
51
     */
52 2
    public function getClosureScopeClass()
53
    {
54 2
        $this->initializeInternalReflection();
55
56 2
        return forward_static_call('parent::getClosureScopeClass');
57
    }
58
59
    /**
60
     * {@inheritDoc}
61
     */
62 2
    public function getClosureThis()
63
    {
64 2
        $this->initializeInternalReflection();
65
66 2
        return forward_static_call('parent::getClosureThis');
67
    }
68
69 2
    public function getDocComment()
70
    {
71 2
        $docComment = $this->functionLikeNode->getDocComment();
72
73 2
        return $docComment ? $docComment->getText() : false;
74
    }
75
76 2
    public function getEndLine()
77
    {
78 2
        return $this->functionLikeNode->getAttribute('endLine');
79
    }
80
81 2
    public function getExtension()
82
    {
83 2
        return null;
84
    }
85
86 2
    public function getExtensionName()
87
    {
88 2
        return false;
89
    }
90
91 9
    public function getFileName()
92
    {
93 9
        return $this->functionLikeNode->getAttribute('fileName');
94
    }
95
96
    /**
97
     * {@inheritDoc}
98
     */
99 23
    public function getName()
100
    {
101 23
        if ($this->functionLikeNode instanceof Function_ || $this->functionLikeNode instanceof ClassMethod) {
102 23
            $functionName = $this->functionLikeNode->name;
103
104 23
            return $this->namespaceName ? $this->namespaceName . '\\' . $functionName : $functionName;
105
        }
106
107
        return false;
108
    }
109
110
    /**
111
     * {@inheritDoc}
112
     */
113 9
    public function getNamespaceName()
114
    {
115 9
        return $this->namespaceName;
116
    }
117
118
    /**
119
     * Get the number of parameters that a function defines, both optional and required.
120
     *
121
     * @link http://php.net/manual/en/reflectionfunctionabstract.getnumberofparameters.php
122
     *
123
     * @return int
124
     */
125 2
    public function getNumberOfParameters()
126
    {
127 2
        return count($this->functionLikeNode->getParams());
128
    }
129
130
    /**
131
     * Get the number of required parameters that a function defines.
132
     *
133
     * @link http://php.net/manual/en/reflectionfunctionabstract.getnumberofrequiredparameters.php
134
     *
135
     * @return int
136
     */
137 2
    public function getNumberOfRequiredParameters()
138
    {
139 2
        $requiredParameters = 0;
140 2
        foreach ($this->getParameters() as $parameter) {
141 1
            if (!$parameter->isOptional()) {
142 1
                $requiredParameters++;
143
            }
144
        }
145
146 2
        return $requiredParameters;
147
    }
148
149
    /**
150
     * {@inheritDoc}
151
     */
152 10
    public function getParameters()
153
    {
154 10
        if (!isset($this->parameters)) {
155 10
            $parameters = [];
156
157 10
            foreach ($this->functionLikeNode->getParams() as $parameterIndex => $parameterNode) {
158 10
                $reflectionParameter = new ReflectionParameter(
159 10
                    $this->getName(),
160 10
                    $parameterNode->name,
161
                    $parameterNode,
162
                    $parameterIndex,
163
                    $this
164
                );
165 10
                $parameters[] = $reflectionParameter;
166
            }
167
168 10
            $this->parameters = $parameters;
169
        }
170
171 10
        return $this->parameters;
172
    }
173
174
    /**
175
     * Gets the specified return type of a function
176
     *
177
     * @return \ReflectionType
178
     *
179
     * @link http://php.net/manual/en/reflectionfunctionabstract.getreturntype.php
180
     */
181 1
    public function getReturnType()
182
    {
183 1
        $isBuiltin  = false;
184 1
        $returnType = $this->functionLikeNode->getReturnType();
185 1
        if (is_object($returnType)) {
186 1
            $returnType = $returnType->toString();
187 1
        } elseif (is_string($returnType)) {
188 1
            $isBuiltin = true;
189
        }
190
191 1
        return new ReflectionType($returnType, false, $isBuiltin);
192
    }
193
194
    /**
195
     * {@inheritDoc}
196
     */
197 2
    public function getShortName()
198
    {
199 2
        if ($this->functionLikeNode instanceof Function_ || $this->functionLikeNode instanceof ClassMethod) {
200 2
            return $this->functionLikeNode->name;
201
        }
202
203
        return false;
204
    }
205
206 2
    public function getStartLine()
207
    {
208 2
        return $this->functionLikeNode->getAttribute('startLine');
209
    }
210
211
    /**
212
     * {@inheritDoc}
213
     */
214 2
    public function getStaticVariables()
215
    {
216 2
        $nodeTraverser      = new NodeTraverser(false);
217 2
        $variablesCollector = new StaticVariablesCollector($this);
218 2
        $nodeTraverser->addVisitor($variablesCollector);
219
220
        /* @see https://github.com/nikic/PHP-Parser/issues/235 */
221 2
        $nodeTraverser->traverse($this->functionLikeNode->getStmts() ?: array());
222
223 2
        return $variablesCollector->getStaticVariables();
224
    }
225
226
    /**
227
     * Checks if the function has a specified return type
228
     *
229
     * @return bool
230
     *
231
     * @link http://php.net/manual/en/reflectionfunctionabstract.hasreturntype.php
232
     */
233 3
    public function hasReturnType()
234
    {
235 3
        $returnType = $this->functionLikeNode->getReturnType();
236
237 3
        return isset($returnType);
238
    }
239
240
    /**
241
     * {@inheritDoc}
242
     */
243 2
    public function inNamespace()
244
    {
245 2
        return !empty($this->namespaceName);
246
    }
247
248
    /**
249
     * {@inheritDoc}
250
     */
251 1
    public function isClosure()
252
    {
253 1
        return $this->functionLikeNode instanceof Closure;
254
    }
255
256
    /**
257
     * {@inheritDoc}
258
     */
259 1
    public function isDeprecated()
260
    {
261
        // userland method/function/closure can not be deprecated
262 1
        return false;
263
    }
264
265
    /**
266
     * {@inheritDoc}
267
     */
268 1
    public function isGenerator()
269
    {
270 1
        $nodeTraverser = new NodeTraverser(false);
271 1
        $nodeDetector  = new GeneratorDetector();
272 1
        $nodeTraverser->addVisitor($nodeDetector);
273
274
        /* @see https://github.com/nikic/PHP-Parser/issues/235 */
275 1
        $nodeTraverser->traverse($this->functionLikeNode->getStmts() ?: array());
276
277 1
        return $nodeDetector->isGenerator();
278
    }
279
280
    /**
281
     * {@inheritDoc}
282
     */
283 1
    public function isInternal()
284
    {
285
        // never can be an internal method
286 1
        return false;
287
    }
288
289
    /**
290
     * {@inheritDoc}
291
     */
292 1
    public function isUserDefined()
293
    {
294
        // always defined by user, because we parse the source code
295 1
        return true;
296
    }
297
298
    /**
299
     * {@inheritDoc}
300
     */
301 1
    public function isVariadic()
302
    {
303 1
        foreach ($this->getParameters() as $parameter) {
304
            if ($parameter->isVariadic()) {
305
                return true;
306
            }
307
        }
308
309 1
        return false;
310
    }
311
312
    /**
313
     * {@inheritDoc}
314
     */
315 2
    public function returnsReference()
316
    {
317 2
        return $this->functionLikeNode->returnsByRef();
318
    }
319
}
320