AbstractUnitObject   F
last analyzed

Complexity

Total Complexity 97

Size/Duplication

Total Lines 559
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 6
Bugs 0 Features 0
Metric Value
wmc 97
eloc 233
c 6
b 0
f 0
dl 0
loc 559
ccs 0
cts 374
cp 0
rs 2

42 Methods

Rating   Name   Duplication   Size   Complexity  
A getMethod() 0 13 2
A usesTrait() 0 2 1
A hasImplements() 0 2 1
A hasMethod() 0 4 1
A addConstant() 0 5 1
A setFinal() 0 2 2
A addExtender() 0 6 2
A setAbstract() 0 2 2
A addMember() 0 5 1
A markDependencyAsUnresolved() 0 12 2
A getUsedTraits() 0 11 3
A export() 0 2 1
A getCompactDescription() 0 8 3
A getTraitUse() 0 13 2
A setName() 0 7 1
A addToContainer() 0 8 2
A getRootNode() 0 2 1
A hasExtends() 0 2 1
A addMethod() 0 21 3
A getSourceFilename() 0 8 2
A getType() 0 2 1
A addExtends() 0 3 1
A getAmbiguousTraitUse() 0 9 2
A getNamespace() 0 2 1
A __construct() 0 18 4
A getExtends() 0 11 3
A getLocalName() 0 2 1
A setEndLine() 0 2 1
A setDocBlock() 0 3 1
A addTrait() 0 5 1
C importExports() 0 53 13
A adjustStaticResolution() 0 14 5
A addImplements() 0 3 1
A getConstants() 0 9 2
A import() 0 4 1
F importTraitExports() 0 80 15
A usesTraits() 0 2 1
A getExportedMembers() 0 9 2
A getImplements() 0 11 3
A getExportedMethods() 0 9 2
A getName() 0 2 1
A setStartLine() 0 2 1

How to fix   Complexity   

Complex Class

Complex classes like AbstractUnitObject 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.

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 AbstractUnitObject, and based on these observations, apply Extract Interface, too.

