code complexity & repetition analysis tool
mccabre docs src examples.md
7.6 kB · 326 lines
Markdown
at main

Example Usage #

This page demonstrates common Mccabre workflows with real examples.

Example Files #

The examples/ directory contains sample files demonstrating different issues:

  • complex.js - High cyclomatic complexity
  • not_dry.go - Duplicated code (clones)

long.py is included as sample source text, but Python files are not currently analyzed by Mccabre.

Analyzing the Examples #

Full Analysis #

mccabre analyze examples/

Output:

================================================================================
MCCABRE CODE ANALYSIS REPORT
================================================================================

SUMMARY
--------------------------------------------------------------------------------
Total files analyzed:        2
Total physical LOC:          135
Total logical LOC:           92
Average complexity:          22.50
Maximum complexity:          23
High complexity files:       2
Clone groups detected:       42

FILE METRICS
--------------------------------------------------------------------------------
FILE: examples/complex.js
    Cyclomatic Complexity:   23
    Physical LOC:            49
    Logical LOC:             37
    Comment lines:           2
    Blank lines:             10

FILE: examples/not_dry.go
    Cyclomatic Complexity:   22
    Physical LOC:            86
    Logical LOC:             55
    Comment lines:           13
    Blank lines:             18

DETECTED CLONES
--------------------------------------------------------------------------------
Clone Group #1 (length: 30 tokens, 3 occurrences)
  - examples/not_dry.go:19-24
  - examples/not_dry.go:40-45
  - examples/not_dry.go:61-66

... additional overlapping clone groups omitted ...

Complexity Only #

mccabre complexity examples/complex.js

Shows that complex.js has high cyclomatic complexity due to many conditional branches.

Clone Detection Only #

mccabre clones examples/not_dry.go

Identifies the three nearly-identical functions in not_dry.go.

Lines of Code #

mccabre loc examples/ --rank-by physical

Ranks the supported example files by physical lines of code. Unsupported files are ignored during directory scans.

Coverage #

mccabre coverage report --from lcov.info --html coverage-html/

Reads LCOV data, prints a terminal summary, and writes a static HTML report.

Real-World Scenarios #

Scenario 1: Pre-Commit Check #

Ensure code quality before committing:

#!/bin/sh
# .git/hooks/pre-commit

echo "Checking code complexity..."

# Get list of staged Rust files
FILES=$(git diff --cached --name-only --diff-filter=ACM | grep '\.rs$')

if [ -n "$FILES" ]; then
    for file in $FILES; do
        mccabre complexity "$file" --threshold 15 || exit 1
    done
fi

echo "Complexity check passed!"

Scenario 2: Finding Refactoring Targets #

Combine complexity and clone detection:

# Find high-complexity files
echo "=== High Complexity Files ==="
mccabre complexity src/ --json | \
  jq -r '.files[] | select(.cyclomatic.file_complexity > 15) | .path'

# Find duplicated code
echo "\n=== Code Clones ==="
mccabre clones src/ --min-tokens 25

Then refactor the flagged files.

Scenario 3: Tracking Technical Debt #

Weekly complexity tracking:

#!/bin/bash
# weekly-report.sh

DATE=$(date +%Y-%m-%d)
REPORT_DIR="reports"

mkdir -p "$REPORT_DIR"

# Generate report
mccabre analyze src/ --json > "$REPORT_DIR/report-$DATE.json"

# Extract key metrics
echo "Complexity Report - $DATE"
jq '.summary' "$REPORT_DIR/report-$DATE.json"

# Compare with last week
LAST_WEEK=$(ls -t $REPORT_DIR/report-*.json | sed -n 2p)
if [ -n "$LAST_WEEK" ]; then
    echo "\nChange from last week:"
    jq -s '.[1].summary.avg_complexity - .[0].summary.avg_complexity' \
      "$LAST_WEEK" "$REPORT_DIR/report-$DATE.json"
fi

Scenario 4: Code Review Automation #

Automatically comment on PRs with complexity issues:

#!/bin/bash
# pr-comment.sh

# Run analysis
mccabre analyze src/ --json > complexity.json

# Extract high complexity files
HIGH_COMPLEXITY=$(jq -r '.files[] | select(.cyclomatic.file_complexity > 15) |
  "- `\(.path)`: Complexity \(.cyclomatic.file_complexity)"' complexity.json)

if [ -n "$HIGH_COMPLEXITY" ]; then
    # Post comment to GitHub PR (requires gh CLI)
    gh pr comment --body "## ⚠️ Complexity Warning

Files with high complexity:
$HIGH_COMPLEXITY

Consider refactoring before merging."
fi

Scenario 5: Compare Branches #

Compare complexity between branches:

#!/bin/bash
# compare-branches.sh

MAIN_BRANCH="main"
FEATURE_BRANCH=$(git branch --show-current)

# Analyze main
git checkout "$MAIN_BRANCH"
mccabre analyze src/ --json > /tmp/main-complexity.json

# Analyze feature
git checkout "$FEATURE_BRANCH"
mccabre analyze src/ --json > /tmp/feature-complexity.json

# Compare
echo "=== Complexity Comparison ==="
echo "Main branch avg: $(jq '.summary.avg_complexity' /tmp/main-complexity.json)"
echo "Feature branch avg: $(jq '.summary.avg_complexity' /tmp/feature-complexity.json)"

# Check if complexity increased
MAIN_AVG=$(jq '.summary.avg_complexity' /tmp/main-complexity.json)
FEATURE_AVG=$(jq '.summary.avg_complexity' /tmp/feature-complexity.json)

if (( $(echo "$FEATURE_AVG > $MAIN_AVG * 1.1" | bc -l) )); then
    echo "Complexity increased by more than 10%!"
    exit 1
else
    echo "Complexity is acceptable"
fi

Filtering and Processing #

Find Files Above Threshold #

# JSON output piped to jq
mccabre complexity src/ --json | \
  jq '.files[] | select(.cyclomatic.file_complexity > 10) | .path'

Count Clone Groups #

mccabre clones src/ --json | jq '.clones | length'

Generate HTML #

# Create HTML from JSON
mccabre analyze src/ --json | \
  jq -r '.files[] | "<tr><td>\(.path)</td><td>\(.cyclomatic.file_complexity)</td></tr>"' | \
  (echo "<html><table>" && cat && echo "</table></html>") > report.html

Summary Statistics #

# Extract just the summary
mccabre analyze src/ --json | jq '.summary'

Generate and Save Configuration #

Create a config file for your project:

# Save default config to current directory
mccabre dump-config -o mccabre.toml

# Generate config for a specific project structure
cd my-project/
mccabre dump-config -o .

# Copy config from one project to another
mccabre dump-config -c ../project-a/mccabre.toml -o ./mccabre.toml

Tips and Tricks #

Syntax Highlighting #

By default, code blocks in analyze and clones output are syntax highlighted. To disable:

# Disable syntax highlighting for cleaner output
mccabre analyze src/ --no-highlight

# Useful for piping to files or when colors aren't supported
mccabre clones src/ --no-highlight > report.txt

Incremental Analysis #

Analyze only changed files:

# Files changed in last commit
for file in $(git diff --name-only HEAD~1 | grep '\.rs$'); do
    mccabre complexity "$file"
done

Watch Mode #

Continuously monitor (requires watch or entr):

# Using entr
ls src/**/*.rs | entr mccabre complexity src/

Focus on New Code #

Analyze only files in your feature branch:

for file in $(git diff --name-only main...HEAD | grep '\.rs$'); do
    mccabre analyze "$file"
done

Next Steps #