1#![allow(clippy::wildcard_imports, clippy::enum_glob_use)]
8#![allow(
15 clippy::cast_precision_loss,
16 clippy::cast_possible_truncation,
17 clippy::cast_sign_loss
18)]
19
20use serde::Serialize;
21use serde::ser::{SerializeStruct, Serializer};
22use std::fmt;
23
24use crate::checker::Checker;
25use crate::macros::implement_metric_trait;
26use crate::*;
27
28#[derive(Debug, Clone)]
33pub struct Stats {
34 fn_nargs: usize,
35 closure_nargs: usize,
36 fn_nargs_sum: usize,
37 closure_nargs_sum: usize,
38 fn_nargs_min: usize,
39 closure_nargs_min: usize,
40 fn_nargs_max: usize,
41 closure_nargs_max: usize,
42 total_functions: usize,
43 total_closures: usize,
44}
45
46impl Default for Stats {
47 fn default() -> Self {
48 Self {
49 fn_nargs: 0,
50 closure_nargs: 0,
51 fn_nargs_sum: 0,
52 closure_nargs_sum: 0,
53 fn_nargs_min: usize::MAX,
54 closure_nargs_min: usize::MAX,
55 fn_nargs_max: 0,
56 closure_nargs_max: 0,
57 total_functions: 0,
58 total_closures: 0,
59 }
60 }
61}
62
63impl Serialize for Stats {
64 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
65 where
66 S: Serializer,
67 {
68 let mut st = serializer.serialize_struct("nargs", 10)?;
69 st.serialize_field("total_functions", &self.fn_args_sum())?;
70 st.serialize_field("total_closures", &self.closure_args_sum())?;
71 st.serialize_field("average_functions", &self.fn_args_average())?;
72 st.serialize_field("average_closures", &self.closure_args_average())?;
73 st.serialize_field("total", &self.nargs_total())?;
74 st.serialize_field("average", &self.nargs_average())?;
75 st.serialize_field("functions_min", &self.fn_args_min())?;
76 st.serialize_field("functions_max", &self.fn_args_max())?;
77 st.serialize_field("closures_min", &self.closure_args_min())?;
78 st.serialize_field("closures_max", &self.closure_args_max())?;
79 st.end()
80 }
81}
82
83impl fmt::Display for Stats {
84 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
85 write!(
86 f,
87 "total_functions: {}, total_closures: {}, average_functions: {}, average_closures: {}, total: {}, average: {}, functions_min: {}, functions_max: {}, closures_min: {}, closures_max: {}",
88 self.fn_args(),
89 self.closure_args(),
90 self.fn_args_average(),
91 self.closure_args_average(),
92 self.nargs_total(),
93 self.nargs_average(),
94 self.fn_args_min(),
95 self.fn_args_max(),
96 self.closure_args_min(),
97 self.closure_args_max()
98 )
99 }
100}
101
102impl Stats {
103 pub fn merge(&mut self, other: &Stats) {
105 self.closure_nargs_min = self.closure_nargs_min.min(other.closure_nargs_min);
106 self.closure_nargs_max = self.closure_nargs_max.max(other.closure_nargs_max);
107 self.fn_nargs_min = self.fn_nargs_min.min(other.fn_nargs_min);
108 self.fn_nargs_max = self.fn_nargs_max.max(other.fn_nargs_max);
109 self.fn_nargs_sum += other.fn_nargs_sum;
110 self.closure_nargs_sum += other.closure_nargs_sum;
111 }
112
113 #[inline]
115 #[must_use]
116 pub fn fn_args(&self) -> f64 {
117 self.fn_nargs as f64
118 }
119
120 #[inline]
122 #[must_use]
123 pub fn closure_args(&self) -> f64 {
124 self.closure_nargs as f64
125 }
126
127 #[inline]
129 #[must_use]
130 pub fn fn_args_sum(&self) -> f64 {
131 self.fn_nargs_sum as f64
132 }
133
134 #[inline]
136 #[must_use]
137 pub fn closure_args_sum(&self) -> f64 {
138 self.closure_nargs_sum as f64
139 }
140
141 #[inline]
143 #[must_use]
144 pub fn fn_args_average(&self) -> f64 {
145 self.fn_nargs_sum as f64 / self.total_functions.max(1) as f64
146 }
147
148 #[inline]
150 #[must_use]
151 pub fn closure_args_average(&self) -> f64 {
152 self.closure_nargs_sum as f64 / self.total_closures.max(1) as f64
153 }
154
155 #[inline]
158 #[must_use]
159 pub fn nargs_total(&self) -> f64 {
160 self.fn_args_sum() + self.closure_args_sum()
161 }
162
163 #[inline]
168 #[must_use]
169 pub fn nargs_average(&self) -> f64 {
170 self.nargs_total() / (self.total_functions + self.total_closures).max(1) as f64
171 }
172 #[inline]
178 #[must_use]
179 pub fn fn_args_min(&self) -> f64 {
180 if self.fn_nargs_min == usize::MAX {
181 0.0
182 } else {
183 self.fn_nargs_min as f64
184 }
185 }
186 #[inline]
188 #[must_use]
189 pub fn fn_args_max(&self) -> f64 {
190 self.fn_nargs_max as f64
191 }
192 #[inline]
196 #[must_use]
197 pub fn closure_args_min(&self) -> f64 {
198 if self.closure_nargs_min == usize::MAX {
199 0.0
200 } else {
201 self.closure_nargs_min as f64
202 }
203 }
204 #[inline]
206 #[must_use]
207 pub fn closure_args_max(&self) -> f64 {
208 self.closure_nargs_max as f64
209 }
210 #[inline]
211 pub(crate) fn compute_sum(&mut self) {
212 self.closure_nargs_sum += self.closure_nargs;
213 self.fn_nargs_sum += self.fn_nargs;
214 }
215 #[inline]
216 pub(crate) fn compute_minmax(&mut self) {
217 self.closure_nargs_min = self.closure_nargs_min.min(self.closure_nargs);
218 self.closure_nargs_max = self.closure_nargs_max.max(self.closure_nargs);
219 self.fn_nargs_min = self.fn_nargs_min.min(self.fn_nargs);
220 self.fn_nargs_max = self.fn_nargs_max.max(self.fn_nargs);
221 self.compute_sum();
222 }
223 pub(crate) fn finalize(&mut self, total_functions: usize, total_closures: usize) {
224 self.total_functions = total_functions;
225 self.total_closures = total_closures;
226 }
227}
228
229#[inline]
230fn compute_args<T: Checker>(node: &Node, nargs: &mut usize) {
231 if let Some(params) = node.child_by_field_name("parameters") {
232 let node_params = params;
233 node_params.act_on_child(&mut |n| {
234 if !T::is_non_arg(n) {
235 *nargs += 1;
236 }
237 });
238 } else if node.child_by_field_name("parameter").is_some() {
239 *nargs += 1;
244 }
245}
246
247#[doc(hidden)]
248pub trait NArgs
250where
251 Self: Checker,
252 Self: std::marker::Sized,
253{
254 fn compute(node: &Node, stats: &mut Stats) {
257 if Self::is_func(node) {
258 compute_args::<Self>(node, &mut stats.fn_nargs);
259 return;
260 }
261
262 if Self::is_closure(node) {
263 compute_args::<Self>(node, &mut stats.closure_nargs);
264 }
265 }
266}
267
268impl NArgs for CppCode {
269 fn compute(node: &Node, stats: &mut Stats) {
270 if Self::is_func(node) {
271 if let Some(declarator) = node.child_by_field_name("declarator") {
272 let new_node = declarator;
273 compute_args::<Self>(&new_node, &mut stats.fn_nargs);
274 }
275 return;
276 }
277
278 if Self::is_closure(node)
279 && let Some(declarator) = node.child_by_field_name("declarator")
280 {
281 let new_node = declarator;
282 compute_args::<Self>(&new_node, &mut stats.closure_nargs);
283 }
284 }
285}
286
287fn compute_go_args(node: &Node, nargs: &mut usize) {
292 let Some(params) = node.child_by_field_name("parameters") else {
293 return;
294 };
295 *nargs += params
296 .children()
297 .map(|child| match child.kind_id().into() {
298 Go::ParameterDeclaration => child
299 .children()
300 .filter(|c| c.kind_id() == Go::Identifier)
301 .count()
302 .max(1),
303 Go::VariadicParameterDeclaration => 1,
304 _ => 0,
305 })
306 .sum::<usize>();
307}
308
309impl NArgs for GoCode {
310 fn compute(node: &Node, stats: &mut Stats) {
311 if Self::is_func(node) {
312 compute_go_args(node, &mut stats.fn_nargs);
313 return;
314 }
315
316 if Self::is_closure(node) {
317 compute_go_args(node, &mut stats.closure_nargs);
318 }
319 }
320}
321
322fn compute_kotlin_func_args(node: &Node, nargs: &mut usize) {
323 if let Some(params) = node
324 .children()
325 .find(|c| c.kind_id() == Kotlin::FunctionValueParameters)
326 {
327 params.act_on_child(&mut |n| {
328 if n.kind_id() == Kotlin::Parameter {
329 *nargs += 1;
330 }
331 });
332 }
333}
334
335fn compute_kotlin_lambda_args(node: &Node, nargs: &mut usize) {
336 if let Some(params) = node
340 .children()
341 .find(|c| c.kind_id() == Kotlin::LambdaParameters)
342 {
343 params.act_on_child(&mut |n| {
344 if n.kind_id() != Kotlin::COMMA {
345 *nargs += 1;
346 }
347 });
348 }
349}
350
351impl NArgs for KotlinCode {
352 fn compute(node: &Node, stats: &mut Stats) {
353 if Self::is_func(node) {
354 compute_kotlin_func_args(node, &mut stats.fn_nargs);
355 return;
356 }
357
358 if Self::is_closure(node) {
359 if node.kind_id() == Kotlin::LambdaLiteral {
360 compute_kotlin_lambda_args(node, &mut stats.closure_nargs);
361 } else {
362 compute_kotlin_func_args(node, &mut stats.closure_nargs);
363 }
364 }
365 }
366}
367
368fn compute_lua_args(node: &Node, nargs: &mut usize) {
369 let Some(params) = node.child_by_field_name("parameters") else {
370 return;
371 };
372 *nargs += params
373 .children()
374 .filter(|c| matches!(c.kind_id().into(), Lua::Identifier | Lua::VarargExpression))
375 .count();
376}
377
378impl NArgs for LuaCode {
379 fn compute(node: &Node, stats: &mut Stats) {
380 if Self::is_func(node) {
381 compute_lua_args(node, &mut stats.fn_nargs);
382 } else if Self::is_closure(node) {
383 compute_lua_args(node, &mut stats.closure_nargs);
384 }
385 }
386}
387
388fn compute_tcl_args(node: &Node, nargs: &mut usize) {
389 let Some(params) = node.child_by_field_name("arguments") else {
390 return;
391 };
392 *nargs += params
393 .children()
394 .filter(|c| c.kind_id() == Tcl::Argument)
395 .count();
396}
397
398impl NArgs for TclCode {
399 fn compute(node: &Node, stats: &mut Stats) {
400 if Self::is_func(node) {
401 compute_tcl_args(node, &mut stats.fn_nargs);
402 }
403 }
404}
405
406implement_metric_trait!(
407 [NArgs],
408 PythonCode,
409 MozjsCode,
410 JavascriptCode,
411 TypescriptCode,
412 TsxCode,
413 RustCode,
414 PreprocCode,
415 CcommentCode,
416 JavaCode,
417 PerlCode,
418 BashCode,
419 PhpCode,
420 CsharpCode,
421 ElixirCode,
422 RubyCode
423);
424
425impl NArgs for GroovyCode {
430 fn compute(node: &Node, stats: &mut Stats) {
431 use crate::languages::language_groovy::Groovy;
432
433 if Self::is_func(node) {
434 compute_args::<Self>(node, &mut stats.fn_nargs);
435 return;
436 }
437
438 if Self::is_closure(node)
439 && let Some(params) = node.first_child(|id| id == Groovy::ClosureParameters)
440 {
441 params.act_on_child(&mut |n| {
442 if n.kind_id() == Groovy::ClosureParameter {
443 stats.closure_nargs += 1;
444 }
445 });
446 }
447 }
448}
449
450#[cfg(test)]
451#[allow(
452 clippy::float_cmp,
453 clippy::cast_precision_loss,
454 clippy::cast_possible_truncation,
455 clippy::cast_sign_loss,
456 clippy::similar_names,
457 clippy::doc_markdown,
458 clippy::needless_raw_string_hashes,
459 clippy::too_many_lines
460)]
461mod tests {
462 use crate::tools::check_metrics;
463
464 use super::*;
465
466 #[test]
471 fn nargs_empty_file_min_is_zero() {
472 let stats = Stats::default();
473 assert_eq!(stats.fn_args_min(), 0.0);
474 assert_eq!(stats.closure_args_min(), 0.0);
475 }
476
477 #[test]
478 fn python_no_functions_and_closures() {
479 check_metrics::<PythonParser>("a = 42", "foo.py", |metric| {
480 insta::assert_json_snapshot!(
482 metric.nargs,
483 @r###"
484 {
485 "total_functions": 0.0,
486 "total_closures": 0.0,
487 "average_functions": 0.0,
488 "average_closures": 0.0,
489 "total": 0.0,
490 "average": 0.0,
491 "functions_min": 0.0,
492 "functions_max": 0.0,
493 "closures_min": 0.0,
494 "closures_max": 0.0
495 }"###
496 );
497 });
498 }
499
500 #[test]
501 fn rust_no_functions_and_closures() {
502 check_metrics::<RustParser>("let a = 42;", "foo.rs", |metric| {
503 insta::assert_json_snapshot!(
505 metric.nargs,
506 @r###"
507 {
508 "total_functions": 0.0,
509 "total_closures": 0.0,
510 "average_functions": 0.0,
511 "average_closures": 0.0,
512 "total": 0.0,
513 "average": 0.0,
514 "functions_min": 0.0,
515 "functions_max": 0.0,
516 "closures_min": 0.0,
517 "closures_max": 0.0
518 }"###
519 );
520 });
521 }
522
523 #[test]
524 fn cpp_no_functions_and_closures() {
525 check_metrics::<CppParser>("int a = 42;", "foo.cpp", |metric| {
526 insta::assert_json_snapshot!(
528 metric.nargs,
529 @r###"
530 {
531 "total_functions": 0.0,
532 "total_closures": 0.0,
533 "average_functions": 0.0,
534 "average_closures": 0.0,
535 "total": 0.0,
536 "average": 0.0,
537 "functions_min": 0.0,
538 "functions_max": 0.0,
539 "closures_min": 0.0,
540 "closures_max": 0.0
541 }"###
542 );
543 });
544 }
545
546 #[test]
547 fn javascript_no_functions_and_closures() {
548 check_metrics::<JavascriptParser>("var a = 42;", "foo.js", |metric| {
549 insta::assert_json_snapshot!(
551 metric.nargs,
552 @r###"
553 {
554 "total_functions": 0.0,
555 "total_closures": 0.0,
556 "average_functions": 0.0,
557 "average_closures": 0.0,
558 "total": 0.0,
559 "average": 0.0,
560 "functions_min": 0.0,
561 "functions_max": 0.0,
562 "closures_min": 0.0,
563 "closures_max": 0.0
564 }"###
565 );
566 });
567 }
568
569 #[test]
570 fn python_single_function() {
571 check_metrics::<PythonParser>(
572 "def f(a, b):
573 if a:
574 return a",
575 "foo.py",
576 |metric| {
577 insta::assert_json_snapshot!(
579 metric.nargs,
580 @r###"
581 {
582 "total_functions": 2.0,
583 "total_closures": 0.0,
584 "average_functions": 2.0,
585 "average_closures": 0.0,
586 "total": 2.0,
587 "average": 2.0,
588 "functions_min": 0.0,
589 "functions_max": 2.0,
590 "closures_min": 0.0,
591 "closures_max": 0.0
592 }"###
593 );
594 },
595 );
596 }
597
598 #[test]
599 fn rust_single_function() {
600 check_metrics::<RustParser>(
601 "fn f(a: bool, b: usize) {
602 if a {
603 return a;
604 }
605 }",
606 "foo.rs",
607 |metric| {
608 insta::assert_json_snapshot!(
610 metric.nargs,
611 @r###"
612 {
613 "total_functions": 2.0,
614 "total_closures": 0.0,
615 "average_functions": 2.0,
616 "average_closures": 0.0,
617 "total": 2.0,
618 "average": 2.0,
619 "functions_min": 0.0,
620 "functions_max": 2.0,
621 "closures_min": 0.0,
622 "closures_max": 0.0
623 }"###
624 );
625 },
626 );
627 }
628
629 #[test]
630 fn c_single_function() {
631 check_metrics::<CppParser>(
632 "int f(int a, int b) {
633 if (a) {
634 return a;
635 }
636 }",
637 "foo.c",
638 |metric| {
639 insta::assert_json_snapshot!(
641 metric.nargs,
642 @r###"
643 {
644 "total_functions": 2.0,
645 "total_closures": 0.0,
646 "average_functions": 2.0,
647 "average_closures": 0.0,
648 "total": 2.0,
649 "average": 2.0,
650 "functions_min": 0.0,
651 "functions_max": 2.0,
652 "closures_min": 0.0,
653 "closures_max": 0.0
654 }"###
655 );
656 },
657 );
658 }
659
660 #[test]
661 fn javascript_single_function() {
662 check_metrics::<JavascriptParser>(
663 "function f(a, b) {
664 return a * b;
665 }",
666 "foo.js",
667 |metric| {
668 insta::assert_json_snapshot!(
670 metric.nargs,
671 @r###"
672 {
673 "total_functions": 2.0,
674 "total_closures": 0.0,
675 "average_functions": 2.0,
676 "average_closures": 0.0,
677 "total": 2.0,
678 "average": 2.0,
679 "functions_min": 0.0,
680 "functions_max": 2.0,
681 "closures_min": 0.0,
682 "closures_max": 0.0
683 }"###
684 );
685 },
686 );
687 }
688
689 #[test]
690 fn python_single_lambda() {
691 check_metrics::<PythonParser>("bar = lambda a: True", "foo.py", |metric| {
692 insta::assert_json_snapshot!(
694 metric.nargs,
695 @r###"
696 {
697 "total_functions": 0.0,
698 "total_closures": 1.0,
699 "average_functions": 0.0,
700 "average_closures": 1.0,
701 "total": 1.0,
702 "average": 1.0,
703 "functions_min": 0.0,
704 "functions_max": 0.0,
705 "closures_min": 1.0,
706 "closures_max": 1.0
707 }"###
708 );
709 });
710 }
711
712 #[test]
713 fn rust_single_closure() {
714 check_metrics::<RustParser>("let bar = |i: i32| -> i32 { i + 1 };", "foo.rs", |metric| {
715 insta::assert_json_snapshot!(
717 metric.nargs,
718 @r###"
719 {
720 "total_functions": 0.0,
721 "total_closures": 1.0,
722 "average_functions": 0.0,
723 "average_closures": 1.0,
724 "total": 1.0,
725 "average": 1.0,
726 "functions_min": 0.0,
727 "functions_max": 0.0,
728 "closures_min": 0.0,
729 "closures_max": 1.0
730 }"###
731 );
732 });
733 }
734
735 #[test]
736 fn cpp_single_lambda() {
737 check_metrics::<CppParser>(
738 "auto bar = [](int x, int y) -> int { return x + y; };",
739 "foo.cpp",
740 |metric| {
741 insta::assert_json_snapshot!(
743 metric.nargs,
744 @r###"
745 {
746 "total_functions": 0.0,
747 "total_closures": 2.0,
748 "average_functions": 0.0,
749 "average_closures": 2.0,
750 "total": 2.0,
751 "average": 2.0,
752 "functions_min": 0.0,
753 "functions_max": 0.0,
754 "closures_min": 2.0,
755 "closures_max": 2.0
756 }"###
757 );
758 },
759 );
760 }
761
762 #[test]
763 fn javascript_single_closure() {
764 check_metrics::<JavascriptParser>("function (a, b) {return a + b};", "foo.js", |metric| {
765 insta::assert_json_snapshot!(
767 metric.nargs,
768 @r###"
769 {
770 "total_functions": 0.0,
771 "total_closures": 2.0,
772 "average_functions": 0.0,
773 "average_closures": 2.0,
774 "total": 2.0,
775 "average": 2.0,
776 "functions_min": 0.0,
777 "functions_max": 0.0,
778 "closures_min": 0.0,
779 "closures_max": 2.0
780 }"###
781 );
782 });
783 }
784
785 #[test]
786 fn python_functions() {
787 check_metrics::<PythonParser>(
788 "def f(a, b):
789 if a:
790 return a
791 def f(a, b):
792 if b:
793 return b",
794 "foo.py",
795 |metric| {
796 insta::assert_json_snapshot!(
798 metric.nargs,
799 @r###"
800 {
801 "total_functions": 4.0,
802 "total_closures": 0.0,
803 "average_functions": 2.0,
804 "average_closures": 0.0,
805 "total": 4.0,
806 "average": 2.0,
807 "functions_min": 0.0,
808 "functions_max": 2.0,
809 "closures_min": 0.0,
810 "closures_max": 0.0
811 }"###
812 );
813 },
814 );
815
816 check_metrics::<PythonParser>(
817 "def f(a, b):
818 if a:
819 return a
820 def f(a, b, c):
821 if b:
822 return b",
823 "foo.py",
824 |metric| {
825 insta::assert_json_snapshot!(
827 metric.nargs,
828 @r###"
829 {
830 "total_functions": 5.0,
831 "total_closures": 0.0,
832 "average_functions": 2.5,
833 "average_closures": 0.0,
834 "total": 5.0,
835 "average": 2.5,
836 "functions_min": 0.0,
837 "functions_max": 3.0,
838 "closures_min": 0.0,
839 "closures_max": 0.0
840 }"###
841 );
842 },
843 );
844 }
845
846 #[test]
847 fn rust_functions() {
848 check_metrics::<RustParser>(
849 "fn f(a: bool, b: usize) {
850 if a {
851 return a;
852 }
853 }
854 fn f1(a: bool, b: usize) {
855 if a {
856 return a;
857 }
858 }",
859 "foo.rs",
860 |metric| {
861 insta::assert_json_snapshot!(
863 metric.nargs,
864 @r###"
865 {
866 "total_functions": 4.0,
867 "total_closures": 0.0,
868 "average_functions": 2.0,
869 "average_closures": 0.0,
870 "total": 4.0,
871 "average": 2.0,
872 "functions_min": 0.0,
873 "functions_max": 2.0,
874 "closures_min": 0.0,
875 "closures_max": 0.0
876 }"###
877 );
878 },
879 );
880
881 check_metrics::<RustParser>(
882 "fn f(a: bool, b: usize) {
883 if a {
884 return a;
885 }
886 }
887 fn f1(a: bool, b: usize, c: usize) {
888 if a {
889 return a;
890 }
891 }",
892 "foo.rs",
893 |metric| {
894 insta::assert_json_snapshot!(
896 metric.nargs,
897 @r###"
898 {
899 "total_functions": 5.0,
900 "total_closures": 0.0,
901 "average_functions": 2.5,
902 "average_closures": 0.0,
903 "total": 5.0,
904 "average": 2.5,
905 "functions_min": 0.0,
906 "functions_max": 3.0,
907 "closures_min": 0.0,
908 "closures_max": 0.0
909 }"###
910 );
911 },
912 );
913 }
914
915 #[test]
916 fn c_functions() {
917 check_metrics::<CppParser>(
918 "int f(int a, int b) {
919 if (a) {
920 return a;
921 }
922 }
923 int f1(int a, int b) {
924 if (a) {
925 return a;
926 }
927 }",
928 "foo.c",
929 |metric| {
930 insta::assert_json_snapshot!(
932 metric.nargs,
933 @r###"
934 {
935 "total_functions": 4.0,
936 "total_closures": 0.0,
937 "average_functions": 2.0,
938 "average_closures": 0.0,
939 "total": 4.0,
940 "average": 2.0,
941 "functions_min": 0.0,
942 "functions_max": 2.0,
943 "closures_min": 0.0,
944 "closures_max": 0.0
945 }"###
946 );
947 },
948 );
949
950 check_metrics::<CppParser>(
951 "int f(int a, int b) {
952 if (a) {
953 return a;
954 }
955 }
956 int f1(int a, int b, int c) {
957 if (a) {
958 return a;
959 }
960 }",
961 "foo.c",
962 |metric| {
963 insta::assert_json_snapshot!(
965 metric.nargs,
966 @r###"
967 {
968 "total_functions": 5.0,
969 "total_closures": 0.0,
970 "average_functions": 2.5,
971 "average_closures": 0.0,
972 "total": 5.0,
973 "average": 2.5,
974 "functions_min": 0.0,
975 "functions_max": 3.0,
976 "closures_min": 0.0,
977 "closures_max": 0.0
978 }"###
979 );
980 },
981 );
982 }
983
984 #[test]
985 fn javascript_functions() {
986 check_metrics::<JavascriptParser>(
987 "function f(a, b) {
988 return a * b;
989 }
990 function f1(a, b) {
991 return a * b;
992 }",
993 "foo.js",
994 |metric| {
995 insta::assert_json_snapshot!(
997 metric.nargs,
998 @r###"
999 {
1000 "total_functions": 4.0,
1001 "total_closures": 0.0,
1002 "average_functions": 2.0,
1003 "average_closures": 0.0,
1004 "total": 4.0,
1005 "average": 2.0,
1006 "functions_min": 0.0,
1007 "functions_max": 2.0,
1008 "closures_min": 0.0,
1009 "closures_max": 0.0
1010 }"###
1011 );
1012 },
1013 );
1014
1015 check_metrics::<JavascriptParser>(
1016 "function f(a, b) {
1017 return a * b;
1018 }
1019 function f1(a, b, c) {
1020 return a * b;
1021 }",
1022 "foo.js",
1023 |metric| {
1024 insta::assert_json_snapshot!(
1026 metric.nargs,
1027 @r###"
1028 {
1029 "total_functions": 5.0,
1030 "total_closures": 0.0,
1031 "average_functions": 2.5,
1032 "average_closures": 0.0,
1033 "total": 5.0,
1034 "average": 2.5,
1035 "functions_min": 0.0,
1036 "functions_max": 3.0,
1037 "closures_min": 0.0,
1038 "closures_max": 0.0
1039 }"###
1040 );
1041 },
1042 );
1043 }
1044
1045 #[test]
1046 fn python_nested_functions() {
1047 check_metrics::<PythonParser>(
1048 "def f(a, b):
1049 def foo(a):
1050 if a:
1051 return 1
1052 bar = lambda a: lambda b: b or True or True
1053 return bar(foo(a))(a)",
1054 "foo.py",
1055 |metric| {
1056 insta::assert_json_snapshot!(
1058 metric.nargs,
1059 @r###"
1060 {
1061 "total_functions": 3.0,
1062 "total_closures": 2.0,
1063 "average_functions": 1.5,
1064 "average_closures": 1.0,
1065 "total": 5.0,
1066 "average": 1.25,
1067 "functions_min": 0.0,
1068 "functions_max": 2.0,
1069 "closures_min": 0.0,
1070 "closures_max": 2.0
1071 }"###
1072 );
1073 },
1074 );
1075 }
1076
1077 #[test]
1078 fn rust_nested_functions() {
1079 check_metrics::<RustParser>(
1080 "fn f(a: i32, b: i32) -> i32 {
1081 fn foo(a: i32) -> i32 {
1082 return a;
1083 }
1084 let bar = |a: i32, b: i32| -> i32 { a + 1 };
1085 let bar1 = |b: i32| -> i32 { b + 1 };
1086 return bar(foo(a), a);
1087 }",
1088 "foo.rs",
1089 |metric| {
1090 insta::assert_json_snapshot!(
1092 metric.nargs,
1093 @r###"
1094 {
1095 "total_functions": 3.0,
1096 "total_closures": 3.0,
1097 "average_functions": 1.5,
1098 "average_closures": 1.5,
1099 "total": 6.0,
1100 "average": 1.5,
1101 "functions_min": 0.0,
1102 "functions_max": 2.0,
1103 "closures_min": 0.0,
1104 "closures_max": 2.0
1105 }"###
1106 );
1107 },
1108 );
1109 }
1110
1111 #[test]
1112 fn cpp_nested_functions() {
1113 check_metrics::<CppParser>(
1114 "int f(int a, int b, int c) {
1115 auto foo = [](int x) -> int { return x; };
1116 auto bar = [](int x, int y) -> int { return x + y; };
1117 return bar(foo(a), a);
1118 }",
1119 "foo.cpp",
1120 |metric| {
1121 insta::assert_json_snapshot!(
1123 metric.nargs,
1124 @r###"
1125 {
1126 "total_functions": 3.0,
1127 "total_closures": 3.0,
1128 "average_functions": 3.0,
1129 "average_closures": 1.5,
1130 "total": 6.0,
1131 "average": 2.0,
1132 "functions_min": 0.0,
1133 "functions_max": 3.0,
1134 "closures_min": 0.0,
1135 "closures_max": 3.0
1136 }"###
1137 );
1138 },
1139 );
1140 }
1141
1142 #[test]
1146 fn cpp_default_arguments() {
1147 check_metrics::<CppParser>(
1148 "int f(int a, int b, int c = 0) {
1149 return a + b + c;
1150 }",
1151 "foo.cpp",
1152 |metric| {
1153 let s = &metric.nargs;
1155 assert_eq!(s.fn_args_sum(), 3.0);
1156 assert_eq!(s.fn_args_max(), 3.0);
1157 insta::assert_json_snapshot!(
1158 metric.nargs,
1159 @r###"
1160 {
1161 "total_functions": 3.0,
1162 "total_closures": 0.0,
1163 "average_functions": 3.0,
1164 "average_closures": 0.0,
1165 "total": 3.0,
1166 "average": 3.0,
1167 "functions_min": 0.0,
1168 "functions_max": 3.0,
1169 "closures_min": 0.0,
1170 "closures_max": 0.0
1171 }"###
1172 );
1173 },
1174 );
1175 }
1176
1177 #[test]
1182 fn c_variadic_function() {
1183 check_metrics::<CppParser>(
1184 "int printf(const char* fmt, ...) {
1185 return 0;
1186 }",
1187 "foo.c",
1188 |metric| {
1189 let s = &metric.nargs;
1191 assert_eq!(s.fn_args_sum(), 2.0);
1192 assert_eq!(s.fn_args_max(), 2.0);
1193 insta::assert_json_snapshot!(
1194 metric.nargs,
1195 @r###"
1196 {
1197 "total_functions": 2.0,
1198 "total_closures": 0.0,
1199 "average_functions": 2.0,
1200 "average_closures": 0.0,
1201 "total": 2.0,
1202 "average": 2.0,
1203 "functions_min": 0.0,
1204 "functions_max": 2.0,
1205 "closures_min": 0.0,
1206 "closures_max": 0.0
1207 }"###
1208 );
1209 },
1210 );
1211 }
1212
1213 #[test]
1220 fn cpp_template_parameter_pack() {
1221 check_metrics::<CppParser>(
1222 "template<typename... Args>
1223 int sum(int seed, Args... args) {
1224 return seed;
1225 }",
1226 "foo.cpp",
1227 |metric| {
1228 let s = &metric.nargs;
1230 assert_eq!(s.fn_args_sum(), 2.0);
1231 assert_eq!(s.fn_args_max(), 2.0);
1232 insta::assert_json_snapshot!(
1233 metric.nargs,
1234 @r###"
1235 {
1236 "total_functions": 2.0,
1237 "total_closures": 0.0,
1238 "average_functions": 2.0,
1239 "average_closures": 0.0,
1240 "total": 2.0,
1241 "average": 2.0,
1242 "functions_min": 0.0,
1243 "functions_max": 2.0,
1244 "closures_min": 0.0,
1245 "closures_max": 0.0
1246 }"###
1247 );
1248 },
1249 );
1250 }
1251
1252 #[test]
1257 fn cpp_lambda_capture_not_counted() {
1258 check_metrics::<CppParser>(
1259 "int f() {
1260 int x = 1;
1261 int y = 2;
1262 auto g = [=, &x](int a, int b) -> int { return a + b + x + y; };
1263 return g(1, 2);
1264 }",
1265 "foo.cpp",
1266 |metric| {
1267 let s = &metric.nargs;
1269 assert_eq!(s.fn_args_sum(), 0.0);
1270 assert_eq!(s.closure_args_sum(), 2.0);
1271 assert_eq!(s.closure_args_max(), 2.0);
1272 insta::assert_json_snapshot!(
1273 metric.nargs,
1274 @r###"
1275 {
1276 "total_functions": 0.0,
1277 "total_closures": 2.0,
1278 "average_functions": 0.0,
1279 "average_closures": 2.0,
1280 "total": 2.0,
1281 "average": 1.0,
1282 "functions_min": 0.0,
1283 "functions_max": 0.0,
1284 "closures_min": 0.0,
1285 "closures_max": 2.0
1286 }"###
1287 );
1288 },
1289 );
1290 }
1291
1292 #[test]
1297 fn cpp_member_function_this_not_counted() {
1298 check_metrics::<CppParser>(
1299 "struct S {
1300 int x;
1301 int set(int a) { // implicit `this` is NOT counted
1302 this->x = a;
1303 return a;
1304 }
1305 };",
1306 "foo.cpp",
1307 |metric| {
1308 let s = &metric.nargs;
1310 assert_eq!(s.fn_args_sum(), 1.0);
1311 assert_eq!(s.fn_args_max(), 1.0);
1312 insta::assert_json_snapshot!(
1313 metric.nargs,
1314 @r###"
1315 {
1316 "total_functions": 1.0,
1317 "total_closures": 0.0,
1318 "average_functions": 1.0,
1319 "average_closures": 0.0,
1320 "total": 1.0,
1321 "average": 1.0,
1322 "functions_min": 0.0,
1323 "functions_max": 1.0,
1324 "closures_min": 0.0,
1325 "closures_max": 0.0
1326 }"###
1327 );
1328 },
1329 );
1330 }
1331
1332 #[test]
1333 fn go_zero_args() {
1334 check_metrics::<GoParser>(
1335 "package main
1336 func f() {}",
1337 "foo.go",
1338 |metric| {
1339 insta::assert_json_snapshot!(
1340 metric.nargs,
1341 @r###"
1342 {
1343 "total_functions": 0.0,
1344 "total_closures": 0.0,
1345 "average_functions": 0.0,
1346 "average_closures": 0.0,
1347 "total": 0.0,
1348 "average": 0.0,
1349 "functions_min": 0.0,
1350 "functions_max": 0.0,
1351 "closures_min": 0.0,
1352 "closures_max": 0.0
1353 }"###
1354 );
1355 },
1356 );
1357 }
1358
1359 #[test]
1360 fn go_multiple_args() {
1361 check_metrics::<GoParser>(
1362 "package main
1363 func f(a int, b string, c bool) {}",
1364 "foo.go",
1365 |metric| {
1366 insta::assert_json_snapshot!(
1367 metric.nargs,
1368 @r###"
1369 {
1370 "total_functions": 3.0,
1371 "total_closures": 0.0,
1372 "average_functions": 3.0,
1373 "average_closures": 0.0,
1374 "total": 3.0,
1375 "average": 3.0,
1376 "functions_min": 0.0,
1377 "functions_max": 3.0,
1378 "closures_min": 0.0,
1379 "closures_max": 0.0
1380 }"###
1381 );
1382 },
1383 );
1384 }
1385
1386 #[test]
1387 fn go_method_excludes_receiver() {
1388 check_metrics::<GoParser>(
1389 "package main
1390 type T struct{}
1391 func (t *T) Greet(name string) string {
1392 return name
1393 }",
1394 "foo.go",
1395 |metric| {
1396 insta::assert_json_snapshot!(
1398 metric.nargs,
1399 @r###"
1400 {
1401 "total_functions": 1.0,
1402 "total_closures": 0.0,
1403 "average_functions": 1.0,
1404 "average_closures": 0.0,
1405 "total": 1.0,
1406 "average": 1.0,
1407 "functions_min": 0.0,
1408 "functions_max": 1.0,
1409 "closures_min": 0.0,
1410 "closures_max": 0.0
1411 }"###
1412 );
1413 },
1414 );
1415 }
1416
1417 #[test]
1418 fn go_variadic() {
1419 check_metrics::<GoParser>(
1420 "package main
1421 func f(args ...int) {}",
1422 "foo.go",
1423 |metric| {
1424 insta::assert_json_snapshot!(
1425 metric.nargs,
1426 @r###"
1427 {
1428 "total_functions": 1.0,
1429 "total_closures": 0.0,
1430 "average_functions": 1.0,
1431 "average_closures": 0.0,
1432 "total": 1.0,
1433 "average": 1.0,
1434 "functions_min": 0.0,
1435 "functions_max": 1.0,
1436 "closures_min": 0.0,
1437 "closures_max": 0.0
1438 }"###
1439 );
1440 },
1441 );
1442 }
1443
1444 #[test]
1445 fn go_grouped_params() {
1446 check_metrics::<GoParser>(
1447 "package main
1448 func f(a, b int, c string) {}",
1449 "foo.go",
1450 |metric| {
1451 insta::assert_json_snapshot!(
1454 metric.nargs,
1455 @r###"
1456 {
1457 "total_functions": 3.0,
1458 "total_closures": 0.0,
1459 "average_functions": 3.0,
1460 "average_closures": 0.0,
1461 "total": 3.0,
1462 "average": 3.0,
1463 "functions_min": 0.0,
1464 "functions_max": 3.0,
1465 "closures_min": 0.0,
1466 "closures_max": 0.0
1467 }"###
1468 );
1469 },
1470 );
1471 }
1472
1473 #[test]
1474 fn go_func_literal_args() {
1475 check_metrics::<GoParser>(
1476 "package main
1477 var f = func(x, y int) int { return x + y }",
1478 "foo.go",
1479 |metric| {
1480 insta::assert_json_snapshot!(
1482 metric.nargs,
1483 @r###"
1484 {
1485 "total_functions": 0.0,
1486 "total_closures": 2.0,
1487 "average_functions": 0.0,
1488 "average_closures": 2.0,
1489 "total": 2.0,
1490 "average": 2.0,
1491 "functions_min": 0.0,
1492 "functions_max": 0.0,
1493 "closures_min": 0.0,
1494 "closures_max": 2.0
1495 }"###
1496 );
1497 },
1498 );
1499 }
1500
1501 #[test]
1502 fn javascript_nested_functions() {
1503 check_metrics::<JavascriptParser>(
1504 "function f(a, b) {
1505 function foo(a, c) {
1506 return a;
1507 }
1508 var bar = function (a, b) {return a + b};
1509 function (a) {return a};
1510 return bar(foo(a), a);
1511 }",
1512 "foo.js",
1513 |metric| {
1514 insta::assert_json_snapshot!(
1516 metric.nargs,
1517 @r###"
1518 {
1519 "total_functions": 6.0,
1520 "total_closures": 1.0,
1521 "average_functions": 2.0,
1522 "average_closures": 1.0,
1523 "total": 7.0,
1524 "average": 1.75,
1525 "functions_min": 0.0,
1526 "functions_max": 2.0,
1527 "closures_min": 0.0,
1528 "closures_max": 1.0
1529 }"###
1530 );
1531 },
1532 );
1533 }
1534
1535 #[test]
1536 fn perl_no_functions_and_closures() {
1537 check_metrics::<PerlParser>(
1538 "my $x = 1;
1539 print $x;",
1540 "foo.pl",
1541 |metric| {
1542 assert_eq!(metric.nom.functions_sum(), 0.0);
1547 assert_eq!(metric.nom.closures_sum(), 0.0);
1548 insta::assert_json_snapshot!(
1549 metric.nargs,
1550 @r#"
1551 {
1552 "total_functions": 0.0,
1553 "total_closures": 0.0,
1554 "average_functions": 0.0,
1555 "average_closures": 0.0,
1556 "total": 0.0,
1557 "average": 0.0,
1558 "functions_min": 0.0,
1559 "functions_max": 0.0,
1560 "closures_min": 0.0,
1561 "closures_max": 0.0
1562 }
1563 "#
1564 );
1565 },
1566 );
1567 }
1568
1569 #[test]
1570 fn perl_single_function() {
1571 check_metrics::<PerlParser>(
1576 "sub greet {
1577 my ($name) = @_;
1578 print \"hi $name\";
1579 }",
1580 "foo.pl",
1581 |metric| {
1582 assert_eq!(metric.nom.functions_sum(), 1.0);
1583 assert_eq!(metric.nom.closures_sum(), 0.0);
1584 insta::assert_json_snapshot!(
1585 metric.nargs,
1586 @r#"
1587 {
1588 "total_functions": 0.0,
1589 "total_closures": 0.0,
1590 "average_functions": 0.0,
1591 "average_closures": 0.0,
1592 "total": 0.0,
1593 "average": 0.0,
1594 "functions_min": 0.0,
1595 "functions_max": 0.0,
1596 "closures_min": 0.0,
1597 "closures_max": 0.0
1598 }
1599 "#
1600 );
1601 },
1602 );
1603 }
1604
1605 #[test]
1606 fn perl_single_closure() {
1607 check_metrics::<PerlParser>(
1611 "my $f = sub {
1612 my ($x) = @_;
1613 return $x + 1;
1614 };",
1615 "foo.pl",
1616 |metric| {
1617 assert_eq!(metric.nom.functions_sum(), 0.0);
1618 assert_eq!(metric.nom.closures_sum(), 1.0);
1619 insta::assert_json_snapshot!(
1620 metric.nargs,
1621 @r#"
1622 {
1623 "total_functions": 0.0,
1624 "total_closures": 0.0,
1625 "average_functions": 0.0,
1626 "average_closures": 0.0,
1627 "total": 0.0,
1628 "average": 0.0,
1629 "functions_min": 0.0,
1630 "functions_max": 0.0,
1631 "closures_min": 0.0,
1632 "closures_max": 0.0
1633 }
1634 "#
1635 );
1636 },
1637 );
1638 }
1639
1640 #[test]
1641 fn perl_multiple_functions() {
1642 check_metrics::<PerlParser>(
1645 "sub a { return 1; }
1646 sub b {
1647 my ($x, $y) = @_;
1648 return $x + $y;
1649 }",
1650 "foo.pl",
1651 |metric| {
1652 assert_eq!(metric.nom.functions_sum(), 2.0);
1653 assert_eq!(metric.nom.closures_sum(), 0.0);
1654 insta::assert_json_snapshot!(
1655 metric.nargs,
1656 @r#"
1657 {
1658 "total_functions": 0.0,
1659 "total_closures": 0.0,
1660 "average_functions": 0.0,
1661 "average_closures": 0.0,
1662 "total": 0.0,
1663 "average": 0.0,
1664 "functions_min": 0.0,
1665 "functions_max": 0.0,
1666 "closures_min": 0.0,
1667 "closures_max": 0.0
1668 }
1669 "#
1670 );
1671 },
1672 );
1673 }
1674
1675 #[test]
1676 fn perl_nested_closure() {
1677 check_metrics::<PerlParser>(
1680 "sub outer {
1681 my $inner = sub { return 42; };
1682 return $inner->();
1683 }",
1684 "foo.pl",
1685 |metric| {
1686 assert_eq!(metric.nom.functions_sum(), 1.0);
1687 assert_eq!(metric.nom.closures_sum(), 1.0);
1688 insta::assert_json_snapshot!(
1689 metric.nargs,
1690 @r#"
1691 {
1692 "total_functions": 0.0,
1693 "total_closures": 0.0,
1694 "average_functions": 0.0,
1695 "average_closures": 0.0,
1696 "total": 0.0,
1697 "average": 0.0,
1698 "functions_min": 0.0,
1699 "functions_max": 0.0,
1700 "closures_min": 0.0,
1701 "closures_max": 0.0
1702 }
1703 "#
1704 );
1705 },
1706 );
1707 }
1708
1709 #[test]
1710 fn java_no_functions() {
1711 check_metrics::<JavaParser>(
1712 "class Foo {
1713 int x = 42;
1714 String name = \"hello\";
1715 }",
1716 "foo.java",
1717 |metric| {
1718 insta::assert_json_snapshot!(
1719 metric.nargs,
1720 @r#"
1721 {
1722 "total_functions": 0.0,
1723 "total_closures": 0.0,
1724 "average_functions": 0.0,
1725 "average_closures": 0.0,
1726 "total": 0.0,
1727 "average": 0.0,
1728 "functions_min": 0.0,
1729 "functions_max": 0.0,
1730 "closures_min": 0.0,
1731 "closures_max": 0.0
1732 }
1733 "#
1734 );
1735 },
1736 );
1737 }
1738
1739 #[test]
1740 fn java_single_method() {
1741 check_metrics::<JavaParser>(
1742 "class Foo {
1743 void greet(String name, int count) {
1744 return;
1745 }
1746 }",
1747 "foo.java",
1748 |metric| {
1749 insta::assert_json_snapshot!(
1750 metric.nargs,
1751 @r#"
1752 {
1753 "total_functions": 2.0,
1754 "total_closures": 0.0,
1755 "average_functions": 2.0,
1756 "average_closures": 0.0,
1757 "total": 2.0,
1758 "average": 2.0,
1759 "functions_min": 0.0,
1760 "functions_max": 2.0,
1761 "closures_min": 0.0,
1762 "closures_max": 0.0
1763 }
1764 "#
1765 );
1766 },
1767 );
1768 }
1769
1770 #[test]
1771 fn java_multiple_methods() {
1772 check_metrics::<JavaParser>(
1773 "class Foo {
1774 void a(int x) {
1775 return;
1776 }
1777 void b(int x, int y, int z) {
1778 return;
1779 }
1780 }",
1781 "foo.java",
1782 |metric| {
1783 insta::assert_json_snapshot!(
1784 metric.nargs,
1785 @r#"
1786 {
1787 "total_functions": 4.0,
1788 "total_closures": 0.0,
1789 "average_functions": 2.0,
1790 "average_closures": 0.0,
1791 "total": 4.0,
1792 "average": 2.0,
1793 "functions_min": 0.0,
1794 "functions_max": 3.0,
1795 "closures_min": 0.0,
1796 "closures_max": 0.0
1797 }
1798 "#
1799 );
1800 },
1801 );
1802 }
1803
1804 #[test]
1805 fn java_constructor_args() {
1806 check_metrics::<JavaParser>(
1807 "class Foo {
1808 Foo(String name, int age) {
1809 return;
1810 }
1811 }",
1812 "foo.java",
1813 |metric| {
1814 insta::assert_json_snapshot!(
1815 metric.nargs,
1816 @r#"
1817 {
1818 "total_functions": 2.0,
1819 "total_closures": 0.0,
1820 "average_functions": 2.0,
1821 "average_closures": 0.0,
1822 "total": 2.0,
1823 "average": 2.0,
1824 "functions_min": 0.0,
1825 "functions_max": 2.0,
1826 "closures_min": 0.0,
1827 "closures_max": 0.0
1828 }
1829 "#
1830 );
1831 },
1832 );
1833 }
1834
1835 #[test]
1836 fn java_lambda_args() {
1837 check_metrics::<JavaParser>(
1838 "class Foo {
1839 void run() {
1840 Runnable r = (int a, int b) -> a + b;
1841 }
1842 }",
1843 "foo.java",
1844 |metric| {
1845 insta::assert_json_snapshot!(
1846 metric.nargs,
1847 @r#"
1848 {
1849 "total_functions": 0.0,
1850 "total_closures": 2.0,
1851 "average_functions": 0.0,
1852 "average_closures": 2.0,
1853 "total": 2.0,
1854 "average": 1.0,
1855 "functions_min": 0.0,
1856 "functions_max": 0.0,
1857 "closures_min": 0.0,
1858 "closures_max": 2.0
1859 }
1860 "#
1861 );
1862 },
1863 );
1864 }
1865
1866 #[test]
1867 fn groovy_no_functions_and_closures() {
1868 check_metrics::<GroovyParser>("int x = 1", "foo.groovy", |metric| {
1869 assert_eq!(metric.nargs.nargs_total(), 0.0);
1870 });
1871 }
1872
1873 #[test]
1874 fn groovy_single_method() {
1875 check_metrics::<GroovyParser>(
1876 "class A {
1877 void greet(String name, int times) {
1878 println(name)
1879 }
1880 }",
1881 "foo.groovy",
1882 |metric| {
1883 assert_eq!(metric.nargs.fn_args_sum(), 2.0);
1884 assert_eq!(metric.nargs.closure_args_sum(), 0.0);
1885 },
1886 );
1887 }
1888
1889 #[test]
1890 fn groovy_multiple_methods() {
1891 check_metrics::<GroovyParser>(
1892 "class A {
1893 int add(int x, int y) { x + y }
1894 int sub(int x, int y, int z) { x - y - z }
1895 }",
1896 "foo.groovy",
1897 |metric| {
1898 assert_eq!(metric.nargs.fn_args_sum(), 5.0);
1899 },
1900 );
1901 }
1902
1903 #[test]
1904 fn groovy_lambda_args() {
1905 check_metrics::<GroovyParser>(
1911 "class Foo {
1912 void run() {
1913 def f = { int a, int b -> a + b }
1914 }
1915 }",
1916 "foo.groovy",
1917 |metric| {
1918 assert_eq!(metric.nargs.closure_args_sum(), 2.0);
1919 },
1920 );
1921 }
1922
1923 #[test]
1924 fn groovy_implicit_it_not_counted() {
1925 check_metrics::<GroovyParser>(
1929 "class A {
1930 void apply() {
1931 [1, 2, 3].each { println(it) }
1932 }
1933 }",
1934 "foo.groovy",
1935 |metric| {
1936 assert_eq!(metric.nargs.closure_args_sum(), 0.0);
1937 },
1938 );
1939 }
1940
1941 #[test]
1942 fn csharp_no_functions() {
1943 check_metrics::<CsharpParser>(
1944 "class Foo {
1945 int x = 42;
1946 string Name = \"hello\";
1947 }",
1948 "foo.cs",
1949 |metric| {
1950 insta::assert_json_snapshot!(
1951 metric.nargs,
1952 @r#"
1953 {
1954 "total_functions": 0.0,
1955 "total_closures": 0.0,
1956 "average_functions": 0.0,
1957 "average_closures": 0.0,
1958 "total": 0.0,
1959 "average": 0.0,
1960 "functions_min": 0.0,
1961 "functions_max": 0.0,
1962 "closures_min": 0.0,
1963 "closures_max": 0.0
1964 }
1965 "#
1966 );
1967 },
1968 );
1969 }
1970
1971 #[test]
1972 fn csharp_single_method() {
1973 check_metrics::<CsharpParser>(
1974 "class Foo {
1975 void Greet(string name, int count) {
1976 return;
1977 }
1978 }",
1979 "foo.cs",
1980 |metric| {
1981 insta::assert_json_snapshot!(
1982 metric.nargs,
1983 @r#"
1984 {
1985 "total_functions": 2.0,
1986 "total_closures": 0.0,
1987 "average_functions": 2.0,
1988 "average_closures": 0.0,
1989 "total": 2.0,
1990 "average": 2.0,
1991 "functions_min": 0.0,
1992 "functions_max": 2.0,
1993 "closures_min": 0.0,
1994 "closures_max": 0.0
1995 }
1996 "#
1997 );
1998 },
1999 );
2000 }
2001
2002 #[test]
2003 fn csharp_multiple_methods() {
2004 check_metrics::<CsharpParser>(
2005 "class Foo {
2006 void A(int x) {
2007 return;
2008 }
2009 void B(int x, int y, int z) {
2010 return;
2011 }
2012 }",
2013 "foo.cs",
2014 |metric| {
2015 insta::assert_json_snapshot!(
2016 metric.nargs,
2017 @r#"
2018 {
2019 "total_functions": 4.0,
2020 "total_closures": 0.0,
2021 "average_functions": 2.0,
2022 "average_closures": 0.0,
2023 "total": 4.0,
2024 "average": 2.0,
2025 "functions_min": 0.0,
2026 "functions_max": 3.0,
2027 "closures_min": 0.0,
2028 "closures_max": 0.0
2029 }
2030 "#
2031 );
2032 },
2033 );
2034 }
2035
2036 #[test]
2037 fn csharp_constructor_args() {
2038 check_metrics::<CsharpParser>(
2039 "class Foo {
2040 public Foo(string name, int age) {
2041 return;
2042 }
2043 }",
2044 "foo.cs",
2045 |metric| {
2046 insta::assert_json_snapshot!(
2047 metric.nargs,
2048 @r#"
2049 {
2050 "total_functions": 2.0,
2051 "total_closures": 0.0,
2052 "average_functions": 2.0,
2053 "average_closures": 0.0,
2054 "total": 2.0,
2055 "average": 2.0,
2056 "functions_min": 0.0,
2057 "functions_max": 2.0,
2058 "closures_min": 0.0,
2059 "closures_max": 0.0
2060 }
2061 "#
2062 );
2063 },
2064 );
2065 }
2066
2067 #[test]
2068 fn csharp_lambda_args() {
2069 check_metrics::<CsharpParser>(
2070 "class Foo {
2071 void Run() {
2072 System.Func<int, int, int> f = (int a, int b) => a + b;
2073 }
2074 }",
2075 "foo.cs",
2076 |metric| {
2077 insta::assert_json_snapshot!(
2078 metric.nargs,
2079 @r#"
2080 {
2081 "total_functions": 0.0,
2082 "total_closures": 2.0,
2083 "average_functions": 0.0,
2084 "average_closures": 2.0,
2085 "total": 2.0,
2086 "average": 1.0,
2087 "functions_min": 0.0,
2088 "functions_max": 0.0,
2089 "closures_min": 0.0,
2090 "closures_max": 2.0
2091 }
2092 "#
2093 );
2094 },
2095 );
2096 }
2097
2098 #[test]
2099 fn tsx_function_and_arrow() {
2100 check_metrics::<TsxParser>(
2101 "function add(a: number, b: number): number {
2102 return a + b;
2103 }
2104 const multiply = (x: number, y: number) => x * y;",
2105 "foo.tsx",
2106 |metric| {
2107 insta::assert_json_snapshot!(
2108 metric.nargs,
2109 @r###"
2110 {
2111 "total_functions": 4.0,
2112 "total_closures": 0.0,
2113 "average_functions": 2.0,
2114 "average_closures": 0.0,
2115 "total": 4.0,
2116 "average": 2.0,
2117 "functions_min": 0.0,
2118 "functions_max": 2.0,
2119 "closures_min": 0.0,
2120 "closures_max": 0.0
2121 }"###
2122 );
2123 },
2124 );
2125 }
2126
2127 #[test]
2128 fn typescript_typed_and_optional_params() {
2129 check_metrics::<TypescriptParser>(
2130 "function format(value: number, prefix?: string, suffix?: string): string {
2131 return (prefix ?? '') + value.toString() + (suffix ?? '');
2132 }
2133 const identity = (x: number): number => x;",
2134 "foo.ts",
2135 |metric| {
2136 insta::assert_json_snapshot!(
2137 metric.nargs,
2138 @r###"
2139 {
2140 "total_functions": 4.0,
2141 "total_closures": 0.0,
2142 "average_functions": 2.0,
2143 "average_closures": 0.0,
2144 "total": 4.0,
2145 "average": 2.0,
2146 "functions_min": 0.0,
2147 "functions_max": 3.0,
2148 "closures_min": 0.0,
2149 "closures_max": 0.0
2150 }"###
2151 );
2152 },
2153 );
2154 }
2155
2156 #[test]
2157 fn mozjs_single_function() {
2158 check_metrics::<MozjsParser>(
2159 "function f(a, b) {
2160 return a * b;
2161 }",
2162 "foo.js",
2163 |metric| {
2164 insta::assert_json_snapshot!(
2165 metric.nargs,
2166 @r###"
2167 {
2168 "total_functions": 2.0,
2169 "total_closures": 0.0,
2170 "average_functions": 2.0,
2171 "average_closures": 0.0,
2172 "total": 2.0,
2173 "average": 2.0,
2174 "functions_min": 0.0,
2175 "functions_max": 2.0,
2176 "closures_min": 0.0,
2177 "closures_max": 0.0
2178 }"###
2179 );
2180 },
2181 );
2182 }
2183
2184 #[test]
2185 fn mozjs_closure_args() {
2186 check_metrics::<MozjsParser>("function (a, b) {return a + b};", "foo.js", |metric| {
2187 insta::assert_json_snapshot!(
2188 metric.nargs,
2189 @r###"
2190 {
2191 "total_functions": 0.0,
2192 "total_closures": 2.0,
2193 "average_functions": 0.0,
2194 "average_closures": 2.0,
2195 "total": 2.0,
2196 "average": 2.0,
2197 "functions_min": 0.0,
2198 "functions_max": 0.0,
2199 "closures_min": 0.0,
2200 "closures_max": 2.0
2201 }"###
2202 );
2203 });
2204 }
2205
2206 #[test]
2216 fn javascript_bare_arrow_function() {
2217 check_metrics::<JavascriptParser>("const f = x => x;", "foo.js", |metric| {
2218 assert_eq!(metric.nargs.nargs_total(), 1.0);
2219 });
2220 }
2221
2222 #[test]
2223 fn javascript_async_bare_arrow_function() {
2224 check_metrics::<JavascriptParser>("const f = async x => x;", "foo.js", |metric| {
2225 assert_eq!(metric.nargs.nargs_total(), 1.0);
2226 });
2227 }
2228
2229 #[test]
2230 fn javascript_parenthesized_arrow_function() {
2231 check_metrics::<JavascriptParser>("const f = (x) => x;", "foo.js", |metric| {
2232 assert_eq!(metric.nargs.nargs_total(), 1.0);
2233 });
2234 }
2235
2236 #[test]
2237 fn javascript_multi_parenthesized_arrow_function() {
2238 check_metrics::<JavascriptParser>("const f = (x, y) => x + y;", "foo.js", |metric| {
2239 assert_eq!(metric.nargs.nargs_total(), 2.0);
2240 });
2241 }
2242
2243 #[test]
2244 fn typescript_bare_arrow_function() {
2245 check_metrics::<TypescriptParser>("const f = x => x;", "foo.ts", |metric| {
2246 assert_eq!(metric.nargs.nargs_total(), 1.0);
2247 });
2248 }
2249
2250 #[test]
2251 fn typescript_async_bare_arrow_function() {
2252 check_metrics::<TypescriptParser>("const f = async x => x;", "foo.ts", |metric| {
2253 assert_eq!(metric.nargs.nargs_total(), 1.0);
2254 });
2255 }
2256
2257 #[test]
2258 fn typescript_parenthesized_arrow_function() {
2259 check_metrics::<TypescriptParser>("const f = (x: number) => x;", "foo.ts", |metric| {
2260 assert_eq!(metric.nargs.nargs_total(), 1.0);
2261 });
2262 }
2263
2264 #[test]
2265 fn typescript_multi_parenthesized_arrow_function() {
2266 check_metrics::<TypescriptParser>(
2267 "const f = (x: number, y: number) => x + y;",
2268 "foo.ts",
2269 |metric| {
2270 assert_eq!(metric.nargs.nargs_total(), 2.0);
2271 },
2272 );
2273 }
2274
2275 #[test]
2276 fn tsx_bare_arrow_function() {
2277 check_metrics::<TsxParser>("const f = x => x;", "foo.tsx", |metric| {
2278 assert_eq!(metric.nargs.nargs_total(), 1.0);
2279 });
2280 }
2281
2282 #[test]
2283 fn tsx_async_bare_arrow_function() {
2284 check_metrics::<TsxParser>("const f = async x => x;", "foo.tsx", |metric| {
2285 assert_eq!(metric.nargs.nargs_total(), 1.0);
2286 });
2287 }
2288
2289 #[test]
2290 fn tsx_parenthesized_arrow_function() {
2291 check_metrics::<TsxParser>("const f = (x: number) => x;", "foo.tsx", |metric| {
2292 assert_eq!(metric.nargs.nargs_total(), 1.0);
2293 });
2294 }
2295
2296 #[test]
2297 fn tsx_multi_parenthesized_arrow_function() {
2298 check_metrics::<TsxParser>(
2299 "const f = (x: number, y: number) => x + y;",
2300 "foo.tsx",
2301 |metric| {
2302 assert_eq!(metric.nargs.nargs_total(), 2.0);
2303 },
2304 );
2305 }
2306
2307 #[test]
2308 fn mozjs_bare_arrow_function() {
2309 check_metrics::<MozjsParser>("const f = x => x;", "foo.js", |metric| {
2310 assert_eq!(metric.nargs.nargs_total(), 1.0);
2311 });
2312 }
2313
2314 #[test]
2315 fn mozjs_async_bare_arrow_function() {
2316 check_metrics::<MozjsParser>("const f = async x => x;", "foo.js", |metric| {
2317 assert_eq!(metric.nargs.nargs_total(), 1.0);
2318 });
2319 }
2320
2321 #[test]
2322 fn mozjs_parenthesized_arrow_function() {
2323 check_metrics::<MozjsParser>("const f = (x) => x;", "foo.js", |metric| {
2324 assert_eq!(metric.nargs.nargs_total(), 1.0);
2325 });
2326 }
2327
2328 #[test]
2329 fn mozjs_multi_parenthesized_arrow_function() {
2330 check_metrics::<MozjsParser>("const f = (x, y) => x + y;", "foo.js", |metric| {
2331 assert_eq!(metric.nargs.nargs_total(), 2.0);
2332 });
2333 }
2334
2335 #[test]
2336 fn kotlin_nargs_functions_and_closures() {
2337 check_metrics::<KotlinParser>(
2338 "fun add(a: Int, b: Int): Int {
2339 val transform = { x: Int, y: Int -> x + y }
2340 return transform(a, b)
2341 }",
2342 "foo.kt",
2343 |metric| {
2344 insta::assert_json_snapshot!(
2345 metric.nargs,
2346 @r###"
2347 {
2348 "total_functions": 2.0,
2349 "total_closures": 2.0,
2350 "average_functions": 2.0,
2351 "average_closures": 2.0,
2352 "total": 4.0,
2353 "average": 2.0,
2354 "functions_min": 0.0,
2355 "functions_max": 2.0,
2356 "closures_min": 0.0,
2357 "closures_max": 2.0
2358 }
2359 "###
2360 );
2361 },
2362 );
2363 }
2364
2365 #[test]
2366 fn lua_no_functions_and_closures() {
2367 check_metrics::<LuaParser>("local x = 1", "foo.lua", |metric| {
2368 assert_eq!(metric.nargs.fn_args_sum(), 0.0);
2370 assert_eq!(metric.nargs.closure_args_sum(), 0.0);
2371 insta::assert_json_snapshot!(metric.nargs);
2372 });
2373 }
2374
2375 #[test]
2376 fn lua_single_function() {
2377 check_metrics::<LuaParser>("function f(a, b) return a + b end", "foo.lua", |metric| {
2378 assert_eq!(metric.nargs.fn_args_sum(), 2.0);
2380 assert_eq!(metric.nargs.closure_args_sum(), 0.0);
2381 insta::assert_json_snapshot!(metric.nargs);
2382 });
2383 }
2384
2385 #[test]
2386 fn lua_single_closure() {
2387 check_metrics::<LuaParser>(
2388 "local f = function(a, b) return a + b end",
2389 "foo.lua",
2390 |metric| {
2391 assert_eq!(metric.nargs.fn_args_sum(), 0.0);
2393 assert_eq!(metric.nargs.closure_args_sum(), 2.0);
2394 insta::assert_json_snapshot!(metric.nargs);
2395 },
2396 );
2397 }
2398
2399 #[test]
2400 fn lua_functions() {
2401 check_metrics::<LuaParser>(
2402 "function f(a) return a end
2403function g(x, y, z) return x + y + z end",
2404 "foo.lua",
2405 |metric| {
2406 assert_eq!(metric.nargs.fn_args_sum(), 4.0);
2408 assert_eq!(metric.nargs.closure_args_sum(), 0.0);
2409 insta::assert_json_snapshot!(metric.nargs);
2410 },
2411 );
2412 }
2413
2414 #[test]
2415 fn lua_vararg_function() {
2416 check_metrics::<LuaParser>("function f(a, ...) return a end", "foo.lua", |metric| {
2418 assert_eq!(metric.nargs.fn_args_sum(), 2.0);
2420 assert_eq!(metric.nargs.closure_args_sum(), 0.0);
2421 insta::assert_json_snapshot!(metric.nargs);
2422 });
2423 }
2424
2425 #[test]
2426 fn lua_colon_method_nargs() {
2427 check_metrics::<LuaParser>(
2430 "function obj:method(a, b) return a + b end",
2431 "foo.lua",
2432 |metric| {
2433 assert_eq!(metric.nargs.fn_args_sum(), 2.0);
2435 assert_eq!(metric.nargs.closure_args_sum(), 0.0);
2436 insta::assert_json_snapshot!(metric.nargs);
2437 },
2438 );
2439 }
2440
2441 #[test]
2442 fn tcl_no_functions() {
2443 check_metrics::<TclParser>("set x 1", "foo.tcl", |metric| {
2444 assert_eq!(metric.nargs.fn_args_sum(), 0.0);
2446 assert_eq!(metric.nargs.closure_args_sum(), 0.0);
2447 insta::assert_json_snapshot!(metric.nargs);
2448 });
2449 }
2450
2451 #[test]
2452 fn tcl_single_function() {
2453 check_metrics::<TclParser>("proc f {a b} { puts $a }", "foo.tcl", |metric| {
2454 assert_eq!(metric.nargs.fn_args_sum(), 2.0);
2456 assert_eq!(metric.nargs.closure_args_sum(), 0.0);
2457 insta::assert_json_snapshot!(metric.nargs);
2458 });
2459 }
2460
2461 #[test]
2462 fn tcl_single_function_no_args() {
2463 check_metrics::<TclParser>("proc f {} { puts hello }", "foo.tcl", |metric| {
2464 assert_eq!(metric.nargs.fn_args_sum(), 0.0);
2466 assert_eq!(metric.nargs.closure_args_sum(), 0.0);
2467 insta::assert_json_snapshot!(metric.nargs);
2468 });
2469 }
2470
2471 #[test]
2472 fn tcl_functions() {
2473 check_metrics::<TclParser>(
2474 "proc f {a b} { puts $a }
2475proc g {x y z} { puts $x }",
2476 "foo.tcl",
2477 |metric| {
2478 assert_eq!(metric.nargs.fn_args_sum(), 5.0);
2480 assert_eq!(metric.nargs.closure_args_sum(), 0.0);
2481 insta::assert_json_snapshot!(metric.nargs);
2482 },
2483 );
2484 }
2485
2486 #[test]
2487 fn tcl_nested_functions() {
2488 check_metrics::<TclParser>(
2489 "proc outer {a} {
2490 proc inner {x y} { puts $x }
2491 inner $a $a
2492}",
2493 "foo.tcl",
2494 |metric| {
2495 assert_eq!(metric.nargs.fn_args_sum(), 3.0);
2497 assert_eq!(metric.nargs.closure_args_sum(), 0.0);
2498 insta::assert_json_snapshot!(metric.nargs);
2499 },
2500 );
2501 }
2502
2503 #[test]
2504 fn tcl_args_vararg() {
2505 check_metrics::<TclParser>("proc f {a b args} { puts $a }", "foo.tcl", |metric| {
2507 assert_eq!(metric.nargs.fn_args_sum(), 3.0);
2509 assert_eq!(metric.nargs.closure_args_sum(), 0.0);
2510 insta::assert_json_snapshot!(metric.nargs);
2511 });
2512 }
2513
2514 #[test]
2515 fn tcl_default_arg() {
2516 check_metrics::<TclParser>(
2518 "proc greet {{name World} greeting} {
2519 puts \"$greeting, $name!\"
2520}",
2521 "foo.tcl",
2522 |metric| {
2523 assert_eq!(metric.nargs.fn_args_sum(), 2.0);
2525 assert_eq!(metric.nargs.closure_args_sum(), 0.0);
2526 insta::assert_json_snapshot!(metric.nargs);
2527 },
2528 );
2529 }
2530
2531 #[test]
2532 fn kotlin_zero_args() {
2533 check_metrics::<KotlinParser>("fun f(): Int { return 42 }", "foo.kt", |metric| {
2534 assert_eq!(metric.nargs.fn_args_sum(), 0.0);
2536 assert_eq!(metric.nargs.closure_args_sum(), 0.0);
2537 insta::assert_json_snapshot!(metric.nargs);
2538 });
2539 }
2540
2541 #[test]
2542 fn kotlin_single_arg() {
2543 check_metrics::<KotlinParser>(
2544 "fun double(x: Int): Int { return x * 2 }",
2545 "foo.kt",
2546 |metric| {
2547 assert_eq!(metric.nargs.fn_args_sum(), 1.0);
2549 assert_eq!(metric.nargs.closure_args_sum(), 0.0);
2550 insta::assert_json_snapshot!(metric.nargs);
2551 },
2552 );
2553 }
2554
2555 #[test]
2556 fn kotlin_multiple_args() {
2557 check_metrics::<KotlinParser>(
2558 "fun add(a: Int, b: Int, c: Int): Int { return a + b + c }",
2559 "foo.kt",
2560 |metric| {
2561 assert_eq!(metric.nargs.fn_args_sum(), 3.0);
2563 assert_eq!(metric.nargs.closure_args_sum(), 0.0);
2564 insta::assert_json_snapshot!(metric.nargs);
2565 },
2566 );
2567 }
2568
2569 #[test]
2570 fn kotlin_default_args() {
2571 check_metrics::<KotlinParser>(
2572 "fun greet(name: String = \"World\", greeting: String = \"Hello\"): String {
2573 return \"$greeting, $name!\"
2574 }",
2575 "foo.kt",
2576 |metric| {
2577 assert_eq!(metric.nargs.fn_args_sum(), 2.0);
2579 assert_eq!(metric.nargs.closure_args_sum(), 0.0);
2580 insta::assert_json_snapshot!(metric.nargs);
2581 },
2582 );
2583 }
2584
2585 #[test]
2586 fn kotlin_empty_lambda() {
2587 check_metrics::<KotlinParser>(
2595 "fun f() {
2596 val two = { x: Int, y: Int -> x + y }
2597 val zero = { -> 42 }
2598 }",
2599 "foo.kt",
2600 |metric| {
2601 assert_eq!(metric.nargs.fn_args_sum(), 0.0);
2605 assert_eq!(metric.nargs.closure_args_sum(), 2.0);
2606 insta::assert_json_snapshot!(metric.nargs);
2607 },
2608 );
2609 }
2610
2611 #[test]
2612 fn kotlin_anonymous_function() {
2613 check_metrics::<KotlinParser>(
2617 "val add = fun(x: Int, y: Int): Int = x + y",
2618 "foo.kt",
2619 |metric| {
2620 assert_eq!(metric.nargs.fn_args_sum(), 0.0);
2622 assert_eq!(metric.nargs.closure_args_sum(), 2.0);
2623 insta::assert_json_snapshot!(metric.nargs);
2624 },
2625 );
2626 }
2627
2628 #[test]
2629 fn php_no_functions_and_closures() {
2630 check_metrics::<PhpParser>("<?php $a = 42;", "foo.php", |metric| {
2631 insta::assert_json_snapshot!(
2632 metric.nargs,
2633 @r###"
2634 {
2635 "total_functions": 0.0,
2636 "total_closures": 0.0,
2637 "average_functions": 0.0,
2638 "average_closures": 0.0,
2639 "total": 0.0,
2640 "average": 0.0,
2641 "functions_min": 0.0,
2642 "functions_max": 0.0,
2643 "closures_min": 0.0,
2644 "closures_max": 0.0
2645 }"###
2646 );
2647 });
2648 }
2649
2650 #[test]
2651 fn php_single_function() {
2652 check_metrics::<PhpParser>(
2654 "<?php
2655 function f(bool $a, int $b): bool {
2656 if ($a) { return $a; }
2657 return false;
2658 }",
2659 "foo.php",
2660 |metric| {
2661 insta::assert_json_snapshot!(
2662 metric.nargs,
2663 @r###"
2664 {
2665 "total_functions": 2.0,
2666 "total_closures": 0.0,
2667 "average_functions": 2.0,
2668 "average_closures": 0.0,
2669 "total": 2.0,
2670 "average": 2.0,
2671 "functions_min": 0.0,
2672 "functions_max": 2.0,
2673 "closures_min": 0.0,
2674 "closures_max": 0.0
2675 }"###
2676 );
2677 },
2678 );
2679 }
2680
2681 #[test]
2682 fn php_single_closure() {
2683 check_metrics::<PhpParser>(
2686 "<?php
2687 $f = function (int $a, int $b) { return $a + $b; };
2688 $g = fn (int $x) => $x * 2;",
2689 "foo.php",
2690 |metric| {
2691 insta::assert_json_snapshot!(
2692 metric.nargs,
2693 @r###"
2694 {
2695 "total_functions": 0.0,
2696 "total_closures": 3.0,
2697 "average_functions": 0.0,
2698 "average_closures": 1.5,
2699 "total": 3.0,
2700 "average": 1.5,
2701 "functions_min": 0.0,
2702 "functions_max": 0.0,
2703 "closures_min": 0.0,
2704 "closures_max": 2.0
2705 }"###
2706 );
2707 },
2708 );
2709 }
2710
2711 #[test]
2712 fn php_functions() {
2713 check_metrics::<PhpParser>(
2715 "<?php
2716 function a(int $x): int { return $x; }
2717 function b(int $x, int $y): int { return $x + $y; }",
2718 "foo.php",
2719 |metric| {
2720 insta::assert_json_snapshot!(
2721 metric.nargs,
2722 @r###"
2723 {
2724 "total_functions": 3.0,
2725 "total_closures": 0.0,
2726 "average_functions": 1.5,
2727 "average_closures": 0.0,
2728 "total": 3.0,
2729 "average": 1.5,
2730 "functions_min": 0.0,
2731 "functions_max": 2.0,
2732 "closures_min": 0.0,
2733 "closures_max": 0.0
2734 }"###
2735 );
2736 },
2737 );
2738 }
2739
2740 #[test]
2741 fn php_nested_functions() {
2742 check_metrics::<PhpParser>(
2746 "<?php
2747 class A {
2748 public function outer(int $a): int {
2749 $f = function (int $b) use ($a) { return $a + $b; };
2750 return $f($a);
2751 }
2752 }",
2753 "foo.php",
2754 |metric| {
2755 insta::assert_json_snapshot!(
2756 metric.nargs,
2757 @r###"
2758 {
2759 "total_functions": 1.0,
2760 "total_closures": 1.0,
2761 "average_functions": 1.0,
2762 "average_closures": 1.0,
2763 "total": 2.0,
2764 "average": 1.0,
2765 "functions_min": 0.0,
2766 "functions_max": 1.0,
2767 "closures_min": 0.0,
2768 "closures_max": 1.0
2769 }"###
2770 );
2771 },
2772 );
2773 }
2774
2775 #[test]
2776 fn elixir_default_nargs_is_zero() {
2777 check_metrics::<ElixirParser>(
2786 "defmodule Foo do\n def add(a, b), do: a + b\n def use_anon do\n add2 = fn x, y -> x + y end\n add2.(1, 2)\n end\nend\n",
2787 "foo.ex",
2788 |metric| {
2789 assert_eq!(metric.nargs.fn_args_sum(), 0.0);
2790 assert_eq!(metric.nargs.closure_args_sum(), 0.0);
2791 },
2792 );
2793 }
2794
2795 #[test]
2796 fn ruby_no_functions_and_closures() {
2797 check_metrics::<RubyParser>("a = 42\n", "foo.rb", |metric| {
2798 assert_eq!(metric.nargs.fn_args_sum(), 0.0);
2799 assert_eq!(metric.nargs.closure_args_sum(), 0.0);
2800 });
2801 }
2802
2803 #[test]
2804 fn ruby_single_function() {
2805 check_metrics::<RubyParser>("def foo(a, b, c)\n a + b + c\nend\n", "foo.rb", |metric| {
2807 assert_eq!(metric.nargs.fn_args_sum(), 3.0);
2808 assert_eq!(metric.nargs.closure_args_sum(), 0.0);
2809 });
2810 }
2811
2812 #[test]
2813 fn ruby_single_closure() {
2814 check_metrics::<RubyParser>("[1, 2, 3].each { |x| puts x }\n", "foo.rb", |metric| {
2817 assert_eq!(metric.nargs.fn_args_sum(), 0.0);
2818 assert_eq!(metric.nargs.closure_args_sum(), 1.0);
2819 });
2820 }
2821
2822 #[test]
2823 fn ruby_functions() {
2824 check_metrics::<RubyParser>(
2826 "def add(a, b)\n a + b\nend\n\ndef neg(x)\n -x\nend\n\nf = ->(a, b) { a * b }\n",
2827 "foo.rb",
2828 |metric| {
2829 assert_eq!(metric.nargs.fn_args_sum(), 3.0);
2830 assert_eq!(metric.nargs.closure_args_sum(), 2.0);
2831 },
2832 );
2833 }
2834
2835 #[test]
2836 fn ruby_nested_functions() {
2837 check_metrics::<RubyParser>(
2839 "def outer(a)\n def inner(b, c)\n b + c\n end\n inner(a, a)\nend\n",
2840 "foo.rb",
2841 |metric| {
2842 assert_eq!(metric.nargs.fn_args_sum(), 3.0);
2843 assert_eq!(metric.nargs.closure_args_sum(), 0.0);
2844 },
2845 );
2846 }
2847}