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 ( 178f3d...f4df6d )
by Zordius
02:49
created

Parser::getPartialName()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 3.1406

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 6
ccs 3
cts 4
cp 0.75
rs 9.4286
cc 3
eloc 4
nc 3
nop 2
crap 3.1406
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 198
    public static function getBlockParams(&$vars) {
45 198
        if (isset($vars[static::BLOCKPARAM])) {
46 8
            $list = $vars[static::BLOCKPARAM];
47 8
            unset($vars[static::BLOCKPARAM]);
48 8
            return $list;
49
        }
50 193
    }
51
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 102
    protected static function getLiteral($name, $asis, $quote = false) {
63 102
        return $asis ? array($name) : array(static::LITERAL, $quote ? "'$name'" : $name);
64
    }
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 655
    protected static function getExpression($v, &$context, $pos) {
92 655
        $asis = ($pos === 0);
93
94
        // handle number
95 655
        if (is_numeric($v)) {
96 29
            return static::getLiteral(strval(1 * $v), $asis);
97
        }
98
99
        // handle double quoted string
100 650
        if (preg_match('/^"(.*)"$/', $v, $matched)) {
101 53
            return static::getLiteral(preg_replace('/([^\\\\])\\\\\\\\"/', '$1"', preg_replace('/^\\\\\\\\"/', '"', $matched[1])), $asis, true);
102
        }
103
104
        // handle single quoted string
105 644
        if (preg_match('/^\\\\\'(.*)\\\\\'$/', $v, $matched)) {
106 21
            return static::getLiteral($matched[1], $asis, true);
107
        }
108
109
        // handle boolean, null and undefined
110 641
        if (preg_match('/^(true|false|null|undefined)$/', $v)) {
111 29
            return static::getLiteral($v, $asis);
112
        }
113
114 636
        $ret = array();
115 636
        $levels = 0;
116
117
        // handle ..
118 636
        if ($v === '..') {
119 6
            $v = '../';
120
        }
121
122
        // Trace to parent for ../ N times
123 636
        $v = preg_replace_callback('/\\.\\.\\//', function() use (&$levels) {
124 46
            $levels++;
125 46
            return '';
126 636
        }, trim($v));
127
128
        // remove ./ in path
129 636
        $v = preg_replace('/\\.\\//', '', $v, -1, $scoped);
130
131 636
        $strp = (($pos !== 0) && $context['flags']['strpar']);
132 636
        if ($levels && !$strp) {
133 43
            $ret[] = $levels;
134 43
            if (!$context['flags']['parent']) {
135 4
                $context['error'][] = 'Do not support {{../var}}, you should do compile with LightnCandy::FLAG_PARENT flag';
136
            }
137 43
            $context['usedFeature']['parent'] ++;
138
        }
139
140 636
        if ($context['flags']['advar'] && preg_match('/\\]/', $v)) {
141 31
            preg_match_all(static::VARNAME_SEARCH, $v, $matchedall);
142
        } else {
143 611
            preg_match_all('/([^\\.\\/]+)/', $v, $matchedall);
144
        }
145
146 636
        foreach ($matchedall[1] as $m) {
147 629
            if ($context['flags']['advar'] && substr($m, 0, 1) === '[') {
148 25
                $ret[] = substr($m, 1, -1);
149 622
            } else if ((!$context['flags']['this'] || ($m !== 'this')) && ($m !== '.')) {
150 620
                $ret[] = $m;
151
            } else {
152 629
                $scoped++;
153
            }
154
        }
155
156 636
        if ($strp) {
157 10
            return array(static::LITERAL, "'" . implode('.', $ret) . "'");
158
        }
159
160 636
        if (($scoped > 0) && ($levels === 0) && (count($ret) > 0)) {
161 9
            array_unshift($ret, 0);
162
        }
163
164 636
        return $ret;
165
    }
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 661
    public static function parse(&$token, &$context) {
206 661
        $vars = static::analyze($token[static::POS_INNERTAG], $context);
207 661
        if ($token[static::POS_OP] === '>') {
208 85
            $fn = static::getPartialName($vars);
209 636
        } else if ($token[static::POS_OP] === '#*') {
210 8
            $fn = static::getPartialName($vars, 1);
211
        }
212
213 661
        $avars = static::advancedVariable($vars, $context, static::toString($token));
214
215 661
        if (isset($fn) && ($fn !== null)) {
216 80
            if ($token[static::POS_OP] === '>') {
217 80
                $avars[0] = $fn;
218 8
            } else if ($token[static::POS_OP] === '#*') {
219 8
                $avars[1] = $fn;
220
            }
221
        }
222
223 661
        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
     * @param array<boolean|integer|array> $vars parsed token
230
     * @param integer $pos position of partial name
231
     *
232
     * @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
     *
234
     */
235 84
    public static function getPartialName(&$vars, $pos = 0) {
236 84
        if (!isset($vars[$pos])) {
237
            return;
238
        }
239 84
        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
     * @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
     */
250 43
    public static function subexpression($expression, &$context) {
251 43
        $context['usedFeature']['subexp']++;
252 43
        $vars = static::analyze(substr($expression, 1, -1), $context);
253 43
        $avars = static::advancedVariable($vars, $context, $expression);
254 43
        if (isset($avars[0][0]) && !$context['flags']['exhlp']) {
255 21
            if (!Validator::helper($context, $avars[0][0])) {
256 2
                $context['error'][] = "Can not find custom helper function defination {$avars[0][0]}() !";
257
            }
258
        }
259 43
        return array(static::SUBEXP, $avars, $expression);
260
    }
261
262
    /**
263
     * Check a parsed result is a subexpression or not
264
     *
265
     * @param array<string|integer|array> $var
266
     *
267
     * @return boolean return true when input is a subexpression
268
     */
269 369
    public static function isSubExp($var) {
270 369
        return is_array($var) && (count($var) === 3) && ($var[0] === static::SUBEXP) && is_string($var[2]);
271
    }
272
273
    /**
274
     * Analyze parsed token for advanved variables.
275
     *
276
     * @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
     *
280
     * @return array<boolean|integer|array> Return parsed result
281
     *
282
     */
283 660
    protected static function advancedVariable($vars, &$context, $token) {
284 660
        $ret = array();
285 660
        $i = 0;
286 660
        foreach ($vars as $idx => $var) {
287
            // 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 654
            if (preg_match(SafeString::IS_SUBEXP_SEARCH, $var)) {
289 37
                $ret[$i] = static::subexpression($var, $context);
290 37
                $i++;
291 37
                continue;
292
            }
293
294
            // 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 654
            if (preg_match(SafeString::IS_BLOCKPARAM_SEARCH, $var, $matched)) {
296 8
                $ret[static::BLOCKPARAM] = explode(' ', $matched[1]);
297 8
                continue;
298
            }
299
300 654
            if ($context['flags']['namev']) {
301 448
                if (preg_match('/^((\\[([^\\]]+)\\])|([^=^["\']+))=(.+)$/', $var, $m)) {
302 39
                    if (!$context['flags']['advar'] && $m[3]) {
303 1
                        $context['error'][] = "Wrong argument name as '[$m[3]]' in $token ! You should fix your template or compile with LightnCandy::FLAG_ADVARNAME flag.";
304
                    }
305 39
                    $idx = $m[3] ? $m[3] : $m[4];
306 39
                    $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 39
                    if (preg_match(SafeString::IS_SUBEXP_SEARCH, $var)) {
309 7
                        $ret[$idx] = static::subexpression($var, $context);
310 7
                        continue;
311
                    }
312
                }
313
            }
314
315 654
            if ($context['flags']['advar'] && !preg_match("/^(\"|\\\\')(.*)(\"|\\\\')$/", $var)) {
316
                    // foo]  Rule 1: no starting [ or [ not start from head
317 463
                if (preg_match('/^[^\\[\\.]+[\\]\\[]/', $var)
318
                    // [bar  Rule 2: no ending ] or ] not in the end
319 457
                    || preg_match('/[\\[\\]][^\\]\\.]+$/', $var)
320
                    // ]bar. Rule 3: middle ] not before .
321 455
                    || preg_match('/\\][^\\]\\[\\.]+\\./', $var)
322
                    // .foo[ Rule 4: middle [ not after .
323 463
                    || preg_match('/\\.[^\\]\\[\\.]+\\[/', preg_replace('/^(..\\/)+/', '', preg_replace('/\\[[^\\]]+\\]/', '[XXX]', $var)))
324
                ) {
325 12
                    $context['error'][] = "Wrong variable naming as '$var' in $token !";
326
                } else {
327 451
                    $name = preg_replace('/(\\[.+?\\])/', '', $var);
328
                    // Scan for invalid charactors which not be protected by [ ]
329
                    // now make ( and ) pass, later fix
330 451
                    if (preg_match('/[!"#%\'*+,;<=>{|}~]/', $name)) {
331 2
                        $context['error'][] = "Wrong variable naming as '$var' in $token ! You should wrap ! \" # % & ' * + , ; < = > { | } ~ into [ ]";
332
                    }
333
                }
334
            }
335
336 654
            $var = static::getExpression($var, $context, $idx);
337
338 654
            if (is_string($idx)) {
339 33
                $ret[$idx] = $var;
340
            } else {
341 653
                $ret[$i] = $var;
342 654
                $i++;
343
            }
344
        }
345 660
        return $ret;
346
    }
347
348
    /**
349
     * Analyze a token string and return parsed result.
350
     *
351
     * @param string $token preg_match results
352
     * @param array<string,array|string|integer> $context current compile context
353
     *
354
     * @return array<boolean|integer|array> Return parsed result
355
     *
356
     */
357 660
    protected static function analyze($token, &$context) {
358 660
        $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 660
        if (($count > 0) && $context['flags']['advar']) {
361 476
            $vars = array();
362 476
            $prev = '';
363 476
            $expect = 0;
364 476
            $stack = 0;
365
366 476
            foreach ($matchedall[2] as $index => $t) {
367
                // continue from previous match when expect something
368 476
                if ($expect) {
369 52
                    $prev .= "{$matchedall[1][$index]}$t";
370 52
                    if (($stack > 0) && (substr($t, 0, 1) === '(')) {
371 10
                        $stack++;
372
                    }
373
                    // end an argument when end with expected charactor
374 52
                    if (substr($t, -1, 1) === $expect) {
375 52
                        if ($stack > 0) {
376 42
                            preg_match('/(\\)+)$/', $t, $matchedq);
377 42
                            $stack -= isset($matchedq[0]) ? strlen($matchedq[0]) : 1;
378 42
                            if ($stack > 0) {
379 4
                                continue;
380
                            }
381 42
                            if ($stack < 0) {
382 1
                                $context['error'][] = "Unexcepted ')' in expression '$token' !!";
383 1
                                break;
384
                            }
385
                        }
386 51
                        $vars[] = $prev;
387 51
                        $prev = '';
388 51
                        $expect = 0;
389
                    }
390 52
                    continue;
391
                }
392
393
                // continue to next match when begin with '(' without ending ')'
394 476
                if (preg_match('/^\([^\)]*$/', $t)) {
395 30
                    $prev = $t;
396 30
                    $expect = ')';
397 30
                    $stack=1;
398 30
                    continue;
399
                }
400
401
                // continue to next match when begin with '"' without ending '"'
402 476
                if (preg_match('/^"[^"]*$/', $t)) {
403 6
                    $prev = $t;
404 6
                    $expect = '"';
405 6
                    continue;
406
                }
407
408
                // continue to next match when begin with \' without ending '
409 475
                if (preg_match('/^\\\\\'[^\']*$/', $t)) {
410 6
                    $prev = $t;
411 6
                    $expect = '\'';
412 6
                    continue;
413
                }
414
415
                // continue to next match when '="' exists without ending '"'
416 474
                if (preg_match('/^[^"]*="[^"]*$/', $t)) {
417 2
                    $prev = $t;
418 2
                    $expect = '"';
419 2
                    continue;
420
                }
421
422
                // continue to next match when '[' exists without ending ']'
423 474
                if (preg_match('/^([^"\'].+)?\\[[^\\]]*$/', $t)) {
424 9
                    $prev = $t;
425 9
                    $expect = ']';
426 9
                    continue;
427
                }
428
429
                // continue to next match when =\' exists without ending '
430 466
                if (preg_match('/^[^\']*=\\\\\'[^\']*$/', $t)) {
431 1
                    $prev = $t;
432 1
                    $expect = '\'';
433 1
                    continue;
434
                }
435
436
                // continue to next match when =( exists without ending )
437 466
                if (preg_match('/.+\([^\)]*$/', $t)) {
438 5
                    $prev = $t;
439 5
                    $expect = ')';
440 5
                    $stack=1;
441 5
                    continue;
442
                }
443
444
                // continue to next match when 'as' without ending '|'
445 466
                if (($t === 'as') && (count($vars) > 0)) {
446 8
                    $prev = '';
447 8
                    $expect = '|';
448 8
                    $stack=1;
449 8
                    continue;
450
                }
451
452 466
                $vars[] = $t;
453
            }
454 476
            return $vars;
455
        }
456 207
        return ($count > 0) ? $matchedall[2] : explode(' ', $token);
457
    }
458
}
459
460