Complex classes like Parser often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use Parser, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
25 | class Parser extends Token |
||
26 | { |
||
27 | // Compile time error handling flags |
||
28 | const BLOCKPARAM = 9999; |
||
29 | const PARTIALBLOCK = 9998; |
||
30 | const LITERAL = -1; |
||
31 | const SUBEXP = -2; |
||
32 | |||
33 | /** |
||
34 | * Get partial block id and fix the variable list |
||
35 | * |
||
36 | * @param array<boolean|integer|string|array> $vars parsed token |
||
37 | * |
||
38 | * @return integer Return partial block id |
||
|
|||
39 | * |
||
40 | */ |
||
41 | 110 | public static function getPartialBlock(&$vars) |
|
50 | |||
51 | /** |
||
52 | * Get block params and fix the variable list |
||
53 | * |
||
54 | * @param array<boolean|integer|string|array> $vars parsed token |
||
55 | * |
||
56 | * @return array<string>|null Return list of block params or null |
||
57 | * |
||
58 | */ |
||
59 | 243 | public static function getBlockParams(&$vars) |
|
67 | |||
68 | /** |
||
69 | * Return array presentation for a literal |
||
70 | * |
||
71 | * @param string $name variable name. |
||
72 | * @param boolean $asis keep the name as is or not |
||
73 | * @param boolean $quote add single quote or not |
||
74 | * |
||
75 | * @return array<integer|string> Return variable name array |
||
76 | * |
||
77 | */ |
||
78 | 124 | protected static function getLiteral($name, $asis, $quote = false) |
|
82 | |||
83 | /** |
||
84 | * Return array presentation for an expression |
||
85 | * |
||
86 | * @param string $v analyzed expression names. |
||
87 | * @param array<string,array|string|integer> $context Current compile content. |
||
88 | * @param integer $pos expression position |
||
89 | * |
||
90 | * @return array<integer,string> Return variable name array |
||
91 | * |
||
92 | * @expect array('this') when input 'this', array('flags' => array('strpar' => 0, 'advar' => 0, 'this' => 0)), 0 |
||
93 | * @expect array() when input 'this', array('flags' => array('strpar' => 0, 'advar' => 0, 'this' => 1)), 0 |
||
94 | * @expect array(1) when input '..', array('flags' => array('strpar' => 0, 'advar' => 0, 'this' => 1, 'parent' => 1), 'usedFeature' => array('parent' => 0)), 0 |
||
95 | * @expect array(1) when input '../', array('flags' => array('strpar' => 0, 'advar' => 0, 'this' => 1, 'parent' => 1), 'usedFeature' => array('parent' => 0)), 0 |
||
96 | * @expect array(1) when input '../.', array('flags' => array('strpar' => 0, 'advar' => 0, 'this' => 1, 'parent' => 1), 'usedFeature' => array('parent' => 0)), 0 |
||
97 | * @expect array(1) when input '../this', array('flags' => array('strpar' => 0, 'advar' => 0, 'this' => 1, 'parent' => 1), 'usedFeature' => array('parent' => 0)), 0 |
||
98 | * @expect array(1, 'a') when input '../a', array('flags' => array('strpar' => 0, 'advar' => 0, 'this' => 1, 'parent' => 1), 'usedFeature' => array('parent' => 0)), 0 |
||
99 | * @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 |
||
100 | * @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 |
||
101 | * @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 |
||
102 | * @expect array(0, 'id') when input 'this.id', array('flags' => array('strpar' => 0, 'advar' => 1, 'this' => 1, 'parent' => 1), 'usedFeature' => array('parent' => 0)), 0 |
||
103 | * @expect array('this', 'id') when input 'this.id', array('flags' => array('strpar' => 0, 'advar' => 1, 'this' => 0, 'parent' => 1), 'usedFeature' => array('parent' => 0)), 0 |
||
104 | * @expect array(0, 'id') when input './id', array('flags' => array('strpar' => 0, 'advar' => 1, 'this' => 0, 'parent' => 1), 'usedFeature' => array('parent' => 0)), 0 |
||
105 | * @expect array(\LightnCandy\Parser::LITERAL, '\'a.b\'') when input '"a.b"', array('flags' => array('strpar' => 0, 'advar' => 1, 'this' => 0, 'parent' => 1), 'usedFeature' => array('parent' => 0)), 1 |
||
106 | * @expect array(\LightnCandy\Parser::LITERAL, '123') when input '123', array('flags' => array('strpar' => 0, 'advar' => 1, 'this' => 0, 'parent' => 1), 'usedFeature' => array('parent' => 0)), 1 |
||
107 | * @expect array(\LightnCandy\Parser::LITERAL, 'null') when input 'null', array('flags' => array('strpar' => 0, 'advar' => 1, 'this' => 0, 'parent' => 1), 'usedFeature' => array('parent' => 0)), 1 |
||
108 | */ |
||
109 | 738 | protected static function getExpression($v, &$context, $pos) |
|
192 | |||
193 | /** |
||
194 | * Parse the token and return parsed result. |
||
195 | * |
||
196 | * @param array<string> $token preg_match results |
||
197 | * @param array<string,array|string|integer> $context current compile context |
||
198 | * |
||
199 | * @return array<boolean|integer|array> Return parsed result |
||
200 | * |
||
201 | * @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) |
||
202 | * @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) |
||
203 | * @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) |
||
204 | * @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) |
||
205 | * @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) |
||
206 | * @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) |
||
207 | * @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) |
||
208 | * @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) |
||
209 | * @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) |
||
210 | * @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) |
||
211 | * @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) |
||
212 | * @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) |
||
213 | * @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) |
||
214 | * @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) |
||
215 | * @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) |
||
216 | * @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) |
||
217 | * @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) |
||
218 | * @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) |
||
219 | * @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) |
||
220 | * @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) |
||
221 | * @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) |
||
222 | * @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) |
||
223 | * @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) |
||
224 | * @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) |
||
225 | * @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, 'helperresolver' => 0) |
||
226 | * @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) |
||
227 | * @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) |
||
228 | * @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) |
||
229 | * @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) |
||
230 | */ |
||
231 | 744 | public static function parse(&$token, &$context) |
|
252 | |||
253 | /** |
||
254 | * Get partial name from "foo" or [foo] or \'foo\' |
||
255 | * |
||
256 | * @param array<boolean|integer|array> $vars parsed token |
||
257 | * @param integer $pos position of partial name |
||
258 | * |
||
259 | * @return array<string>|null Return one element partial name array |
||
260 | * |
||
261 | * @expect null when input array() |
||
262 | * @expect array('foo') when input array('foo') |
||
263 | * @expect array('foo') when input array('"foo"') |
||
264 | * @expect array('foo') when input array('[foo]') |
||
265 | * @expect array('foo') when input array("\\'foo\\'") |
||
266 | * @expect array('foo') when input array(0, 'foo'), 1 |
||
267 | */ |
||
268 | 114 | public static function getPartialName(&$vars, $pos = 0) |
|
275 | |||
276 | /** |
||
277 | * Parse a subexpression then return parsed result. |
||
278 | * |
||
279 | * @param string $expression the full string of a sub expression |
||
280 | * @param array<string,array|string|integer> $context current compile context |
||
281 | * |
||
282 | * @return array<boolean|integer|array> Return parsed result |
||
283 | * |
||
284 | * @expect array(\LightnCandy\Parser::SUBEXP, array(array('a'), array('b')), '(a b)') when input '(a b)', array('usedFeature' => array('subexp' => 0), 'flags' => array('advar' => 0, 'namev' => 0, 'this' => 0, 'exhlp' => 1, 'strpar' => 0)) |
||
285 | */ |
||
286 | 49 | public static function subexpression($expression, &$context) |
|
298 | |||
299 | /** |
||
300 | * Check a parsed result is a subexpression or not |
||
301 | * |
||
302 | * @param array<string|integer|array> $var |
||
303 | * |
||
304 | * @return boolean return true when input is a subexpression |
||
305 | * |
||
306 | * @expect false when input 0 |
||
307 | * @expect false when input array() |
||
308 | * @expect false when input array(\LightnCandy\Parser::SUBEXP, 0) |
||
309 | * @expect false when input array(\LightnCandy\Parser::SUBEXP, 0, 0) |
||
310 | * @expect false when input array(\LightnCandy\Parser::SUBEXP, 0, '', 0) |
||
311 | * @expect true when input array(\LightnCandy\Parser::SUBEXP, 0, '') |
||
312 | */ |
||
313 | 435 | public static function isSubExp($var) |
|
317 | |||
318 | /** |
||
319 | * Analyze parsed token for advanved variables. |
||
320 | * |
||
321 | * @param array<boolean|integer|array> $vars parsed token |
||
322 | * @param array<string,array|string|integer> $context current compile context |
||
323 | * @param string $token original token |
||
324 | * |
||
325 | * @return array<boolean|integer|array> Return parsed result |
||
326 | * |
||
327 | * @expect array(array('this')) when input array('this'), array('flags' => array('advar' => 1, 'namev' => 1, 'this' => 0,)), 0 |
||
328 | * @expect array(array()) when input array('this'), array('flags' => array('advar' => 1, 'namev' => 1, 'this' => 1)), 0 |
||
329 | * @expect array(array('a')) when input array('a'), array('flags' => array('advar' => 1, 'namev' => 1, 'this' => 0, 'strpar' => 0)), 0 |
||
330 | * @expect array(array('a'), array('b')) when input array('a', 'b'), array('flags' => array('advar' => 1, 'namev' => 1, 'this' => 0, 'strpar' => 0)), 0 |
||
331 | * @expect array('a' => array('b')) when input array('a=b'), array('flags' => array('advar' => 1, 'namev' => 1, 'this' => 0, 'strpar' => 0)), 0 |
||
332 | * @expect array('fo o' => array(\LightnCandy\Parser::LITERAL, '123')) when input array('[fo o]=123'), array('flags' => array('advar' => 1, 'namev' => 1, 'this' => 0)), 0 |
||
333 | * @expect array('fo o' => array(\LightnCandy\Parser::LITERAL, '\'bar\'')) when input array('[fo o]="bar"'), array('flags' => array('advar' => 1, 'namev' => 1, 'this' => 0)), 0 |
||
334 | */ |
||
335 | 744 | protected static function advancedVariable($vars, &$context, $token) |
|
404 | |||
405 | /** |
||
406 | * Detect quote charactors |
||
407 | * |
||
408 | * @param string $string the string to be detect the quote charactors |
||
409 | * |
||
410 | * @return array<string,integer>|null Expected ending string when quote charactor be detected |
||
411 | */ |
||
412 | 533 | protected static function detectQuote($string) |
|
449 | |||
450 | /** |
||
451 | * Analyze a token string and return parsed result. |
||
452 | * |
||
453 | * @param string $token preg_match results |
||
454 | * @param array<string,array|string|integer> $context current compile context |
||
455 | * |
||
456 | * @return array<boolean|integer|array> Return parsed result |
||
457 | * |
||
458 | * @expect array('foo', 'bar') when input 'foo bar', array('flags' => array('advar' => 1)) |
||
459 | * @expect array('foo', "'bar'") when input "foo 'bar'", array('flags' => array('advar' => 1)) |
||
460 | * @expect array('[fo o]', '"bar"') when input '[fo o] "bar"', array('flags' => array('advar' => 1)) |
||
461 | * @expect array('fo=123', 'bar="45', '6"') when input 'fo=123 bar="45 6"', array('flags' => array('advar' => 0)) |
||
462 | * @expect array('fo=123', 'bar="45 6"') when input 'fo=123 bar="45 6"', array('flags' => array('advar' => 1)) |
||
463 | * @expect array('[fo', 'o]=123') when input '[fo o]=123', array('flags' => array('advar' => 0)) |
||
464 | * @expect array('[fo o]=123') when input '[fo o]=123', array('flags' => array('advar' => 1)) |
||
465 | * @expect array('[fo o]=123', 'bar="456"') when input '[fo o]=123 bar="456"', array('flags' => array('advar' => 1)) |
||
466 | * @expect array('[fo o]="1 2 3"') when input '[fo o]="1 2 3"', array('flags' => array('advar' => 1)) |
||
467 | * @expect array('foo', 'a=(foo a=(foo a="ok"))') when input 'foo a=(foo a=(foo a="ok"))', array('flags' => array('advar' => 1)) |
||
468 | */ |
||
469 | 744 | protected static function analyze($token, &$context) |
|
552 | } |
||
553 |
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[]
orarray<String>
.