Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 3 additions & 3 deletions big-code-analysis-web/src/web/server_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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},
Expand Down Expand Up @@ -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},
Expand Down Expand Up @@ -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},
Expand Down
6 changes: 3 additions & 3 deletions src/metrics/abc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down
10 changes: 6 additions & 4 deletions src/metrics/cognitive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
Loading
Loading