Passed
Pull Request — master (#42)
by Alexander
02:06
created

UseStatementParser::replaceAliases()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 14
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 3

Importance

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