Passed
Push — master ( c826a7...1a0ddb )
by Kyle
52s queued 10s
created

AbstractNode::findChildrenOfTypeVariable()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 4
ccs 1
cts 1
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * This file is part of PHP Mess Detector.
4
 *
5
 * Copyright (c) Manuel Pichler <[email protected]>.
6
 * All rights reserved.
7
 *
8
 * Licensed under BSD License
9
 * For full copyright and license information, please see the LICENSE file.
10
 * Redistributions of files must retain the above copyright notice.
11
 *
12
 * @author Manuel Pichler <[email protected]>
13
 * @copyright Manuel Pichler. All rights reserved.
14
 * @license https://opensource.org/licenses/bsd-license.php BSD License
15
 * @link http://phpmd.org/
16
 */
17
18
namespace PHPMD;
19
20
use PDepend\Source\AST\AbstractASTArtifact;
21
use PDepend\Source\AST\ASTVariable;
22
use PHPMD\Node\ASTNode;
23
24
/**
25
 * This is an abstract base class for PHPMD code nodes, it is just a wrapper
26
 * around PDepend's object model.
27
 */
28
abstract class AbstractNode
29
{
30
    /**
31
     * @var \PDepend\Source\AST\ASTArtifact|\PDepend\Source\AST\ASTNode $node
32
     */
33
    private $node = null;
34
35
    /**
36
     * The collected metrics for this node.
37
     *
38
     * @var array<string, mixed>
39
     */
40
    private $metrics = null;
41
42
    /**
43
     * Constructs a new PHPMD node.
44
     *
45 59
     * @param \PDepend\Source\AST\ASTArtifact|\PDepend\Source\AST\ASTNode $node
46
     */
47 59
    public function __construct($node)
48 59
    {
49
        $this->node = $node;
50
    }
51
52
    /**
53
     * The magic call method is used to pipe requests from rules direct
54
     * to the underlying PDepend AST node.
55
     *
56
     * @param string $name
57
     * @param array $args
58
     * @return mixed
59
     * @throws \BadMethodCallException When the underlying PDepend node
60 36
     *         does not contain a method named <b>$name</b>.
61
     */
62 36
    public function __call($name, array $args)
63 36
    {
64
        $node = $this->getNode();
65
        if (!method_exists($node, $name)) {
66
            throw new \BadMethodCallException(
67
                sprintf('Invalid method %s() called.', $name)
68 36
            );
69
        }
70
71
        return call_user_func_array(array($node, $name), $args);
72
    }
73
74
    /**
75
     * Returns the parent of this node or <b>null</b> when no parent node
76
     * exists.
77 8
     *
78
     * @return ASTNode
79 8
     */
80
    public function getParent()
81
    {
82 8
        $node = $this->node->getParent();
0 ignored issues
show
Bug introduced by
The method getParent does only exist in PDepend\Source\AST\ASTNode, but not in PDepend\Source\AST\ASTArtifact.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
83
        if ($node === null) {
84
            return null;
85
        }
86
87
        return new ASTNode($node, $this->getFileName());
88
    }
89
90
    /**
91 13
     * Returns a child node at the given index.
92
     *
93 13
     * @param integer $index The child offset.
94 13
     * @return \PHPMD\Node\ASTNode
95 13
     */
96
    public function getChild($index)
97
    {
98
        return new ASTNode(
99
            $this->node->getChild($index),
0 ignored issues
show
Bug introduced by
The method getChild does only exist in PDepend\Source\AST\ASTNode, but not in PDepend\Source\AST\ASTArtifact.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
100
            $this->getFileName()
101
        );
102
    }
103
104
    /**
105
     * Returns the first child of the given type or <b>null</b> when this node
106 22
     * has no child of the given type.
107
     *
108 22
     * @param string $type The searched child type.
109 22
     * @return ASTNode|null
110
     */
111
    public function getFirstChildOfType($type)
112 22
    {
113
        $node = $this->node->getFirstChildOfType('PDepend\Source\AST\AST' . $type);
0 ignored issues
show
Bug introduced by
The method getFirstChildOfType does only exist in PDepend\Source\AST\ASTNode, but not in PDepend\Source\AST\ASTArtifact.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
114
115
        if ($node === null) {
116
            return null;
117
        }
118
119
        return new ASTNode($node, $this->getFileName());
120
    }
121
122 55
    /**
123
     * Searches recursive for all children of this node that are of the given
124 55
     * type.
125
     *
126 55
     * @param string $type The searched child type.
127 55
     * @return ASTNode[]
128 51
     */
129
    public function findChildrenOfType($type)
130 55
    {
131
        $children = $this->node->findChildrenOfType('PDepend\Source\AST\AST' . $type);
0 ignored issues
show
Bug introduced by
The method findChildrenOfType does only exist in PDepend\Source\AST\ASTNode, but not in PDepend\Source\AST\ASTArtifact.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
132
133
        $nodes = array();
134
135
        foreach ($children as $child) {
136
            $nodes[] = new ASTNode($child, $this->getFileName());
137
        }
138
139 2
        return $nodes;
140
    }
141 2
142 2
    /**
143
     * Searches recursive for all children of this node that are of variable.
144
     *
145
     * @return ASTVariable[]
146
     * @todo Cover by a test.
147
     */
148
    public function findChildrenOfTypeVariable()
149
    {
150 2
        return $this->findChildrenOfType('Variable');
151
    }
152 2
153
    /**
154
     * Tests if this node represents the the given type.
155
     *
156
     * @param string $type The expected node type.
157
     * @return boolean
158
     */
159
    public function isInstanceOf($type)
160
    {
161 15
        $class = 'PDepend\Source\AST\AST' . $type;
162
163 15
        return ($this->node instanceof $class);
164
    }
165
166
    /**
167
     * Returns the image of the underlying node.
168
     *
169
     * @return string
170
     */
171 6
    public function getImage()
172
    {
173 6
        return $this->node->getName();
0 ignored issues
show
Bug introduced by
The method getName does only exist in PDepend\Source\AST\ASTArtifact, but not in PDepend\Source\AST\ASTNode.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
174
    }
175
176
    /**
177
     * Returns the source name for this node, maybe a class or interface name,
178
     * or a package, method, function name.
179
     *
180
     * @return string
181
     */
182
    public function getName()
183
    {
184
        return $this->node->getName();
0 ignored issues
show
Bug introduced by
The method getName does only exist in PDepend\Source\AST\ASTArtifact, but not in PDepend\Source\AST\ASTNode.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
185
    }
186
187
    /**
188
     * Returns the begin line for this node in the php source code file.
189
     *
190
     * @return integer
191 54
     */
192
    public function getBeginLine()
193 54
    {
194
        return $this->node->getStartLine();
0 ignored issues
show
Bug introduced by
The method getStartLine does only exist in PDepend\Source\AST\ASTNode, but not in PDepend\Source\AST\ASTArtifact.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
195
    }
196
197
    /**
198
     * Returns the end line for this node in the php source code file.
199
     *
200
     * @return integer
201 51
     */
202
    public function getEndLine()
203 51
    {
204
        return $this->node->getEndLine();
0 ignored issues
show
Bug introduced by
The method getEndLine does only exist in PDepend\Source\AST\ASTNode, but not in PDepend\Source\AST\ASTArtifact.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
205
    }
206
207
    /**
208
     * Returns the name of the declaring source file.
209
     *
210
     * @return string|null
211 3
     */
212
    public function getFileName()
213 3
    {
214 3
        $compilationUnit = $this->node instanceof AbstractASTArtifact
215
            ? $this->node->getCompilationUnit()
216
            : null;
217
218
        return $compilationUnit
219
            ? (string)$compilationUnit->getFileName()
220
            : null; // @TODO: Find the name from some parent node https://github.com/phpmd/phpmd/issues/837
221
    }
222
223
    /**
224 3
     * Returns the wrapped PDepend node instance.
225
     *
226 3
     * @return \PDepend\Source\AST\ASTArtifact
227 3
     */
228
    public function getNode()
229
    {
230
        return $this->node;
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->node; of type PDepend\Source\AST\ASTAr...pend\Source\AST\ASTNode adds the type PDepend\Source\AST\ASTNode to the return on line 230 which is incompatible with the return type documented by PHPMD\AbstractNode::getNode of type PDepend\Source\AST\ASTArtifact.
Loading history...
231
    }
232
233
    /**
234
     * Returns a textual representation/name for the concrete node type.
235
     *
236
     * @return string
237
     */
238 6
    public function getType()
239
    {
240 6
        $type = explode('\\', get_class($this));
241 6
242
        return preg_replace('(node$)', '', strtolower(array_pop($type)));
243 6
    }
244
245
    /**
246
     * This method will return the metric value for the given identifier or
247
     * <b>null</b> when no such metric exists.
248
     *
249
     * @param string $name The metric name or abbreviation.
250
     * @return mixed
251
     */
252
    public function getMetric($name)
253
    {
254
        if (isset($this->metrics[$name])) {
255
            return $this->metrics[$name];
256
        }
257
258
        return null;
259
    }
260
261
    /**
262
     * This method will set the metrics for this node.
263
     *
264
     * @param array<string, mixed> $metrics The collected node metrics.
265
     * @return void
266
     */
267
    public function setMetrics(array $metrics)
268
    {
269
        if ($this->metrics === null) {
270
            $this->metrics = $metrics;
271
        }
272
    }
273
274
    /**
275
     * Checks if this node has a suppressed annotation for the given rule
276
     * instance.
277
     *
278
     * @param \PHPMD\Rule $rule
279
     * @return boolean
280
     */
281
    abstract public function hasSuppressWarningsAnnotationFor(Rule $rule);
282
283
    /**
284
     * Returns the full qualified name of a class, an interface, a method or
285
     * a function.
286
     *
287
     * @return string
288
     */
289
    abstract public function getFullQualifiedName();
290
291
    /**
292
     * Returns the name of the parent type or <b>null</b> when this node has no
293
     * parent type.
294
     *
295
     * @return string
296
     */
297
    abstract public function getParentName();
298
299
    /**
300
     * Returns the name of the parent package.
301
     *
302
     * @return string
303
     */
304
    abstract public function getNamespaceName();
305
}
306