rust_code_analysis/metrics/
nargs.rs

1use serde::ser::{SerializeStruct, Serializer};
2use serde::Serialize;
3use std::fmt;
4
5use crate::checker::Checker;
6use crate::*;
7
8/// The `NArgs` metric.
9///
10/// This metric counts the number of arguments
11/// of functions/closures.
12#[derive(Debug, Clone)]
13pub struct Stats {
14    fn_nargs: usize,
15    closure_nargs: usize,
16    fn_nargs_sum: usize,
17    closure_nargs_sum: usize,
18    fn_nargs_min: usize,
19    closure_nargs_min: usize,
20    fn_nargs_max: usize,
21    closure_nargs_max: usize,
22    total_functions: usize,
23    total_closures: usize,
24}
25
26impl Default for Stats {
27    fn default() -> Self {
28        Self {
29            fn_nargs: 0,
30            closure_nargs: 0,
31            fn_nargs_sum: 0,
32            closure_nargs_sum: 0,
33            fn_nargs_min: usize::MAX,
34            closure_nargs_min: usize::MAX,
35            fn_nargs_max: 0,
36            closure_nargs_max: 0,
37            total_functions: 0,
38            total_closures: 0,
39        }
40    }
41}
42
43impl Serialize for Stats {
44    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
45    where
46        S: Serializer,
47    {
48        let mut st = serializer.serialize_struct("nargs", 10)?;
49        st.serialize_field("total_functions", &self.fn_args_sum())?;
50        st.serialize_field("total_closures", &self.closure_args_sum())?;
51        st.serialize_field("average_functions", &self.fn_args_average())?;
52        st.serialize_field("average_closures", &self.closure_args_average())?;
53        st.serialize_field("total", &self.nargs_total())?;
54        st.serialize_field("average", &self.nargs_average())?;
55        st.serialize_field("functions_min", &self.fn_args_min())?;
56        st.serialize_field("functions_max", &self.fn_args_max())?;
57        st.serialize_field("closures_min", &self.closure_args_min())?;
58        st.serialize_field("closures_max", &self.closure_args_max())?;
59        st.end()
60    }
61}
62
63impl fmt::Display for Stats {
64    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
65        write!(
66            f,
67            "total_functions: {}, total_closures: {}, average_functions: {}, average_closures: {}, total: {}, average: {}, functions_min: {}, functions_max: {}, closures_min: {}, closures_max: {}",
68            self.fn_args(),
69            self.closure_args(),
70            self.fn_args_average(),
71            self.closure_args_average(),
72            self.nargs_total(),
73            self.nargs_average(),
74            self.fn_args_min(),
75            self.fn_args_max(),
76            self.closure_args_min(),
77            self.closure_args_max()
78        )
79    }
80}
81
82impl Stats {
83    /// Merges a second `NArgs` metric into the first one
84    pub fn merge(&mut self, other: &Stats) {
85        self.closure_nargs_min = self.closure_nargs_min.min(other.closure_nargs_min);
86        self.closure_nargs_max = self.closure_nargs_max.max(other.closure_nargs_max);
87        self.fn_nargs_min = self.fn_nargs_min.min(other.fn_nargs_min);
88        self.fn_nargs_max = self.fn_nargs_max.max(other.fn_nargs_max);
89        self.fn_nargs_sum += other.fn_nargs_sum;
90        self.closure_nargs_sum += other.closure_nargs_sum;
91    }
92
93    /// Returns the number of function arguments in a space.
94    #[inline(always)]
95    pub fn fn_args(&self) -> f64 {
96        self.fn_nargs as f64
97    }
98
99    /// Returns the number of closure arguments in a space.
100    #[inline(always)]
101    pub fn closure_args(&self) -> f64 {
102        self.closure_nargs as f64
103    }
104
105    /// Returns the number of function arguments sum in a space.
106    #[inline(always)]
107    pub fn fn_args_sum(&self) -> f64 {
108        self.fn_nargs_sum as f64
109    }
110
111    /// Returns the number of closure arguments sum in a space.
112    #[inline(always)]
113    pub fn closure_args_sum(&self) -> f64 {
114        self.closure_nargs_sum as f64
115    }
116
117    /// Returns the average number of functions arguments in a space.
118    #[inline(always)]
119    pub fn fn_args_average(&self) -> f64 {
120        self.fn_nargs_sum as f64 / self.total_functions.max(1) as f64
121    }
122
123    /// Returns the average number of closures arguments in a space.
124    #[inline(always)]
125    pub fn closure_args_average(&self) -> f64 {
126        self.closure_nargs_sum as f64 / self.total_closures.max(1) as f64
127    }
128
129    /// Returns the total number of arguments of each function and
130    /// closure in a space.
131    #[inline(always)]
132    pub fn nargs_total(&self) -> f64 {
133        self.fn_args_sum() + self.closure_args_sum()
134    }
135
136    /// Returns the `NArgs` metric average value
137    ///
138    /// This value is computed dividing the `NArgs` value
139    /// for the total number of functions/closures in a space.
140    #[inline(always)]
141    pub fn nargs_average(&self) -> f64 {
142        self.nargs_total() / (self.total_functions + self.total_closures).max(1) as f64
143    }
144    /// Returns the minimum number of function arguments in a space.
145    #[inline(always)]
146    pub fn fn_args_min(&self) -> f64 {
147        self.fn_nargs_min as f64
148    }
149    /// Returns the maximum number of function arguments in a space.
150    #[inline(always)]
151    pub fn fn_args_max(&self) -> f64 {
152        self.fn_nargs_max as f64
153    }
154    /// Returns the minimum number of closure arguments in a space.
155    #[inline(always)]
156    pub fn closure_args_min(&self) -> f64 {
157        self.closure_nargs_min as f64
158    }
159    /// Returns the maximum number of closure arguments in a space.
160    #[inline(always)]
161    pub fn closure_args_max(&self) -> f64 {
162        self.closure_nargs_max as f64
163    }
164    #[inline(always)]
165    pub(crate) fn compute_sum(&mut self) {
166        self.closure_nargs_sum += self.closure_nargs;
167        self.fn_nargs_sum += self.fn_nargs;
168    }
169    #[inline(always)]
170    pub(crate) fn compute_minmax(&mut self) {
171        self.closure_nargs_min = self.closure_nargs_min.min(self.closure_nargs);
172        self.closure_nargs_max = self.closure_nargs_max.max(self.closure_nargs);
173        self.fn_nargs_min = self.fn_nargs_min.min(self.fn_nargs);
174        self.fn_nargs_max = self.fn_nargs_max.max(self.fn_nargs);
175        self.compute_sum();
176    }
177    pub(crate) fn finalize(&mut self, total_functions: usize, total_closures: usize) {
178        self.total_functions = total_functions;
179        self.total_closures = total_closures;
180    }
181}
182
183#[inline(always)]
184fn compute_args<T: Checker>(node: &Node, nargs: &mut usize) {
185    if let Some(params) = node.object().child_by_field_name("parameters") {
186        let node_params = Node::new(params);
187        node_params.act_on_child(&mut |n| {
188            if !T::is_non_arg(n) {
189                *nargs += 1;
190            }
191        });
192    }
193}
194
195#[doc(hidden)]
196pub trait NArgs
197where
198    Self: Checker,
199    Self: std::marker::Sized,
200{
201    fn compute(node: &Node, stats: &mut Stats) {
202        if Self::is_func(node) {
203            compute_args::<Self>(node, &mut stats.fn_nargs);
204            return;
205        }
206
207        if Self::is_closure(node) {
208            compute_args::<Self>(node, &mut stats.closure_nargs);
209        }
210    }
211}
212
213impl NArgs for CppCode {
214    fn compute(node: &Node, stats: &mut Stats) {
215        if Self::is_func(node) {
216            if let Some(declarator) = node.object().child_by_field_name("declarator") {
217                let new_node = Node::new(declarator);
218                compute_args::<Self>(&new_node, &mut stats.fn_nargs);
219            }
220            return;
221        }
222
223        if Self::is_closure(node) {
224            if let Some(declarator) = node.object().child_by_field_name("declarator") {
225                let new_node = Node::new(declarator);
226                compute_args::<Self>(&new_node, &mut stats.closure_nargs);
227            }
228        }
229    }
230}
231
232impl NArgs for MozjsCode {}
233impl NArgs for JavascriptCode {}
234impl NArgs for TypescriptCode {}
235impl NArgs for TsxCode {}
236impl NArgs for PreprocCode {}
237impl NArgs for CcommentCode {}
238impl NArgs for RustCode {}
239impl NArgs for PythonCode {}
240impl NArgs for JavaCode {}
241
242#[cfg(test)]
243mod tests {
244    use std::path::PathBuf;
245
246    use super::*;
247
248    #[test]
249    fn python_no_functions_and_closures() {
250        check_metrics!(
251            "a = 42",
252            "foo.py",
253            PythonParser,
254            nargs,
255            [
256                (fn_args_sum, 0, usize),
257                (closure_args_sum, 0, usize),
258                (nargs_total, 0, usize)
259            ],
260            [
261                (fn_args_average, 0.0),
262                (closure_args_average, 0.0),
263                (nargs_average, 0.0)
264            ] // 0 functions + 0 closures = 0
265        );
266    }
267
268    #[test]
269    fn rust_no_functions_and_closures() {
270        check_metrics!(
271            "let a = 42;",
272            "foo.rs",
273            RustParser,
274            nargs,
275            [
276                (fn_args_sum, 0, usize),
277                (closure_args_sum, 0, usize),
278                (nargs_total, 0, usize)
279            ],
280            [
281                (fn_args_average, 0.0),
282                (closure_args_average, 0.0),
283                (nargs_average, 0.0)
284            ] // 0 functions + 0 closures = 0
285        );
286    }
287
288    #[test]
289    fn cpp_no_functions_and_closures() {
290        check_metrics!(
291            "int a = 42;",
292            "foo.cpp",
293            CppParser,
294            nargs,
295            [
296                (fn_args_sum, 0, usize),
297                (closure_args_sum, 0, usize),
298                (nargs_total, 0, usize)
299            ],
300            [
301                (fn_args_average, 0.0),
302                (closure_args_average, 0.0),
303                (nargs_average, 0.0)
304            ] // 0 functions + 0 closures = 0
305        );
306    }
307
308    #[test]
309    fn javascript_no_functions_and_closures() {
310        check_metrics!(
311            "var a = 42;",
312            "foo.js",
313            JavascriptParser,
314            nargs,
315            [
316                (fn_args_sum, 0, usize),
317                (closure_args_sum, 0, usize),
318                (nargs_total, 0, usize)
319            ],
320            [
321                (fn_args_average, 0.0),
322                (closure_args_average, 0.0),
323                (nargs_average, 0.0)
324            ] // 0 functions + 0 closures = 0
325        );
326    }
327
328    #[test]
329    fn python_single_function() {
330        check_metrics!(
331            "def f(a, b):
332                 if a:
333                     return a",
334            "foo.py",
335            PythonParser,
336            nargs,
337            [
338                (fn_args_sum, 2, usize),
339                (closure_args_sum, 0, usize),
340                (nargs_total, 2, usize),
341                (fn_args_min, 0, usize),
342                (fn_args_max, 2, usize),
343                (closure_args_min, 0, usize),
344                (closure_args_max, 0, usize),
345            ],
346            [
347                (fn_args_average, 2.0),
348                (closure_args_average, 0.0),
349                (nargs_average, 2.0)
350            ] // 1 function
351        );
352    }
353
354    #[test]
355    fn rust_single_function() {
356        check_metrics!(
357            "fn f(a: bool, b: usize) {
358                 if a {
359                     return a;
360                }
361             }",
362            "foo.rs",
363            RustParser,
364            nargs,
365            [
366                (fn_args_sum, 2, usize),
367                (closure_args_sum, 0, usize),
368                (nargs_total, 2, usize),
369                (fn_args_min, 0, usize),
370                (fn_args_max, 2, usize),
371                (closure_args_min, 0, usize),
372                (closure_args_max, 0, usize),
373            ],
374            [
375                (fn_args_average, 2.0),
376                (closure_args_average, 0.0),
377                (nargs_average, 2.0)
378            ] // 1 function
379        );
380    }
381
382    #[test]
383    fn c_single_function() {
384        check_metrics!(
385            "int f(int a, int b) {
386                 if (a) {
387                     return a;
388                }
389             }",
390            "foo.c",
391            CppParser,
392            nargs,
393            [
394                (fn_args_sum, 2, usize),
395                (closure_args_sum, 0, usize),
396                (nargs_total, 2, usize),
397                (fn_args_min, 0, usize),
398                (fn_args_max, 2, usize),
399                (closure_args_min, 0, usize),
400                (closure_args_max, 0, usize),
401            ],
402            [
403                (fn_args_average, 2.0),
404                (closure_args_average, 0.0),
405                (nargs_average, 2.0)
406            ] // 1 function
407        );
408    }
409
410    #[test]
411    fn javascript_single_function() {
412        check_metrics!(
413            "function f(a, b) {
414                 return a * b;
415             }",
416            "foo.js",
417            JavascriptParser,
418            nargs,
419            [
420                (fn_args_sum, 2, usize),
421                (closure_args_sum, 0, usize),
422                (nargs_total, 2, usize),
423                (fn_args_min, 0, usize),
424                (fn_args_max, 2, usize),
425                (closure_args_min, 0, usize),
426                (closure_args_max, 0, usize),
427            ],
428            [
429                (fn_args_average, 2.0),
430                (closure_args_average, 0.0),
431                (nargs_average, 2.0)
432            ] // 1 function
433        );
434    }
435
436    #[test]
437    fn python_single_lambda() {
438        check_metrics!(
439            "bar = lambda a: True",
440            "foo.py",
441            PythonParser,
442            nargs,
443            [
444                (fn_args_sum, 0, usize),
445                (closure_args_sum, 1, usize),
446                (nargs_total, 1, usize),
447                (fn_args_min, 0, usize),
448                (fn_args_max, 0, usize),
449                (closure_args_min, 1, usize),
450                (closure_args_max, 1, usize),
451            ],
452            [
453                (fn_args_average, 0.0),
454                (closure_args_average, 1.0),
455                (nargs_average, 1.0)
456            ] // 1 lambda
457        );
458    }
459
460    #[test]
461    fn rust_single_closure() {
462        check_metrics!(
463            "let bar = |i: i32| -> i32 { i + 1 };",
464            "foo.rs",
465            RustParser,
466            nargs,
467            [
468                (fn_args_sum, 0, usize),
469                (closure_args_sum, 1, usize),
470                (nargs_total, 1, usize),
471                (fn_args_min, 0, usize),
472                (fn_args_max, 0, usize),
473                (closure_args_min, 0, usize),
474                (closure_args_max, 1, usize),
475            ],
476            [
477                (fn_args_average, 0.0),
478                (closure_args_average, 1.0),
479                (nargs_average, 1.0)
480            ] // 1 lambda
481        );
482    }
483
484    #[test]
485    fn cpp_single_lambda() {
486        check_metrics!(
487            "auto bar = [](int x, int y) -> int { return x + y; };",
488            "foo.cpp",
489            CppParser,
490            nargs,
491            [
492                (fn_args_sum, 0, usize),
493                (closure_args_sum, 2, usize),
494                (nargs_total, 2, usize),
495                (fn_args_min, 0, usize),
496                (fn_args_max, 0, usize),
497                (closure_args_min, 2, usize),
498                (closure_args_max, 2, usize),
499            ],
500            [
501                (fn_args_average, 0.0),
502                (closure_args_average, 2.0),
503                (nargs_average, 2.0)
504            ] // 1 lambda
505        );
506    }
507
508    #[test]
509    fn javascript_single_closure() {
510        check_metrics!(
511            "function (a, b) {return a + b};",
512            "foo.js",
513            JavascriptParser,
514            nargs,
515            [
516                (fn_args_sum, 0, usize),
517                (closure_args_sum, 2, usize),
518                (nargs_total, 2, usize),
519                (fn_args_min, 0, usize),
520                (fn_args_max, 0, usize),
521                (closure_args_min, 0, usize),
522                (closure_args_max, 2, usize),
523            ],
524            [
525                (fn_args_average, 0.0),
526                (closure_args_average, 2.0),
527                (nargs_average, 2.0)
528            ] // 1 lambda
529        );
530    }
531
532    #[test]
533    fn python_functions() {
534        check_metrics!(
535            "def f(a, b):
536                 if a:
537                     return a
538            def f(a, b):
539                 if b:
540                     return b",
541            "foo.py",
542            PythonParser,
543            nargs,
544            [
545                (fn_args_sum, 4, usize),
546                (closure_args_sum, 0, usize),
547                (nargs_total, 4, usize),
548                (fn_args_min, 0, usize),
549                (fn_args_max, 2, usize),
550                (closure_args_min, 0, usize),
551                (closure_args_max, 0, usize),
552            ],
553            [
554                (fn_args_average, 2.0),
555                (closure_args_average, 0.0),
556                (nargs_average, 2.0)
557            ] // 2 functions
558        );
559
560        check_metrics!(
561            "def f(a, b):
562                 if a:
563                     return a
564            def f(a, b, c):
565                 if b:
566                     return b",
567            "foo.py",
568            PythonParser,
569            nargs,
570            [
571                (fn_args_sum, 5, usize),
572                (closure_args_sum, 0, usize),
573                (nargs_total, 5, usize),
574                (fn_args_min, 0, usize),
575                (fn_args_max, 3, usize),
576                (closure_args_min, 0, usize),
577                (closure_args_max, 0, usize),
578            ],
579            [
580                (fn_args_average, 2.5),
581                (closure_args_average, 0.0),
582                (nargs_average, 2.5)
583            ] // 2 functions
584        );
585    }
586
587    #[test]
588    fn rust_functions() {
589        check_metrics!(
590            "fn f(a: bool, b: usize) {
591                 if a {
592                     return a;
593                }
594             }
595             fn f1(a: bool, b: usize) {
596                 if a {
597                     return a;
598                }
599             }",
600            "foo.rs",
601            RustParser,
602            nargs,
603            [
604                (fn_args_sum, 4, usize),
605                (closure_args_sum, 0, usize),
606                (nargs_total, 4, usize),
607                (fn_args_min, 0, usize),
608                (fn_args_max, 2, usize),
609                (closure_args_min, 0, usize),
610                (closure_args_max, 0, usize),
611            ],
612            [
613                (fn_args_average, 2.0),
614                (closure_args_average, 0.0),
615                (nargs_average, 2.0)
616            ] // 2 functions
617        );
618
619        check_metrics!(
620            "fn f(a: bool, b: usize) {
621                 if a {
622                     return a;
623                }
624             }
625             fn f1(a: bool, b: usize, c: usize) {
626                 if a {
627                     return a;
628                }
629             }",
630            "foo.rs",
631            RustParser,
632            nargs,
633            [
634                (fn_args_sum, 5, usize),
635                (closure_args_sum, 0, usize),
636                (nargs_total, 5, usize),
637                (fn_args_min, 0, usize),
638                (fn_args_max, 3, usize),
639                (closure_args_min, 0, usize),
640                (closure_args_max, 0, usize),
641            ],
642            [
643                (fn_args_average, 2.5),
644                (closure_args_average, 0.0),
645                (nargs_average, 2.5)
646            ] // 2 functions
647        );
648    }
649
650    #[test]
651    fn c_functions() {
652        check_metrics!(
653            "int f(int a, int b) {
654                 if (a) {
655                     return a;
656                }
657             }
658             int f1(int a, int b) {
659                 if (a) {
660                     return a;
661                }
662             }",
663            "foo.c",
664            CppParser,
665            nargs,
666            [
667                (fn_args_sum, 4, usize),
668                (closure_args_sum, 0, usize),
669                (nargs_total, 4, usize),
670                (fn_args_min, 0, usize),
671                (fn_args_max, 2, usize),
672                (closure_args_min, 0, usize),
673                (closure_args_max, 0, usize),
674            ],
675            [
676                (fn_args_average, 2.0),
677                (closure_args_average, 0.0),
678                (nargs_average, 2.0)
679            ] // 2 functions
680        );
681
682        check_metrics!(
683            "int f(int a, int b) {
684                 if (a) {
685                     return a;
686                }
687             }
688             int f1(int a, int b, int c) {
689                 if (a) {
690                     return a;
691                }
692             }",
693            "foo.c",
694            CppParser,
695            nargs,
696            [
697                (fn_args_sum, 5, usize),
698                (closure_args_sum, 0, usize),
699                (nargs_total, 5, usize),
700                (fn_args_min, 0, usize),
701                (fn_args_max, 3, usize),
702                (closure_args_min, 0, usize),
703                (closure_args_max, 0, usize),
704            ],
705            [
706                (fn_args_average, 2.5),
707                (closure_args_average, 0.0),
708                (nargs_average, 2.5)
709            ] // 2 functions
710        );
711    }
712
713    #[test]
714    fn javascript_functions() {
715        check_metrics!(
716            "function f(a, b) {
717                 return a * b;
718             }
719             function f1(a, b) {
720                 return a * b;
721             }",
722            "foo.js",
723            JavascriptParser,
724            nargs,
725            [
726                (fn_args_sum, 4, usize),
727                (closure_args_sum, 0, usize),
728                (nargs_total, 4, usize),
729                (fn_args_min, 0, usize),
730                (fn_args_max, 2, usize),
731                (closure_args_min, 0, usize),
732                (closure_args_max, 0, usize),
733            ],
734            [
735                (fn_args_average, 2.0),
736                (closure_args_average, 0.0),
737                (nargs_average, 2.0)
738            ] // 2 functions
739        );
740
741        check_metrics!(
742            "function f(a, b) {
743                 return a * b;
744             }
745             function f1(a, b, c) {
746                 return a * b;
747             }",
748            "foo.js",
749            JavascriptParser,
750            nargs,
751            [
752                (fn_args_sum, 5, usize),
753                (closure_args_sum, 0, usize),
754                (nargs_total, 5, usize),
755                (fn_args_min, 0, usize),
756                (fn_args_max, 3, usize),
757                (closure_args_min, 0, usize),
758                (closure_args_max, 0, usize),
759            ],
760            [
761                (fn_args_average, 2.5),
762                (closure_args_average, 0.0),
763                (nargs_average, 2.5)
764            ] // 2 functions
765        );
766    }
767
768    #[test]
769    fn python_nested_functions() {
770        check_metrics!(
771            "def f(a, b):
772                 def foo(a):
773                     if a:
774                         return 1
775                 bar = lambda a: lambda b: b or True or True
776                 return bar(foo(a))(a)",
777            "foo.py",
778            PythonParser,
779            nargs,
780            [
781                (fn_args_sum, 3, usize),
782                (closure_args_sum, 2, usize),
783                (nargs_total, 5, usize),
784                (fn_args_min, 0, usize),
785                (fn_args_max, 2, usize),
786                (closure_args_min, 0, usize),
787                (closure_args_max, 2, usize),
788            ],
789            [
790                (fn_args_average, 1.5),
791                (closure_args_average, 1.0),
792                (nargs_average, 1.25)
793            ] // 2 functions + 2 lambdas = 4
794        );
795    }
796
797    #[test]
798    fn rust_nested_functions() {
799        check_metrics!(
800            "fn f(a: i32, b: i32) -> i32 {
801                 fn foo(a: i32) -> i32 {
802                     return a;
803                 }
804                 let bar = |a: i32, b: i32| -> i32 { a + 1 };
805                 let bar1 = |b: i32| -> i32 { b + 1 };
806                 return bar(foo(a), a);
807             }",
808            "foo.rs",
809            RustParser,
810            nargs,
811            [
812                (fn_args_sum, 3, usize),
813                (closure_args_sum, 3, usize),
814                (nargs_total, 6, usize),
815                (fn_args_min, 0, usize),
816                (fn_args_max, 2, usize),
817                (closure_args_min, 0, usize),
818                (closure_args_max, 2, usize),
819            ],
820            [
821                (fn_args_average, 1.5),
822                (closure_args_average, 1.5),
823                (nargs_average, 1.5)
824            ] // 2 functions + 2 lambdas = 4
825        );
826    }
827
828    #[test]
829    fn cpp_nested_functions() {
830        check_metrics!(
831            "int f(int a, int b, int c) {
832                 auto foo = [](int x) -> int { return x; };
833                 auto bar = [](int x, int y) -> int { return x + y; };
834                 return bar(foo(a), a);
835             }",
836            "foo.cpp",
837            CppParser,
838            nargs,
839            [
840                (fn_args_sum, 3, usize),
841                (closure_args_sum, 3, usize),
842                (nargs_total, 6, usize),
843                (fn_args_min, 0, usize),
844                (fn_args_max, 3, usize),
845                (closure_args_min, 0, usize),
846                (closure_args_max, 3, usize),
847            ],
848            [
849                (fn_args_average, 3.0),
850                (closure_args_average, 1.5),
851                (nargs_average, 2.0)
852            ] // 1 function + 2 lambdas = 3
853        );
854    }
855
856    #[test]
857    fn javascript_nested_functions() {
858        check_metrics!(
859            "function f(a, b) {
860                 function foo(a, c) {
861                     return a;
862                 }
863                 var bar = function (a, b) {return a + b};
864                 function (a) {return a};
865                 return bar(foo(a), a);
866             }",
867            "foo.js",
868            JavascriptParser,
869            nargs,
870            [
871                (fn_args_sum, 6, usize),
872                (closure_args_sum, 1, usize),
873                (nargs_total, 7, usize),
874                (fn_args_min, 0, usize),
875                (fn_args_max, 2, usize),
876                (closure_args_min, 0, usize),
877                (closure_args_max, 1, usize),
878            ],
879            [
880                (fn_args_average, 2.),
881                (closure_args_average, 1.),
882                (nargs_average, 1.75)
883            ] // 3 functions + 1 lambdas = 4
884        );
885    }
886}