ParseUseStatement   A
last analyzed

Complexity

Total Complexity 34

Size/Duplication

Total Lines 138
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 1

Importance

Changes 0
Metric Value
dl 0
loc 138
rs 9.68
c 0
b 0
f 0
wmc 34
lcom 1
cbo 1

6 Methods

Rating   Name   Duplication   Size   Complexity  
A getUseStatementsByPath() 0 4 1
A findClassReferences() 0 14 3
D parseUseStatements() 0 68 23
A fetch() 0 19 5
A requestIssue() 0 10 1
A FetchNS() 0 4 1
1
<?php
2
3
namespace Imanghafoori\LaravelMicroscope\Analyzers;
4
5
class ParseUseStatement
6
{
7
    public static function getUseStatementsByPath($namespacedClassName, $absPath)
8
    {
9
        return self::parseUseStatements(token_get_all(file_get_contents($absPath)), $namespacedClassName)[1];
10
    }
11
12
    public static function findClassReferences(&$tokens, $absFilePath)
13
    {
14
        try {
15
            $imports = self::parseUseStatements($tokens);
16
            $imports = $imports[0] ?: [$imports[1]];
17
            [$classes, $namespace] = ClassReferenceFinder::process($tokens);
0 ignored issues
show
Bug introduced by
The variable $classes does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $namespace does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
18
19
            return Expander::expendReferences($classes, $imports, $namespace);
20
        } catch (\ErrorException $e) {
0 ignored issues
show
Bug introduced by
The class ErrorException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
21
            self::requestIssue($absFilePath);
22
23
            return [];
24
        }
25
    }
26
27
    /**
28
     * Parses PHP code.
29
     *
30
     * @param $tokens
31
     * @param  null  $forClass
32
     *
33
     * @return array of [class => [alias => class, ...]]
34
     */
35
    public static function parseUseStatements($tokens, $forClass = null)
36
    {
37
        $namespace = $class = $classLevel = $level = null;
38
        $output = $uses = [];
39
        while ($token = \current($tokens)) {
40
            \next($tokens);
41
            switch (\is_array($token) ? $token[0] : $token) {
42
                case T_NAMESPACE:
43
                    $namespace = ltrim(self::FetchNS($tokens).'\\', '\\');
44
                    $uses = [];
45
                    break;
46
47
                case T_CLASS:
48
                case T_INTERFACE:
49
                case T_TRAIT:
50
                    if ($name = self::fetch($tokens, T_STRING)) {
51
                        $class = $namespace.$name;
52
                        $classLevel = $level + 1;
53
                        $output[$class] = $uses;
54
                        if ($class === $forClass) {
55
                            return [$output, $uses];
56
                        }
57
                    }
58
                    break;
59
60
                case T_USE:
61
                    while (! $class && ($name = self::FetchNS($tokens))) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $class of type string|null is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
62
                        $name = ltrim($name, '\\');
63
                        if (self::fetch($tokens, '{')) {
0 ignored issues
show
Bug Best Practice introduced by
The expression self::fetch($tokens, '{') of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
64
                            while ($suffix = self::FetchNS($tokens)) {
65
                                if (self::fetch($tokens, T_AS)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression self::fetch($tokens, T_AS) of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
66
                                    $uses[self::fetch($tokens, T_STRING)] = [$name.$suffix, $token[2]];
67
                                } else {
68
                                    $tmp = \explode('\\', $suffix);
69
                                    $uses[end($tmp)] = [$name.$suffix, $token[2]];
70
                                }
71
                                if (! self::fetch($tokens, ',')) {
0 ignored issues
show
Bug Best Practice introduced by
The expression self::fetch($tokens, ',') of type string|null is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
72
                                    break;
73
                                }
74
                            }
75
                        } elseif (self::fetch($tokens, T_AS)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression self::fetch($tokens, T_AS) of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
76
                            $uses[self::fetch($tokens, T_STRING)] = [$name, $token[2]];
77
                        } else {
78
                            $tmp = \explode('\\', $name);
79
                            $uses[\end($tmp)] = [$name, $token[2]];
80
                        }
81
                        if (! self::fetch($tokens, ',')) {
0 ignored issues
show
Bug Best Practice introduced by
The expression self::fetch($tokens, ',') of type string|null is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
82
                            break;
83
                        }
84
                    }
85
                    break;
86
87
                case T_CURLY_OPEN:
88
                case T_DOLLAR_OPEN_CURLY_BRACES:
89
                case '{':
90
                    $level++;
91
                    break;
92
93
                case '}':
94
                    if ($level === $classLevel) {
95
                        $class = $classLevel = null;
96
                    }
97
                    $level--;
98
            }
99
        }
100
101
        return [$output, $uses];
102
    }
103
104
    public static function fetch(&$tokens, $take)
105
    {
106
        $result = null;
107
108
        $neutral = [T_DOC_COMMENT, T_WHITESPACE, T_COMMENT];
109
110
        while ($token = \current($tokens)) {
111
            [$token, $s,] = \is_array($token) ? $token : [$token, $token];
0 ignored issues
show
Bug introduced by
The variable $s does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
112
113
            if (\in_array($token, (array) $take, true)) {
114
                $result .= $s;
115
            } elseif (! \in_array($token, $neutral, true)) {
116
                break;
117
            }
118
            \next($tokens);
119
        }
120
121
        return $result;
122
    }
123
124
    /**
125
     * @param $absFilePath
126
     */
127
    protected static function requestIssue($absFilePath)
128
    {
129
        dump('===========================================================');
130
        dump('was not able to properly parse the: '.$absFilePath.' file.');
131
        dump('Please open up an issue on the github repo');
132
        dump('https://github.com/imanghafoori1/laravel-microscope/issues');
133
        dump('and also send the content of the file to fix the issue.');
134
        dump('========================== Thanks ==========================');
135
        sleep(3);
136
    }
137
138
    private static function FetchNS(&$tokens)
139
    {
140
        return self::fetch($tokens, [T_STRING, T_NS_SEPARATOR, T_NAME_QUALIFIED]);
141
    }
142
}
143