|
| 1 | +# Cyclomatic Complexity Calculator |
| 2 | + |
| 3 | +This tool calculates cyclomatic complexity for PHP classes and methods. Cyclomatic complexity is a software metric that measures the complexity of a program by counting the number of linearly independent paths through the source code. |
| 4 | + |
| 5 | +## What is Cyclomatic Complexity? |
| 6 | + |
| 7 | +Cyclomatic complexity is calculated as: |
| 8 | +- **Base complexity**: 1 (for the entry point) |
| 9 | +- **+1 for each decision point**: if statements, loops, switch cases, catch blocks, etc. |
| 10 | +- **+1 for each logical operator**: &&, ||, and, or, xor, ternary operators |
| 11 | + |
| 12 | +## Risk Levels |
| 13 | + |
| 14 | +- **Low (1-5)**: Simple, easy to understand and maintain |
| 15 | +- **Medium (6-10)**: Moderately complex, may need some refactoring |
| 16 | +- **High (11-15)**: Complex, should be refactored |
| 17 | +- **Very High (16+)**: Very complex, difficult to maintain and test |
| 18 | + |
| 19 | +## Usage |
| 20 | + |
| 21 | +### Command Line Interface |
| 22 | + |
| 23 | +```bash |
| 24 | +# Basic usage |
| 25 | +bin/phpcca complexity src/ |
| 26 | + |
| 27 | +# With threshold (only show methods with complexity >= 5) |
| 28 | +bin/phpcca complexity src/ --threshold=5 |
| 29 | + |
| 30 | +# Detailed breakdown |
| 31 | +bin/phpcca complexity src/ --detailed |
| 32 | + |
| 33 | +# Output to JSON file |
| 34 | +bin/phpcca complexity src/ --format=json --output=complexity.json |
| 35 | + |
| 36 | +# Output to CSV file |
| 37 | +bin/phpcca complexity src/ --format=csv --output=complexity.csv |
| 38 | +``` |
| 39 | + |
| 40 | +### Command Options |
| 41 | + |
| 42 | +- `--format, -f`: Output format (text, json, csv) - default: text |
| 43 | +- `--output, -o`: Output file path |
| 44 | +- `--threshold, -t`: Minimum complexity threshold to report (default: 1) |
| 45 | +- `--detailed, -d`: Show detailed breakdown of complexity factors |
| 46 | + |
| 47 | +### Programmatic Usage |
| 48 | + |
| 49 | +```php |
| 50 | +<?php |
| 51 | + |
| 52 | +use PhpParser\ParserFactory; |
| 53 | +use PhpParser\NodeTraverser; |
| 54 | +use Phauthentic\CognitiveCodeAnalysis\PhpParser\CyclomaticComplexityVisitor; |
| 55 | + |
| 56 | +// Create parser and traverser |
| 57 | +$parser = (new ParserFactory())->createForNewestSupportedVersion(); |
| 58 | +$traverser = new NodeTraverser(); |
| 59 | +$visitor = new CyclomaticComplexityVisitor(); |
| 60 | +$traverser->addVisitor($visitor); |
| 61 | + |
| 62 | +// Parse your PHP code |
| 63 | +$code = file_get_contents('your-file.php'); |
| 64 | +$ast = $parser->parse($code); |
| 65 | +$traverser->traverse($ast); |
| 66 | + |
| 67 | +// Get results |
| 68 | +$classComplexity = $visitor->getClassComplexity(); |
| 69 | +$methodComplexity = $visitor->getMethodComplexity(); |
| 70 | +$methodBreakdown = $visitor->getMethodComplexityBreakdown(); |
| 71 | +$summary = $visitor->getComplexitySummary(); |
| 72 | +``` |
| 73 | + |
| 74 | +## Complexity Factors |
| 75 | + |
| 76 | +The calculator counts the following complexity factors: |
| 77 | + |
| 78 | +### Control Structures |
| 79 | +- `if` statements |
| 80 | +- `elseif` statements |
| 81 | +- `switch` statements |
| 82 | +- `case` statements |
| 83 | +- `while` loops |
| 84 | +- `do-while` loops |
| 85 | +- `for` loops |
| 86 | +- `foreach` loops |
| 87 | + |
| 88 | +### Exception Handling |
| 89 | +- `catch` blocks |
| 90 | + |
| 91 | +### Logical Operators |
| 92 | +- `&&` (logical AND) |
| 93 | +- `||` (logical OR) |
| 94 | +- `and` (logical AND) |
| 95 | +- `or` (logical OR) |
| 96 | +- `xor` (logical XOR) |
| 97 | +- Ternary operators (`? :`) |
| 98 | + |
| 99 | +## Example Output |
| 100 | + |
| 101 | +### Text Format |
| 102 | +``` |
| 103 | +Cyclomatic Complexity Analysis |
| 104 | +Files analyzed: 15 |
| 105 | +
|
| 106 | +Class Complexity: |
| 107 | + Test\ComplexityTest: 45 (high) |
| 108 | + Test\AnotherComplexityTest: 6 (medium) |
| 109 | +
|
| 110 | +Method Complexity: |
| 111 | + Test\ComplexityTest::simpleMethod: 1 (low) |
| 112 | + Test\ComplexityTest::methodWithIf: 2 (low) |
| 113 | + Test\ComplexityTest::highComplexityMethod: 12 (high) |
| 114 | + Test\ComplexityTest::veryHighComplexityMethod: 18 (very_high) |
| 115 | +
|
| 116 | +High Risk Methods (≥10): |
| 117 | + Test\ComplexityTest::highComplexityMethod: 12 |
| 118 | + Test\ComplexityTest::veryHighComplexityMethod: 18 |
| 119 | +
|
| 120 | +Summary Statistics: |
| 121 | + Average complexity: 4.2 |
| 122 | + Maximum complexity: 18 |
| 123 | + Minimum complexity: 1 |
| 124 | + Total methods: 10 |
| 125 | +``` |
| 126 | + |
| 127 | +### JSON Format |
| 128 | +```json |
| 129 | +{ |
| 130 | + "summary": { |
| 131 | + "classes": { |
| 132 | + "Test\\ComplexityTest": { |
| 133 | + "complexity": 45, |
| 134 | + "risk_level": "high" |
| 135 | + } |
| 136 | + }, |
| 137 | + "methods": { |
| 138 | + "Test\\ComplexityTest::highComplexityMethod": { |
| 139 | + "complexity": 12, |
| 140 | + "risk_level": "high", |
| 141 | + "breakdown": { |
| 142 | + "total": 12, |
| 143 | + "base": 1, |
| 144 | + "if": 3, |
| 145 | + "switch": 1, |
| 146 | + "case": 3, |
| 147 | + "foreach": 1, |
| 148 | + "logical_and": 1 |
| 149 | + } |
| 150 | + } |
| 151 | + }, |
| 152 | + "high_risk_methods": { |
| 153 | + "Test\\ComplexityTest::highComplexityMethod": 12, |
| 154 | + "Test\\ComplexityTest::veryHighComplexityMethod": 18 |
| 155 | + } |
| 156 | + }, |
| 157 | + "files_analyzed": 15 |
| 158 | +} |
| 159 | +``` |
| 160 | + |
| 161 | +## Best Practices |
| 162 | + |
| 163 | +1. **Keep methods simple**: Aim for complexity ≤ 10 |
| 164 | +2. **Refactor complex methods**: Break down methods with complexity > 15 |
| 165 | +3. **Use early returns**: Reduce nesting and complexity |
| 166 | +4. **Extract conditions**: Move complex conditions to separate methods |
| 167 | +5. **Use strategy pattern**: Replace complex switch statements |
| 168 | +6. **Limit logical operators**: Avoid deeply nested AND/OR conditions |
| 169 | + |
| 170 | +## Integration with CI/CD |
| 171 | + |
| 172 | +Add complexity checks to your CI pipeline: |
| 173 | + |
| 174 | +```bash |
| 175 | +# Fail if any method has complexity > 15 |
| 176 | +bin/phpcca complexity src/ --threshold=15 --format=json | jq '.summary.very_high_risk_methods | length == 0' |
| 177 | + |
| 178 | +# Generate complexity report |
| 179 | +bin/phpcca complexity src/ --format=json --output=complexity-report.json |
| 180 | +``` |
| 181 | + |
| 182 | +## Testing |
| 183 | + |
| 184 | +Run the example to see the complexity calculator in action: |
| 185 | + |
| 186 | +```bash |
| 187 | +php example_complexity_usage.php |
| 188 | +``` |
| 189 | + |
| 190 | +This will analyze the `test_complexity.php` file and show detailed complexity metrics for all classes and methods. |
0 commit comments