1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* @author Kévin Gomez https://github.com/K-Phoen <[email protected]> |
4
|
|
|
*/ |
5
|
|
|
|
6
|
|
|
namespace PHPSA\Analyzer\Pass\Statement; |
7
|
|
|
|
8
|
|
|
use PhpParser\Node\Stmt; |
9
|
|
|
use PHPSA\Analyzer\Helper\DefaultMetadataPassTrait; |
10
|
|
|
use PHPSA\Analyzer\Pass; |
11
|
|
|
use PHPSA\Context; |
12
|
|
|
|
13
|
|
|
class MissingBreakStatement implements Pass\AnalyzerPassInterface |
14
|
|
|
{ |
15
|
|
|
use DefaultMetadataPassTrait; |
16
|
|
|
|
17
|
|
|
/** |
18
|
|
|
* @param Stmt\Switch_ $switchStmt |
19
|
|
|
* @param Context $context |
20
|
|
|
* @return bool |
21
|
|
|
*/ |
22
|
1 |
|
public function pass(Stmt\Switch_ $switchStmt, Context $context) |
23
|
|
|
{ |
24
|
1 |
|
$result = false; |
25
|
1 |
|
$caseStmts = $switchStmt->cases; |
26
|
|
|
|
27
|
1 |
|
if (count($caseStmts) < 2) { |
28
|
|
|
return $result; |
29
|
|
|
} |
30
|
|
|
|
31
|
1 |
|
array_pop($caseStmts); // the last case statement CAN have no "break" or "return" |
32
|
|
|
|
33
|
|
|
/** @var Stmt\Case_ $case */ |
34
|
1 |
|
foreach ($caseStmts as $case) { |
35
|
1 |
|
$result = $this->checkCaseStatement($case, $context) || $result; |
36
|
1 |
|
} |
37
|
|
|
|
38
|
1 |
|
return $result; |
39
|
|
|
} |
40
|
|
|
|
41
|
|
|
/** |
42
|
|
|
* @return array |
43
|
|
|
*/ |
44
|
1 |
|
public function getRegister() |
45
|
|
|
{ |
46
|
|
|
return [ |
47
|
|
|
Stmt\Switch_::class |
48
|
1 |
|
]; |
49
|
|
|
} |
50
|
|
|
|
51
|
|
|
/** |
52
|
|
|
* @param Stmt\Case_ $case |
53
|
|
|
* @param Context $context |
54
|
|
|
* @return bool |
55
|
|
|
*/ |
56
|
1 |
|
private function checkCaseStatement(Stmt\Case_ $case, Context $context) |
57
|
|
|
{ |
58
|
|
|
/* |
59
|
|
|
* switch(…) { |
60
|
|
|
* case 41: |
61
|
|
|
* case 42: |
62
|
|
|
* case 43: |
63
|
|
|
* return 'the truth, or almost.'; |
64
|
|
|
* } |
65
|
|
|
*/ |
66
|
1 |
|
if (!$case->stmts) { |
|
|
|
|
67
|
1 |
|
return false; |
68
|
|
|
} |
69
|
|
|
|
70
|
1 |
|
foreach ($case->stmts as $node) { |
71
|
|
|
// look for a break statement |
72
|
1 |
|
if ($node instanceof Stmt\Break_) { |
73
|
1 |
|
return false; |
74
|
|
|
} |
75
|
|
|
|
76
|
|
|
// or for a return |
77
|
1 |
|
if ($node instanceof Stmt\Return_) { |
78
|
1 |
|
return false; |
79
|
|
|
} |
80
|
1 |
|
} |
81
|
|
|
|
82
|
1 |
|
$context->notice( |
83
|
1 |
|
'missing_break_statement', |
84
|
1 |
|
'Missing "break" statement', |
85
|
|
|
$case |
86
|
1 |
|
); |
87
|
|
|
|
88
|
1 |
|
return true; |
89
|
|
|
} |
90
|
|
|
} |
91
|
|
|
|
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.