Passed
Pull Request — master (#34)
by Evgeniy
02:22
created

UseStatementParser::fromFile()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 18
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 4.0119

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 10
nc 4
nop 1
dl 0
loc 18
ccs 10
cts 11
cp 0.9091
crap 4.0119
rs 9.9332
c 1
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\VarDumper;
6
7
use function define;
8
use function defined;
9
10 1
defined('T_NAME_QUALIFIED') || define('T_NAME_QUALIFIED', -4);
11 1
defined('T_NAME_FULLY_QUALIFIED') || define('T_NAME_FULLY_QUALIFIED', -5);
12
13
/**
14
 * UseStatementParser given a PHP file, returns a set of `use` statements from the code.
15
 */
16
final class UseStatementParser
17
{
18
    /**
19
     * @param string $file File to read.
20
     *
21
     * @return array Use statements data.
22
     */
23 44
    public function fromFile(string $file): array
24
    {
25 44
        $tokens = token_get_all(file_get_contents($file));
26 44
        array_shift($tokens);
27
28 44
        $uses = [];
29 44
        foreach ($tokens as $i => $token) {
30 44
            if (!isset($token[0])) {
31
                continue;
32
            }
33
34 44
            if ($token[0] === T_USE) {
35 44
                $uses = array_merge($uses, $this->normalizeUse(array_slice($tokens, $i + 1)));
36 44
                continue;
37
            }
38
        }
39
40 44
        return $uses;
41
    }
42
43
    /**
44
     * Normalizes raw tokens into uniform use statement data.
45
     *
46
     * @param array $tokens Raw tokens.
47
     *
48
     * @return array Normalized use statement data.
49
     */
50 44
    private function normalizeUse(array $tokens): array
51
    {
52 44
        $commonNamespace = '\\';
53 44
        $current = '';
54 44
        $alias = null;
55 44
        $uses = [];
56
57 44
        foreach ($tokens as $token) {
58 44
            if (!isset($token[0])) {
59
                continue;
60
            }
61
62
            if (
63 44
                $token[0] === T_STRING || $token[0] === T_NS_SEPARATOR || $token[0] === T_NAME_QUALIFIED || $token[0] === T_NAME_FULLY_QUALIFIED
64 44
                || (version_compare(PHP_VERSION, '8.0.0', '>=') && $token[0] === T_NAME_RELATIVE)
65
            ) {
66 44
                $current .= $token[1];
67 44
                continue;
68
            }
69 44
            if ($token === ',' || $token === ';') {
70 44
                if ($current !== '') {
71 44
                    if ($alias === null) {
72 44
                        $uses[] = $commonNamespace . $current;
73
                    } else {
74
                        $uses[$alias] = $commonNamespace . $current;
75
                    }
76 44
                    $current = '';
77
                }
78
            }
79 44
            if ($token === ';') {
80 44
                break;
81
            }
82 44
            if ($token === '{') {
83 1
                $commonNamespace .= $current;
84 1
                $current = '';
85 1
                continue;
86
            }
87 44
            if ($token[0] === T_AS) {
88 41
                $current .= '@';
89
            }
90
        }
91
92 44
        return $this->replaceAliases($uses);
93
    }
94
95 44
    private function replaceAliases(array $uses): array
96
    {
97 44
        $result = [];
98 44
        foreach ($uses as $use) {
99 44
            $delimiterPosition = strpos($use, '@');
100 44
            if ($delimiterPosition !== false) {
101 41
                $alias = mb_substr($use, $delimiterPosition + 1);
102 41
                $result[$alias] = mb_substr($use, 0, $delimiterPosition);
103
            } else {
104 42
                $result[substr(strrchr($use, '\\'), 1)] = $use;
105
            }
106
        }
107
108 44
        return $result;
109
    }
110
}
111