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
168 changes: 131 additions & 37 deletions src/metrics/wmc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,11 @@ use crate::*;
/// <https://www.researchgate.net/publication/3187649_Kemerer_CF_A_metric_suite_for_object_oriented_design_IEEE_Trans_Softw_Eng_206_476-493>
#[derive(Debug, Clone, Default)]
pub struct Stats {
wmc: f64,
cc: f64,
cyclomatic: f64,
class_wmc: f64,
interface_wmc: f64,
class_wmc_sum: f64,
interface_wmc_sum: f64,
space_kind: SpaceKind,
}

Expand All @@ -29,15 +32,23 @@ impl Serialize for Stats {
where
S: Serializer,
{
let mut st = serializer.serialize_struct("wmc", 1)?;
st.serialize_field("wmc", &self.wmc())?;
let mut st = serializer.serialize_struct("wmc", 3)?;
st.serialize_field("classes", &self.class_wmc_sum())?;
st.serialize_field("interfaces", &self.interface_wmc_sum())?;
st.serialize_field("total", &self.total_wmc())?;
st.end()
}
}

impl fmt::Display for Stats {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "wmc: {}", self.wmc(),)
write!(
f,
"classes: {}, interfaces: {}, total: {}",
self.class_wmc_sum(),
self.interface_wmc_sum(),
self.total_wmc()
)
}
}

Expand All @@ -46,23 +57,56 @@ impl Stats {
pub fn merge(&mut self, other: &Stats) {
use SpaceKind::*;

match (self.space_kind, other.space_kind) {
(Unit, Class | Interface) => {
self.wmc += other.wmc;
// Merges the cyclomatic complexity of a method
// into the `Wmc` metric value of a class or interface
if let Function = other.space_kind {
match self.space_kind {
Class => self.class_wmc += other.cyclomatic,
Interface => self.interface_wmc += other.cyclomatic,
_ => {}
}
(Class | Interface, Function) => {
// Merges the cyclomatic complexity of the method
// into the `Wmc` metric of the class or interface
self.wmc += other.cc;
}
_ => {}
}

self.class_wmc_sum += other.class_wmc_sum;
self.interface_wmc_sum += other.interface_wmc_sum;
}

/// Returns the `Wmc` metric value of the classes in a space.
#[inline(always)]
pub fn class_wmc(&self) -> f64 {
self.class_wmc
}

/// Returns the `Wmc` metric value of the interfaces in a space.
#[inline(always)]
pub fn interface_wmc(&self) -> f64 {
self.interface_wmc
}

/// Returns the sum of the `Wmc` metric values of the classes in a space.
#[inline(always)]
pub fn class_wmc_sum(&self) -> f64 {
self.class_wmc_sum
}

/// Returns the sum of the `Wmc` metric values of the interfaces in a space.
#[inline(always)]
pub fn interface_wmc_sum(&self) -> f64 {
self.interface_wmc_sum
}

/// Returns the total `Wmc` metric value in a space.
#[inline(always)]
pub fn total_wmc(&self) -> f64 {
self.class_wmc_sum() + self.interface_wmc_sum()
}

/// Returns the `Wmc` metric value.
// Accumulates the `Wmc` metric values
// of classes and interfaces into the sums
#[inline(always)]
pub fn wmc(&self) -> f64 {
self.wmc
pub(crate) fn compute_sum(&mut self) {
self.class_wmc_sum += self.class_wmc;
self.interface_wmc_sum += self.interface_wmc;
}

// Checks if the `Wmc` metric is disabled
Expand Down Expand Up @@ -94,16 +138,14 @@ impl Wmc for JavaCode {
fn compute(space_kind: SpaceKind, cyclomatic: &cyclomatic::Stats, stats: &mut Stats) {
use SpaceKind::*;

match space_kind {
Function => {
if let Unit | Class | Interface | Function = space_kind {
if stats.space_kind == Unknown {
stats.space_kind = space_kind;
// Saves the cyclomatic complexity of the method
stats.cc = cyclomatic.cyclomatic_sum();
}
Class | Interface | Unit => {
stats.space_kind = space_kind;
if space_kind == Function {
// Saves the cyclomatic complexity of the method
stats.cyclomatic = cyclomatic.cyclomatic_sum();
}
_ => {}
}
}
}
Expand Down Expand Up @@ -160,7 +202,11 @@ mod tests {
"foo.java",
JavaParser,
wmc,
[(wmc, 13.0)] // 1 top level class
[
(class_wmc_sum, 13.0), // 1 class
(interface_wmc_sum, 0.0),
(total_wmc, 13.0)
]
);
}

Expand Down Expand Up @@ -194,7 +240,11 @@ mod tests {
"foo.java",
JavaParser,
wmc,
[(wmc, 5.0)] // 2 top level classes (wmc total = 3 + 2)
[
(class_wmc_sum, 5.0), // 2 classes (3 + 2)
(interface_wmc_sum, 0.0),
(total_wmc, 5.0)
]
);
}

Expand All @@ -211,7 +261,11 @@ mod tests {
"foo.java",
JavaParser,
wmc,
[(wmc, 0.0)] // 1 top level class
[
(class_wmc_sum, 1.0), // 2 classes (0 + 1)
(interface_wmc_sum, 0.0),
(total_wmc, 1.0)
]
);
}

Expand Down Expand Up @@ -270,7 +324,11 @@ mod tests {
"foo.java",
JavaParser,
wmc,
[(wmc, 2.0)] // 1 top level class
[
(class_wmc_sum, 9.0), // 6 classes (2 + 1 + 2 + 1 + 1 + 2)
(interface_wmc_sum, 0.0),
(total_wmc, 9.0)
]
);
}

Expand Down Expand Up @@ -298,7 +356,11 @@ mod tests {
"foo.java",
JavaParser,
wmc,
[(wmc, 5.0)] // 1 top level class
[
(class_wmc_sum, 7.0), // 2 classes (5 + 2)
(interface_wmc_sum, 0.0),
(total_wmc, 7.0)
]
);
}

Expand All @@ -323,7 +385,11 @@ mod tests {
"foo.java",
JavaParser,
wmc,
[(wmc, 4.0)] // 2 top level classes (wmc total = 1 + 3)
[
(class_wmc_sum, 4.0), // 2 classes (1 + 3)
(interface_wmc_sum, 0.0),
(total_wmc, 4.0)
]
);
}

Expand Down Expand Up @@ -362,7 +428,11 @@ mod tests {
"foo.java",
JavaParser,
wmc,
[(wmc, 8.0)] // 2 top level classes (wmc total = 2 + 6)
[
(class_wmc_sum, 8.0), // 2 classes (2 + 6)
(interface_wmc_sum, 0.0),
(total_wmc, 8.0)
]
);
}

