Skip to content

Rust: cyclomatic and cognitive values that differ from McCabe and the Cognitive Complexity whitepaper #1249

Description

@brandon-arrendondo

Version: rust-code-analysis-cli 0.0.25 (crates.io), and master at 37e5d83. Same results on both.

Four small cases (five departures), each a self-contained file. The expected values come from McCabe (1976) for cyclomatic and from G. Ann Campbell's Cognitive Complexity whitepaper (SonarSource, v1.7) for cognitive.

1. match counts every arm, including the last (the whitepaper's getWords example, written with match):

fn get_words(number: u32) -> &'static str {
    match number {
        1 => "one",
        2 => "a couple",
        3 => "a few",
        _ => "lots",
    }
}

Cyclomatic: expected 4 (a four-way branch is three decisions; the whitepaper gives 4 for its switch version), actual 5. Cognitive 1 is as expected.

2. A bare loop counts as a decision, and is not counted for cognitive:

fn f(mut n: u32) -> u32 {
    loop {
        n += 1;
        if n > 10 {
            break;
        }
    }
    n
}

Cyclomatic: expected 2 (loop has no predicate; the if is the only decision), actual 3. Cognitive: expected 3 (the whitepaper adds +1 for the loop and +2 for the if nested in it), actual 1.

3. let ... else is not a decision:

fn first(v: &[i32]) -> i32 {
    let Some(x) = v.first() else { return 0; };
    *x
}

Cyclomatic: expected 2 (the pattern either matches, or the diverging else runs), actual 1.

4. The whitepaper's mixed-operator example:

fn mixed(a: bool, b: bool, c: bool, d: bool, e: bool, g: bool) -> i32 {
    if a && b && c || d || e && g {
        return 1;
    }
    0
}

Cognitive: expected 4 (the whitepaper's own worked example: +1 for the if, +1 for each of the three operator sequences), actual 5. Cyclomatic 7 is as expected.

I'm happy to split this into separate issues if that's easier to track.

This report was drafted with AI assistance; I ran the repro and checked the numbers myself.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions