Passed
Push — master ( 1c5a50...565b8d )
by Théo
10:21
created

UseStmtPrefixer   A

Complexity

Total Complexity 15

Size/Duplication

Total Lines 85
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 1
Bugs 1 Features 0
Metric Value
eloc 32
dl 0
loc 85
ccs 25
cts 25
cp 1
rs 10
c 1
b 1
f 0
wmc 15

5 Methods

Rating   Name   Duplication   Size   Complexity  
A findUseType() 0 10 2
A __construct() 0 5 1
A enterNode() 0 13 3
A shouldPrefixConstantUseStmt() 0 9 3
A shouldPrefixUseStmt() 0 27 6
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\UseStmt;
16
17
use Humbug\PhpScoper\PhpParser\NodeVisitor\ParentNodeAppender;
18
use Humbug\PhpScoper\Reflector;
19
use Humbug\PhpScoper\Whitelist;
20
use PhpParser\Node;
21
use PhpParser\Node\Name;
22
use PhpParser\Node\Stmt\Use_;
23
use PhpParser\Node\Stmt\UseUse;
24
use PhpParser\NodeVisitorAbstract;
25
use function count;
26
27
/**
28
 * Prefixes the use statements.
29
 *
30
 * @private
31
 */
32
final class UseStmtPrefixer extends NodeVisitorAbstract
33
{
34
    private string $prefix;
35
    private Whitelist $whitelist;
36
    private Reflector $reflector;
37 549
38
    public function __construct(string $prefix, Whitelist $whitelist, Reflector $reflector)
39 549
    {
40 549
        $this->prefix = $prefix;
41 549
        $this->reflector = $reflector;
42
        $this->whitelist = $whitelist;
43
    }
44
45
    public function enterNode(Node $node): Node
46
    {
47 548
        if ($node instanceof UseUse && $this->shouldPrefixUseStmt($node)) {
48
            $previousName = $node->name;
49 548
50 202
            /** @var Name $prefixedName */
51
            $prefixedName = Name::concat($this->prefix, $node->name, $node->name->getAttributes());
52
            $node->name = $prefixedName;
53 548
54
            UseStmtManipulator::setOriginalName($node, $previousName);
55
        }
56 264
57
        return $node;
58 264
    }
59
60
    private function shouldPrefixUseStmt(UseUse $use): bool
61 264
    {
62 12
        $useType = $this->findUseType($use);
63
64
        // If is already from the prefix namespace
65
        if ($this->prefix === $use->name->getFirst()) {
66 253
            return false;
67 6
        }
68
69
        // If is whitelisted
70 247
        if ($this->whitelist->belongsToWhitelistedNamespace((string) $use->name)) {
71 21
            return false;
72
        }
73
74 227
        if (Use_::TYPE_FUNCTION === $useType) {
75
            return false === $this->reflector->isFunctionInternal((string) $use->name);
76 26
        }
77 26
78
        if (Use_::TYPE_CONSTANT === $useType) {
79
            return self::shouldPrefixConstantUseStmt(
80
                $use->name->toString(),
81 202
                $this->whitelist,
82
                $this->reflector,
83
            );
84
        }
85
86
        return Use_::TYPE_NORMAL !== $useType || false === $this->reflector->isClassInternal((string) $use->name);
87
    }
88
89
    private static function shouldPrefixConstantUseStmt(
90
        string $name,
91 264
        Whitelist $whitelist,
92
        Reflector $reflector
93 264
    ): bool
94
    {
95 259
        return !$whitelist->isGlobalWhitelistedConstant($name)
96
            && !$whitelist->isSymbolWhitelisted($name)
97 259
            && !$reflector->isConstantInternal($name);
98
    }
99
100 5
    /**
101
     * Finds the type of the use statement.
102
     *
103
     * @param UseUse $use
104
     *
105
     * @return int See \PhpParser\Node\Stmt\Use_ type constants.
106
     */
107
    private function findUseType(UseUse $use): int
108
    {
109
        if (Use_::TYPE_UNKNOWN === $use->type) {
110
            /** @var Use_ $parentNode */
111
            $parentNode = ParentNodeAppender::getParent($use);
112
113
            return $parentNode->type;
114
        }
115
116
        return $use->type;
117
    }
118
}
119