Completed
Push — master ( 010d44...6c2765 )
by Oscar
13s
created

JsFunctionsScanner::downStatus()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 4
rs 10
1
<?php
2
3
namespace Gettext\Utils;
4
5
class JsFunctionsScanner extends FunctionsScanner
6
{
7
    protected $code;
8
    protected $status = [];
9
10
    /**
11
     * Constructor.
12
     *
13
     * @param string $code The php code to scan
14
     */
15
    public function __construct($code)
16
    {
17
        $this->code = $code;
18
    }
19
20
    /**
21
     * {@inheritdoc}
22
     */
23
    public function getFunctions(array $constants = [])
24
    {
25
        $length = strlen($this->code);
26
        $line = 1;
27
        $buffer = '';
28
        $functions = [];
29
        $bufferFunctions = [];
30
        $char = null;
31
32
        for ($pos = 0; $pos < $length; ++$pos) {
33
            $prev = $char;
34
            $char = $this->code[$pos];
35
            $next = isset($this->code[$pos + 1]) ? $this->code[$pos + 1] : null;
36
37
            switch ($char) {
38
                case '\\':
39
                    $prev = $char;
0 ignored issues
show
Unused Code introduced by
$prev is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
40
                    $char = $next;
41
                    $pos++;
42
                    $next = isset($this->code[$pos]) ? $this->code[$pos] : null;
0 ignored issues
show
Unused Code introduced by
$next is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
43
                    break;
44
45
                case "\n":
46
                    ++$line;
47
48
                    if ($this->status('line-comment')) {
49
                        $this->upStatus();
50
                    }
51
                    break;
52
53
                case '/':
54
                    switch ($this->status()) {
55
                        case 'simple-quote':
56
                        case 'double-quote':
57
                        case 'line-comment':
58
                            break;
59
60
                        case 'block-comment':
61
                            if ($prev === '*') {
62
                                $this->upStatus();
63
                            }
64
                            break;
65
66
                        default:
67
                            if ($next === '/') {
68
                                $this->downStatus('line-comment');
69
                            } elseif ($next === '*') {
70
                                $this->downStatus('block-comment');
71
                            }
72
                            break;
73
                    }
74
                    break;
75
76 View Code Duplication
                case "'":
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
77
                    switch ($this->status()) {
78
                        case 'simple-quote':
79
                            $this->upStatus();
80
                            break;
81
82
                        case 'line-comment':
83
                        case 'block-comment':
84
                        case 'double-quote':
85
                            break;
86
87
                        default:
88
                            $this->downStatus('simple-quote');
89
                            break;
90
                    }
91
                    break;
92
93 View Code Duplication
                case '"':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
94
                    switch ($this->status()) {
95
                        case 'double-quote':
96
                            $this->upStatus();
97
                            break;
98
99
                        case 'line-comment':
100
                        case 'block-comment':
101
                        case 'simple-quote':
102
                            break;
103
104
                        default:
105
                            $this->downStatus('double-quote');
106
                            break;
107
                    }
108
                    break;
109
110
                case '(':
111
                    switch ($this->status()) {
112
                        case 'simple-quote':
113
                        case 'double-quote':
114
                        case 'line-comment':
115
                        case 'block-comment':
116
                        case 'line-comment':
117
                            break;
118
119
                        default:
120
                            if ($buffer && preg_match('/(\w+)$/', $buffer, $matches)) {
121
                                $this->downStatus('function');
122
                                array_unshift($bufferFunctions, [$matches[1], $line, []]);
123
                                $buffer = '';
124
                                continue 3;
125
                            }
126
                            break;
127
                    }
128
                    break;
129
130
                case ')':
131
                    switch ($this->status()) {
132
                        case 'function':
133
                            if (($argument = self::prepareArgument($buffer))) {
134
                                $bufferFunctions[0][2][] = $argument;
135
                            }
136
137
                            if (!empty($bufferFunctions)) {
138
                                $functions[] = array_shift($bufferFunctions);
139
                            }
140
141
                            $this->upStatus();
142
                            $buffer = '';
143
                            continue 3;
144
                    }
145
                    break;
146
147
                case ',':
148
                    switch ($this->status()) {
149
                        case 'function':
150
                            if (($argument = self::prepareArgument($buffer))) {
151
                                $bufferFunctions[0][2][] = $argument;
152
                            }
153
154
                            $buffer = '';
155
                            continue 3;
156
                    }
157
                    break;
158
159
                case ' ':
160
                case '\t':
161
                    switch ($this->status()) {
162
                        case 'double-quote':
163
                        case 'simple-quote':
164
                            break;
165
166
                        default:
167
                            continue 3;
168
                    }
169
                    break;
170
            }
171
172
            switch ($this->status()) {
173
                case 'line-comment':
174
                case 'block-comment':
175
                    break;
176
177
                default:
178
                    $buffer .= $char;
179
                    break;
180
            }
181
        }
182
183
        return $functions;
184
    }
185
186
    /**
187
     * Get the current context of the scan.
188
     *
189
     * @param null|string $match To check whether the current status is this value
190
     *
191
     * @return string|bool
192
     */
193
    protected function status($match = null)
194
    {
195
        $status = isset($this->status[0]) ? $this->status[0] : null;
196
197
        if ($match !== null) {
198
            return $status === $match;
199
        }
200
201
        return $status;
202
    }
203
204
    /**
205
     * Add a new status to the stack.
206
     *
207
     * @param string $status
208
     */
209
    protected function downStatus($status)
210
    {
211
        array_unshift($this->status, $status);
212
    }
213
214
    /**
215
     * Removes and return the current status.
216
     *
217
     * @return string|null
218
     */
219
    protected function upStatus()
220
    {
221
        return array_shift($this->status);
222
    }
223
224
    /**
225
     * Prepares the arguments found in functions.
226
     *
227
     * @param string $argument
228
     *
229
     * @return string
230
     */
231
    protected static function prepareArgument($argument)
232
    {
233
        if ($argument && ($argument[0] === '"' || $argument[0] === "'")) {
234
            return substr($argument, 1, -1);
235
        }
236
    }
237
}
238