Completed
Pull Request — master (#25)
by Alexander
02:46
created

ReflectionFunctionLikeTrait::isVariadic()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 3

Importance

Changes 0
Metric Value
dl 0
loc 10
c 0
b 0
f 0
ccs 5
cts 5
cp 1
rs 9.4285
cc 3
eloc 5
nc 3
nop 0
crap 3
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 2
            if (!$parameter->isOptional()) {
142 2
                $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
        } else {
190 1
            return null;
191
        }
192
193 1
        return new ReflectionType($returnType, false, $isBuiltin);
194
    }
195
196
    /**
197
     * {@inheritDoc}
198
     */
199 2
    public function getShortName()
200
    {
201 2
        if ($this->functionLikeNode instanceof Function_ || $this->functionLikeNode instanceof ClassMethod) {
202 2
            return $this->functionLikeNode->name;
203
        }
204
205
        return false;
206
    }
207
208 2
    public function getStartLine()
209
    {
210 2
        return $this->functionLikeNode->getAttribute('startLine');
211
    }
212
213
    /**
214
     * {@inheritDoc}
215
     */
216 2
    public function getStaticVariables()
217
    {
218 2
        $nodeTraverser      = new NodeTraverser(false);
219 2
        $variablesCollector = new StaticVariablesCollector($this);
220 2
        $nodeTraverser->addVisitor($variablesCollector);
221
222
        /* @see https://github.com/nikic/PHP-Parser/issues/235 */
223 2
        $nodeTraverser->traverse($this->functionLikeNode->getStmts() ?: array());
224
225 2
        return $variablesCollector->getStaticVariables();
226
    }
227
228
    /**
229
     * Checks if the function has a specified return type
230
     *
231
     * @return bool
232
     *
233
     * @link http://php.net/manual/en/reflectionfunctionabstract.hasreturntype.php
234
     */
235 3
    public function hasReturnType()
236
    {
237 3
        $returnType = $this->functionLikeNode->getReturnType();
238
239 3
        return isset($returnType);
240
    }
241
242
    /**
243
     * {@inheritDoc}
244
     */
245 2
    public function inNamespace()
246
    {
247 2
        return !empty($this->namespaceName);
248
    }
249
250
    /**
251
     * {@inheritDoc}
252
     */
253 1
    public function isClosure()
254
    {
255 1
        return $this->functionLikeNode instanceof Closure;
256
    }
257
258
    /**
259
     * {@inheritDoc}
260
     */
261 1
    public function isDeprecated()
262
    {
263
        // userland method/function/closure can not be deprecated
264 1
        return false;
265
    }
266
267
    /**
268
     * {@inheritDoc}
269
     */
270 1
    public function isGenerator()
271
    {
272 1
        $nodeTraverser = new NodeTraverser(false);
273 1
        $nodeDetector  = new GeneratorDetector();
274 1
        $nodeTraverser->addVisitor($nodeDetector);
275
276
        /* @see https://github.com/nikic/PHP-Parser/issues/235 */
277 1
        $nodeTraverser->traverse($this->functionLikeNode->getStmts() ?: array());
278
279 1
        return $nodeDetector->isGenerator();
280
    }
281
282
    /**
283
     * {@inheritDoc}
284
     */
285 1
    public function isInternal()
286
    {
287
        // never can be an internal method
288 1
        return false;
289
    }
290
291
    /**
292
     * {@inheritDoc}
293
     */
294 1
    public function isUserDefined()
295
    {
296
        // always defined by user, because we parse the source code
297 1
        return true;
298
    }
299
300
    /**
301
     * {@inheritDoc}
302
     */
303 1
    public function isVariadic()
304
    {
305 1
        foreach ($this->getParameters() as $parameter) {
306 1
            if ($parameter->isVariadic()) {
307 1
                return true;
308
            }
309
        }
310
311 1
        return false;
312
    }
313
314
    /**
315
     * {@inheritDoc}
316
     */
317 2
    public function returnsReference()
318
    {
319 2
        return $this->functionLikeNode->returnsByRef();
320
    }
321
}
322