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\ConfigurablePassTrait; |
10
|
|
|
use PHPSA\Analyzer\Pass; |
11
|
|
|
use PHPSA\Context; |
12
|
|
|
|
13
|
|
|
class MissingBreakStatement implements Pass\ConfigurablePassInterface, Pass\AnalyzerPassInterface |
14
|
|
|
{ |
15
|
|
|
use ConfigurablePassTrait; |
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
|
|
|
|
26
|
|
|
/** @var Stmt\Case_ $case */ |
27
|
1 |
|
foreach ($switchStmt->cases as $case) { |
28
|
1 |
|
$result = $this->checkCaseStatement($case, $context) || $result; |
29
|
1 |
|
} |
30
|
|
|
|
31
|
1 |
|
return $result; |
32
|
|
|
} |
33
|
|
|
|
34
|
|
|
/** |
35
|
|
|
* @return array |
36
|
|
|
*/ |
37
|
1 |
|
public function getRegister() |
38
|
|
|
{ |
39
|
|
|
return [ |
40
|
|
|
Stmt\Switch_::class |
41
|
1 |
|
]; |
42
|
|
|
} |
43
|
|
|
|
44
|
|
|
/** |
45
|
|
|
* @param Stmt\Case_ $case |
46
|
|
|
* @param Context $context |
47
|
|
|
* @return bool |
48
|
|
|
*/ |
49
|
1 |
|
private function checkCaseStatement(Stmt\Case_ $case, Context $context) |
50
|
|
|
{ |
51
|
|
|
/* |
52
|
|
|
* switch(…) { |
53
|
|
|
* case 41: |
54
|
|
|
* case 42: |
55
|
|
|
* case 43: |
56
|
|
|
* return 'the truth, or almost.'; |
57
|
|
|
* } |
58
|
|
|
*/ |
59
|
1 |
|
if (!$case->stmts) { |
|
|
|
|
60
|
1 |
|
return false; |
61
|
|
|
} |
62
|
|
|
|
63
|
1 |
|
foreach ($case->stmts as $node) { |
64
|
|
|
// look for a break statement |
65
|
1 |
|
if ($node instanceof Stmt\Break_) { |
66
|
1 |
|
return false; |
67
|
|
|
} |
68
|
|
|
|
69
|
|
|
// or for a return |
70
|
1 |
|
if ($node instanceof Stmt\Return_) { |
71
|
|
|
// but emit a notice if it's empty. |
72
|
1 |
|
if (!$node->expr) { |
73
|
1 |
|
$context->notice( |
74
|
1 |
|
'missing_break_statement', |
75
|
1 |
|
'Empty return in "case" statement', |
76
|
|
|
$node |
77
|
1 |
|
); |
78
|
1 |
|
return true; |
79
|
|
|
} |
80
|
|
|
|
81
|
1 |
|
return false; |
82
|
|
|
} |
83
|
1 |
|
} |
84
|
|
|
|
85
|
1 |
|
$context->notice( |
86
|
1 |
|
'missing_break_statement', |
87
|
1 |
|
'Missing "break" statement', |
88
|
|
|
$case |
89
|
1 |
|
); |
90
|
|
|
|
91
|
1 |
|
return true; |
92
|
|
|
} |
93
|
|
|
} |
94
|
|
|
|
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.