Passed
Push — master ( 1a0ddb...73af58 )
by Kyle
47s queued 10s
created

src/main/php/PHPMD/Node/MethodNode.php (5 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\ASTMethod;
21
use PDepend\Source\AST\ASTClass;
22
use PDepend\Source\AST\ASTTrait;
23
use PHPMD\Rule;
24
25
/**
26
 * Wrapper around a PHP_Depend method node.
27
 *
28
 * Methods available on $node via PHPMD\AbstractNode::__call
29
 *
30
 * @method bool isPrivate() Returns true if this node is marked as private.
31
 */
32
class MethodNode extends AbstractCallableNode
33
{
34
    /**
35
     * Constructs a new method wrapper.
36
     *
37
     * @param \PDepend\Source\AST\ASTMethod $node
38
     */
39 56
    public function __construct(ASTMethod $node)
40
    {
41 56
        parent::__construct($node);
42 56
    }
43
44
    /**
45
     * Returns the name of the parent package.
46
     *
47
     * @return string
48
     */
49 4
    public function getNamespaceName()
50
    {
51 4
        return $this->getNode()->getParent()->getNamespace()->getName();
0 ignored issues
show
It seems like you code against a concrete implementation and not the interface PDepend\Source\AST\ASTArtifact as the method getParent() does only exist in the following implementations of said interface: PDepend\Source\AST\ASTAnonymousClass, PDepend\Source\AST\ASTMethod.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
52
    }
53
54
    /**
55
     * Returns the name of the parent type or <b>null</b> when this node has no
56
     * parent type.
57
     *
58
     * @return string
59
     */
60 2
    public function getParentName()
61
    {
62 2
        return $this->getNode()->getParent()->getName();
0 ignored issues
show
It seems like you code against a concrete implementation and not the interface PDepend\Source\AST\ASTArtifact as the method getParent() does only exist in the following implementations of said interface: PDepend\Source\AST\ASTAnonymousClass, PDepend\Source\AST\ASTMethod.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
63
    }
64
65
    /**
66
     * Returns the full qualified name of a class, an interface, a method or
67
     * a function.
68
     *
69
     * @return string
70
     */
71 1
    public function getFullQualifiedName()
72
    {
73 1
        return sprintf(
74 1
            '%s\\%s::%s()',
75 1
            $this->getNamespaceName(),
76 1
            $this->getParentName(),
77 1
            $this->getName()
78
        );
79
    }
80
81
    /**
82
     * Returns <b>true</b> when the underlying method is declared as abstract or
83
     * is declared as child of an interface.
84
     *
85
     * @return boolean
86
     */
87 2
    public function isAbstract()
88
    {
89 2
        return $this->getNode()->isAbstract();
0 ignored issues
show
It seems like you code against a concrete implementation and not the interface PDepend\Source\AST\ASTArtifact as the method isAbstract() does only exist in the following implementations of said interface: PDepend\Source\AST\ASTAnonymousClass, PDepend\Source\AST\ASTClass, PDepend\Source\AST\ASTInterface, PDepend\Source\AST\ASTMethod, PDepend\Source\AST\ASTTrait, PDepend\Source\AST\AbstractASTClassOrInterface.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
90
    }
91
92
    /**
93
     * Checks if this node has a suppressed annotation for the given rule
94
     * instance.
95
     *
96
     * @param \PHPMD\Rule $rule
97
     * @return boolean
98
     */
99 11
    public function hasSuppressWarningsAnnotationFor(Rule $rule)
100
    {
101 11
        if (parent::hasSuppressWarningsAnnotationFor($rule)) {
102 3
            return true;
103
        }
104 8
105
        return $this->getParentType()->hasSuppressWarningsAnnotationFor($rule);
106
    }
107
108
    /**
109
     * Returns the parent class or interface instance.
110
     *
111
     * @return \PHPMD\Node\AbstractTypeNode
112 11
     */
113
    public function getParentType()
114 11
    {
115
        $parentNode = $this->getNode()->getParent();
0 ignored issues
show
It seems like you code against a concrete implementation and not the interface PDepend\Source\AST\ASTArtifact as the method getParent() does only exist in the following implementations of said interface: PDepend\Source\AST\ASTAnonymousClass, PDepend\Source\AST\ASTMethod.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
116 11
117 1
        if ($parentNode instanceof ASTTrait) {
118
            return new TraitNode($parentNode);
119
        }
120 10
121 8
        if ($parentNode instanceof ASTClass) {
122
            return new ClassNode($parentNode);
123
        }
124 2
125
        return new InterfaceNode($parentNode);
126
    }
127
128
    /**
129
     * Returns <b>true</b> when this method is the initial method declaration.
130
     * Otherwise this method will return <b>false</b>.
131
     *
132
     * @return boolean
133
     * @since 1.2.1
134 8
     */
135
    public function isDeclaration()
136 8
    {
137 1
        if ($this->isPrivate()) {
138
            return true;
139
        }
140 7
141
        $methodName = strtolower($this->getName());
142 7
143 7
        $parentNode = $this->getNode()->getParent();
0 ignored issues
show
It seems like you code against a concrete implementation and not the interface PDepend\Source\AST\ASTArtifact as the method getParent() does only exist in the following implementations of said interface: PDepend\Source\AST\ASTAnonymousClass, PDepend\Source\AST\ASTMethod.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
144 1
        foreach ($parentNode->getInterfaces() as $parentType) {
145 1
            $methods = $parentType->getAllMethods();
146 1
            if (isset($methods[$methodName])) {
147
                return false;
148
            }
149
        }
150 6
151 3
        $parentType = $parentNode->getParentClass();
152 3
        if (is_object($parentType)) {
153 2
            $methods = $parentType->getAllMethods();
154
            if (isset($methods[$methodName])) {
155
                return false;
156
            }
157 4
        }
158
159
        return true;
160
    }
161
}
162