Skip to content

Commit f391f31

Browse files
Replace single WMC field with class and interface sums (#916)
1 parent 7ee331d commit f391f31

File tree

3 files changed

+144
-41
lines changed

3 files changed

+144
-41
lines changed

src/metrics/wmc.rs

Lines changed: 131 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,11 @@ use crate::*;
1919
/// <https://www.researchgate.net/publication/3187649_Kemerer_CF_A_metric_suite_for_object_oriented_design_IEEE_Trans_Softw_Eng_206_476-493>
2020
#[derive(Debug, Clone, Default)]
2121
pub struct Stats {
22-
wmc: f64,
23-
cc: f64,
22+
cyclomatic: f64,
23+
class_wmc: f64,
24+
interface_wmc: f64,
25+
class_wmc_sum: f64,
26+
interface_wmc_sum: f64,
2427
space_kind: SpaceKind,
2528
}
2629

@@ -29,15 +32,23 @@ impl Serialize for Stats {
2932
where
3033
S: Serializer,
3134
{
32-
let mut st = serializer.serialize_struct("wmc", 1)?;
33-
st.serialize_field("wmc", &self.wmc())?;
35+
let mut st = serializer.serialize_struct("wmc", 3)?;
36+
st.serialize_field("classes", &self.class_wmc_sum())?;
37+
st.serialize_field("interfaces", &self.interface_wmc_sum())?;
38+
st.serialize_field("total", &self.total_wmc())?;
3439
st.end()
3540
}
3641
}
3742

3843
impl fmt::Display for Stats {
3944
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
40-
write!(f, "wmc: {}", self.wmc(),)
45+
write!(
46+
f,
47+
"classes: {}, interfaces: {}, total: {}",
48+
self.class_wmc_sum(),
49+
self.interface_wmc_sum(),
50+
self.total_wmc()
51+
)
4152
}
4253
}
4354

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

