Passed
Pull Request — master (#34)
by Evgeniy
01:51
created

UseStatementParser   A

Complexity

Total Complexity 25

Size/Duplication

Total Lines 95
Duplicated Lines 0 %

Test Coverage

Coverage 94%

Importance

Changes 6
Bugs 1 Features 0
Metric Value
eloc 50
c 6
b 1
f 0
dl 0
loc 95
ccs 47
cts 50
cp 0.94
rs 10
wmc 25

3 Methods

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