diff --git a/rust-code-analysis-web/src/web/server.rs b/rust-code-analysis-web/src/web/server.rs index 2d1bc3721..eafba9624 100644 --- a/rust-code-analysis-web/src/web/server.rs +++ b/rust-code-analysis-web/src/web/server.rs @@ -633,7 +633,7 @@ mod tests { "end_line": 4, "metrics": {"cyclomatic": {"sum": 2.0, "average": 1.0}, "cognitive": {"sum": 0.0, "average": 0.0}, - "nargs": {"sum": 0.0, "average": 0.0}, + "nargs": {"total_functions": 0.0, "average_functions": 0.0, "total_closures": 0.0, "average_closures": 0.0, "total": 0.0, "average": 0.0}, "nexits": {"sum": 0.0, "average": 0.0}, "halstead": {"bugs": 0.000_942_552_557_372_941_4, "difficulty": 1.0, @@ -660,7 +660,7 @@ mod tests { "end_line": 4, "metrics": {"cyclomatic": {"sum": 1.0, "average": 1.0}, "cognitive": {"sum": 0.0, "average": 0.0}, - "nargs": {"sum": 0.0, "average": 0.0}, + "nargs": {"total_functions": 0.0, "average_functions": 0.0, "total_closures": 0.0, "average_closures": 0.0, "total": 0.0, "average": 0.0}, "nexits": {"sum": 0.0, "average": 0.0}, "halstead": {"bugs": 0.000_942_552_557_372_941_4, "difficulty": 1.0, @@ -713,7 +713,7 @@ mod tests { "end_line": 2, "metrics": {"cyclomatic": {"sum": 2.0, "average": 1.0}, "cognitive": {"sum": 0.0, "average": 0.0}, - "nargs": {"sum": 0.0, "average": 0.0}, + "nargs": {"total_functions": 0.0, "average_functions": 0.0, "total_closures": 0.0, "average_closures": 0.0, "total": 0.0, "average": 0.0}, "nexits": {"sum": 0.0, "average": 0.0}, "halstead": {"bugs": 0.000_942_552_557_372_941_4, "difficulty": 1.0, @@ -762,7 +762,7 @@ mod tests { "end_line": 2, "metrics": {"cyclomatic": {"sum": 2.0, "average": 1.0}, "cognitive": {"sum": 0.0, "average": 0.0}, - "nargs": {"sum": 0.0, "average": 0.0}, + "nargs": {"total_functions": 0.0, "average_functions": 0.0, "total_closures": 0.0, "average_closures": 0.0, "total": 0.0, "average": 0.0}, "nexits": {"sum": 0.0, "average": 0.0}, "halstead": {"bugs": 0.000_942_552_557_372_941_4, "difficulty": 1.0, @@ -789,7 +789,7 @@ mod tests { "end_line": 2, "metrics": {"cyclomatic": {"sum": 1.0, "average": 1.0}, "cognitive": {"sum": 0.0, "average": 0.0}, - "nargs": {"sum": 0.0, "average": 0.0}, + "nargs": {"total_functions": 0.0, "average_functions": 0.0, "total_closures": 0.0, "average_closures": 0.0, "total": 0.0, "average": 0.0}, "nexits": {"sum": 0.0, "average": 0.0}, "halstead": {"bugs": 0.000_942_552_557_372_941_4, "difficulty": 1.0, diff --git a/src/checker.rs b/src/checker.rs index d450bcb52..5e54f3b55 100644 --- a/src/checker.rs +++ b/src/checker.rs @@ -351,5 +351,5 @@ impl Checker for RustCode { TraitItem, ClosureExpression ); - mk_checker!(is_non_arg, LPAREN, COMMA, RPAREN, AttributeItem); + mk_checker!(is_non_arg, LPAREN, COMMA, RPAREN, PIPE, AttributeItem); } diff --git a/src/metrics/fn_args.rs b/src/metrics/fn_args.rs deleted file mode 100644 index 94dd256c2..000000000 --- a/src/metrics/fn_args.rs +++ /dev/null @@ -1,192 +0,0 @@ -use serde::ser::{SerializeStruct, Serializer}; -use serde::Serialize; -use std::fmt; - -use crate::checker::Checker; -use crate::*; - -/// The `NArgs` metric. -/// -/// This metric counts the number of arguments -/// of a function/method. -#[derive(Debug, Clone)] -pub struct Stats { - nargs: usize, - total_space_functions: usize, -} - -impl Default for Stats { - fn default() -> Self { - Self { - nargs: 0, - total_space_functions: 1, - } - } -} - -impl Serialize for Stats { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - let mut st = serializer.serialize_struct("nargs", 2)?; - st.serialize_field("sum", &self.nargs())?; - st.serialize_field("average", &self.nargs_average())?; - st.end() - } -} - -impl fmt::Display for Stats { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!( - f, - "sum: {}, average: {}", - self.nargs(), - self.nargs_average() - ) - } -} - -impl Stats { - /// Merges a second `NArgs` metric into the first one - pub fn merge(&mut self, other: &Stats) { - self.nargs += other.nargs; - } - - /// Returns the `NArgs` metric value - pub fn nargs(&self) -> f64 { - self.nargs as f64 - } - - /// Returns the `NArgs` metric average value - /// - /// This value is computed dividing the `NArgs` value - /// for the total number of functions/closures in a space. - pub fn nargs_average(&self) -> f64 { - self.nargs() / self.total_space_functions as f64 - } - - pub(crate) fn finalize(&mut self, total_space_functions: usize) { - self.total_space_functions = total_space_functions; - } -} - -#[doc(hidden)] -pub trait NArgs -where - Self: Checker, -{ - fn compute(node: &Node, stats: &mut Stats) { - if !Self::is_func(node) { - return; - } - - if let Some(params) = node.object().child_by_field_name("parameters") { - let node_params = Node::new(params); - node_params.act_on_child(&mut |n| { - if !Self::is_non_arg(n) { - stats.nargs += 1; - } - }); - } - } -} - -impl NArgs for CppCode { - fn compute(node: &Node, stats: &mut Stats) { - if !Self::is_func(node) { - return; - } - - if let Some(declarator) = node.object().child_by_field_name("declarator") { - if let Some(params) = declarator.child_by_field_name("parameters") { - let node_params = Node::new(params); - node_params.act_on_child(&mut |n| { - if !Self::is_non_arg(n) { - stats.nargs += 1; - } - }); - } - } - } -} - -impl NArgs for PythonCode {} -impl NArgs for MozjsCode {} -impl NArgs for JavascriptCode {} -impl NArgs for TypescriptCode {} -impl NArgs for TsxCode {} -impl NArgs for RustCode {} -impl NArgs for PreprocCode {} -impl NArgs for CcommentCode {} -impl NArgs for JavaCode {} - -#[cfg(test)] -mod tests { - use std::path::PathBuf; - - use super::*; - - #[test] - fn test_function_nargs() { - check_metrics!( - "def f(a, b): - if a: - return a", - "foo.py", - PythonParser, - nargs, - [(nargs, 2, usize)], - [(nargs_average, 2.0)] // 1 function - ); - } - - #[test] - fn test_functions_nargs() { - check_metrics!( - "def f(a, b): - if a: - return a - def f(a, b): - if b: - return b", - "foo.py", - PythonParser, - nargs, - [(nargs, 4, usize)], - [(nargs_average, 2.0)] // 2 functions - ); - - check_metrics!( - "def f(a, b): - if a: - return a - def f(a, b, c): - if b: - return b", - "foo.py", - PythonParser, - nargs, - [(nargs, 5, usize)], - [(nargs_average, 2.5)] // 2 functions - ); - } - - #[test] - fn test_nested_functions_nargs() { - check_metrics!( - "def f(a, b): - def foo(a): - if a: - return 1 - bar = lambda a: lambda b: b or True or True - return bar(foo(a))(a)", - "foo.py", - PythonParser, - nargs, - // FIXME: Consider lambda arguments also - [(nargs, 3, usize)], - [(nargs_average, 0.75)] // 2 functions + 2 lambdas = 4 - ); - } -} diff --git a/src/metrics/mod.rs b/src/metrics/mod.rs index d16f0322a..49d52291c 100644 --- a/src/metrics/mod.rs +++ b/src/metrics/mod.rs @@ -1,8 +1,8 @@ pub mod cognitive; pub mod cyclomatic; pub mod exit; -pub mod fn_args; pub mod halstead; pub mod loc; pub mod mi; +pub mod nargs; pub mod nom; diff --git a/src/metrics/nargs.rs b/src/metrics/nargs.rs new file mode 100644 index 000000000..208c37a44 --- /dev/null +++ b/src/metrics/nargs.rs @@ -0,0 +1,738 @@ +use serde::ser::{SerializeStruct, Serializer}; +use serde::Serialize; +use std::fmt; + +use crate::checker::Checker; +use crate::*; + +/// The `NArgs` metric. +/// +/// This metric counts the number of arguments +/// of functions/closures. +#[derive(Debug, Clone)] +pub struct Stats { + fn_nargs: usize, + closure_nargs: usize, + total_functions: usize, + total_closures: usize, +} + +impl Default for Stats { + fn default() -> Self { + Self { + fn_nargs: 0, + closure_nargs: 0, + total_functions: 0, + total_closures: 0, + } + } +} + +impl Serialize for Stats { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + let mut st = serializer.serialize_struct("nargs", 6)?; + st.serialize_field("total_functions", &self.fn_args())?; + st.serialize_field("total_closures", &self.closure_args())?; + st.serialize_field("average_functions", &self.fn_args_average())?; + st.serialize_field("average_closures", &self.closure_args_average())?; + st.serialize_field("total", &self.nargs_total())?; + st.serialize_field("average", &self.nargs_average())?; + st.end() + } +} + +impl fmt::Display for Stats { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!( + f, + "total_functions: {}, total_closures: {}, average_functions: {}, average_closures: {}, total: {}, average: {}", + self.fn_args(), + self.closure_args(), + self.fn_args_average(), + self.closure_args_average(), + self.nargs_total(), + self.nargs_average() + ) + } +} + +impl Stats { + /// Merges a second `NArgs` metric into the first one + pub fn merge(&mut self, other: &Stats) { + self.fn_nargs += other.fn_nargs; + self.closure_nargs += other.closure_nargs; + } + + /// Returns the number of function arguments in a space. + #[inline(always)] + pub fn fn_args(&self) -> f64 { + self.fn_nargs as f64 + } + + /// Returns the number of closure arguments in a space. + #[inline(always)] + pub fn closure_args(&self) -> f64 { + self.closure_nargs as f64 + } + + /// Returns the average number of functions arguments in a space. + #[inline(always)] + pub fn fn_args_average(&self) -> f64 { + self.fn_nargs as f64 / self.total_functions.max(1) as f64 + } + + /// Returns the average number of closures arguments in a space. + #[inline(always)] + pub fn closure_args_average(&self) -> f64 { + self.closure_nargs as f64 / self.total_closures.max(1) as f64 + } + + /// Returns the total number of arguments of each function and + /// closure in a space. + #[inline(always)] + pub fn nargs_total(&self) -> f64 { + self.fn_args() + self.closure_args() + } + + /// Returns the `NArgs` metric average value + /// + /// This value is computed dividing the `NArgs` value + /// for the total number of functions/closures in a space. + #[inline(always)] + pub fn nargs_average(&self) -> f64 { + self.nargs_total() / (self.total_functions + self.total_closures).max(1) as f64 + } + + pub(crate) fn finalize(&mut self, total_functions: usize, total_closures: usize) { + self.total_functions = total_functions; + self.total_closures = total_closures; + } +} + +#[inline(always)] +fn compute_args(node: &Node, nargs: &mut usize) { + if let Some(params) = node.object().child_by_field_name("parameters") { + let node_params = Node::new(params); + node_params.act_on_child(&mut |n| { + if !T::is_non_arg(n) { + *nargs += 1; + } + }); + } +} + +#[doc(hidden)] +pub trait NArgs +where + Self: Checker, + Self: std::marker::Sized, +{ + fn compute(node: &Node, stats: &mut Stats) { + if Self::is_func(node) { + compute_args::(node, &mut stats.fn_nargs); + return; + } + + if Self::is_closure(node) { + compute_args::(node, &mut stats.closure_nargs); + } + } +} + +impl NArgs for CppCode { + fn compute(node: &Node, stats: &mut Stats) { + if Self::is_func(node) { + if let Some(declarator) = node.object().child_by_field_name("declarator") { + let new_node = Node::new(declarator); + compute_args::(&new_node, &mut stats.fn_nargs); + } + return; + } + + if Self::is_closure(node) { + if let Some(declarator) = node.object().child_by_field_name("declarator") { + let new_node = Node::new(declarator); + compute_args::(&new_node, &mut stats.closure_nargs); + } + } + } +} + +impl NArgs for MozjsCode {} +impl NArgs for JavascriptCode {} +impl NArgs for TypescriptCode {} +impl NArgs for TsxCode {} +impl NArgs for PreprocCode {} +impl NArgs for CcommentCode {} +impl NArgs for RustCode {} +impl NArgs for PythonCode {} +impl NArgs for JavaCode {} + +#[cfg(test)] +mod tests { + use std::path::PathBuf; + + use super::*; + + #[test] + fn python_no_functions_and_closures() { + check_metrics!( + "a = 42", + "foo.py", + PythonParser, + nargs, + [ + (fn_args, 0, usize), + (closure_args, 0, usize), + (nargs_total, 0, usize) + ], + [ + (fn_args_average, 0.0), + (closure_args_average, 0.0), + (nargs_average, 0.0) + ] // 0 functions + 0 closures = 0 + ); + } + + #[test] + fn rust_no_functions_and_closures() { + check_metrics!( + "let a = 42;", + "foo.rs", + RustParser, + nargs, + [ + (fn_args, 0, usize), + (closure_args, 0, usize), + (nargs_total, 0, usize) + ], + [ + (fn_args_average, 0.0), + (closure_args_average, 0.0), + (nargs_average, 0.0) + ] // 0 functions + 0 closures = 0 + ); + } + + #[test] + fn cpp_no_functions_and_closures() { + check_metrics!( + "int a = 42;", + "foo.cpp", + CppParser, + nargs, + [ + (fn_args, 0, usize), + (closure_args, 0, usize), + (nargs_total, 0, usize) + ], + [ + (fn_args_average, 0.0), + (closure_args_average, 0.0), + (nargs_average, 0.0) + ] // 0 functions + 0 closures = 0 + ); + } + + #[test] + fn javascript_no_functions_and_closures() { + check_metrics!( + "var a = 42;", + "foo.js", + JavascriptParser, + nargs, + [ + (fn_args, 0, usize), + (closure_args, 0, usize), + (nargs_total, 0, usize) + ], + [ + (fn_args_average, 0.0), + (closure_args_average, 0.0), + (nargs_average, 0.0) + ] // 0 functions + 0 closures = 0 + ); + } + + #[test] + fn python_single_function() { + check_metrics!( + "def f(a, b): + if a: + return a", + "foo.py", + PythonParser, + nargs, + [ + (fn_args, 2, usize), + (closure_args, 0, usize), + (nargs_total, 2, usize) + ], + [ + (fn_args_average, 2.0), + (closure_args_average, 0.0), + (nargs_average, 2.0) + ] // 1 function + ); + } + + #[test] + fn rust_single_function() { + check_metrics!( + "fn f(a: bool, b: usize) { + if a { + return a; + } + }", + "foo.rs", + RustParser, + nargs, + [ + (fn_args, 2, usize), + (closure_args, 0, usize), + (nargs_total, 2, usize) + ], + [ + (fn_args_average, 2.0), + (closure_args_average, 0.0), + (nargs_average, 2.0) + ] // 1 function + ); + } + + #[test] + fn c_single_function() { + check_metrics!( + "int f(int a, int b) { + if (a) { + return a; + } + }", + "foo.c", + CppParser, + nargs, + [ + (fn_args, 2, usize), + (closure_args, 0, usize), + (nargs_total, 2, usize) + ], + [ + (fn_args_average, 2.0), + (closure_args_average, 0.0), + (nargs_average, 2.0) + ] // 1 function + ); + } + + #[test] + fn javascript_single_function() { + check_metrics!( + "function f(a, b) { + return a * b; + }", + "foo.js", + JavascriptParser, + nargs, + [ + (fn_args, 2, usize), + (closure_args, 0, usize), + (nargs_total, 2, usize) + ], + [ + (fn_args_average, 2.0), + (closure_args_average, 0.0), + (nargs_average, 2.0) + ] // 1 function + ); + } + + #[test] + fn python_single_lambda() { + check_metrics!( + "bar = lambda a: True", + "foo.py", + PythonParser, + nargs, + [ + (fn_args, 0, usize), + (closure_args, 1, usize), + (nargs_total, 1, usize) + ], + [ + (fn_args_average, 0.0), + (closure_args_average, 1.0), + (nargs_average, 1.0) + ] // 1 lambda + ); + } + + #[test] + fn rust_single_closure() { + check_metrics!( + "let bar = |i: i32| -> i32 { i + 1 };", + "foo.rs", + RustParser, + nargs, + [ + (fn_args, 0, usize), + (closure_args, 1, usize), + (nargs_total, 1, usize) + ], + [ + (fn_args_average, 0.0), + (closure_args_average, 1.0), + (nargs_average, 1.0) + ] // 1 lambda + ); + } + + #[test] + fn cpp_single_lambda() { + check_metrics!( + "auto bar = [](int x, int y) -> int { return x + y; };", + "foo.cpp", + CppParser, + nargs, + [ + (fn_args, 0, usize), + (closure_args, 2, usize), + (nargs_total, 2, usize) + ], + [ + (fn_args_average, 0.0), + (closure_args_average, 2.0), + (nargs_average, 2.0) + ] // 1 lambda + ); + } + + #[test] + fn javascript_single_closure() { + check_metrics!( + "function (a, b) {return a + b};", + "foo.js", + JavascriptParser, + nargs, + [ + (fn_args, 0, usize), + (closure_args, 2, usize), + (nargs_total, 2, usize) + ], + [ + (fn_args_average, 0.0), + (closure_args_average, 2.0), + (nargs_average, 2.0) + ] // 1 lambda + ); + } + + #[test] + fn python_functions() { + check_metrics!( + "def f(a, b): + if a: + return a + def f(a, b): + if b: + return b", + "foo.py", + PythonParser, + nargs, + [ + (fn_args, 4, usize), + (closure_args, 0, usize), + (nargs_total, 4, usize) + ], + [ + (fn_args_average, 2.0), + (closure_args_average, 0.0), + (nargs_average, 2.0) + ] // 2 functions + ); + + check_metrics!( + "def f(a, b): + if a: + return a + def f(a, b, c): + if b: + return b", + "foo.py", + PythonParser, + nargs, + [ + (fn_args, 5, usize), + (closure_args, 0, usize), + (nargs_total, 5, usize) + ], + [ + (fn_args_average, 2.5), + (closure_args_average, 0.0), + (nargs_average, 2.5) + ] // 2 functions + ); + } + + #[test] + fn rust_functions() { + check_metrics!( + "fn f(a: bool, b: usize) { + if a { + return a; + } + } + fn f1(a: bool, b: usize) { + if a { + return a; + } + }", + "foo.rs", + RustParser, + nargs, + [ + (fn_args, 4, usize), + (closure_args, 0, usize), + (nargs_total, 4, usize) + ], + [ + (fn_args_average, 2.0), + (closure_args_average, 0.0), + (nargs_average, 2.0) + ] // 2 functions + ); + + check_metrics!( + "fn f(a: bool, b: usize) { + if a { + return a; + } + } + fn f1(a: bool, b: usize, c: usize) { + if a { + return a; + } + }", + "foo.rs", + RustParser, + nargs, + [ + (fn_args, 5, usize), + (closure_args, 0, usize), + (nargs_total, 5, usize) + ], + [ + (fn_args_average, 2.5), + (closure_args_average, 0.0), + (nargs_average, 2.5) + ] // 2 functions + ); + } + + #[test] + fn c_functions() { + check_metrics!( + "int f(int a, int b) { + if (a) { + return a; + } + } + int f1(int a, int b) { + if (a) { + return a; + } + }", + "foo.c", + CppParser, + nargs, + [ + (fn_args, 4, usize), + (closure_args, 0, usize), + (nargs_total, 4, usize) + ], + [ + (fn_args_average, 2.0), + (closure_args_average, 0.0), + (nargs_average, 2.0) + ] // 2 functions + ); + + check_metrics!( + "int f(int a, int b) { + if (a) { + return a; + } + } + int f1(int a, int b, int c) { + if (a) { + return a; + } + }", + "foo.c", + CppParser, + nargs, + [ + (fn_args, 5, usize), + (closure_args, 0, usize), + (nargs_total, 5, usize) + ], + [ + (fn_args_average, 2.5), + (closure_args_average, 0.0), + (nargs_average, 2.5) + ] // 2 functions + ); + } + + #[test] + fn javascript_functions() { + check_metrics!( + "function f(a, b) { + return a * b; + } + function f1(a, b) { + return a * b; + }", + "foo.js", + JavascriptParser, + nargs, + [ + (fn_args, 4, usize), + (closure_args, 0, usize), + (nargs_total, 4, usize) + ], + [ + (fn_args_average, 2.0), + (closure_args_average, 0.0), + (nargs_average, 2.0) + ] // 2 functions + ); + + check_metrics!( + "function f(a, b) { + return a * b; + } + function f1(a, b, c) { + return a * b; + }", + "foo.js", + JavascriptParser, + nargs, + [ + (fn_args, 5, usize), + (closure_args, 0, usize), + (nargs_total, 5, usize) + ], + [ + (fn_args_average, 2.5), + (closure_args_average, 0.0), + (nargs_average, 2.5) + ] // 2 functions + ); + } + + #[test] + fn python_nested_functions() { + check_metrics!( + "def f(a, b): + def foo(a): + if a: + return 1 + bar = lambda a: lambda b: b or True or True + return bar(foo(a))(a)", + "foo.py", + PythonParser, + nargs, + [ + (fn_args, 3, usize), + (closure_args, 2, usize), + (nargs_total, 5, usize) + ], + [ + (fn_args_average, 1.5), + (closure_args_average, 1.0), + (nargs_average, 1.25) + ] // 2 functions + 2 lambdas = 4 + ); + } + + #[test] + fn rust_nested_functions() { + check_metrics!( + "fn f(a: i32, b: i32) -> i32 { + fn foo(a: i32) -> i32 { + return a; + } + let bar = |a: i32, b: i32| -> i32 { a + 1 }; + let bar1 = |b: i32| -> i32 { b + 1 }; + return bar(foo(a), a); + }", + "foo.rs", + RustParser, + nargs, + [ + (fn_args, 3, usize), + (closure_args, 3, usize), + (nargs_total, 6, usize) + ], + [ + (fn_args_average, 1.5), + (closure_args_average, 1.5), + (nargs_average, 1.5) + ] // 2 functions + 2 lambdas = 4 + ); + } + + #[test] + fn cpp_nested_functions() { + check_metrics!( + "int f(int a, int b, int c) { + auto foo = [](int x) -> int { return x; }; + auto bar = [](int x, int y) -> int { return x + y; }; + return bar(foo(a), a); + }", + "foo.cpp", + CppParser, + nargs, + [ + (fn_args, 3, usize), + (closure_args, 3, usize), + (nargs_total, 6, usize) + ], + [ + (fn_args_average, 3.0), + (closure_args_average, 1.5), + (nargs_average, 2.0) + ] // 1 function + 2 lambdas = 3 + ); + } + + #[test] + fn javascript_nested_functions() { + check_metrics!( + "function f(a, b) { + function foo(a, c) { + return a; + } + var bar = function (a, b) {return a + b}; + function (a) {return a}; + return bar(foo(a), a); + }", + "foo.js", + JavascriptParser, + nargs, + [ + (fn_args, 6, usize), + (closure_args, 1, usize), + (nargs_total, 7, usize) + ], + [ + (fn_args_average, 2.), + (closure_args_average, 1.), + (nargs_average, 1.75) + ] // 3 functions + 1 lambdas = 4 + ); + } +} diff --git a/src/output/dump_metrics.rs b/src/output/dump_metrics.rs index 286c13281..fbb671e00 100644 --- a/src/output/dump_metrics.rs +++ b/src/output/dump_metrics.rs @@ -4,10 +4,10 @@ use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, StandardStreamLoc use crate::cognitive; use crate::cyclomatic; use crate::exit; -use crate::fn_args; use crate::halstead; use crate::loc; use crate::mi; +use crate::nargs; use crate::nom; use crate::spaces::{CodeMetrics, FuncSpace}; @@ -255,21 +255,24 @@ fn dump_mi( } fn dump_nargs( - stats: &fn_args::Stats, + stats: &nargs::Stats, prefix: &str, last: bool, stdout: &mut StandardStreamLock, ) -> std::io::Result<()> { - let pref = if last { "`- " } else { "|- " }; + let (pref_child, pref) = if last { (" ", "`- ") } else { ("| ", "|- ") }; color!(stdout, Blue); write!(stdout, "{}{}", prefix, pref)?; color!(stdout, Green, true); - write!(stdout, "nargs: ")?; + writeln!(stdout, "nargs")?; - color!(stdout, White); - writeln!(stdout, "{}", stats.nargs()) + let prefix = format!("{}{}", prefix, pref_child); + dump_value("functions", stats.fn_args(), &prefix, false, stdout)?; + dump_value("closures", stats.closure_args(), &prefix, false, stdout)?; + dump_value("total", stats.nargs_total(), &prefix, false, stdout)?; + dump_value("average", stats.nargs_average(), &prefix, true, stdout) } fn dump_nexits( diff --git a/src/spaces.rs b/src/spaces.rs index 26601e88f..2f9455623 100644 --- a/src/spaces.rs +++ b/src/spaces.rs @@ -8,11 +8,11 @@ use crate::node::Node; use crate::cognitive::{self, Cognitive}; use crate::cyclomatic::{self, Cyclomatic}; use crate::exit::{self, Exit}; -use crate::fn_args::{self, NArgs}; use crate::getter::Getter; use crate::halstead::{self, Halstead, HalsteadMaps}; use crate::loc::{self, Loc}; use crate::mi::{self, Mi}; +use crate::nargs::{self, NArgs}; use crate::nom::{self, Nom}; use crate::dump_metrics::*; @@ -60,7 +60,7 @@ impl fmt::Display for SpaceKind { #[derive(Debug, Clone, Serialize)] pub struct CodeMetrics { /// `NArgs` data - pub nargs: fn_args::Stats, + pub nargs: nargs::Stats, /// `NExits` data pub nexits: exit::Stats, pub cognitive: cognitive::Stats, @@ -85,7 +85,7 @@ impl Default for CodeMetrics { loc: loc::Stats::default(), nom: nom::Stats::default(), mi: mi::Stats::default(), - nargs: fn_args::Stats::default(), + nargs: nargs::Stats::default(), nexits: exit::Stats::default(), } } @@ -181,13 +181,19 @@ fn compute_halstead_and_mi(state: &mut State) { #[inline(always)] fn compute_averages(state: &mut State) { + let nom_functions = state.space.metrics.nom.functions() as usize; + let nom_closures = state.space.metrics.nom.closures() as usize; let nom_total = state.space.metrics.nom.total() as usize; // Cognitive average state.space.metrics.cognitive.finalize(nom_total); // Nexit average state.space.metrics.nexits.finalize(nom_total); // Nargs average - state.space.metrics.nargs.finalize(nom_total); + state + .space + .metrics + .nargs + .finalize(nom_functions, nom_closures); } fn finalize(state_stack: &mut Vec, diff_level: usize) { diff --git a/src/traits.rs b/src/traits.rs index f855da1da..c73350818 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -7,12 +7,12 @@ use crate::checker::Checker; use crate::cognitive::Cognitive; use crate::cyclomatic::Cyclomatic; use crate::exit::Exit; -use crate::fn_args::NArgs; use crate::getter::Getter; use crate::halstead::Halstead; use crate::langs::*; use crate::loc::Loc; use crate::mi::Mi; +use crate::nargs::NArgs; use crate::node::Node; use crate::nom::Nom; use crate::parser::Filter;