49-
match (self.space_kind, other.space_kind) {
50-
(Unit, Class | Interface) => {
51-
self.wmc += other.wmc;
60+
// Merges the cyclomatic complexity of a method
61+
// into the `Wmc` metric value of a class or interface
62+
if let Function = other.space_kind {
63+
match self.space_kind {
64+
Class => self.class_wmc += other.cyclomatic,
65+
Interface => self.interface_wmc += other.cyclomatic,
66+
_ => {}
5267
}
53-
(Class | Interface, Function) => {
54-
// Merges the cyclomatic complexity of the method
55-
// into the `Wmc` metric of the class or interface
56-
self.wmc += other.cc;
57-
}
58-
_ => {}
5968
}
69+
70+
self.class_wmc_sum += other.class_wmc_sum;
71+
self.interface_wmc_sum += other.interface_wmc_sum;
72+
}
73+
74+
/// Returns the `Wmc` metric value of the classes in a space.
75+
#[inline(always)]
76+
pub fn class_wmc(&self) -> f64 {
77+
self.class_wmc
78+
}
79+
80+
/// Returns the `Wmc` metric value of the interfaces in a space.
81+
#[inline(always)]
82+
pub fn interface_wmc(&self) -> f64 {
83+
self.interface_wmc
84+
}
85+
86+
/// Returns the sum of the `Wmc` metric values of the classes in a space.
87+
#[inline(always)]
88+
pub fn class_wmc_sum(&self) -> f64 {
89+
self.class_wmc_sum
90+
}
91+
92+
/// Returns the sum of the `Wmc` metric values of the interfaces in a space.
93+
#[inline(always)]
94+
pub fn interface_wmc_sum(&self) -> f64 {
95+
self.interface_wmc_sum
96+
}
97+
98+
/// Returns the total `Wmc` metric value in a space.
99+
#[inline(always)]
100+
pub fn total_wmc(&self) -> f64 {
101+
self.class_wmc_sum() + self.interface_wmc_sum()
60102
}
61103

62-
/// Returns the `Wmc` metric value.
104+
// Accumulates the `Wmc` metric values
105+
// of classes and interfaces into the sums
63106
#[inline(always)]
64-
pub fn wmc(&self) -> f64 {
65-
self.wmc
107+
pub(crate) fn compute_sum(&mut self) {
108+
self.class_wmc_sum += self.class_wmc;
109+
self.interface_wmc_sum += self.interface_wmc;
66110
}
67111

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

97-
match space_kind {
98-
Function => {
141+
if let Unit | Class | Interface | Function = space_kind {
142+
if stats.space_kind == Unknown {
99143
stats.space_kind = space_kind;
100-
// Saves the cyclomatic complexity of the method
101-
stats.cc = cyclomatic.cyclomatic_sum();
102144
}
103-
Class | Interface | Unit => {
104-
stats.space_kind = space_kind;
145+
if space_kind == Function {
146+
// Saves the cyclomatic complexity of the method
147+
stats.cyclomatic = cyclomatic.cyclomatic_sum();
105148
}
106-
_ => {}
107149
}
108150
}
109151
}
@@ -160,7 +202,11 @@ mod tests {
160202
"foo.java",
161203
JavaParser,
162204
wmc,
163-
[(wmc, 13.0)] // 1 top level class
205+
[
206+
(class_wmc_sum, 13.0), // 1 class
207+
(interface_wmc_sum, 0.0),
208+
(total_wmc, 13.0)
209+
]
164210
);
165211
}
166212

@@ -194,7 +240,11 @@ mod tests {
194240
"foo.java",
195241
JavaParser,
196242
wmc,
197-
[(wmc, 5.0)] // 2 top level classes (wmc total = 3 + 2)
243+
[
244+
(class_wmc_sum, 5.0), // 2 classes (3 + 2)
245+
(interface_wmc_sum, 0.0),
246+
(total_wmc, 5.0)
247+
]
198248
);
199249
}
200250

@@ -211,7 +261,11 @@ mod tests {
211261
"foo.java",
212262
JavaParser,
213263
wmc,
214-
[(wmc, 0.0)] // 1 top level class
264+
[
265+
(class_wmc_sum, 1.0), // 2 classes (0 + 1)
266+
(interface_wmc_sum, 0.0),
267+
(total_wmc, 1.0)
268+
]
215269
);
216270
}
217271

@@ -270,7 +324,11 @@ mod tests {
270324
"foo.java",
271325
JavaParser,
272326
wmc,
273-
[(wmc, 2.0)] // 1 top level class
327+
[
328+
(class_wmc_sum, 9.0), // 6 classes (2 + 1 + 2 + 1 + 1 + 2)
329+
(interface_wmc_sum, 0.0),
330+
(total_wmc, 9.0)
331+
]
274332
);
275333
}
276334

@@ -298,7 +356,11 @@ mod tests {
298356
"foo.java",
299357
JavaParser,
300358
wmc,
301-
[(wmc, 5.0)] // 1 top level class
359+
[
360+
(class_wmc_sum, 7.0), // 2 classes (5 + 2)
361+
(interface_wmc_sum, 0.0),
362+
(total_wmc, 7.0)
363+
]
302364
);
303365
}
304366

@@ -323,7 +385,11 @@ mod tests {
323385
"foo.java",
324386
JavaParser,
325387
wmc,
326-
[(wmc, 4.0)] // 2 top level classes (wmc total = 1 + 3)
388+
[
389+
(class_wmc_sum, 4.0), // 2 classes (1 + 3)
390+
(interface_wmc_sum, 0.0),
391+
(total_wmc, 4.0)
392+
]
327393
);
328394
}
329395

@@ -362,7 +428,11 @@ mod tests {
362428
"foo.java",
363429
JavaParser,
364430
wmc,
365-
[(wmc, 8.0)] // 2 top level classes (wmc total = 2 + 6)
431+
[
432+
(class_wmc_sum, 8.0), // 2 classes (2 + 6)
433+
(interface_wmc_sum, 0.0),
434+
(total_wmc, 8.0)
435+
]
366436
);
367437
}
368438