1
<?php declare(strict_types = 1);
2
namespace TheSeer\phpDox\Collector;
3
4
use TheSeer\fDOM\fDOMDocument;
5
use TheSeer\fDOM\fDOMElement;
6
use TheSeer\phpDox\DocBlock\DocBlock;
7
use TheSeer\phpDox\FileInfo;
8
9
abstract class AbstractUnitObject {
10
    /**
11
     * PHPDOX Namespace
12
     */
13
    public const XMLNS = 'http://xml.phpdox.net/src';
14
15
    /**
16
     * @var string
17
     */
18
    protected $rootName;
19
20
    /**
21
     * @var fDOMDocument
22
     */
23
    private $dom;
24
25
    /**
26
     * @var fDOMElement
27
     */
28
    private $rootNode;
29
30
    /**
31
     * @param string       $name
32
     * @param \SplFileInfo $file
33
     */
34
    public function __construct($name = null, SourceFile $file = null) {
35
        if ($this->rootName === null) {
36
            throw new UnitObjectException('No or invalid rootname set', UnitObjectException::InvalidRootname);
37
        }
38
        $this->dom = new fDOMDocument('1.0', 'UTF-8');
39
        $this->dom->registerNamespace('phpdox', self::XMLNS);
40
        $this->rootNode = $this->dom->createElementNS(self::XMLNS, $this->rootName);
41
        $this->dom->appendChild($this->rootNode);
42
43
        if ($name !== null) {
44
            $this->setName($name, $this->rootNode);
45
        }
46
47
        if ($file !== null) {
48
            $this->rootNode->appendChild($file->asNode($this->rootNode));
49
        }
50
        $this->setAbstract(false);
51
        $this->setFinal(false);
52
    }
53
54
    public function export(): fDOMDocument {
55
        return $this->dom;
56
    }
57
58
    public function import(fDOMDocument $dom): void {
59
        $this->dom      = $dom;
60
        $this->rootNode = $dom->documentElement;
0 ignored issues
show
Documentation Bug introduced by Arne Blankerts
$dom->documentElement is of type DOMElement, but the property $rootNode was declared to be of type TheSeer\fDOM\fDOMElement. Are you sure that you always receive this specific sub-class here, or does it make sense to add an instanceof check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a given class or a super-class is assigned to a property that is type hinted more strictly.

Either this assignment is in error or an instanceof check should be added for that assignment.

class Alien {}

class Dalek extends Alien {}

class Plot
{
    /** @var  Dalek */
    public $villain;
}

$alien = new Alien();
$plot = new Plot();
if ($alien instanceof Dalek) {
    $plot->villain = $alien;
}
Loading history...
61
        $this->dom->registerNamespace('phpdox', self::XMLNS);
62
    }
63
64
    public function getType() {
65
        return $this->rootNode->localName;
66
    }
67
68
    public function getLocalName(): string {
69
        return $this->rootNode->getAttribute('name');
70
    }
71
72
    public function getName(): string {
73
        return $this->rootNode->getAttribute('full');
74
    }
75
76
    public function getNamespace(): string {
77
        return $this->rootNode->getAttribute('namespace');
78
    }
79
80
    public function getSourceFilename(): ?FileInfo {
81
        $file = $this->rootNode->queryOne('phpdox:file');
82
83
        if (!$file) {
0 ignored issues
show
introduced by Arne Blankerts
$file is of type TheSeer\fDOM\fDOMNode, thus it always evaluated to true.
Loading history...
84
            return null;
85
        }
86
87
        return new FileInfo($file->getAttribute('path') . '/' . $file->getAttribute('file'));
0 ignored issues
show
Bug introduced by Arne Blankerts
The method getAttribute() does not exist on TheSeer\fDOM\fDOMNode. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

87
        return new FileInfo($file->/** @scrutinizer ignore-call */ getAttribute('path') . '/' . $file->getAttribute('file'));

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
88
    }
89
90
    public function getCompactDescription(): string {
91
        $desc = $this->rootNode->queryOne('phpdox:docblock/phpdox:description');
92
93
        if (!$desc || !$desc->hasAttribute('compact')) {
0 ignored issues
show
Bug introduced by Arne Blankerts
The method hasAttribute() does not exist on TheSeer\fDOM\fDOMNode. Did you maybe mean hasAttributes()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

93
        if (!$desc || !$desc->/** @scrutinizer ignore-call */ hasAttribute('compact')) {

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
introduced by Arne Blankerts
$desc is of type TheSeer\fDOM\fDOMNode, thus it always evaluated to true.
Loading history...
94
            return '';
95
        }
96
97
        return $desc->getAttribute('compact');
98
    }
99
100
    /**
101
     * @param int $endLine
102
     */
103
    public function setEndLine($endLine): void {
104
        $this->rootNode->setAttribute('end', $endLine);
105
    }
106
107
    /**
108
     * @param int $startLine
109
     */
110
    public function setStartLine($startLine): void {
111
        $this->rootNode->setAttribute('start', $startLine);
112
    }
113
114
    /**
115
     * @param bool $isAbstract
116
     */
117
    public function setAbstract($isAbstract): void {
118
        $this->rootNode->setAttribute('abstract', $isAbstract ? 'true' : 'false');
119
    }
120
121
    /**
122
     * @param bool $isFinal
123
     */
124
    public function setFinal($isFinal): void {
125
        $this->rootNode->setAttribute('final', $isFinal ? 'true' : 'false');
126
    }
127
128
    public function setDocBlock(DocBlock $docblock): void {
129
        $docNode = $docblock->asDom($this->dom);
130
        $this->rootNode->appendChild($docNode);
131
    }
132
133
    /**
134
     * @param $name
135
     */
136
    public function addExtends($name): void {
137
        $extends = $this->rootNode->appendElementNS(self::XMLNS, 'extends');
138
        $this->setName($name, $extends);
139
    }
140
141
    public function hasExtends(): bool {
142
        return $this->rootNode->queryOne('phpdox:extends') !== null;
143
    }
144
145
    /**
146
     * @throws UnitObjectException
147
     */
148
    public function getExtends() {
149
        if (!$this->hasExtends()) {
150
            throw new UnitObjectException('This unit does not extend any unit', UnitObjectException::NoExtends);
151
        }
152
        $result = [];
153
154
        foreach ($this->rootNode->query('phpdox:extends') as $ext) {
155
            $result[] = $ext->getAttribute('full');
156
        }
157
158
        return $result;
159
    }
160
161
    public function addExtender(self $unit): void {
162
        if ($this->rootNode->queryOne(\sprintf('phpdox:extenders/phpdox:*[@full = "%s"]', $unit->getName())) !== null) {
163
            return;
164
        }
165
        $extender = $this->addToContainer('extenders', 'extender');
166
        $this->setName($unit->getName(), $extender);
167
    }
168
169
    /**
170
     * @param $name
171
     */
172
    public function addImplements($name): void {
173
        $implements = $this->rootNode->appendElementNS(self::XMLNS, 'implements');
174
        $this->setName($name, $implements);
175
    }
176
177
    public function hasImplements(): bool {
178
        return $this->rootNode->query('phpdox:implements')->length > 0;
179
    }
180
181
    /**
182
     * @throws UnitObjectException
183
     */
184
    public function getImplements(): array {
185
        if (!$this->hasImplements()) {
186
            throw new UnitObjectException('This unit does not implement any interfaces', UnitObjectException::NoImplements);
187
        }
188
        $result = [];
189
190
        foreach ($this->rootNode->query('phpdox:implements') as $impl) {
191
            $result[] = $impl->getAttribute('full');
192
        }
193
194
        return $result;
195
    }
196
197
    public function usesTraits(): bool {
198
        return $this->rootNode->query('phpdox:uses')->length > 0;
199
    }
200
201
    /**
202
     * @param $name
203
     */
204
    public function usesTrait($name): bool {
205
        return $this->rootNode->query(\sprintf('phpdox:uses[@full="%s"]', $name))->length > 0;
206
    }
207
208
    /**
209
     * @param string $name
210
     */
211
    public function addTrait($name): TraitUseObject {
212
        $traituse = new TraitUseObject($this->rootNode->appendElementNS(self::XMLNS, 'uses'));
213
        $traituse->setName($name);
214
215
        return $traituse;
216
    }
217
218
    /**
219
     * @throws UnitObjectException
220
     */
221
    public function getUsedTraits(): array {
222
        if (!$this->usesTraits()) {
223
            throw new UnitObjectException('This unit does not use any traits', UnitObjectException::NoTraitsUsed);
224
        }
225
        $result = [];
226
227
        foreach ($this->rootNode->query('phpdox:uses') as $trait) {
228
            $result[] = $trait->getAttribute('full');
229
        }
230
231
        return $result;
232
    }
233
234
    /**
235
     * @param $name
236
     *
237
     * @throws UnitObjectException
238
     */
239
    public function getTraitUse($name): TraitUseObject {
240
        $node = $this->rootNode->queryOne(
241
            \sprintf('phpdox:uses[@full="%s"]', $name)
242
        );
243
244
        if (!$node) {
0 ignored issues
show
introduced by Arne Blankerts
$node is of type TheSeer\fDOM\fDOMNode, thus it always evaluated to true.
Loading history...
245
            throw new UnitObjectException(
246
                \sprintf('Trait "%s" not used', $name),
247
                UnitObjectException::NoSuchTrait
248
            );
249
        }
250
251
        return new TraitUseObject($node);
0 ignored issues
show
Bug introduced by Arne Blankerts
$node of type TheSeer\fDOM\fDOMNode is incompatible with the type TheSeer\fDOM\fDOMElement expected by parameter $ctx of TheSeer\phpDox\Collector...seObject::__construct(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

251
        return new TraitUseObject(/** @scrutinizer ignore-type */ $node);
Loading history...
252
    }
253
254
    public function getAmbiguousTraitUse() {
255
        $node = $this->rootNode->queryOne('phpdox:ambiguous[@type="trait-alias"]');
256
257
        if (!$node) {
0 ignored issues
show
introduced by Arne Blankerts
$node is of type TheSeer\fDOM\fDOMNode, thus it always evaluated to true.
Loading history...
258
            $node = $this->rootNode->appendElementNS(self::XMLNS, 'ambiguous');
259
            $node->setAttribute('type', 'trait-alias');
260
        }
261
262
        return new TraitUseObject($node);
0 ignored issues
show
Bug introduced by Arne Blankerts
$node of type TheSeer\fDOM\fDOMNode is incompatible with the type TheSeer\fDOM\fDOMElement expected by parameter $ctx of TheSeer\phpDox\Collector...seObject::__construct(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

262
        return new TraitUseObject(/** @scrutinizer ignore-type */ $node);
Loading history...
263
    }
264
265
    /**
266
     * @param string $dependency
267
     */
268
    public function markDependencyAsUnresolved($dependency): void {
269
        $depNode = $this->rootNode->queryOne(
270
            \sprintf('//phpdox:implements[@full="%1$s"]|//phpdox:extends[@full="%1$s"]|//phpdox:uses[@full="%1$s"]', $dependency)
271
        );
272
273
        if (!$depNode) {
0 ignored issues
show
introduced by Arne Blankerts
$depNode is of type TheSeer\fDOM\fDOMNode, thus it always evaluated to true.
Loading history...
274
            throw new UnitObjectException(
275
                \sprintf('No dependency "%s" found in unit %s', $dependency, $this->getName()),
276
                UnitObjectException::NoSuchDependency
277
            );
278
        }
279
        $depNode->setAttribute('unresolved', 'true');
0 ignored issues
show
Bug introduced by Arne Blankerts
The method setAttribute() does not exist on TheSeer\fDOM\fDOMNode. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

279
        $depNode->/** @scrutinizer ignore-call */ 
280
                  setAttribute('unresolved', 'true');

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
280
    }
281
282
    public function addMethod($name) {
283
        switch ($name) {
284
            case '__construct':
285
                {
286
                    $nodeName = 'constructor';
287
288
                    break;
289
                }
290
            case '__destruct':
291
                {
292
                    $nodeName = 'destructor';
293
294
                    break;
295
                }
296
            default:
297
                $nodeName = 'method';
298
        }
299
        $method = new MethodObject($this, $this->rootNode->appendElementNS(self::XMLNS, $nodeName));
300
        $method->setName($name);
301
302
        return $method;
303
    }
304
305
    /**
306
     * @return MethodObject[]
307
     */
308
    public function getExportedMethods(): array {
309
        $result = [];
310
        $xpath  = '(phpdox:constructor|phpdox:destructor|phpdox:method)[@visibility="public" or @visibility="protected"]';
311
312
        foreach ($this->rootNode->query($xpath) as $node) {
313
            $result[] = new MethodObject($this, $node);
314
        }
315
316
        return $result;
317
    }
318
319
    /**
320
     * @param $name
321
     */
322
    public function addMember($name): MemberObject {
323
        $member = new MemberObject($this->rootNode->appendElementNS(self::XMLNS, 'member'));
324
        $member->setName($name);
325
326
        return $member;
327
    }
328
329
    public function getExportedMembers(): array {
330
        $result = [];
331
        $xpath  = 'phpdox:member[@visibility="public" or @visibility="protected"]';
332
333
        foreach ($this->rootNode->query($xpath) as $node) {
334
            $result[] = new MemberObject($node);
335
        }
336
337
        return $result;
338
    }
339
340
    /**
341
     * @param $name
342
     */
343
    public function addConstant($name): ConstantObject {
344
        $const = new ConstantObject($this->rootNode->appendElementNS(self::XMLNS, 'constant'));
345
        $const->setName($name);
346
347
        return $const;
348
    }
349
350
    public function getConstants(): array {
351
        $result = [];
352
        $xpath  = 'phpdox:constant';
353
354
        foreach ($this->rootNode->query($xpath) as $node) {
355
            $result[] = new ConstantObject($node);
356
        }
357
358
        return $result;
359
    }
360
361
    public function importExports(self $unit, $container = 'parent'): void {
362
        $parent = $this->rootNode->queryOne(\sprintf('//phpdox:%s[@full="%s"]', $container, $unit->getName()));
363
364
        if ($parent instanceof fDOMElement) {
0 ignored issues
show
introduced by Arne Blankerts
$parent is never a sub-type of TheSeer\fDOM\fDOMElement.
Loading history...
365
            $parent->parentNode->removeChild($parent);
366
        }
367
368
        $parent = $this->rootNode->appendElementNS(self::XMLNS, $container);
369
        $parent->setAttribute('full', $unit->getName());
370
        $parent->setAttribute('namespace', $unit->getNamespace());
371
        $parent->setAttribute('name', $unit->getLocalName());
372
373
        if ($unit->hasExtends()) {
374
            foreach ($unit->getExtends() as $name) {
375
                $extends = $parent->appendElementNS(self::XMLNS, 'extends');
376
                $this->setName($name, $extends);
377
            }
378
        }
379
380
        if ($unit->hasImplements()) {
381
            foreach ($unit->getImplements() as $name) {
382
                $implements = $parent->appendElementNS(self::XMLNS, 'implements');
383
                $this->setName($name, $implements);
384
            }
385
        }
386
387
        if ($unit->usesTraits()) {
388
            foreach ($unit->getUsedTraits() as $name) {
389
                $uses = $parent->appendElementNS(self::XMLNS, 'uses');
390
                $this->setName($name, $uses);
391
            }
392
        }
393
394
        foreach ($unit->getConstants() as $constant) {
395
            $parent->appendChild($this->dom->importNode($constant->export(), true));
396
        }
397
398
        foreach ($unit->getExportedMembers() as $member) {
399
            $memberNode = $this->dom->importNode($member->export(), true);
400
            $this->adjustStaticResolution($memberNode);
401
            $parent->appendChild($memberNode);
402
        }
403
404
        foreach ($unit->getExportedMethods() as $method) {
405
            $methodNode = $this->dom->importNode($method->export(), true);
406
            $this->adjustStaticResolution($methodNode);
407
            $parent->appendChild($methodNode);
408
409
            if ($this->hasMethod($method->getName())) {
410
                $unitMethod = $this->getMethod($method->getName());
411
412
                if ($unitMethod->hasInheritDoc()) {
413
                    $unitMethod->inhertDocBlock($method);
414
                }
415
            }
416
        }
417
    }
418
419
    public function importTraitExports(self $trait, TraitUseObject $use): void {
420
        $container = $this->rootNode->queryOne(
421
            \sprintf(
422
                'phpdox:trait[@full="%s"]',
423
                $trait->getName()
424
            )
425
        );
426
427
        if ($container instanceof fDOMElement) {
0 ignored issues
show
introduced by Arne Blankerts
$container is never a sub-type of TheSeer\fDOM\fDOMElement.
Loading history...
428
            $container->parentNode->removeChild($container);
429
        }
430
431
        $container = $this->rootNode->appendElementNS(self::XMLNS, 'trait');
432
        $this->setName($trait->getName(), $container);
433
434
        if ($trait->hasExtends()) {
435
            foreach ($trait->getExtends() as $name) {
436
                $extends = $container->appendElementNS(self::XMLNS, 'extends');
437
                $this->setName($name, $extends);
438
            }
439
        }
440
441
        if ($trait->usesTraits()) {
442
            foreach ($trait->getUsedTraits() as $name) {
443
                $used = $container->appendElementNS(self::XMLNS, 'uses');
444
                $this->setName($name, $used);
445
            }
446
        }
447
448
        foreach ($trait->getConstants() as $constant) {
449
            $container->appendChild($this->dom->importNode($constant->export(), true));
450
        }
451
452
        foreach ($trait->getExportedMembers() as $member) {
453
            $memberNode = $this->dom->importNode($member->export(), true);
454
            $this->adjustStaticResolution($memberNode);
455
            $container->appendChild($memberNode);
456
        }
457
458
        $ambiguousContainer = $this->dom->queryOne('//phpdox:ambiguous[@type="trait-alias"]');
459
460
        foreach ($trait->getExportedMethods() as $method) {
461
            $methodName = $method->getName();
462
            $methodNode = $this->dom->importNode($method->export(), true);
463
464
            if (!$use->isExcluded($methodName)) {
465
                $container->appendChild($methodNode);
466
            }
467
468
            $this->adjustStaticResolution($methodNode);
469
470
            if ($ambiguousContainer !== null) {
471
                $ambiguousMethod = $ambiguousContainer->queryOne(
472
                    \sprintf('phpdox:alias[@method="%s"]', $methodName)
473
                );
474
475
                if ($ambiguousMethod !== null) {
476
                    $usesNode = $this->dom->queryOne(
477
                        \sprintf('//phpdox:uses[@full="%s"]', $trait->getName())
478
                    );
479
                    $usesNode->appendChild($ambiguousMethod);
480
481
                    if ($ambiguousContainer->query('phpdox:alias')->length === 0) {
482
                        $ambiguousContainer->parentNode->removeChild($ambiguousContainer);
483
                        $ambiguousContainer = null;
484
                    }
485
                }
486
            }
487
488
            $aliasNode = null;
489
490
            if ($use->isAliased($methodName)) {
491
                $aliasNode = $methodNode->cloneNode(true);
492
                $aliasNode->setAttribute('original', $aliasNode->getAttribute('name'));
493
                $aliasNode->setAttribute('name', $use->getAliasedName($methodName));
494
495
                if ($use->hasAliasedModifier($methodName)) {
496
                    $aliasNode->setAttribute('visibility', $use->getAliasedModifier($methodName));
497
                }
498
                $container->appendChild($aliasNode);
499
            }
500
        }
501
    }
502
503
    /**
504
     * @param $name
505
     */
506
    protected function setName($name, fDOMElement $ctx): void {
507
        $parts     = \explode('\\', $name);
508
        $local     = \array_pop($parts);
509
        $namespace = \implode('\\', $parts);
510
        $ctx->setAttribute('full', $name);
511
        $ctx->setAttribute('namespace', $namespace);
512
        $ctx->setAttribute('name', $local);
513
    }
514
515
    protected function getRootNode() {
516
        return $this->rootNode;
517
    }
518
519
    /**
520
     * @param $containerName
521
     * @param $elementName
522
     */
523
    protected function addToContainer($containerName, $elementName): fDOMElement {
524
        $container = $this->rootNode->queryOne('phpdox:' . $containerName);
525
526
        if (!$container) {
0 ignored issues
show
introduced by Arne Blankerts
$container is of type TheSeer\fDOM\fDOMNode, thus it always evaluated to true.
Loading history...
527
            $container = $this->rootNode->appendElementNS(self::XMLNS, $containerName);
528
        }
529
530
        return $container->appendElementNS(self::XMLNS, $elementName);
0 ignored issues
show
Bug introduced by Arne Blankerts
The method appendElementNS() does not exist on TheSeer\fDOM\fDOMNode. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

530
        return $container->/** @scrutinizer ignore-call */ appendElementNS(self::XMLNS, $elementName);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
531
    }
532
533
    private function hasMethod($name) {
534
        return $this->dom->query(
535
                \sprintf('phpdox:method[@name="%s"]', $name)
536
            )->length > 0;
537
    }
538
539
    private function getMethod($name) {
540
        $ctx = $this->dom->queryOne(
541
            \sprintf('phpdox:method[@name="%s"]', $name)
542
        );
543
544
        if (!$ctx) {
0 ignored issues
show
introduced by Arne Blankerts
$ctx is of type TheSeer\fDOM\fDOMNode, thus it always evaluated to true.
Loading history...
545
            throw new UnitObjectException(
546
                \sprintf('Method "%s" not found', $name),
547
                UnitObjectException::NoSuchMethod
548
            );
549
        }
550
551
        return new MethodObject($this, $ctx);
0 ignored issues
show
Bug introduced by Arne Blankerts
$ctx of type TheSeer\fDOM\fDOMNode is incompatible with the type TheSeer\fDOM\fDOMElement expected by parameter $ctx of TheSeer\phpDox\Collector...odObject::__construct(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

551
        return new MethodObject($this, /** @scrutinizer ignore-type */ $ctx);
Loading history...
552
    }
553
554
    private function adjustStaticResolution(fDOMElement $ctx): void {
555
        $container = $ctx->queryOne('.//phpdox:docblock/phpdox:return|.//phpdox:docblock/phpdox:var');
556
557
        if (!$container || $container->getAttribute('resolution') !== 'static') {
0 ignored issues
show
introduced by Arne Blankerts
$container is of type TheSeer\fDOM\fDOMNode, thus it always evaluated to true.
Loading history...
558
            return;
559
        }
560
        $type = $container->queryOne('phpdox:type');
561
562
        if (!$type) {
0 ignored issues
show
introduced by Arne Blankerts
$type is of type TheSeer\fDOM\fDOMNode, thus it always evaluated to true.
Loading history...
563
            return;
564
        }
565
566
        foreach (['full', 'namespace', 'name'] as $attribute) {
567
            $type->setAttribute($attribute, $this->rootNode->getAttribute($attribute));
568
        }
569
    }
570
}
571