rust-lang / rust-clippy

A bunch of lints to catch common mistakes and improve your Rust code. Book: https://doc.rust-lang.org/clippy/
https://rust-lang.github.io/rust-clippy/
Other
11.46k stars 1.55k forks source link

New lint: comment line density for files and functions #13402

Open TristanFAURE opened 2 months ago

TristanFAURE commented 2 months ago

What it does

The lint counts the number of lines of the file and count the number of comments in the source file and do a percentage if the percentage is bellow a specific threshold a warning is raised

In tools like sonarqube it corresponds to comment_lines_density https://docs.sonarsource.com/sonarqube/latest/user-guide/code-metrics/metrics-definition/

Comment Density (%) = (Number of Comment Lines / (Total Lines - Empty Lines)) × 100

Advantage

It is important for some industries (like space industry), some coding standards request it

Drawbacks

This metric is generally not relevant and we want developers to think about relevant comments instead of number of lines of comments, but as said in Advantage it is something requested by standards

Example

<code>
// Calculate nth Fibonacci number
fn fibonacci(n: u32) -> u32 {
    if n <= 1 {
        return n;
    }

    let mut a = 0;
    let mut b = 1;

    for _ in 2..=n {
        let next = a + b;
        a = b;
        b = next;
    }

    b
}

fn main() {
    // Test Fibonacci
    let n = 10;
    println!("Fibonacci of {} is {}", n, fibonacci(n));
}

Could be written as with 52 % (13 of 25) of comments:

<code>
// This function calculates the nth Fibonacci number
fn fibonacci(n: u32) -> u32 {
    // Base case: If n is 0 or 1, return n
    if n <= 1 {
        return n;
    }

    // Initialize variables for the iterative calculation
    let mut a = 0; // This will hold the (n-2)th Fibonacci number
    let mut b = 1; // This will hold the (n-1)th Fibonacci number

    // Loop from 2 to n to calculate the nth Fibonacci number
    for _ in 2..=n {
        // Calculate the next Fibonacci number in the sequence
        let next = a + b;

        // Update a and b for the next iteration
        a = b; // Shift b to a
        b = next; // Set b to the newly calculated Fibonacci number
    }

    // Return the nth Fibonacci number
    b
}

fn main() {
    // Example usage: Calculate and print the 10th Fibonacci number
    let n = 10; // Change this value to calculate a different Fibonacci number
    println!("Fibonacci of {} is {}", n, fibonacci(n));
}
TristanFAURE commented 2 months ago

I am taking the feedback of the community and will be glad to contribute this lint

samueltardieu commented 2 months ago

You may also want to use tools such as Mozilla's rust-code-analysis to gather metrics by function.

TristanFAURE commented 2 months ago

You may also want to use tools such as Mozilla's rust-code-analysis to gather metrics by function.

Thanks for the information, i did not look yet the source code of clippy I would expect to plug a visitor on the AST but no problem if I have to run an AST. Do you know if an existing rule already use it ? (to have an example) I will check the library, thanks for the reference !

samueltardieu commented 2 months ago

It includes a CLI tool which produces various metrics for every item (function, module, etc.), as json or toml files for example. It gives you the number of lines, the number of physical code lines, the number of blank lines. The rest is comments. It also gives you directly the number of comments, but a block with multiple lines will count as one comment so it may be less useful for you.