Completed
Push — develop ( 8eb671...133594 )
by Mike
19:30 queued 09:24
created

Descriptor/Builder/Reflector/FunctionAssembler.php (3 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
declare(strict_types=1);
3
4
/**
5
 * This file is part of phpDocumentor.
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 *
10
 * @author    Mike van Riel <[email protected]>
11
 * @copyright 2010-2018 Mike van Riel / Naenius (http://www.naenius.com)
12
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
13
 * @link      http://phpdoc.org
14
 */
15
16
namespace phpDocumentor\Descriptor\Builder\Reflector;
17
18
use phpDocumentor\Descriptor\ArgumentDescriptor;
19
use phpDocumentor\Descriptor\Collection;
20
use phpDocumentor\Descriptor\FunctionDescriptor;
21
use phpDocumentor\Descriptor\TagDescriptor;
22
use phpDocumentor\Reflection\Php\Argument;
23
use phpDocumentor\Reflection\Php\Function_;
24
25
/**
26
 * Assembles a FunctionDescriptor from a FunctionReflector.
27
 */
28
class FunctionAssembler extends AssemblerAbstract
29
{
30
    /** @var ArgumentAssembler */
31
    protected $argumentAssembler;
32
33
    /**
34
     * Initializes this assembler and its dependencies.
35
     */
36 1
    public function __construct(ArgumentAssembler $argumentAssembler)
37
    {
38 1
        $this->argumentAssembler = $argumentAssembler;
39 1
    }
40
41
    /**
42
     * Creates a Descriptor from the provided data.
43
     *
44
     * @param Function_ $data
45
     *
46
     * @return FunctionDescriptor
47
     */
48 1
    public function create($data)
49
    {
50 1
        $functionDescriptor = new FunctionDescriptor();
51
52 1
        $this->mapReflectorPropertiesOntoDescriptor($data, $functionDescriptor);
53 1
        $this->assembleDocBlock($data->getDocBlock(), $functionDescriptor);
54 1
        $this->addArgumentsToFunctionDescriptor($data->getArguments(), $functionDescriptor);
55
56 1
        return $functionDescriptor;
57
    }
58
59
    /**
60
     * Maps the properties of the Function reflector onto the Descriptor.
61
     */
62 1
    protected function mapReflectorPropertiesOntoDescriptor(Function_ $reflector, FunctionDescriptor $descriptor): void
63
    {
64 1
        $packages = new Collection();
65 1
        $package = $this->extractPackageFromDocBlock($reflector->getDocBlock());
0 ignored issues
show
It seems like $reflector->getDocBlock() can be null; however, extractPackageFromDocBlock() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
66
        //TODO: this looks like a potential bug. Have to investigate this!
67 1
        if ($package) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $package of type null|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
68 1
            $tag = new TagDescriptor('package');
69 1
            $tag->setDescription($package);
70 1
            $packages->add($tag);
71
        }
72
73 1
        $descriptor->getTags()->set('package', $packages);
74
75 1
        $descriptor->setFullyQualifiedStructuralElementName($reflector->getFqsen());
76 1
        $descriptor->setName($reflector->getName());
77 1
        $descriptor->setLine($reflector->getLocation()->getLineNumber());
78 1
        $descriptor->setNamespace('\\' . trim(substr(
79 1
            (string) $reflector->getFqsen(),
80 1
            0,
81
            -strlen($reflector->getName()) - 2
82
        ), '\\'));
83
        $descriptor->setReturnType($reflector->getReturnType());
84
    }
85
86
    /**
87 1
     * Converts each argument reflector to an argument descriptor and adds it to the function descriptor.
88
     *
89 1
     * @param Argument[] $arguments
90 1
     */
91 1
    protected function addArgumentsToFunctionDescriptor(array $arguments, FunctionDescriptor $functionDescriptor): void
92 1
    {
93
        foreach ($arguments as $argument) {
94
            $this->addArgumentDescriptorToFunction(
95 1
                $functionDescriptor,
96
                $this->createArgumentDescriptor($functionDescriptor, $argument)
97
            );
98
        }
99
    }
100 1
101
    /**
102 1
     * Adds the given argument to the function.
103 1
     */
104
    protected function addArgumentDescriptorToFunction(
105
        FunctionDescriptor $functionDescriptor,
106
        ArgumentDescriptor $argumentDescriptor
107
    ): void {
108 1
        $functionDescriptor->getArguments()->set($argumentDescriptor->getName(), $argumentDescriptor);
109
    }
110 1
111
    /**
112 1
     * Creates a new ArgumentDescriptor from the given Reflector and Param.
113 1
     */
114
    protected function createArgumentDescriptor(
115
        FunctionDescriptor $functionDescriptor,
116 1
        Argument $argument
117
    ): ArgumentDescriptor {
118
        $params = $functionDescriptor->getTags()->get('param', []);
119
120
        if (!$this->argumentAssembler->getBuilder()) {
121
            $this->argumentAssembler->setBuilder($this->builder);
0 ignored issues
show
It seems like $this->builder can be null; however, setBuilder() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
122
        }
123
124
        return $this->argumentAssembler->create($argument, $params);
125
    }
126
}
127