Passed
Push — master ( 1c054e...456420 )
by Théo
01:28
created

NodeTraverser::wrapInNamespace()   B

Complexity

Conditions 7
Paths 7

Size

Total Lines 31
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 7

Importance

Changes 0
Metric Value
cc 7
eloc 16
nc 7
nop 1
dl 0
loc 31
ccs 11
cts 11
cp 1
crap 7
rs 8.8333
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;
16
17
use PhpParser\Node;
18
use PhpParser\Node\Name;
19
use PhpParser\Node\Stmt\Declare_;
20
use PhpParser\Node\Stmt\GroupUse;
21
use PhpParser\Node\Stmt\InlineHTML;
22
use PhpParser\Node\Stmt\Namespace_;
23
use PhpParser\Node\Stmt\Use_;
24
use PhpParser\Node\Stmt\UseUse;
25
use PhpParser\NodeTraverser as PhpParserNodeTraverser;
26
use function array_slice;
27
use function array_values;
28
use function count;
29
30
/**
31
 * @private
32
 */
33
final class NodeTraverser extends PhpParserNodeTraverser
34
{
35
    /**
36
     * @inheritdoc
37 549
     */
38
    public function traverse(array $nodes): array
39 549
    {
40
        $nodes = $this->wrapInNamespace($nodes);
41 549
        $nodes = $this->replaceGroupUseStatements($nodes);
42
43
        return parent::traverse($nodes);
44
    }
45
46
    /**
47 549
     * Wrap the statements in a namespace when necessary:.
48
     *
49 549
     * ```php
50 549
     * #!/usr/bin/env php
51
     * <?php declare(strict_types=1);
52 549
     *
53
     * // A small comment
54
     *
55
     * if (\true) {
56
     *  echo "yo";
57
     * }
58
     * ```
59
     *
60
     * Will result in:
61
     *
62
     * ```php
63
     * #!/usr/bin/env php
64
     * <?php declare(strict_types=1);
65
     *
66
     * // A small comment
67
     *
68
     * namespace {
69
     *     if (\true) {
70
     *      echo "yo";
71
     *     }
72
     * }
73
     * ```
74
     *
75
     * @param Node[] $nodes
76
     *
77
     * @return Node[]
78
     */
79
    private function wrapInNamespace(array $nodes): array
80
    {
81
        if ([] === $nodes) {
82
            return $nodes;
83
        }
84
85
        $nodes = array_values($nodes);
86
87
        $firstRealStatementIndex = 0;
88 549
        $realStatements = [];
89
90 549
        foreach ($nodes as $i => $node) {
91 1
            if ($node instanceof Declare_ || $node instanceof InlineHTML) {
92
                continue;
93
            }
94 548
95
            $firstRealStatementIndex = $i;
96 548
            $realStatements = array_slice($nodes, $i);
97 548
98
            break;
99 548
        }
100 548
101 11
        $firstRealStatement = current($realStatements);
102
103
        if (false !== $firstRealStatement && false === ($firstRealStatement instanceof Namespace_)) {
104 546
            $wrappedStatements = new Namespace_(null, $realStatements);
105 546
106
            array_splice($nodes, $firstRealStatementIndex, count($realStatements), [$wrappedStatements]);
107
        }
108
109
        return $nodes;
110 548
    }
111
112 548
    /**
113 242
     * @param Node[] $nodes
114
     *
115 242
     * @return Node[]
116
     */
117
    private function replaceGroupUseStatements(array $nodes): array
118 548
    {
119
        foreach ($nodes as $node) {
120
            if (false === ($node instanceof Namespace_)) {
121
                continue;
122
            }
123
124
            /** @var Namespace_ $node */
125
            $statements = $node->stmts;
126 549
127
            $newStatements = [];
128 549
129 548
            foreach ($statements as $statement) {
130 11
                if ($statement instanceof GroupUse) {
131
                    $uses_ = $this->createUses_($statement);
132
133
                    array_splice($newStatements, count($newStatements), 0, $uses_);
134 546
                } else {
135
                    $newStatements[] = $statement;
136 546
                }
137
            }
138 546
139 533
            $node->stmts = $newStatements;
140 6
        }
141
142 6
        return $nodes;
143
    }
144 527
145
    /**
146
     * @param GroupUse $node
147
     *
148 546
     * @return Use_[]
149
     */
150
    private function createUses_(GroupUse $node): array
151 549
    {
152
        return array_map(
153
            static function (UseUse $use) use ($node): Use_ {
154
                $newUse = new UseUse(
155
                    Name::concat($node->prefix, $use->name, $use->name->getAttributes()),
156
                    $use->alias,
157
                    $use->type,
158
                    $use->getAttributes()
159 6
                );
160
161 6
                return new Use_(
162
                    [$newUse],
163 6
                    $node->type,
164 6
                    $node->getAttributes()
165 6
                );
166 6
            },
167 6
            $node->uses
168
        );
169
    }
170
}
171