@@ -388,7 +458,11 @@ mod tests {
388458
"foo.java",
389459
JavaParser,
390460
wmc,
391-
[(wmc, 2.0)] // 1 top level class
461+
[
462+
(class_wmc_sum, 2.0), // 1 class
463+
(interface_wmc_sum, 0.0),
464+
(total_wmc, 2.0)
465+
]
392466
);
393467
}
394468

@@ -407,7 +481,11 @@ mod tests {
407481
"foo.java",
408482
JavaParser,
409483
wmc,
410-
[(wmc, 6.0)] // 1 top level interface
484+
[
485+
(class_wmc_sum, 0.0),
486+
(interface_wmc_sum, 6.0), // 1 interface
487+
(total_wmc, 6.0)
488+
]
411489
);
412490
}
413491

@@ -428,7 +506,11 @@ mod tests {
428506
"foo.java",
429507
JavaParser,
430508
wmc,
431-
[(wmc, 3.0)] // 2 top level interfaces (wmc total = 1 + 2)
509+
[
510+
(class_wmc_sum, 0.0),
511+
(interface_wmc_sum, 3.0), // 2 interfaces (1 + 2)
512+
(total_wmc, 3.0)
513+
]
432514
);
433515
}
434516

@@ -453,7 +535,11 @@ mod tests {
453535
"foo.java",
454536
JavaParser,
455537
wmc,
456-
[(wmc, 1.0)] // 1 top level interface
538+
[
539+
(class_wmc_sum, 0.0),
540+
(interface_wmc_sum, 5.0), // 4 interfaces (1 + 1 + 2 + 1)
541+
(total_wmc, 5.0)
542+
]
457543
);
458544
}
459545

@@ -478,7 +564,11 @@ mod tests {
478564
"foo.java",
479565
JavaParser,
480566
wmc,
481-
[(wmc, 2.0)] // 1 top level interface
567+
[
568+
(class_wmc_sum, 2.0), // 1 class
569+
(interface_wmc_sum, 2.0), // 1 interface
570+
(total_wmc, 4.0)
571+
]
482572
);
483573
}
484574

@@ -503,7 +593,11 @@ mod tests {
503593
"foo.java",
504594
JavaParser,
505595
wmc,
506-
[(wmc, 2.0)] // 1 top level class
596+
[
597+
(class_wmc_sum, 2.0), // 1 class
598+
(interface_wmc_sum, 2.0), // 1 interface
599+
(total_wmc, 4.0)
600+
]
507601
);
508602
}
509603
}

src/output/dump_metrics.rs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -339,16 +339,24 @@ fn dump_wmc(
339339
return Ok(());
340340
}
341341

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

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

347347
color!(stdout, Green, true);
348-
write!(stdout, "wmc: ")?;
348+
writeln!(stdout, "wmc")?;
349349

350-
color!(stdout, White);
351-
writeln!(stdout, "{}", stats.wmc())
350+
let prefix = format!("{}{}", prefix, pref_child);
351+
dump_value("classes", stats.class_wmc_sum(), &prefix, false, stdout)?;
352+
dump_value(
353+
"interfaces",
354+
stats.interface_wmc_sum(),
355+
&prefix,
356+
false,
357+
stdout,
358+
)?;
359+
dump_value("total", stats.total_wmc(), &prefix, true, stdout)
352360
}
353361

354362
fn dump_npm(

src/spaces.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,7 @@ fn compute_minmax(state: &mut State) {
222222

223223
#[inline(always)]
224224
fn compute_sum(state: &mut State) {
225+
state.space.metrics.wmc.compute_sum();
225226
state.space.metrics.npm.compute_sum();
226227
state.space.metrics.npa.compute_sum();
227228
}

0 commit comments

Comments
 (0)