From 14794bc4c64719a7cd2f25b494b985034976132a Mon Sep 17 00:00:00 2001 From: Elijah Zupancic Date: Thu, 4 Jun 2026 20:29:44 -0700 Subject: [PATCH] refactor(metrics): unify average-divisor guard, cyclomatic per-function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extract a single `crate::metrics::average(sum, count)` helper that applies the `.max(1)` divide-by-zero guard (#428) in one place, and route every metric average through it. This removes the former reliance on a counter that merely defaulted to 1 for cyclomatic and nom, and adds the guard to the previously-unguarded per-space averages (loc, abc, tokens). Make `cyclomatic.average` / `cyclomatic.modified.average` per-function: the divisor is now the count of function/closure spaces in the subtree (`function_spaces`), the per-function convention cognitive/exit/nargs use, instead of the per-space count (which also divided by classes, structs, and the file unit). The count is seeded in `FuncSpace::new` from the space kind and summed on merge, so it is sourced independently of the Nom metric and a cyclomatic-only selection still divides per function without pulling a nom block into the output. Metric values change for cyclomatic.average and modified.average only; sum/min/max and every other metric (including MI and WMC, which consume the cyclomatic sum) are unchanged. The denominator equals nom.total() wherever a closure opens its own space; a spaceless closure such as a Python lambda is counted by cognitive but not as a separate cyclomatic divisor unit (pinned by a regression test). Snapshots — including the big-code-analysis-output submodule — are re-baselined accordingly. Part of #505. Folded into the 2.0 re-baseline. Fixes #512 --- CHANGELOG.md | 34 + big-code-analysis-web/src/web/server_tests.rs | 6 +- src/metrics/abc.rs | 6 +- src/metrics/cognitive.rs | 10 +- src/metrics/cyclomatic.rs | 2464 +++++++++-------- src/metrics/exit.rs | 10 +- src/metrics/loc.rs | 10 +- src/metrics/mod.rs | 35 + src/metrics/nargs.rs | 9 +- src/metrics/nom.rs | 6 +- ...sts__bash_case_bare_wildcard_excluded.snap | 4 +- ...yclomatic__tests__bash_case_statement.snap | 4 +- ...atic__tests__bash_nested_control_flow.snap | 4 +- ...clomatic__tests__bash_simple_function.snap | 4 +- ...s__cyclomatic__tests__bash_while_loop.snap | 4 +- ...s__cyclomatic__tests__kotlin_for_loop.snap | 4 +- ...atic__tests__kotlin_logical_operators.snap | 4 +- ..._cyclomatic__tests__kotlin_while_loop.snap | 4 +- ...cs__cyclomatic__tests__mozjs_for_loop.snap | 4 +- ...matic__tests__mozjs_logical_operators.snap | 4 +- ...__cyclomatic__tests__mozjs_while_loop.snap | 4 +- ...yclomatic__tests__php_switch_modified.snap | 4 +- ...yclomatic__tests__ruby_case_when_arms.snap | 4 +- ...clomatic__tests__ruby_nested_branches.snap | 4 +- ...clomatic__tests__ruby_rescue_modifier.snap | 4 +- ...yclomatic__tests__tcl_1_level_nesting.snap | 4 +- ...__cyclomatic__tests__tcl_catch_branch.snap | 4 +- ..._cyclomatic__tests__tcl_elseif_branch.snap | 4 +- ...lomatic__tests__tcl_logical_operators.snap | 4 +- ...rics__cyclomatic__tests__tsx_for_loop.snap | 4 +- ...lomatic__tests__tsx_logical_operators.snap | 4 +- ...etrics__cyclomatic__tests__tsx_switch.snap | 4 +- ...yclomatic__tests__tsx_switch_modified.snap | 4 +- ...ics__cyclomatic__tests__tsx_try_catch.snap | 4 +- ...cs__cyclomatic__tests__tsx_while_loop.snap | 4 +- ...yclomatic__tests__typescript_for_loop.snap | 4 +- ...__tests__typescript_logical_operators.snap | 4 +- ...clomatic__tests__typescript_try_catch.snap | 4 +- ...lomatic__tests__typescript_while_loop.snap | 4 +- src/metrics/tokens.rs | 2 +- src/spaces.rs | 12 +- tests/repositories/big-code-analysis-output | 2 +- tests/snapshots/csv_test__csv_cpp_widget.snap | 6 +- .../csv_test__csv_python_greeter.snap | 4 +- .../snapshots/csv_test__csv_rust_counter.snap | 4 +- 45 files changed, 1531 insertions(+), 1205 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 725acb11..db5250f4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -475,6 +475,40 @@ for historical reference. ### Changed +- Unified the "average over a count" divisor convention and its + divide-by-zero guard across the metric suite, and **re-baselined the + cyclomatic averages** as part of the `2.0` re-baseline + ([#512](https://github.com/dekobon/big-code-analysis/issues/512), + part of [#505](https://github.com/dekobon/big-code-analysis/issues/505)). + - A single shared `average(sum, count)` helper now applies the `.max(1)` + divisor guard (added for + [#428](https://github.com/dekobon/big-code-analysis/issues/428)) for + every metric average instead of repeating it per call site. This + removes the former reliance on a counter that merely defaulted to `1` + for `cyclomatic`, `nom`, and the previously-unguarded per-space + averages (`loc`, `abc`, `tokens`). Behaviour-preserving for every + metric except `cyclomatic` (below): the guarded divisor is identical + whenever the count is already non-zero. + - **Metric values change for `cyclomatic.average` and + `cyclomatic.modified.average` only.** They are now **per function**: + the divisor is the number of function/closure *spaces* in the subtree + — the per-function convention `cognitive` / `exit` / `nargs` use — + rather than the previous per-space count (which also divided by + classes, structs, and the file unit and so reported a smaller + average). Files with classes/structs/units see a larger average. + `cyclomatic.sum` / `min` / `max` and every other metric — including + the Maintainability Index and WMC, which consume the cyclomatic + *sum* — are unchanged. (The divisor counts the spaces that each carry + a cyclomatic value, so it matches `cognitive`'s function/closure count + wherever every closure opens its own space; a closure form that opens + no space, such as a Python `lambda`, is counted by `cognitive` but not + as a separate cyclomatic divisor unit.) + - The divisor is sourced from the space kind during finalization, not + from the `Nom` metric, so a `cyclomatic`-only metric selection still + divides per function without pulling a `nom` block into the output. + - `nom`'s own averages stay **per space** (it is the count metric; + a per-function divisor would be circular). + - `get_ops`, `metrics_from_tree`, and the doc-hidden `operands_and_operators` are now `#[deprecated]` in favour of the explicit-name `Ast` seams (`Ast::ops`, `Ast::from_tree_sitter`), which diff --git a/big-code-analysis-web/src/web/server_tests.rs b/big-code-analysis-web/src/web/server_tests.rs index 39f66647..284dde5f 100644 --- a/big-code-analysis-web/src/web/server_tests.rs +++ b/big-code-analysis-web/src/web/server_tests.rs @@ -499,7 +499,7 @@ async fn test_web_metrics_json() { "spaces": {"kind": "unit", "start_line": 1, "end_line": 4, - "metrics": {"cyclomatic": {"sum": 2.0, "average": 1.0, "min":1.0, "max":1.0, "modified": {"sum": 2.0, "average": 1.0, "min":1.0, "max":1.0}}, + "metrics": {"cyclomatic": {"sum": 2.0, "average": 2.0, "min":1.0, "max":1.0, "modified": {"sum": 2.0, "average": 2.0, "min":1.0, "max":1.0}}, "cognitive": {"sum": 0.0, "average": 0.0, "min":0.0, "max":0.0}, "nargs": {"function_args": 0.0, "function_args_average": 0.0, "closure_args": 0.0, "closure_args_average": 0.0, "total": 0.0, "average": 0.0, "closure_args_max": 0.0, "closure_args_min": 0.0, "function_args_max": 0.0, "function_args_min": 0.0}, "nexits": {"sum": 0.0, "average": 0.0,"min":0.0,"max":0.0}, @@ -588,7 +588,7 @@ async fn test_web_metrics_json_unit() { "spaces": {"kind": "unit", "start_line": 1, "end_line": 2, - "metrics": {"cyclomatic": {"sum": 2.0, "average": 1.0, "min":1.0, "max":1.0, "modified": {"sum": 2.0, "average": 1.0, "min":1.0, "max":1.0}}, + "metrics": {"cyclomatic": {"sum": 2.0, "average": 2.0, "min":1.0, "max":1.0, "modified": {"sum": 2.0, "average": 2.0, "min":1.0, "max":1.0}}, "cognitive": {"sum": 0.0, "average": 0.0 , "min":0.0, "max":0.0}, "nargs": {"function_args": 0.0, "function_args_average": 0.0, "closure_args": 0.0, "closure_args_average": 0.0, "total": 0.0, "average": 0.0, "closure_args_max": 0.0, "closure_args_min": 0.0, "function_args_max": 0.0, "function_args_min": 0.0}, "nexits": {"sum": 0.0, "average": 0.0,"min":0.0,"max":0.0}, @@ -644,7 +644,7 @@ async fn test_web_metrics_plain() { "spaces": {"kind": "unit", "start_line": 1, "end_line": 2, - "metrics": {"cyclomatic": {"sum": 2.0, "average": 1.0, "min": 1.0,"max": 1.0, "modified": {"sum": 2.0, "average": 1.0, "min": 1.0,"max": 1.0}}, + "metrics": {"cyclomatic": {"sum": 2.0, "average": 2.0, "min": 1.0,"max": 1.0, "modified": {"sum": 2.0, "average": 2.0, "min": 1.0,"max": 1.0}}, "cognitive": {"sum": 0.0, "average": 0.0 , "min":0.0, "max":0.0}, "nargs": {"function_args": 0.0, "function_args_average": 0.0, "closure_args": 0.0, "closure_args_average": 0.0, "total": 0.0, "average": 0.0, "closure_args_max": 0.0, "closure_args_min": 0.0, "function_args_max": 0.0, "function_args_min": 0.0}, "nexits": {"sum": 0.0, "average": 0.0,"min":0.0,"max":0.0}, diff --git a/src/metrics/abc.rs b/src/metrics/abc.rs index 17d79e42..5150374a 100644 --- a/src/metrics/abc.rs +++ b/src/metrics/abc.rs @@ -241,7 +241,7 @@ impl Stats { /// assignments value for the number of spaces. #[must_use] pub fn assignments_average(&self) -> f64 { - self.assignments_sum() / self.space_count as f64 + crate::metrics::average(self.assignments_sum(), self.space_count) } /// Returns the `Abc` assignments minimum value. @@ -283,7 +283,7 @@ impl Stats { /// branches value for the number of spaces. #[must_use] pub fn branches_average(&self) -> f64 { - self.branches_sum() / self.space_count as f64 + crate::metrics::average(self.branches_sum(), self.space_count) } /// Returns the `Abc` branches minimum value. @@ -323,7 +323,7 @@ impl Stats { /// conditions value for the number of spaces. #[must_use] pub fn conditions_average(&self) -> f64 { - self.conditions_sum() / self.space_count as f64 + crate::metrics::average(self.conditions_sum(), self.space_count) } /// Returns the `Abc` conditions minimum value. diff --git a/src/metrics/cognitive.rs b/src/metrics/cognitive.rs index a9ea3426..a0b90be0 100644 --- a/src/metrics/cognitive.rs +++ b/src/metrics/cognitive.rs @@ -143,12 +143,14 @@ impl Stats { /// This value is computed dividing the `Cognitive Complexity` value /// for the total number of functions/closures in a space. /// - /// The divisor is guarded with `.max(1)` so a space with no - /// counted functions (or one where `Nom` was not selected) - /// degrades to `sum / 1` instead of producing `inf`/`NaN` (#428). + /// The per-function divisor (shared with `cyclomatic`/`exit`/`nargs`, + /// #512) is guarded with `.max(1)` via the shared `average` helper, so + /// a space with no counted functions (or one where `Nom` was not + /// selected) degrades to `sum / 1` instead of producing `inf`/`NaN` + /// (#428). #[must_use] pub fn cognitive_average(&self) -> f64 { - self.cognitive_sum() / self.total_space_functions.max(1) as f64 + crate::metrics::average(self.cognitive_sum(), self.total_space_functions) } #[inline] pub(crate) fn compute_sum(&mut self) { diff --git a/src/metrics/cyclomatic.rs b/src/metrics/cyclomatic.rs index e3fac4ec..5d11488e 100644 --- a/src/metrics/cyclomatic.rs +++ b/src/metrics/cyclomatic.rs @@ -36,7 +36,24 @@ use crate::*; pub struct Stats { cyclomatic_sum: f64, cyclomatic: f64, - n: usize, + /// Number of function/closure spaces in this subtree, used as the + /// per-function divisor for the cyclomatic averages. + /// + /// Seeded to `1` for a [`SpaceKind::Function`][crate::SpaceKind] + /// space and `0` otherwise (see [`Stats::note_function_space`]), then + /// summed across child spaces in [`Stats::merge`]. This is the + /// per-function divisor convention shared with `cognitive`/`exit`/ + /// `nargs`, sourced independently of whether the `Nom` metric was + /// selected (#512). + /// + /// It counts the function/closure *spaces* — the spaces that each + /// contribute a base cyclomatic value to the sum — so it equals + /// `nom.total()` wherever every function and closure opens its own + /// space (the common case). The known exception is a closure form + /// that opens no space, such as a Python `lambda`: `nom` counts it + /// but it folds its decisions into the enclosing space, so + /// `function_spaces` does not count it as a separate divisor unit. + function_spaces: usize, cyclomatic_max: f64, cyclomatic_min: f64, cyclomatic_modified_sum: f64, @@ -50,7 +67,7 @@ impl Default for Stats { Self { cyclomatic_sum: 0., cyclomatic: 1., - n: 1, + function_spaces: 0, cyclomatic_max: 0., cyclomatic_min: f64::MAX, cyclomatic_modified_sum: 0., @@ -112,7 +129,7 @@ impl Stats { self.cyclomatic_max = self.cyclomatic_max.max(other.cyclomatic_max); self.cyclomatic_min = self.cyclomatic_min.min(other.cyclomatic_min); self.cyclomatic_sum += other.cyclomatic_sum; - self.n += other.n; + self.function_spaces += other.function_spaces; self.cyclomatic_modified_max = self .cyclomatic_modified_max @@ -136,9 +153,16 @@ impl Stats { } /// Returns the average standard cyclomatic complexity. + /// + /// The divisor is the number of function/closure spaces in the + /// subtree (`function_spaces`), guarded with `.max(1)` via the shared + /// `average` helper. This is the per-function convention shared with + /// `cognitive`/`exit`/`nargs`; before #512 the divisor was the + /// per-space count `n`, which also counted classes, structs, and the + /// file unit and so reported a different — lower — average. #[must_use] pub fn cyclomatic_average(&self) -> f64 { - self.cyclomatic_sum() / self.n as f64 + crate::metrics::average(self.cyclomatic_sum(), self.function_spaces) } /// Returns the maximum standard cyclomatic complexity. @@ -184,9 +208,12 @@ impl Stats { } /// Returns the average modified cyclomatic complexity. + /// + /// Uses the same per-function divisor (`function_spaces`, guarded by + /// the shared `average` helper) as [`Stats::cyclomatic_average`]. #[must_use] pub fn cyclomatic_modified_average(&self) -> f64 { - self.cyclomatic_modified_sum() / self.n as f64 + crate::metrics::average(self.cyclomatic_modified_sum(), self.function_spaces) } /// Returns the maximum modified cyclomatic complexity. @@ -208,6 +235,20 @@ impl Stats { } } + /// Marks this space as a function/closure space, seeding the + /// per-function divisor (`function_spaces`) with `1`. + /// + /// Called once at space construction for every + /// [`SpaceKind::Function`][crate::SpaceKind] space; non-function + /// spaces leave the seed at its `0` default. [`Stats::merge`] then + /// sums the seeds so each space's `function_spaces` reflects the + /// function/closure count of its whole subtree — independently of + /// the `Nom` metric (#512). + #[inline] + pub(crate) fn note_function_space(&mut self) { + self.function_spaces = 1; + } + #[inline] pub(crate) fn compute_sum(&mut self) { self.cyclomatic_sum += self.cyclomatic; @@ -1143,6 +1184,123 @@ mod tests { assert_eq!(stats.cyclomatic_modified_min(), 0.0); } + /// A `Stats::default()` with no function spaces and an unguarded + /// divisor would divide by zero. The shared `average` helper guards + /// the divisor with `.max(1)`, so a function-less aggregate yields a + /// finite `0.0` rather than `NaN` (#512 — the guard `cognitive`/ + /// `exit`/`nargs` already had, now applied to cyclomatic too). + #[test] + fn cyclomatic_no_function_spaces_average_is_finite() { + let stats = Stats::default(); + assert_eq!(stats.cyclomatic_average(), 0.0); + assert_eq!(stats.cyclomatic_modified_average(), 0.0); + } + + /// #512: the cyclomatic average divisor is now the per-function count + /// (`function_spaces`), reconciled with the `cognitive`/`exit`/`nargs` + /// convention, *not* the per-space count `n` it used before. For a + /// file with one class holding two methods the spaces are + /// `{unit, class, method, method}` (4) but only the two methods are + /// functions, so the divisor is 2. + /// + /// Here every function/closure opens its own space, so + /// `function_spaces == nom.total()` and + /// `cyclomatic_average == cyclomatic_sum / nom.total()` — the same + /// denominator `cognitive_average` divides by. (That equality can + /// break for closure forms that open no space, e.g. Python lambdas — + /// see `cyclomatic_python_lambda_divisor_excludes_spaceless_closure`.) + /// Before #512 the divisor was 4 (every space, base 1 each) and the + /// averages were two-thirds of these values (`6 / 4 == 1.5`). + #[test] + fn cyclomatic_average_is_per_function_512() { + check_metrics::( + "class A { + int f(int x) { return x > 0 ? 1 : 2; } + int g(int x) { return x > 0 ? 1 : 2; } + }", + "foo.cs", + |metric| { + // Sum is over every space's base 1 plus its decisions: + // unit(1) + class(1) + f(1 + ternary 1) + g(1 + ternary 1) + // = 6. + assert_eq!(metric.cyclomatic.cyclomatic_sum(), 6.0); + // Divisor is the two function spaces, not the four total + // spaces: 6 / 2 = 3.0 (was 6 / 4 = 1.5 before #512). + assert_eq!(metric.cyclomatic.cyclomatic_average(), 3.0); + assert_eq!(metric.cyclomatic.cyclomatic_modified_average(), 3.0); + // Reconciliation invariant: cyclomatic divides by the same + // function/closure count cognitive does. + assert_eq!( + metric.cyclomatic.cyclomatic_average(), + metric.cyclomatic.cyclomatic_sum() / metric.nom.total() + ); + assert_eq!(metric.nom.total(), 2.0); + }, + ); + } + + /// #512: the per-function divisor is sourced from the space kind, not + /// from the `Nom` metric, so selecting `cyclomatic` *alone* (which + /// does not pull `Nom` in via the metric-selection dependency graph) + /// still divides by the function count. This guards the load-bearing + /// "one selected metric emits exactly that metric" contract: coupling + /// cyclomatic to `nom` to obtain the divisor would have leaked a + /// `nom` block into a cyclomatic-only selection. + /// + /// `nom.total()` is `0.0` here (Nom was never computed) yet the + /// average is still the correct per-function `6 / 2 == 3.0` — proof + /// the divisor does not read `nom`. + #[test] + fn cyclomatic_average_per_function_without_nom_512() { + let space = crate::analyze( + crate::Source::new( + crate::LANG::Csharp, + b"class A {\n int f(int x) { return x > 0 ? 1 : 2; }\n int g(int x) { return x > 0 ? 1 : 2; }\n}", + ) + .with_name(Some("foo.cs".to_owned())), + crate::MetricsOptions::default().with_only(&[crate::Metric::Cyclomatic]), + ) + .expect("analyze must succeed on a well-formed C# fixture"); + + let c = &space.metrics.cyclomatic; + assert_eq!(c.cyclomatic_sum(), 6.0); + assert_eq!(c.cyclomatic_average(), 3.0); + assert_eq!(c.cyclomatic_modified_average(), 3.0); + // Nom was not selected, so its count stays at the zero default — + // the cyclomatic divisor must not depend on it. + assert_eq!(space.metrics.nom.total(), 0.0); + } + + /// #512 edge case: a Python `lambda` is counted by `nom` (as a + /// closure) but opens **no** function space — it folds its decisions + /// into the enclosing space. So `function_spaces` counts only the + /// spaces that actually carry a cyclomatic value (here the single + /// `def`), and the cyclomatic divisor is `1`, not `nom.total()`'s `2`. + /// + /// This documents that the per-function reconciliation with + /// `cognitive` is exact only where every function/closure opens its + /// own space; for spaceless closures `function_spaces` is the divisor + /// that matches the spaces contributing to `cyclomatic_sum`. The + /// behaviour is intentional, not a bug — pinning it so a future change + /// to lambda space-handling is a deliberate, visible decision. + #[test] + fn cyclomatic_python_lambda_divisor_excludes_spaceless_closure() { + check_metrics::( + "def f(x):\n return x if x > 0 else -x\ng = lambda y: y if y else 0\n", + "p.py", + |metric| { + // sum: unit(1 + lambda's ternary 1) + f(1 + ternary 1) = 4. + assert_eq!(metric.cyclomatic.cyclomatic_sum(), 4.0); + // nom counts the lambda as a closure, so total == 2 … + assert_eq!(metric.nom.total(), 2.0); + // … but only the `def` opens a function space, so the + // cyclomatic divisor is 1: 4 / 1 = 4.0, which deliberately + // differs from cyclomatic_sum / nom.total() (4 / 2 = 2.0). + assert_eq!(metric.cyclomatic.cyclomatic_average(), 4.0); + }, + ); + } + /// A plain `if/else` must not be credited /// as a loop-`else`. The `Else` arm of `impl Cyclomatic for /// PythonCode` previously fired for every `else_clause` because @@ -1168,19 +1326,20 @@ mod tests { assert_eq!(metric.cyclomatic.cyclomatic_max(), 2.0); insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 3.0, - "average": 1.5, - "min": 1.0, - "max": 2.0, - "modified": { - "sum": 3.0, - "average": 1.5, - "min": 1.0, - "max": 2.0 - } - }"### + @r#" + { + "sum": 3.0, + "average": 3.0, + "min": 1.0, + "max": 2.0, + "modified": { + "sum": 3.0, + "average": 3.0, + "min": 1.0, + "max": 2.0 + } + } + "# ); }, ); @@ -1385,19 +1544,20 @@ mod tests { // nspace = 2 (func and unit) insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 6.0, - "average": 3.0, - "min": 1.0, - "max": 5.0, - "modified": { - "sum": 6.0, - "average": 3.0, - "min": 1.0, - "max": 5.0 - } - }"### + @r#" + { + "sum": 6.0, + "average": 6.0, + "min": 1.0, + "max": 5.0, + "modified": { + "sum": 6.0, + "average": 6.0, + "min": 1.0, + "max": 5.0 + } + } + "# ); }, ); @@ -1425,19 +1585,20 @@ mod tests { // function space alone holds 1 decision -> max = 2 insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 3.0, - "average": 1.5, - "min": 1.0, - "max": 2.0, - "modified": { - "sum": 3.0, - "average": 1.5, - "min": 1.0, - "max": 2.0 - } - }"### + @r#" + { + "sum": 3.0, + "average": 3.0, + "min": 1.0, + "max": 2.0, + "modified": { + "sum": 3.0, + "average": 3.0, + "min": 1.0, + "max": 2.0 + } + } + "# ); }, ); @@ -1473,19 +1634,20 @@ mod tests { // + 1 (`if` keyword in the guard) = 4. insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 5.0, - "average": 2.5, - "min": 1.0, - "max": 4.0, - "modified": { - "sum": 4.0, - "average": 2.0, - "min": 1.0, - "max": 3.0 - } - }"### + @r#" + { + "sum": 5.0, + "average": 5.0, + "min": 1.0, + "max": 4.0, + "modified": { + "sum": 4.0, + "average": 4.0, + "min": 1.0, + "max": 3.0 + } + } + "# ); }, ); @@ -1503,19 +1665,20 @@ mod tests { // nspace = 2 (func and unit) insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 4.0, - "average": 2.0, - "min": 1.0, - "max": 3.0, - "modified": { - "sum": 4.0, - "average": 2.0, - "min": 1.0, - "max": 3.0 - } - }"### + @r#" + { + "sum": 4.0, + "average": 4.0, + "min": 1.0, + "max": 3.0, + "modified": { + "sum": 4.0, + "average": 4.0, + "min": 1.0, + "max": 3.0 + } + } + "# ); }, ); @@ -1540,12 +1703,12 @@ mod tests { @r#" { "sum": 5.0, - "average": 2.5, + "average": 5.0, "min": 1.0, "max": 4.0, "modified": { "sum": 4.0, - "average": 2.0, + "average": 4.0, "min": 1.0, "max": 3.0 } @@ -1573,19 +1736,20 @@ mod tests { |metric| { insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 4.0, - "average": 2.0, - "min": 1.0, - "max": 3.0, - "modified": { - "sum": 3.0, - "average": 1.5, - "min": 1.0, - "max": 2.0 - } - }"### + @r#" + { + "sum": 4.0, + "average": 4.0, + "min": 1.0, + "max": 3.0, + "modified": { + "sum": 3.0, + "average": 3.0, + "min": 1.0, + "max": 2.0 + } + } + "# ); }, ); @@ -1685,19 +1849,20 @@ mod tests { // nspace = 2 (func and unit) insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 5.0, - "average": 2.5, - "min": 1.0, - "max": 4.0, - "modified": { - "sum": 3.0, - "average": 1.5, - "min": 1.0, - "max": 2.0 - } - }"### + @r#" + { + "sum": 5.0, + "average": 5.0, + "min": 1.0, + "max": 4.0, + "modified": { + "sum": 3.0, + "average": 3.0, + "min": 1.0, + "max": 2.0 + } + } + "# ); }, ); @@ -1721,19 +1886,20 @@ mod tests { // modified: unit(1) + fn(1) + switch(1) = 3 insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 5.0, - "average": 2.5, - "min": 1.0, - "max": 4.0, - "modified": { - "sum": 3.0, - "average": 1.5, - "min": 1.0, - "max": 2.0 - } - }"### + @r#" + { + "sum": 5.0, + "average": 5.0, + "min": 1.0, + "max": 4.0, + "modified": { + "sum": 3.0, + "average": 3.0, + "min": 1.0, + "max": 2.0 + } + } + "# ); }, ); @@ -1759,19 +1925,20 @@ mod tests { // nspace = 2 (func and unit) insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 5.0, - "average": 2.5, - "min": 1.0, - "max": 4.0, - "modified": { - "sum": 5.0, - "average": 2.5, - "min": 1.0, - "max": 4.0 - } - }"### + @r#" + { + "sum": 5.0, + "average": 5.0, + "min": 1.0, + "max": 4.0, + "modified": { + "sum": 5.0, + "average": 5.0, + "min": 1.0, + "max": 4.0 + } + } + "# ); }, ); @@ -1807,19 +1974,20 @@ mod tests { // nspace = 2 (func and unit) insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 7.0, - "average": 3.5, - "min": 3.0, - "max": 4.0, - "modified": { - "sum": 7.0, - "average": 3.5, - "min": 3.0, - "max": 4.0 - } - }"### + @r#" + { + "sum": 7.0, + "average": 7.0, + "min": 3.0, + "max": 4.0, + "modified": { + "sum": 7.0, + "average": 7.0, + "min": 3.0, + "max": 4.0 + } + } + "# ); }, ); @@ -1859,19 +2027,20 @@ mod tests { // nspace = 2 (func and unit) insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 7.0, - "average": 3.5, - "min": 3.0, - "max": 4.0, - "modified": { - "sum": 7.0, - "average": 3.5, - "min": 3.0, - "max": 4.0 - } - }"### + @r#" + { + "sum": 7.0, + "average": 7.0, + "min": 3.0, + "max": 4.0, + "modified": { + "sum": 7.0, + "average": 7.0, + "min": 3.0, + "max": 4.0 + } + } + "# ); }, ); @@ -1903,19 +2072,20 @@ mod tests { // nspace = 4 (unit, class and 2 methods) insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 9.0, - "average": 2.25, - "min": 1.0, - "max": 3.0, - "modified": { - "sum": 9.0, - "average": 2.25, - "min": 1.0, - "max": 3.0 - } - }"### + @r#" + { + "sum": 9.0, + "average": 4.5, + "min": 1.0, + "max": 3.0, + "modified": { + "sum": 9.0, + "average": 4.5, + "min": 1.0, + "max": 3.0 + } + } + "# ); }, ); @@ -1962,19 +2132,20 @@ mod tests { // nspace = 5 (unit, class and 3 methods) insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 11.0, - "average": 2.2, - "min": 1.0, - "max": 3.0, - "modified": { - "sum": 10.0, - "average": 2.0, - "min": 1.0, - "max": 3.0 - } - }"### + @r#" + { + "sum": 11.0, + "average": 3.6666666666666665, + "min": 1.0, + "max": 3.0, + "modified": { + "sum": 10.0, + "average": 3.3333333333333335, + "min": 1.0, + "max": 3.0 + } + } + "# ); }, ); @@ -2004,19 +2175,20 @@ mod tests { // modified: unit(1) + class(1) + fn(1) + switch(1) = 4 insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 5.0, - "average": 1.6666666666666667, - "min": 1.0, - "max": 3.0, - "modified": { - "sum": 4.0, - "average": 1.3333333333333333, - "min": 1.0, - "max": 2.0 - } - }"### + @r#" + { + "sum": 5.0, + "average": 5.0, + "min": 1.0, + "max": 3.0, + "modified": { + "sum": 4.0, + "average": 4.0, + "min": 1.0, + "max": 2.0 + } + } + "# ); }, ); @@ -2046,19 +2218,20 @@ mod tests { |metric| { insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 9.0, - "average": 2.25, - "min": 1.0, - "max": 3.0, - "modified": { - "sum": 9.0, - "average": 2.25, - "min": 1.0, - "max": 3.0 - } - }"### + @r#" + { + "sum": 9.0, + "average": 4.5, + "min": 1.0, + "max": 3.0, + "modified": { + "sum": 9.0, + "average": 4.5, + "min": 1.0, + "max": 3.0 + } + } + "# ); }, ); @@ -2104,19 +2277,20 @@ mod tests { |metric| { insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 11.0, - "average": 2.2, - "min": 1.0, - "max": 3.0, - "modified": { - "sum": 10.0, - "average": 2.0, - "min": 1.0, - "max": 3.0 - } - }"### + @r#" + { + "sum": 11.0, + "average": 3.6666666666666665, + "min": 1.0, + "max": 3.0, + "modified": { + "sum": 10.0, + "average": 3.3333333333333335, + "min": 1.0, + "max": 3.0 + } + } + "# ); }, ); @@ -2138,19 +2312,20 @@ mod tests { |metric| { insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 5.0, - "average": 1.25, - "min": 1.0, - "max": 2.0, - "modified": { - "sum": 5.0, - "average": 1.25, - "min": 1.0, - "max": 2.0 - } - }"### + @r#" + { + "sum": 5.0, + "average": 2.5, + "min": 1.0, + "max": 2.0, + "modified": { + "sum": 5.0, + "average": 2.5, + "min": 1.0, + "max": 2.0 + } + } + "# ); }, ); @@ -2181,19 +2356,20 @@ mod tests { assert_eq!(metric.cyclomatic.cyclomatic_modified_sum(), 4.0); insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 6.0, - "average": 2.0, - "min": 1.0, - "max": 4.0, - "modified": { - "sum": 4.0, - "average": 1.3333333333333333, - "min": 1.0, - "max": 2.0 - } - }"### + @r#" + { + "sum": 6.0, + "average": 6.0, + "min": 1.0, + "max": 4.0, + "modified": { + "sum": 4.0, + "average": 4.0, + "min": 1.0, + "max": 2.0 + } + } + "# ); }, ); @@ -2347,29 +2523,30 @@ mod tests { // modified: unit(1) + class(1) + fn(1) + switch(1) = 4 insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 5.0, - "average": 1.6666666666666667, - "min": 1.0, - "max": 3.0, - "modified": { - "sum": 4.0, - "average": 1.3333333333333333, - "min": 1.0, - "max": 2.0 - } - }"### - ); - }, - ); - } - - #[test] - fn csharp_null_coalescing_and_conditional_access() { - // Each `??` and `?.` is +1 cyclomatic. - check_metrics::( - "public class A { + @r#" + { + "sum": 5.0, + "average": 5.0, + "min": 1.0, + "max": 3.0, + "modified": { + "sum": 4.0, + "average": 4.0, + "min": 1.0, + "max": 2.0 + } + } + "# + ); + }, + ); + } + + #[test] + fn csharp_null_coalescing_and_conditional_access() { + // Each `??` and `?.` is +1 cyclomatic. + check_metrics::( + "public class A { public int? Get(string s, A b) { return s?.Length ?? b?.Get(null, null) ?? 0; } @@ -2378,19 +2555,20 @@ mod tests { |metric| { insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 7.0, - "average": 2.3333333333333335, - "min": 1.0, - "max": 5.0, - "modified": { - "sum": 7.0, - "average": 2.3333333333333335, - "min": 1.0, - "max": 5.0 - } - }"### + @r#" + { + "sum": 7.0, + "average": 7.0, + "min": 1.0, + "max": 5.0, + "modified": { + "sum": 7.0, + "average": 7.0, + "min": 1.0, + "max": 5.0 + } + } + "# ); }, ); @@ -2411,19 +2589,20 @@ mod tests { |metric| { insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 4.0, - "average": 2.0, - "min": 1.0, - "max": 3.0, - "modified": { - "sum": 4.0, - "average": 2.0, - "min": 1.0, - "max": 3.0 - } - }"### + @r#" + { + "sum": 4.0, + "average": 4.0, + "min": 1.0, + "max": 3.0, + "modified": { + "sum": 4.0, + "average": 4.0, + "min": 1.0, + "max": 3.0 + } + } + "# ); }, ); @@ -2452,19 +2631,20 @@ mod tests { |metric| { insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 5.0, - "average": 2.5, - "min": 1.0, - "max": 4.0, - "modified": { - "sum": 3.0, - "average": 1.5, - "min": 1.0, - "max": 2.0 - } - }"### + @r#" + { + "sum": 5.0, + "average": 5.0, + "min": 1.0, + "max": 4.0, + "modified": { + "sum": 3.0, + "average": 3.0, + "min": 1.0, + "max": 2.0 + } + } + "# ); }, ); @@ -2487,19 +2667,20 @@ mod tests { // modified: unit(1) + fn(1) + switch(1) = 3 insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 5.0, - "average": 2.5, - "min": 1.0, - "max": 4.0, - "modified": { - "sum": 3.0, - "average": 1.5, - "min": 1.0, - "max": 2.0 - } - }"### + @r#" + { + "sum": 5.0, + "average": 5.0, + "min": 1.0, + "max": 4.0, + "modified": { + "sum": 3.0, + "average": 3.0, + "min": 1.0, + "max": 2.0 + } + } + "# ); }, ); @@ -2515,19 +2696,20 @@ mod tests { // nspace = 2 (file unit + func), each base 1. insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 2.0, - "average": 1.0, - "min": 1.0, - "max": 1.0, - "modified": { - "sum": 2.0, - "average": 1.0, - "min": 1.0, - "max": 1.0 - } - }"### + @r#" + { + "sum": 2.0, + "average": 2.0, + "min": 1.0, + "max": 1.0, + "modified": { + "sum": 2.0, + "average": 2.0, + "min": 1.0, + "max": 1.0 + } + } + "# ); }, ); @@ -2548,19 +2730,20 @@ mod tests { // not counted again. insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 3.0, - "average": 1.5, - "min": 1.0, - "max": 2.0, - "modified": { - "sum": 3.0, - "average": 1.5, - "min": 1.0, - "max": 2.0 - } - }"### + @r#" + { + "sum": 3.0, + "average": 3.0, + "min": 1.0, + "max": 2.0, + "modified": { + "sum": 3.0, + "average": 3.0, + "min": 1.0, + "max": 2.0 + } + } + "# ); }, ); @@ -2584,19 +2767,20 @@ mod tests { // if contributes +1. insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 5.0, - "average": 2.5, - "min": 1.0, - "max": 4.0, - "modified": { - "sum": 5.0, - "average": 2.5, - "min": 1.0, - "max": 4.0 - } - }"### + @r#" + { + "sum": 5.0, + "average": 5.0, + "min": 1.0, + "max": 4.0, + "modified": { + "sum": 5.0, + "average": 5.0, + "min": 1.0, + "max": 4.0 + } + } + "# ); }, ); @@ -2614,19 +2798,20 @@ mod tests { |metric| { insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 3.0, - "average": 1.5, - "min": 1.0, - "max": 2.0, - "modified": { - "sum": 3.0, - "average": 1.5, - "min": 1.0, - "max": 2.0 - } - }"### + @r#" + { + "sum": 3.0, + "average": 3.0, + "min": 1.0, + "max": 2.0, + "modified": { + "sum": 3.0, + "average": 3.0, + "min": 1.0, + "max": 2.0 + } + } + "# ); }, ); @@ -2647,19 +2832,20 @@ mod tests { // for_statement contributes. insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 3.0, - "average": 1.5, - "min": 1.0, - "max": 2.0, - "modified": { - "sum": 3.0, - "average": 1.5, - "min": 1.0, - "max": 2.0 - } - }"### + @r#" + { + "sum": 3.0, + "average": 3.0, + "min": 1.0, + "max": 2.0, + "modified": { + "sum": 3.0, + "average": 3.0, + "min": 1.0, + "max": 2.0 + } + } + "# ); }, ); @@ -2680,19 +2866,20 @@ mod tests { |metric| { insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 4.0, - "average": 2.0, - "min": 1.0, - "max": 3.0, - "modified": { - "sum": 3.0, - "average": 1.5, - "min": 1.0, - "max": 2.0 - } - }"### + @r#" + { + "sum": 4.0, + "average": 4.0, + "min": 1.0, + "max": 3.0, + "modified": { + "sum": 3.0, + "average": 3.0, + "min": 1.0, + "max": 2.0 + } + } + "# ); }, ); @@ -2719,19 +2906,20 @@ mod tests { // modified: unit(1) + fn(1) + switch(1) = 3 insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 5.0, - "average": 2.5, - "min": 1.0, - "max": 4.0, - "modified": { - "sum": 3.0, - "average": 1.5, - "min": 1.0, - "max": 2.0 - } - }"### + @r#" + { + "sum": 5.0, + "average": 5.0, + "min": 1.0, + "max": 4.0, + "modified": { + "sum": 3.0, + "average": 3.0, + "min": 1.0, + "max": 2.0 + } + } + "# ); }, ); @@ -2751,19 +2939,20 @@ mod tests { |metric| { insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 4.0, - "average": 2.0, - "min": 1.0, - "max": 3.0, - "modified": { - "sum": 3.0, - "average": 1.5, - "min": 1.0, - "max": 2.0 - } - }"### + @r#" + { + "sum": 4.0, + "average": 4.0, + "min": 1.0, + "max": 3.0, + "modified": { + "sum": 3.0, + "average": 3.0, + "min": 1.0, + "max": 2.0 + } + } + "# ); }, ); @@ -2784,19 +2973,20 @@ mod tests { |metric| { insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 4.0, - "average": 2.0, - "min": 1.0, - "max": 3.0, - "modified": { - "sum": 3.0, - "average": 1.5, - "min": 1.0, - "max": 2.0 - } - }"### + @r#" + { + "sum": 4.0, + "average": 4.0, + "min": 1.0, + "max": 3.0, + "modified": { + "sum": 3.0, + "average": 3.0, + "min": 1.0, + "max": 2.0 + } + } + "# ); }, ); @@ -2814,19 +3004,20 @@ mod tests { |metric| { insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 5.0, - "average": 2.5, - "min": 1.0, - "max": 4.0, - "modified": { - "sum": 5.0, - "average": 2.5, - "min": 1.0, - "max": 4.0 - } - }"### + @r#" + { + "sum": 5.0, + "average": 5.0, + "min": 1.0, + "max": 4.0, + "modified": { + "sum": 5.0, + "average": 5.0, + "min": 1.0, + "max": 4.0 + } + } + "# ); }, ); @@ -2845,19 +3036,20 @@ mod tests { // defer_statement and go_statement are not branches. insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 2.0, - "average": 1.0, - "min": 1.0, - "max": 1.0, - "modified": { - "sum": 2.0, - "average": 1.0, - "min": 1.0, - "max": 1.0 - } - }"### + @r#" + { + "sum": 2.0, + "average": 2.0, + "min": 1.0, + "max": 1.0, + "modified": { + "sum": 2.0, + "average": 2.0, + "min": 1.0, + "max": 1.0 + } + } + "# ); }, ); @@ -2905,19 +3097,20 @@ mod tests { // re-count of any method. insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 11.0, - "average": 1.2222222222222223, - "min": 1.0, - "max": 2.0, - "modified": { - "sum": 11.0, - "average": 1.2222222222222223, - "min": 1.0, - "max": 2.0 - } - }"### + @r#" + { + "sum": 11.0, + "average": 2.2, + "min": 1.0, + "max": 2.0, + "modified": { + "sum": 11.0, + "average": 2.2, + "min": 1.0, + "max": 2.0 + } + } + "# ); }, ); @@ -2949,19 +3142,20 @@ mod tests { assert_eq!(s.cyclomatic_modified_sum(), 4.0); insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 4.0, - "average": 1.3333333333333333, - "min": 1.0, - "max": 2.0, - "modified": { - "sum": 4.0, - "average": 1.3333333333333333, - "min": 1.0, - "max": 2.0 - } - }"### + @r#" + { + "sum": 4.0, + "average": 4.0, + "min": 1.0, + "max": 2.0, + "modified": { + "sum": 4.0, + "average": 4.0, + "min": 1.0, + "max": 2.0 + } + } + "# ); }, ); @@ -2992,19 +3186,20 @@ mod tests { assert_eq!(s.cyclomatic_modified_sum(), 4.0); insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 4.0, - "average": 1.3333333333333333, - "min": 1.0, - "max": 2.0, - "modified": { - "sum": 4.0, - "average": 1.3333333333333333, - "min": 1.0, - "max": 2.0 - } - }"### + @r#" + { + "sum": 4.0, + "average": 4.0, + "min": 1.0, + "max": 2.0, + "modified": { + "sum": 4.0, + "average": 4.0, + "min": 1.0, + "max": 2.0 + } + } + "# ); }, ); @@ -3233,12 +3428,12 @@ mod tests { @r#" { "sum": 4.0, - "average": 2.0, + "average": 4.0, "min": 1.0, "max": 3.0, "modified": { "sum": 4.0, - "average": 2.0, + "average": 4.0, "min": 1.0, "max": 3.0 } @@ -3263,12 +3458,12 @@ mod tests { @r#" { "sum": 4.0, - "average": 2.0, + "average": 4.0, "min": 1.0, "max": 3.0, "modified": { "sum": 4.0, - "average": 2.0, + "average": 4.0, "min": 1.0, "max": 3.0 } @@ -3297,12 +3492,12 @@ mod tests { @r#" { "sum": 4.0, - "average": 2.0, + "average": 4.0, "min": 1.0, "max": 3.0, "modified": { "sum": 4.0, - "average": 2.0, + "average": 4.0, "min": 1.0, "max": 3.0 } @@ -3329,12 +3524,12 @@ mod tests { @r#" { "sum": 6.0, - "average": 3.0, + "average": 6.0, "min": 1.0, "max": 5.0, "modified": { "sum": 6.0, - "average": 3.0, + "average": 6.0, "min": 1.0, "max": 5.0 } @@ -3359,12 +3554,12 @@ mod tests { @r#" { "sum": 4.0, - "average": 2.0, + "average": 4.0, "min": 1.0, "max": 3.0, "modified": { "sum": 4.0, - "average": 2.0, + "average": 4.0, "min": 1.0, "max": 3.0 } @@ -3397,19 +3592,20 @@ mod tests { assert_eq!(metric.cyclomatic.cyclomatic_max(), 4.0); insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 5.0, - "average": 2.5, - "min": 1.0, - "max": 4.0, - "modified": { - "sum": 5.0, - "average": 2.5, - "min": 1.0, - "max": 4.0 - } - }"### + @r#" + { + "sum": 5.0, + "average": 5.0, + "min": 1.0, + "max": 4.0, + "modified": { + "sum": 5.0, + "average": 5.0, + "min": 1.0, + "max": 4.0 + } + } + "# ); }, ); @@ -3428,12 +3624,12 @@ mod tests { insta::assert_json_snapshot!(metric.cyclomatic, @r#" { "sum": 3.0, - "average": 1.5, + "average": 3.0, "min": 1.0, "max": 2.0, "modified": { "sum": 3.0, - "average": 1.5, + "average": 3.0, "min": 1.0, "max": 2.0 } @@ -3462,17 +3658,17 @@ mod tests { @r#" { "sum": 4.0, - "average": 2.0, + "average": 4.0, "min": 1.0, "max": 3.0, "modified": { "sum": 4.0, - "average": 2.0, + "average": 4.0, "min": 1.0, "max": 3.0 } } - "# + "# ); }, ); @@ -3493,19 +3689,20 @@ mod tests { |metric| { insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 4.0, - "average": 2.0, - "min": 1.0, - "max": 3.0, - "modified": { - "sum": 4.0, - "average": 2.0, - "min": 1.0, - "max": 3.0 - } - }"### + @r#" + { + "sum": 4.0, + "average": 4.0, + "min": 1.0, + "max": 3.0, + "modified": { + "sum": 4.0, + "average": 4.0, + "min": 1.0, + "max": 3.0 + } + } + "# ); }, ); @@ -3533,19 +3730,20 @@ mod tests { |metric| { insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 6.0, - "average": 3.0, - "min": 1.0, - "max": 5.0, - "modified": { - "sum": 5.0, - "average": 2.5, - "min": 1.0, - "max": 4.0 - } - }"### + @r#" + { + "sum": 6.0, + "average": 6.0, + "min": 1.0, + "max": 5.0, + "modified": { + "sum": 5.0, + "average": 5.0, + "min": 1.0, + "max": 4.0 + } + } + "# ); }, ); @@ -3569,19 +3767,20 @@ mod tests { // modified: unit(1) + fn(1) + switch(1) = 3 insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 5.0, - "average": 2.5, - "min": 1.0, - "max": 4.0, - "modified": { - "sum": 3.0, - "average": 1.5, - "min": 1.0, - "max": 2.0 - } - }"### + @r#" + { + "sum": 5.0, + "average": 5.0, + "min": 1.0, + "max": 4.0, + "modified": { + "sum": 3.0, + "average": 3.0, + "min": 1.0, + "max": 2.0 + } + } + "# ); }, ); @@ -3609,19 +3808,20 @@ mod tests { |metric| { insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 6.0, - "average": 3.0, - "min": 1.0, - "max": 5.0, - "modified": { - "sum": 5.0, - "average": 2.5, - "min": 1.0, - "max": 4.0 - } - }"### + @r#" + { + "sum": 6.0, + "average": 6.0, + "min": 1.0, + "max": 5.0, + "modified": { + "sum": 5.0, + "average": 5.0, + "min": 1.0, + "max": 4.0 + } + } + "# ); }, ); @@ -3643,19 +3843,20 @@ mod tests { // modified: unit(1) + fn(1) + switch(1) = 3 insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 4.0, - "average": 2.0, - "min": 1.0, - "max": 3.0, - "modified": { - "sum": 3.0, - "average": 1.5, - "min": 1.0, - "max": 2.0 - } - }"### + @r#" + { + "sum": 4.0, + "average": 4.0, + "min": 1.0, + "max": 3.0, + "modified": { + "sum": 3.0, + "average": 3.0, + "min": 1.0, + "max": 2.0 + } + } + "# ); }, ); @@ -3694,20 +3895,20 @@ mod tests { assert_eq!(metric.cyclomatic.cyclomatic_max(), 7.0); insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 9.0, - "average": 3.0, - "min": 1.0, - "max": 7.0, - "modified": { - "sum": 8.0, - "average": 2.6666666666666665, - "min": 1.0, - "max": 6.0 - } - } - "### + @r#" + { + "sum": 9.0, + "average": 9.0, + "min": 1.0, + "max": 7.0, + "modified": { + "sum": 8.0, + "average": 8.0, + "min": 1.0, + "max": 6.0 + } + } + "# ); }, ); @@ -3734,19 +3935,20 @@ mod tests { assert_eq!(metric.cyclomatic.cyclomatic_max(), 4.0); insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 5.0, - "average": 2.5, - "min": 1.0, - "max": 4.0, - "modified": { - "sum": 3.0, - "average": 1.5, - "min": 1.0, - "max": 2.0 - } - }"### + @r#" + { + "sum": 5.0, + "average": 5.0, + "min": 1.0, + "max": 4.0, + "modified": { + "sum": 3.0, + "average": 3.0, + "min": 1.0, + "max": 2.0 + } + } + "# ); }, ); @@ -3813,20 +4015,20 @@ mod tests { end", "foo.lua", |metric| { - insta::assert_json_snapshot!(metric.cyclomatic, @r###" + insta::assert_json_snapshot!(metric.cyclomatic, @r#" { "sum": 4.0, - "average": 2.0, + "average": 4.0, "min": 1.0, "max": 3.0, "modified": { "sum": 4.0, - "average": 2.0, + "average": 4.0, "min": 1.0, "max": 3.0 } } - "###); + "#); }, ); } @@ -3849,20 +4051,20 @@ end", end", "foo.lua", |metric| { - insta::assert_json_snapshot!(metric.cyclomatic, @r###" + insta::assert_json_snapshot!(metric.cyclomatic, @r#" { "sum": 5.0, - "average": 2.5, + "average": 5.0, "min": 1.0, "max": 4.0, "modified": { "sum": 5.0, - "average": 2.5, + "average": 5.0, "min": 1.0, "max": 4.0 } } - "###); + "#); }, ); } @@ -3879,20 +4081,20 @@ end", end", "foo.lua", |metric| { - insta::assert_json_snapshot!(metric.cyclomatic, @r###" + insta::assert_json_snapshot!(metric.cyclomatic, @r#" { "sum": 5.0, - "average": 2.5, + "average": 5.0, "min": 1.0, "max": 4.0, "modified": { "sum": 5.0, - "average": 2.5, + "average": 5.0, "min": 1.0, "max": 4.0 } } - "###); + "#); }, ); } @@ -3940,19 +4142,20 @@ f() { // modified: unit(1) + fn(1) + case_stmt(1) = 3 insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 5.0, - "average": 2.5, - "min": 1.0, - "max": 4.0, - "modified": { - "sum": 3.0, - "average": 1.5, - "min": 1.0, - "max": 2.0 - } - }"### + @r#" + { + "sum": 5.0, + "average": 5.0, + "min": 1.0, + "max": 4.0, + "modified": { + "sum": 3.0, + "average": 3.0, + "min": 1.0, + "max": 2.0 + } + } + "# ); }, ); @@ -4058,19 +4261,19 @@ f() { insta::assert_json_snapshot!( metric.cyclomatic, @r#" - { - "sum": 2.0, - "average": 1.0, - "min": 1.0, - "max": 1.0, - "modified": { - "sum": 2.0, - "average": 1.0, - "min": 1.0, - "max": 1.0 - } - } - "# + { + "sum": 2.0, + "average": 2.0, + "min": 1.0, + "max": 1.0, + "modified": { + "sum": 2.0, + "average": 2.0, + "min": 1.0, + "max": 1.0 + } + } + "# ); }, ); @@ -4181,19 +4384,20 @@ f() { assert_eq!(metric.cyclomatic.cyclomatic_max(), 3.0); insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 4.0, - "average": 2.0, - "min": 1.0, - "max": 3.0, - "modified": { - "sum": 4.0, - "average": 2.0, - "min": 1.0, - "max": 3.0 - } - }"### + @r#" + { + "sum": 4.0, + "average": 4.0, + "min": 1.0, + "max": 3.0, + "modified": { + "sum": 4.0, + "average": 4.0, + "min": 1.0, + "max": 3.0 + } + } + "# ); }, ); @@ -4215,19 +4419,20 @@ f() { assert_eq!(metric.cyclomatic.cyclomatic_max(), 4.0); insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 5.0, - "average": 2.5, - "min": 1.0, - "max": 4.0, - "modified": { - "sum": 5.0, - "average": 2.5, - "min": 1.0, - "max": 4.0 - } - }"### + @r#" + { + "sum": 5.0, + "average": 5.0, + "min": 1.0, + "max": 4.0, + "modified": { + "sum": 5.0, + "average": 5.0, + "min": 1.0, + "max": 4.0 + } + } + "# ); }, ); @@ -4247,19 +4452,20 @@ f() { assert_eq!(metric.cyclomatic.cyclomatic_max(), 3.0); insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 4.0, - "average": 2.0, - "min": 1.0, - "max": 3.0, - "modified": { - "sum": 4.0, - "average": 2.0, - "min": 1.0, - "max": 3.0 - } - }"### + @r#" + { + "sum": 4.0, + "average": 4.0, + "min": 1.0, + "max": 3.0, + "modified": { + "sum": 4.0, + "average": 4.0, + "min": 1.0, + "max": 3.0 + } + } + "# ); }, ); @@ -4279,19 +4485,20 @@ f() { assert_eq!(metric.cyclomatic.cyclomatic_max(), 3.0); insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 4.0, - "average": 2.0, - "min": 1.0, - "max": 3.0, - "modified": { - "sum": 4.0, - "average": 2.0, - "min": 1.0, - "max": 3.0 - } - }"### + @r#" + { + "sum": 4.0, + "average": 4.0, + "min": 1.0, + "max": 3.0, + "modified": { + "sum": 4.0, + "average": 4.0, + "min": 1.0, + "max": 3.0 + } + } + "# ); }, ); @@ -4314,19 +4521,20 @@ f() { assert_eq!(metric.cyclomatic.cyclomatic_max(), 3.0); insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 4.0, - "average": 2.0, - "min": 1.0, - "max": 3.0, - "modified": { - "sum": 4.0, - "average": 2.0, - "min": 1.0, - "max": 3.0 - } - }"### + @r#" + { + "sum": 4.0, + "average": 4.0, + "min": 1.0, + "max": 3.0, + "modified": { + "sum": 4.0, + "average": 4.0, + "min": 1.0, + "max": 3.0 + } + } + "# ); }, ); @@ -4348,19 +4556,20 @@ f() { assert_eq!(metric.cyclomatic.cyclomatic_max(), 3.0); insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 4.0, - "average": 2.0, - "min": 1.0, - "max": 3.0, - "modified": { - "sum": 4.0, - "average": 2.0, - "min": 1.0, - "max": 3.0 - } - }"### + @r#" + { + "sum": 4.0, + "average": 4.0, + "min": 1.0, + "max": 3.0, + "modified": { + "sum": 4.0, + "average": 4.0, + "min": 1.0, + "max": 3.0 + } + } + "# ); }, ); @@ -4382,19 +4591,20 @@ f() { assert_eq!(metric.cyclomatic.cyclomatic_max(), 3.0); insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 4.0, - "average": 2.0, - "min": 1.0, - "max": 3.0, - "modified": { - "sum": 4.0, - "average": 2.0, - "min": 1.0, - "max": 3.0 - } - }"### + @r#" + { + "sum": 4.0, + "average": 4.0, + "min": 1.0, + "max": 3.0, + "modified": { + "sum": 4.0, + "average": 4.0, + "min": 1.0, + "max": 3.0 + } + } + "# ); }, ); @@ -4416,19 +4626,20 @@ f() { assert_eq!(metric.cyclomatic.cyclomatic_max(), 3.0); insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 4.0, - "average": 2.0, - "min": 1.0, - "max": 3.0, - "modified": { - "sum": 4.0, - "average": 2.0, - "min": 1.0, - "max": 3.0 - } - }"### + @r#" + { + "sum": 4.0, + "average": 4.0, + "min": 1.0, + "max": 3.0, + "modified": { + "sum": 4.0, + "average": 4.0, + "min": 1.0, + "max": 3.0 + } + } + "# ); }, ); @@ -4453,19 +4664,20 @@ f() { assert_eq!(metric.cyclomatic.cyclomatic_max(), 4.0); insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 5.0, - "average": 2.5, - "min": 1.0, - "max": 4.0, - "modified": { - "sum": 5.0, - "average": 2.5, - "min": 1.0, - "max": 4.0 - } - }"### + @r#" + { + "sum": 5.0, + "average": 5.0, + "min": 1.0, + "max": 4.0, + "modified": { + "sum": 5.0, + "average": 5.0, + "min": 1.0, + "max": 4.0 + } + } + "# ); }, ); @@ -4488,19 +4700,20 @@ f() { assert_eq!(metric.cyclomatic.cyclomatic_max(), 5.0); insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 6.0, - "average": 3.0, - "min": 1.0, - "max": 5.0, - "modified": { - "sum": 6.0, - "average": 3.0, - "min": 1.0, - "max": 5.0 - } - }"### + @r#" + { + "sum": 6.0, + "average": 6.0, + "min": 1.0, + "max": 5.0, + "modified": { + "sum": 6.0, + "average": 6.0, + "min": 1.0, + "max": 5.0 + } + } + "# ); }, ); @@ -4523,19 +4736,20 @@ f() { assert_eq!(metric.cyclomatic.cyclomatic_max(), 5.0); insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 6.0, - "average": 3.0, - "min": 1.0, - "max": 5.0, - "modified": { - "sum": 6.0, - "average": 3.0, - "min": 1.0, - "max": 5.0 - } - }"### + @r#" + { + "sum": 6.0, + "average": 6.0, + "min": 1.0, + "max": 5.0, + "modified": { + "sum": 6.0, + "average": 6.0, + "min": 1.0, + "max": 5.0 + } + } + "# ); }, ); @@ -4558,19 +4772,20 @@ f() { assert_eq!(metric.cyclomatic.cyclomatic_max(), 4.0); insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 5.0, - "average": 2.5, - "min": 1.0, - "max": 4.0, - "modified": { - "sum": 5.0, - "average": 2.5, - "min": 1.0, - "max": 4.0 - } - }"### + @r#" + { + "sum": 5.0, + "average": 5.0, + "min": 1.0, + "max": 4.0, + "modified": { + "sum": 5.0, + "average": 5.0, + "min": 1.0, + "max": 4.0 + } + } + "# ); }, ); @@ -4696,19 +4911,20 @@ f() { assert_eq!(metric.cyclomatic.cyclomatic_max(), 3.0); insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 5.0, - "average": 1.6666666666666667, - "min": 1.0, - "max": 3.0, - "modified": { - "sum": 5.0, - "average": 1.6666666666666667, - "min": 1.0, - "max": 3.0 - } - }"### + @r#" + { + "sum": 5.0, + "average": 5.0, + "min": 1.0, + "max": 3.0, + "modified": { + "sum": 5.0, + "average": 5.0, + "min": 1.0, + "max": 3.0 + } + } + "# ); }, ); @@ -4920,19 +5136,20 @@ f() { assert_eq!(metric.cyclomatic.cyclomatic_max(), 3.0); insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 4.0, - "average": 2.0, - "min": 1.0, - "max": 3.0, - "modified": { - "sum": 4.0, - "average": 2.0, - "min": 1.0, - "max": 3.0 - } - }"### + @r#" + { + "sum": 4.0, + "average": 4.0, + "min": 1.0, + "max": 3.0, + "modified": { + "sum": 4.0, + "average": 4.0, + "min": 1.0, + "max": 3.0 + } + } + "# ); }, ); @@ -5174,19 +5391,20 @@ f() { |metric| { insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 4.0, - "average": 2.0, - "min": 1.0, - "max": 3.0, - "modified": { - "sum": 4.0, - "average": 2.0, - "min": 1.0, - "max": 3.0 - } - }"### + @r#" + { + "sum": 4.0, + "average": 4.0, + "min": 1.0, + "max": 3.0, + "modified": { + "sum": 4.0, + "average": 4.0, + "min": 1.0, + "max": 3.0 + } + } + "# ); }, ); @@ -5386,19 +5604,20 @@ f() { // Default arm contributes 0. insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 5.0, - "average": 2.5, - "min": 1.0, - "max": 4.0, - "modified": { - "sum": 3.0, - "average": 1.5, - "min": 1.0, - "max": 2.0 - } - }"### + @r#" + { + "sum": 5.0, + "average": 5.0, + "min": 1.0, + "max": 4.0, + "modified": { + "sum": 3.0, + "average": 3.0, + "min": 1.0, + "max": 2.0 + } + } + "# ); }, ); @@ -5452,19 +5671,20 @@ f() { assert_eq!(metric.cyclomatic.cyclomatic_max(), 3.0); insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 4.0, - "average": 2.0, - "min": 1.0, - "max": 3.0, - "modified": { - "sum": 4.0, - "average": 2.0, - "min": 1.0, - "max": 3.0 - } - }"### + @r#" + { + "sum": 4.0, + "average": 4.0, + "min": 1.0, + "max": 3.0, + "modified": { + "sum": 4.0, + "average": 4.0, + "min": 1.0, + "max": 3.0 + } + } + "# ); }, ); @@ -5517,19 +5737,20 @@ f() { // modified: unit(1) + fn(1) + 2 switches = 4 insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 6.0, - "average": 3.0, - "min": 1.0, - "max": 5.0, - "modified": { - "sum": 4.0, - "average": 2.0, - "min": 1.0, - "max": 3.0 - } - }"### + @r#" + { + "sum": 6.0, + "average": 6.0, + "min": 1.0, + "max": 5.0, + "modified": { + "sum": 4.0, + "average": 4.0, + "min": 1.0, + "max": 3.0 + } + } + "# ); }, ); @@ -5556,19 +5777,20 @@ f() { // modified: unit(1) + fn(1) + 2 matches = 4 insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 5.0, - "average": 2.5, - "min": 1.0, - "max": 4.0, - "modified": { - "sum": 4.0, - "average": 2.0, - "min": 1.0, - "max": 3.0 - } - }"### + @r#" + { + "sum": 5.0, + "average": 5.0, + "min": 1.0, + "max": 4.0, + "modified": { + "sum": 4.0, + "average": 4.0, + "min": 1.0, + "max": 3.0 + } + } + "# ); }, ); @@ -5583,19 +5805,20 @@ f() { // modified: unit(1) + fn(1) + 1 switch = 3 insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 2.0, - "average": 1.0, - "min": 1.0, - "max": 1.0, - "modified": { - "sum": 3.0, - "average": 1.5, - "min": 1.0, - "max": 2.0 - } - }"### + @r#" + { + "sum": 2.0, + "average": 2.0, + "min": 1.0, + "max": 1.0, + "modified": { + "sum": 3.0, + "average": 3.0, + "min": 1.0, + "max": 2.0 + } + } + "# ); }); } @@ -5622,19 +5845,20 @@ f() { assert_eq!(s.cyclomatic_modified_sum(), 4.0); insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 4.0, - "average": 2.0, - "min": 1.0, - "max": 3.0, - "modified": { - "sum": 4.0, - "average": 2.0, - "min": 1.0, - "max": 3.0 - } - }"### + @r#" + { + "sum": 4.0, + "average": 4.0, + "min": 1.0, + "max": 3.0, + "modified": { + "sum": 4.0, + "average": 4.0, + "min": 1.0, + "max": 3.0 + } + } + "# ); }, ); @@ -5666,19 +5890,20 @@ f() { assert_eq!(s.cyclomatic_modified_sum(), 3.0); insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 3.0, - "average": 1.5, - "min": 1.0, - "max": 2.0, - "modified": { - "sum": 3.0, - "average": 1.5, - "min": 1.0, - "max": 2.0 - } - }"### + @r#" + { + "sum": 3.0, + "average": 3.0, + "min": 1.0, + "max": 2.0, + "modified": { + "sum": 3.0, + "average": 3.0, + "min": 1.0, + "max": 2.0 + } + } + "# ); }, ); @@ -5707,19 +5932,20 @@ f() { assert_eq!(s.cyclomatic_modified_sum(), 3.0); insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 3.0, - "average": 1.5, - "min": 1.0, - "max": 2.0, - "modified": { - "sum": 3.0, - "average": 1.5, - "min": 1.0, - "max": 2.0 - } - }"### + @r#" + { + "sum": 3.0, + "average": 3.0, + "min": 1.0, + "max": 2.0, + "modified": { + "sum": 3.0, + "average": 3.0, + "min": 1.0, + "max": 2.0 + } + } + "# ); }, ); @@ -5743,19 +5969,20 @@ f() { assert_eq!(s.cyclomatic_modified_sum(), 4.0); insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 4.0, - "average": 2.0, - "min": 1.0, - "max": 3.0, - "modified": { - "sum": 4.0, - "average": 2.0, - "min": 1.0, - "max": 3.0 - } - }"### + @r#" + { + "sum": 4.0, + "average": 4.0, + "min": 1.0, + "max": 3.0, + "modified": { + "sum": 4.0, + "average": 4.0, + "min": 1.0, + "max": 3.0 + } + } + "# ); }, ); @@ -5781,19 +6008,20 @@ f() { assert_eq!(s.cyclomatic_modified_sum(), 6.0); insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 6.0, - "average": 3.0, - "min": 1.0, - "max": 5.0, - "modified": { - "sum": 6.0, - "average": 3.0, - "min": 1.0, - "max": 5.0 - } - }"### + @r#" + { + "sum": 6.0, + "average": 6.0, + "min": 1.0, + "max": 5.0, + "modified": { + "sum": 6.0, + "average": 6.0, + "min": 1.0, + "max": 5.0 + } + } + "# ); }, ); @@ -5828,19 +6056,20 @@ f() { assert!(s.cyclomatic_modified_sum() < s.cyclomatic_sum()); insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 5.0, - "average": 2.5, - "min": 1.0, - "max": 4.0, - "modified": { - "sum": 3.0, - "average": 1.5, - "min": 1.0, - "max": 2.0 - } - }"### + @r#" + { + "sum": 5.0, + "average": 5.0, + "min": 1.0, + "max": 4.0, + "modified": { + "sum": 3.0, + "average": 3.0, + "min": 1.0, + "max": 2.0 + } + } + "# ); }, ); @@ -5874,19 +6103,20 @@ f() { assert_eq!(s.cyclomatic_modified_sum(), 3.0); insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 3.0, - "average": 1.5, - "min": 1.0, - "max": 2.0, - "modified": { - "sum": 3.0, - "average": 1.5, - "min": 1.0, - "max": 2.0 - } - }"### + @r#" + { + "sum": 3.0, + "average": 3.0, + "min": 1.0, + "max": 2.0, + "modified": { + "sum": 3.0, + "average": 3.0, + "min": 1.0, + "max": 2.0 + } + } + "# ); }, ); @@ -5914,7 +6144,9 @@ f() { assert_eq!(s.cyclomatic_modified_sum(), 3.0); assert_eq!(s.cyclomatic_modified_min(), 1.0); assert_eq!(s.cyclomatic_modified_max(), 2.0); - assert_eq!(s.cyclomatic_modified_average(), 1.5); + // #512: divisor is the single function space, not the two + // total spaces (unit + fn), so 3 / 1 = 3.0 (was 3 / 2 = 1.5). + assert_eq!(s.cyclomatic_modified_average(), 3.0); assert!(s.cyclomatic_modified_sum() <= s.cyclomatic_sum()); }, ); @@ -5935,19 +6167,20 @@ f() { // modified: unit(1) + fn(1) + MatchExpr(1) = 3 insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 2.0, - "average": 1.0, - "min": 1.0, - "max": 1.0, - "modified": { - "sum": 3.0, - "average": 1.5, - "min": 1.0, - "max": 2.0 - } - }"### + @r#" + { + "sum": 2.0, + "average": 2.0, + "min": 1.0, + "max": 1.0, + "modified": { + "sum": 3.0, + "average": 3.0, + "min": 1.0, + "max": 2.0 + } + } + "# ); }, ); @@ -5971,19 +6204,20 @@ f() { // modified: unit(1) + fn(1) + MatchExpr(1) = 3 insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 5.0, - "average": 2.5, - "min": 1.0, - "max": 4.0, - "modified": { - "sum": 3.0, - "average": 1.5, - "min": 1.0, - "max": 2.0 - } - }"### + @r#" + { + "sum": 5.0, + "average": 5.0, + "min": 1.0, + "max": 4.0, + "modified": { + "sum": 3.0, + "average": 3.0, + "min": 1.0, + "max": 2.0 + } + } + "# ); }, ); @@ -6005,19 +6239,20 @@ f() { // modified: unit(1) + fn(1) + MatchExpr(1) = 3 insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 4.0, - "average": 2.0, - "min": 1.0, - "max": 3.0, - "modified": { - "sum": 3.0, - "average": 1.5, - "min": 1.0, - "max": 2.0 - } - }"### + @r#" + { + "sum": 4.0, + "average": 4.0, + "min": 1.0, + "max": 3.0, + "modified": { + "sum": 3.0, + "average": 3.0, + "min": 1.0, + "max": 2.0 + } + } + "# ); }, ); @@ -6039,19 +6274,20 @@ f() { // modified: unit(1) + fn(1) + MatchExpr(1) = 3 insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 4.0, - "average": 2.0, - "min": 1.0, - "max": 3.0, - "modified": { - "sum": 3.0, - "average": 1.5, - "min": 1.0, - "max": 2.0 - } - }"### + @r#" + { + "sum": 4.0, + "average": 4.0, + "min": 1.0, + "max": 3.0, + "modified": { + "sum": 3.0, + "average": 3.0, + "min": 1.0, + "max": 2.0 + } + } + "# ); }, ); @@ -6075,19 +6311,20 @@ f() { // modified: unit(1) + fn(1 + MatchExpr(1) + if_kw(1)) = 4 insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 5.0, - "average": 2.5, - "min": 1.0, - "max": 4.0, - "modified": { - "sum": 4.0, - "average": 2.0, - "min": 1.0, - "max": 3.0 - } - }"### + @r#" + { + "sum": 5.0, + "average": 5.0, + "min": 1.0, + "max": 4.0, + "modified": { + "sum": 4.0, + "average": 4.0, + "min": 1.0, + "max": 3.0 + } + } + "# ); }, ); @@ -6109,19 +6346,20 @@ f() { // modified: unit(1) + fn(1) + case_stmt(1) = 3 insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 2.0, - "average": 1.0, - "min": 1.0, - "max": 1.0, - "modified": { - "sum": 3.0, - "average": 1.5, - "min": 1.0, - "max": 2.0 - } - }"### + @r#" + { + "sum": 2.0, + "average": 2.0, + "min": 1.0, + "max": 1.0, + "modified": { + "sum": 3.0, + "average": 3.0, + "min": 1.0, + "max": 2.0 + } + } + "# ); }, ); @@ -6150,19 +6388,20 @@ f() { // modified: unit(1) + fn(1) + 2 case_stmts = 4 insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 6.0, - "average": 3.0, - "min": 1.0, - "max": 5.0, - "modified": { - "sum": 4.0, - "average": 2.0, - "min": 1.0, - "max": 3.0 - } - }"### + @r#" + { + "sum": 6.0, + "average": 6.0, + "min": 1.0, + "max": 5.0, + "modified": { + "sum": 4.0, + "average": 4.0, + "min": 1.0, + "max": 3.0 + } + } + "# ); }, ); @@ -6188,19 +6427,20 @@ f() { // modified: unit(1) + fn(1) + 2 MatchExpr(+2) = 4 insta::assert_json_snapshot!( metric.cyclomatic, - @r###" - { - "sum": 4.0, - "average": 2.0, - "min": 1.0, - "max": 3.0, - "modified": { - "sum": 4.0, - "average": 2.0, - "min": 1.0, - "max": 3.0 - } - }"### + @r#" + { + "sum": 4.0, + "average": 4.0, + "min": 1.0, + "max": 3.0, + "modified": { + "sum": 4.0, + "average": 4.0, + "min": 1.0, + "max": 3.0 + } + } + "# ); }, ); diff --git a/src/metrics/exit.rs b/src/metrics/exit.rs index b3ceb2d1..530b9f6f 100644 --- a/src/metrics/exit.rs +++ b/src/metrics/exit.rs @@ -125,12 +125,14 @@ impl Stats { /// This value is computed dividing the `NExit` value /// for the total number of functions/closures in a space. /// - /// The divisor is guarded with `.max(1)` so a space with no - /// counted functions (or one where `Nom` was not selected) - /// degrades to `sum / 1` instead of producing `inf`/`NaN` (#428). + /// The per-function divisor (shared with `cyclomatic`/`cognitive`/ + /// `nargs`, #512) is guarded with `.max(1)` via the shared `average` + /// helper, so a space with no counted functions (or one where `Nom` + /// was not selected) degrades to `sum / 1` instead of producing + /// `inf`/`NaN` (#428). #[must_use] pub fn exit_average(&self) -> f64 { - self.exit_sum() / self.total_space_functions.max(1) as f64 + crate::metrics::average(self.exit_sum(), self.total_space_functions) } #[inline] pub(crate) fn compute_sum(&mut self) { diff --git a/src/metrics/loc.rs b/src/metrics/loc.rs index 44b989a9..6e62b984 100644 --- a/src/metrics/loc.rs +++ b/src/metrics/loc.rs @@ -524,7 +524,7 @@ impl Stats { #[inline] #[must_use] pub fn sloc_average(&self) -> f64 { - self.sloc() / self.space_count as f64 + crate::metrics::average(self.sloc(), self.space_count) } /// The `Ploc` metric average value. @@ -533,7 +533,7 @@ impl Stats { #[inline] #[must_use] pub fn ploc_average(&self) -> f64 { - self.ploc() / self.space_count as f64 + crate::metrics::average(self.ploc(), self.space_count) } /// The `Lloc` metric average value. @@ -542,7 +542,7 @@ impl Stats { #[inline] #[must_use] pub fn lloc_average(&self) -> f64 { - self.lloc() / self.space_count as f64 + crate::metrics::average(self.lloc(), self.space_count) } /// The `Cloc` metric average value. @@ -551,7 +551,7 @@ impl Stats { #[inline] #[must_use] pub fn cloc_average(&self) -> f64 { - self.cloc() / self.space_count as f64 + crate::metrics::average(self.cloc(), self.space_count) } /// The `Blank` metric average value. @@ -560,7 +560,7 @@ impl Stats { #[inline] #[must_use] pub fn blank_average(&self) -> f64 { - self.blank() / self.space_count as f64 + crate::metrics::average(self.blank(), self.space_count) } /// The `Sloc` metric minimum value. diff --git a/src/metrics/mod.rs b/src/metrics/mod.rs index 8d251027..d2538b5a 100644 --- a/src/metrics/mod.rs +++ b/src/metrics/mod.rs @@ -30,3 +30,38 @@ pub mod npm; pub mod tokens; /// Weighted Methods per Class. pub mod wmc; + +/// Divides a metric sum by a count, guarding the divisor with `.max(1)`. +/// +/// Every "average over a count" metric routes through this helper so the +/// divide-by-zero guard added for [#428] is applied uniformly rather than +/// per call site. A `count` of `0` degrades to `sum / 1` (the sum itself) +/// instead of producing `inf`/`NaN`, so a never-observed or count-less +/// space still serializes a finite number. +/// +/// The *meaning* of `count` is the caller's choice of denominator +/// convention; the project uses two: +/// +/// - **Per-function** averages (`cognitive`, `cyclomatic`, `exit`, +/// `nargs`) divide by the function/closure count of the subtree, so the +/// value reads as "average complexity per function". `cognitive`/ +/// `exit`/`nargs` source this count from `Nom`; `cyclomatic` counts its +/// own function/closure *spaces* (equal in the common case, but +/// independent of whether `Nom` is selected — see +/// `cyclomatic::Stats::function_spaces`). +/// - **Per-space** averages (`nom`, `loc`, `abc`, `tokens`) divide by the +/// total number of spaces (functions, closures, classes, the file unit, +/// …). These measure a property of each space rather than of each +/// function, so a per-function denominator would not match their +/// meaning (and for `nom` it would be circular — it *is* the function +/// count). +/// +/// [#428]: https://github.com/dekobon/big-code-analysis/issues/428 +#[inline] +#[must_use] +// `count as f64` is exact for any realistic space count; the cast mirrors +// the per-metric modules' module-level allowance for count-to-float casts. +#[allow(clippy::cast_precision_loss)] +pub(crate) fn average(sum: f64, count: usize) -> f64 { + sum / count.max(1) as f64 +} diff --git a/src/metrics/nargs.rs b/src/metrics/nargs.rs index a9cf73bd..5639281e 100644 --- a/src/metrics/nargs.rs +++ b/src/metrics/nargs.rs @@ -148,14 +148,14 @@ impl Stats { #[inline] #[must_use] pub fn fn_args_average(&self) -> f64 { - self.fn_nargs_sum as f64 / self.total_functions.max(1) as f64 + crate::metrics::average(self.fn_nargs_sum as f64, self.total_functions) } /// Returns the average number of closures arguments in a space. #[inline] #[must_use] pub fn closure_args_average(&self) -> f64 { - self.closure_nargs_sum as f64 / self.total_closures.max(1) as f64 + crate::metrics::average(self.closure_nargs_sum as f64, self.total_closures) } /// Returns the total number of arguments of each function and @@ -173,7 +173,10 @@ impl Stats { #[inline] #[must_use] pub fn nargs_average(&self) -> f64 { - self.nargs_total() / (self.total_functions + self.total_closures).max(1) as f64 + crate::metrics::average( + self.nargs_total(), + self.total_functions + self.total_closures, + ) } /// Returns the minimum number of function arguments in a space. /// diff --git a/src/metrics/nom.rs b/src/metrics/nom.rs index 4bdc32c5..eb5c393b 100644 --- a/src/metrics/nom.rs +++ b/src/metrics/nom.rs @@ -162,21 +162,21 @@ impl Stats { #[inline] #[must_use] pub fn functions_average(&self) -> f64 { - self.functions_sum() / self.space_count.max(1) as f64 + crate::metrics::average(self.functions_sum(), self.space_count) } /// Returns the average number of closures over all spaces. #[inline] #[must_use] pub fn closures_average(&self) -> f64 { - self.closures_sum() / self.space_count.max(1) as f64 + crate::metrics::average(self.closures_sum(), self.space_count) } /// Returns the average number of function definitions and closures over all spaces. #[inline] #[must_use] pub fn average(&self) -> f64 { - self.total() / self.space_count.max(1) as f64 + crate::metrics::average(self.total(), self.space_count) } /// Counts the number of function definitions in a scope. diff --git a/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__bash_case_bare_wildcard_excluded.snap b/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__bash_case_bare_wildcard_excluded.snap index ec46c562..3bb81c84 100644 --- a/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__bash_case_bare_wildcard_excluded.snap +++ b/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__bash_case_bare_wildcard_excluded.snap @@ -4,12 +4,12 @@ expression: metric.cyclomatic --- { "sum": 3.0, - "average": 1.5, + "average": 3.0, "min": 1.0, "max": 2.0, "modified": { "sum": 3.0, - "average": 1.5, + "average": 3.0, "min": 1.0, "max": 2.0 } diff --git a/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__bash_case_statement.snap b/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__bash_case_statement.snap index 2ee55f62..6d2debb9 100644 --- a/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__bash_case_statement.snap +++ b/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__bash_case_statement.snap @@ -4,12 +4,12 @@ expression: metric.cyclomatic --- { "sum": 4.0, - "average": 2.0, + "average": 4.0, "min": 1.0, "max": 3.0, "modified": { "sum": 3.0, - "average": 1.5, + "average": 3.0, "min": 1.0, "max": 2.0 } diff --git a/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__bash_nested_control_flow.snap b/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__bash_nested_control_flow.snap index ace56820..08dec2ba 100644 --- a/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__bash_nested_control_flow.snap +++ b/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__bash_nested_control_flow.snap @@ -4,12 +4,12 @@ expression: metric.cyclomatic --- { "sum": 5.0, - "average": 2.5, + "average": 5.0, "min": 1.0, "max": 4.0, "modified": { "sum": 5.0, - "average": 2.5, + "average": 5.0, "min": 1.0, "max": 4.0 } diff --git a/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__bash_simple_function.snap b/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__bash_simple_function.snap index 93e0fed1..f6782a4a 100644 --- a/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__bash_simple_function.snap +++ b/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__bash_simple_function.snap @@ -4,12 +4,12 @@ expression: metric.cyclomatic --- { "sum": 2.0, - "average": 1.0, + "average": 2.0, "min": 1.0, "max": 1.0, "modified": { "sum": 2.0, - "average": 1.0, + "average": 2.0, "min": 1.0, "max": 1.0 } diff --git a/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__bash_while_loop.snap b/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__bash_while_loop.snap index ec46c562..3bb81c84 100644 --- a/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__bash_while_loop.snap +++ b/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__bash_while_loop.snap @@ -4,12 +4,12 @@ expression: metric.cyclomatic --- { "sum": 3.0, - "average": 1.5, + "average": 3.0, "min": 1.0, "max": 2.0, "modified": { "sum": 3.0, - "average": 1.5, + "average": 3.0, "min": 1.0, "max": 2.0 } diff --git a/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__kotlin_for_loop.snap b/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__kotlin_for_loop.snap index ec46c562..3bb81c84 100644 --- a/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__kotlin_for_loop.snap +++ b/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__kotlin_for_loop.snap @@ -4,12 +4,12 @@ expression: metric.cyclomatic --- { "sum": 3.0, - "average": 1.5, + "average": 3.0, "min": 1.0, "max": 2.0, "modified": { "sum": 3.0, - "average": 1.5, + "average": 3.0, "min": 1.0, "max": 2.0 } diff --git a/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__kotlin_logical_operators.snap b/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__kotlin_logical_operators.snap index 66b66a5c..8607e531 100644 --- a/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__kotlin_logical_operators.snap +++ b/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__kotlin_logical_operators.snap @@ -4,12 +4,12 @@ expression: metric.cyclomatic --- { "sum": 4.0, - "average": 2.0, + "average": 4.0, "min": 1.0, "max": 3.0, "modified": { "sum": 4.0, - "average": 2.0, + "average": 4.0, "min": 1.0, "max": 3.0 } diff --git a/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__kotlin_while_loop.snap b/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__kotlin_while_loop.snap index ec46c562..3bb81c84 100644 --- a/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__kotlin_while_loop.snap +++ b/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__kotlin_while_loop.snap @@ -4,12 +4,12 @@ expression: metric.cyclomatic --- { "sum": 3.0, - "average": 1.5, + "average": 3.0, "min": 1.0, "max": 2.0, "modified": { "sum": 3.0, - "average": 1.5, + "average": 3.0, "min": 1.0, "max": 2.0 } diff --git a/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__mozjs_for_loop.snap b/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__mozjs_for_loop.snap index ec46c562..3bb81c84 100644 --- a/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__mozjs_for_loop.snap +++ b/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__mozjs_for_loop.snap @@ -4,12 +4,12 @@ expression: metric.cyclomatic --- { "sum": 3.0, - "average": 1.5, + "average": 3.0, "min": 1.0, "max": 2.0, "modified": { "sum": 3.0, - "average": 1.5, + "average": 3.0, "min": 1.0, "max": 2.0 } diff --git a/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__mozjs_logical_operators.snap b/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__mozjs_logical_operators.snap index ace56820..08dec2ba 100644 --- a/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__mozjs_logical_operators.snap +++ b/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__mozjs_logical_operators.snap @@ -4,12 +4,12 @@ expression: metric.cyclomatic --- { "sum": 5.0, - "average": 2.5, + "average": 5.0, "min": 1.0, "max": 4.0, "modified": { "sum": 5.0, - "average": 2.5, + "average": 5.0, "min": 1.0, "max": 4.0 } diff --git a/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__mozjs_while_loop.snap b/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__mozjs_while_loop.snap index ec46c562..3bb81c84 100644 --- a/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__mozjs_while_loop.snap +++ b/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__mozjs_while_loop.snap @@ -4,12 +4,12 @@ expression: metric.cyclomatic --- { "sum": 3.0, - "average": 1.5, + "average": 3.0, "min": 1.0, "max": 2.0, "modified": { "sum": 3.0, - "average": 1.5, + "average": 3.0, "min": 1.0, "max": 2.0 } diff --git a/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__php_switch_modified.snap b/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__php_switch_modified.snap index 59bc9a7e..6ab34a15 100644 --- a/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__php_switch_modified.snap +++ b/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__php_switch_modified.snap @@ -4,12 +4,12 @@ expression: metric.cyclomatic --- { "sum": 5.0, - "average": 2.5, + "average": 5.0, "min": 1.0, "max": 4.0, "modified": { "sum": 3.0, - "average": 1.5, + "average": 3.0, "min": 1.0, "max": 2.0 } diff --git a/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__ruby_case_when_arms.snap b/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__ruby_case_when_arms.snap index 59bc9a7e..6ab34a15 100644 --- a/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__ruby_case_when_arms.snap +++ b/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__ruby_case_when_arms.snap @@ -4,12 +4,12 @@ expression: metric.cyclomatic --- { "sum": 5.0, - "average": 2.5, + "average": 5.0, "min": 1.0, "max": 4.0, "modified": { "sum": 3.0, - "average": 1.5, + "average": 3.0, "min": 1.0, "max": 2.0 } diff --git a/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__ruby_nested_branches.snap b/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__ruby_nested_branches.snap index 66b66a5c..8607e531 100644 --- a/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__ruby_nested_branches.snap +++ b/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__ruby_nested_branches.snap @@ -4,12 +4,12 @@ expression: metric.cyclomatic --- { "sum": 4.0, - "average": 2.0, + "average": 4.0, "min": 1.0, "max": 3.0, "modified": { "sum": 4.0, - "average": 2.0, + "average": 4.0, "min": 1.0, "max": 3.0 } diff --git a/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__ruby_rescue_modifier.snap b/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__ruby_rescue_modifier.snap index ec46c562..3bb81c84 100644 --- a/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__ruby_rescue_modifier.snap +++ b/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__ruby_rescue_modifier.snap @@ -4,12 +4,12 @@ expression: metric.cyclomatic --- { "sum": 3.0, - "average": 1.5, + "average": 3.0, "min": 1.0, "max": 2.0, "modified": { "sum": 3.0, - "average": 1.5, + "average": 3.0, "min": 1.0, "max": 2.0 } diff --git a/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__tcl_1_level_nesting.snap b/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__tcl_1_level_nesting.snap index 66b66a5c..8607e531 100644 --- a/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__tcl_1_level_nesting.snap +++ b/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__tcl_1_level_nesting.snap @@ -4,12 +4,12 @@ expression: metric.cyclomatic --- { "sum": 4.0, - "average": 2.0, + "average": 4.0, "min": 1.0, "max": 3.0, "modified": { "sum": 4.0, - "average": 2.0, + "average": 4.0, "min": 1.0, "max": 3.0 } diff --git a/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__tcl_catch_branch.snap b/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__tcl_catch_branch.snap index ec46c562..3bb81c84 100644 --- a/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__tcl_catch_branch.snap +++ b/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__tcl_catch_branch.snap @@ -4,12 +4,12 @@ expression: metric.cyclomatic --- { "sum": 3.0, - "average": 1.5, + "average": 3.0, "min": 1.0, "max": 2.0, "modified": { "sum": 3.0, - "average": 1.5, + "average": 3.0, "min": 1.0, "max": 2.0 } diff --git a/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__tcl_elseif_branch.snap b/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__tcl_elseif_branch.snap index 66b66a5c..8607e531 100644 --- a/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__tcl_elseif_branch.snap +++ b/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__tcl_elseif_branch.snap @@ -4,12 +4,12 @@ expression: metric.cyclomatic --- { "sum": 4.0, - "average": 2.0, + "average": 4.0, "min": 1.0, "max": 3.0, "modified": { "sum": 4.0, - "average": 2.0, + "average": 4.0, "min": 1.0, "max": 3.0 } diff --git a/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__tcl_logical_operators.snap b/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__tcl_logical_operators.snap index ace56820..08dec2ba 100644 --- a/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__tcl_logical_operators.snap +++ b/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__tcl_logical_operators.snap @@ -4,12 +4,12 @@ expression: metric.cyclomatic --- { "sum": 5.0, - "average": 2.5, + "average": 5.0, "min": 1.0, "max": 4.0, "modified": { "sum": 5.0, - "average": 2.5, + "average": 5.0, "min": 1.0, "max": 4.0 } diff --git a/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__tsx_for_loop.snap b/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__tsx_for_loop.snap index ec46c562..3bb81c84 100644 --- a/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__tsx_for_loop.snap +++ b/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__tsx_for_loop.snap @@ -4,12 +4,12 @@ expression: metric.cyclomatic --- { "sum": 3.0, - "average": 1.5, + "average": 3.0, "min": 1.0, "max": 2.0, "modified": { "sum": 3.0, - "average": 1.5, + "average": 3.0, "min": 1.0, "max": 2.0 } diff --git a/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__tsx_logical_operators.snap b/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__tsx_logical_operators.snap index 66b66a5c..8607e531 100644 --- a/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__tsx_logical_operators.snap +++ b/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__tsx_logical_operators.snap @@ -4,12 +4,12 @@ expression: metric.cyclomatic --- { "sum": 4.0, - "average": 2.0, + "average": 4.0, "min": 1.0, "max": 3.0, "modified": { "sum": 4.0, - "average": 2.0, + "average": 4.0, "min": 1.0, "max": 3.0 } diff --git a/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__tsx_switch.snap b/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__tsx_switch.snap index 2ee55f62..6d2debb9 100644 --- a/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__tsx_switch.snap +++ b/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__tsx_switch.snap @@ -4,12 +4,12 @@ expression: metric.cyclomatic --- { "sum": 4.0, - "average": 2.0, + "average": 4.0, "min": 1.0, "max": 3.0, "modified": { "sum": 3.0, - "average": 1.5, + "average": 3.0, "min": 1.0, "max": 2.0 } diff --git a/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__tsx_switch_modified.snap b/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__tsx_switch_modified.snap index 2ee55f62..6d2debb9 100644 --- a/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__tsx_switch_modified.snap +++ b/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__tsx_switch_modified.snap @@ -4,12 +4,12 @@ expression: metric.cyclomatic --- { "sum": 4.0, - "average": 2.0, + "average": 4.0, "min": 1.0, "max": 3.0, "modified": { "sum": 3.0, - "average": 1.5, + "average": 3.0, "min": 1.0, "max": 2.0 } diff --git a/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__tsx_try_catch.snap b/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__tsx_try_catch.snap index ec46c562..3bb81c84 100644 --- a/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__tsx_try_catch.snap +++ b/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__tsx_try_catch.snap @@ -4,12 +4,12 @@ expression: metric.cyclomatic --- { "sum": 3.0, - "average": 1.5, + "average": 3.0, "min": 1.0, "max": 2.0, "modified": { "sum": 3.0, - "average": 1.5, + "average": 3.0, "min": 1.0, "max": 2.0 } diff --git a/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__tsx_while_loop.snap b/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__tsx_while_loop.snap index ec46c562..3bb81c84 100644 --- a/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__tsx_while_loop.snap +++ b/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__tsx_while_loop.snap @@ -4,12 +4,12 @@ expression: metric.cyclomatic --- { "sum": 3.0, - "average": 1.5, + "average": 3.0, "min": 1.0, "max": 2.0, "modified": { "sum": 3.0, - "average": 1.5, + "average": 3.0, "min": 1.0, "max": 2.0 } diff --git a/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__typescript_for_loop.snap b/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__typescript_for_loop.snap index ec46c562..3bb81c84 100644 --- a/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__typescript_for_loop.snap +++ b/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__typescript_for_loop.snap @@ -4,12 +4,12 @@ expression: metric.cyclomatic --- { "sum": 3.0, - "average": 1.5, + "average": 3.0, "min": 1.0, "max": 2.0, "modified": { "sum": 3.0, - "average": 1.5, + "average": 3.0, "min": 1.0, "max": 2.0 } diff --git a/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__typescript_logical_operators.snap b/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__typescript_logical_operators.snap index 66b66a5c..8607e531 100644 --- a/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__typescript_logical_operators.snap +++ b/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__typescript_logical_operators.snap @@ -4,12 +4,12 @@ expression: metric.cyclomatic --- { "sum": 4.0, - "average": 2.0, + "average": 4.0, "min": 1.0, "max": 3.0, "modified": { "sum": 4.0, - "average": 2.0, + "average": 4.0, "min": 1.0, "max": 3.0 } diff --git a/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__typescript_try_catch.snap b/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__typescript_try_catch.snap index ec46c562..3bb81c84 100644 --- a/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__typescript_try_catch.snap +++ b/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__typescript_try_catch.snap @@ -4,12 +4,12 @@ expression: metric.cyclomatic --- { "sum": 3.0, - "average": 1.5, + "average": 3.0, "min": 1.0, "max": 2.0, "modified": { "sum": 3.0, - "average": 1.5, + "average": 3.0, "min": 1.0, "max": 2.0 } diff --git a/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__typescript_while_loop.snap b/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__typescript_while_loop.snap index ec46c562..3bb81c84 100644 --- a/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__typescript_while_loop.snap +++ b/src/metrics/snapshots/big_code_analysis__metrics__cyclomatic__tests__typescript_while_loop.snap @@ -4,12 +4,12 @@ expression: metric.cyclomatic --- { "sum": 3.0, - "average": 1.5, + "average": 3.0, "min": 1.0, "max": 2.0, "modified": { "sum": 3.0, - "average": 1.5, + "average": 3.0, "min": 1.0, "max": 2.0 } diff --git a/src/metrics/tokens.rs b/src/metrics/tokens.rs index cd510862..85c09e80 100644 --- a/src/metrics/tokens.rs +++ b/src/metrics/tokens.rs @@ -112,7 +112,7 @@ impl Stats { #[inline] #[must_use] pub fn tokens_average(&self) -> f64 { - self.tokens_sum() / self.space_count as f64 + crate::metrics::average(self.tokens_sum(), self.space_count) } /// Returns the smallest single-space token count. diff --git a/src/spaces.rs b/src/spaces.rs index fe96a57a..6a599798 100644 --- a/src/spaces.rs +++ b/src/spaces.rs @@ -367,10 +367,20 @@ impl FuncSpace { }) .flatten(); + let mut metrics = CodeMetrics::with_selected(selected); + // Seed the cyclomatic per-function divisor: each function/closure + // space contributes 1 to `function_spaces`, which `Stats::merge` + // then sums across the subtree. Sourced here from the space kind + // rather than from the `Nom` metric so the cyclomatic averages + // stay correct even when `Nom` is not selected (#512). + if kind == SpaceKind::Function { + metrics.cyclomatic.note_function_space(); + } + Self { name, spaces: Vec::new(), - metrics: CodeMetrics::with_selected(selected), + metrics, kind, start_line: start_position, end_line: end_position, diff --git a/tests/repositories/big-code-analysis-output b/tests/repositories/big-code-analysis-output index d4c999fa..65f5dccf 160000 --- a/tests/repositories/big-code-analysis-output +++ b/tests/repositories/big-code-analysis-output @@ -1 +1 @@ -Subproject commit d4c999fa95b7d7a071b86da8c9bfd12cc30f381e +Subproject commit 65f5dccf46ee9bfb40e8bc253b39826b22a2407b diff --git a/tests/snapshots/csv_test__csv_cpp_widget.snap b/tests/snapshots/csv_test__csv_cpp_widget.snap index 40814ed0..f89d3ece 100644 --- a/tests/snapshots/csv_test__csv_cpp_widget.snap +++ b/tests/snapshots/csv_test__csv_cpp_widget.snap @@ -3,8 +3,8 @@ source: tests/csv_test.rs expression: out --- path,space_name,space_kind,start_line,end_line,cognitive.sum,cognitive.average,cognitive.min,cognitive.max,cyclomatic.sum,cyclomatic.average,cyclomatic.min,cyclomatic.max,cyclomatic.modified.sum,cyclomatic.modified.average,cyclomatic.modified.min,cyclomatic.modified.max,halstead.unique_operators,halstead.total_operators,halstead.unique_operands,halstead.total_operands,halstead.length,halstead.estimated_program_length,halstead.purity_ratio,halstead.vocabulary,halstead.volume,halstead.difficulty,halstead.level,halstead.effort,halstead.time,halstead.bugs,loc.sloc,loc.ploc,loc.lloc,loc.cloc,loc.blank,loc.sloc_average,loc.ploc_average,loc.lloc_average,loc.cloc_average,loc.blank_average,loc.sloc_min,loc.sloc_max,loc.cloc_min,loc.cloc_max,loc.ploc_min,loc.ploc_max,loc.lloc_min,loc.lloc_max,loc.blank_min,loc.blank_max,nom.functions,nom.closures,nom.functions_average,nom.closures_average,nom.total,nom.average,nom.functions_min,nom.functions_max,nom.closures_min,nom.closures_max,nargs.function_args,nargs.closure_args,nargs.function_args_average,nargs.closure_args_average,nargs.total,nargs.average,nargs.function_args_min,nargs.function_args_max,nargs.closure_args_min,nargs.closure_args_max,nexits.sum,nexits.average,nexits.min,nexits.max,tokens.sum,tokens.average,tokens.min,tokens.max,abc.assignments,abc.branches,abc.conditions,abc.magnitude,abc.assignments_average,abc.branches_average,abc.conditions_average,abc.assignments_min,abc.assignments_max,abc.branches_min,abc.branches_max,abc.conditions_min,abc.conditions_max,wmc.classes,wmc.interfaces,wmc.total,npm.classes,npm.interfaces,npm.class_methods,npm.interface_methods,npm.class_coa,npm.interface_coa,npm.total,npm.total_methods,npm.coa,npa.classes,npa.interfaces,npa.class_attributes,npa.interface_attributes,npa.class_cda,npa.interface_cda,npa.total,npa.total_attributes,npa.cda,mi.original,mi.sei,mi.visual_studio -widget.cc,widget.cc,unit,2,10,0,0,0,0,5,1,1,1,5,1,1,1,8,18,6,9,27,39.50977500432694,1.4633250001602571,14,102.79858289555531,6,0.16666666666666666,616.7914973733318,34.266194298518435,0.024152995332196794,9,9,2,0,0,1.8,1.8,0.4,0,0,1,9,0,0,1,9,1,2,0,0,2,0,0.4,0,2,0.4,0,1,0,0,1,0,0.5,0,1,0.5,0,1,0,0,1,0.5,0,1,38,7.6,0,12,1,0,0,1,0.2,0,0,0,1,0,0,0,0,2,0,2,2,0,2,0,1,0,2,2,1,0,0,1,0,0,0,0,1,0,110.16454969426378,83.7420968306897,64.4237132714993 -widget.cc,ns,namespace,2,10,0,0,0,0,4,1,1,1,4,1,1,1,8,18,6,9,27,39.50977500432694,1.4633250001602571,14,102.79858289555531,6,0.16666666666666666,616.7914973733318,34.266194298518435,0.024152995332196794,9,9,2,0,0,2.25,2.25,0.5,0,0,1,9,0,0,1,9,1,2,0,0,2,0,0.5,0,2,0.5,0,1,0,0,1,0,0.5,0,1,0.5,0,1,0,0,1,0.5,0,1,38,9.5,5,12,1,0,0,1,0.25,0,0,0,1,0,0,0,0,2,0,2,2,0,2,0,1,0,2,2,1,0,0,1,0,0,0,0,1,0,110.3945496942638,83.97209683068972,64.55821619547591 -widget.cc,Widget,class,3,9,0,0,0,0,3,1,1,1,3,1,1,1,8,16,5,8,24,35.60964047443681,1.4837350197682004,13,88.81055323538621,6.4,0.15625,568.3875407064718,31.57708559480399,0.022872226594196698,7,7,2,0,0,2.3333333333333335,2.3333333333333335,0.6666666666666666,0,0,1,7,0,0,1,7,1,2,0,0,2,0,0.6666666666666666,0,2,0.6666666666666666,0,1,0,0,1,0,0.5,0,1,0.5,0,1,0,0,1,0.5,0,1,33,11,10,12,1,0,0,1,0.3333333333333333,0,0,0,1,0,0,0,0,2,0,2,2,0,2,0,1,0,2,2,1,0,0,1,0,0,0,0,1,0,115.45642705977977,91.17302234410326,67.51837839753202 +widget.cc,widget.cc,unit,2,10,0,0,0,0,5,2.5,1,1,5,2.5,1,1,8,18,6,9,27,39.50977500432694,1.4633250001602571,14,102.79858289555531,6,0.16666666666666666,616.7914973733318,34.266194298518435,0.024152995332196794,9,9,2,0,0,1.8,1.8,0.4,0,0,1,9,0,0,1,9,1,2,0,0,2,0,0.4,0,2,0.4,0,1,0,0,1,0,0.5,0,1,0.5,0,1,0,0,1,0.5,0,1,38,7.6,0,12,1,0,0,1,0.2,0,0,0,1,0,0,0,0,2,0,2,2,0,2,0,1,0,2,2,1,0,0,1,0,0,0,0,1,0,110.16454969426378,83.7420968306897,64.4237132714993 +widget.cc,ns,namespace,2,10,0,0,0,0,4,2,1,1,4,2,1,1,8,18,6,9,27,39.50977500432694,1.4633250001602571,14,102.79858289555531,6,0.16666666666666666,616.7914973733318,34.266194298518435,0.024152995332196794,9,9,2,0,0,2.25,2.25,0.5,0,0,1,9,0,0,1,9,1,2,0,0,2,0,0.5,0,2,0.5,0,1,0,0,1,0,0.5,0,1,0.5,0,1,0,0,1,0.5,0,1,38,9.5,5,12,1,0,0,1,0.25,0,0,0,1,0,0,0,0,2,0,2,2,0,2,0,1,0,2,2,1,0,0,1,0,0,0,0,1,0,110.3945496942638,83.97209683068972,64.55821619547591 +widget.cc,Widget,class,3,9,0,0,0,0,3,1.5,1,1,3,1.5,1,1,8,16,5,8,24,35.60964047443681,1.4837350197682004,13,88.81055323538621,6.4,0.15625,568.3875407064718,31.57708559480399,0.022872226594196698,7,7,2,0,0,2.3333333333333335,2.3333333333333335,0.6666666666666666,0,0,1,7,0,0,1,7,1,2,0,0,2,0,0.6666666666666666,0,2,0.6666666666666666,0,1,0,0,1,0,0.5,0,1,0.5,0,1,0,0,1,0.5,0,1,33,11,10,12,1,0,0,1,0.3333333333333333,0,0,0,1,0,0,0,0,2,0,2,2,0,2,0,1,0,2,2,1,0,0,1,0,0,0,0,1,0,115.45642705977977,91.17302234410326,67.51837839753202 widget.cc,value,function,5,5,0,0,0,0,1,1,1,1,1,1,1,1,5,5,2,2,7,13.60964047443681,1.944234353490973,7,19.651484454403228,2.5,0.4,49.12871113600807,2.7293728408893374,0.004471319041702271,1,1,1,0,0,1,1,1,0,0,1,1,0,0,1,1,1,1,0,0,1,0,1,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,10,10,10,10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,155.2836050228807,148.4278547652622,90.80912574437467 widget.cc,set,function,6,6,0,0,0,0,1,1,1,1,1,1,1,1,6,6,3,4,10,20.264662506490403,2.0264662506490403,9,31.69925001442312,4,0.25,126.79700005769249,7.044277780982916,0.008413009854528818,1,1,1,0,0,1,1,1,0,0,1,1,0,0,1,1,1,1,0,0,1,0,1,0,1,1,1,1,0,0,1,0,1,0,1,1,1,1,0,0,0,0,0,0,12,12,12,12,1,0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,152.79727628688778,144.8408406278255,89.35513233151332 diff --git a/tests/snapshots/csv_test__csv_python_greeter.snap b/tests/snapshots/csv_test__csv_python_greeter.snap index 74c63a85..d333d84e 100644 --- a/tests/snapshots/csv_test__csv_python_greeter.snap +++ b/tests/snapshots/csv_test__csv_python_greeter.snap @@ -3,7 +3,7 @@ source: tests/csv_test.rs expression: out --- path,space_name,space_kind,start_line,end_line,cognitive.sum,cognitive.average,cognitive.min,cognitive.max,cyclomatic.sum,cyclomatic.average,cyclomatic.min,cyclomatic.max,cyclomatic.modified.sum,cyclomatic.modified.average,cyclomatic.modified.min,cyclomatic.modified.max,halstead.unique_operators,halstead.total_operators,halstead.unique_operands,halstead.total_operands,halstead.length,halstead.estimated_program_length,halstead.purity_ratio,halstead.vocabulary,halstead.volume,halstead.difficulty,halstead.level,halstead.effort,halstead.time,halstead.bugs,loc.sloc,loc.ploc,loc.lloc,loc.cloc,loc.blank,loc.sloc_average,loc.ploc_average,loc.lloc_average,loc.cloc_average,loc.blank_average,loc.sloc_min,loc.sloc_max,loc.cloc_min,loc.cloc_max,loc.ploc_min,loc.ploc_max,loc.lloc_min,loc.lloc_max,loc.blank_min,loc.blank_max,nom.functions,nom.closures,nom.functions_average,nom.closures_average,nom.total,nom.average,nom.functions_min,nom.functions_max,nom.closures_min,nom.closures_max,nargs.function_args,nargs.closure_args,nargs.function_args_average,nargs.closure_args_average,nargs.total,nargs.average,nargs.function_args_min,nargs.function_args_max,nargs.closure_args_min,nargs.closure_args_max,nexits.sum,nexits.average,nexits.min,nexits.max,tokens.sum,tokens.average,tokens.min,tokens.max,abc.assignments,abc.branches,abc.conditions,abc.magnitude,abc.assignments_average,abc.branches_average,abc.conditions_average,abc.assignments_min,abc.assignments_max,abc.branches_min,abc.branches_max,abc.conditions_min,abc.conditions_max,wmc.classes,wmc.interfaces,wmc.total,npm.classes,npm.interfaces,npm.class_methods,npm.interface_methods,npm.class_coa,npm.interface_coa,npm.total,npm.total_methods,npm.coa,npa.classes,npa.interfaces,npa.class_attributes,npa.interface_attributes,npa.class_cda,npa.interface_cda,npa.total,npa.total_attributes,npa.cda,mi.original,mi.sei,mi.visual_studio -greeter.py,greeter.py,unit,2,9,1,0.5,0,1,5,1.25,1,2,5,1.25,1,2,6,10,6,14,24,31.019550008653873,1.292481250360578,12,86.03910001730775,7,0.14285714285714285,602.2737001211542,33.45965000673079,0.02377249024853662,8,7,4,0,1,2,1.75,1,0,0.25,2,8,0,0,2,7,1,4,0,1,2,0,0.5,0,2,0.5,0,1,0,0,3,0,1.5,0,3,1.5,0,2,0,0,2,1,0,2,41,10.25,0,25,1,0,1,1.4142135623730951,0.25,0,0.25,0,1,0,0,0,1,3,0,3,2,0,2,0,1,0,2,2,1,1,0,1,0,1,0,1,1,1,112.998077434453,87.83001324968197,66.08074703769181 -greeter.py,Greeter,class,2,9,1,0.5,0,1,4,1.3333333333333333,1,2,4,1.3333333333333333,1,2,6,10,6,14,24,31.019550008653873,1.292481250360578,12,86.03910001730775,7,0.14285714285714285,602.2737001211542,33.45965000673079,0.02377249024853662,8,7,4,0,1,2.6666666666666665,2.3333333333333335,1.3333333333333333,0,0.3333333333333333,2,8,0,0,2,7,1,4,0,1,2,0,0.6666666666666666,0,2,0.6666666666666666,0,1,0,0,3,0,1.5,0,3,1.5,0,2,0,0,2,1,0,2,41,13.666666666666666,3,25,1,0,1,1.4142135623730951,0.3333333333333333,0,0.3333333333333333,0,1,0,0,0,1,3,0,3,2,0,2,0,1,0,2,2,1,1,0,1,0,1,0,1,1,1,113.22807743445301,88.06001324968199,66.21524996166842 +greeter.py,greeter.py,unit,2,9,1,0.5,0,1,5,2.5,1,2,5,2.5,1,2,6,10,6,14,24,31.019550008653873,1.292481250360578,12,86.03910001730775,7,0.14285714285714285,602.2737001211542,33.45965000673079,0.02377249024853662,8,7,4,0,1,2,1.75,1,0,0.25,2,8,0,0,2,7,1,4,0,1,2,0,0.5,0,2,0.5,0,1,0,0,3,0,1.5,0,3,1.5,0,2,0,0,2,1,0,2,41,10.25,0,25,1,0,1,1.4142135623730951,0.25,0,0.25,0,1,0,0,0,1,3,0,3,2,0,2,0,1,0,2,2,1,1,0,1,0,1,0,1,1,1,112.998077434453,87.83001324968197,66.08074703769181 +greeter.py,Greeter,class,2,9,1,0.5,0,1,4,2,1,2,4,2,1,2,6,10,6,14,24,31.019550008653873,1.292481250360578,12,86.03910001730775,7,0.14285714285714285,602.2737001211542,33.45965000673079,0.02377249024853662,8,7,4,0,1,2.6666666666666665,2.3333333333333335,1.3333333333333333,0,0.3333333333333333,2,8,0,0,2,7,1,4,0,1,2,0,0.6666666666666666,0,2,0.6666666666666666,0,1,0,0,3,0,1.5,0,3,1.5,0,2,0,0,2,1,0,2,41,13.666666666666666,3,25,1,0,1,1.4142135623730951,0.3333333333333333,0,0.3333333333333333,0,1,0,0,0,1,3,0,3,2,0,2,0,1,0,2,2,1,1,0,1,0,1,0,1,1,1,113.22807743445301,88.06001324968199,66.21524996166842 greeter.py,__init__,function,3,4,0,0,0,0,1,1,1,1,1,1,1,1,4,4,3,6,10,12.754887502163468,1.2754887502163468,7,28.07354922057604,4,0.25,112.29419688230416,6.2385664934613425,0.007758604623869012,2,2,1,0,0,2,2,1,0,0,2,2,0,0,2,2,1,1,0,0,1,0,1,0,1,1,1,1,0,0,2,0,2,0,2,2,2,2,0,0,0,0,0,0,13,13,13,13,1,0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,142.19991098932817,129.5520742665475,83.15784268381765 greeter.py,greet,function,6,9,1,1,1,1,2,2,2,2,2,2,2,2,4,6,4,7,13,16,1.2307692307692308,8,39,3.5,0.2857142857142857,136.5,7.583333333333333,0.008836911647049637,4,4,3,0,0,4,4,3,0,0,4,4,0,0,4,4,3,3,0,0,1,0,1,0,1,1,1,1,0,0,1,0,1,0,1,1,1,1,0,0,2,2,2,2,25,25,25,25,0,0,1,1,0,0,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,129.0315107899836,110.65590846191628,75.45702385379158 diff --git a/tests/snapshots/csv_test__csv_rust_counter.snap b/tests/snapshots/csv_test__csv_rust_counter.snap index 42029f72..3130efc9 100644 --- a/tests/snapshots/csv_test__csv_rust_counter.snap +++ b/tests/snapshots/csv_test__csv_rust_counter.snap @@ -3,6 +3,6 @@ source: tests/csv_test.rs expression: out --- path,space_name,space_kind,start_line,end_line,cognitive.sum,cognitive.average,cognitive.min,cognitive.max,cyclomatic.sum,cyclomatic.average,cyclomatic.min,cyclomatic.max,cyclomatic.modified.sum,cyclomatic.modified.average,cyclomatic.modified.min,cyclomatic.modified.max,halstead.unique_operators,halstead.total_operators,halstead.unique_operands,halstead.total_operands,halstead.length,halstead.estimated_program_length,halstead.purity_ratio,halstead.vocabulary,halstead.volume,halstead.difficulty,halstead.level,halstead.effort,halstead.time,halstead.bugs,loc.sloc,loc.ploc,loc.lloc,loc.cloc,loc.blank,loc.sloc_average,loc.ploc_average,loc.lloc_average,loc.cloc_average,loc.blank_average,loc.sloc_min,loc.sloc_max,loc.cloc_min,loc.cloc_max,loc.ploc_min,loc.ploc_max,loc.lloc_min,loc.lloc_max,loc.blank_min,loc.blank_max,nom.functions,nom.closures,nom.functions_average,nom.closures_average,nom.total,nom.average,nom.functions_min,nom.functions_max,nom.closures_min,nom.closures_max,nargs.function_args,nargs.closure_args,nargs.function_args_average,nargs.closure_args_average,nargs.total,nargs.average,nargs.function_args_min,nargs.function_args_max,nargs.closure_args_min,nargs.closure_args_max,nexits.sum,nexits.average,nexits.min,nexits.max,tokens.sum,tokens.average,tokens.min,tokens.max,abc.assignments,abc.branches,abc.conditions,abc.magnitude,abc.assignments_average,abc.branches_average,abc.conditions_average,abc.assignments_min,abc.assignments_max,abc.branches_min,abc.branches_max,abc.conditions_min,abc.conditions_max,wmc.classes,wmc.interfaces,wmc.total,npm.classes,npm.interfaces,npm.class_methods,npm.interface_methods,npm.class_coa,npm.interface_coa,npm.total,npm.total_methods,npm.coa,npa.classes,npa.interfaces,npa.class_attributes,npa.interface_attributes,npa.class_cda,npa.interface_cda,npa.total,npa.total_attributes,npa.cda,mi.original,mi.sei,mi.visual_studio -counter.rs,counter.rs,unit,2,13,2,2,0,2,4,1.3333333333333333,1,2,4,1.3333333333333333,1,2,15,23,6,15,38,74.11313393845472,1.950345629959335,21,166.9080620655929,18.75,0.05333333333333334,3129.5261637298668,173.86256465165926,0.07131777790263222,12,11,3,0,1,4,3.6666666666666665,1,0,0.3333333333333333,8,12,0,0,8,11,3,3,0,1,1,0,0.3333333333333333,0,1,0.3333333333333333,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,45,15,4,34,1,0,2,2.23606797749979,0.3333333333333333,0,0.6666666666666666,0,1,0,0,0,2,2,0,2,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,0,1,0,103.21380797524063,73.61247636275048,60.358952032304465 -counter.rs,Counter,impl,4,13,2,2,0,2,3,1.5,1,2,3,1.5,1,2,14,20,6,13,33,68.81274391313339,2.085234664034345,20,142.62362713128297,15.166666666666666,0.06593406593406594,2163.125011491125,120.17361174950695,0.05575277534828428,10,10,3,0,0,5,5,1.5,0,0,8,10,0,0,8,10,3,3,0,0,1,0,0.5,0,1,0.5,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,38,19,4,34,1,0,2,2.23606797749979,0.5,0,1,0,1,0,0,0,2,2,0,2,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,107.21503374494837,79.28320507878054,62.69885014324466 +counter.rs,counter.rs,unit,2,13,2,2,0,2,4,4,1,2,4,4,1,2,15,23,6,15,38,74.11313393845472,1.950345629959335,21,166.9080620655929,18.75,0.05333333333333334,3129.5261637298668,173.86256465165926,0.07131777790263222,12,11,3,0,1,4,3.6666666666666665,1,0,0.3333333333333333,8,12,0,0,8,11,3,3,0,1,1,0,0.3333333333333333,0,1,0.3333333333333333,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,45,15,4,34,1,0,2,2.23606797749979,0.3333333333333333,0,0.6666666666666666,0,1,0,0,0,2,2,0,2,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,0,1,0,103.21380797524063,73.61247636275048,60.358952032304465 +counter.rs,Counter,impl,4,13,2,2,0,2,3,3,1,2,3,3,1,2,14,20,6,13,33,68.81274391313339,2.085234664034345,20,142.62362713128297,15.166666666666666,0.06593406593406594,2163.125011491125,120.17361174950695,0.05575277534828428,10,10,3,0,0,5,5,1.5,0,0,8,10,0,0,8,10,3,3,0,0,1,0,0.5,0,1,0.5,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,38,19,4,34,1,0,2,2.23606797749979,0.5,0,1,0,1,0,0,0,2,2,0,2,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,107.21503374494837,79.28320507878054,62.69885014324466 counter.rs,bump,function,5,12,2,2,2,2,2,2,2,2,2,2,2,2,13,18,5,12,30,59.715356810271004,1.9905118936757,18,125.09775004326937,15.6,0.06410256410256411,1951.524900675002,108.41805003750011,0.05205488323759921,8,8,3,0,0,8,8,3,0,0,8,8,0,0,8,8,3,3,0,0,1,0,1,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,34,34,34,34,1,0,2,2.23606797749979,1,0,2,1,1,0,0,2,2,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,111.74175077815008,85.71205743468377,65.34605308663747