Subversion Repositories Applications.framework

Rev

Rev 5 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
5 aurelien 1
<?php
2
/**
3
 * Checks the cyclomatic complexity (McCabe) for functions.
4
 *
5
 * PHP version 5
6
 *
7
 * @category  PHP
8
 * @package   PHP_CodeSniffer
9
 * @author    Greg Sherwood <gsherwood@squiz.net>
10
 * @author    Marc McIntyre <mmcintyre@squiz.net>
11
 * @copyright 2006 Squiz Pty Ltd (ABN 77 084 670 600)
12
 * @license   http://matrix.squiz.net/developer/tools/php_cs/licence BSD Licence
34 aurelien 13
 * @version   CVS: $Id: CyclomaticComplexitySniff.php 34 2009-04-09 07:34:39Z aurelien $
5 aurelien 14
 * @link      http://pear.php.net/package/PHP_CodeSniffer
15
 */
16
 
17
/**
18
 * Checks the cyclomatic complexity (McCabe) for functions.
19
 *
20
 * The cyclomatic complexity (also called McCabe code metrics)
21
 * indicates the complexity within a function by counting
22
 * the different paths the function includes.
23
 *
24
 * @category  PHP
25
 * @package   PHP_CodeSniffer
26
 * @author    Johann-Peter Hartmann <hartmann@mayflower.de>
27
 * @author    Greg Sherwood <gsherwood@squiz.net>
28
 * @copyright 2007 Mayflower GmbH
29
 * @license   http://matrix.squiz.net/developer/tools/php_cs/licence BSD Licence
30
 * @version   Release: 1.2.0RC1
31
 * @link      http://pear.php.net/package/PHP_CodeSniffer
32
 */
33
class Generic_Sniffs_Metrics_CyclomaticComplexitySniff implements PHP_CodeSniffer_Sniff
34
{
35
 
36
    /**
37
     * A complexity higher than this value will throw a warning.
38
     *
39
     * @var int
40
     */
41
    protected $complexity = 10;
42
 
43
    /**
44
     * A complexity higer than this value will throw an error.
45
     *
46
     * @var int
47
     */
48
    protected $absoluteComplexity = 20;
49
 
50
 
51
    /**
52
     * Returns an array of tokens this test wants to listen for.
53
     *
54
     * @return array
55
     */
56
    public function register()
57
    {
58
        return array(T_FUNCTION);
59
 
60
    }//end register()
61
 
62
 
63
    /**
64
     * Processes this test, when one of its tokens is encountered.
65
     *
66
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
67
     * @param int                  $stackPtr  The position of the current token
68
     *                                        in the stack passed in $tokens.
69
     *
70
     * @return void
71
     */
72
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
73
    {
74
        $this->currentFile = $phpcsFile;
75
 
76
        $tokens = $phpcsFile->getTokens();
77
 
78
        // Ignore abstract methods.
79
        if (isset($tokens[$stackPtr]['scope_opener']) === false) {
80
            return;
81
        }
82
 
83
        // Detect start and end of this function definition.
84
        $start = $tokens[$stackPtr]['scope_opener'];
85
        $end   = $tokens[$stackPtr]['scope_closer'];
86
 
87
        // Predicate nodes for PHP.
88
        $find = array(
89
                 'T_CASE',
90
                 'T_DEFAULT',
91
                 'T_CATCH',
92
                 'T_IF',
93
                 'T_FOR',
94
                 'T_FOREACH',
95
                 'T_WHILE',
96
                 'T_DO',
97
                 'T_ELSEIF',
98
                );
99
 
100
        $complexity = 1;
101
 
102
        // Iterate from start to end and count predicate nodes.
103
        for ($i = ($start + 1); $i < $end; $i++) {
104
            if (in_array($tokens[$i]['type'], $find) === true) {
105
                $complexity++;
106
            }
107
        }
108
 
109
        if ($complexity > $this->absoluteComplexity) {
110
            $error = "Function's cyclomatic complexity ($complexity) exceeds allowed maximum of ".$this->absoluteComplexity;
111
            $phpcsFile->addError($error, $stackPtr);
112
        } else if ($complexity > $this->complexity) {
113
            $warning = "Function's cyclomatic complexity ($complexity) exceeds ".$this->complexity.'; consider refactoring the function';
114
            $phpcsFile->addWarning($warning, $stackPtr);
115
        }
116
 
117
        return;
118
 
119
    }//end process()
120
 
121
 
122
}//end class
123
 
124
?>