Completed
Push — master ( 2042ea...18e329 )
by Oscar
02:29
created

JsFunctionsScanner::getFunctions()   F

Complexity

Conditions 43
Paths 231

Size

Total Lines 151
Code Lines 108

Duplication

Lines 32
Ratio 21.19 %

Importance

Changes 4
Bugs 2 Features 0
Metric Value
cc 43
eloc 108
c 4
b 2
f 0
nc 231
nop 0
dl 32
loc 151
rs 3.5866

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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()
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]) ? $this->code[$pos] : null;
36
37
            switch ($char) {
38
                case "\n":
39
                    ++$line;
40
41
                    if ($this->status('line-comment')) {
42
                        $this->upStatus();
43
                    }
44
                    break;
45
46
                case '/':
47
                    switch ($this->status()) {
48
                        case 'simple-quote':
49
                        case 'double-quote':
50
                        case 'line-comment':
51
                            break;
52
53
                        case 'block-comment':
54
                            if ($prev === '*') {
55
                                $this->upStatus();
56
                            }
57
                            break;
58
59
                        default:
60
                            if ($next === '/') {
61
                                $this->downStatus('line-comment');
62
                            } elseif ($next === '*') {
63
                                $this->downStatus('block-comment');
64
                            }
65
                            break;
66
                    }
67
                    break;
68
69 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...
70
                    switch ($this->status()) {
71
                        case 'simple-quote':
72
                            $this->upStatus();
73
                            break;
74
75
                        case 'line-comment':
76
                        case 'block-comment':
77
                        case 'double-quote':
78
                            break;
79
80
                        default:
81
                            $this->downStatus('simple-quote');
82
                            break;
83
                    }
84
                    break;
85
86 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...
87
                    switch ($this->status()) {
88
                        case 'double-quote':
89
                            $this->upStatus();
90
                            break;
91
92
                        case 'line-comment':
93
                        case 'block-comment':
94
                        case 'simple-quote':
95
                            break;
96
97
                        default:
98
                            $this->downStatus('double-quote');
99
                            break;
100
                    }
101
                    break;
102
103
                case '(':
104
                    switch ($this->status()) {
105
                        case 'double-quote':
106
                        case 'line-comment':
107
                        case 'block-comment':
108
                        case 'line-comment':
109
                            break;
110
111
                        default:
112
                            if ($buffer && preg_match('/(\w+)$/', $buffer, $matches)) {
113
                                $this->downStatus('function');
114
                                array_unshift($bufferFunctions, [$matches[1], $line, []]);
115
                                $buffer = '';
116
                                continue 3;
117
                            }
118
                            break;
119
                    }
120
                    break;
121
122
                case ')':
123
                    switch ($this->status()) {
124
                        case 'function':
125
                            if (($argument = self::prepareArgument($buffer))) {
126
                                $bufferFunctions[0][2][] = $argument;
127
                            }
128
129
                            if (!empty($bufferFunctions)) {
130
                                $functions[] = array_shift($bufferFunctions);
131
                            }
132
133
                            $buffer = '';
134
                            continue 3;
135
                    }
136
137
                case ',':
138
                    switch ($this->status()) {
139
                        case 'function':
140
                            if (($argument = self::prepareArgument($buffer))) {
141
                                $bufferFunctions[0][2][] = $argument;
142
                            }
143
144
                            $buffer = '';
145
                            continue 3;
146
                    }
147
148
                case ' ':
149
                case '\t':
150
                    switch ($this->status()) {
151
                        case 'double-quote':
152
                        case 'simple-quote':
153
                            break;
154
155
                        default:
156
                            continue 3;
157
                    }
158
                    break;
159
            }
160
161
            switch ($this->status()) {
162
                case 'line-comment':
163
                case 'block-comment':
164
                    break;
165
166
                default:
167
                    $buffer .= $char;
168
                    break;
169
            }
170
        }
171
172
        return $functions;
173
    }
174
175
    /**
176
     * Get the current context of the scan.
177
     *
178
     * @param null|string $match To check whether the current status is this value
179
     *
180
     * @return string|bool
181
     */
182
    protected function status($match = null)
183
    {
184
        $status = isset($this->status[0]) ? $this->status[0] : null;
185
186
        if ($match !== null) {
187
            return $status === $match;
188
        }
189
190
        return $status;
191
    }
192
193
    /**
194
     * Add a new status to the stack.
195
     *
196
     * @param string $status
197
     */
198
    protected function downStatus($status)
199
    {
200
        array_unshift($this->status, $status);
201
    }
202
203
    /**
204
     * Removes and return the current status.
205
     *
206
     * @return string|null
207
     */
208
    protected function upStatus()
209
    {
210
        return array_shift($this->status);
211
    }
212
213
    /**
214
     * Prepares the arguments found in functions.
215
     *
216
     * @param string $argument
217
     *
218
     * @return string
219
     */
220
    protected static function prepareArgument($argument)
221
    {
222
        if ($argument && ($argument[0] === '"' || $argument[0] === "'")) {
223
            if ($argument[0] === '"') {
224
                $argument = str_replace('\\"', '"', $argument);
225
            } else {
226
                $argument = str_replace("\\'", "'", $argument);
227
            }
228
229
            return substr($argument, 1, -1);
230
        }
231
    }
232
}
233