Completed
Push — master ( 4568c2...6bb1b7 )
by Théo
03:18
created

UseStmtPrefixer::shouldPrefixUseStmt()   C

Complexity

Conditions 7
Paths 7

Size

Total Lines 27
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 7.0283

Importance

Changes 0
Metric Value
cc 7
eloc 13
nc 7
nop 1
dl 0
loc 27
rs 6.7272
c 0
b 0
f 0
ccs 11
cts 12
cp 0.9167
crap 7.0283
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\NodeVisitor\UseStmt;
16
17
use Humbug\PhpScoper\NodeVisitor\AppendParentNode;
18
use Humbug\PhpScoper\Reflector;
19
use PhpParser\Node;
20
use PhpParser\Node\Name;
21
use PhpParser\Node\Stmt\Use_;
22
use PhpParser\Node\Stmt\UseUse;
23
use PhpParser\NodeVisitorAbstract;
24
25
/**
26
 * Prefixes the use statements.
27
 */
28
final class UseStmtPrefixer extends NodeVisitorAbstract
29
{
30
    private $prefix;
31
    private $whitelist;
32
    private $reflector;
33
34
    /**
35
     * @param string    $prefix
36
     * @param string[]  $whitelist
37
     * @param Reflector $reflector
38
     */
39 341
    public function __construct(string $prefix, array $whitelist, Reflector $reflector)
40
    {
41 341
        $this->prefix = $prefix;
42 341
        $this->whitelist = $whitelist;
43 341
        $this->reflector = $reflector;
44
    }
45
46
    /**
47
     * @inheritdoc
48
     */
49 340
    public function enterNode(Node $node)
50
    {
51 340
        if ($node instanceof UseUse && $this->shouldPrefixUseStmt($node)) {
52 149
            $node->name = Name::concat($this->prefix, $node->name);
53
        }
54
55 340
        return $node;
56
    }
57
58 196
    private function shouldPrefixUseStmt(UseUse $use): bool
59
    {
60 196
        $useType = $this->findUseType($use);
61
62
        // If is already from the prefix namespace
63 196
        if ($this->prefix === $use->name->getFirst()) {
64 11
            return false;
65
        }
66
67
        // Is not from the Composer namespace
68 185
        if ('Composer' === $use->name->getFirst()) {
69
            return false;
70
        }
71
72 185
        if (1 === count($use->name->parts)) {
73 135
            if (Use_::TYPE_FUNCTION === $useType) {
74 11
                return false === $this->reflector->isFunctionInternal($use->name->getFirst());
75
            }
76
77 124
            return Use_::TYPE_NORMAL !== $useType || false === $this->reflector->isClassInternal($use->name->getFirst());
78
        }
79
80
        return false === (
81 54
            Use_::TYPE_NORMAL === $useType
82 54
            && in_array((string) $use->name, $this->whitelist)
83
        );
84
    }
85
86
    /**
87
     * Finds the type of the use statement.
88
     *
89
     * @param UseUse $use
90
     *
91
     * @return int See \PhpParser\Node\Stmt\Use_ type constants.
92
     */
93 196
    private function findUseType(UseUse $use): int
94
    {
95 196
        if (Use_::TYPE_UNKNOWN === $use->type) {
96
            /** @var Use_ $parentNode */
97 191
            $parentNode = AppendParentNode::getParent($use);
98
99 191
            return $parentNode->type;
100
        }
101
102 5
        return $use->type;
103
    }
104
}
105