Completed
Push — master ( 02285f...915210 )
by personal
05:27
created

McCabe::calculate()   D

Complexity

Conditions 20
Paths 20

Size

Total Lines 42
Code Lines 32

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 42
rs 4.882
cc 20
eloc 32
nc 20
nop 1

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/*
4
 * (c) Jean-François Lépine <https://twitter.com/Halleck45>
5
 *
6
 * For the full copyright and license information, please view the LICENSE
7
 * file that was distributed with this source code.
8
 */
9
10
namespace Hal\Metrics\Complexity\Component\McCabe;
11
use Hal\Component\Token\Tokenizer;
12
13
/**
14
 * Calculates cyclomatic complexity
15
 *
16
 * @author Jean-François Lépine <https://twitter.com/Halleck45>
17
 */
18
class McCabe {
19
20
    /**
21
     * Tokenizer
22
     *
23
     * @var \Hal\Component\Token\Tokenizer
24
     */
25
    private $tokenizer;
26
27
    /**
28
     * Constructor
29
     *
30
     * @param Tokenizer $tokenizer
31
     */
32
    public function __construct(Tokenizer $tokenizer) {
33
        $this->tokenizer = $tokenizer;
34
    }
35
36
    /**
37
     * Calculate cyclomatic complexity number
38
     *
39
     * We can calculate ccn in two ways (we choose the second):
40
     *
41
     *  1.  Cyclomatic complexity (CC) = E - N + 2P
42
     *      Where:
43
     *      P = number of disconnected parts of the flow graph (e.g. a calling program and a subroutine)
44
     *      E = number of edges (transfers of control)
45
     *      N = number of nodes (sequential group of statements containing only one transfer of control)
46
     *
47
     * 2. CC = Number of each decision point
48
     *
49
     * @param string $filename
50
     * @return Result
51
     */
52
    public function calculate($filename)
53
    {
54
55
        $info = new Result;
56
        $tokens = $this->tokenizer->tokenize($filename);
57
58
        $ccn = 1; // default path
59
        foreach($tokens as $token) {
60
61
            switch($token->getType()) {
62
                case T_IF:
63
                case T_ELSEIF:
64
                case T_FOREACH:
65
                case T_FOR:
66
                case T_WHILE:
67
                case T_DO:
68
                case T_BOOLEAN_AND:
69
                case T_LOGICAL_AND:
70
                case T_BOOLEAN_OR:
71
                case T_LOGICAL_OR:
72
                case T_SPACESHIP:
73
                case T_CASE:
74
                case T_DEFAULT:
75
                case T_CATCH:
76
                case T_CONTINUE:
77
                    $ccn++;
78
                    break;
79
                case T_STRING:
80
                    if('?' == $token->getValue()) {
81
                        $ccn = $ccn + 2;
82
                    }
83
                    break;
84
                case T_COALESCE:
85
                    $ccn = $ccn + 2;
86
                    break;
87
            }
88
89
        }
90
91
        $info->setCyclomaticComplexityNumber(max(1, $ccn));
92
        return $info;
93
    }
94
}