Expand All @@ -388,7 +458,11 @@ mod tests {
"foo.java",
JavaParser,
wmc,
[(wmc, 2.0)] // 1 top level class
[
(class_wmc_sum, 2.0), // 1 class
(interface_wmc_sum, 0.0),
(total_wmc, 2.0)
]
);
}

Expand All @@ -407,7 +481,11 @@ mod tests {
"foo.java",
JavaParser,
wmc,
[(wmc, 6.0)] // 1 top level interface
[
(class_wmc_sum, 0.0),
(interface_wmc_sum, 6.0), // 1 interface
(total_wmc, 6.0)
]
);
}

Expand All @@ -428,7 +506,11 @@ mod tests {
"foo.java",
JavaParser,
wmc,
[(wmc, 3.0)] // 2 top level interfaces (wmc total = 1 + 2)
[
(class_wmc_sum, 0.0),
(interface_wmc_sum, 3.0), // 2 interfaces (1 + 2)
(total_wmc, 3.0)
]
);
}

Expand All @@ -453,7 +535,11 @@ mod tests {
"foo.java",
JavaParser,
wmc,
[(wmc, 1.0)] // 1 top level interface
[
(class_wmc_sum, 0.0),
(interface_wmc_sum, 5.0), // 4 interfaces (1 + 1 + 2 + 1)
(total_wmc, 5.0)
]
);
}

Expand All @@ -478,7 +564,11 @@ mod tests {
"foo.java",
JavaParser,
wmc,
[(wmc, 2.0)] // 1 top level interface
[
(class_wmc_sum, 2.0), // 1 class
(interface_wmc_sum, 2.0), // 1 interface
(total_wmc, 4.0)
]
);
}

Expand All @@ -503,7 +593,11 @@ mod tests {
"foo.java",
JavaParser,
wmc,
[(wmc, 2.0)] // 1 top level class
[
(class_wmc_sum, 2.0), // 1 class
(interface_wmc_sum, 2.0), // 1 interface
(total_wmc, 4.0)
]
);
}
}
16 changes: 12 additions & 4 deletions src/output/dump_metrics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -339,16 +339,24 @@ fn dump_wmc(
return Ok(());
}

let pref = if last { "`- " } else { "|- " };
let (pref_child, pref) = if last { (" ", "`- ") } else { ("| ", "|- ") };

color!(stdout, Blue);
write!(stdout, "{}{}", prefix, pref)?;

color!(stdout, Green, true);
write!(stdout, "wmc: ")?;
writeln!(stdout, "wmc")?;

color!(stdout, White);
writeln!(stdout, "{}", stats.wmc())
let prefix = format!("{}{}", prefix, pref_child);
dump_value("classes", stats.class_wmc_sum(), &prefix, false, stdout)?;
dump_value(
"interfaces",
stats.interface_wmc_sum(),
&prefix,
false,
stdout,
)?;
dump_value("total", stats.total_wmc(), &prefix, true, stdout)
}

fn dump_npm(
Expand Down
1 change: 1 addition & 0 deletions src/spaces.rs
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ fn compute_minmax(state: &mut State) {

#[inline(always)]
fn compute_sum(state: &mut State) {
state.space.metrics.wmc.compute_sum();
state.space.metrics.npm.compute_sum();
state.space.metrics.npa.compute_sum();
}
Expand Down