MissingBreakStatement   A
last analyzed

Complexity

Total Complexity 13

Size/Duplication

Total Lines 82
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
dl 0
loc 82
ccs 0
cts 27
cp 0
rs 10
c 0
b 0
f 0
wmc 13
lcom 1
cbo 4

3 Methods

Rating   Name   Duplication   Size   Complexity  
A pass() 0 18 4
A getRegister() 0 6 1
B checkCaseStatement() 0 36 8
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
    const DESCRIPTION = 'Checks for a missing break or return statement in switch cases. Can ignore empty cases and the last case.';
18
19
    /**
20
     * @param Stmt\Switch_ $switchStmt
21
     * @param Context $context
22
     * @return bool
23
     */
24
    public function pass(Stmt\Switch_ $switchStmt, Context $context)
25
    {
26
        $result = false;
27
        $caseStmts = $switchStmt->cases;
28
29
        if (count($caseStmts) < 2) {
30
            return $result;
31
        }
32
33
        array_pop($caseStmts); // the last case statement CAN have no "break" or "return"
34
35
        /** @var Stmt\Case_ $case */
36
        foreach ($caseStmts as $case) {
37
            $result = $this->checkCaseStatement($case, $context) || $result;
38
        }
39
40
        return $result;
41
    }
42
43
    /**
44
     * @return array
45
     */
46
    public function getRegister()
47
    {
48
        return [
49
            Stmt\Switch_::class
50
        ];
51
    }
52
53
    /**
54
     * @param Stmt\Case_ $case
55
     * @param Context $context
56
     * @return bool
57
     */
58
    private function checkCaseStatement(Stmt\Case_ $case, Context $context)
59
    {
60
        /*
61
         * switch(…) {
62
         *     case 41:
63
         *     case 42:
64
         *     case 43:
65
         *         return 'the truth, or almost.';
66
         * }
67
         */
68
        if ($case->stmts === null) {
69
            return false;
70
        }
71
72
        $stmt = end($case->stmts);
73
        while ($stmt !== false) {
74
            if ($stmt instanceof Stmt\Break_ || $stmt instanceof Stmt\Return_
75
            || $stmt instanceof Stmt\Throw_ || $stmt instanceof Stmt\Continue_) {
76
                break;
77
            }
78
79
            if (!$stmt instanceof Stmt\Nop) {
80
                $context->notice(
81
                    'missing_break_statement',
82
                    'Missing "break" statement',
83
                    $case
84
                );
85
86
                return true;
87
            }
88
89
            $stmt = prev($case->stmts);
90
        }
91
92
        return false;
93
    }
94
}
95