Passed
Push — master ( 902a34...c826a7 )
by Kyle
53s queued 11s
created

src/test/php/PHPMD/Node/MethodNodeTest.php (2 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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\Node;
19
20
use PDepend\Source\AST\ASTClass;
21
use PDepend\Source\AST\ASTMethod;
22
use PDepend\Source\AST\ASTNamespace;
23
use PHPMD\AbstractTest;
24
25
/**
26
 * Test case for the method node implementation.
27
 *
28
 * @covers \PHPMD\Node\MethodNode
29
 * @covers \PHPMD\Node\AbstractCallableNode
30
 */
31
class MethodNodeTest extends AbstractTest
32
{
33
    /**
34
     * testMagicCallDelegatesToWrappedPHPDependMethod
35
     *
36
     * @return void
37
     */
38 View Code Duplication
    public function testMagicCallDelegatesToWrappedPHPDependMethod()
39
    {
40
        $method = $this->getMockFromBuilder(
41
            $this->getMockBuilder('PDepend\\Source\\AST\\ASTMethod')
42
                ->setConstructorArgs(array(null))
43
        );
44
        $method->expects($this->once())
45
            ->method('getStartLine');
46
47
        $node = new MethodNode($method);
48
        $node->getStartLine();
49
    }
50
51
    /**
52
     * testMagicCallThrowsExceptionWhenNoMatchingMethodExists
53
     *
54
     * @return void
55
     * @expectedException \BadMethodCallException
56
     */
57
    public function testMagicCallThrowsExceptionWhenNoMatchingMethodExists()
58
    {
59
        $node = new MethodNode(new ASTMethod(null));
60
        $node->getFooBar();
61
    }
62
63
    /**
64
     * testGetParentTypeReturnsInterfaceForInterfaceMethod
65
     *
66
     * @return void
67
     */
68
    public function testGetParentTypeReturnsInterfaceForInterfaceMethod()
69
    {
70
        $this->assertInstanceOf(
71
            'PHPMD\\Node\\InterfaceNode',
72
            $this->getMethod()->getParentType()
73
        );
74
    }
75
76
    /**
77
     * testGetParentTypeReturnsClassForClassMethod
78
     *
79
     * @return void
80
     */
81
    public function testGetParentTypeReturnsClassForClassMethod()
82
    {
83
        $this->assertInstanceOf(
84
            'PHPMD\\Node\\ClassNode',
85
            $this->getMethod()->getParentType()
86
        );
87
    }
88
89
    /**
90
     * @return void
91
     */
92
    public function testGetParentTypeReturnsTrait()
93
    {
94
        $this->assertInstanceOf(
95
            'PHPMD\\Node\\TraitNode',
96
            $this->getMethod()->getParentType()
97
        );
98
    }
99
100
    /**
101
     * testHasSuppressWarningsExecutesDefaultImplementation
102
     *
103
     * @return void
104
     */
105 View Code Duplication
    public function testHasSuppressWarningsExecutesDefaultImplementation()
106
    {
107
        $rule = $this->getRuleMock();
108
        $rule->setName('FooBar');
109
110
        $method = $this->getMethod();
111
        $this->assertTrue($method->hasSuppressWarningsAnnotationFor($rule));
112
    }
113
114
    /**
115
     * testHasSuppressWarningsDelegatesToParentClassMethod
116
     *
117
     * @return void
118
     */
119 View Code Duplication
    public function testHasSuppressWarningsDelegatesToParentClassMethod()
120
    {
121
        $rule = $this->getRuleMock();
122
        $rule->setName('FooBar');
123
124
        $method = $this->getMethod();
125
        $this->assertTrue($method->hasSuppressWarningsAnnotationFor($rule));
126
    }
127
128
    /**
129
     * testHasSuppressWarningsDelegatesToParentInterfaceMethod
130
     *
131
     * @return void
132
     */
133 View Code Duplication
    public function testHasSuppressWarningsDelegatesToParentInterfaceMethod()
134
    {
135
        $rule = $this->getRuleMock();
136
        $rule->setName('FooBar');
137
138
        $method = $this->getMethod();
139
        $this->assertTrue($method->hasSuppressWarningsAnnotationFor($rule));
140
    }
141
142
    /**
143
     * testHasSuppressWarningsIgnoresCaseFirstLetter
144
     *
145
     * @return void
146
     */
147 View Code Duplication
    public function testHasSuppressWarningsIgnoresCaseFirstLetter()
148
    {
149
        $rule = $this->getRuleMock();
150
        $rule->setName('FooBar');
0 ignored issues
show
The method setName does only exist in PHPMD\AbstractRule, but not in PHPUnit_Framework_MockObject_MockObject.

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...
151
152
        $method = $this->getMethod();
153
        $this->assertTrue($method->hasSuppressWarningsAnnotationFor($rule));
0 ignored issues
show
It seems like $rule defined by $this->getRuleMock() on line 149 can also be of type object<PHPUnit_Framework_MockObject_MockObject>; however, PHPMD\Node\MethodNode::h...WarningsAnnotationFor() does only seem to accept object<PHPMD\Rule>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
154
    }
155
156
    /**
157
     * testIsDeclarationReturnsTrueForMethodDeclaration
158
     *
159
     * @return void
160
     * @since 1.2.1
161
     */
162
    public function testIsDeclarationReturnsTrueForMethodDeclaration()
163
    {
164
        $method = $this->getMethod();
165
        $this->assertTrue($method->isDeclaration());
166
    }
167
168
    /**
169
     * testIsDeclarationReturnsTrueForMethodDeclarationWithParent
170
     *
171
     * @return void
172
     * @since 1.2.1
173
     */
174
    public function testIsDeclarationReturnsTrueForMethodDeclarationWithParent()
175
    {
176
        $method = $this->getMethod();
177
        $this->assertTrue($method->isDeclaration());
178
    }
179
180
    /**
181
     * testIsDeclarationReturnsFalseForInheritMethodDeclaration
182
     *
183
     * @return void
184
     * @since 1.2.1
185
     */
186
    public function testIsDeclarationReturnsFalseForInheritMethodDeclaration()
187
    {
188
        $method = $this->getMethod();
189
        $this->assertFalse($method->isDeclaration());
190
    }
191
192
    /**
193
     * testIsDeclarationReturnsFalseForImplementedAbstractMethod
194
     *
195
     * @return void
196
     * @since 1.2.1
197
     */
198
    public function testIsDeclarationReturnsFalseForImplementedAbstractMethod()
199
    {
200
        $method = $this->getMethod();
201
        $this->assertFalse($method->isDeclaration());
202
    }
203
204
    /**
205
     * testIsDeclarationReturnsFalseForImplementedInterfaceMethod
206
     *
207
     * @return void
208
     * @since 1.2.1
209
     */
210
    public function testIsDeclarationReturnsFalseForImplementedInterfaceMethod()
211
    {
212
        $method = $this->getMethod();
213
        $this->assertFalse($method->isDeclaration());
214
    }
215
216
    /**
217
     * @return void
218
     */
219
    public function testIsDeclarationReturnsTrueForPrivateMethod()
220
    {
221
        $method = $this->getMethod();
222
        $this->assertTrue($method->isDeclaration());
223
    }
224
225
    /**
226
     * testGetFullQualifiedNameReturnsExpectedValue
227
     *
228
     * @return void
229
     */
230
    public function testGetFullQualifiedNameReturnsExpectedValue()
231
    {
232
        $class = new ASTClass('MyClass');
233
        $class->setNamespace(new ASTNamespace('Sindelfingen'));
234
235
        $method = new ASTMethod('beer');
236
        $method->setParent($class);
237
238
        $node = new MethodNode($method);
239
240
        $this->assertSame('Sindelfingen\\MyClass::beer()', $node->getFullQualifiedName());
241
    }
242
}
243