Passed
Push — master ( 157651...e7eb4b )
by Théo
03:29
created

NamespaceStmtPrefixer::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 3
dl 0
loc 6
ccs 4
cts 4
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the humbug/php-scoper package.
7
 *
8
 * Copyright (c) 2017 Théo FIDRY <[email protected]>,
9
 *                    Pádraic Brady <[email protected]>
10
 *
11
 * For the full copyright and license information, please view the LICENSE
12
 * file that was distributed with this source code.
13
 */
14
15
namespace Humbug\PhpScoper\PhpParser\NodeVisitor;
16
17
use Humbug\PhpScoper\PhpParser\NodeVisitor\Collection\NamespaceStmtCollection;
18
use Humbug\PhpScoper\Whitelist;
19
use PhpParser\Node;
20
use PhpParser\Node\Name;
21
use PhpParser\Node\Stmt\ClassLike;
22
use PhpParser\Node\Stmt\Namespace_;
23
use PhpParser\NodeVisitorAbstract;
24
use function Humbug\PhpScoper\clone_node;
25
26
/**
27
 * Prefixes the relevant namespaces.
28
 *
29
 * ```
30
 * namespace Foo;
31
 * ```
32
 *
33
 * =>
34
 *
35
 * ```
36
 * namespace Humbug\Foo;
37
 * ```
38
 *
39
 * @private
40
 */
41
final class NamespaceStmtPrefixer extends NodeVisitorAbstract
42
{
43
    private $prefix;
44
    private $whitelist;
45
    private $namespaceStatements;
46
47 466
    public function __construct(string $prefix, Whitelist $whitelist, NamespaceStmtCollection $namespaceStatements)
48
    {
49 466
        $this->prefix = $prefix;
50 466
        $this->whitelist = $whitelist;
51 466
        $this->namespaceStatements = $namespaceStatements;
52
    }
53
54
    /**
55
     * @inheritdoc
56
     */
57 465
    public function enterNode(Node $node): Node
58
    {
59 465
        return ($node instanceof Namespace_)
60 463
            ? $this->prefixNamespaceStmt($node)
61 465
            : $node
62
        ;
63
    }
64
65 463
    private function prefixNamespaceStmt(Namespace_ $namespace): Node
66
    {
67 463
        $originalNamespace = $namespace;
68
69 463
        if ($this->shouldPrefixStmt($namespace)) {
70 448
            $originalNamespace = clone_node($namespace);
71
72 448
            $namespace->name = Name::concat($this->prefix, $namespace->name);
73
        }
74
75 463
        $this->namespaceStatements->add($namespace, $originalNamespace);
1 ignored issue
show
Bug introduced by
It seems like $originalNamespace defined by \Humbug\PhpScoper\clone_node($namespace) on line 70 can also be of type object<PhpParser\Node>; however, Humbug\PhpScoper\PhpPars...ceStmtCollection::add() does only seem to accept object<PhpParser\Node\Stmt\Namespace_>, 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...
76
77 463
        return $namespace;
78
    }
79
80
    private function isWhitelistedNode(Node $node): bool
0 ignored issues
show
Unused Code introduced by
This method is not used, and could be removed.
Loading history...
81
    {
82
        if ($node instanceof ClassLike) {
83
            return true;
84
        }
85
86
        // Check nodes in the global namespaces.
87
        if ($node instanceof Namespace_ && null === $node->name) {
88
            foreach ($node->stmts as $statement) {
89
                if ($this->isWhitelistedNode($statement)) {
90
                    return true;
91
                }
92
            }
93
        }
94
95
        return false;
96
    }
97
98 463
    private function shouldPrefixStmt(Namespace_ $namespace): bool
99
    {
100 463
        if ($this->whitelist->belongsToWhitelistedNamespace((string) $namespace->name)) {
101 18
            return false;
102
        }
103
104 450
        return null === $namespace->name || (null !== $namespace->name && $this->prefix !== $namespace->name->getFirst());
105
    }
106
}
107