1+ use crate :: checker:: Checker ;
2+ use crate :: * ;
13use serde:: ser:: { SerializeStruct , Serializer } ;
24use serde:: Serialize ;
35use std:: fmt;
46
5- use crate :: checker:: Checker ;
6- use crate :: * ;
7-
87/// The `Cyclomatic` metric.
98#[ derive( Debug , Clone ) ]
109pub struct Stats {
10+ self_cyclomatic : f64 ,
1111 cyclomatic : f64 ,
1212 n : usize ,
13+ cyclomatic_max : f64 ,
14+ cyclomatic_min : f64 ,
1315}
1416
1517impl Default for Stats {
1618 fn default ( ) -> Self {
1719 Self {
20+ self_cyclomatic : 1. ,
1821 cyclomatic : 1. ,
1922 n : 1 ,
23+ cyclomatic_max : 0. ,
24+ cyclomatic_min : f64:: MAX ,
2025 }
2126 }
2227}
@@ -29,6 +34,8 @@ impl Serialize for Stats {
2934 let mut st = serializer. serialize_struct ( "cyclomatic" , 2 ) ?;
3035 st. serialize_field ( "sum" , & self . cyclomatic ( ) ) ?;
3136 st. serialize_field ( "average" , & self . cyclomatic_average ( ) ) ?;
37+ st. serialize_field ( "min" , & self . cyclomatic_min ( ) ) ?;
38+ st. serialize_field ( "max" , & self . cyclomatic_max ( ) ) ?;
3239 st. end ( )
3340 }
3441}
@@ -37,9 +44,11 @@ impl fmt::Display for Stats {
3744 fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
3845 write ! (
3946 f,
40- "sum: {}, average: {}" ,
47+ "sum: {}, average: {}, min: {}, max: {} " ,
4148 self . cyclomatic( ) ,
42- self . cyclomatic_average( )
49+ self . cyclomatic_average( ) ,
50+ self . cyclomatic_min( ) ,
51+ self . cyclomatic_max( )
4352 )
4453 }
4554}
@@ -49,6 +58,17 @@ impl Stats {
4958 pub fn merge ( & mut self , other : & Stats ) {
5059 self . cyclomatic += other. cyclomatic ;
5160 self . n += other. n ;
61+
62+ //Calculate minimum and maximum values
63+ if other. n == 1 {
64+ self . cyclomatic_max = self . cyclomatic_max . max ( other. cyclomatic ) ;
65+ self . cyclomatic_min = self . cyclomatic_min . min ( other. cyclomatic ) ;
66+ } else {
67+ self . cyclomatic_max = self . cyclomatic_max . max ( other. cyclomatic_max ) ;
68+ self . cyclomatic_min = self . cyclomatic_min . min ( other. cyclomatic_min ) ;
69+ self . cyclomatic_max = self . cyclomatic_max . max ( other. self_cyclomatic ) ;
70+ self . cyclomatic_min = self . cyclomatic_min . min ( other. self_cyclomatic ) ;
71+ }
5272 }
5373
5474 /// Returns the `Cyclomatic` metric value
@@ -63,6 +83,19 @@ impl Stats {
6383 pub fn cyclomatic_average ( & self ) -> f64 {
6484 self . cyclomatic ( ) / self . n as f64
6585 }
86+ /// Returns the `Cyclomatic` maximum value
87+ pub fn cyclomatic_max ( & self ) -> f64 {
88+ self . cyclomatic_max
89+ }
90+ /// Returns the `Cyclomatic` minimum value
91+ pub fn cyclomatic_min ( & self ) -> f64 {
92+ self . cyclomatic_min
93+ }
94+ /// Last step for computing minimum and maximum valus
95+ pub fn compute_minmax ( & mut self ) {
96+ self . cyclomatic_max = self . cyclomatic_max . max ( self . self_cyclomatic ) ;
97+ self . cyclomatic_min = self . cyclomatic_min . min ( self . self_cyclomatic ) ;
98+ }
6699}
67100
68101#[ doc( hidden) ]
@@ -80,10 +113,12 @@ impl Cyclomatic for PythonCode {
80113 match node. object ( ) . kind_id ( ) . into ( ) {
81114 If | Elif | For | While | Except | With | Assert | And | Or => {
82115 stats. cyclomatic += 1. ;
116+ stats. self_cyclomatic += 1. ;
83117 }
84118 Else => {
85119 if has_ancestors ! ( node, ForStatement | WhileStatement , ElseClause ) {
86120 stats. cyclomatic += 1. ;
121+ stats. self_cyclomatic += 1. ;
87122 }
88123 }
89124 _ => { }
@@ -98,6 +133,7 @@ impl Cyclomatic for MozjsCode {
98133 match node. object ( ) . kind_id ( ) . into ( ) {
99134 If | For | While | Case | Catch | TernaryExpression | AMPAMP | PIPEPIPE => {
100135 stats. cyclomatic += 1. ;
136+ stats. self_cyclomatic += 1. ;
101137 }
102138 _ => { }
103139 }
@@ -111,6 +147,7 @@ impl Cyclomatic for JavascriptCode {
111147 match node. object ( ) . kind_id ( ) . into ( ) {
112148 If | For | While | Case | Catch | TernaryExpression | AMPAMP | PIPEPIPE => {
113149 stats. cyclomatic += 1. ;
150+ stats. self_cyclomatic += 1. ;
114151 }
115152 _ => { }
116153 }
@@ -124,6 +161,7 @@ impl Cyclomatic for TypescriptCode {
124161 match node. object ( ) . kind_id ( ) . into ( ) {
125162 If | For | While | Case | Catch | TernaryExpression | AMPAMP | PIPEPIPE => {
126163 stats. cyclomatic += 1. ;
164+ stats. self_cyclomatic += 1. ;
127165 }
128166 _ => { }
129167 }
@@ -137,6 +175,7 @@ impl Cyclomatic for TsxCode {
137175 match node. object ( ) . kind_id ( ) . into ( ) {
138176 If | For | While | Case | Catch | TernaryExpression | AMPAMP | PIPEPIPE => {
139177 stats. cyclomatic += 1. ;
178+ stats. self_cyclomatic += 1. ;
140179 }
141180 _ => { }
142181 }
@@ -150,6 +189,7 @@ impl Cyclomatic for RustCode {
150189 match node. object ( ) . kind_id ( ) . into ( ) {
151190 If | For | While | Loop | MatchArm | MatchArm2 | QMARK | AMPAMP | PIPEPIPE => {
152191 stats. cyclomatic += 1. ;
192+ stats. self_cyclomatic += 1. ;
153193 }
154194 _ => { }
155195 }
@@ -163,6 +203,7 @@ impl Cyclomatic for CppCode {
163203 match node. object ( ) . kind_id ( ) . into ( ) {
164204 If | For | While | Case | Catch | ConditionalExpression | AMPAMP | PIPEPIPE => {
165205 stats. cyclomatic += 1. ;
206+ stats. self_cyclomatic += 1. ;
166207 }
167208 _ => { }
168209 }
@@ -192,7 +233,9 @@ mod tests {
192233 cyclomatic,
193234 [ ( cyclomatic, 6 , usize ) ] ,
194235 [
195- ( cyclomatic_average, 3.0 ) // nspace = 2 (func and unit)
236+ ( cyclomatic_average, 3.0 ) , // nspace = 2 (func and unit)
237+ ( cyclomatic_max, 5.0 ) ,
238+ ( cyclomatic_min, 1.0 )
196239 ]
197240 ) ;
198241 }
@@ -209,7 +252,9 @@ mod tests {
209252 cyclomatic,
210253 [ ( cyclomatic, 4 , usize ) ] ,
211254 [
212- ( cyclomatic_average, 2.0 ) // nspace = 2 (func and unit)
255+ ( cyclomatic_average, 2.0 ) , // nspace = 2 (func and unit)
256+ ( cyclomatic_max, 3.0 ) ,
257+ ( cyclomatic_min, 1.0 )
213258 ]
214259 ) ;
215260 }
@@ -230,7 +275,9 @@ mod tests {
230275 cyclomatic,
231276 [ ( cyclomatic, 5 , usize ) ] ,
232277 [
233- ( cyclomatic_average, 2.5 ) // nspace = 2 (func and unit)
278+ ( cyclomatic_average, 2.5 ) , // nspace = 2 (func and unit)
279+ ( cyclomatic_max, 4.0 ) ,
280+ ( cyclomatic_min, 1.0 )
234281 ]
235282 ) ;
236283 }
@@ -259,7 +306,9 @@ mod tests {
259306 cyclomatic,
260307 [ ( cyclomatic, 5 , usize ) ] ,
261308 [
262- ( cyclomatic_average, 2.5 ) // nspace = 2 (func and unit)
309+ ( cyclomatic_average, 2.5 ) , // nspace = 2 (func and unit)
310+ ( cyclomatic_max, 4.0 ) ,
311+ ( cyclomatic_min, 1.0 )
263312 ]
264313 ) ;
265314 }
@@ -284,7 +333,83 @@ mod tests {
284333 cyclomatic,
285334 [ ( cyclomatic, 5 , usize ) ] ,
286335 [
287- ( cyclomatic_average, 2.5 ) // nspace = 2 (func and unit)
336+ ( cyclomatic_average, 2.5 ) , // nspace = 2 (func and unit)
337+ ( cyclomatic_max, 4.0 ) ,
338+ ( cyclomatic_min, 1.0 )
339+ ]
340+ ) ;
341+ }
342+ #[ test]
343+ fn c_unit_before ( ) {
344+ check_metrics ! (
345+ "
346+ int a=42;
347+ if(a==42) //+2(+1 unit space)
348+ {
349+
350+ }
351+ if(a==34) //+1
352+ {
353+
354+ }
355+ int sumOfPrimes(int max) { // +1
356+ int total = 0;
357+ OUT: for (int i = 1; i <= max; ++i) { // +1
358+ for (int j = 2; j < i; ++j) { // +1
359+ if (i % j == 0) { // +1
360+ continue OUT;
361+ }
362+ }
363+ total += i;
364+ }
365+ return total;
366+ }" ,
367+ "foo.c" ,
368+ CppParser ,
369+ cyclomatic,
370+ [ ( cyclomatic, 7 , usize ) ] ,
371+ [
372+ ( cyclomatic_average, 3.5 ) , // nspace = 2 (func and unit)
373+ ( cyclomatic_max, 4.0 ) ,
374+ ( cyclomatic_min, 3.0 )
375+ ]
376+ ) ;
377+ }
378+
379+ #[ test]
380+ fn c_unit_after ( ) {
381+ check_metrics ! (
382+ "
383+ int sumOfPrimes(int max) { // +1
384+ int total = 0;
385+ OUT: for (int i = 1; i <= max; ++i) { // +1
386+ for (int j = 2; j < i; ++j) { // +1
387+ if (i % j == 0) { // +1
388+ continue OUT;
389+ }
390+ }
391+ total += i;
392+ }
393+ return total;
394+ }
395+
396+ int a=42;
397+ if(a==42) //+2(+1 unit space)
398+ {
399+
400+ }
401+ if(a==34) //+1
402+ {
403+
404+ }" ,
405+ "foo.c" ,
406+ CppParser ,
407+ cyclomatic,
408+ [ ( cyclomatic, 7 , usize ) ] ,
409+ [
410+ ( cyclomatic_average, 3.5 ) , // nspace = 2 (func and unit)
411+ ( cyclomatic_max, 4.0 ) ,
412+ ( cyclomatic_min, 3.0 )
288413 ]
289414 ) ;
290415 }
0 commit comments