Passed
Pull Request — master (#39)
by Alexander
02:21
created

UseStatementParser   A

Complexity

Total Complexity 25

Size/Duplication

Total Lines 91
Duplicated Lines 0 %

Test Coverage

Coverage 95.83%

Importance

Changes 6
Bugs 1 Features 0
Metric Value
eloc 47
c 6
b 1
f 0
dl 0
loc 91
ccs 46
cts 48
cp 0.9583
rs 10
wmc 25

3 Methods

Rating   Name   Duplication   Size   Complexity  
A fromFile() 0 18 4
A replaceAliases() 0 15 4
C normalizeUse() 0 40 17
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 34
    public function fromFile(string $file): array
20
    {
21 34
        $tokens = token_get_all(file_get_contents($file));
22 34
        array_shift($tokens);
23
24 34
        $uses = [];
25 34
        foreach ($tokens as $i => $token) {
26 34
            if (!isset($token[0])) {
27
                continue;
28
            }
29
30 34
            if ($token[0] === T_USE) {
31 34
                $uses = array_merge($uses, $this->normalizeUse(array_slice($tokens, $i + 1)));
32 34
                continue;
33
            }
34
        }
35
36 34
        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 34
    private function normalizeUse(array $tokens): array
47
    {
48 34
        $commonNamespace = '\\';
49 34
        $current = '';
50 34
        $uses = [];
51
52 34
        foreach ($tokens as $token) {
53 34
            if (!isset($token[0])) {
54
                continue;
55
            }
56
            if (
57 34
                $token[0] === T_STRING
58 34
                || $token[0] === T_NS_SEPARATOR
59 34
                || (defined('T_NAME_QUALIFIED') && $token[0] === T_NAME_QUALIFIED)
60 34
                || (defined('T_NAME_FULLY_QUALIFIED') && $token[0] === T_NAME_FULLY_QUALIFIED)
61 34
                || (defined('T_NAME_RELATIVE') && $token[0] === T_NAME_RELATIVE)
62
            ) {
63 34
                $current .= $token[1];
64 34
                continue;
65
            }
66 34
            if ($token === ',' || $token === ';') {
67 34
                if ($current !== '') {
68 34
                    $uses[] = $commonNamespace . $current;
69 34
                    $current = '';
70
                }
71
            }
72 34
            if ($token === ';') {
73 34
                break;
74
            }
75 34
            if ($token === '{') {
76 1
                $commonNamespace .= $current;
77 1
                $current = '';
78 1
                continue;
79
            }
80 34
            if ($token[0] === T_AS) {
81 31
                $current .= '@';
82
            }
83
        }
84
85 34
        return $this->replaceAliases($uses);
86
    }
87
88 34
    private function replaceAliases(array $uses): array
89
    {
90 34
        $result = [];
91 34
        foreach ($uses as $use) {
92 34
            $delimiterPosition = strpos($use, '@');
93 34
            if ($delimiterPosition !== false) {
94 31
                $alias = mb_substr($use, $delimiterPosition + 1);
95 31
                $result[$alias] = mb_substr($use, 0, $delimiterPosition);
96
            } else {
97 32
                $part = strrchr($use, '\\');
98 32
                $result[$part === false ? $use : substr($part, 1)] = $use;
99
            }
100
        }
101
102 34
        return $result;
103
    }
104
}
105