Skip to content

Commit

Permalink
Merge pull request #10 from rohaquinlop/issue-5
Browse files Browse the repository at this point in the history
feat(build): fix cognitive complexity algorithm
  • Loading branch information
rohaquinlop authored Feb 27, 2024
2 parents 9345045 + 9d42518 commit 9e0383f
Show file tree
Hide file tree
Showing 6 changed files with 34 additions and 67 deletions.
5 changes: 4 additions & 1 deletion complexipy/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def main(
start_time = time.time()
files = rust.main(path, is_dir, is_url, max_complexity)
execution_time = time.time() - start_time
console.rule("Analysis completed! :tada:")
console.rule(":tada: Analysis completed!:tada:")

if output:
with open(f"{invocation_path}/complexipy.csv", "w", newline="") as file:
Expand All @@ -59,7 +59,9 @@ def main(
table.add_column("Path")
table.add_column("File")
table.add_column("Complexity")
total_complexity = 0
for file in files:
total_complexity += file.complexity
if file.complexity > max_complexity and max_complexity != 0:
table.add_row(
f"{file.path}",
Expand All @@ -74,6 +76,7 @@ def main(
f"[blue]{file.complexity}[/blue]",
)
console.print(table)
console.print(f":brain: Total Cognitive Complexity in {path}: {total_complexity}")
console.print(f"{len(files)} files analyzed in {execution_time:.4f} seconds")

if not has_success:
Expand Down
31 changes: 18 additions & 13 deletions src/cognitive_complexity/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use std::env;
use std::path;
use std::process;
use tempfile::tempdir;
use utils::{count_bool_ops, get_repo_name, has_recursive_calls, is_decorator};
use utils::{count_bool_ops, get_repo_name, is_decorator};

// Main function
#[pyfunction]
Expand Down Expand Up @@ -150,10 +150,6 @@ fn statement_cognitive_complexity(statement: Stmt, nesting_level: u64) -> PyResu
}
}

if has_recursive_calls(statement.clone()) {
complexity += 1;
}

match statement {
Stmt::FunctionDef(f) => {
for node in f.body.iter() {
Expand All @@ -170,6 +166,9 @@ fn statement_cognitive_complexity(statement: Stmt, nesting_level: u64) -> PyResu
complexity += statement_cognitive_complexity(node.clone(), nesting_level)?;
}
}
Stmt::Assign(a) => {
complexity += count_bool_ops(*a.value);
}
// breaks in the linear flow
Stmt::For(f) => {
complexity += 1;
Expand All @@ -179,6 +178,7 @@ fn statement_cognitive_complexity(statement: Stmt, nesting_level: u64) -> PyResu
}
Stmt::While(w) => {
complexity += 1;
complexity += count_bool_ops(*w.test);
for node in w.body.iter() {
complexity += statement_cognitive_complexity(node.clone(), nesting_level + 1)?;
}
Expand All @@ -189,6 +189,18 @@ fn statement_cognitive_complexity(statement: Stmt, nesting_level: u64) -> PyResu
for node in i.body.iter() {
complexity += statement_cognitive_complexity(node.clone(), nesting_level + 1)?;
}

let mut orelse_complexity: u64 = 0;
for node in i.orelse.iter() {
orelse_complexity += statement_cognitive_complexity(node.clone(), nesting_level)?;
}

if orelse_complexity > 0 && i.orelse.len() > 0 {
complexity -= (nesting_level) * i.orelse.len() as u64;
complexity += orelse_complexity;
} else if i.orelse.len() > 0 {
complexity += 1;
}
}
Stmt::Try(t) => {
complexity += 1;
Expand All @@ -208,19 +220,12 @@ fn statement_cognitive_complexity(statement: Stmt, nesting_level: u64) -> PyResu
}
}
Stmt::Match(m) => {
complexity += 1;
for case in m.cases.iter() {
for node in case.body.iter() {
complexity += statement_cognitive_complexity(node.clone(), nesting_level)?;
complexity += statement_cognitive_complexity(node.clone(), nesting_level + 1)?;
}
}
}
Stmt::Break(..) => {
complexity += 1;
}
Stmt::Continue(..) => {
complexity += 1;
}
_ => {}
};

Expand Down
46 changes: 2 additions & 44 deletions src/cognitive_complexity/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,45 +14,6 @@ pub fn get_repo_name(url: &str) -> String {
repo_name.to_string()
}

pub fn has_recursive_calls(statement: Stmt) -> bool {
let mut ans = false;

match statement {
Stmt::FunctionDef(f) => {
f.body.iter().for_each(|node| {
match node {
Stmt::Return(r) => match &r.value {
Some(v) => match v.clone().as_ref() {
ast::Expr::Call(c) => match c.func.clone().as_ref() {
ast::Expr::Name(n) => {
ans = ans || n.id == f.name;
}
_ => {}
},
_ => {}
},
_ => {}
},
Stmt::Expr(e) => match e.value.clone().as_ref() {
ast::Expr::Call(c) => match c.func.clone().as_ref() {
ast::Expr::Name(n) => {
ans = ans || n.id == f.name;
}
_ => {}
},
_ => {}
},
_ => {}
};
ans = ans || has_recursive_calls(node.clone());
});
}
_ => {}
};

ans
}

pub fn is_decorator(statement: Stmt) -> bool {
let mut ans = false;
match statement {
Expand All @@ -78,11 +39,8 @@ pub fn count_bool_ops(expr: ast::Expr) -> u64 {
let mut complexity: u64 = 0;

match expr {
ast::Expr::BoolOp(b) => {
complexity += b.values.len() as u64 - 1;
for value in b.values.iter() {
complexity += count_bool_ops(value.clone());
}
ast::Expr::BoolOp(..) => {
complexity += 1;
}
ast::Expr::BinOp(b) => {
complexity += 1;
Expand Down
10 changes: 5 additions & 5 deletions tests/test_break_continue.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
def function():
for i in range(10):
if i == 5:
break
continue
print(i)
for i in range(10): # 1
if i == 5: # 2 (nested = 1)
break # 0 (nested = 2)
continue # 0 (nested = 1)
print(i)
7 changes: 4 additions & 3 deletions tests/test_for.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
def sum_values(values):
total = 0
for value in values:
for value in values: # 1 (nested = 0)
total += value
return total


def sum_values_with_if(values):
total = 0
for value in values:
if value > 0 and value < 10 and value % 2 == 0:
for value in values: # 1 (nested = 0)
if value > 0 and value < 10 and value % 2 == 0: # [2] + 1 (nested = 1)
total += value
return total
2 changes: 1 addition & 1 deletion tests/test_if.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
if "1" == "1":
print(1)
if "2" == "2" and "3" == "3":
print(1)
print(1)

0 comments on commit 9e0383f

Please sign in to comment.