3 个不稳定版本

0.2.0 2020 年 4 月 26 日
0.1.1 2020 年 4 月 25 日
0.1.0 2020 年 4 月 20 日
0.0.0 2020 年 4 月 19 日

#1371开发工具

Download history 3/week @ 2024-03-28 2/week @ 2024-04-04 3/week @ 2024-05-02

67 每月下载量

MIT/Apache

28KB
395

complexity

计算 Rust 代码的认知复杂度。


基于 G. Ann Campbell 的 认知复杂度

入门指南

complexity 添加到您的 Cargo.toml 文件中。

[dependencies]
complexity = "0.2"
syn = "1"

您需要将 Complexity 特性引入作用域,可能还需要从 syn 中的一些内容。

use complexity::Complexity;
use syn::{Expr, parse_quote};

表达式和其他 syn 类型的复杂度计算非常简单,只需在那种类型的实例上调用 .complexity() 方法即可。

let expr: Expr = parse_quote! {
    for element in iterable { // +1
        if something {        // +2 (nesting = 1)
            do_something();
        }
    }
};
assert_eq!(expr.complexity(), 3);

示例

本库中认知复杂度的实现主要基于 G. Ann Campbell 的 认知复杂度。阅读它将有助于理解复杂度指数是如何计算的。

引入分支的循环和结构会增加复杂度,每个分支增加 1。一些语法结构引入了“嵌套”级别,除了常规增加外,还会增加一些表达式的复杂度。下面我们看看两个嵌套循环和一个 if 语句如何产生相当高的 7 复杂度。

use complexity::Complexity;
use syn::{ItemFn, parse_quote};

let func: ItemFn = parse_quote! {
    fn sum_of_primes(max: u64) -> u64 {
        let mut total = 0;
        'outer: for i in 1..=max {   // +1
            for j in 2..i {          // +2 (nesting = 1)
                if i % j == 0 {      // +3 (nesting = 2)
                    continue 'outer; // +1
                }
            }
            total += i;
        }
    }
};
assert_eq!(func.complexity(), 7);

但某些结构是受奖励的。特别是 match 语句,无论有多少分支,它只会增加 1 的复杂度。(尽管它会增加嵌套级别。)下面我们看看尽管代码中有很多分支(这会为更传统的 圈复杂度 测量贡献很多),但复杂度相当低,只有 1

use complexity::Complexity;
use syn::{ItemFn, parse_quote};

let func: ItemFn = parse_quote! {
    fn get_words(number: u64) -> &str {
        match number {       // +1
            1 => "one",
            2 => "a couple",
            3 => "a few",
            _ => "lots",
        }
    }
};
assert_eq!(func.complexity(), 1);

下面提供了一个示例,用于计算并优雅地打印出整个 Rust 文件中每个函数和方法的认知复杂度。请参阅 examples/lint-files.rs。您可以在这样的 Rust 文件上运行它

cargo run --example lint-files -- src/

许可证

许可协议为以下之一:

任选其一。

依赖项

约 1.5MB
约 35K SLoC