GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — v0.89-develop ( 4347a7...178f3d )
by Zordius
02:13
created

Parser::getExpression()   D

Complexity

Conditions 22
Paths 292

Size

Total Lines 75
Code Lines 41

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 39
CRAP Score 22

Importance

Changes 6
Bugs 1 Features 0
Metric Value
c 6
b 1
f 0
dl 0
loc 75
ccs 39
cts 39
cp 1
rs 4
cc 22
eloc 41
nc 292
nop 3
crap 22

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
4
Copyrights for code authored by Yahoo! Inc. is licensed under the following terms:
5
MIT License
6
Copyright (c) 2013-2015 Yahoo! Inc. All Rights Reserved.
7
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
8
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
9
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
10
11
Origin: https://github.com/zordius/lightncandy
12
*/
13
14
/**
15
 * file to keep LightnCandy Parser
16
 *
17
 * @package    LightnCandy
18
 * @author     Zordius <[email protected]>
19
 */
20
21
namespace LightnCandy;
22
23
use \LightnCandy\Token;
24
use \LightnCandy\SafeString;
25
26
/**
27
 * LightnCandy Parser
28
 */
29
class Parser extends Token
30
{
31
    // Compile time error handling flags
32
    const BLOCKPARAM = 9999;
33
    const LITERAL = -1;
34
    const SUBEXP = -2;
35
36
    /**
37
     * Get block params and fix the variable list
38
     *
39
     * @param array<boolean|integer|array> $vars parsed token
40
     *
41
     * @return array<string>|null Return list of block params or null
0 ignored issues
show
Documentation introduced by
Should the return type not be boolean|integer|array|null? Also, consider making the array more specific, something like array<String>, or String[].

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

If the return type contains the type array, this check recommends the use of a more specific type like String[] or array<String>.

Loading history...
42
     *
43
     */
44
    public static function getBlockParams(&$vars) {
45 189
        if (isset($vars[static::BLOCKPARAM])) {
46 189
            $list = $vars[static::BLOCKPARAM];
47 8
            unset($vars[static::BLOCKPARAM]);
48 8
            return $list;
49 8
        }
50
    }
51 184
52
    /**
53
     * Return array presentation for an expression
54
     *
55
     * @param string $name variable name.
56
     * @param boolean $asis keep the name as is or not
57
     * @param boolean $quote add single quote or not
58
     *
59
     * @return array<integer|string> Return variable name array
60
     *
61
     */
62
    protected static function getLiteral($name, $asis, $quote = false) {
63 94
        return $asis ? array($name) : array(static::LITERAL, $quote ? "'$name'" : $name);
64 94
    }
65
66
    /**
67
     * Return array presentation for an expression
68
     *
69
     * @param string $v analyzed expression names.
70
     * @param array<string,array|string|integer> $context Current compile content.
71
     * @param integer $pos expression position
72
     *
73
     * @return array<integer,string> Return variable name array
74
     *
75
     * @expect array('this') when input 'this', array('flags' => array('strpar' => 0, 'advar' => 0, 'this' => 0)), 0
76
     * @expect array() when input 'this', array('flags' => array('strpar' => 0, 'advar' => 0, 'this' => 1)), 0
77
     * @expect array(1) when input '../', array('flags' => array('strpar' => 0, 'advar' => 0, 'this' => 1, 'parent' => 1), 'usedFeature' => array('parent' => 0)), 0
78
     * @expect array(1) when input '../.', array('flags' => array('strpar' => 0, 'advar' => 0, 'this' => 1, 'parent' => 1), 'usedFeature' => array('parent' => 0)), 0
79
     * @expect array(1) when input '../this', array('flags' => array('strpar' => 0, 'advar' => 0, 'this' => 1, 'parent' => 1), 'usedFeature' => array('parent' => 0)), 0
80
     * @expect array(1, 'a') when input '../a', array('flags' => array('strpar' => 0, 'advar' => 0, 'this' => 1, 'parent' => 1), 'usedFeature' => array('parent' => 0)), 0
81
     * @expect array(2, 'a', 'b') when input '../../a.b', array('flags' => array('strpar' => 0, 'advar' => 0, 'this' => 0, 'parent' => 1), 'usedFeature' => array('parent' => 0)), 0
82
     * @expect array(2, '[a]', 'b') when input '../../[a].b', array('flags' => array('strpar' => 0, 'advar' => 0, 'this' => 0, 'parent' => 1), 'usedFeature' => array('parent' => 0)), 0
83
     * @expect array(2, 'a', 'b') when input '../../[a].b', array('flags' => array('strpar' => 0, 'advar' => 1, 'this' => 0, 'parent' => 1), 'usedFeature' => array('parent' => 0)), 0
84
     * @expect array(0, 'id') when input 'this.id', array('flags' => array('strpar' => 0, 'advar' => 1, 'this' => 1, 'parent' => 1), 'usedFeature' => array('parent' => 0)), 0
85
     * @expect array('this', 'id') when input 'this.id', array('flags' => array('strpar' => 0, 'advar' => 1, 'this' => 0, 'parent' => 1), 'usedFeature' => array('parent' => 0)), 0
86
     * @expect array(0, 'id') when input './id', array('flags' => array('strpar' => 0, 'advar' => 1, 'this' => 0, 'parent' => 1), 'usedFeature' => array('parent' => 0)), 0
87
     * @expect array(-1, '\'a.b\'') when input '"a.b"', array('flags' => array('strpar' => 0, 'advar' => 1, 'this' => 0, 'parent' => 1), 'usedFeature' => array('parent' => 0)), 1
88
     * @expect array(-1, '123') when input '123', array('flags' => array('strpar' => 0, 'advar' => 1, 'this' => 0, 'parent' => 1), 'usedFeature' => array('parent' => 0)), 1
89
     * @expect array(-1, 'null') when input 'null', array('flags' => array('strpar' => 0, 'advar' => 1, 'this' => 0, 'parent' => 1), 'usedFeature' => array('parent' => 0)), 1
90
     */
91
    protected static function getExpression($v, &$context, $pos) {
92 645
        $asis = ($pos === 0);
93 645
94
        // handle number
95
        if (is_numeric($v)) {
96 645
            return static::getLiteral(strval(1 * $v), $asis);
97 29
        }
98
99
        // handle double quoted string
100
        if (preg_match('/^"(.*)"$/', $v, $matched)) {
101 640
            return static::getLiteral(preg_replace('/([^\\\\])\\\\\\\\"/', '$1"', preg_replace('/^\\\\\\\\"/', '"', $matched[1])), $asis, true);
102 45
        }
103
104
        // handle single quoted string
105
        if (preg_match('/^\\\\\'(.*)\\\\\'$/', $v, $matched)) {
106 634
            return static::getLiteral($matched[1], $asis, true);
107 21
        }
108
109
        // handle boolean, null and undefined
110
        if (preg_match('/^(true|false|null|undefined)$/', $v)) {
111 631
            return static::getLiteral($v, $asis);
112 29
        }
113
114
        $ret = array();
115 626
        $levels = 0;
116 626
117
        // handle ..
118
        if ($v === '..') {
119 626
            $v = '../';
120 6
        }
121
122
        // Trace to parent for ../ N times
123
        $v = preg_replace_callback('/\\.\\.\\//', function() use (&$levels) {
124 626
            $levels++;
125 46
            return '';
126 46
        }, trim($v));
127 626
128
        // remove ./ in path
129
        $v = preg_replace('/\\.\\//', '', $v, -1, $scoped);
130 626
131
        $strp = (($pos !== 0) && $context['flags']['strpar']);
132 626
        if ($levels && !$strp) {
133 626
            $ret[] = $levels;
134 43
            if (!$context['flags']['parent']) {
135 43
                $context['error'][] = 'Do not support {{../var}}, you should do compile with LightnCandy::FLAG_PARENT flag';
136 4
            }
137
            $context['usedFeature']['parent'] ++;
138 43
        }
139
140
        if ($context['flags']['advar'] && preg_match('/\\]/', $v)) {
141 626
            preg_match_all(static::VARNAME_SEARCH, $v, $matchedall);
142 31
        } else {
143
            preg_match_all('/([^\\.\\/]+)/', $v, $matchedall);
144 601
        }
145
146
        foreach ($matchedall[1] as $m) {
147 626
            if ($context['flags']['advar'] && substr($m, 0, 1) === '[') {
148 619
                $ret[] = substr($m, 1, -1);
149 25
            } else if ((!$context['flags']['this'] || ($m !== 'this')) && ($m !== '.')) {
150 612
                $ret[] = $m;
151 610
            } else {
152
                $scoped++;
153 619
            }
154
        }
155
156
        if ($strp) {
157 626
            return array(static::LITERAL, "'" . implode('.', $ret) . "'");
158 10
        }
159
160
        if (($scoped > 0) && ($levels === 0) && (count($ret) > 0)) {
161 626
            array_unshift($ret, 0);
162 9
        }
163
164
        return $ret;
165 626
    }
166
167
    /**
168
     * Parse the token and return parsed result.
169
     *
170
     * @param array<string> $token preg_match results
171
     * @param array<string,array|string|integer> $context current compile context
172
     *
173
     * @return array<boolean|integer|array> Return parsed result
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array<boolean|array<boolean|integer|array>>.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
174
     *
175
     * @expect array(false, array(array())) when input array(0,0,0,0,0,0,0,''), array('flags' => array('strpar' => 0, 'advar' => 0, 'this' => 1, 'namev' => 0, 'noesc' => 0), 'rawblock' => false)
176
     * @expect array(true, array(array())) when input array(0,0,0,'{{',0,'{',0,''), array('flags' => array('strpar' => 0, 'advar' => 0, 'this' => 1, 'namev' => 0, 'noesc' => 0), 'rawblock' => false)
177
     * @expect array(true, array(array())) when input array(0,0,0,0,0,0,0,''), array('flags' => array('strpar' => 0, 'advar' => 0, 'this' => 1, 'namev' => 0, 'noesc' => 1), 'rawblock' => false)
178
     * @expect array(false, array(array('a'))) when input array(0,0,0,0,0,0,0,'a'), array('flags' => array('strpar' => 0, 'advar' => 0, 'this' => 1, 'namev' => 0, 'noesc' => 0), 'rawblock' => false)
179
     * @expect array(false, array(array('a'), array('b'))) when input array(0,0,0,0,0,0,0,'a  b'), array('flags' => array('strpar' => 0, 'advar' => 0, 'this' => 1, 'namev' => 0, 'noesc' => 0), 'rawblock' => false)
180
     * @expect array(false, array(array('a'), array('"b'), array('c"'))) when input array(0,0,0,0,0,0,0,'a "b c"'), array('flags' => array('strpar' => 0, 'advar' => 0, 'this' => 1, 'namev' => 0, 'noesc' => 0), 'rawblock' => false)
181
     * @expect array(false, array(array('a'), array(-1, '\'b c\''))) when input array(0,0,0,0,0,0,0,'a "b c"'), array('flags' => array('strpar' => 0, 'advar' => 1, 'this' => 1, 'namev' => 0, 'noesc' => 0), 'rawblock' => false)
182
     * @expect array(false, array(array('a'), array('[b'), array('c]'))) when input array(0,0,0,0,0,0,0,'a [b c]'), array('flags' => array('strpar' => 0, 'advar' => 0, 'this' => 1, 'namev' => 0, 'noesc' => 0), 'rawblock' => false)
183
     * @expect array(false, array(array('a'), array('[b'), array('c]'))) when input array(0,0,0,0,0,0,0,'a [b c]'), array('flags' => array('strpar' => 0, 'advar' => 0, 'this' => 1, 'namev' => 1, 'noesc' => 0), 'rawblock' => false)
184
     * @expect array(false, array(array('a'), array('b c'))) when input array(0,0,0,0,0,0,0,'a [b c]'), array('flags' => array('strpar' => 0, 'advar' => 1, 'this' => 1, 'namev' => 0, 'noesc' => 0), 'rawblock' => false)
185
     * @expect array(false, array(array('a'), array('b c'))) when input array(0,0,0,0,0,0,0,'a [b c]'), array('flags' => array('strpar' => 0, 'advar' => 1, 'this' => 1, 'namev' => 1, 'noesc' => 0), 'rawblock' => false)
186
     * @expect array(false, array(array('a'), 'q' => array('b c'))) when input array(0,0,0,0,0,0,0,'a q=[b c]'), array('flags' => array('strpar' => 0, 'advar' => 1, 'this' => 1, 'namev' => 1, 'noesc' => 0), 'rawblock' => false)
187
     * @expect array(false, array(array('a'), array('q=[b c'))) when input array(0,0,0,0,0,0,0,'a [q=[b c]'), array('flags' => array('strpar' => 0, 'advar' => 1, 'this' => 1, 'namev' => 1, 'noesc' => 0), 'rawblock' => false)
188
     * @expect array(false, array(array('a'), 'q' => array('[b'), array('c]'))) when input array(0,0,0,0,0,0,0,'a q=[b c]'), array('flags' => array('strpar' => 0, 'advar' => 0, 'this' => 1, 'namev' => 1, 'noesc' => 0), 'rawblock' => false)
189
     * @expect array(false, array(array('a'), 'q' => array('b'), array('c'))) when input array(0,0,0,0,0,0,0,'a [q]=b c'), array('flags' => array('strpar' => 0, 'advar' => 0, 'this' => 1, 'namev' => 1, 'noesc' => 0), 'rawblock' => false)
190
     * @expect array(false, array(array('a'), 'q' => array(-1, '\'b c\''))) when input array(0,0,0,0,0,0,0,'a q="b c"'), array('flags' => array('strpar' => 0, 'advar' => 1, 'this' => 1, 'namev' => 1, 'noesc' => 0), 'rawblock' => false)
191
     * @expect array(false, array(array(-2, array(array('foo'), array('bar')), '(foo bar)'))) when input array(0,0,0,0,0,0,0,'(foo bar)'), array('flags' => array('strpar' => 0, 'advar' => 1, 'this' => 1, 'namev' => 1, 'noesc' => 0, 'exhlp' => 1, 'lambda' => 0), 'ops' => array('seperator' => ''), 'usedFeature' => array('subexp' => 0), 'rawblock' => false)
192
     * @expect array(false, array(array('foo'), array("'=='"), array('bar'))) when input array(0,0,0,0,0,0,0,"foo '==' bar"), array('flags' => array('strpar' => 0, 'advar' => 1, 'namev' => 1, 'noesc' => 0, 'this' => 0), 'rawblock' => false)
193
     * @expect array(false, array(array(-2, array(array('foo'), array('bar')), '( foo bar)'))) when input array(0,0,0,0,0,0,0,'( foo bar)'), array('flags' => array('strpar' => 0, 'advar' => 1, 'this' => 1, 'namev' => 1, 'noesc' => 0, 'exhlp' => 1, 'lambda' => 0), 'ops' => array('seperator' => ''), 'usedFeature' => array('subexp' => 0), 'rawblock' => false)
194
     * @expect array(false, array(array('a'), array(-1, '\' b c\''))) when input array(0,0,0,0,0,0,0,'a " b c"'), array('flags' => array('strpar' => 0, 'advar' => 1, 'this' => 1, 'namev' => 0, 'noesc' => 0), 'rawblock' => false)
195
     * @expect array(false, array(array('a'), 'q' => array(-1, '\' b c\''))) when input array(0,0,0,0,0,0,0,'a q=" b c"'), array('flags' => array('strpar' => 0, 'advar' => 1, 'this' => 1, 'namev' => 1, 'noesc' => 0), 'rawblock' => false)
196
     * @expect array(false, array(array('foo'), array(-1, "' =='"), array('bar'))) when input array(0,0,0,0,0,0,0,"foo \' ==\' bar"), array('flags' => array('strpar' => 0, 'advar' => 1, 'namev' => 1, 'noesc' => 0, 'this' => 0), 'rawblock' => false)
197
     * @expect array(false, array(array('a'), array(' b c'))) when input array(0,0,0,0,0,0,0,'a [ b c]'), array('flags' => array('strpar' => 0, 'advar' => 1, 'this' => 1, 'namev' => 1, 'noesc' => 0), 'rawblock' => false)
198
     * @expect array(false, array(array('a'), 'q' => array(-1, "' d e'"))) when input array(0,0,0,0,0,0,0,"a q=\' d e\'"), array('flags' => array('strpar' => 0, 'advar' => 1, 'this' => 1, 'namev' => 1, 'noesc' => 0), 'rawblock' => false)
199
     * @expect array(false, array('q' => array(-2, array(array('foo'), array('bar')), '( foo bar)'))) when input array(0,0,0,0,0,0,0,'q=( foo bar)'), array('flags' => array('strpar' => 0, 'advar' => 1, 'this' => 1, 'namev' => 1, 'noesc' => 0, 'exhlp' => 0, 'lambda' => 0), 'usedFeature' => array('subexp' => 0), 'ops' => array('seperator' => 0), 'rawblock' => false)
200
     * @expect array(false, array(array('foo'))) when input array(0,0,0,0,0,0,'>','foo'), array('flags' => array('strpar' => 0, 'advar' => 1, 'this' => 1, 'namev' => 1, 'noesc' => 0, 'exhlp' => 0, 'lambda' => 0), 'usedFeature' => array('subexp' => 0), 'ops' => array('seperator' => 0), 'rawblock' => false)
201
     * @expect array(false, array(array('foo'))) when input array(0,0,0,0,0,0,'>','"foo"'), array('flags' => array('strpar' => 0, 'advar' => 1, 'this' => 1, 'namev' => 1, 'noesc' => 0, 'exhlp' => 0, 'lambda' => 0), 'usedFeature' => array('subexp' => 0), 'ops' => array('seperator' => 0), 'rawblock' => false)
202
     * @expect array(false, array(array('foo'))) when input array(0,0,0,0,0,0,'>','[foo] '), array('flags' => array('strpar' => 0, 'advar' => 1, 'this' => 1, 'namev' => 1, 'noesc' => 0, 'exhlp' => 0, 'lambda' => 0), 'usedFeature' => array('subexp' => 0), 'ops' => array('seperator' => 0), 'rawblock' => false)
203
     * @expect array(false, array(array('foo'))) when input array(0,0,0,0,0,0,'>','\\\'foo\\\''), array('flags' => array('strpar' => 0, 'advar' => 1, 'this' => 1, 'namev' => 1, 'noesc' => 0, 'exhlp' => 0, 'lambda' => 0), 'usedFeature' => array('subexp' => 0), 'ops' => array('seperator' => 0), 'rawblock' => false)
204
     */
205
    public static function parse(&$token, &$context) {
206 651
        $vars = static::analyze($token[static::POS_INNERTAG], $context);
207 651
        if ($token[static::POS_OP] === '>') {
208 651
            $fn = static::getPartialName($vars);
209 76
        } else if ($token[static::POS_OP] === '#*') {
210
            $fn = static::getPartialName($vars, 1);
211
        }
212 651
213
        $avars = static::advancedVariable($vars, $context, static::toString($token));
214 651
215 76
        if (isset($fn) && ($fn !== null)) {
216
            if ($token[static::POS_OP] === '>') {
217
                $avars[0] = $fn;
218 651
            } else if ($token[static::POS_OP] === '#*') {
219
                $avars[1] = $fn;
220
            }
221
        }
222
223
        return array(($token[static::POS_BEGINRAW] === '{') || ($token[static::POS_OP] === '&') || $context['flags']['noesc'] || $context['rawblock'], $avars);
224
    }
225
226
    /**
227
     * Get block params and fix the variable list
228
     *
229 43
     * @param array<boolean|integer|array> $vars parsed token
230 43
     * @param integer $pos position of partial name
231 43
     *
232 43
     * @return array<string>|null Return list of block params or null
0 ignored issues
show
Documentation introduced by
Should the return type not be null|array<string[]|string>?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
233 43
     *
234 21
     */
235 2
    public static function getPartialName(&$vars, $pos = 0) {
236
        if (!isset($vars[$pos])) {
237
            return;
238 43
        }
239
        return preg_match(SafeString::IS_SUBEXP_SEARCH, $vars[$pos]) ? null : array(preg_replace('/^("(.+)")|(\\[(.+)\\])|(\\\\\'(.+)\\\\\')$/', '$2$4$6', $vars[$pos]));
240
    }
241
242
    /**
243
     * Parse a subexpression then return parsed result.
244
     *
245
     * @param string $expression the full string of a sub expression
246
     * @param array<string,array|string|integer> $context current compile context
247
     *
248 359
     * @return array<boolean|integer|array> Return parsed result
0 ignored issues
show
Documentation introduced by
Should the return type not be array<integer|array<bool...|integer|array>|string>?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
249 359
     */
250
    public static function subexpression($expression, &$context) {
251
        $context['usedFeature']['subexp']++;
252
        $vars = static::analyze(substr($expression, 1, -1), $context);
253
        $avars = static::advancedVariable($vars, $context, $expression);
254
        if (isset($avars[0][0]) && !$context['flags']['exhlp']) {
255
            if (!Validator::helper($context, $avars[0][0])) {
256
                $context['error'][] = "Can not find custom helper function defination {$avars[0][0]}() !";
257
            }
258
        }
259
        return array(static::SUBEXP, $avars, $expression);
260
    }
261
262 650
    /**
263 650
     * Check a parsed result is a subexpression or not
264 650
     *
265 650
     * @param array<string|integer|array> $var
266
     *
267 644
     * @return boolean return true when input is a subexpression
268 37
     */
269 37
    public static function isSubExp($var) {
270 37
        return is_array($var) && (count($var) === 3) && ($var[0] === static::SUBEXP) && is_string($var[2]);
271
    }
272
273
    /**
274 644
     * Analyze parsed token for advanved variables.
275 8
     *
276 8
     * @param array<boolean|integer|array> $vars parsed token
277
     * @param array<string,array|string|integer> $context current compile context
278
     * @param string $token original token
279 644
     *
280 438
     * @return array<boolean|integer|array> Return parsed result
281 39
     *
282 1
     */
283
    protected static function advancedVariable($vars, &$context, $token) {
284 39
        $ret = array();
285 39
        $i = 0;
286
        foreach ($vars as $idx => $var) {
287 39
            // handle (...)
1 ignored issue
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
288 7
            if (preg_match(SafeString::IS_SUBEXP_SEARCH, $var)) {
289 7
                $ret[$i] = static::subexpression($var, $context);
290
                $i++;
291
                continue;
292
            }
293
294 644
            // handle |...|
1 ignored issue
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
295
            if (preg_match(SafeString::IS_BLOCKPARAM_SEARCH, $var, $matched)) {
296 453
                $ret[static::BLOCKPARAM] = explode(' ', $matched[1]);
297
                continue;
298 447
            }
299
300 445
            if ($context['flags']['namev']) {
301
                if (preg_match('/^((\\[([^\\]]+)\\])|([^=^["\']+))=(.+)$/', $var, $m)) {
302 453
                    if (!$context['flags']['advar'] && $m[3]) {
303
                        $context['error'][] = "Wrong argument name as '[$m[3]]' in $token ! You should fix your template or compile with LightnCandy::FLAG_ADVARNAME flag.";
304 12
                    }
305
                    $idx = $m[3] ? $m[3] : $m[4];
306 441
                    $var = $m[5];
307
                    // handle foo=(...)
1 ignored issue
show
Unused Code Comprehensibility introduced by
38% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
308
                    if (preg_match(SafeString::IS_SUBEXP_SEARCH, $var)) {
309 441
                        $ret[$idx] = static::subexpression($var, $context);
310 2
                        continue;
311
                    }
312
                }
313
            }
314
315 644
            if ($context['flags']['advar'] && !preg_match("/^(\"|\\\\')(.*)(\"|\\\\')$/", $var)) {
316
                    // foo]  Rule 1: no starting [ or [ not start from head
317 644
                if (preg_match('/^[^\\[\\.]+[\\]\\[]/', $var)
318 33
                    // [bar  Rule 2: no ending ] or ] not in the end
319
                    || preg_match('/[\\[\\]][^\\]\\.]+$/', $var)
320 643
                    // ]bar. Rule 3: middle ] not before .
321 644
                    || preg_match('/\\][^\\]\\[\\.]+\\./', $var)
322
                    // .foo[ Rule 4: middle [ not after .
323
                    || preg_match('/\\.[^\\]\\[\\.]+\\[/', preg_replace('/^(..\\/)+/', '', preg_replace('/\\[[^\\]]+\\]/', '[XXX]', $var)))
324 650
                ) {
325
                    $context['error'][] = "Wrong variable naming as '$var' in $token !";
326
                } else {
327
                    $name = preg_replace('/(\\[.+?\\])/', '', $var);
328
                    // Scan for invalid charactors which not be protected by [ ]
329
                    // now make ( and ) pass, later fix
330
                    if (preg_match('/[!"#%\'*+,;<=>{|}~]/', $name)) {
331
                        $context['error'][] = "Wrong variable naming as '$var' in $token ! You should wrap ! \" # % & ' * + , ; < = > { | } ~ into [ ]";
332
                    }
333
                }
334
            }
335
336 650
            $var = static::getExpression($var, $context, $idx);
337 650
338
            if (is_string($idx)) {
339 650
                $ret[$idx] = $var;
340 466
            } else {
341 466
                $ret[$i] = $var;
342 466
                $i++;
343 466
            }
344
        }
345 466
        return $ret;
346
    }
347 466
348 52
    /**
349 52
     * Analyze a token string and return parsed result.
350 10
     *
351
     * @param string $token preg_match results
352
     * @param array<string,array|string|integer> $context current compile context
353 52
     *
354 52
     * @return array<boolean|integer|array> Return parsed result
355 42
     *
356 42
     */
357 42
    protected static function analyze($token, &$context) {
358 4
        $count = preg_match_all('/(\s*)([^\s]+)/', $token, $matchedall);
359
        // Parse arguments and deal with "..." or [...] or (...) or \'...\' or |...|
1 ignored issue
show
Unused Code Comprehensibility introduced by
46% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
360 42
        if (($count > 0) && $context['flags']['advar']) {
361 1
            $vars = array();
362 1
            $prev = '';
363
            $expect = 0;
364
            $stack = 0;
365 51
366 51
            foreach ($matchedall[2] as $index => $t) {
367 51
                // continue from previous match when expect something
368
                if ($expect) {
369 52
                    $prev .= "{$matchedall[1][$index]}$t";
370
                    if (($stack > 0) && (substr($t, 0, 1) === '(')) {
371
                        $stack++;
372
                    }
373 466
                    // end an argument when end with expected charactor
374 30
                    if (substr($t, -1, 1) === $expect) {
375 30
                        if ($stack > 0) {
376 30
                            preg_match('/(\\)+)$/', $t, $matchedq);
377 30
                            $stack -= isset($matchedq[0]) ? strlen($matchedq[0]) : 1;
378
                            if ($stack > 0) {
379
                                continue;
380
                            }
381 466
                            if ($stack < 0) {
382 6
                                $context['error'][] = "Unexcepted ')' in expression '$token' !!";
383 6
                                break;
384 6
                            }
385
                        }
386
                        $vars[] = $prev;
387
                        $prev = '';
388 465
                        $expect = 0;
389 6
                    }
390 6
                    continue;
391 6
                }
392
393
                // continue to next match when begin with '(' without ending ')'
394
                if (preg_match('/^\([^\)]*$/', $t)) {
395 464
                    $prev = $t;
396 2
                    $expect = ')';
397 2
                    $stack=1;
398 2
                    continue;
399
                }
400
401
                // continue to next match when begin with '"' without ending '"'
402 464
                if (preg_match('/^"[^"]*$/', $t)) {
403 9
                    $prev = $t;
404 9
                    $expect = '"';
405 9
                    continue;
406
                }
407
408
                // continue to next match when begin with \' without ending '
409 456
                if (preg_match('/^\\\\\'[^\']*$/', $t)) {
410 1
                    $prev = $t;
411 1
                    $expect = '\'';
412 1
                    continue;
413
                }
414
415
                // continue to next match when '="' exists without ending '"'
416 456
                if (preg_match('/^[^"]*="[^"]*$/', $t)) {
417 5
                    $prev = $t;
418 5
                    $expect = '"';
419 5
                    continue;
420 5
                }
421
422
                // continue to next match when '[' exists without ending ']'
423
                if (preg_match('/^([^"\'].+)?\\[[^\\]]*$/', $t)) {
424 456
                    $prev = $t;
425 8
                    $expect = ']';
426 8
                    continue;
427 8
                }
428 8
429
                // continue to next match when =\' exists without ending '
430
                if (preg_match('/^[^\']*=\\\\\'[^\']*$/', $t)) {
431 456
                    $prev = $t;
432
                    $expect = '\'';
433 466
                    continue;
434
                }
435 207
436
                // continue to next match when =( exists without ending )
437
                if (preg_match('/.+\([^\)]*$/', $t)) {
438
                    $prev = $t;
439
                    $expect = ')';
440
                    $stack=1;
441
                    continue;
442
                }
443
444
                // continue to next match when 'as' without ending '|'
445
                if (($t === 'as') && (count($vars) > 0)) {
446
                    $prev = '';
447
                    $expect = '|';
448
                    $stack=1;
449
                    continue;
450
                }
451
452
                $vars[] = $t;
453
            }
454
            return $vars;
455
        }
456
        return ($count > 0) ? $matchedall[2] : explode(' ', $token);
457
    }
458
}
459
460