Completed
Push — develop ( 722f70...af048b )
by Jaap
15:12 queued 05:04
created

MethodDescriptor   B

Complexity

Total Complexity 41

Size/Duplication

Total Lines 271
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 5

Importance

Changes 1
Bugs 0 Features 0
Metric Value
dl 0
loc 271
rs 8.2769
c 1
b 0
f 0
wmc 41
lcom 2
cbo 5

19 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
A setParent() 0 11 1
A getParent() 0 4 1
A setAbstract() 0 4 1
A isAbstract() 0 4 1
A setFinal() 0 4 1
A isFinal() 0 4 1
A setStatic() 0 4 1
A isStatic() 0 4 1
A setVisibility() 0 4 1
A getVisibility() 0 4 1
A setArguments() 0 7 2
A addArgument() 0 5 1
A getArguments() 0 4 1
A getResponse() 0 9 3
A getFile() 0 4 1
A getReturn() 0 15 3
A getParam() 0 15 4
C getInheritedElement() 0 48 15

How to fix   Complexity   

Complex Class

Complex classes like MethodDescriptor often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use MethodDescriptor, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * phpDocumentor
4
 *
5
 * PHP Version 5.3
6
 *
7
 * @copyright 2010-2014 Mike van Riel / Naenius (http://www.naenius.com)
8
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
9
 * @link      http://phpdoc.org
10
 */
11
12
namespace phpDocumentor\Descriptor;
13
14
/**
15
 * Descriptor representing a Method in a Class, Interface or Trait.
16
 */
17
class MethodDescriptor extends DescriptorAbstract implements Interfaces\MethodInterface, Interfaces\VisibilityInterface
18
{
19
    /** @var ClassDescriptor|InterfaceDescriptor|TraitDescriptor $parent */
20
    protected $parent;
21
22
    /** @var bool $abstract */
23
    protected $abstract = false;
24
25
    /** @var bool $final */
26
    protected $final = false;
27
28
    /** @var bool $static */
29
    protected $static = false;
30
31
    /** @var string $visibility */
32
    protected $visibility = 'public';
33
34
    /** @var Collection */
35
    protected $arguments;
36
37
    /**
38
     * Initializes the all properties representing a collection with a new Collection object.
39
     */
40
    public function __construct()
41
    {
42
        parent::__construct();
43
44
        $this->setArguments(new Collection());
45
    }
46
47
    /**
48
     * @param ClassDescriptor|InterfaceDescriptor|TraitDescriptor $parent
49
     */
50
    public function setParent($parent)
51
    {
52
        $this->setFullyQualifiedStructuralElementName(
53
            $parent->getFullyQualifiedStructuralElementName() . '::' . $this->getName() . '()'
54
        );
55
56
        // reset cached inherited element so that it can be re-detected.
57
        $this->inheritedElement = null;
58
59
        $this->parent = $parent;
60
    }
61
62
    /**
63
     * @return ClassDescriptor|InterfaceDescriptor|TraitDescriptor
64
     */
65
    public function getParent()
66
    {
67
        return $this->parent;
68
    }
69
70
    /**
71
     * {@inheritDoc}
72
     */
73
    public function setAbstract($abstract)
74
    {
75
        $this->abstract = $abstract;
76
    }
77
78
    /**
79
     * {@inheritDoc}
80
     */
81
    public function isAbstract()
82
    {
83
        return $this->abstract;
84
    }
85
86
    /**
87
     * {@inheritDoc}
88
     */
89
    public function setFinal($final)
90
    {
91
        $this->final = $final;
92
    }
93
94
    /**
95
     * {@inheritDoc}
96
     */
97
    public function isFinal()
98
    {
99
        return $this->final;
100
    }
101
102
    /**
103
     * {@inheritDoc}
104
     */
105
    public function setStatic($static)
106
    {
107
        $this->static = $static;
108
    }
109
110
    /**
111
     * {@inheritDoc}
112
     */
113
    public function isStatic()
114
    {
115
        return $this->static;
116
    }
117
118
    /**
119
     * {@inheritDoc}
120
     */
121
    public function setVisibility($visibility)
122
    {
123
        $this->visibility = $visibility;
124
    }
125
126
    /**
127
     * {@inheritDoc}
128
     */
129
    public function getVisibility()
130
    {
131
        return $this->visibility;
132
    }
133
134
    /**
135
     * {@inheritDoc}
136
     */
137
    public function setArguments(Collection $arguments)
138
    {
139
        foreach( $arguments as $argument) {
0 ignored issues
show
Coding Style introduced by
Space found after opening bracket of FOREACH loop
Loading history...
Coding Style introduced by
Expected 1 space after FOREACH keyword; 0 found
Loading history...
140
            $argument->setMethod($this);
141
        }
142
        $this->arguments = $arguments;
143
    }
144
145
    /**
146
     * @param string $name
147
     * @param ArgumentDescriptor $argument
148
     */
149
    public function addArgument($name, ArgumentDescriptor $argument)
150
    {
151
        $argument->setMethod($this);
152
        $this->arguments->set($name, $argument);
153
    }
154
155
    /**
156
     * {@inheritDoc}
157
     */
158
    public function getArguments()
159
    {
160
        return $this->arguments;
161
    }
162
163
    /**
164
     * {@inheritDoc}
165
     */
166
    public function getResponse()
167
    {
168
        /** @var Collection|null $returnTags */
169
        $returnTags = $this->getReturn();
170
171
        return $returnTags instanceof Collection && $returnTags->count() > 0
172
            ? current($returnTags->getAll())
173
            : null;
174
    }
175
176
    /**
177
     * Returns the file associated with the parent class, interface or trait.
178
     *
179
     * @return FileDescriptor
180
     */
181
    public function getFile()
182
    {
183
        return $this->getParent()->getFile();
184
    }
185
186
    /**
187
     * @return Collection
188
     */
189
    public function getReturn()
190
    {
191
        /** @var Collection $var */
192
        $var = $this->getTags()->get('return', new Collection());
193
        if ($var->count() != 0) {
194
            return $var;
195
        }
196
197
        $inheritedElement = $this->getInheritedElement();
198
        if ($inheritedElement) {
199
            return $inheritedElement->getReturn();
200
        }
201
202
        return new Collection();
203
    }
204
205
    /**
206
     * @return Collection
207
     */
208
    public function getParam()
209
    {
210
        /** @var Collection $var */
211
        $var = $this->getTags()->get('param', new Collection());
212
        if ($var instanceof Collection && $var->count() > 0) {
213
            return $var;
214
        }
215
216
        $inheritedElement = $this->getInheritedElement();
217
        if ($inheritedElement) {
218
            return $inheritedElement->getParam();
219
        }
220
221
        return new Collection();
222
    }
223
224
    /**
225
     * Returns the Method from which this method should inherit its information, if any.
226
     *
227
     * The inheritance scheme for a method is more complicated than for most elements; the following business rules
228
     * apply:
229
     *
230
     * 1. if the parent class/interface extends another class or other interfaces (interfaces have multiple
231
     *    inheritance!) then:
232
     *    1. Check each parent class/interface's parent if they have a method with the exact same name
233
     *    2. if a method is found with the same name; return the first one encountered.
234
     * 2. if the parent is a class and implements interfaces, check each interface for a method with the exact same
235
     *    name. If such a method is found, return the first hit.
236
     *
237
     * @return MethodDescriptor|null
238
     */
239
    public function getInheritedElement()
0 ignored issues
show
Complexity introduced by
This operation has 972 execution paths which exceeds the configured maximum of 200.

A high number of execution paths generally suggests many nested conditional statements and make the code less readible. This can usually be fixed by splitting the method into several smaller methods.

You can also find more information in the “Code” section of your repository.

Loading history...
240
    {
241
        if ($this->inheritedElement !== null) {
242
            return $this->inheritedElement;
243
        }
244
245
        /** @var ClassDescriptor|InterfaceDescriptor|null $associatedClass */
246
        $associatedClass = $this->getParent();
247
        if (!$associatedClass instanceof ClassDescriptor && !$associatedClass instanceof InterfaceDescriptor) {
248
            return null;
249
        }
250
251
        /** @var ClassDescriptor|InterfaceDescriptor $parentClass|null */
252
        $parentClass = $associatedClass->getParent();
253
        if ($parentClass instanceof ClassDescriptor || $parentClass instanceof Collection) {
254
            // the parent of a class is always a class, but the parent of an interface is a collection of interfaces.
255
            $parents = $parentClass instanceof ClassDescriptor ? array($parentClass) : $parentClass->getAll();
256
            foreach ($parents as $parent) {
257
                if ($parent instanceof ClassDescriptor || $parent instanceof InterfaceDescriptor) {
258
                    $parentMethod = $parent->getMethods()->get($this->getName());
259
                    if ($parentMethod) {
260
                        $this->inheritedElement = $parentMethod;
261
262
                        return $this->inheritedElement;
263
                    }
264
                }
265
            }
266
        }
267
268
        // also check all implemented interfaces next if the parent is a class and not an interface
269
        if ($associatedClass instanceof ClassDescriptor) {
270
            /** @var InterfaceDescriptor $interface */
271
            foreach ($associatedClass->getInterfaces() as $interface) {
272
                if (!$interface instanceof InterfaceDescriptor) {
273
                    continue;
274
                }
275
276
                $parentMethod = $interface->getMethods()->get($this->getName());
277
                if ($parentMethod) {
278
                    $this->inheritedElement = $parentMethod;
279
280
                    return $this->inheritedElement;
281
                }
282
            }
283
        }
284
285
        return null;
286
    }
287
}
288