1#![allow(
8 clippy::enum_glob_use,
9 clippy::match_same_arms,
10 clippy::struct_field_names,
11 clippy::wildcard_imports
12)]
13#![allow(
20 clippy::cast_precision_loss,
21 clippy::cast_possible_truncation,
22 clippy::cast_sign_loss
23)]
24
25use crate::checker::Checker;
26use crate::metrics::npa::python_is_block;
27use std::fmt;
28
29use crate::macros::implement_metric_trait;
30use crate::*;
31
32#[inline]
37fn min_or_zero(v: usize) -> u64 {
38 if v == usize::MAX { 0 } else { v as u64 }
39}
40
41#[inline]
60fn span_rows(start_row: usize, end_line: usize) -> usize {
61 end_line - start_row
62}
63
64mod line_set;
65use line_set::LineSet;
66
67#[derive(Debug, Clone, PartialEq)]
69pub struct Sloc {
70 start: usize,
71 end_line: usize,
75 excluded_lines: usize,
84 sloc_min: usize,
85 sloc_max: usize,
86}
87
88impl Default for Sloc {
89 fn default() -> Self {
90 Self {
91 start: 0,
92 end_line: 0,
93 excluded_lines: 0,
94 sloc_min: usize::MAX,
95 sloc_max: 0,
96 }
97 }
98}
99
100impl Sloc {
101 #[inline]
103 #[must_use]
104 pub fn sloc(&self) -> u64 {
105 let span = span_rows(self.start, self.end_line);
108 span.saturating_sub(self.excluded_lines) as u64
114 }
115
116 #[inline]
130 pub(crate) fn exclude_span(&mut self, start_row: usize, end_line: usize) {
131 self.excluded_lines += span_rows(start_row, end_line);
132 }
133
134 #[inline]
137 #[must_use]
138 pub fn sloc_min(&self) -> u64 {
139 min_or_zero(self.sloc_min)
140 }
141
142 #[inline]
144 #[must_use]
145 pub fn sloc_max(&self) -> u64 {
146 self.sloc_max as u64
147 }
148
149 #[inline]
152 pub fn merge(&mut self, other: &Sloc) {
153 self.sloc_min = self.sloc_min.min(other.sloc_min);
158 self.sloc_max = self.sloc_max.max(other.sloc_max);
159
160 self.excluded_lines += other.excluded_lines;
174 }
175
176 #[inline]
177 pub(crate) fn compute_minmax(&mut self) {
178 self.sloc_min = self.sloc_min.min(self.sloc() as usize);
183 self.sloc_max = self.sloc_max.max(self.sloc() as usize);
184 }
185}
186
187#[derive(Debug, Clone, PartialEq)]
189pub struct Ploc {
190 lines: LineSet,
191 ploc_min: usize,
192 ploc_max: usize,
193}
194
195impl Default for Ploc {
196 fn default() -> Self {
197 Self {
198 lines: LineSet::default(),
199 ploc_min: usize::MAX,
200 ploc_max: 0,
201 }
202 }
203}
204
205impl Ploc {
206 #[inline]
208 #[must_use]
209 pub fn ploc(&self) -> u64 {
210 self.lines.len() as u64
213 }
214
215 #[inline]
218 #[must_use]
219 pub fn ploc_min(&self) -> u64 {
220 min_or_zero(self.ploc_min)
221 }
222
223 #[inline]
225 #[must_use]
226 pub fn ploc_max(&self) -> u64 {
227 self.ploc_max as u64
228 }
229
230 #[inline]
232 pub fn merge(&mut self, other: &Ploc) {
233 self.lines.union_with(&other.lines);
238
239 self.ploc_min = self.ploc_min.min(other.ploc_min);
241 self.ploc_max = self.ploc_max.max(other.ploc_max);
242 }
243
244 #[inline]
245 pub(crate) fn compute_minmax(&mut self) {
246 let ploc = self.ploc() as usize;
251 self.ploc_min = self.ploc_min.min(ploc);
252 self.ploc_max = self.ploc_max.max(ploc);
253 }
254}
255
256#[derive(Debug, Clone, PartialEq)]
258pub struct Cloc {
259 only_comment_line_starts: LineSet,
267 code_comment_line_starts: LineSet,
275 comment_line_end: Option<usize>,
276 cloc_min: usize,
277 cloc_max: usize,
278}
279
280impl Default for Cloc {
281 fn default() -> Self {
282 Self {
283 only_comment_line_starts: LineSet::default(),
284 code_comment_line_starts: LineSet::default(),
285 comment_line_end: Option::default(),
286 cloc_min: usize::MAX,
287 cloc_max: 0,
288 }
289 }
290}
291
292impl Cloc {
293 #[inline]
295 #[must_use]
296 pub fn cloc(&self) -> u64 {
297 self.only_comment_line_starts
307 .union_len(&self.code_comment_line_starts) as u64
308 }
309
310 #[inline]
313 #[must_use]
314 pub fn cloc_min(&self) -> u64 {
315 min_or_zero(self.cloc_min)
316 }
317
318 #[inline]
320 #[must_use]
321 pub fn cloc_max(&self) -> u64 {
322 self.cloc_max as u64
323 }
324
325 #[inline]
327 pub fn merge(&mut self, other: &Cloc) {
328 self.only_comment_line_starts
331 .union_with(&other.only_comment_line_starts);
332 self.code_comment_line_starts
333 .union_with(&other.code_comment_line_starts);
334
335 self.cloc_min = self.cloc_min.min(other.cloc_min);
337 self.cloc_max = self.cloc_max.max(other.cloc_max);
338 }
339
340 #[inline]
341 pub(crate) fn compute_minmax(&mut self) {
342 let cloc = self.cloc() as usize;
347 self.cloc_min = self.cloc_min.min(cloc);
348 self.cloc_max = self.cloc_max.max(cloc);
349 }
350}
351
352#[derive(Debug, Clone, PartialEq)]
354pub struct Lloc {
355 logical_lines: usize,
356 lloc_min: usize,
357 lloc_max: usize,
358}
359
360impl Default for Lloc {
361 fn default() -> Self {
362 Self {
363 logical_lines: 0,
364 lloc_min: usize::MAX,
365 lloc_max: 0,
366 }
367 }
368}
369
370impl Lloc {
371 #[inline]
373 #[must_use]
374 pub fn lloc(&self) -> u64 {
375 self.logical_lines as u64
378 }
379
380 #[inline]
383 #[must_use]
384 pub fn lloc_min(&self) -> u64 {
385 min_or_zero(self.lloc_min)
386 }
387
388 #[inline]
390 #[must_use]
391 pub fn lloc_max(&self) -> u64 {
392 self.lloc_max as u64
393 }
394
395 #[inline]
397 pub fn merge(&mut self, other: &Lloc) {
398 self.logical_lines += other.logical_lines;
400 self.lloc_min = self.lloc_min.min(other.lloc_min);
402 self.lloc_max = self.lloc_max.max(other.lloc_max);
403 }
404
405 #[inline]
406 pub(crate) fn compute_minmax(&mut self) {
407 self.lloc_min = self.lloc_min.min(self.lloc() as usize);
410 self.lloc_max = self.lloc_max.max(self.lloc() as usize);
411 }
412}
413
414#[derive(Debug, Clone, PartialEq)]
416#[non_exhaustive]
417pub struct Stats {
418 sloc: Sloc,
419 ploc: Ploc,
420 cloc: Cloc,
421 lloc: Lloc,
422 space_count: usize,
423 blank_min: usize,
424 blank_max: usize,
425}
426
427impl Default for Stats {
428 fn default() -> Self {
429 Self {
430 sloc: Sloc::default(),
431 ploc: Ploc::default(),
432 cloc: Cloc::default(),
433 lloc: Lloc::default(),
434 space_count: 1,
435 blank_min: usize::MAX,
436 blank_max: 0,
437 }
438 }
439}
440
441impl fmt::Display for Stats {
442 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
443 write!(
444 f,
445 "sloc: {}, ploc: {}, lloc: {}, cloc: {}, blank: {}, sloc_average: {}, ploc_average: {}, lloc_average: {}, cloc_average: {}, blank_average: {}, sloc_min: {}, sloc_max: {}, cloc_min: {}, cloc_max: {}, ploc_min: {}, ploc_max: {}, lloc_min: {}, lloc_max: {}, blank_min: {}, blank_max: {}",
446 self.sloc(),
447 self.ploc(),
448 self.lloc(),
449 self.cloc(),
450 self.blank(),
451 self.sloc_average(),
452 self.ploc_average(),
453 self.lloc_average(),
454 self.cloc_average(),
455 self.blank_average(),
456 self.sloc_min(),
457 self.sloc_max(),
458 self.cloc_min(),
459 self.cloc_max(),
460 self.ploc_min(),
461 self.ploc_max(),
462 self.lloc_min(),
463 self.lloc_max(),
464 self.blank_min(),
465 self.blank_max(),
466 )
467 }
468}
469
470impl Stats {
471 #[cfg(test)]
477 pub(crate) fn with_cloc_sloc(code_comment_lines: usize, sloc_end_row: usize) -> Self {
478 let mut stats = Stats::default();
479 stats.sloc.start = 0;
480 stats.sloc.end_line = sloc_end_row + 1;
483 if code_comment_lines > 0 {
488 let synthetic_base = sloc_end_row + 1;
489 stats
493 .cloc
494 .code_comment_line_starts
495 .insert_range(synthetic_base, synthetic_base + code_comment_lines - 1);
496 }
497 stats
498 }
499
500 pub fn merge(&mut self, other: &Stats) {
502 self.sloc.merge(&other.sloc);
503 self.ploc.merge(&other.ploc);
504 self.cloc.merge(&other.cloc);
505 self.lloc.merge(&other.lloc);
506
507 self.space_count += other.space_count;
509
510 self.blank_min = self.blank_min.min(other.blank_min);
512 self.blank_max = self.blank_max.max(other.blank_max);
513 }
514
515 #[inline]
521 pub(crate) fn exclude_test_span(&mut self, start_row: usize, end_line: usize) {
522 self.sloc.exclude_span(start_row, end_line);
523 }
524
525 #[inline]
529 #[must_use]
530 pub fn sloc(&self) -> u64 {
531 self.sloc.sloc()
532 }
533
534 #[inline]
538 #[must_use]
539 pub fn ploc(&self) -> u64 {
540 self.ploc.ploc()
541 }
542
543 #[inline]
547 #[must_use]
548 pub fn lloc(&self) -> u64 {
549 self.lloc.lloc()
550 }
551
552 #[inline]
556 #[must_use]
557 pub fn cloc(&self) -> u64 {
558 self.cloc.cloc()
559 }
560
561 #[inline]
565 #[must_use]
566 pub fn blank(&self) -> u64 {
567 self.sloc()
573 .saturating_sub(self.ploc())
574 .saturating_sub(self.cloc.only_comment_line_starts.len() as u64)
575 }
576
577 #[inline]
581 #[must_use]
582 pub fn sloc_average(&self) -> f64 {
583 crate::metrics::average(self.sloc() as f64, self.space_count)
584 }
585
586 #[inline]
590 #[must_use]
591 pub fn ploc_average(&self) -> f64 {
592 crate::metrics::average(self.ploc() as f64, self.space_count)
593 }
594
595 #[inline]
599 #[must_use]
600 pub fn lloc_average(&self) -> f64 {
601 crate::metrics::average(self.lloc() as f64, self.space_count)
602 }
603
604 #[inline]
608 #[must_use]
609 pub fn cloc_average(&self) -> f64 {
610 crate::metrics::average(self.cloc() as f64, self.space_count)
611 }
612
613 #[inline]
617 #[must_use]
618 pub fn blank_average(&self) -> f64 {
619 crate::metrics::average(self.blank() as f64, self.space_count)
620 }
621
622 #[inline]
624 #[must_use]
625 pub fn sloc_min(&self) -> u64 {
626 self.sloc.sloc_min()
627 }
628
629 #[inline]
631 #[must_use]
632 pub fn sloc_max(&self) -> u64 {
633 self.sloc.sloc_max()
634 }
635
636 #[inline]
638 #[must_use]
639 pub fn cloc_min(&self) -> u64 {
640 self.cloc.cloc_min()
641 }
642
643 #[inline]
645 #[must_use]
646 pub fn cloc_max(&self) -> u64 {
647 self.cloc.cloc_max()
648 }
649
650 #[inline]
652 #[must_use]
653 pub fn ploc_min(&self) -> u64 {
654 self.ploc.ploc_min()
655 }
656
657 #[inline]
659 #[must_use]
660 pub fn ploc_max(&self) -> u64 {
661 self.ploc.ploc_max()
662 }
663
664 #[inline]
666 #[must_use]
667 pub fn lloc_min(&self) -> u64 {
668 self.lloc.lloc_min()
669 }
670
671 #[inline]
673 #[must_use]
674 pub fn lloc_max(&self) -> u64 {
675 self.lloc.lloc_max()
676 }
677
678 #[inline]
681 #[must_use]
682 pub fn blank_min(&self) -> u64 {
683 min_or_zero(self.blank_min)
684 }
685
686 #[inline]
688 #[must_use]
689 pub fn blank_max(&self) -> u64 {
690 self.blank_max as u64
691 }
692
693 #[inline]
694 pub(crate) fn compute_minmax(&mut self) {
695 self.sloc.compute_minmax();
696 self.ploc.compute_minmax();
697 self.cloc.compute_minmax();
698 self.lloc.compute_minmax();
699
700 let blank = self.blank() as usize;
707 self.blank_min = self.blank_min.min(blank);
708 self.blank_max = self.blank_max.max(blank);
709 }
710
711 pub(crate) fn init_unit_span(&mut self, start: usize, end_line: usize) {
712 self.sloc.start = start;
713 self.sloc.end_line = end_line;
714 }
715}
716
717#[doc(hidden)]
718pub(crate) trait Loc
720where
721 Self: Checker,
722{
723 fn compute(node: &Node, ancestors: Ancestors<'_, '_>, stats: &mut Stats, is_func_space: bool);
729}
730
731mod shared;
732pub(crate) use shared::*;
733
734implement_metric_trait!(Loc, PreprocCode, CcommentCode);
738
739mod bash;
740mod c;
741mod cpp;
742mod csharp;
743mod elixir;
744mod go;
745mod groovy;
746mod irules;
747mod java;
748mod javascript;
749mod kotlin;
750mod lua;
751mod mozcpp;
752mod mozjs;
753mod objc;
754mod perl;
755mod php;
756mod python;
757mod ruby;
758mod rust;
759mod tcl;
760mod tsx;
761mod typescript;
762
763#[cfg(test)]
764#[allow(
765 clippy::float_cmp,
766 clippy::cast_precision_loss,
767 clippy::cast_possible_truncation,
768 clippy::cast_sign_loss,
769 clippy::similar_names,
770 clippy::doc_markdown,
771 clippy::needless_raw_string_hashes,
772 clippy::too_many_lines
773)]
774mod tests {
775 use crate::test_support::{check_metrics_only_shim, metrics_verbatim, space_verbatim};
776
777 use super::*;
778
779 check_metrics_only_shim!(check_metrics, Loc);
780
781 #[test]
787 fn loc_empty_file_min_is_zero() {
788 let stats = Stats::default();
789 assert_eq!(stats.sloc_min(), 0);
790 assert_eq!(stats.ploc_min(), 0);
791 assert_eq!(stats.lloc_min(), 0);
792 assert_eq!(stats.cloc_min(), 0);
793 assert_eq!(stats.blank_min(), 0);
794 }
795
796 #[cfg(test)]
802 fn assert_perl_parses_cleanly(source: &str) {
803 use crate::traits::ParserTrait;
804 let path = std::path::PathBuf::from("foo.pl");
808 let mut bytes = source.trim_end_matches('\n').as_bytes().to_vec();
809 bytes.push(b'\n');
810 let parser = PerlParser::new(bytes, &path, None);
811 assert!(
812 !parser.root().has_error(),
813 "tree-sitter-perl returned an error tree for snippet:\n{source}"
814 );
815 }
816
817 #[test]
818 fn python_sloc() {
819 check_metrics::<PythonParser>(
820 "
821
822 a = 42
823
824 ",
825 "foo.py",
826 |metric| {
827 insta::assert_json_snapshot!(
829 metric.loc,
830 @r#"
831 {
832 "sloc": 1,
833 "ploc": 1,
834 "lloc": 1,
835 "cloc": 0,
836 "blank": 0,
837 "sloc_average": 1.0,
838 "ploc_average": 1.0,
839 "lloc_average": 1.0,
840 "cloc_average": 0.0,
841 "blank_average": 0.0,
842 "sloc_min": 1,
843 "sloc_max": 1,
844 "cloc_min": 0,
845 "cloc_max": 0,
846 "ploc_min": 1,
847 "ploc_max": 1,
848 "lloc_min": 1,
849 "lloc_max": 1,
850 "blank_min": 0,
851 "blank_max": 0
852 }
853 "#
854 );
855 },
856 );
857 }
858
859 #[test]
860 fn python_blank() {
861 check_metrics::<PythonParser>(
862 "
863 a = 42
864
865 b = 43
866
867 ",
868 "foo.py",
869 |metric| {
870 insta::assert_json_snapshot!(
872 metric.loc,
873 @r#"
874 {
875 "sloc": 3,
876 "ploc": 2,
877 "lloc": 2,
878 "cloc": 0,
879 "blank": 1,
880 "sloc_average": 3.0,
881 "ploc_average": 2.0,
882 "lloc_average": 2.0,
883 "cloc_average": 0.0,
884 "blank_average": 1.0,
885 "sloc_min": 3,
886 "sloc_max": 3,
887 "cloc_min": 0,
888 "cloc_max": 0,
889 "ploc_min": 2,
890 "ploc_max": 2,
891 "lloc_min": 2,
892 "lloc_max": 2,
893 "blank_min": 1,
894 "blank_max": 1
895 }
896 "#
897 );
898 },
899 );
900 }
901
902 #[test]
903 fn rust_blank() {
904 check_metrics::<RustParser>(
905 "
906
907 let a = 42;
908
909 let b = 43;
910
911 ",
912 "foo.rs",
913 |metric| {
914 insta::assert_json_snapshot!(
916 metric.loc,
917 @r#"
918 {
919 "sloc": 3,
920 "ploc": 2,
921 "lloc": 2,
922 "cloc": 0,
923 "blank": 1,
924 "sloc_average": 3.0,
925 "ploc_average": 2.0,
926 "lloc_average": 2.0,
927 "cloc_average": 0.0,
928 "blank_average": 1.0,
929 "sloc_min": 3,
930 "sloc_max": 3,
931 "cloc_min": 0,
932 "cloc_max": 0,
933 "ploc_min": 2,
934 "ploc_max": 2,
935 "lloc_min": 2,
936 "lloc_max": 2,
937 "blank_min": 1,
938 "blank_max": 1
939 }
940 "#
941 );
942 },
943 );
944
945 check_metrics::<RustParser>("fn func() { /* comment */ }", "foo.rs", |metric| {
946 insta::assert_json_snapshot!(
948 metric.loc,
949 @r#"
950 {
951 "sloc": 1,
952 "ploc": 1,
953 "lloc": 0,
954 "cloc": 1,
955 "blank": 0,
956 "sloc_average": 0.5,
957 "ploc_average": 0.5,
958 "lloc_average": 0.0,
959 "cloc_average": 0.5,
960 "blank_average": 0.0,
961 "sloc_min": 1,
962 "sloc_max": 1,
963 "cloc_min": 1,
964 "cloc_max": 1,
965 "ploc_min": 1,
966 "ploc_max": 1,
967 "lloc_min": 0,
968 "lloc_max": 0,
969 "blank_min": 0,
970 "blank_max": 0
971 }
972 "#
973 );
974 });
975 }
976
977 #[test]
978 fn c_blank() {
979 check_metrics::<CParser>(
980 "
981
982 int a = 42;
983
984 int b = 43;
985
986 ",
987 "foo.c",
988 |metric| {
989 insta::assert_json_snapshot!(
991 metric.loc,
992 @r#"
993 {
994 "sloc": 3,
995 "ploc": 2,
996 "lloc": 2,
997 "cloc": 0,
998 "blank": 1,
999 "sloc_average": 3.0,
1000 "ploc_average": 2.0,
1001 "lloc_average": 2.0,
1002 "cloc_average": 0.0,
1003 "blank_average": 1.0,
1004 "sloc_min": 3,
1005 "sloc_max": 3,
1006 "cloc_min": 0,
1007 "cloc_max": 0,
1008 "ploc_min": 2,
1009 "ploc_max": 2,
1010 "lloc_min": 2,
1011 "lloc_max": 2,
1012 "blank_min": 1,
1013 "blank_max": 1
1014 }
1015 "#
1016 );
1017 },
1018 );
1019 }
1020
1021 #[test]
1022 fn python_no_zero_blank() {
1023 check_metrics::<PythonParser>(
1026 "def ConnectToUpdateServer():
1027 pool = 4
1028
1029 updateServer = -42
1030 isConnected = False
1031 currTry = 0
1032 numRetries = 10 # Number of IPC connection retries before
1033 # giving up.
1034 numTries = 20 # Number of IPC connection tries before
1035 # giving up.",
1036 "foo.py",
1037 |metric| {
1038 insta::assert_json_snapshot!(
1040 metric.loc,
1041 @r#"
1042 {
1043 "sloc": 10,
1044 "ploc": 7,
1045 "lloc": 6,
1046 "cloc": 4,
1047 "blank": 1,
1048 "sloc_average": 5.0,
1049 "ploc_average": 3.5,
1050 "lloc_average": 3.0,
1051 "cloc_average": 2.0,
1052 "blank_average": 0.5,
1053 "sloc_min": 10,
1054 "sloc_max": 10,
1055 "cloc_min": 4,
1056 "cloc_max": 4,
1057 "ploc_min": 7,
1058 "ploc_max": 7,
1059 "lloc_min": 6,
1060 "lloc_max": 6,
1061 "blank_min": 1,
1062 "blank_max": 1
1063 }
1064 "#
1065 );
1066 },
1067 );
1068 }
1069
1070 #[test]
1071 fn python_no_blank() {
1072 check_metrics::<PythonParser>(
1075 "def ConnectToUpdateServer():
1076 pool = 4
1077 updateServer = -42
1078 isConnected = False
1079 currTry = 0
1080 numRetries = 10 # Number of IPC connection retries before
1081 # giving up.
1082 numTries = 20 # Number of IPC connection tries before
1083 # giving up.",
1084 "foo.py",
1085 |metric| {
1086 insta::assert_json_snapshot!(
1088 metric.loc,
1089 @r#"
1090 {
1091 "sloc": 9,
1092 "ploc": 7,
1093 "lloc": 6,
1094 "cloc": 4,
1095 "blank": 0,
1096 "sloc_average": 4.5,
1097 "ploc_average": 3.5,
1098 "lloc_average": 3.0,
1099 "cloc_average": 2.0,
1100 "blank_average": 0.0,
1101 "sloc_min": 9,
1102 "sloc_max": 9,
1103 "cloc_min": 4,
1104 "cloc_max": 4,
1105 "ploc_min": 7,
1106 "ploc_max": 7,
1107 "lloc_min": 6,
1108 "lloc_max": 6,
1109 "blank_min": 0,
1110 "blank_max": 0
1111 }
1112 "#
1113 );
1114 },
1115 );
1116 }
1117
1118 #[test]
1119 fn python_no_zero_blank_more_comments() {
1120 check_metrics::<PythonParser>(
1123 "def ConnectToUpdateServer():
1124 pool = 4
1125
1126 updateServer = -42
1127 isConnected = False
1128 currTry = 0 # Set this variable to 0
1129 numRetries = 10 # Number of IPC connection retries before
1130 # giving up.
1131 numTries = 20 # Number of IPC connection tries before
1132 # giving up.",
1133 "foo.py",
1134 |metric| {
1135 insta::assert_json_snapshot!(
1137 metric.loc,
1138 @r#"
1139 {
1140 "sloc": 10,
1141 "ploc": 7,
1142 "lloc": 6,
1143 "cloc": 5,
1144 "blank": 1,
1145 "sloc_average": 5.0,
1146 "ploc_average": 3.5,
1147 "lloc_average": 3.0,
1148 "cloc_average": 2.5,
1149 "blank_average": 0.5,
1150 "sloc_min": 10,
1151 "sloc_max": 10,
1152 "cloc_min": 5,
1153 "cloc_max": 5,
1154 "ploc_min": 7,
1155 "ploc_max": 7,
1156 "lloc_min": 6,
1157 "lloc_max": 6,
1158 "blank_min": 1,
1159 "blank_max": 1
1160 }
1161 "#
1162 );
1163 },
1164 );
1165 }
1166
1167 #[test]
1168 fn rust_no_zero_blank() {
1169 check_metrics::<RustParser>(
1172 "fn ConnectToUpdateServer() {
1173 let pool = 0;
1174
1175 let updateServer = -42;
1176 let isConnected = false;
1177 let currTry = 0;
1178 let numRetries = 10; // Number of IPC connection retries before
1179 // giving up.
1180 let numTries = 20; // Number of IPC connection tries before
1181 // giving up.
1182 }",
1183 "foo.rs",
1184 |metric| {
1185 insta::assert_json_snapshot!(
1187 metric.loc,
1188 @r#"
1189 {
1190 "sloc": 11,
1191 "ploc": 8,
1192 "lloc": 6,
1193 "cloc": 4,
1194 "blank": 1,
1195 "sloc_average": 5.5,
1196 "ploc_average": 4.0,
1197 "lloc_average": 3.0,
1198 "cloc_average": 2.0,
1199 "blank_average": 0.5,
1200 "sloc_min": 11,
1201 "sloc_max": 11,
1202 "cloc_min": 4,
1203 "cloc_max": 4,
1204 "ploc_min": 8,
1205 "ploc_max": 8,
1206 "lloc_min": 6,
1207 "lloc_max": 6,
1208 "blank_min": 1,
1209 "blank_max": 1
1210 }
1211 "#
1212 );
1213 },
1214 );
1215 }
1216
1217 #[test]
1218 fn javascript_no_zero_blank() {
1219 check_metrics::<JavascriptParser>(
1222 "function ConnectToUpdateServer() {
1223 var pool = 0;
1224
1225 var updateServer = -42;
1226 var isConnected = false;
1227 var currTry = 0;
1228 var numRetries = 10; // Number of IPC connection retries before
1229 // giving up.
1230 var numTries = 20; // Number of IPC connection tries before
1231 // giving up.
1232 }",
1233 "foo.js",
1234 |metric| {
1235 insta::assert_json_snapshot!(
1237 metric.loc,
1238 @r#"
1239 {
1240 "sloc": 11,
1241 "ploc": 8,
1242 "lloc": 0,
1243 "cloc": 4,
1244 "blank": 1,
1245 "sloc_average": 5.5,
1246 "ploc_average": 4.0,
1247 "lloc_average": 0.0,
1248 "cloc_average": 2.0,
1249 "blank_average": 0.5,
1250 "sloc_min": 11,
1251 "sloc_max": 11,
1252 "cloc_min": 4,
1253 "cloc_max": 4,
1254 "ploc_min": 8,
1255 "ploc_max": 8,
1256 "lloc_min": 0,
1257 "lloc_max": 0,
1258 "blank_min": 1,
1259 "blank_max": 1
1260 }
1261 "#
1262 );
1263 },
1264 );
1265 }
1266
1267 #[test]
1268 fn cpp_no_zero_blank() {
1269 check_metrics::<CppParser>(
1272 "void ConnectToUpdateServer() {
1273 int pool;
1274
1275 int updateServer = -42;
1276 bool isConnected = false;
1277 int currTry = 0;
1278 const int numRetries = 10; // Number of IPC connection retries before
1279 // giving up.
1280 const int numTries = 20; // Number of IPC connection tries before
1281 // giving up.
1282 }",
1283 "foo.cpp",
1284 |metric| {
1285 insta::assert_json_snapshot!(
1287 metric.loc,
1288 @r#"
1289 {
1290 "sloc": 11,
1291 "ploc": 8,
1292 "lloc": 6,
1293 "cloc": 4,
1294 "blank": 1,
1295 "sloc_average": 5.5,
1296 "ploc_average": 4.0,
1297 "lloc_average": 3.0,
1298 "cloc_average": 2.0,
1299 "blank_average": 0.5,
1300 "sloc_min": 11,
1301 "sloc_max": 11,
1302 "cloc_min": 4,
1303 "cloc_max": 4,
1304 "ploc_min": 8,
1305 "ploc_max": 8,
1306 "lloc_min": 6,
1307 "lloc_max": 6,
1308 "blank_min": 1,
1309 "blank_max": 1
1310 }
1311 "#
1312 );
1313 },
1314 );
1315 }
1316
1317 #[test]
1318 fn cpp_code_line_start_block_blank() {
1319 check_metrics::<CppParser>(
1322 "void ConnectToUpdateServer() {
1323 int pool;
1324
1325 int updateServer = -42;
1326 bool isConnected = false;
1327 int currTry = 0;
1328 const int numRetries = 10; /* Number of IPC connection retries
1329 before
1330 giving up. */
1331 const int numTries = 20; // Number of IPC connection tries before
1332 // giving up.
1333 }",
1334 "foo.cpp",
1335 |metric| {
1336 insta::assert_json_snapshot!(
1338 metric.loc,
1339 @r#"
1340 {
1341 "sloc": 12,
1342 "ploc": 8,
1343 "lloc": 6,
1344 "cloc": 5,
1345 "blank": 1,
1346 "sloc_average": 6.0,
1347 "ploc_average": 4.0,
1348 "lloc_average": 3.0,
1349 "cloc_average": 2.5,
1350 "blank_average": 0.5,
1351 "sloc_min": 12,
1352 "sloc_max": 12,
1353 "cloc_min": 5,
1354 "cloc_max": 5,
1355 "ploc_min": 8,
1356 "ploc_max": 8,
1357 "lloc_min": 6,
1358 "lloc_max": 6,
1359 "blank_min": 1,
1360 "blank_max": 1
1361 }
1362 "#
1363 );
1364 },
1365 );
1366 }
1367
1368 #[test]
1369 fn cpp_block_comment_blank() {
1370 check_metrics::<CppParser>(
1373 "void ConnectToUpdateServer() {
1374 int pool;
1375
1376 int updateServer = -42;
1377 bool isConnected = false;
1378 int currTry = 0;
1379 /* Number of IPC connection retries
1380 before
1381 giving up. */
1382 const int numRetries = 10;
1383 const int numTries = 20; // Number of IPC connection tries before
1384 // giving up.
1385 }",
1386 "foo.cpp",
1387 |metric| {
1388 insta::assert_json_snapshot!(
1390 metric.loc,
1391 @r#"
1392 {
1393 "sloc": 13,
1394 "ploc": 8,
1395 "lloc": 6,
1396 "cloc": 5,
1397 "blank": 1,
1398 "sloc_average": 6.5,
1399 "ploc_average": 4.0,
1400 "lloc_average": 3.0,
1401 "cloc_average": 2.5,
1402 "blank_average": 0.5,
1403 "sloc_min": 13,
1404 "sloc_max": 13,
1405 "cloc_min": 5,
1406 "cloc_max": 5,
1407 "ploc_min": 8,
1408 "ploc_max": 8,
1409 "lloc_min": 6,
1410 "lloc_max": 6,
1411 "blank_min": 1,
1412 "blank_max": 1
1413 }
1414 "#
1415 );
1416 },
1417 );
1418 }
1419
1420 #[test]
1421 fn cpp_code_line_block_one_line_blank() {
1422 check_metrics::<CppParser>(
1425 "void ConnectToUpdateServer() {
1426 int pool;
1427
1428 int updateServer = -42;
1429 bool isConnected = false;
1430 int currTry = 0;
1431 /* Number of IPC connection retries before giving up. */ const int numRetries = 10;
1432 const int numTries = 20; // Number of IPC connection tries before
1433 // giving up.
1434 }",
1435 "foo.cpp",
1436 |metric| {
1437 insta::assert_json_snapshot!(
1439 metric.loc,
1440 @r#"
1441 {
1442 "sloc": 10,
1443 "ploc": 8,
1444 "lloc": 6,
1445 "cloc": 3,
1446 "blank": 1,
1447 "sloc_average": 5.0,
1448 "ploc_average": 4.0,
1449 "lloc_average": 3.0,
1450 "cloc_average": 1.5,
1451 "blank_average": 0.5,
1452 "sloc_min": 10,
1453 "sloc_max": 10,
1454 "cloc_min": 3,
1455 "cloc_max": 3,
1456 "ploc_min": 8,
1457 "ploc_max": 8,
1458 "lloc_min": 6,
1459 "lloc_max": 6,
1460 "blank_min": 1,
1461 "blank_max": 1
1462 }
1463 "#
1464 );
1465 },
1466 );
1467 }
1468
1469 #[test]
1470 fn cpp_code_line_end_block_blank() {
1471 check_metrics::<CppParser>(
1474 "void ConnectToUpdateServer() {
1475 int pool;
1476
1477 int updateServer = -42;
1478 bool isConnected = false;
1479 int currTry = 0;
1480 /* Number of IPC connection retries
1481 before
1482 giving up. */ const int numRetries = 10;
1483 const int numTries = 20; // Number of IPC connection tries before
1484 // giving up.
1485 }",
1486 "foo.cpp",
1487 |metric| {
1488 insta::assert_json_snapshot!(
1490 metric.loc,
1491 @r#"
1492 {
1493 "sloc": 12,
1494 "ploc": 8,
1495 "lloc": 6,
1496 "cloc": 5,
1497 "blank": 1,
1498 "sloc_average": 6.0,
1499 "ploc_average": 4.0,
1500 "lloc_average": 3.0,
1501 "cloc_average": 2.5,
1502 "blank_average": 0.5,
1503 "sloc_min": 12,
1504 "sloc_max": 12,
1505 "cloc_min": 5,
1506 "cloc_max": 5,
1507 "ploc_min": 8,
1508 "ploc_max": 8,
1509 "lloc_min": 6,
1510 "lloc_max": 6,
1511 "blank_min": 1,
1512 "blank_max": 1
1513 }
1514 "#
1515 );
1516 },
1517 );
1518 }
1519
1520 #[test]
1521 fn python_cloc() {
1522 check_metrics::<PythonParser>(
1523 "\"\"\"Block comment
1524 Block comment
1525 \"\"\"
1526 # Line Comment
1527 a = 42 # Line Comment",
1528 "foo.py",
1529 |metric| {
1530 insta::assert_json_snapshot!(
1532 metric.loc,
1533 @r#"
1534 {
1535 "sloc": 5,
1536 "ploc": 1,
1537 "lloc": 2,
1538 "cloc": 5,
1539 "blank": 0,
1540 "sloc_average": 5.0,
1541 "ploc_average": 1.0,
1542 "lloc_average": 2.0,
1543 "cloc_average": 5.0,
1544 "blank_average": 0.0,
1545 "sloc_min": 5,
1546 "sloc_max": 5,
1547 "cloc_min": 5,
1548 "cloc_max": 5,
1549 "ploc_min": 1,
1550 "ploc_max": 1,
1551 "lloc_min": 2,
1552 "lloc_max": 2,
1553 "blank_min": 0,
1554 "blank_max": 0
1555 }
1556 "#
1557 );
1558 },
1559 );
1560 }
1561
1562 #[test]
1563 fn rust_cloc() {
1564 check_metrics::<RustParser>(
1565 "/*Block comment
1566 Block Comment*/
1567 //Line Comment
1568 /*Block Comment*/ let a = 42; // Line Comment",
1569 "foo.rs",
1570 |metric| {
1571 insta::assert_json_snapshot!(
1580 metric.loc,
1581 @r#"
1582 {
1583 "sloc": 4,
1584 "ploc": 1,
1585 "lloc": 1,
1586 "cloc": 4,
1587 "blank": 0,
1588 "sloc_average": 4.0,
1589 "ploc_average": 1.0,
1590 "lloc_average": 1.0,
1591 "cloc_average": 4.0,
1592 "blank_average": 0.0,
1593 "sloc_min": 4,
1594 "sloc_max": 4,
1595 "cloc_min": 4,
1596 "cloc_max": 4,
1597 "ploc_min": 1,
1598 "ploc_max": 1,
1599 "lloc_min": 1,
1600 "lloc_max": 1,
1601 "blank_min": 0,
1602 "blank_max": 0
1603 }
1604 "#
1605 );
1606 },
1607 );
1608 }
1609
1610 #[test]
1611 fn c_cloc() {
1612 check_metrics::<CParser>(
1613 "/*Block comment
1614 Block Comment*/
1615 //Line Comment
1616 /*Block Comment*/ int a = 42; // Line Comment",
1617 "foo.c",
1618 |metric| {
1619 insta::assert_json_snapshot!(
1625 metric.loc,
1626 @r#"
1627 {
1628 "sloc": 4,
1629 "ploc": 1,
1630 "lloc": 1,
1631 "cloc": 4,
1632 "blank": 0,
1633 "sloc_average": 4.0,
1634 "ploc_average": 1.0,
1635 "lloc_average": 1.0,
1636 "cloc_average": 4.0,
1637 "blank_average": 0.0,
1638 "sloc_min": 4,
1639 "sloc_max": 4,
1640 "cloc_min": 4,
1641 "cloc_max": 4,
1642 "ploc_min": 1,
1643 "ploc_max": 1,
1644 "lloc_min": 1,
1645 "lloc_max": 1,
1646 "blank_min": 0,
1647 "blank_max": 0
1648 }
1649 "#
1650 );
1651 },
1652 );
1653 }
1654
1655 #[test]
1656 fn python_lloc() {
1657 check_metrics::<PythonParser>(
1658 "for x in range(0,42):
1659 if x % 2 == 0:
1660 print(x)",
1661 "foo.py",
1662 |metric| {
1663 insta::assert_json_snapshot!(
1665 metric.loc,
1666 @r#"
1667 {
1668 "sloc": 3,
1669 "ploc": 3,
1670 "lloc": 3,
1671 "cloc": 0,
1672 "blank": 0,
1673 "sloc_average": 3.0,
1674 "ploc_average": 3.0,
1675 "lloc_average": 3.0,
1676 "cloc_average": 0.0,
1677 "blank_average": 0.0,
1678 "sloc_min": 3,
1679 "sloc_max": 3,
1680 "cloc_min": 0,
1681 "cloc_max": 0,
1682 "ploc_min": 3,
1683 "ploc_max": 3,
1684 "lloc_min": 3,
1685 "lloc_max": 3,
1686 "blank_min": 0,
1687 "blank_max": 0
1688 }
1689 "#
1690 );
1691 },
1692 );
1693 }
1694
1695 #[test]
1696 fn rust_lloc() {
1697 check_metrics::<RustParser>(
1698 "for x in 0..42 {
1699 if x % 2 == 0 {
1700 println!(\"{}\", x);
1701 }
1702 }",
1703 "foo.rs",
1704 |metric| {
1705 insta::assert_json_snapshot!(
1707 metric.loc,
1708 @r#"
1709 {
1710 "sloc": 5,
1711 "ploc": 5,
1712 "lloc": 3,
1713 "cloc": 0,
1714 "blank": 0,
1715 "sloc_average": 5.0,
1716 "ploc_average": 5.0,
1717 "lloc_average": 3.0,
1718 "cloc_average": 0.0,
1719 "blank_average": 0.0,
1720 "sloc_min": 5,
1721 "sloc_max": 5,
1722 "cloc_min": 0,
1723 "cloc_max": 0,
1724 "ploc_min": 5,
1725 "ploc_max": 5,
1726 "lloc_min": 3,
1727 "lloc_max": 3,
1728 "blank_min": 0,
1729 "blank_max": 0
1730 }
1731 "#
1732 );
1733 },
1734 );
1735
1736 check_metrics::<RustParser>(
1738 "let a = 42;
1739 if true {
1740 42
1741 } else {
1742 43
1743 };",
1744 "foo.rs",
1745 |metric| {
1746 insta::assert_json_snapshot!(
1748 metric.loc,
1749 @r#"
1750 {
1751 "sloc": 6,
1752 "ploc": 6,
1753 "lloc": 3,
1754 "cloc": 0,
1755 "blank": 0,
1756 "sloc_average": 6.0,
1757 "ploc_average": 6.0,
1758 "lloc_average": 3.0,
1759 "cloc_average": 0.0,
1760 "blank_average": 0.0,
1761 "sloc_min": 6,
1762 "sloc_max": 6,
1763 "cloc_min": 0,
1764 "cloc_max": 0,
1765 "ploc_min": 6,
1766 "ploc_max": 6,
1767 "lloc_min": 3,
1768 "lloc_max": 3,
1769 "blank_min": 0,
1770 "blank_max": 0
1771 }
1772 "#
1773 );
1774 },
1775 );
1776 }
1777
1778 #[test]
1779 fn c_lloc() {
1780 check_metrics::<CParser>(
1781 "for (;;)
1782 break;",
1783 "foo.c",
1784 |metric| {
1785 insta::assert_json_snapshot!(
1787 metric.loc,
1788 @r#"
1789 {
1790 "sloc": 2,
1791 "ploc": 2,
1792 "lloc": 2,
1793 "cloc": 0,
1794 "blank": 0,
1795 "sloc_average": 2.0,
1796 "ploc_average": 2.0,
1797 "lloc_average": 2.0,
1798 "cloc_average": 0.0,
1799 "blank_average": 0.0,
1800 "sloc_min": 2,
1801 "sloc_max": 2,
1802 "cloc_min": 0,
1803 "cloc_max": 0,
1804 "ploc_min": 2,
1805 "ploc_max": 2,
1806 "lloc_min": 2,
1807 "lloc_max": 2,
1808 "blank_min": 0,
1809 "blank_max": 0
1810 }
1811 "#
1812 );
1813 },
1814 );
1815 }
1816
1817 #[test]
1818 fn cpp_lloc() {
1819 check_metrics::<CppParser>(
1820 "nsTArray<xpcGCCallback> callbacks(extraGCCallbacks.Clone());
1821 for (uint32_t i = 0; i < callbacks.Length(); ++i) {
1822 callbacks[i](status);
1823 }",
1824 "foo.cpp",
1825 |metric| {
1826 insta::assert_json_snapshot!(
1829 metric.loc,
1830 @r#"
1831 {
1832 "sloc": 4,
1833 "ploc": 4,
1834 "lloc": 3,
1835 "cloc": 0,
1836 "blank": 0,
1837 "sloc_average": 4.0,
1838 "ploc_average": 4.0,
1839 "lloc_average": 3.0,
1840 "cloc_average": 0.0,
1841 "blank_average": 0.0,
1842 "sloc_min": 4,
1843 "sloc_max": 4,
1844 "cloc_min": 0,
1845 "cloc_max": 0,
1846 "ploc_min": 4,
1847 "ploc_max": 4,
1848 "lloc_min": 3,
1849 "lloc_max": 3,
1850 "blank_min": 0,
1851 "blank_max": 0
1852 }
1853 "#
1854 );
1855 },
1856 );
1857 }
1858
1859 #[test]
1860 fn cpp_return_lloc() {
1861 check_metrics::<CppParser>(
1862 "uint8_t* pixel_data = frame.GetFrameDataAtPos(DesktopVector(x, y));
1863 return RgbaColor(pixel_data) == blank_pixel_;",
1864 "foo.cpp",
1865 |metric| {
1866 insta::assert_json_snapshot!(
1869 metric.loc,
1870 @r#"
1871 {
1872 "sloc": 2,
1873 "ploc": 2,
1874 "lloc": 2,
1875 "cloc": 0,
1876 "blank": 0,
1877 "sloc_average": 2.0,
1878 "ploc_average": 2.0,
1879 "lloc_average": 2.0,
1880 "cloc_average": 0.0,
1881 "blank_average": 0.0,
1882 "sloc_min": 2,
1883 "sloc_max": 2,
1884 "cloc_min": 0,
1885 "cloc_max": 0,
1886 "ploc_min": 2,
1887 "ploc_max": 2,
1888 "lloc_min": 2,
1889 "lloc_max": 2,
1890 "blank_min": 0,
1891 "blank_max": 0
1892 }
1893 "#
1894 );
1895 },
1896 );
1897 }
1898
1899 #[test]
1900 fn cpp_for_lloc() {
1901 check_metrics::<CppParser>(
1902 "for (; start != end; ++start) {
1903 const unsigned char idx = *start;
1904 if (idx > 127 || !kValidTokenMap[idx]) return false;
1905 }",
1906 "foo.cpp",
1907 |metric| {
1908 insta::assert_json_snapshot!(
1911 metric.loc,
1912 @r#"
1913 {
1914 "sloc": 4,
1915 "ploc": 4,
1916 "lloc": 4,
1917 "cloc": 0,
1918 "blank": 0,
1919 "sloc_average": 4.0,
1920 "ploc_average": 4.0,
1921 "lloc_average": 4.0,
1922 "cloc_average": 0.0,
1923 "blank_average": 0.0,
1924 "sloc_min": 4,
1925 "sloc_max": 4,
1926 "cloc_min": 0,
1927 "cloc_max": 0,
1928 "ploc_min": 4,
1929 "ploc_max": 4,
1930 "lloc_min": 4,
1931 "lloc_max": 4,
1932 "blank_min": 0,
1933 "blank_max": 0
1934 }
1935 "#
1936 );
1937 },
1938 );
1939 }
1940
1941 #[test]
1942 fn cpp_while_lloc() {
1943 check_metrics::<CppParser>(
1944 "while (sHeapAtoms) {
1945 HttpHeapAtom* next = sHeapAtoms->next;
1946 free(sHeapAtoms);
1947 }",
1948 "foo.cpp",
1949 |metric| {
1950 insta::assert_json_snapshot!(
1953 metric.loc,
1954 @r#"
1955 {
1956 "sloc": 4,
1957 "ploc": 4,
1958 "lloc": 3,
1959 "cloc": 0,
1960 "blank": 0,
1961 "sloc_average": 4.0,
1962 "ploc_average": 4.0,
1963 "lloc_average": 3.0,
1964 "cloc_average": 0.0,
1965 "blank_average": 0.0,
1966 "sloc_min": 4,
1967 "sloc_max": 4,
1968 "cloc_min": 0,
1969 "cloc_max": 0,
1970 "ploc_min": 4,
1971 "ploc_max": 4,
1972 "lloc_min": 3,
1973 "lloc_max": 3,
1974 "blank_min": 0,
1975 "blank_max": 0
1976 }
1977 "#
1978 );
1979 },
1980 );
1981 }
1982
1983 #[test]
1984 fn python_string_on_new_line() {
1985 check_metrics::<PythonParser>(
1987 "capabilities[\"goog:chromeOptions\"][\"androidPackage\"] = \\
1988 \"org.chromium.weblayer.shell\"",
1989 "foo.py",
1990 |metric| {
1991 insta::assert_json_snapshot!(
1993 metric.loc,
1994 @r#"
1995 {
1996 "sloc": 2,
1997 "ploc": 2,
1998 "lloc": 1,
1999 "cloc": 0,
2000 "blank": 0,
2001 "sloc_average": 2.0,
2002 "ploc_average": 2.0,
2003 "lloc_average": 1.0,
2004 "cloc_average": 0.0,
2005 "blank_average": 0.0,
2006 "sloc_min": 2,
2007 "sloc_max": 2,
2008 "cloc_min": 0,
2009 "cloc_max": 0,
2010 "ploc_min": 2,
2011 "ploc_max": 2,
2012 "lloc_min": 1,
2013 "lloc_max": 1,
2014 "blank_min": 0,
2015 "blank_max": 0
2016 }
2017 "#
2018 );
2019 },
2020 );
2021 }
2022
2023 #[test]
2024 fn python_multiline_string_assignment_ploc() {
2025 check_metrics::<PythonParser>(
2028 "QUERY = \"\"\"
2029SELECT id, name
2030FROM users
2031WHERE active = 1
2032ORDER BY name
2033\"\"\"",
2034 "foo.py",
2035 |metric| {
2036 assert_eq!(metric.loc.sloc(), 6);
2038 assert_eq!(metric.loc.ploc(), 6);
2039 assert_eq!(metric.loc.cloc(), 0);
2040 assert_eq!(metric.loc.blank(), 0);
2041 insta::assert_json_snapshot!(
2042 metric.loc,
2043 @r#"
2044 {
2045 "sloc": 6,
2046 "ploc": 6,
2047 "lloc": 1,
2048 "cloc": 0,
2049 "blank": 0,
2050 "sloc_average": 6.0,
2051 "ploc_average": 6.0,
2052 "lloc_average": 1.0,
2053 "cloc_average": 0.0,
2054 "blank_average": 0.0,
2055 "sloc_min": 6,
2056 "sloc_max": 6,
2057 "cloc_min": 0,
2058 "cloc_max": 0,
2059 "ploc_min": 6,
2060 "ploc_max": 6,
2061 "lloc_min": 1,
2062 "lloc_max": 1,
2063 "blank_min": 0,
2064 "blank_max": 0
2065 }
2066 "#
2067 );
2068 },
2069 );
2070 }
2071
2072 #[test]
2073 fn python_multiline_string_argument_ploc() {
2074 check_metrics::<PythonParser>(
2077 "print(\"\"\"
2078line one
2079line two
2080\"\"\")",
2081 "foo.py",
2082 |metric| {
2083 assert_eq!(metric.loc.sloc(), 4);
2085 assert_eq!(metric.loc.ploc(), 4);
2086 assert_eq!(metric.loc.cloc(), 0);
2087 assert_eq!(metric.loc.blank(), 0);
2088 },
2089 );
2090 }
2091
2092 #[test]
2093 fn python_single_line_string_assignment_ploc() {
2094 check_metrics::<PythonParser>("QUERY = \"SELECT 1\"", "foo.py", |metric| {
2097 assert_eq!(metric.loc.sloc(), 1);
2099 assert_eq!(metric.loc.ploc(), 1);
2100 assert_eq!(metric.loc.cloc(), 0);
2101 assert_eq!(metric.loc.blank(), 0);
2102 });
2103 }
2104
2105 #[test]
2106 fn python_multiline_docstring_still_cloc() {
2107 check_metrics::<PythonParser>(
2110 "def f():
2111 \"\"\"Docstring line one
2112 Docstring line two
2113 \"\"\"
2114 return 1",
2115 "foo.py",
2116 |metric| {
2117 assert_eq!(metric.loc.cloc(), 3);
2120 assert_eq!(metric.loc.blank(), 0);
2121 },
2122 );
2123 }
2124
2125 #[test]
2126 fn rust_no_field_expression_lloc() {
2127 check_metrics::<RustParser>(
2128 "struct Foo {
2129 field: usize,
2130 }
2131 let foo = Foo { 42 };
2132 foo.field;",
2133 "foo.rs",
2134 |metric| {
2135 insta::assert_json_snapshot!(
2137 metric.loc,
2138 @r#"
2139 {
2140 "sloc": 5,
2141 "ploc": 5,
2142 "lloc": 2,
2143 "cloc": 0,
2144 "blank": 0,
2145 "sloc_average": 5.0,
2146 "ploc_average": 5.0,
2147 "lloc_average": 2.0,
2148 "cloc_average": 0.0,
2149 "blank_average": 0.0,
2150 "sloc_min": 5,
2151 "sloc_max": 5,
2152 "cloc_min": 0,
2153 "cloc_max": 0,
2154 "ploc_min": 5,
2155 "ploc_max": 5,
2156 "lloc_min": 2,
2157 "lloc_max": 2,
2158 "blank_min": 0,
2159 "blank_max": 0
2160 }
2161 "#
2162 );
2163 },
2164 );
2165 }
2166
2167 #[test]
2168 fn rust_no_parenthesized_expression_lloc() {
2169 check_metrics::<RustParser>("let a = (42 + 0);", "foo.rs", |metric| {
2170 insta::assert_json_snapshot!(
2172 metric.loc,
2173 @r#"
2174 {
2175 "sloc": 1,
2176 "ploc": 1,
2177 "lloc": 1,
2178 "cloc": 0,
2179 "blank": 0,
2180 "sloc_average": 1.0,
2181 "ploc_average": 1.0,
2182 "lloc_average": 1.0,
2183 "cloc_average": 0.0,
2184 "blank_average": 0.0,
2185 "sloc_min": 1,
2186 "sloc_max": 1,
2187 "cloc_min": 0,
2188 "cloc_max": 0,
2189 "ploc_min": 1,
2190 "ploc_max": 1,
2191 "lloc_min": 1,
2192 "lloc_max": 1,
2193 "blank_min": 0,
2194 "blank_max": 0
2195 }
2196 "#
2197 );
2198 });
2199 }
2200
2201 #[test]
2202 fn rust_no_array_expression_lloc() {
2203 check_metrics::<RustParser>("let a = [0; 42];", "foo.rs", |metric| {
2204 insta::assert_json_snapshot!(
2206 metric.loc,
2207 @r#"
2208 {
2209 "sloc": 1,
2210 "ploc": 1,
2211 "lloc": 1,
2212 "cloc": 0,
2213 "blank": 0,
2214 "sloc_average": 1.0,
2215 "ploc_average": 1.0,
2216 "lloc_average": 1.0,
2217 "cloc_average": 0.0,
2218 "blank_average": 0.0,
2219 "sloc_min": 1,
2220 "sloc_max": 1,
2221 "cloc_min": 0,
2222 "cloc_max": 0,
2223 "ploc_min": 1,
2224 "ploc_max": 1,
2225 "lloc_min": 1,
2226 "lloc_max": 1,
2227 "blank_min": 0,
2228 "blank_max": 0
2229 }
2230 "#
2231 );
2232 });
2233 }
2234
2235 #[test]
2236 fn rust_no_tuple_expression_lloc() {
2237 check_metrics::<RustParser>("let a = (0, 42);", "foo.rs", |metric| {
2238 insta::assert_json_snapshot!(
2240 metric.loc,
2241 @r#"
2242 {
2243 "sloc": 1,
2244 "ploc": 1,
2245 "lloc": 1,
2246 "cloc": 0,
2247 "blank": 0,
2248 "sloc_average": 1.0,
2249 "ploc_average": 1.0,
2250 "lloc_average": 1.0,
2251 "cloc_average": 0.0,
2252 "blank_average": 0.0,
2253 "sloc_min": 1,
2254 "sloc_max": 1,
2255 "cloc_min": 0,
2256 "cloc_max": 0,
2257 "ploc_min": 1,
2258 "ploc_max": 1,
2259 "lloc_min": 1,
2260 "lloc_max": 1,
2261 "blank_min": 0,
2262 "blank_max": 0
2263 }
2264 "#
2265 );
2266 });
2267 }
2268
2269 #[test]
2270 fn rust_no_unit_expression_lloc() {
2271 check_metrics::<RustParser>("let a = ();", "foo.rs", |metric| {
2272 insta::assert_json_snapshot!(
2274 metric.loc,
2275 @r#"
2276 {
2277 "sloc": 1,
2278 "ploc": 1,
2279 "lloc": 1,
2280 "cloc": 0,
2281 "blank": 0,
2282 "sloc_average": 1.0,
2283 "ploc_average": 1.0,
2284 "lloc_average": 1.0,
2285 "cloc_average": 0.0,
2286 "blank_average": 0.0,
2287 "sloc_min": 1,
2288 "sloc_max": 1,
2289 "cloc_min": 0,
2290 "cloc_max": 0,
2291 "ploc_min": 1,
2292 "ploc_max": 1,
2293 "lloc_min": 1,
2294 "lloc_max": 1,
2295 "blank_min": 0,
2296 "blank_max": 0
2297 }
2298 "#
2299 );
2300 });
2301 }
2302
2303 #[test]
2304 fn rust_call_function_lloc() {
2305 check_metrics::<RustParser>(
2306 "let a = foo(); // +1
2307 foo(); // +1
2308 k!(foo()); // +1",
2309 "foo.rs",
2310 |metric| {
2311 insta::assert_json_snapshot!(
2313 metric.loc,
2314 @r#"
2315 {
2316 "sloc": 3,
2317 "ploc": 3,
2318 "lloc": 3,
2319 "cloc": 3,
2320 "blank": 0,
2321 "sloc_average": 3.0,
2322 "ploc_average": 3.0,
2323 "lloc_average": 3.0,
2324 "cloc_average": 3.0,
2325 "blank_average": 0.0,
2326 "sloc_min": 3,
2327 "sloc_max": 3,
2328 "cloc_min": 3,
2329 "cloc_max": 3,
2330 "ploc_min": 3,
2331 "ploc_max": 3,
2332 "lloc_min": 3,
2333 "lloc_max": 3,
2334 "blank_min": 0,
2335 "blank_max": 0
2336 }
2337 "#
2338 );
2339 },
2340 );
2341 }
2342
2343 #[test]
2344 fn rust_macro_invocation_lloc() {
2345 check_metrics::<RustParser>(
2346 "let a = foo!(); // +1
2347 foo!(); // +1
2348 k(foo!()); // +1",
2349 "foo.rs",
2350 |metric| {
2351 insta::assert_json_snapshot!(
2353 metric.loc,
2354 @r#"
2355 {
2356 "sloc": 3,
2357 "ploc": 3,
2358 "lloc": 3,
2359 "cloc": 3,
2360 "blank": 0,
2361 "sloc_average": 3.0,
2362 "ploc_average": 3.0,
2363 "lloc_average": 3.0,
2364 "cloc_average": 3.0,
2365 "blank_average": 0.0,
2366 "sloc_min": 3,
2367 "sloc_max": 3,
2368 "cloc_min": 3,
2369 "cloc_max": 3,
2370 "ploc_min": 3,
2371 "ploc_max": 3,
2372 "lloc_min": 3,
2373 "lloc_max": 3,
2374 "blank_min": 0,
2375 "blank_max": 0
2376 }
2377 "#
2378 );
2379 },
2380 );
2381 }
2382
2383 #[test]
2384 fn rust_function_in_loop_lloc() {
2385 check_metrics::<RustParser>(
2386 "for (a, b) in c.iter().enumerate() {} // +1
2387 while (a, b) in c.iter().enumerate() {} // +1
2388 while let Some(a) = c.strip_prefix(\"hi\") {} // +1",
2389 "foo.rs",
2390 |metric| {
2391 insta::assert_json_snapshot!(
2393 metric.loc,
2394 @r#"
2395 {
2396 "sloc": 3,
2397 "ploc": 3,
2398 "lloc": 3,
2399 "cloc": 3,
2400 "blank": 0,
2401 "sloc_average": 3.0,
2402 "ploc_average": 3.0,
2403 "lloc_average": 3.0,
2404 "cloc_average": 3.0,
2405 "blank_average": 0.0,
2406 "sloc_min": 3,
2407 "sloc_max": 3,
2408 "cloc_min": 3,
2409 "cloc_max": 3,
2410 "ploc_min": 3,
2411 "ploc_max": 3,
2412 "lloc_min": 3,
2413 "lloc_max": 3,
2414 "blank_min": 0,
2415 "blank_max": 0
2416 }
2417 "#
2418 );
2419 },
2420 );
2421 }
2422
2423 #[test]
2424 fn rust_function_in_if_lloc() {
2425 check_metrics::<RustParser>(
2426 "if foo() {} // +1
2427 if let Some(a) = foo() {} // +1",
2428 "foo.rs",
2429 |metric| {
2430 insta::assert_json_snapshot!(
2432 metric.loc,
2433 @r#"
2434 {
2435 "sloc": 2,
2436 "ploc": 2,
2437 "lloc": 2,
2438 "cloc": 2,
2439 "blank": 0,
2440 "sloc_average": 2.0,
2441 "ploc_average": 2.0,
2442 "lloc_average": 2.0,
2443 "cloc_average": 2.0,
2444 "blank_average": 0.0,
2445 "sloc_min": 2,
2446 "sloc_max": 2,
2447 "cloc_min": 2,
2448 "cloc_max": 2,
2449 "ploc_min": 2,
2450 "ploc_max": 2,
2451 "lloc_min": 2,
2452 "lloc_max": 2,
2453 "blank_min": 0,
2454 "blank_max": 0
2455 }
2456 "#
2457 );
2458 },
2459 );
2460 }
2461
2462 #[test]
2463 fn rust_function_in_return_lloc() {
2464 check_metrics::<RustParser>(
2465 "return foo();
2466 await foo();",
2467 "foo.rs",
2468 |metric| {
2469 insta::assert_json_snapshot!(
2471 metric.loc,
2472 @r#"
2473 {
2474 "sloc": 2,
2475 "ploc": 2,
2476 "lloc": 2,
2477 "cloc": 0,
2478 "blank": 0,
2479 "sloc_average": 2.0,
2480 "ploc_average": 2.0,
2481 "lloc_average": 2.0,
2482 "cloc_average": 0.0,
2483 "blank_average": 0.0,
2484 "sloc_min": 2,
2485 "sloc_max": 2,
2486 "cloc_min": 0,
2487 "cloc_max": 0,
2488 "ploc_min": 2,
2489 "ploc_max": 2,
2490 "lloc_min": 2,
2491 "lloc_max": 2,
2492 "blank_min": 0,
2493 "blank_max": 0
2494 }
2495 "#
2496 );
2497 },
2498 );
2499 }
2500
2501 #[test]
2502 fn rust_closure_expression_lloc() {
2503 check_metrics::<RustParser>(
2504 "let a = |i: i32| -> i32 { i + 1 }; // +1
2505 a(42); // +1
2506 k(b.iter().map(|n| n.parse.ok().unwrap_or(42))); // +1",
2507 "foo.rs",
2508 |metric| {
2509 insta::assert_json_snapshot!(
2511 metric.loc,
2512 @r#"
2513 {
2514 "sloc": 3,
2515 "ploc": 3,
2516 "lloc": 3,
2517 "cloc": 3,
2518 "blank": 0,
2519 "sloc_average": 1.0,
2520 "ploc_average": 1.0,
2521 "lloc_average": 1.0,
2522 "cloc_average": 1.0,
2523 "blank_average": 0.0,
2524 "sloc_min": 1,
2525 "sloc_max": 3,
2526 "cloc_min": 0,
2527 "cloc_max": 3,
2528 "ploc_min": 1,
2529 "ploc_max": 3,
2530 "lloc_min": 0,
2531 "lloc_max": 3,
2532 "blank_min": 0,
2533 "blank_max": 0
2534 }
2535 "#
2536 );
2537 },
2538 );
2539 }
2540
2541 #[test]
2542 fn python_general_loc() {
2543 check_metrics::<PythonParser>(
2544 "def func(a,
2545 b,
2546 c):
2547 print(a)
2548 print(b)
2549 print(c)",
2550 "foo.py",
2551 |metric| {
2552 insta::assert_json_snapshot!(
2554 metric.loc,
2555 @r#"
2556 {
2557 "sloc": 6,
2558 "ploc": 6,
2559 "lloc": 3,
2560 "cloc": 0,
2561 "blank": 0,
2562 "sloc_average": 3.0,
2563 "ploc_average": 3.0,
2564 "lloc_average": 1.5,
2565 "cloc_average": 0.0,
2566 "blank_average": 0.0,
2567 "sloc_min": 6,
2568 "sloc_max": 6,
2569 "cloc_min": 0,
2570 "cloc_max": 0,
2571 "ploc_min": 6,
2572 "ploc_max": 6,
2573 "lloc_min": 3,
2574 "lloc_max": 3,
2575 "blank_min": 0,
2576 "blank_max": 0
2577 }
2578 "#
2579 );
2580 },
2581 );
2582 }
2583
2584 #[test]
2585 fn python_real_loc() {
2586 check_metrics::<PythonParser>(
2587 "def web_socket_transfer_data(request):
2588 while True:
2589 line = request.ws_stream.receive_message()
2590 if line is None:
2591 return
2592 code, reason = line.split(' ', 1)
2593 if code is None or reason is None:
2594 return
2595 request.ws_stream.close_connection(int(code), reason)
2596 # close_connection() initiates closing handshake. It validates code
2597 # and reason. If you want to send a broken close frame for a test,
2598 # following code will be useful.
2599 # > data = struct.pack('!H', int(code)) + reason.encode('UTF-8')
2600 # > request.connection.write(stream.create_close_frame(data))
2601 # > # Suppress to re-respond client responding close frame.
2602 # > raise Exception(\"customized server initiated closing handshake\")",
2603 "foo.py",
2604 |metric| {
2605 insta::assert_json_snapshot!(
2607 metric.loc,
2608 @r#"
2609 {
2610 "sloc": 16,
2611 "ploc": 9,
2612 "lloc": 8,
2613 "cloc": 7,
2614 "blank": 0,
2615 "sloc_average": 8.0,
2616 "ploc_average": 4.5,
2617 "lloc_average": 4.0,
2618 "cloc_average": 3.5,
2619 "blank_average": 0.0,
2620 "sloc_min": 16,
2621 "sloc_max": 16,
2622 "cloc_min": 7,
2623 "cloc_max": 7,
2624 "ploc_min": 9,
2625 "ploc_max": 9,
2626 "lloc_min": 8,
2627 "lloc_max": 8,
2628 "blank_min": 0,
2629 "blank_max": 0
2630 }
2631 "#
2632 );
2633 },
2634 );
2635 }
2636
2637 #[test]
2638 fn javascript_real_loc() {
2639 check_metrics::<JavascriptParser>(
2640 "assert.throws(Test262Error, function() {
2641 for (let { poisoned: x = ++initEvalCount } = poisonedProperty; ; ) {
2642 return;
2643 }
2644 });",
2645 "foo.js",
2646 |metric| {
2647 insta::assert_json_snapshot!(
2649 metric.loc,
2650 @r#"
2651 {
2652 "sloc": 5,
2653 "ploc": 5,
2654 "lloc": 4,
2655 "cloc": 0,
2656 "blank": 0,
2657 "sloc_average": 2.5,
2658 "ploc_average": 2.5,
2659 "lloc_average": 2.0,
2660 "cloc_average": 0.0,
2661 "blank_average": 0.0,
2662 "sloc_min": 5,
2663 "sloc_max": 5,
2664 "cloc_min": 0,
2665 "cloc_max": 0,
2666 "ploc_min": 5,
2667 "ploc_max": 5,
2668 "lloc_min": 3,
2669 "lloc_max": 4,
2670 "blank_min": 0,
2671 "blank_max": 0
2672 }
2673 "#
2674 );
2675 },
2676 );
2677 }
2678
2679 #[test]
2680 fn mozjs_real_loc() {
2681 check_metrics::<MozjsParser>(
2682 "assert.throws(Test262Error, function() {
2683 for (let { poisoned: x = ++initEvalCount } = poisonedProperty; ; ) {
2684 return;
2685 }
2686 });",
2687 "foo.js",
2688 |metric| {
2689 insta::assert_json_snapshot!(
2691 metric.loc,
2692 @r#"
2693 {
2694 "sloc": 5,
2695 "ploc": 5,
2696 "lloc": 4,
2697 "cloc": 0,
2698 "blank": 0,
2699 "sloc_average": 2.5,
2700 "ploc_average": 2.5,
2701 "lloc_average": 2.0,
2702 "cloc_average": 0.0,
2703 "blank_average": 0.0,
2704 "sloc_min": 5,
2705 "sloc_max": 5,
2706 "cloc_min": 0,
2707 "cloc_max": 0,
2708 "ploc_min": 5,
2709 "ploc_max": 5,
2710 "lloc_min": 3,
2711 "lloc_max": 4,
2712 "blank_min": 0,
2713 "blank_max": 0
2714 }
2715 "#
2716 );
2717 },
2718 );
2719 }
2720
2721 #[test]
2722 fn mozjs_blank_and_comment_loc() {
2723 check_metrics::<MozjsParser>(
2724 "// a comment
2725 function f() {
2726
2727 var x = 1;
2728
2729 }",
2730 "foo.js",
2731 |metric| {
2732 insta::assert_json_snapshot!(
2733 metric.loc,
2734 @r#"
2735 {
2736 "sloc": 6,
2737 "ploc": 3,
2738 "lloc": 0,
2739 "cloc": 1,
2740 "blank": 2,
2741 "sloc_average": 3.0,
2742 "ploc_average": 1.5,
2743 "lloc_average": 0.0,
2744 "cloc_average": 0.5,
2745 "blank_average": 1.0,
2746 "sloc_min": 5,
2747 "sloc_max": 6,
2748 "cloc_min": 0,
2749 "cloc_max": 1,
2750 "ploc_min": 3,
2751 "ploc_max": 3,
2752 "lloc_min": 0,
2753 "lloc_max": 0,
2754 "blank_min": 2,
2755 "blank_max": 2
2756 }
2757 "#
2758 );
2759 },
2760 );
2761 }
2762
2763 #[test]
2764 fn cpp_namespace_loc() {
2765 check_metrics::<CppParser>(
2766 "namespace mozilla::dom::quota {} // namespace mozilla::dom::quota",
2767 "foo.cpp",
2768 |metric| {
2769 insta::assert_json_snapshot!(
2771 metric.loc,
2772 @r#"
2773 {
2774 "sloc": 1,
2775 "ploc": 1,
2776 "lloc": 0,
2777 "cloc": 1,
2778 "blank": 0,
2779 "sloc_average": 0.5,
2780 "ploc_average": 0.5,
2781 "lloc_average": 0.0,
2782 "cloc_average": 0.5,
2783 "blank_average": 0.0,
2784 "sloc_min": 1,
2785 "sloc_max": 1,
2786 "cloc_min": 0,
2787 "cloc_max": 1,
2788 "ploc_min": 1,
2789 "ploc_max": 1,
2790 "lloc_min": 0,
2791 "lloc_max": 0,
2792 "blank_min": 0,
2793 "blank_max": 0
2794 }
2795 "#
2796 );
2797 },
2798 );
2799 }
2800
2801 #[test]
2802 fn java_comments() {
2803 check_metrics::<JavaParser>(
2804 "for (int i = 0; i < 100; i++) { \
2805 // Print hello
2806 System.out.println(\"hello\"); \
2807 // Print world
2808 System.out.println(\"hello\"); \
2809 }",
2810 "foo.java",
2811 |metric| {
2812 insta::assert_json_snapshot!(
2814 metric.loc,
2815 @r#"
2816 {
2817 "sloc": 3,
2818 "ploc": 3,
2819 "lloc": 3,
2820 "cloc": 2,
2821 "blank": 0,
2822 "sloc_average": 3.0,
2823 "ploc_average": 3.0,
2824 "lloc_average": 3.0,
2825 "cloc_average": 2.0,
2826 "blank_average": 0.0,
2827 "sloc_min": 3,
2828 "sloc_max": 3,
2829 "cloc_min": 2,
2830 "cloc_max": 2,
2831 "ploc_min": 3,
2832 "ploc_max": 3,
2833 "lloc_min": 3,
2834 "lloc_max": 3,
2835 "blank_min": 0,
2836 "blank_max": 0
2837 }
2838 "#
2839 );
2840 },
2841 );
2842 }
2843
2844 #[test]
2845 fn java_blank() {
2846 check_metrics::<JavaParser>(
2847 "int x = 1;
2848
2849
2850 int y = 2;",
2851 "foo.java",
2852 |metric| {
2853 insta::assert_json_snapshot!(
2855 metric.loc,
2856 @r#"
2857 {
2858 "sloc": 4,
2859 "ploc": 2,
2860 "lloc": 2,
2861 "cloc": 0,
2862 "blank": 2,
2863 "sloc_average": 4.0,
2864 "ploc_average": 2.0,
2865 "lloc_average": 2.0,
2866 "cloc_average": 0.0,
2867 "blank_average": 2.0,
2868 "sloc_min": 4,
2869 "sloc_max": 4,
2870 "cloc_min": 0,
2871 "cloc_max": 0,
2872 "ploc_min": 2,
2873 "ploc_max": 2,
2874 "lloc_min": 2,
2875 "lloc_max": 2,
2876 "blank_min": 2,
2877 "blank_max": 2
2878 }
2879 "#
2880 );
2881 },
2882 );
2883 }
2884
2885 #[test]
2886 fn java_sloc() {
2887 check_metrics::<JavaParser>(
2888 "for (int i = 0; i < 100; i++) {
2889 System.out.println(i);
2890 }",
2891 "foo.java",
2892 |metric| {
2893 insta::assert_json_snapshot!(
2895 metric.loc,
2896 @r#"
2897 {
2898 "sloc": 3,
2899 "ploc": 3,
2900 "lloc": 2,
2901 "cloc": 0,
2902 "blank": 0,
2903 "sloc_average": 3.0,
2904 "ploc_average": 3.0,
2905 "lloc_average": 2.0,
2906 "cloc_average": 0.0,
2907 "blank_average": 0.0,
2908 "sloc_min": 3,
2909 "sloc_max": 3,
2910 "cloc_min": 0,
2911 "cloc_max": 0,
2912 "ploc_min": 3,
2913 "ploc_max": 3,
2914 "lloc_min": 2,
2915 "lloc_max": 2,
2916 "blank_min": 0,
2917 "blank_max": 0
2918 }
2919 "#
2920 );
2921 },
2922 );
2923 }
2924
2925 #[test]
2926 fn java_module_sloc() {
2927 check_metrics::<JavaParser>(
2928 "module helloworld{
2929 exports com.test;
2930 }",
2931 "foo.java",
2932 |metric| {
2933 insta::assert_json_snapshot!(
2935 metric.loc,
2936 @r#"
2937 {
2938 "sloc": 3,
2939 "ploc": 3,
2940 "lloc": 0,
2941 "cloc": 0,
2942 "blank": 0,
2943 "sloc_average": 3.0,
2944 "ploc_average": 3.0,
2945 "lloc_average": 0.0,
2946 "cloc_average": 0.0,
2947 "blank_average": 0.0,
2948 "sloc_min": 3,
2949 "sloc_max": 3,
2950 "cloc_min": 0,
2951 "cloc_max": 0,
2952 "ploc_min": 3,
2953 "ploc_max": 3,
2954 "lloc_min": 0,
2955 "lloc_max": 0,
2956 "blank_min": 0,
2957 "blank_max": 0
2958 }
2959 "#
2960 );
2961 },
2962 );
2963 }
2964
2965 #[test]
2966 fn java_single_ploc() {
2967 check_metrics::<JavaParser>("int x = 1;", "foo.java", |metric| {
2968 insta::assert_json_snapshot!(
2970 metric.loc,
2971 @r#"
2972 {
2973 "sloc": 1,
2974 "ploc": 1,
2975 "lloc": 1,
2976 "cloc": 0,
2977 "blank": 0,
2978 "sloc_average": 1.0,
2979 "ploc_average": 1.0,
2980 "lloc_average": 1.0,
2981 "cloc_average": 0.0,
2982 "blank_average": 0.0,
2983 "sloc_min": 1,
2984 "sloc_max": 1,
2985 "cloc_min": 0,
2986 "cloc_max": 0,
2987 "ploc_min": 1,
2988 "ploc_max": 1,
2989 "lloc_min": 1,
2990 "lloc_max": 1,
2991 "blank_min": 0,
2992 "blank_max": 0
2993 }
2994 "#
2995 );
2996 });
2997 }
2998
2999 #[test]
3000 fn java_simple_ploc() {
3001 check_metrics::<JavaParser>(
3002 "for (int i = 0; i < 100; i = i++) {
3003 System.out.println(i);
3004 }",
3005 "foo.java",
3006 |metric| {
3007 insta::assert_json_snapshot!(
3009 metric.loc,
3010 @r#"
3011 {
3012 "sloc": 3,
3013 "ploc": 3,
3014 "lloc": 2,
3015 "cloc": 0,
3016 "blank": 0,
3017 "sloc_average": 3.0,
3018 "ploc_average": 3.0,
3019 "lloc_average": 2.0,
3020 "cloc_average": 0.0,
3021 "blank_average": 0.0,
3022 "sloc_min": 3,
3023 "sloc_max": 3,
3024 "cloc_min": 0,
3025 "cloc_max": 0,
3026 "ploc_min": 3,
3027 "ploc_max": 3,
3028 "lloc_min": 2,
3029 "lloc_max": 2,
3030 "blank_min": 0,
3031 "blank_max": 0
3032 }
3033 "#
3034 );
3035 },
3036 );
3037 }
3038
3039 #[test]
3040 fn java_multi_ploc() {
3041 check_metrics::<JavaParser>(
3042 "int x = 1;
3043 for (int i = 0; i < 100; i++) {
3044 System.out.println(i);
3045 }",
3046 "foo.java",
3047 |metric| {
3048 insta::assert_json_snapshot!(
3050 metric.loc,
3051 @r#"
3052 {
3053 "sloc": 4,
3054 "ploc": 4,
3055 "lloc": 3,
3056 "cloc": 0,
3057 "blank": 0,
3058 "sloc_average": 4.0,
3059 "ploc_average": 4.0,
3060 "lloc_average": 3.0,
3061 "cloc_average": 0.0,
3062 "blank_average": 0.0,
3063 "sloc_min": 4,
3064 "sloc_max": 4,
3065 "cloc_min": 0,
3066 "cloc_max": 0,
3067 "ploc_min": 4,
3068 "ploc_max": 4,
3069 "lloc_min": 3,
3070 "lloc_max": 3,
3071 "blank_min": 0,
3072 "blank_max": 0
3073 }
3074 "#
3075 );
3076 },
3077 );
3078 }
3079
3080 #[test]
3081 fn java_single_statement_lloc() {
3082 check_metrics::<JavaParser>("int max = 10;", "foo.java", |metric| {
3083 insta::assert_json_snapshot!(
3085 metric.loc,
3086 @r#"
3087 {
3088 "sloc": 1,
3089 "ploc": 1,
3090 "lloc": 1,
3091 "cloc": 0,
3092 "blank": 0,
3093 "sloc_average": 1.0,
3094 "ploc_average": 1.0,
3095 "lloc_average": 1.0,
3096 "cloc_average": 0.0,
3097 "blank_average": 0.0,
3098 "sloc_min": 1,
3099 "sloc_max": 1,
3100 "cloc_min": 0,
3101 "cloc_max": 0,
3102 "ploc_min": 1,
3103 "ploc_max": 1,
3104 "lloc_min": 1,
3105 "lloc_max": 1,
3106 "blank_min": 0,
3107 "blank_max": 0
3108 }
3109 "#
3110 );
3111 });
3112 }
3113
3114 #[test]
3115 fn java_for_lloc() {
3116 check_metrics::<JavaParser>(
3117 "for (int i = 0; i < 100; i++) { // + 1
3118 System.out.println(i); // + 1
3119 }",
3120 "foo.java",
3121 |metric| {
3122 insta::assert_json_snapshot!(
3124 metric.loc,
3125 @r#"
3126 {
3127 "sloc": 3,
3128 "ploc": 3,
3129 "lloc": 2,
3130 "cloc": 2,
3131 "blank": 0,
3132 "sloc_average": 3.0,
3133 "ploc_average": 3.0,
3134 "lloc_average": 2.0,
3135 "cloc_average": 2.0,
3136 "blank_average": 0.0,
3137 "sloc_min": 3,
3138 "sloc_max": 3,
3139 "cloc_min": 2,
3140 "cloc_max": 2,
3141 "ploc_min": 3,
3142 "ploc_max": 3,
3143 "lloc_min": 2,
3144 "lloc_max": 2,
3145 "blank_min": 0,
3146 "blank_max": 0
3147 }
3148 "#
3149 );
3150 },
3151 );
3152 }
3153
3154 #[test]
3155 fn java_foreach_lloc() {
3156 check_metrics::<JavaParser>(
3157 "
3158 int arr[]={12,13,14,44}; // +1
3159 for (int i:arr) { // +1
3160 System.out.println(i); // +1
3161 }",
3162 "foo.java",
3163 |metric| {
3164 insta::assert_json_snapshot!(
3166 metric.loc,
3167 @r#"
3168 {
3169 "sloc": 4,
3170 "ploc": 4,
3171 "lloc": 3,
3172 "cloc": 3,
3173 "blank": 0,
3174 "sloc_average": 4.0,
3175 "ploc_average": 4.0,
3176 "lloc_average": 3.0,
3177 "cloc_average": 3.0,
3178 "blank_average": 0.0,
3179 "sloc_min": 4,
3180 "sloc_max": 4,
3181 "cloc_min": 3,
3182 "cloc_max": 3,
3183 "ploc_min": 4,
3184 "ploc_max": 4,
3185 "lloc_min": 3,
3186 "lloc_max": 3,
3187 "blank_min": 0,
3188 "blank_max": 0
3189 }
3190 "#
3191 );
3192 },
3193 );
3194 }
3195
3196 #[test]
3197 fn java_while_lloc() {
3198 check_metrics::<JavaParser>(
3199 "
3200 int i=0; // +1
3201 while(i < 10) { // +1
3202 i++; // +1
3203 System.out.println(i); // +1
3204 }",
3205 "foo.java",
3206 |metric| {
3207 insta::assert_json_snapshot!(
3209 metric.loc,
3210 @r#"
3211 {
3212 "sloc": 5,
3213 "ploc": 5,
3214 "lloc": 4,
3215 "cloc": 4,
3216 "blank": 0,
3217 "sloc_average": 5.0,
3218 "ploc_average": 5.0,
3219 "lloc_average": 4.0,
3220 "cloc_average": 4.0,
3221 "blank_average": 0.0,
3222 "sloc_min": 5,
3223 "sloc_max": 5,
3224 "cloc_min": 4,
3225 "cloc_max": 4,
3226 "ploc_min": 5,
3227 "ploc_max": 5,
3228 "lloc_min": 4,
3229 "lloc_max": 4,
3230 "blank_min": 0,
3231 "blank_max": 0
3232 }
3233 "#
3234 );
3235 },
3236 );
3237 }
3238
3239 #[test]
3240 fn java_do_while_lloc() {
3241 check_metrics::<JavaParser>(
3242 "
3243 int i=0; // +1
3244 do { // +1
3245 i++; // +1
3246 System.out.println(i); // +1
3247 } while(i < 10)",
3248 "foo.java",
3249 |metric| {
3250 insta::assert_json_snapshot!(
3252 metric.loc,
3253 @r#"
3254 {
3255 "sloc": 5,
3256 "ploc": 5,
3257 "lloc": 4,
3258 "cloc": 4,
3259 "blank": 0,
3260 "sloc_average": 5.0,
3261 "ploc_average": 5.0,
3262 "lloc_average": 4.0,
3263 "cloc_average": 4.0,
3264 "blank_average": 0.0,
3265 "sloc_min": 5,
3266 "sloc_max": 5,
3267 "cloc_min": 4,
3268 "cloc_max": 4,
3269 "ploc_min": 5,
3270 "ploc_max": 5,
3271 "lloc_min": 4,
3272 "lloc_max": 4,
3273 "blank_min": 0,
3274 "blank_max": 0
3275 }
3276 "#
3277 );
3278 },
3279 );
3280 }
3281
3282 #[test]
3283 fn java_switch_lloc() {
3284 check_metrics::<JavaParser>(
3285 "switch(grade) { // +1
3286 case 'A' :
3287 System.out.println(\"Pass with distinction\"); // +1
3288 break; // +1
3289 case 'B' :
3290 case 'C' :
3291 System.out.println(\"Pass\"); // +1
3292 break; // +1
3293 case 'D' :
3294 System.out.println(\"At risk\"); // +1
3295 case 'F' :
3296 System.out.println(\"Fail\"); // +1
3297 break; // +1
3298 default :
3299 System.out.println(\"Invalid grade\"); // +1
3300 }",
3301 "foo.java",
3302 |metric| {
3303 insta::assert_json_snapshot!(
3305 metric.loc,
3306 @r#"
3307 {
3308 "sloc": 16,
3309 "ploc": 16,
3310 "lloc": 9,
3311 "cloc": 9,
3312 "blank": 0,
3313 "sloc_average": 16.0,
3314 "ploc_average": 16.0,
3315 "lloc_average": 9.0,
3316 "cloc_average": 9.0,
3317 "blank_average": 0.0,
3318 "sloc_min": 16,
3319 "sloc_max": 16,
3320 "cloc_min": 9,
3321 "cloc_max": 9,
3322 "ploc_min": 16,
3323 "ploc_max": 16,
3324 "lloc_min": 9,
3325 "lloc_max": 9,
3326 "blank_min": 0,
3327 "blank_max": 0
3328 }
3329 "#
3330 );
3331 },
3332 );
3333 }
3334
3335 #[test]
3336 fn java_continue_lloc() {
3337 check_metrics::<JavaParser>(
3338 "int max = 10; // +1
3339
3340 for (int i = 0; i < max; i++) { // +1
3341 if(i % 2 == 0) { continue;} + 2
3342 System.out.println(i); // +1
3343 }",
3344 "foo.java",
3345 |metric| {
3346 insta::assert_json_snapshot!(
3348 metric.loc,
3349 @r#"
3350 {
3351 "sloc": 6,
3352 "ploc": 5,
3353 "lloc": 5,
3354 "cloc": 3,
3355 "blank": 1,
3356 "sloc_average": 6.0,
3357 "ploc_average": 5.0,
3358 "lloc_average": 5.0,
3359 "cloc_average": 3.0,
3360 "blank_average": 1.0,
3361 "sloc_min": 6,
3362 "sloc_max": 6,
3363 "cloc_min": 3,
3364 "cloc_max": 3,
3365 "ploc_min": 5,
3366 "ploc_max": 5,
3367 "lloc_min": 5,
3368 "lloc_max": 5,
3369 "blank_min": 1,
3370 "blank_max": 1
3371 }
3372 "#
3373 );
3374 },
3375 );
3376 }
3377
3378 #[test]
3379 fn java_try_lloc() {
3380 check_metrics::<JavaParser>(
3381 "try { // +1
3382 int[] myNumbers = {1, 2, 3}; // +1
3383 System.out.println(myNumbers[10]); // +1
3384 } catch (Exception e) {
3385 System.out.println(e.getMessage()); // +1
3386 throw e; // +1
3387 }",
3388 "foo.java",
3389 |metric| {
3390 insta::assert_json_snapshot!(
3392 metric.loc,
3393 @r#"
3394 {
3395 "sloc": 7,
3396 "ploc": 7,
3397 "lloc": 5,
3398 "cloc": 5,
3399 "blank": 0,
3400 "sloc_average": 7.0,
3401 "ploc_average": 7.0,
3402 "lloc_average": 5.0,
3403 "cloc_average": 5.0,
3404 "blank_average": 0.0,
3405 "sloc_min": 7,
3406 "sloc_max": 7,
3407 "cloc_min": 5,
3408 "cloc_max": 5,
3409 "ploc_min": 7,
3410 "ploc_max": 7,
3411 "lloc_min": 5,
3412 "lloc_max": 5,
3413 "blank_min": 0,
3414 "blank_max": 0
3415 }
3416 "#
3417 );
3418 },
3419 );
3420 }
3421
3422 #[test]
3423 fn java_class_loc() {
3424 check_metrics::<JavaParser>(
3425 "
3426 public class Person {
3427 private String name;
3428 public Person(String name){
3429 this.name = name; // +1
3430 }
3431 public String getName() {
3432 return name; // +1
3433 }
3434 }",
3435 "foo.java",
3436 |metric| {
3437 insta::assert_json_snapshot!(
3439 metric.loc,
3440 @r#"
3441 {
3442 "sloc": 9,
3443 "ploc": 9,
3444 "lloc": 2,
3445 "cloc": 2,
3446 "blank": 0,
3447 "sloc_average": 2.25,
3448 "ploc_average": 2.25,
3449 "lloc_average": 0.5,
3450 "cloc_average": 0.5,
3451 "blank_average": 0.0,
3452 "sloc_min": 3,
3453 "sloc_max": 9,
3454 "cloc_min": 1,
3455 "cloc_max": 2,
3456 "ploc_min": 3,
3457 "ploc_max": 9,
3458 "lloc_min": 1,
3459 "lloc_max": 2,
3460 "blank_min": 0,
3461 "blank_max": 0
3462 }
3463 "#
3464 );
3465 },
3466 );
3467 }
3468
3469 #[test]
3470 fn java_expressions_lloc() {
3471 check_metrics::<JavaParser>(
3472 "int x = 10; // +1 local var declaration
3473 x=+89; // +1 expression statement
3474 int y = x * 2; // +1 local var declaration
3475 IntFunction double = (n) -> n*2; // +1 local var declaration
3476 int y2 = double(x); // +1 local var declaration
3477 System.out.println(\"double \" + x + \" = \" + y2); // +1 expression statement
3478 String message = (x % 2) == 0 ? \"Evenly done.\" : \"Oddly done.\"; // +1 local var declaration
3479 Object done = (Runnable) () -> { System.out.println(\"Done!\"); }; // +2 local var declaration + expression statement
3480 String s = \"string\"; // +1 local var declaration
3481 boolean isS = (s instanceof String); // +1 local var declaration
3482 done.run(); // +1 expression statement
3483 ",
3484 "foo.java",
3485 |metric| {
3486 insta::assert_json_snapshot!(
3488 metric.loc,
3489 @r#"
3490 {
3491 "sloc": 11,
3492 "ploc": 11,
3493 "lloc": 12,
3494 "cloc": 11,
3495 "blank": 0,
3496 "sloc_average": 11.0,
3497 "ploc_average": 11.0,
3498 "lloc_average": 12.0,
3499 "cloc_average": 11.0,
3500 "blank_average": 0.0,
3501 "sloc_min": 11,
3502 "sloc_max": 11,
3503 "cloc_min": 11,
3504 "cloc_max": 11,
3505 "ploc_min": 11,
3506 "ploc_max": 11,
3507 "lloc_min": 12,
3508 "lloc_max": 12,
3509 "blank_min": 0,
3510 "blank_max": 0
3511 }
3512 "#
3513 );
3514 },
3515 );
3516 }
3517
3518 #[test]
3519 fn java_statement_inline_loc() {
3520 check_metrics::<JavaParser>(
3521 "for (int i = 0; i < 100; i++) { System.out.println(\"hello\"); }",
3522 "foo.java",
3523 |metric| {
3524 insta::assert_json_snapshot!(
3526 metric.loc,
3527 @r#"
3528 {
3529 "sloc": 1,
3530 "ploc": 1,
3531 "lloc": 2,
3532 "cloc": 0,
3533 "blank": 0,
3534 "sloc_average": 1.0,
3535 "ploc_average": 1.0,
3536 "lloc_average": 2.0,
3537 "cloc_average": 0.0,
3538 "blank_average": 0.0,
3539 "sloc_min": 1,
3540 "sloc_max": 1,
3541 "cloc_min": 0,
3542 "cloc_max": 0,
3543 "ploc_min": 1,
3544 "ploc_max": 1,
3545 "lloc_min": 2,
3546 "lloc_max": 2,
3547 "blank_min": 0,
3548 "blank_max": 0
3549 }
3550 "#
3551 );
3552 },
3553 );
3554 }
3555
3556 #[test]
3557 fn java_general_loc() {
3558 check_metrics::<JavaParser>(
3559 "int max = 100;
3560
3561 /*
3562 Loop through and print
3563 from: 0
3564 to: max
3565 */
3566 for (int i = 0; i < max; i++) {
3567 // Print the value
3568 System.out.println(i);
3569 }",
3570 "foo.java",
3571 |metric| {
3572 insta::assert_json_snapshot!(
3574 metric.loc,
3575 @r#"
3576 {
3577 "sloc": 11,
3578 "ploc": 4,
3579 "lloc": 3,
3580 "cloc": 6,
3581 "blank": 1,
3582 "sloc_average": 11.0,
3583 "ploc_average": 4.0,
3584 "lloc_average": 3.0,
3585 "cloc_average": 6.0,
3586 "blank_average": 1.0,
3587 "sloc_min": 11,
3588 "sloc_max": 11,
3589 "cloc_min": 6,
3590 "cloc_max": 6,
3591 "ploc_min": 4,
3592 "ploc_max": 4,
3593 "lloc_min": 3,
3594 "lloc_max": 3,
3595 "blank_min": 1,
3596 "blank_max": 1
3597 }
3598 "#
3599 );
3600 },
3601 );
3602 }
3603
3604 #[test]
3605 fn java_main_class_loc() {
3606 check_metrics::<JavaParser>(
3607 "package com.company;
3608 /**
3609 * The HelloWorldApp class implements an application that
3610 * simply prints \"Hello World!\" to standard output.
3611 */
3612
3613 class HelloWorldApp {
3614 public void main(String[] args) {
3615 String message = args.length == 0 ? \"Hello empty world\" : \"Hello world\"; // +1 lloc : 1 var assignment
3616 System.out.println(message); // Display the string. +1 lloc
3617 }
3618 }",
3619 "foo.java",
3620 |metric| {
3621 insta::assert_json_snapshot!(
3623 metric.loc,
3624 @r#"
3625 {
3626 "sloc": 12,
3627 "ploc": 7,
3628 "lloc": 2,
3629 "cloc": 6,
3630 "blank": 1,
3631 "sloc_average": 4.0,
3632 "ploc_average": 2.3333333333333335,
3633 "lloc_average": 0.6666666666666666,
3634 "cloc_average": 2.0,
3635 "blank_average": 0.3333333333333333,
3636 "sloc_min": 4,
3637 "sloc_max": 12,
3638 "cloc_min": 2,
3639 "cloc_max": 6,
3640 "ploc_min": 4,
3641 "ploc_max": 7,
3642 "lloc_min": 2,
3643 "lloc_max": 2,
3644 "blank_min": 0,
3645 "blank_max": 1
3646 }
3647 "#
3648 );
3649 },
3650 );
3651 }
3652
3653 #[test]
3654 fn go_general_loc() {
3655 check_metrics::<GoParser>(
3656 "package main
3657
3658 // entrypoint
3659 func main() {
3660 /* loop body */
3661 for i := 0; i < 10; i++ {
3662 fmt.Println(i)
3663 }
3664 }",
3665 "foo.go",
3666 |metric| {
3667 insta::assert_json_snapshot!(
3672 metric.loc,
3673 @r#"
3674 {
3675 "sloc": 9,
3676 "ploc": 6,
3677 "lloc": 2,
3678 "cloc": 2,
3679 "blank": 1,
3680 "sloc_average": 4.5,
3681 "ploc_average": 3.0,
3682 "lloc_average": 1.0,
3683 "cloc_average": 1.0,
3684 "blank_average": 0.5,
3685 "sloc_min": 6,
3686 "sloc_max": 9,
3687 "cloc_min": 1,
3688 "cloc_max": 2,
3689 "ploc_min": 5,
3690 "ploc_max": 6,
3691 "lloc_min": 2,
3692 "lloc_max": 2,
3693 "blank_min": 0,
3694 "blank_max": 1
3695 }
3696 "#
3697 );
3698 },
3699 );
3700 }
3701
3702 #[test]
3703 fn go_for_clause_does_not_double_count_lloc() {
3704 check_metrics::<GoParser>(
3708 "package main
3709 func f(n int) int {
3710 for i := 0; i < n; i++ {
3711 return i
3712 }
3713 return 0
3714 }",
3715 "foo.go",
3716 |metric| {
3717 assert_eq!(metric.loc.lloc(), 3);
3720 },
3721 );
3722 }
3723
3724 #[test]
3725 fn go_blank() {
3726 check_metrics::<GoParser>(
3727 "package main
3728
3729 func foo() {
3730 x := 1
3731
3732 y := 2
3733 }",
3734 "foo.go",
3735 |metric| {
3736 insta::assert_json_snapshot!(
3739 metric.loc,
3740 @r#"
3741 {
3742 "sloc": 7,
3743 "ploc": 5,
3744 "lloc": 2,
3745 "cloc": 0,
3746 "blank": 2,
3747 "sloc_average": 3.5,
3748 "ploc_average": 2.5,
3749 "lloc_average": 1.0,
3750 "cloc_average": 0.0,
3751 "blank_average": 1.0,
3752 "sloc_min": 5,
3753 "sloc_max": 7,
3754 "cloc_min": 0,
3755 "cloc_max": 0,
3756 "ploc_min": 4,
3757 "ploc_max": 5,
3758 "lloc_min": 2,
3759 "lloc_max": 2,
3760 "blank_min": 1,
3761 "blank_max": 2
3762 }
3763 "#
3764 );
3765 },
3766 );
3767 }
3768
3769 #[test]
3770 fn go_cloc_line_comments() {
3771 check_metrics::<GoParser>(
3772 "package main
3773
3774 // helper adds two numbers.
3775 // It returns their sum.
3776 func add(a, b int) int {
3777 // compute the result
3778 return a + b
3779 }",
3780 "foo.go",
3781 |metric| {
3782 insta::assert_json_snapshot!(
3785 metric.loc,
3786 @r#"
3787 {
3788 "sloc": 8,
3789 "ploc": 4,
3790 "lloc": 1,
3791 "cloc": 3,
3792 "blank": 1,
3793 "sloc_average": 4.0,
3794 "ploc_average": 2.0,
3795 "lloc_average": 0.5,
3796 "cloc_average": 1.5,
3797 "blank_average": 0.5,
3798 "sloc_min": 4,
3799 "sloc_max": 8,
3800 "cloc_min": 1,
3801 "cloc_max": 3,
3802 "ploc_min": 3,
3803 "ploc_max": 4,
3804 "lloc_min": 1,
3805 "lloc_max": 1,
3806 "blank_min": 0,
3807 "blank_max": 1
3808 }
3809 "#
3810 );
3811 },
3812 );
3813 }
3814
3815 #[test]
3816 fn go_cloc_block_comments() {
3817 check_metrics::<GoParser>(
3818 "package main
3819
3820 /* block comment
3821 spanning two lines */
3822 func foo() {
3823 x := 1 /* inline block */
3824 }",
3825 "foo.go",
3826 |metric| {
3827 insta::assert_json_snapshot!(
3830 metric.loc,
3831 @r#"
3832 {
3833 "sloc": 7,
3834 "ploc": 4,
3835 "lloc": 1,
3836 "cloc": 3,
3837 "blank": 1,
3838 "sloc_average": 3.5,
3839 "ploc_average": 2.0,
3840 "lloc_average": 0.5,
3841 "cloc_average": 1.5,
3842 "blank_average": 0.5,
3843 "sloc_min": 3,
3844 "sloc_max": 7,
3845 "cloc_min": 1,
3846 "cloc_max": 3,
3847 "ploc_min": 3,
3848 "ploc_max": 4,
3849 "lloc_min": 1,
3850 "lloc_max": 1,
3851 "blank_min": 0,
3852 "blank_max": 1
3853 }
3854 "#
3855 );
3856 },
3857 );
3858 }
3859
3860 #[test]
3861 fn go_lloc_if_for_switch() {
3862 check_metrics::<GoParser>(
3863 "package main
3864
3865 func foo(n int) int {
3866 if n > 0 {
3867 for i := 0; i < n; i++ {
3868 switch i {
3869 }
3870 }
3871 }
3872 return n
3873 }",
3874 "foo.go",
3875 |metric| {
3876 insta::assert_json_snapshot!(
3879 metric.loc,
3880 @r#"
3881 {
3882 "sloc": 11,
3883 "ploc": 10,
3884 "lloc": 4,
3885 "cloc": 0,
3886 "blank": 1,
3887 "sloc_average": 5.5,
3888 "ploc_average": 5.0,
3889 "lloc_average": 2.0,
3890 "cloc_average": 0.0,
3891 "blank_average": 0.5,
3892 "sloc_min": 9,
3893 "sloc_max": 11,
3894 "cloc_min": 0,
3895 "cloc_max": 0,
3896 "ploc_min": 9,
3897 "ploc_max": 10,
3898 "lloc_min": 4,
3899 "lloc_max": 4,
3900 "blank_min": 0,
3901 "blank_max": 1
3902 }
3903 "#
3904 );
3905 },
3906 );
3907 }
3908
3909 #[test]
3910 fn go_lloc_go_defer() {
3911 check_metrics::<GoParser>(
3912 "package main
3913
3914 func foo() {
3915 go run()
3916 defer cleanup()
3917 }",
3918 "foo.go",
3919 |metric| {
3920 insta::assert_json_snapshot!(
3923 metric.loc,
3924 @r#"
3925 {
3926 "sloc": 6,
3927 "ploc": 5,
3928 "lloc": 2,
3929 "cloc": 0,
3930 "blank": 1,
3931 "sloc_average": 3.0,
3932 "ploc_average": 2.5,
3933 "lloc_average": 1.0,
3934 "cloc_average": 0.0,
3935 "blank_average": 0.5,
3936 "sloc_min": 4,
3937 "sloc_max": 6,
3938 "cloc_min": 0,
3939 "cloc_max": 0,
3940 "ploc_min": 4,
3941 "ploc_max": 5,
3942 "lloc_min": 2,
3943 "lloc_max": 2,
3944 "blank_min": 0,
3945 "blank_max": 1
3946 }
3947 "#
3948 );
3949 },
3950 );
3951 }
3952
3953 #[test]
3954 fn go_lloc_var_const_declarations() {
3955 check_metrics::<GoParser>(
3956 "package main
3957
3958 func foo() {
3959 var x int
3960 var y = 10
3961 const z = 42
3962 a := 3
3963 a = 4
3964 }",
3965 "foo.go",
3966 |metric| {
3967 insta::assert_json_snapshot!(
3971 metric.loc,
3972 @r#"
3973 {
3974 "sloc": 9,
3975 "ploc": 8,
3976 "lloc": 5,
3977 "cloc": 0,
3978 "blank": 1,
3979 "sloc_average": 4.5,
3980 "ploc_average": 4.0,
3981 "lloc_average": 2.5,
3982 "cloc_average": 0.0,
3983 "blank_average": 0.5,
3984 "sloc_min": 7,
3985 "sloc_max": 9,
3986 "cloc_min": 0,
3987 "cloc_max": 0,
3988 "ploc_min": 7,
3989 "ploc_max": 8,
3990 "lloc_min": 5,
3991 "lloc_max": 5,
3992 "blank_min": 0,
3993 "blank_max": 1
3994 }
3995 "#
3996 );
3997 },
3998 );
3999 }
4000
4001 #[test]
4002 fn go_lloc_select() {
4003 check_metrics::<GoParser>(
4004 "package main
4005
4006 func foo(ch chan int) {
4007 select {
4008 case v := <-ch:
4009 _ = v
4010 }
4011 }",
4012 "foo.go",
4013 |metric| {
4014 insta::assert_json_snapshot!(
4019 metric.loc,
4020 @r#"
4021 {
4022 "sloc": 8,
4023 "ploc": 7,
4024 "lloc": 2,
4025 "cloc": 0,
4026 "blank": 1,
4027 "sloc_average": 4.0,
4028 "ploc_average": 3.5,
4029 "lloc_average": 1.0,
4030 "cloc_average": 0.0,
4031 "blank_average": 0.5,
4032 "sloc_min": 6,
4033 "sloc_max": 8,
4034 "cloc_min": 0,
4035 "cloc_max": 0,
4036 "ploc_min": 6,
4037 "ploc_max": 7,
4038 "lloc_min": 2,
4039 "lloc_max": 2,
4040 "blank_min": 0,
4041 "blank_max": 1
4042 }
4043 "#
4044 );
4045 },
4046 );
4047 }
4048
4049 #[test]
4050 fn go_sloc_multiline_function() {
4051 check_metrics::<GoParser>(
4052 "package main
4053
4054 func add(
4055 a int,
4056 b int,
4057 ) int {
4058 return a + b
4059 }",
4060 "foo.go",
4061 |metric| {
4062 insta::assert_json_snapshot!(
4065 metric.loc,
4066 @r#"
4067 {
4068 "sloc": 8,
4069 "ploc": 7,
4070 "lloc": 1,
4071 "cloc": 0,
4072 "blank": 1,
4073 "sloc_average": 4.0,
4074 "ploc_average": 3.5,
4075 "lloc_average": 0.5,
4076 "cloc_average": 0.0,
4077 "blank_average": 0.5,
4078 "sloc_min": 6,
4079 "sloc_max": 8,
4080 "cloc_min": 0,
4081 "cloc_max": 0,
4082 "ploc_min": 6,
4083 "ploc_max": 7,
4084 "lloc_min": 1,
4085 "lloc_max": 1,
4086 "blank_min": 0,
4087 "blank_max": 1
4088 }
4089 "#
4090 );
4091 },
4092 );
4093 }
4094
4095 #[test]
4096 fn go_code_comment_same_line() {
4097 check_metrics::<GoParser>(
4098 "package main
4099
4100 func foo() {
4101 x := 1 // initialize x
4102 y := 2 // initialize y
4103 }",
4104 "foo.go",
4105 |metric| {
4106 insta::assert_json_snapshot!(
4111 metric.loc,
4112 @r#"
4113 {
4114 "sloc": 6,
4115 "ploc": 5,
4116 "lloc": 2,
4117 "cloc": 2,
4118 "blank": 1,
4119 "sloc_average": 3.0,
4120 "ploc_average": 2.5,
4121 "lloc_average": 1.0,
4122 "cloc_average": 1.0,
4123 "blank_average": 0.5,
4124 "sloc_min": 4,
4125 "sloc_max": 6,
4126 "cloc_min": 2,
4127 "cloc_max": 2,
4128 "ploc_min": 4,
4129 "ploc_max": 5,
4130 "lloc_min": 2,
4131 "lloc_max": 2,
4132 "blank_min": 0,
4133 "blank_max": 1
4134 }
4135 "#
4136 );
4137 },
4138 );
4139 }
4140
4141 #[test]
4142 fn perl_grammar_smoke() {
4143 assert_perl_parses_cleanly(
4149 "use strict;
4150use warnings;
4151
4152# line comment
4153
4154=pod
4155multi-line POD
4156=cut
4157
4158sub factorial {
4159 my ($n) = @_;
4160 return 1 if $n <= 1;
4161 return $n * factorial($n - 1);
4162}
4163
4164my @arr = (1, 2, 3);
4165my %hash = (a => 1, b => 2);
4166my $closure = sub { return $_[0] + 1; };
4167
4168for my $i (1..3) {
4169 if ($i % 2 == 0) {
4170 print \"even\\n\";
4171 } elsif ($i == 1) {
4172 print \"one\\n\";
4173 } else {
4174 print \"odd\\n\";
4175 }
4176}
4177
4178while ($x > 0) {
4179 last if $x == 0;
4180 $x--;
4181}
4182
4183unless ($done) {
4184 next;
4185}
4186
4187my $heredoc = <<END;
4188hello
4189END
4190",
4191 );
4192 }
4193
4194 #[test]
4195 fn perl_blank() {
4196 check_metrics::<PerlParser>(
4197 "
4198
4199my $a = 42;
4200
4201my $b = 43;
4202
4203",
4204 "foo.pl",
4205 |metric| {
4206 insta::assert_json_snapshot!(metric.loc, @r#"
4207 {
4208 "sloc": 3,
4209 "ploc": 2,
4210 "lloc": 2,
4211 "cloc": 0,
4212 "blank": 1,
4213 "sloc_average": 3.0,
4214 "ploc_average": 2.0,
4215 "lloc_average": 2.0,
4216 "cloc_average": 0.0,
4217 "blank_average": 1.0,
4218 "sloc_min": 3,
4219 "sloc_max": 3,
4220 "cloc_min": 0,
4221 "cloc_max": 0,
4222 "ploc_min": 2,
4223 "ploc_max": 2,
4224 "lloc_min": 2,
4225 "lloc_max": 2,
4226 "blank_min": 1,
4227 "blank_max": 1
4228 }
4229 "#);
4230 },
4231 );
4232 }
4233
4234 #[test]
4235 fn perl_no_zero_blank() {
4236 check_metrics::<PerlParser>(
4239 "my $a = 1;
4240my $b = 2;
4241
4242my $c = 3; # trailing
4243my $d = 4; # trailing
4244my $e = 5;",
4245 "foo.pl",
4246 |metric| {
4247 assert_eq!(metric.loc.sloc(), 6);
4248 assert_eq!(metric.loc.ploc(), 5);
4249 assert_eq!(metric.loc.cloc(), 2);
4250 assert_eq!(metric.loc.blank(), 1);
4251 insta::assert_json_snapshot!(metric.loc);
4252 },
4253 );
4254 }
4255
4256 #[test]
4257 fn perl_blank_zero_sanity() {
4258 check_metrics::<PerlParser>(
4261 "my $a = 1;
4262my $b = 2;",
4263 "foo.pl",
4264 |metric| {
4265 assert_eq!(metric.loc.sloc(), 2);
4266 assert_eq!(metric.loc.ploc(), 2);
4267 assert_eq!(metric.loc.lloc(), 2);
4268 assert_eq!(metric.loc.cloc(), 0);
4269 assert_eq!(metric.loc.blank(), 0);
4270 },
4271 );
4272 }
4273
4274 #[test]
4280 fn perl_cloc_line_comments() {
4281 check_metrics::<PerlParser>(
4282 "# top comment
4283my $a = 1; # trailing
4284my $b = 2;",
4285 "foo.pl",
4286 |metric| {
4287 insta::assert_json_snapshot!(metric.loc, @r#"
4288 {
4289 "sloc": 3,
4290 "ploc": 2,
4291 "lloc": 2,
4292 "cloc": 2,
4293 "blank": 0,
4294 "sloc_average": 3.0,
4295 "ploc_average": 2.0,
4296 "lloc_average": 2.0,
4297 "cloc_average": 2.0,
4298 "blank_average": 0.0,
4299 "sloc_min": 3,
4300 "sloc_max": 3,
4301 "cloc_min": 2,
4302 "cloc_max": 2,
4303 "ploc_min": 2,
4304 "ploc_max": 2,
4305 "lloc_min": 2,
4306 "lloc_max": 2,
4307 "blank_min": 0,
4308 "blank_max": 0
4309 }
4310 "#);
4311 },
4312 );
4313 }
4314
4315 #[test]
4316 fn perl_cloc_pod_block() {
4317 check_metrics::<PerlParser>(
4318 "my $x = 1;
4319=pod
4320multi-line
4321pod block
4322=cut
4323my $y = 2;",
4324 "foo.pl",
4325 |metric| {
4326 insta::assert_json_snapshot!(metric.loc, @r#"
4327 {
4328 "sloc": 6,
4329 "ploc": 2,
4330 "lloc": 2,
4331 "cloc": 4,
4332 "blank": 0,
4333 "sloc_average": 6.0,
4334 "ploc_average": 2.0,
4335 "lloc_average": 2.0,
4336 "cloc_average": 4.0,
4337 "blank_average": 0.0,
4338 "sloc_min": 6,
4339 "sloc_max": 6,
4340 "cloc_min": 4,
4341 "cloc_max": 4,
4342 "ploc_min": 2,
4343 "ploc_max": 2,
4344 "lloc_min": 2,
4345 "lloc_max": 2,
4346 "blank_min": 0,
4347 "blank_max": 0
4348 }
4349 "#);
4350 },
4351 );
4352 }
4353
4354 #[test]
4355 fn perl_lloc_simple_statements() {
4356 check_metrics::<PerlParser>(
4357 "my $a = 1;
4358my $b = 2;
4359my $c = 3;",
4360 "foo.pl",
4361 |metric| {
4362 insta::assert_json_snapshot!(metric.loc, @r#"
4363 {
4364 "sloc": 3,
4365 "ploc": 3,
4366 "lloc": 3,
4367 "cloc": 0,
4368 "blank": 0,
4369 "sloc_average": 3.0,
4370 "ploc_average": 3.0,
4371 "lloc_average": 3.0,
4372 "cloc_average": 0.0,
4373 "blank_average": 0.0,
4374 "sloc_min": 3,
4375 "sloc_max": 3,
4376 "cloc_min": 0,
4377 "cloc_max": 0,
4378 "ploc_min": 3,
4379 "ploc_max": 3,
4380 "lloc_min": 3,
4381 "lloc_max": 3,
4382 "blank_min": 0,
4383 "blank_max": 0
4384 }
4385 "#);
4386 },
4387 );
4388 }
4389
4390 #[test]
4391 fn perl_lloc_compound_statements() {
4392 check_metrics::<PerlParser>(
4393 "if ($x) {
4394 print 'a';
4395}
4396while ($n > 0) {
4397 $n--;
4398}",
4399 "foo.pl",
4400 |metric| {
4401 insta::assert_json_snapshot!(metric.loc, @r#"
4402 {
4403 "sloc": 6,
4404 "ploc": 6,
4405 "lloc": 4,
4406 "cloc": 0,
4407 "blank": 0,
4408 "sloc_average": 6.0,
4409 "ploc_average": 6.0,
4410 "lloc_average": 4.0,
4411 "cloc_average": 0.0,
4412 "blank_average": 0.0,
4413 "sloc_min": 6,
4414 "sloc_max": 6,
4415 "cloc_min": 0,
4416 "cloc_max": 0,
4417 "ploc_min": 6,
4418 "ploc_max": 6,
4419 "lloc_min": 4,
4420 "lloc_max": 4,
4421 "blank_min": 0,
4422 "blank_max": 0
4423 }
4424 "#);
4425 },
4426 );
4427 }
4428
4429 #[test]
4430 fn perl_lloc_postfix_form_counts_once() {
4431 check_metrics::<PerlParser>(
4435 "sub f {
4436 return 1 if $_[0];
4437}",
4438 "foo.pl",
4439 |metric| {
4440 assert_eq!(metric.loc.lloc(), 1);
4441 },
4442 );
4443 }
4444
4445 #[test]
4446 fn perl_lloc_use_statement() {
4447 check_metrics::<PerlParser>(
4448 "use strict;
4449use warnings;
4450my $x = 1;",
4451 "foo.pl",
4452 |metric| {
4453 insta::assert_json_snapshot!(metric.loc, @r#"
4454 {
4455 "sloc": 3,
4456 "ploc": 3,
4457 "lloc": 3,
4458 "cloc": 0,
4459 "blank": 0,
4460 "sloc_average": 3.0,
4461 "ploc_average": 3.0,
4462 "lloc_average": 3.0,
4463 "cloc_average": 0.0,
4464 "blank_average": 0.0,
4465 "sloc_min": 3,
4466 "sloc_max": 3,
4467 "cloc_min": 0,
4468 "cloc_max": 0,
4469 "ploc_min": 3,
4470 "ploc_max": 3,
4471 "lloc_min": 3,
4472 "lloc_max": 3,
4473 "blank_min": 0,
4474 "blank_max": 0
4475 }
4476 "#);
4477 },
4478 );
4479 }
4480
4481 #[test]
4482 fn perl_lloc_for_loop() {
4483 check_metrics::<PerlParser>(
4484 "for my $i (1..3) {
4485 print $i;
4486}",
4487 "foo.pl",
4488 |metric| {
4489 assert_eq!(metric.loc.lloc(), 2);
4491 },
4492 );
4493 }
4494
4495 #[test]
4496 fn perl_lloc_loop_control_statement() {
4497 check_metrics::<PerlParser>(
4498 "while (1) {
4499 last if $done;
4500}",
4501 "foo.pl",
4502 |metric| {
4503 assert_eq!(metric.loc.lloc(), 2);
4505 },
4506 );
4507 }
4508
4509 #[test]
4510 fn perl_lloc_no_double_count_inside_single_line_statement() {
4511 check_metrics::<PerlParser>(
4514 "sub f {
4515 print 'a' unless $_[0];
4516}",
4517 "foo.pl",
4518 |metric| {
4519 assert_eq!(metric.loc.lloc(), 1);
4520 },
4521 );
4522 }
4523
4524 #[test]
4525 fn perl_lloc_function_definition_not_counted() {
4526 check_metrics::<PerlParser>(
4529 "sub f {
4530 my $x = 1;
4531}",
4532 "foo.pl",
4533 |metric| {
4534 assert_eq!(metric.loc.lloc(), 1);
4535 },
4536 );
4537 }
4538
4539 #[test]
4540 fn perl_lloc_anonymous_function() {
4541 check_metrics::<PerlParser>("my $f = sub { return 1; };", "foo.pl", |metric| {
4545 assert_eq!(metric.loc.lloc(), 2);
4546 });
4547 }
4548
4549 #[test]
4550 fn perl_multiline_string_assignment_ploc() {
4551 check_metrics::<PerlParser>(
4558 "my $s = \"line1
4559line2
4560line3\";",
4561 "foo.pl",
4562 |metric| {
4563 assert_eq!(metric.loc.sloc(), 3);
4565 assert_eq!(metric.loc.ploc(), 3);
4566 assert_eq!(metric.loc.cloc(), 0);
4567 assert_eq!(metric.loc.blank(), 0);
4568 },
4569 );
4570 }
4571
4572 #[test]
4573 fn multiline_string_ploc_consistent_across_languages() {
4574 #[allow(clippy::needless_pass_by_value)]
4582 fn assert_three_code_rows(metric: crate::CodeMetrics) {
4583 assert_eq!(metric.loc.sloc(), 3);
4584 assert_eq!(metric.loc.ploc(), 3);
4585 assert_eq!(metric.loc.cloc(), 0);
4586 assert_eq!(metric.loc.blank(), 0);
4587 }
4588 check_metrics::<PythonParser>(
4589 "s = \"\"\"line1\nline2\nline3\"\"\"",
4590 "foo.py",
4591 assert_three_code_rows,
4592 );
4593 check_metrics::<PerlParser>(
4594 "my $s = \"line1\nline2\nline3\";",
4595 "foo.pl",
4596 assert_three_code_rows,
4597 );
4598 check_metrics::<RubyParser>(
4599 "s = \"line1\nline2\nline3\"",
4600 "foo.rb",
4601 assert_three_code_rows,
4602 );
4603 check_metrics::<GoParser>(
4610 "package p\n\nvar s = `line1\nline2\nline3`",
4611 "foo.go",
4612 |metric| {
4613 assert_eq!(metric.loc.sloc(), 5);
4616 assert_eq!(metric.loc.ploc(), 4);
4617 assert_eq!(metric.loc.cloc(), 0);
4618 assert_eq!(metric.loc.blank(), 1);
4619 },
4620 );
4621 check_metrics::<KotlinParser>(
4622 "val s = \"\"\"line1\nline2\nline3\"\"\"",
4623 "foo.kt",
4624 assert_three_code_rows,
4625 );
4626 check_metrics::<MozcppParser>(
4627 "const char* s = R\"(line1\nline2\nline3)\";",
4628 "foo.cpp",
4629 assert_three_code_rows,
4630 );
4631 }
4632
4633 #[test]
4634 fn perl_lloc_unless_until() {
4635 check_metrics::<PerlParser>(
4636 "unless ($x) {
4637 print 'a';
4638}
4639until ($n == 0) {
4640 $n--;
4641}",
4642 "foo.pl",
4643 |metric| {
4644 assert_eq!(metric.loc.lloc(), 4);
4647 },
4648 );
4649 }
4650
4651 #[test]
4652 fn perl_lloc_heredoc_body_not_counted() {
4653 check_metrics::<PerlParser>(
4656 "my $s = <<END;
4657line1
4658line2
4659END
4660my $x = 1;",
4661 "foo.pl",
4662 |metric| {
4663 assert_eq!(metric.loc.lloc(), 2);
4666 },
4667 );
4668 assert_perl_parses_cleanly(
4672 "my $s = <<END;
4673line1
4674line2
4675END
4676my $x = 1;",
4677 );
4678 }
4679
4680 #[test]
4681 fn perl_lloc_package_and_require() {
4682 check_metrics::<PerlParser>(
4683 "package Foo;
4684require 5.010;
4685my $x = 1;",
4686 "foo.pl",
4687 |metric| {
4688 insta::assert_json_snapshot!(metric.loc, @r#"
4689 {
4690 "sloc": 3,
4691 "ploc": 3,
4692 "lloc": 3,
4693 "cloc": 0,
4694 "blank": 0,
4695 "sloc_average": 3.0,
4696 "ploc_average": 3.0,
4697 "lloc_average": 3.0,
4698 "cloc_average": 0.0,
4699 "blank_average": 0.0,
4700 "sloc_min": 3,
4701 "sloc_max": 3,
4702 "cloc_min": 0,
4703 "cloc_max": 0,
4704 "ploc_min": 3,
4705 "ploc_max": 3,
4706 "lloc_min": 3,
4707 "lloc_max": 3,
4708 "blank_min": 0,
4709 "blank_max": 0
4710 }
4711 "#);
4712 },
4713 );
4714 }
4715
4716 #[test]
4717 fn lua_blank() {
4718 check_metrics::<LuaParser>(
4719 "local x = 1
4720
4721local y = 2",
4722 "foo.lua",
4723 |metric| {
4724 assert_eq!(metric.loc.sloc(), 3);
4725 assert_eq!(metric.loc.ploc(), 2);
4726 assert_eq!(metric.loc.lloc(), 2);
4727 assert_eq!(metric.loc.cloc(), 0);
4728 assert_eq!(metric.loc.blank(), 1);
4729 insta::assert_json_snapshot!(metric.loc);
4730 },
4731 );
4732 }
4733
4734 #[test]
4735 fn lua_no_zero_blank() {
4736 check_metrics::<LuaParser>(
4739 "local a = 1
4740local b = 2
4741
4742local c = 3 -- trailing
4743local d = 4 -- trailing
4744local e = 5",
4745 "foo.lua",
4746 |metric| {
4747 assert_eq!(metric.loc.sloc(), 6);
4748 assert_eq!(metric.loc.ploc(), 5);
4749 assert_eq!(metric.loc.cloc(), 2);
4750 assert_eq!(metric.loc.blank(), 1);
4751 insta::assert_json_snapshot!(metric.loc);
4752 },
4753 );
4754 }
4755
4756 #[test]
4757 fn lua_blank_zero_sanity() {
4758 check_metrics::<LuaParser>(
4761 "local x = 1
4762local y = 2",
4763 "foo.lua",
4764 |metric| {
4765 assert_eq!(metric.loc.sloc(), 2);
4766 assert_eq!(metric.loc.ploc(), 2);
4767 assert_eq!(metric.loc.lloc(), 2);
4768 assert_eq!(metric.loc.cloc(), 0);
4769 assert_eq!(metric.loc.blank(), 0);
4770 },
4771 );
4772 }
4773
4774 #[test]
4775 fn lua_cloc() {
4776 check_metrics::<LuaParser>(
4777 "-- single line comment
4778local x = 1
4779--[[
4780 block comment
4781 second line
4782]]",
4783 "foo.lua",
4784 |metric| {
4785 assert_eq!(metric.loc.sloc(), 6);
4786 assert_eq!(metric.loc.ploc(), 1);
4787 assert_eq!(metric.loc.lloc(), 1);
4788 assert_eq!(metric.loc.cloc(), 5);
4789 assert_eq!(metric.loc.blank(), 0);
4790 insta::assert_json_snapshot!(metric.loc);
4791 },
4792 );
4793 }
4794
4795 #[test]
4796 fn lua_lloc() {
4797 check_metrics::<LuaParser>(
4798 "local function f(x)
4799 if x > 0 then
4800 local y = x + 1
4801 return y
4802 end
4803 return 0
4804end",
4805 "foo.lua",
4806 |metric| {
4807 assert_eq!(metric.loc.sloc(), 7);
4808 assert_eq!(metric.loc.ploc(), 7);
4809 assert_eq!(metric.loc.lloc(), 5);
4810 assert_eq!(metric.loc.cloc(), 0);
4811 assert_eq!(metric.loc.blank(), 0);
4812 insta::assert_json_snapshot!(metric.loc);
4813 },
4814 );
4815 }
4816
4817 #[test]
4818 fn lua_no_string_lloc() {
4819 check_metrics::<LuaParser>(
4821 "local s = [[
4822 line one
4823 line two
4824]]",
4825 "foo.lua",
4826 |metric| {
4827 assert_eq!(metric.loc.sloc(), 4);
4832 assert_eq!(metric.loc.ploc(), 4);
4833 assert_eq!(metric.loc.lloc(), 1);
4834 assert_eq!(metric.loc.cloc(), 0);
4835 assert_eq!(metric.loc.blank(), 0);
4836 insta::assert_json_snapshot!(metric.loc);
4837 },
4838 );
4839 }
4840
4841 #[test]
4842 fn lua_no_functiondefinition_lloc() {
4843 check_metrics::<LuaParser>(
4846 "local f = function(x)
4847 return x + 1
4848end",
4849 "foo.lua",
4850 |metric| {
4851 assert_eq!(metric.loc.sloc(), 3);
4852 assert_eq!(metric.loc.ploc(), 3);
4853 assert_eq!(metric.loc.lloc(), 2);
4854 assert_eq!(metric.loc.cloc(), 0);
4855 assert_eq!(metric.loc.blank(), 0);
4856 insta::assert_json_snapshot!(metric.loc);
4857 },
4858 );
4859 }
4860
4861 #[test]
4862 fn lua_no_elseif_lloc() {
4863 check_metrics::<LuaParser>(
4865 "local function f(x)
4866 if x > 0 then
4867 return 1
4868 elseif x < 0 then
4869 return -1
4870 else
4871 return 0
4872 end
4873end",
4874 "foo.lua",
4875 |metric| {
4876 assert_eq!(metric.loc.sloc(), 9);
4877 assert_eq!(metric.loc.ploc(), 9);
4878 assert_eq!(metric.loc.lloc(), 5);
4879 assert_eq!(metric.loc.cloc(), 0);
4880 assert_eq!(metric.loc.blank(), 0);
4881 insta::assert_json_snapshot!(metric.loc);
4882 },
4883 );
4884 }
4885
4886 #[test]
4887 fn lua_no_else_lloc() {
4888 check_metrics::<LuaParser>(
4890 "local function f(x)
4891 if x > 0 then
4892 return 1
4893 else
4894 return 0
4895 end
4896end",
4897 "foo.lua",
4898 |metric| {
4899 assert_eq!(metric.loc.sloc(), 7);
4900 assert_eq!(metric.loc.ploc(), 7);
4901 assert_eq!(metric.loc.lloc(), 4);
4902 assert_eq!(metric.loc.cloc(), 0);
4903 assert_eq!(metric.loc.blank(), 0);
4904 insta::assert_json_snapshot!(metric.loc);
4905 },
4906 );
4907 }
4908
4909 #[test]
4910 fn lua_functiondeclaration_lloc() {
4911 check_metrics::<LuaParser>(
4913 "function f()
4914 return 1
4915end",
4916 "foo.lua",
4917 |metric| {
4918 assert_eq!(metric.loc.sloc(), 3);
4919 assert_eq!(metric.loc.ploc(), 3);
4920 assert_eq!(metric.loc.lloc(), 2);
4921 assert_eq!(metric.loc.cloc(), 0);
4922 assert_eq!(metric.loc.blank(), 0);
4923 insta::assert_json_snapshot!(metric.loc);
4924 },
4925 );
4926 }
4927
4928 #[test]
4929 fn lua_local_function_lloc() {
4930 check_metrics::<LuaParser>(
4932 "local function g()
4933 return 2
4934end",
4935 "foo.lua",
4936 |metric| {
4937 assert_eq!(metric.loc.sloc(), 3);
4938 assert_eq!(metric.loc.ploc(), 3);
4939 assert_eq!(metric.loc.lloc(), 2);
4940 assert_eq!(metric.loc.cloc(), 0);
4941 assert_eq!(metric.loc.blank(), 0);
4942 insta::assert_json_snapshot!(metric.loc);
4943 },
4944 );
4945 }
4946
4947 #[test]
4948 fn lua_for_numeric_lloc() {
4949 check_metrics::<LuaParser>(
4950 "for i = 1, 10 do
4951 print(i)
4952end",
4953 "foo.lua",
4954 |metric| {
4955 assert_eq!(metric.loc.sloc(), 3);
4956 assert_eq!(metric.loc.ploc(), 3);
4957 assert_eq!(metric.loc.lloc(), 1);
4958 assert_eq!(metric.loc.cloc(), 0);
4959 assert_eq!(metric.loc.blank(), 0);
4960 insta::assert_json_snapshot!(metric.loc);
4961 },
4962 );
4963 }
4964
4965 #[test]
4966 fn lua_for_generic_lloc() {
4967 check_metrics::<LuaParser>(
4968 "for k, v in pairs(t) do
4969 print(k, v)
4970end",
4971 "foo.lua",
4972 |metric| {
4973 assert_eq!(metric.loc.sloc(), 3);
4974 assert_eq!(metric.loc.ploc(), 3);
4975 assert_eq!(metric.loc.lloc(), 1);
4976 assert_eq!(metric.loc.cloc(), 0);
4977 assert_eq!(metric.loc.blank(), 0);
4978 insta::assert_json_snapshot!(metric.loc);
4979 },
4980 );
4981 }
4982
4983 #[test]
4984 fn lua_repeat_lloc() {
4985 check_metrics::<LuaParser>(
4986 "local i = 0
4987repeat
4988 i = i + 1
4989until i >= 10",
4990 "foo.lua",
4991 |metric| {
4992 assert_eq!(metric.loc.sloc(), 4);
4993 assert_eq!(metric.loc.ploc(), 4);
4994 assert_eq!(metric.loc.lloc(), 3);
4995 assert_eq!(metric.loc.cloc(), 0);
4996 assert_eq!(metric.loc.blank(), 0);
4997 insta::assert_json_snapshot!(metric.loc);
4998 },
4999 );
5000 }
5001
5002 #[test]
5003 fn lua_local_decl_lloc() {
5004 check_metrics::<LuaParser>(
5005 "local x = 1
5006local y, z = 2, 3",
5007 "foo.lua",
5008 |metric| {
5009 assert_eq!(metric.loc.sloc(), 2);
5010 assert_eq!(metric.loc.ploc(), 2);
5011 assert_eq!(metric.loc.lloc(), 2);
5012 assert_eq!(metric.loc.cloc(), 0);
5013 assert_eq!(metric.loc.blank(), 0);
5014 insta::assert_json_snapshot!(metric.loc);
5015 },
5016 );
5017 }
5018
5019 #[test]
5020 fn lua_function_call_lloc() {
5021 check_metrics::<LuaParser>(
5024 "print(\"hello\")
5025local x = 1",
5026 "foo.lua",
5027 |metric| {
5028 assert_eq!(metric.loc.sloc(), 2);
5029 assert_eq!(metric.loc.ploc(), 2);
5030 assert_eq!(metric.loc.lloc(), 1);
5031 assert_eq!(metric.loc.cloc(), 0);
5032 assert_eq!(metric.loc.blank(), 0);
5033 insta::assert_json_snapshot!(metric.loc);
5034 },
5035 );
5036 }
5037
5038 #[test]
5039 fn lua_toplevel_assignment_lloc() {
5040 check_metrics::<LuaParser>(
5043 "x = 1
5044y, z = 2, 3",
5045 "foo.lua",
5046 |metric| {
5047 assert_eq!(metric.loc.sloc(), 2);
5048 assert_eq!(metric.loc.ploc(), 2);
5049 assert_eq!(metric.loc.lloc(), 2);
5050 assert_eq!(metric.loc.cloc(), 0);
5051 assert_eq!(metric.loc.blank(), 0);
5052 insta::assert_json_snapshot!(metric.loc);
5053 },
5054 );
5055 }
5056
5057 #[test]
5058 fn tsx_basic_loc() {
5059 check_metrics::<TsxParser>(
5060 "// A simple utility function
5061 function add(a: number, b: number): number {
5062 /* multi-line
5063 comment */
5064 return a + b;
5065 }
5066
5067 const greet = (name: string) => {
5068 return `Hello, ${name}`;
5069 };",
5070 "foo.tsx",
5071 |metric| {
5072 insta::assert_json_snapshot!(
5073 metric.loc,
5074 @r#"
5075 {
5076 "sloc": 10,
5077 "ploc": 6,
5078 "lloc": 2,
5079 "cloc": 3,
5080 "blank": 1,
5081 "sloc_average": 3.3333333333333335,
5082 "ploc_average": 2.0,
5083 "lloc_average": 0.6666666666666666,
5084 "cloc_average": 1.0,
5085 "blank_average": 0.3333333333333333,
5086 "sloc_min": 3,
5087 "sloc_max": 10,
5088 "cloc_min": 0,
5089 "cloc_max": 3,
5090 "ploc_min": 3,
5091 "ploc_max": 6,
5092 "lloc_min": 1,
5093 "lloc_max": 2,
5094 "blank_min": 0,
5095 "blank_max": 1
5096 }
5097 "#
5098 );
5099 },
5100 );
5101 }
5102
5103 #[test]
5104 fn typescript_basic_loc() {
5105 check_metrics::<TypescriptParser>(
5106 "// Line comment
5107 /* Block
5108 comment */
5109 function greet(name: string): string {
5110 return `Hello, ${name}`;
5111 }
5112
5113 const add = (a: number, b: number): number => a + b;",
5114 "foo.ts",
5115 |metric| {
5116 insta::assert_json_snapshot!(
5117 metric.loc,
5118 @r#"
5119 {
5120 "sloc": 8,
5121 "ploc": 4,
5122 "lloc": 1,
5123 "cloc": 3,
5124 "blank": 1,
5125 "sloc_average": 2.6666666666666665,
5126 "ploc_average": 1.3333333333333333,
5127 "lloc_average": 0.3333333333333333,
5128 "cloc_average": 1.0,
5129 "blank_average": 0.3333333333333333,
5130 "sloc_min": 1,
5131 "sloc_max": 8,
5132 "cloc_min": 0,
5133 "cloc_max": 3,
5134 "ploc_min": 1,
5135 "ploc_max": 4,
5136 "lloc_min": 0,
5137 "lloc_max": 1,
5138 "blank_min": 0,
5139 "blank_max": 1
5140 }
5141 "#
5142 );
5143 },
5144 );
5145 }
5146
5147 #[test]
5148 fn csharp_comments() {
5149 check_metrics::<CsharpParser>(
5150 "for (int i = 0; i < 100; i++) {
5151 // Print hello
5152 System.Console.WriteLine(\"hello\");
5153 /// XML doc comment
5154 System.Console.WriteLine(\"hello\");
5155 }",
5156 "foo.cs",
5157 |metric| {
5158 assert_eq!(metric.loc.sloc(), 6);
5159 assert_eq!(metric.loc.ploc(), 4);
5160 assert_eq!(metric.loc.lloc(), 3);
5161 assert_eq!(metric.loc.cloc(), 2);
5162 assert_eq!(metric.loc.blank(), 0);
5163 insta::assert_json_snapshot!(metric.loc);
5164 },
5165 );
5166 }
5167
5168 #[test]
5169 fn csharp_blank() {
5170 check_metrics::<CsharpParser>(
5171 "int x = 1;
5172
5173
5174 int y = 2;",
5175 "foo.cs",
5176 |metric| {
5177 assert_eq!(metric.loc.sloc(), 4);
5178 assert_eq!(metric.loc.ploc(), 2);
5179 assert_eq!(metric.loc.lloc(), 2);
5180 assert_eq!(metric.loc.cloc(), 0);
5181 assert_eq!(metric.loc.blank(), 2);
5182 insta::assert_json_snapshot!(metric.loc);
5183 },
5184 );
5185 }
5186
5187 #[test]
5188 fn csharp_sloc() {
5189 check_metrics::<CsharpParser>(
5190 "for (int i = 0; i < 100; i++) {
5191 System.Console.WriteLine(i);
5192 }",
5193 "foo.cs",
5194 |metric| {
5195 assert_eq!(metric.loc.sloc(), 3);
5196 assert_eq!(metric.loc.ploc(), 3);
5197 assert_eq!(metric.loc.lloc(), 2);
5198 assert_eq!(metric.loc.cloc(), 0);
5199 assert_eq!(metric.loc.blank(), 0);
5200 insta::assert_json_snapshot!(metric.loc);
5201 },
5202 );
5203 }
5204
5205 #[test]
5206 fn csharp_module_sloc() {
5207 check_metrics::<CsharpParser>(
5208 "namespace HelloWorld {
5209 class Program { }
5210 }",
5211 "foo.cs",
5212 |metric| {
5213 assert_eq!(metric.loc.sloc(), 3);
5214 assert_eq!(metric.loc.ploc(), 3);
5215 assert_eq!(metric.loc.lloc(), 0);
5216 assert_eq!(metric.loc.cloc(), 0);
5217 assert_eq!(metric.loc.blank(), 0);
5218 insta::assert_json_snapshot!(metric.loc);
5219 },
5220 );
5221 }
5222
5223 #[test]
5224 fn csharp_single_ploc() {
5225 check_metrics::<CsharpParser>("int x = 1;", "foo.cs", |metric| {
5226 assert_eq!(metric.loc.sloc(), 1);
5227 assert_eq!(metric.loc.ploc(), 1);
5228 assert_eq!(metric.loc.lloc(), 1);
5229 assert_eq!(metric.loc.cloc(), 0);
5230 assert_eq!(metric.loc.blank(), 0);
5231 insta::assert_json_snapshot!(metric.loc);
5232 });
5233 }
5234
5235 #[test]
5236 fn csharp_simple_ploc() {
5237 check_metrics::<CsharpParser>(
5238 "for (int i = 0; i < 100; i++) {
5239 System.Console.WriteLine(i);
5240 }",
5241 "foo.cs",
5242 |metric| {
5243 assert_eq!(metric.loc.sloc(), 3);
5244 assert_eq!(metric.loc.ploc(), 3);
5245 assert_eq!(metric.loc.lloc(), 2);
5246 assert_eq!(metric.loc.cloc(), 0);
5247 assert_eq!(metric.loc.blank(), 0);
5248 insta::assert_json_snapshot!(metric.loc);
5249 },
5250 );
5251 }
5252
5253 #[test]
5254 fn csharp_multi_ploc() {
5255 check_metrics::<CsharpParser>(
5256 "int x = 1;
5257 for (int i = 0; i < 100; i++) {
5258 System.Console.WriteLine(i);
5259 }",
5260 "foo.cs",
5261 |metric| {
5262 assert_eq!(metric.loc.sloc(), 4);
5263 assert_eq!(metric.loc.ploc(), 4);
5264 assert_eq!(metric.loc.lloc(), 3);
5265 assert_eq!(metric.loc.cloc(), 0);
5266 assert_eq!(metric.loc.blank(), 0);
5267 insta::assert_json_snapshot!(metric.loc);
5268 },
5269 );
5270 }
5271
5272 #[test]
5273 fn csharp_single_statement_lloc() {
5274 check_metrics::<CsharpParser>("int max = 10;", "foo.cs", |metric| {
5275 assert_eq!(metric.loc.sloc(), 1);
5276 assert_eq!(metric.loc.ploc(), 1);
5277 assert_eq!(metric.loc.lloc(), 1);
5278 assert_eq!(metric.loc.cloc(), 0);
5279 assert_eq!(metric.loc.blank(), 0);
5280 insta::assert_json_snapshot!(metric.loc);
5281 });
5282 }
5283
5284 #[test]
5285 fn csharp_for_lloc() {
5286 check_metrics::<CsharpParser>(
5287 "for (int i = 0; i < 10; i++) {
5288 System.Console.WriteLine(i);
5289 }",
5290 "foo.cs",
5291 |metric| {
5292 assert_eq!(metric.loc.sloc(), 3);
5293 assert_eq!(metric.loc.ploc(), 3);
5294 assert_eq!(metric.loc.lloc(), 2);
5295 assert_eq!(metric.loc.cloc(), 0);
5296 assert_eq!(metric.loc.blank(), 0);
5297 insta::assert_json_snapshot!(metric.loc);
5298 },
5299 );
5300 }
5301
5302 #[test]
5303 fn csharp_foreach_lloc() {
5304 check_metrics::<CsharpParser>(
5305 "foreach (var item in items) {
5306 System.Console.WriteLine(item);
5307 }",
5308 "foo.cs",
5309 |metric| {
5310 assert_eq!(metric.loc.sloc(), 3);
5311 assert_eq!(metric.loc.ploc(), 3);
5312 assert_eq!(metric.loc.lloc(), 2);
5313 assert_eq!(metric.loc.cloc(), 0);
5314 assert_eq!(metric.loc.blank(), 0);
5315 insta::assert_json_snapshot!(metric.loc);
5316 },
5317 );
5318 }
5319
5320 #[test]
5321 fn csharp_while_lloc() {
5322 check_metrics::<CsharpParser>(
5323 "int i = 0;
5324 while (i < 10) {
5325 i++;
5326 }",
5327 "foo.cs",
5328 |metric| {
5329 assert_eq!(metric.loc.sloc(), 4);
5330 assert_eq!(metric.loc.ploc(), 4);
5331 assert_eq!(metric.loc.lloc(), 3);
5332 assert_eq!(metric.loc.cloc(), 0);
5333 assert_eq!(metric.loc.blank(), 0);
5334 insta::assert_json_snapshot!(metric.loc);
5335 },
5336 );
5337 }
5338
5339 #[test]
5340 fn csharp_do_while_lloc() {
5341 check_metrics::<CsharpParser>(
5342 "int i = 0;
5343 do {
5344 i++;
5345 } while (i < 10);",
5346 "foo.cs",
5347 |metric| {
5348 assert_eq!(metric.loc.sloc(), 4);
5349 assert_eq!(metric.loc.ploc(), 4);
5350 assert_eq!(metric.loc.lloc(), 3);
5351 assert_eq!(metric.loc.cloc(), 0);
5352 assert_eq!(metric.loc.blank(), 0);
5353 insta::assert_json_snapshot!(metric.loc);
5354 },
5355 );
5356 }
5357
5358 #[test]
5359 fn csharp_switch_lloc() {
5360 check_metrics::<CsharpParser>(
5361 "switch (x) {
5362 case 1: System.Console.WriteLine(1); break;
5363 case 2: System.Console.WriteLine(2); break;
5364 default: System.Console.WriteLine(0); break;
5365 }
5366 string s = x switch { 1 => \"one\", _ => \"other\" };",
5367 "foo.cs",
5368 |metric| {
5369 assert_eq!(metric.loc.sloc(), 6);
5370 assert_eq!(metric.loc.ploc(), 6);
5371 assert_eq!(metric.loc.lloc(), 8);
5372 assert_eq!(metric.loc.cloc(), 0);
5373 assert_eq!(metric.loc.blank(), 0);
5374 insta::assert_json_snapshot!(metric.loc);
5375 },
5376 );
5377 }
5378
5379 #[test]
5380 fn csharp_continue_lloc() {
5381 check_metrics::<CsharpParser>(
5382 "for (int i = 0; i < 10; i++) {
5383 if (i == 5) continue;
5384 System.Console.WriteLine(i);
5385 }",
5386 "foo.cs",
5387 |metric| {
5388 assert_eq!(metric.loc.sloc(), 4);
5389 assert_eq!(metric.loc.ploc(), 4);
5390 assert_eq!(metric.loc.lloc(), 4);
5391 assert_eq!(metric.loc.cloc(), 0);
5392 assert_eq!(metric.loc.blank(), 0);
5393 insta::assert_json_snapshot!(metric.loc);
5394 },
5395 );
5396 }
5397
5398 #[test]
5399 fn csharp_try_lloc() {
5400 check_metrics::<CsharpParser>(
5401 "try {
5402 System.Console.WriteLine(\"try\");
5403 } catch (System.Exception e) {
5404 throw new System.Exception(\"caught\");
5405 } finally {
5406 System.Console.WriteLine(\"done\");
5407 }",
5408 "foo.cs",
5409 |metric| {
5410 assert_eq!(metric.loc.sloc(), 7);
5411 assert_eq!(metric.loc.ploc(), 7);
5412 assert_eq!(metric.loc.lloc(), 4);
5413 assert_eq!(metric.loc.cloc(), 0);
5414 assert_eq!(metric.loc.blank(), 0);
5415 insta::assert_json_snapshot!(metric.loc);
5416 },
5417 );
5418 }
5419
5420 #[test]
5421 fn csharp_class_loc() {
5422 check_metrics::<CsharpParser>(
5423 "class A {
5424 int x;
5425 public void M() {
5426 System.Console.WriteLine(x);
5427 }
5428 }",
5429 "foo.cs",
5430 |metric| {
5431 assert_eq!(metric.loc.sloc(), 6);
5432 assert_eq!(metric.loc.ploc(), 6);
5433 assert_eq!(metric.loc.lloc(), 1);
5434 assert_eq!(metric.loc.cloc(), 0);
5435 assert_eq!(metric.loc.blank(), 0);
5436 insta::assert_json_snapshot!(metric.loc);
5437 },
5438 );
5439 }
5440
5441 #[test]
5442 fn csharp_expressions_lloc() {
5443 check_metrics::<CsharpParser>(
5444 "int a = 1;
5445 int b = 2;
5446 int c = a + b;
5447 System.Console.WriteLine(c);",
5448 "foo.cs",
5449 |metric| {
5450 assert_eq!(metric.loc.sloc(), 4);
5451 assert_eq!(metric.loc.ploc(), 4);
5452 assert_eq!(metric.loc.lloc(), 4);
5453 assert_eq!(metric.loc.cloc(), 0);
5454 assert_eq!(metric.loc.blank(), 0);
5455 insta::assert_json_snapshot!(metric.loc);
5456 },
5457 );
5458 }
5459
5460 #[test]
5461 fn csharp_statement_inline_loc() {
5462 check_metrics::<CsharpParser>(
5463 "if (x > 0) System.Console.WriteLine(x);",
5464 "foo.cs",
5465 |metric| {
5466 assert_eq!(metric.loc.sloc(), 1);
5467 assert_eq!(metric.loc.ploc(), 1);
5468 assert_eq!(metric.loc.lloc(), 2);
5469 assert_eq!(metric.loc.cloc(), 0);
5470 assert_eq!(metric.loc.blank(), 0);
5471 insta::assert_json_snapshot!(metric.loc);
5472 },
5473 );
5474 }
5475
5476 #[test]
5477 fn csharp_general_loc() {
5478 check_metrics::<CsharpParser>(
5479 "using System;
5480 namespace Demo {
5481 class A {
5482 public void M() {
5483 Console.WriteLine(\"hi\");
5484 }
5485 }
5486 class B {
5487 public int N() { return 0; }
5488 }
5489 }",
5490 "foo.cs",
5491 |metric| {
5492 assert_eq!(metric.loc.sloc(), 11);
5493 assert_eq!(metric.loc.ploc(), 11);
5494 assert_eq!(metric.loc.lloc(), 2);
5495 assert_eq!(metric.loc.cloc(), 0);
5496 assert_eq!(metric.loc.blank(), 0);
5497 insta::assert_json_snapshot!(metric.loc);
5498 },
5499 );
5500 }
5501
5502 #[test]
5503 fn csharp_using_lloc() {
5504 check_metrics::<CsharpParser>(
5509 "using System;
5510 using System.IO;
5511 class A {
5512 public void M() {
5513 using (var s = File.OpenRead(\"x\")) {
5514 Console.WriteLine(s);
5515 }
5516 using var t = File.OpenRead(\"y\");
5517 Console.WriteLine(t);
5518 }
5519 }",
5520 "foo.cs",
5521 |metric| {
5522 assert_eq!(metric.loc.sloc(), 11);
5523 assert_eq!(metric.loc.ploc(), 11);
5524 assert_eq!(metric.loc.lloc(), 4);
5525 assert_eq!(metric.loc.cloc(), 0);
5526 assert_eq!(metric.loc.blank(), 0);
5527 insta::assert_json_snapshot!(metric.loc);
5528 },
5529 );
5530 }
5531
5532 #[test]
5533 fn kotlin_loc_basic() {
5534 check_metrics::<KotlinParser>(
5535 "// A simple function
5536 fun greet(name: String): String {
5537 val greeting = \"Hello, \" + name
5538 if (name.isEmpty()) {
5539 return \"Hello, World!\"
5540 }
5541 return greeting
5542 }",
5543 "foo.kt",
5544 |metric| {
5545 insta::assert_json_snapshot!(
5546 metric.loc,
5547 @r#"
5548 {
5549 "sloc": 8,
5550 "ploc": 7,
5551 "lloc": 4,
5552 "cloc": 1,
5553 "blank": 0,
5554 "sloc_average": 4.0,
5555 "ploc_average": 3.5,
5556 "lloc_average": 2.0,
5557 "cloc_average": 0.5,
5558 "blank_average": 0.0,
5559 "sloc_min": 7,
5560 "sloc_max": 8,
5561 "cloc_min": 0,
5562 "cloc_max": 1,
5563 "ploc_min": 7,
5564 "ploc_max": 7,
5565 "lloc_min": 4,
5566 "lloc_max": 4,
5567 "blank_min": 0,
5568 "blank_max": 0
5569 }
5570 "#
5571 );
5572 },
5573 );
5574 }
5575
5576 #[test]
5577 fn kotlin_loc_bare_expression() {
5578 check_metrics::<KotlinParser>(
5579 "fun main() {
5580 val x = 42
5581 println(x)
5582 listOf(1, 2, 3).forEach { println(it) }
5583 }",
5584 "foo.kt",
5585 |metric| {
5586 insta::assert_json_snapshot!(
5590 metric.loc,
5591 @r#"
5592 {
5593 "sloc": 5,
5594 "ploc": 5,
5595 "lloc": 3,
5596 "cloc": 0,
5597 "blank": 0,
5598 "sloc_average": 2.5,
5599 "ploc_average": 2.5,
5600 "lloc_average": 1.5,
5601 "cloc_average": 0.0,
5602 "blank_average": 0.0,
5603 "sloc_min": 5,
5604 "sloc_max": 5,
5605 "cloc_min": 0,
5606 "cloc_max": 0,
5607 "ploc_min": 5,
5608 "ploc_max": 5,
5609 "lloc_min": 3,
5610 "lloc_max": 3,
5611 "blank_min": 0,
5612 "blank_max": 0
5613 }
5614 "#
5615 );
5616 },
5617 );
5618 }
5619
5620 #[test]
5621 fn bash_loc() {
5622 check_metrics::<BashParser>(
5623 "#!/bin/bash
5624# This is a comment
5625f() {
5626 echo 'hello'
5627}
5628
5629# Another comment
5630f",
5631 "foo.sh",
5632 |metric| {
5633 assert_eq!(metric.loc.sloc(), 8);
5634 assert_eq!(metric.loc.ploc(), 4);
5635 assert_eq!(metric.loc.lloc(), 3);
5636 assert_eq!(metric.loc.cloc(), 3);
5637 assert_eq!(metric.loc.blank(), 1);
5638 insta::assert_json_snapshot!(metric.loc);
5639 },
5640 );
5641 }
5642
5643 #[test]
5647 fn python_cloc_crlf_matches_lf() {
5648 check_metrics::<PythonParser>("# comment\nx = 1", "foo.py", |m| {
5649 assert_eq!(m.loc.cloc(), 1);
5650 assert_eq!(m.loc.ploc(), 1);
5651 assert_eq!(m.loc.sloc(), 2);
5652 assert_eq!(m.loc.blank(), 0);
5653 });
5654 check_metrics::<PythonParser>("# comment\r\nx = 1", "foo.py", |m| {
5655 assert_eq!(m.loc.cloc(), 1);
5656 assert_eq!(m.loc.ploc(), 1);
5657 assert_eq!(m.loc.sloc(), 2);
5658 assert_eq!(m.loc.blank(), 0);
5659 });
5660 check_metrics::<PythonParser>("# comment\rx = 1", "foo.py", |m| {
5664 assert_eq!(m.loc.cloc(), 1);
5665 assert_eq!(m.loc.ploc(), 1);
5666 assert_eq!(m.loc.sloc(), 2);
5667 assert_eq!(m.loc.blank(), 0);
5668 });
5669 }
5670
5671 #[test]
5672 fn python_blank_crlf_matches_lf() {
5673 check_metrics::<PythonParser>("# comment\n\nx = 1", "foo.py", |m| {
5674 assert_eq!(m.loc.blank(), 1);
5675 });
5676 check_metrics::<PythonParser>("# comment\r\n\r\nx = 1", "foo.py", |m| {
5677 assert_eq!(m.loc.blank(), 1);
5678 });
5679 check_metrics::<PythonParser>("# comment\r\rx = 1", "foo.py", |m| {
5681 assert_eq!(m.loc.blank(), 1);
5682 });
5683 }
5684
5685 #[test]
5686 fn rust_cloc_crlf_matches_lf() {
5687 check_metrics::<RustParser>(
5688 "fn f() {\n // comment\n let x = 1;\n}",
5689 "foo.rs",
5690 |m| {
5691 assert_eq!(m.loc.cloc(), 1);
5692 assert_eq!(m.loc.sloc(), 4);
5693 },
5694 );
5695 check_metrics::<RustParser>(
5696 "fn f() {\r\n // comment\r\n let x = 1;\r\n}",
5697 "foo.rs",
5698 |m| {
5699 assert_eq!(m.loc.cloc(), 1);
5700 assert_eq!(m.loc.sloc(), 4);
5701 },
5702 );
5703 check_metrics::<RustParser>(
5706 "fn f() {\r // comment\r let x = 1;\r}",
5707 "foo.rs",
5708 |m| {
5709 assert_eq!(m.loc.cloc(), 1);
5710 assert_eq!(m.loc.sloc(), 4);
5711 },
5712 );
5713 }
5714
5715 #[test]
5716 fn tcl_blank() {
5717 check_metrics::<TclParser>("set x 1\n\nset y 2", "foo.tcl", |metric| {
5718 assert_eq!(metric.loc.sloc(), 3);
5719 assert_eq!(metric.loc.ploc(), 2);
5720 assert_eq!(metric.loc.lloc(), 2);
5721 assert_eq!(metric.loc.cloc(), 0);
5722 assert_eq!(metric.loc.blank(), 1);
5723 insta::assert_json_snapshot!(metric.loc);
5724 });
5725 }
5726
5727 #[test]
5728 fn tcl_no_zero_blank() {
5729 check_metrics::<TclParser>(
5733 "set a 1\nset b 2\n\nset c 3 ;# trailing\nset d 4 ;# trailing\nset e 5",
5734 "foo.tcl",
5735 |metric| {
5736 assert_eq!(metric.loc.sloc(), 6);
5737 assert_eq!(metric.loc.ploc(), 5);
5738 assert_eq!(metric.loc.cloc(), 2);
5739 assert_eq!(metric.loc.blank(), 1);
5740 },
5741 );
5742 }
5743
5744 #[test]
5750 fn tcl_cloc() {
5751 check_metrics::<TclParser>("# This is a comment\nset x 1", "foo.tcl", |metric| {
5752 assert_eq!(metric.loc.sloc(), 2);
5753 assert_eq!(metric.loc.ploc(), 1);
5754 assert_eq!(metric.loc.lloc(), 1);
5755 assert_eq!(metric.loc.cloc(), 1);
5756 assert_eq!(metric.loc.blank(), 0);
5757 insta::assert_json_snapshot!(metric.loc);
5758 });
5759 }
5760
5761 #[test]
5762 fn tcl_lloc() {
5763 check_metrics::<TclParser>(
5764 "proc f {x} {
5765 while {$x > 0} {
5766 if {$x > 10} {
5767 set x [expr {$x - 1}]
5768 }
5769 }
5770}",
5771 "foo.tcl",
5772 |metric| {
5773 assert_eq!(metric.loc.sloc(), 7);
5774 assert_eq!(metric.loc.ploc(), 7);
5775 assert_eq!(metric.loc.lloc(), 4);
5776 assert_eq!(metric.loc.cloc(), 0);
5777 assert_eq!(metric.loc.blank(), 0);
5778 insta::assert_json_snapshot!(metric.loc);
5779 },
5780 );
5781 }
5782
5783 #[test]
5784 fn tcl_no_command_substitution_lloc() {
5785 check_metrics::<TclParser>("puts [string toupper x]", "foo.tcl", |metric| {
5787 assert_eq!(metric.loc.sloc(), 1);
5788 assert_eq!(metric.loc.ploc(), 1);
5789 assert_eq!(metric.loc.lloc(), 1);
5790 assert_eq!(metric.loc.cloc(), 0);
5791 assert_eq!(metric.loc.blank(), 0);
5792 insta::assert_json_snapshot!(metric.loc);
5793 });
5794 }
5795
5796 #[test]
5797 fn tcl_procedure_lloc() {
5798 check_metrics::<TclParser>("proc foo {} {\n puts hello\n}", "foo.tcl", |metric| {
5799 assert_eq!(metric.loc.sloc(), 3);
5800 assert_eq!(metric.loc.ploc(), 3);
5801 assert_eq!(metric.loc.lloc(), 2);
5802 assert_eq!(metric.loc.cloc(), 0);
5803 assert_eq!(metric.loc.blank(), 0);
5804 insta::assert_json_snapshot!(metric.loc);
5805 });
5806 }
5807
5808 #[test]
5809 fn tcl_if_lloc() {
5810 check_metrics::<TclParser>("if {1} {\n puts hello\n}", "foo.tcl", |metric| {
5811 assert_eq!(metric.loc.sloc(), 3);
5812 assert_eq!(metric.loc.ploc(), 3);
5813 assert_eq!(metric.loc.lloc(), 2);
5814 assert_eq!(metric.loc.cloc(), 0);
5815 assert_eq!(metric.loc.blank(), 0);
5816 insta::assert_json_snapshot!(metric.loc);
5817 });
5818 }
5819
5820 #[test]
5821 fn tcl_elseif_lloc() {
5822 check_metrics::<TclParser>(
5824 "if {$x > 10} {
5825 puts big
5826} elseif {$x > 5} {
5827 puts medium
5828} else {
5829 puts small
5830}",
5831 "foo.tcl",
5832 |metric| {
5833 assert_eq!(metric.loc.sloc(), 7);
5834 assert_eq!(metric.loc.ploc(), 7);
5835 assert_eq!(metric.loc.lloc(), 5);
5836 assert_eq!(metric.loc.cloc(), 0);
5837 assert_eq!(metric.loc.blank(), 0);
5838 insta::assert_json_snapshot!(metric.loc);
5839 },
5840 );
5841 }
5842
5843 #[test]
5844 fn tcl_while_lloc() {
5845 check_metrics::<TclParser>(
5846 "while {$x > 0} {\n set x [expr {$x - 1}]\n}",
5847 "foo.tcl",
5848 |metric| {
5849 assert_eq!(metric.loc.sloc(), 3);
5850 assert_eq!(metric.loc.ploc(), 3);
5851 assert_eq!(metric.loc.lloc(), 2);
5852 assert_eq!(metric.loc.cloc(), 0);
5853 assert_eq!(metric.loc.blank(), 0);
5854 insta::assert_json_snapshot!(metric.loc);
5855 },
5856 );
5857 }
5858
5859 #[test]
5860 fn tcl_foreach_lloc() {
5861 check_metrics::<TclParser>(
5862 "foreach item {a b c} {\n puts $item\n}",
5863 "foo.tcl",
5864 |metric| {
5865 assert_eq!(metric.loc.sloc(), 3);
5866 assert_eq!(metric.loc.ploc(), 3);
5867 assert_eq!(metric.loc.lloc(), 2);
5868 assert_eq!(metric.loc.cloc(), 0);
5869 assert_eq!(metric.loc.blank(), 0);
5870 insta::assert_json_snapshot!(metric.loc);
5871 },
5872 );
5873 }
5874
5875 #[test]
5876 fn tcl_set_lloc() {
5877 check_metrics::<TclParser>("set x 42", "foo.tcl", |metric| {
5878 assert_eq!(metric.loc.sloc(), 1);
5879 assert_eq!(metric.loc.ploc(), 1);
5880 assert_eq!(metric.loc.lloc(), 1);
5881 assert_eq!(metric.loc.cloc(), 0);
5882 assert_eq!(metric.loc.blank(), 0);
5883 insta::assert_json_snapshot!(metric.loc);
5884 });
5885 }
5886
5887 #[test]
5888 fn tcl_global_lloc() {
5889 check_metrics::<TclParser>("global x", "foo.tcl", |metric| {
5890 assert_eq!(metric.loc.sloc(), 1);
5891 assert_eq!(metric.loc.ploc(), 1);
5892 assert_eq!(metric.loc.lloc(), 1);
5893 assert_eq!(metric.loc.cloc(), 0);
5894 assert_eq!(metric.loc.blank(), 0);
5895 insta::assert_json_snapshot!(metric.loc);
5896 });
5897 }
5898
5899 #[test]
5900 fn tcl_try_catch_lloc() {
5901 check_metrics::<TclParser>(
5903 "catch {
5904 set x 1
5905} result
5906try {
5907 set y 2
5908} on error {msg} {
5909 puts $msg
5910}",
5911 "foo.tcl",
5912 |metric| {
5913 assert_eq!(metric.loc.sloc(), 8);
5914 assert_eq!(metric.loc.ploc(), 8);
5915 assert_eq!(metric.loc.lloc(), 5);
5916 assert_eq!(metric.loc.cloc(), 0);
5917 assert_eq!(metric.loc.blank(), 0);
5918 insta::assert_json_snapshot!(metric.loc);
5919 },
5920 );
5921 }
5922
5923 #[test]
5924 fn tcl_namespace_lloc() {
5925 check_metrics::<TclParser>(
5926 "namespace eval myns {\n set x 1\n}",
5927 "foo.tcl",
5928 |metric| {
5929 assert_eq!(metric.loc.sloc(), 3);
5930 assert_eq!(metric.loc.ploc(), 3);
5931 assert_eq!(metric.loc.lloc(), 2);
5932 assert_eq!(metric.loc.cloc(), 0);
5933 assert_eq!(metric.loc.blank(), 0);
5934 insta::assert_json_snapshot!(metric.loc);
5935 },
5936 );
5937 }
5938
5939 #[test]
5940 fn tcl_regexp_lloc() {
5941 check_metrics::<TclParser>("regexp {^[0-9]+$} $x", "foo.tcl", |metric| {
5942 assert_eq!(metric.loc.sloc(), 1);
5943 assert_eq!(metric.loc.ploc(), 1);
5944 assert_eq!(metric.loc.lloc(), 1);
5945 assert_eq!(metric.loc.cloc(), 0);
5946 assert_eq!(metric.loc.blank(), 0);
5947 insta::assert_json_snapshot!(metric.loc);
5948 });
5949 }
5950
5951 #[test]
5952 fn tcl_expr_cmd_lloc() {
5953 check_metrics::<TclParser>("expr {1 + 2}", "foo.tcl", |metric| {
5954 assert_eq!(metric.loc.sloc(), 1);
5955 assert_eq!(metric.loc.ploc(), 1);
5956 assert_eq!(metric.loc.lloc(), 1);
5957 assert_eq!(metric.loc.cloc(), 0);
5958 assert_eq!(metric.loc.blank(), 0);
5959 insta::assert_json_snapshot!(metric.loc);
5960 });
5961 }
5962
5963 #[test]
5964 fn tcl_no_expr_cmd_substitution_lloc() {
5965 check_metrics::<TclParser>("set x [expr {1 + 2}]", "foo.tcl", |metric| {
5967 assert_eq!(metric.loc.sloc(), 1);
5968 assert_eq!(metric.loc.ploc(), 1);
5969 assert_eq!(metric.loc.lloc(), 1);
5970 assert_eq!(metric.loc.cloc(), 0);
5971 assert_eq!(metric.loc.blank(), 0);
5972 insta::assert_json_snapshot!(metric.loc);
5973 });
5974 }
5975
5976 #[test]
5977 fn tcl_nested_commands_lloc() {
5978 check_metrics::<TclParser>(
5980 "proc f {x} {
5981 set y [expr {$x * 2}]
5982 puts $y
5983}",
5984 "foo.tcl",
5985 |metric| {
5986 assert_eq!(metric.loc.sloc(), 4);
5987 assert_eq!(metric.loc.ploc(), 4);
5988 assert_eq!(metric.loc.lloc(), 3);
5989 assert_eq!(metric.loc.cloc(), 0);
5990 assert_eq!(metric.loc.blank(), 0);
5991 insta::assert_json_snapshot!(metric.loc);
5992 },
5993 );
5994 }
5995
5996 #[test]
5997 fn tcl_command_lloc() {
5998 check_metrics::<TclParser>("puts hello", "foo.tcl", |metric| {
5999 assert_eq!(metric.loc.sloc(), 1);
6000 assert_eq!(metric.loc.ploc(), 1);
6001 assert_eq!(metric.loc.lloc(), 1);
6002 assert_eq!(metric.loc.cloc(), 0);
6003 assert_eq!(metric.loc.blank(), 0);
6004 insta::assert_json_snapshot!(metric.loc);
6005 });
6006 }
6007
6008 #[test]
6009 fn tcl_no_else_lloc() {
6010 check_metrics::<TclParser>(
6012 "if {1} {\n puts yes\n} else {\n puts no\n}",
6013 "foo.tcl",
6014 |metric| {
6015 assert_eq!(metric.loc.sloc(), 5);
6016 assert_eq!(metric.loc.ploc(), 5);
6017 assert_eq!(metric.loc.lloc(), 3);
6018 assert_eq!(metric.loc.cloc(), 0);
6019 assert_eq!(metric.loc.blank(), 0);
6020 insta::assert_json_snapshot!(metric.loc);
6021 },
6022 );
6023 }
6024
6025 #[test]
6026 fn tcl_no_finally_lloc() {
6027 check_metrics::<TclParser>(
6030 "proc f {} {\n try {\n puts hi\n } finally {\n puts done\n }\n}",
6031 "foo.tcl",
6032 |metric| {
6033 assert_eq!(
6034 metric.loc.lloc(),
6035 4,
6036 "finally adds 0 lloc; would be 5 if finally counted"
6037 );
6038 },
6039 );
6040 }
6041
6042 #[test]
6043 fn tcl_multiline_block() {
6044 check_metrics::<TclParser>(
6045 "proc f {x} {
6046 set a 1
6047
6048 set b 2
6049 return [expr {$a + $b}]
6050}",
6051 "foo.tcl",
6052 |metric| {
6053 assert_eq!(metric.loc.sloc(), 6);
6054 assert_eq!(metric.loc.ploc(), 5);
6055 assert_eq!(metric.loc.lloc(), 4);
6056 assert_eq!(metric.loc.cloc(), 0);
6057 assert_eq!(metric.loc.blank(), 1);
6058 insta::assert_json_snapshot!(metric.loc);
6059 },
6060 );
6061 }
6062
6063 #[test]
6064 fn tcl_no_string_lloc() {
6065 check_metrics::<TclParser>(
6070 "set s \"line one\nline two\nline three\"",
6071 "foo.tcl",
6072 |metric| {
6073 assert_eq!(metric.loc.sloc(), 3);
6074 assert_eq!(metric.loc.ploc(), 2);
6075 assert_eq!(metric.loc.lloc(), 1);
6076 assert_eq!(metric.loc.cloc(), 0);
6077 assert_eq!(metric.loc.blank(), 1);
6078 insta::assert_json_snapshot!(metric.loc);
6079 },
6080 );
6081 }
6082
6083 #[test]
6084 fn javascript_blank() {
6085 check_metrics::<JavascriptParser>(
6086 "// header comment
6087 function f() {
6088
6089 var x = 1;
6090
6091 var y = 2;
6092 }",
6093 "foo.js",
6094 |metric| {
6095 assert_eq!(metric.loc.sloc(), 7);
6096 assert_eq!(metric.loc.ploc(), 4);
6097 assert_eq!(metric.loc.lloc(), 0);
6098 assert_eq!(metric.loc.cloc(), 1);
6099 assert_eq!(metric.loc.blank(), 2);
6100 insta::assert_json_snapshot!(metric.loc);
6101 },
6102 );
6103 }
6104
6105 #[test]
6106 fn javascript_cloc() {
6107 check_metrics::<JavascriptParser>(
6108 "// line comment
6109 /* block
6110 comment */
6111 function f() {
6112 return 1; // inline
6113 }",
6114 "foo.js",
6115 |metric| {
6116 assert_eq!(metric.loc.sloc(), 6);
6117 assert_eq!(metric.loc.ploc(), 3);
6118 assert_eq!(metric.loc.lloc(), 1);
6119 assert_eq!(metric.loc.cloc(), 4);
6120 assert_eq!(metric.loc.blank(), 0);
6121 insta::assert_json_snapshot!(metric.loc);
6122 },
6123 );
6124 }
6125
6126 #[test]
6127 fn javascript_cloc_html_comment() {
6128 check_metrics::<JavascriptParser>(
6132 "<!-- header comment -->
6133function f() {
6134 return 1;
6135}",
6136 "foo.js",
6137 |metric| {
6138 assert_eq!(metric.loc.sloc(), 4);
6139 assert_eq!(metric.loc.ploc(), 3);
6140 assert_eq!(metric.loc.lloc(), 1);
6141 assert_eq!(metric.loc.cloc(), 1);
6142 assert_eq!(metric.loc.blank(), 0);
6143 },
6144 );
6145 }
6146
6147 #[test]
6148 fn mozjs_blank() {
6149 check_metrics::<MozjsParser>(
6150 "function f() {
6151
6152 var x = 1;
6153
6154 }",
6155 "foo.js",
6156 |metric| {
6157 assert_eq!(metric.loc.sloc(), 5);
6158 assert_eq!(metric.loc.ploc(), 3);
6159 assert_eq!(metric.loc.lloc(), 0);
6160 assert_eq!(metric.loc.cloc(), 0);
6161 assert_eq!(metric.loc.blank(), 2);
6162 insta::assert_json_snapshot!(metric.loc);
6163 },
6164 );
6165 }
6166
6167 #[test]
6168 fn mozjs_cloc() {
6169 check_metrics::<MozjsParser>(
6170 "// header
6171 /* block comment */
6172 function f() {
6173 return 42;
6174 }",
6175 "foo.js",
6176 |metric| {
6177 assert_eq!(metric.loc.sloc(), 5);
6178 assert_eq!(metric.loc.ploc(), 3);
6179 assert_eq!(metric.loc.lloc(), 1);
6180 assert_eq!(metric.loc.cloc(), 2);
6181 assert_eq!(metric.loc.blank(), 0);
6182 insta::assert_json_snapshot!(metric.loc);
6183 },
6184 );
6185 }
6186
6187 #[test]
6188 fn mozjs_no_zero_blank() {
6189 check_metrics::<MozjsParser>(
6192 "function f() {
6193 var a = 1;
6194
6195 var b = 2; // trailing
6196 var c = 3; // trailing
6197}",
6198 "foo.js",
6199 |metric| {
6200 assert_eq!(metric.loc.sloc(), 6);
6201 assert_eq!(metric.loc.ploc(), 5);
6202 assert_eq!(metric.loc.cloc(), 2);
6203 assert_eq!(metric.loc.blank(), 1);
6204 insta::assert_json_snapshot!(metric.loc);
6205 },
6206 );
6207 }
6208
6209 #[test]
6210 fn mozjs_arrow_function_loc() {
6211 check_metrics::<MozjsParser>(
6212 "const add = (a, b) => a + b;
6213 const greet = name => {
6214 return 'Hello ' + name;
6215 };",
6216 "foo.js",
6217 |metric| {
6218 assert_eq!(metric.loc.sloc(), 4);
6219 assert_eq!(metric.loc.ploc(), 4);
6220 assert_eq!(metric.loc.lloc(), 1);
6221 assert_eq!(metric.loc.cloc(), 0);
6222 assert_eq!(metric.loc.blank(), 0);
6223 insta::assert_json_snapshot!(metric.loc);
6224 },
6225 );
6226 }
6227
6228 #[test]
6229 fn mozjs_multiple_functions_loc() {
6230 check_metrics::<MozjsParser>(
6231 "function f() {
6232 return 1;
6233 }
6234 function g() {
6235 return 2;
6236 }",
6237 "foo.js",
6238 |metric| {
6239 assert_eq!(metric.loc.sloc(), 6);
6240 assert_eq!(metric.loc.ploc(), 6);
6241 assert_eq!(metric.loc.lloc(), 2);
6242 assert_eq!(metric.loc.cloc(), 0);
6243 assert_eq!(metric.loc.blank(), 0);
6244 insta::assert_json_snapshot!(metric.loc);
6245 },
6246 );
6247 }
6248
6249 #[test]
6250 fn mozjs_nested_function_loc() {
6251 check_metrics::<MozjsParser>(
6252 "function outer() {
6253 function inner() {
6254 return 1;
6255 }
6256 return inner();
6257 }",
6258 "foo.js",
6259 |metric| {
6260 assert_eq!(metric.loc.sloc(), 6);
6261 assert_eq!(metric.loc.ploc(), 6);
6262 assert_eq!(metric.loc.lloc(), 2);
6263 assert_eq!(metric.loc.cloc(), 0);
6264 assert_eq!(metric.loc.blank(), 0);
6265 insta::assert_json_snapshot!(metric.loc);
6266 },
6267 );
6268 }
6269
6270 #[test]
6271 fn mozjs_if_lloc() {
6272 check_metrics::<MozjsParser>(
6273 "function f(x) {
6274 if (x > 0) {
6275 return 1;
6276 } else {
6277 return -1;
6278 }
6279 }",
6280 "foo.js",
6281 |metric| {
6282 assert_eq!(metric.loc.sloc(), 7);
6283 assert_eq!(metric.loc.ploc(), 7);
6284 assert_eq!(metric.loc.lloc(), 3);
6291 assert_eq!(metric.loc.cloc(), 0);
6292 assert_eq!(metric.loc.blank(), 0);
6293 insta::assert_json_snapshot!(metric.loc);
6294 },
6295 );
6296 }
6297
6298 #[test]
6305 fn js_family_if_lloc_matches_c_and_rust() {
6306 const JS_SRC: &str = "function f(x) {
6307 if (x > 0) {
6308 return 1;
6309 } else {
6310 return -1;
6311 }
6312 }";
6313 const C_SRC: &str = "int f(int x) {
6314 if (x > 0) {
6315 return 1;
6316 } else {
6317 return -1;
6318 }
6319 }";
6320 const RUST_SRC: &str = "fn f(x: i32) -> i32 {
6321 if x > 0 {
6322 return 1;
6323 } else {
6324 return -1;
6325 }
6326 }";
6327
6328 const EXPECTED_LLOC: usize = 3;
6331
6332 check_metrics::<CppParser>(C_SRC, "f.c", |m| {
6333 assert_eq!(m.loc.lloc() as usize, EXPECTED_LLOC);
6334 });
6335 check_metrics::<RustParser>(RUST_SRC, "f.rs", |m| {
6336 assert_eq!(m.loc.lloc() as usize, EXPECTED_LLOC);
6337 });
6338 check_metrics::<MozjsParser>(JS_SRC, "f.js", |m| {
6339 assert_eq!(m.loc.lloc() as usize, EXPECTED_LLOC);
6340 });
6341 check_metrics::<JavascriptParser>(JS_SRC, "f.js", |m| {
6342 assert_eq!(m.loc.lloc() as usize, EXPECTED_LLOC);
6343 });
6344 check_metrics::<TypescriptParser>(JS_SRC, "f.ts", |m| {
6345 assert_eq!(m.loc.lloc() as usize, EXPECTED_LLOC);
6346 });
6347 check_metrics::<TsxParser>(JS_SRC, "f.tsx", |m| {
6348 assert_eq!(m.loc.lloc() as usize, EXPECTED_LLOC);
6349 });
6350 }
6351
6352 #[test]
6353 fn mozjs_for_lloc() {
6354 check_metrics::<MozjsParser>(
6355 "function f(n) {
6356 var s = 0;
6357 for (var i = 0; i < n; i++) {
6358 s += i;
6359 }
6360 return s;
6361 }",
6362 "foo.js",
6363 |metric| {
6364 assert_eq!(metric.loc.sloc(), 7);
6365 assert_eq!(metric.loc.ploc(), 7);
6366 assert_eq!(metric.loc.lloc(), 3);
6367 assert_eq!(metric.loc.cloc(), 0);
6368 assert_eq!(metric.loc.blank(), 0);
6369 insta::assert_json_snapshot!(metric.loc);
6370 },
6371 );
6372 }
6373
6374 #[test]
6375 fn bash_blank() {
6376 check_metrics::<BashParser>(
6377 "#!/bin/bash
6378
6379 f() {
6380
6381 echo hello
6382
6383 }",
6384 "foo.sh",
6385 |metric| {
6386 assert_eq!(metric.loc.sloc(), 7);
6387 assert_eq!(metric.loc.ploc(), 3);
6388 assert_eq!(metric.loc.lloc(), 2);
6389 assert_eq!(metric.loc.cloc(), 1);
6390 assert_eq!(metric.loc.blank(), 3);
6391 insta::assert_json_snapshot!(metric.loc);
6392 },
6393 );
6394 }
6395
6396 #[test]
6397 fn bash_cloc() {
6398 check_metrics::<BashParser>(
6399 "# header comment
6400 f() {
6401 # body comment
6402 echo hello
6403 }",
6404 "foo.sh",
6405 |metric| {
6406 assert_eq!(metric.loc.sloc(), 5);
6407 assert_eq!(metric.loc.ploc(), 3);
6408 assert_eq!(metric.loc.lloc(), 2);
6409 assert_eq!(metric.loc.cloc(), 2);
6410 assert_eq!(metric.loc.blank(), 0);
6411 insta::assert_json_snapshot!(metric.loc);
6412 },
6413 );
6414 }
6415
6416 #[test]
6417 fn bash_no_zero_blank() {
6418 check_metrics::<BashParser>(
6421 "f() {
6422 echo a
6423
6424 echo b # trailing
6425 echo c # trailing
6426}",
6427 "foo.sh",
6428 |metric| {
6429 assert_eq!(metric.loc.sloc(), 6);
6430 assert_eq!(metric.loc.ploc(), 5);
6431 assert_eq!(metric.loc.cloc(), 2);
6432 assert_eq!(metric.loc.blank(), 1);
6433 insta::assert_json_snapshot!(metric.loc);
6434 },
6435 );
6436 }
6437
6438 #[test]
6439 fn bash_comment_before_code_line_reclassified() {
6440 check_metrics::<BashParser>("echo a\n\necho \"$(\n # c\n)\"\n", "foo.sh", |metric| {
6458 assert_eq!(metric.loc.sloc(), 5);
6459 assert_eq!(metric.loc.ploc(), 4);
6460 assert_eq!(metric.loc.lloc(), 3);
6461 assert_eq!(metric.loc.cloc(), 1);
6462 assert_eq!(metric.loc.blank(), 1);
6463 insta::assert_json_snapshot!(
6464 metric.loc,
6465 @r#"
6466 {
6467 "sloc": 5,
6468 "ploc": 4,
6469 "lloc": 3,
6470 "cloc": 1,
6471 "blank": 1,
6472 "sloc_average": 5.0,
6473 "ploc_average": 4.0,
6474 "lloc_average": 3.0,
6475 "cloc_average": 1.0,
6476 "blank_average": 1.0,
6477 "sloc_min": 5,
6478 "sloc_max": 5,
6479 "cloc_min": 1,
6480 "cloc_max": 1,
6481 "ploc_min": 4,
6482 "ploc_max": 4,
6483 "lloc_min": 3,
6484 "lloc_max": 3,
6485 "blank_min": 1,
6486 "blank_max": 1
6487 }
6488 "#
6489 );
6490 });
6491 }
6492
6493 #[test]
6494 fn bash_if_lloc() {
6495 check_metrics::<BashParser>(
6496 "f() {
6497 if [ $1 -gt 0 ]; then
6498 echo positive
6499 else
6500 echo negative
6501 fi
6502 }",
6503 "foo.sh",
6504 |metric| {
6505 assert_eq!(metric.loc.sloc(), 7);
6506 assert_eq!(metric.loc.ploc(), 7);
6507 assert_eq!(metric.loc.lloc(), 4);
6508 assert_eq!(metric.loc.cloc(), 0);
6509 assert_eq!(metric.loc.blank(), 0);
6510 insta::assert_json_snapshot!(metric.loc);
6511 },
6512 );
6513 }
6514
6515 #[test]
6516 fn bash_for_lloc() {
6517 check_metrics::<BashParser>(
6518 "f() {
6519 for i in 1 2 3; do
6520 echo $i
6521 done
6522 }",
6523 "foo.sh",
6524 |metric| {
6525 assert_eq!(metric.loc.sloc(), 5);
6526 assert_eq!(metric.loc.ploc(), 5);
6527 assert_eq!(metric.loc.lloc(), 3);
6528 assert_eq!(metric.loc.cloc(), 0);
6529 assert_eq!(metric.loc.blank(), 0);
6530 insta::assert_json_snapshot!(metric.loc);
6531 },
6532 );
6533 }
6534
6535 #[test]
6536 fn bash_while_lloc() {
6537 check_metrics::<BashParser>(
6538 "f() {
6539 local n=5
6540 while [ $n -gt 0 ]; do
6541 echo $n
6542 n=$((n - 1))
6543 done
6544 }",
6545 "foo.sh",
6546 |metric| {
6547 assert_eq!(metric.loc.sloc(), 7);
6548 assert_eq!(metric.loc.ploc(), 7);
6549 assert_eq!(metric.loc.lloc(), 4);
6550 assert_eq!(metric.loc.cloc(), 0);
6551 assert_eq!(metric.loc.blank(), 0);
6552 insta::assert_json_snapshot!(metric.loc);
6553 },
6554 );
6555 }
6556
6557 #[test]
6558 fn bash_case_lloc() {
6559 check_metrics::<BashParser>(
6560 "f() {
6561 case $1 in
6562 start) echo starting ;;
6563 stop) echo stopping ;;
6564 *) echo unknown ;;
6565 esac
6566 }",
6567 "foo.sh",
6568 |metric| {
6569 assert_eq!(metric.loc.sloc(), 7);
6570 assert_eq!(metric.loc.ploc(), 7);
6571 assert_eq!(metric.loc.lloc(), 5);
6572 assert_eq!(metric.loc.cloc(), 0);
6573 assert_eq!(metric.loc.blank(), 0);
6574 insta::assert_json_snapshot!(metric.loc);
6575 },
6576 );
6577 }
6578
6579 #[test]
6580 fn bash_multiple_functions_loc() {
6581 check_metrics::<BashParser>(
6582 "f() {
6583 echo hello
6584 }
6585 g() {
6586 echo world
6587 }",
6588 "foo.sh",
6589 |metric| {
6590 assert_eq!(metric.loc.sloc(), 6);
6591 assert_eq!(metric.loc.ploc(), 6);
6592 assert_eq!(metric.loc.lloc(), 4);
6593 assert_eq!(metric.loc.cloc(), 0);
6594 assert_eq!(metric.loc.blank(), 0);
6595 insta::assert_json_snapshot!(metric.loc);
6596 },
6597 );
6598 }
6599
6600 #[test]
6601 fn bash_nested_function_loc() {
6602 check_metrics::<BashParser>(
6603 "outer() {
6604 inner() {
6605 echo inner
6606 }
6607 inner
6608 echo outer
6609 }",
6610 "foo.sh",
6611 |metric| {
6612 assert_eq!(metric.loc.sloc(), 7);
6613 assert_eq!(metric.loc.ploc(), 7);
6614 assert_eq!(metric.loc.lloc(), 5);
6615 assert_eq!(metric.loc.cloc(), 0);
6616 assert_eq!(metric.loc.blank(), 0);
6617 insta::assert_json_snapshot!(metric.loc);
6618 },
6619 );
6620 }
6621
6622 #[test]
6623 fn bash_heredoc_loc() {
6624 check_metrics::<BashParser>(
6625 "f() {
6626 cat <<EOF
6627line1
6628line2
6629EOF
6630 }",
6631 "foo.sh",
6632 |metric| {
6633 assert_eq!(metric.loc.sloc(), 6);
6634 assert_eq!(metric.loc.ploc(), 5);
6635 assert_eq!(metric.loc.lloc(), 2);
6636 assert_eq!(metric.loc.cloc(), 0);
6637 assert_eq!(metric.loc.blank(), 1);
6638 insta::assert_json_snapshot!(metric.loc);
6639 },
6640 );
6641 }
6642
6643 #[test]
6644 fn kotlin_loc_blank() {
6645 check_metrics::<KotlinParser>(
6646 "fun f(): Int {
6647
6648 val x = 1
6649
6650 return x
6651 }",
6652 "foo.kt",
6653 |metric| {
6654 assert_eq!(metric.loc.sloc(), 6);
6655 assert_eq!(metric.loc.ploc(), 4);
6656 assert_eq!(metric.loc.lloc(), 2);
6657 assert_eq!(metric.loc.cloc(), 0);
6658 assert_eq!(metric.loc.blank(), 2);
6659 insta::assert_json_snapshot!(metric.loc);
6660 },
6661 );
6662 }
6663
6664 #[test]
6665 fn kotlin_loc_cloc() {
6666 check_metrics::<KotlinParser>(
6667 "// header comment
6668 /* block
6669 comment */
6670 fun f(): Int {
6671 return 42 // inline
6672 }",
6673 "foo.kt",
6674 |metric| {
6675 assert_eq!(metric.loc.sloc(), 6);
6676 assert_eq!(metric.loc.ploc(), 3);
6677 assert_eq!(metric.loc.lloc(), 1);
6678 assert_eq!(metric.loc.cloc(), 4);
6679 assert_eq!(metric.loc.blank(), 0);
6680 insta::assert_json_snapshot!(metric.loc);
6681 },
6682 );
6683 }
6684
6685 #[test]
6686 fn kotlin_loc_no_zero_blank() {
6687 check_metrics::<KotlinParser>(
6690 "fun connectToUpdateServer() {
6691 val pool = 0
6692
6693 val updateServer = -42
6694 val isConnected = false
6695 val currTry = 0
6696 val numRetries = 10 // Number of IPC connection retries before
6697 // giving up.
6698 val numTries = 20 // Number of IPC connection tries before
6699 // giving up.
6700 }",
6701 "foo.kt",
6702 |metric| {
6703 assert_eq!(metric.loc.sloc(), 11);
6706 assert_eq!(metric.loc.ploc(), 8);
6707 assert_eq!(metric.loc.cloc(), 4);
6708 assert_eq!(metric.loc.blank(), 1);
6709 insta::assert_json_snapshot!(
6710 metric.loc,
6711 @r#"
6712 {
6713 "sloc": 11,
6714 "ploc": 8,
6715 "lloc": 6,
6716 "cloc": 4,
6717 "blank": 1,
6718 "sloc_average": 5.5,
6719 "ploc_average": 4.0,
6720 "lloc_average": 3.0,
6721 "cloc_average": 2.0,
6722 "blank_average": 0.5,
6723 "sloc_min": 11,
6724 "sloc_max": 11,
6725 "cloc_min": 4,
6726 "cloc_max": 4,
6727 "ploc_min": 8,
6728 "ploc_max": 8,
6729 "lloc_min": 6,
6730 "lloc_max": 6,
6731 "blank_min": 1,
6732 "blank_max": 1
6733 }
6734 "#
6735 );
6736 },
6737 );
6738 }
6739
6740 #[test]
6741 fn kotlin_loc_blank_zero_sanity() {
6742 check_metrics::<KotlinParser>(
6747 "fun f(): Int {
6748 val x = 1 // x
6749 val y = 2 // y
6750 return x + y
6751 }",
6752 "foo.kt",
6753 |metric| {
6754 assert_eq!(metric.loc.sloc(), 5);
6755 assert_eq!(metric.loc.ploc(), 5);
6756 assert_eq!(metric.loc.lloc(), 3);
6757 assert_eq!(metric.loc.cloc(), 2);
6758 assert_eq!(metric.loc.blank(), 0);
6759 },
6760 );
6761 }
6762
6763 #[test]
6764 fn kotlin_loc_if_lloc() {
6765 check_metrics::<KotlinParser>(
6766 "fun classify(n: Int): String {
6767 if (n > 0) {
6768 return \"positive\"
6769 } else if (n < 0) {
6770 return \"negative\"
6771 }
6772 return \"zero\"
6773 }",
6774 "foo.kt",
6775 |metric| {
6776 assert_eq!(metric.loc.sloc(), 8);
6777 assert_eq!(metric.loc.ploc(), 8);
6778 assert_eq!(metric.loc.lloc(), 5);
6779 assert_eq!(metric.loc.cloc(), 0);
6780 assert_eq!(metric.loc.blank(), 0);
6781 insta::assert_json_snapshot!(metric.loc);
6782 },
6783 );
6784 }
6785
6786 #[test]
6787 fn kotlin_loc_for_lloc() {
6788 check_metrics::<KotlinParser>(
6789 "fun sum(n: Int): Int {
6790 var s = 0
6791 for (i in 1..n) {
6792 s += i
6793 }
6794 return s
6795 }",
6796 "foo.kt",
6797 |metric| {
6798 assert_eq!(metric.loc.sloc(), 7);
6799 assert_eq!(metric.loc.ploc(), 7);
6800 assert_eq!(metric.loc.lloc(), 4);
6801 assert_eq!(metric.loc.cloc(), 0);
6802 assert_eq!(metric.loc.blank(), 0);
6803 insta::assert_json_snapshot!(metric.loc);
6804 },
6805 );
6806 }
6807
6808 #[test]
6809 fn kotlin_loc_when_lloc() {
6810 check_metrics::<KotlinParser>(
6811 "fun describe(x: Int): String {
6812 return when (x) {
6813 1 -> \"one\"
6814 2 -> \"two\"
6815 else -> \"other\"
6816 }
6817 }",
6818 "foo.kt",
6819 |metric| {
6820 assert_eq!(metric.loc.sloc(), 7);
6821 assert_eq!(metric.loc.ploc(), 7);
6822 assert_eq!(metric.loc.lloc(), 2);
6823 assert_eq!(metric.loc.cloc(), 0);
6824 assert_eq!(metric.loc.blank(), 0);
6825 insta::assert_json_snapshot!(metric.loc);
6826 },
6827 );
6828 }
6829
6830 #[test]
6831 fn kotlin_loc_lambda_lloc() {
6832 check_metrics::<KotlinParser>(
6833 "fun f(list: List<Int>): List<Int> {
6834 return list.filter { it > 0 }
6835 .map { it * 2 }
6836 }",
6837 "foo.kt",
6838 |metric| {
6839 assert_eq!(metric.loc.sloc(), 4);
6840 assert_eq!(metric.loc.ploc(), 4);
6841 assert_eq!(metric.loc.lloc(), 1);
6842 assert_eq!(metric.loc.cloc(), 0);
6843 assert_eq!(metric.loc.blank(), 0);
6844 insta::assert_json_snapshot!(metric.loc);
6845 },
6846 );
6847 }
6848
6849 #[test]
6850 fn kotlin_loc_class_loc() {
6851 check_metrics::<KotlinParser>(
6852 "class Counter {
6853 private var count = 0
6854 fun increment() { count++ }
6855 fun get(): Int = count
6856 }",
6857 "foo.kt",
6858 |metric| {
6859 assert_eq!(metric.loc.sloc(), 5);
6860 assert_eq!(metric.loc.ploc(), 5);
6861 assert_eq!(metric.loc.lloc(), 1);
6862 assert_eq!(metric.loc.cloc(), 0);
6863 assert_eq!(metric.loc.blank(), 0);
6864 insta::assert_json_snapshot!(metric.loc);
6865 },
6866 );
6867 }
6868
6869 #[test]
6870 fn kotlin_loc_multiple_functions_loc() {
6871 check_metrics::<KotlinParser>(
6872 "fun f(): Int {
6873 return 1
6874 }
6875 fun g(): Int {
6876 return 2
6877 }",
6878 "foo.kt",
6879 |metric| {
6880 assert_eq!(metric.loc.sloc(), 6);
6881 assert_eq!(metric.loc.ploc(), 6);
6882 assert_eq!(metric.loc.lloc(), 2);
6883 assert_eq!(metric.loc.cloc(), 0);
6884 assert_eq!(metric.loc.blank(), 0);
6885 insta::assert_json_snapshot!(metric.loc);
6886 },
6887 );
6888 }
6889
6890 #[test]
6891 fn kotlin_loc_while_lloc() {
6892 check_metrics::<KotlinParser>(
6893 "fun countdown(n: Int) {
6894 var i = n
6895 while (i > 0) {
6896 println(i)
6897 i--
6898 }
6899 }",
6900 "foo.kt",
6901 |metric| {
6902 assert_eq!(metric.loc.sloc(), 7);
6903 assert_eq!(metric.loc.ploc(), 7);
6904 assert_eq!(metric.loc.lloc(), 3);
6905 assert_eq!(metric.loc.cloc(), 0);
6906 assert_eq!(metric.loc.blank(), 0);
6907 insta::assert_json_snapshot!(metric.loc);
6908 },
6909 );
6910 }
6911
6912 #[test]
6913 fn typescript_blank() {
6914 check_metrics::<TypescriptParser>(
6915 "function f(): void {
6916
6917 const x = 1;
6918
6919 }",
6920 "foo.ts",
6921 |metric| {
6922 assert_eq!(metric.loc.sloc(), 5);
6923 assert_eq!(metric.loc.ploc(), 3);
6924 assert_eq!(metric.loc.lloc(), 0);
6925 assert_eq!(metric.loc.cloc(), 0);
6926 assert_eq!(metric.loc.blank(), 2);
6927 insta::assert_json_snapshot!(metric.loc);
6928 },
6929 );
6930 }
6931
6932 #[test]
6933 fn typescript_cloc() {
6934 check_metrics::<TypescriptParser>(
6935 "// header
6936 /* block
6937 comment */
6938 function f(): number {
6939 return 42; // inline
6940 }",
6941 "foo.ts",
6942 |metric| {
6943 assert_eq!(metric.loc.sloc(), 6);
6944 assert_eq!(metric.loc.ploc(), 3);
6945 assert_eq!(metric.loc.lloc(), 1);
6946 assert_eq!(metric.loc.cloc(), 4);
6947 assert_eq!(metric.loc.blank(), 0);
6948 insta::assert_json_snapshot!(metric.loc);
6949 },
6950 );
6951 }
6952
6953 #[test]
6954 fn typescript_no_zero_blank() {
6955 check_metrics::<TypescriptParser>(
6958 "function f(): void {
6959 const a = 1;
6960
6961 const b = 2; // trailing
6962 const c = 3; // trailing
6963}",
6964 "foo.ts",
6965 |metric| {
6966 assert_eq!(metric.loc.sloc(), 6);
6967 assert_eq!(metric.loc.ploc(), 5);
6968 assert_eq!(metric.loc.cloc(), 2);
6969 assert_eq!(metric.loc.blank(), 1);
6970 insta::assert_json_snapshot!(metric.loc);
6971 },
6972 );
6973 }
6974
6975 #[test]
6976 fn typescript_if_lloc() {
6977 check_metrics::<TypescriptParser>(
6978 "function classify(n: number): string {
6979 if (n > 0) {
6980 return 'positive';
6981 } else {
6982 return 'non-positive';
6983 }
6984 }",
6985 "foo.ts",
6986 |metric| {
6987 assert_eq!(metric.loc.sloc(), 7);
6988 assert_eq!(metric.loc.ploc(), 7);
6989 assert_eq!(metric.loc.lloc(), 3);
6990 assert_eq!(metric.loc.cloc(), 0);
6991 assert_eq!(metric.loc.blank(), 0);
6992 insta::assert_json_snapshot!(metric.loc);
6993 },
6994 );
6995 }
6996
6997 #[test]
6998 fn typescript_for_lloc() {
6999 check_metrics::<TypescriptParser>(
7000 "function sum(n: number): number {
7001 let s = 0;
7002 for (let i = 0; i < n; i++) {
7003 s += i;
7004 }
7005 return s;
7006 }",
7007 "foo.ts",
7008 |metric| {
7009 assert_eq!(metric.loc.sloc(), 7);
7010 assert_eq!(metric.loc.ploc(), 7);
7011 assert_eq!(metric.loc.lloc(), 3);
7012 assert_eq!(metric.loc.cloc(), 0);
7013 assert_eq!(metric.loc.blank(), 0);
7014 insta::assert_json_snapshot!(metric.loc);
7015 },
7016 );
7017 }
7018
7019 #[test]
7020 fn typescript_while_lloc() {
7021 check_metrics::<TypescriptParser>(
7022 "function countdown(n: number): void {
7023 let i = n;
7024 while (i > 0) {
7025 console.log(i);
7026 i--;
7027 }
7028 }",
7029 "foo.ts",
7030 |metric| {
7031 assert_eq!(metric.loc.sloc(), 7);
7032 assert_eq!(metric.loc.ploc(), 7);
7033 assert_eq!(metric.loc.lloc(), 3);
7034 assert_eq!(metric.loc.cloc(), 0);
7035 assert_eq!(metric.loc.blank(), 0);
7036 insta::assert_json_snapshot!(metric.loc);
7037 },
7038 );
7039 }
7040
7041 #[test]
7042 fn typescript_switch_lloc() {
7043 check_metrics::<TypescriptParser>(
7044 "function describe(x: number): string {
7045 switch (x) {
7046 case 1: return 'one';
7047 case 2: return 'two';
7048 default: return 'other';
7049 }
7050 }",
7051 "foo.ts",
7052 |metric| {
7053 assert_eq!(metric.loc.sloc(), 7);
7054 assert_eq!(metric.loc.ploc(), 7);
7055 assert_eq!(metric.loc.lloc(), 4);
7056 assert_eq!(metric.loc.cloc(), 0);
7057 assert_eq!(metric.loc.blank(), 0);
7058 insta::assert_json_snapshot!(metric.loc);
7059 },
7060 );
7061 }
7062
7063 #[test]
7064 fn typescript_class_loc() {
7065 check_metrics::<TypescriptParser>(
7066 "class Counter {
7067 private count: number = 0;
7068 increment(): void { this.count++; }
7069 get(): number { return this.count; }
7070 }",
7071 "foo.ts",
7072 |metric| {
7073 assert_eq!(metric.loc.sloc(), 5);
7074 assert_eq!(metric.loc.ploc(), 5);
7075 assert_eq!(metric.loc.lloc(), 2);
7076 assert_eq!(metric.loc.cloc(), 0);
7077 assert_eq!(metric.loc.blank(), 0);
7078 insta::assert_json_snapshot!(metric.loc);
7079 },
7080 );
7081 }
7082
7083 #[test]
7084 fn typescript_arrow_function_loc() {
7085 check_metrics::<TypescriptParser>(
7086 "const add = (a: number, b: number): number => a + b;
7087 const greet = (name: string): string => {
7088 return `Hello, ${name}`;
7089 };",
7090 "foo.ts",
7091 |metric| {
7092 assert_eq!(metric.loc.sloc(), 4);
7093 assert_eq!(metric.loc.ploc(), 4);
7094 assert_eq!(metric.loc.lloc(), 1);
7095 assert_eq!(metric.loc.cloc(), 0);
7096 assert_eq!(metric.loc.blank(), 0);
7097 insta::assert_json_snapshot!(metric.loc);
7098 },
7099 );
7100 }
7101
7102 #[test]
7103 fn typescript_interface_loc() {
7104 check_metrics::<TypescriptParser>(
7105 "interface Shape {
7106 area(): number;
7107 perimeter(): number;
7108 }
7109 function describe(s: Shape): string {
7110 return `area=${s.area()}`;
7111 }",
7112 "foo.ts",
7113 |metric| {
7114 assert_eq!(metric.loc.sloc(), 7);
7115 assert_eq!(metric.loc.ploc(), 7);
7116 assert_eq!(metric.loc.lloc(), 1);
7117 assert_eq!(metric.loc.cloc(), 0);
7118 assert_eq!(metric.loc.blank(), 0);
7119 insta::assert_json_snapshot!(metric.loc);
7120 },
7121 );
7122 }
7123
7124 #[test]
7125 fn typescript_multiple_functions_loc() {
7126 check_metrics::<TypescriptParser>(
7127 "function f(): number {
7128 return 1;
7129 }
7130 function g(): number {
7131 return 2;
7132 }
7133 function h(): number {
7134 return 3;
7135 }",
7136 "foo.ts",
7137 |metric| {
7138 assert_eq!(metric.loc.sloc(), 9);
7139 assert_eq!(metric.loc.ploc(), 9);
7140 assert_eq!(metric.loc.lloc(), 3);
7141 assert_eq!(metric.loc.cloc(), 0);
7142 assert_eq!(metric.loc.blank(), 0);
7143 insta::assert_json_snapshot!(metric.loc);
7144 },
7145 );
7146 }
7147
7148 #[test]
7149 fn typescript_try_catch_lloc() {
7150 check_metrics::<TypescriptParser>(
7151 "function safe(x: number): number {
7152 try {
7153 return 1 / x;
7154 } catch (e) {
7155 return 0;
7156 }
7157 }",
7158 "foo.ts",
7159 |metric| {
7160 assert_eq!(metric.loc.sloc(), 7);
7161 assert_eq!(metric.loc.ploc(), 7);
7162 assert_eq!(metric.loc.lloc(), 3);
7163 assert_eq!(metric.loc.cloc(), 0);
7164 assert_eq!(metric.loc.blank(), 0);
7165 insta::assert_json_snapshot!(metric.loc);
7166 },
7167 );
7168 }
7169
7170 #[test]
7171 fn typescript_nested_functions_loc() {
7172 check_metrics::<TypescriptParser>(
7173 "function outer(x: number): number {
7174 function inner(y: number): number {
7175 return y * 2;
7176 }
7177 return inner(x) + 1;
7178 }",
7179 "foo.ts",
7180 |metric| {
7181 assert_eq!(metric.loc.sloc(), 6);
7182 assert_eq!(metric.loc.ploc(), 6);
7183 assert_eq!(metric.loc.lloc(), 2);
7184 assert_eq!(metric.loc.cloc(), 0);
7185 assert_eq!(metric.loc.blank(), 0);
7186 insta::assert_json_snapshot!(metric.loc);
7187 },
7188 );
7189 }
7190
7191 #[test]
7192 fn typescript_generic_function_loc() {
7193 check_metrics::<TypescriptParser>(
7194 "function identity<T>(value: T): T {
7195 return value;
7196 }
7197 function first<T>(arr: T[]): T | undefined {
7198 return arr[0];
7199 }",
7200 "foo.ts",
7201 |metric| {
7202 assert_eq!(metric.loc.sloc(), 6);
7203 assert_eq!(metric.loc.ploc(), 6);
7204 assert_eq!(metric.loc.lloc(), 2);
7205 assert_eq!(metric.loc.cloc(), 0);
7206 assert_eq!(metric.loc.blank(), 0);
7207 insta::assert_json_snapshot!(metric.loc);
7208 },
7209 );
7210 }
7211
7212 #[test]
7213 fn tsx_blank() {
7214 check_metrics::<TsxParser>(
7215 "function f(): void {
7216
7217 const x = 1;
7218
7219 }",
7220 "foo.tsx",
7221 |metric| {
7222 assert_eq!(metric.loc.sloc(), 5);
7223 assert_eq!(metric.loc.ploc(), 3);
7224 assert_eq!(metric.loc.lloc(), 0);
7225 assert_eq!(metric.loc.cloc(), 0);
7226 assert_eq!(metric.loc.blank(), 2);
7227 insta::assert_json_snapshot!(metric.loc);
7228 },
7229 );
7230 }
7231
7232 #[test]
7233 fn tsx_cloc() {
7234 check_metrics::<TsxParser>(
7235 "// header
7236 /* block
7237 comment */
7238 function f(): number {
7239 return 42; // inline
7240 }",
7241 "foo.tsx",
7242 |metric| {
7243 assert_eq!(metric.loc.sloc(), 6);
7244 assert_eq!(metric.loc.ploc(), 3);
7245 assert_eq!(metric.loc.lloc(), 1);
7246 assert_eq!(metric.loc.cloc(), 4);
7247 assert_eq!(metric.loc.blank(), 0);
7248 insta::assert_json_snapshot!(metric.loc);
7249 },
7250 );
7251 }
7252
7253 #[test]
7254 fn tsx_no_zero_blank() {
7255 check_metrics::<TsxParser>(
7258 "function f(): void {
7259 const a = 1;
7260
7261 const b = 2; // trailing
7262 const c = 3; // trailing
7263}",
7264 "foo.tsx",
7265 |metric| {
7266 assert_eq!(metric.loc.sloc(), 6);
7267 assert_eq!(metric.loc.ploc(), 5);
7268 assert_eq!(metric.loc.cloc(), 2);
7269 assert_eq!(metric.loc.blank(), 1);
7270 insta::assert_json_snapshot!(metric.loc);
7271 },
7272 );
7273 }
7274
7275 #[test]
7276 fn tsx_if_lloc() {
7277 check_metrics::<TsxParser>(
7278 "function classify(n: number): string {
7279 if (n > 0) {
7280 return 'positive';
7281 } else {
7282 return 'non-positive';
7283 }
7284 }",
7285 "foo.tsx",
7286 |metric| {
7287 assert_eq!(metric.loc.sloc(), 7);
7288 assert_eq!(metric.loc.ploc(), 7);
7289 assert_eq!(metric.loc.lloc(), 3);
7290 assert_eq!(metric.loc.cloc(), 0);
7291 assert_eq!(metric.loc.blank(), 0);
7292 insta::assert_json_snapshot!(metric.loc);
7293 },
7294 );
7295 }
7296
7297 #[test]
7298 fn tsx_for_lloc() {
7299 check_metrics::<TsxParser>(
7300 "function sum(n: number): number {
7301 let s = 0;
7302 for (let i = 0; i < n; i++) {
7303 s += i;
7304 }
7305 return s;
7306 }",
7307 "foo.tsx",
7308 |metric| {
7309 assert_eq!(metric.loc.sloc(), 7);
7310 assert_eq!(metric.loc.ploc(), 7);
7311 assert_eq!(metric.loc.lloc(), 3);
7312 assert_eq!(metric.loc.cloc(), 0);
7313 assert_eq!(metric.loc.blank(), 0);
7314 insta::assert_json_snapshot!(metric.loc);
7315 },
7316 );
7317 }
7318
7319 #[test]
7320 fn tsx_while_lloc() {
7321 check_metrics::<TsxParser>(
7322 "function countdown(n: number): void {
7323 let i = n;
7324 while (i > 0) {
7325 console.log(i);
7326 i--;
7327 }
7328 }",
7329 "foo.tsx",
7330 |metric| {
7331 assert_eq!(metric.loc.sloc(), 7);
7332 assert_eq!(metric.loc.ploc(), 7);
7333 assert_eq!(metric.loc.lloc(), 3);
7334 assert_eq!(metric.loc.cloc(), 0);
7335 assert_eq!(metric.loc.blank(), 0);
7336 insta::assert_json_snapshot!(metric.loc);
7337 },
7338 );
7339 }
7340
7341 #[test]
7342 fn tsx_switch_lloc() {
7343 check_metrics::<TsxParser>(
7344 "function describe(x: number): string {
7345 switch (x) {
7346 case 1: return 'one';
7347 case 2: return 'two';
7348 default: return 'other';
7349 }
7350 }",
7351 "foo.tsx",
7352 |metric| {
7353 assert_eq!(metric.loc.sloc(), 7);
7354 assert_eq!(metric.loc.ploc(), 7);
7355 assert_eq!(metric.loc.lloc(), 4);
7356 assert_eq!(metric.loc.cloc(), 0);
7357 assert_eq!(metric.loc.blank(), 0);
7358 insta::assert_json_snapshot!(metric.loc);
7359 },
7360 );
7361 }
7362
7363 #[test]
7364 fn tsx_class_loc() {
7365 check_metrics::<TsxParser>(
7366 "class Counter {
7367 private count: number = 0;
7368 increment(): void { this.count++; }
7369 get(): number { return this.count; }
7370 }",
7371 "foo.tsx",
7372 |metric| {
7373 assert_eq!(metric.loc.sloc(), 5);
7374 assert_eq!(metric.loc.ploc(), 5);
7375 assert_eq!(metric.loc.lloc(), 2);
7376 assert_eq!(metric.loc.cloc(), 0);
7377 assert_eq!(metric.loc.blank(), 0);
7378 insta::assert_json_snapshot!(metric.loc);
7379 },
7380 );
7381 }
7382
7383 #[test]
7384 fn tsx_arrow_function_loc() {
7385 check_metrics::<TsxParser>(
7386 "const add = (a: number, b: number): number => a + b;
7387 const greet = (name: string): string => {
7388 return `Hello, ${name}`;
7389 };",
7390 "foo.tsx",
7391 |metric| {
7392 assert_eq!(metric.loc.sloc(), 4);
7393 assert_eq!(metric.loc.ploc(), 4);
7394 assert_eq!(metric.loc.lloc(), 1);
7395 assert_eq!(metric.loc.cloc(), 0);
7396 assert_eq!(metric.loc.blank(), 0);
7397 insta::assert_json_snapshot!(metric.loc);
7398 },
7399 );
7400 }
7401
7402 #[test]
7403 fn tsx_multiple_functions_loc() {
7404 check_metrics::<TsxParser>(
7405 "function f(): number {
7406 return 1;
7407 }
7408 function g(): number {
7409 return 2;
7410 }
7411 function h(): number {
7412 return 3;
7413 }",
7414 "foo.tsx",
7415 |metric| {
7416 assert_eq!(metric.loc.sloc(), 9);
7417 assert_eq!(metric.loc.ploc(), 9);
7418 assert_eq!(metric.loc.lloc(), 3);
7419 assert_eq!(metric.loc.cloc(), 0);
7420 assert_eq!(metric.loc.blank(), 0);
7421 insta::assert_json_snapshot!(metric.loc);
7422 },
7423 );
7424 }
7425
7426 #[test]
7427 fn tsx_try_catch_lloc() {
7428 check_metrics::<TsxParser>(
7429 "function safe(x: number): number {
7430 try {
7431 return 1 / x;
7432 } catch (e) {
7433 return 0;
7434 }
7435 }",
7436 "foo.tsx",
7437 |metric| {
7438 assert_eq!(metric.loc.sloc(), 7);
7439 assert_eq!(metric.loc.ploc(), 7);
7440 assert_eq!(metric.loc.lloc(), 3);
7441 assert_eq!(metric.loc.cloc(), 0);
7442 assert_eq!(metric.loc.blank(), 0);
7443 insta::assert_json_snapshot!(metric.loc);
7444 },
7445 );
7446 }
7447
7448 #[test]
7449 fn tsx_nested_functions_loc() {
7450 check_metrics::<TsxParser>(
7451 "function outer(x: number): number {
7452 function inner(y: number): number {
7453 return y * 2;
7454 }
7455 return inner(x) + 1;
7456 }",
7457 "foo.tsx",
7458 |metric| {
7459 assert_eq!(metric.loc.sloc(), 6);
7460 assert_eq!(metric.loc.ploc(), 6);
7461 assert_eq!(metric.loc.lloc(), 2);
7462 assert_eq!(metric.loc.cloc(), 0);
7463 assert_eq!(metric.loc.blank(), 0);
7464 insta::assert_json_snapshot!(metric.loc);
7465 },
7466 );
7467 }
7468
7469 #[test]
7470 fn tsx_interface_loc() {
7471 check_metrics::<TsxParser>(
7472 "interface Shape {
7473 area(): number;
7474 perimeter(): number;
7475 }
7476 function describe(s: Shape): string {
7477 return `area=${s.area()}`;
7478 }",
7479 "foo.tsx",
7480 |metric| {
7481 assert_eq!(metric.loc.sloc(), 7);
7482 assert_eq!(metric.loc.ploc(), 7);
7483 assert_eq!(metric.loc.lloc(), 1);
7484 assert_eq!(metric.loc.cloc(), 0);
7485 assert_eq!(metric.loc.blank(), 0);
7486 insta::assert_json_snapshot!(metric.loc);
7487 },
7488 );
7489 }
7490
7491 #[test]
7492 fn tsx_generic_function_loc() {
7493 check_metrics::<TsxParser>(
7494 "function identity<T>(value: T): T {
7495 return value;
7496 }
7497 function first<T>(arr: T[]): T | undefined {
7498 return arr[0];
7499 }",
7500 "foo.tsx",
7501 |metric| {
7502 assert_eq!(metric.loc.sloc(), 6);
7503 assert_eq!(metric.loc.ploc(), 6);
7504 assert_eq!(metric.loc.lloc(), 2);
7505 assert_eq!(metric.loc.cloc(), 0);
7506 assert_eq!(metric.loc.blank(), 0);
7507 insta::assert_json_snapshot!(metric.loc);
7508 },
7509 );
7510 }
7511
7512 #[test]
7513 fn php_blank() {
7514 check_metrics::<PhpParser>(
7515 "<?php
7516
7517$a = 1;
7518
7519$b = 2;
7520
7521",
7522 "foo.php",
7523 |metric| {
7524 assert_eq!(metric.loc.sloc(), 5);
7525 assert_eq!(metric.loc.ploc(), 3);
7526 assert_eq!(metric.loc.lloc(), 2);
7527 assert_eq!(metric.loc.cloc(), 0);
7528 assert_eq!(metric.loc.blank(), 2);
7529 insta::assert_json_snapshot!(metric.loc);
7530 },
7531 );
7532 }
7533
7534 #[test]
7535 fn php_no_zero_blank() {
7536 check_metrics::<PhpParser>(
7539 "<?php
7540$a = 1;
7541
7542$b = 2; // trailing
7543$c = 3; // trailing
7544",
7545 "foo.php",
7546 |metric| {
7547 assert_eq!(metric.loc.sloc(), 5);
7548 assert_eq!(metric.loc.ploc(), 4);
7549 assert_eq!(metric.loc.cloc(), 2);
7550 assert_eq!(metric.loc.blank(), 1);
7551 insta::assert_json_snapshot!(metric.loc);
7552 },
7553 );
7554 }
7555
7556 #[test]
7557 fn php_cloc_double_slash() {
7558 check_metrics::<PhpParser>(
7559 "<?php
7560// first
7561// second
7562$a = 1; // trailing",
7563 "foo.php",
7564 |metric| {
7565 assert_eq!(metric.loc.sloc(), 4);
7566 assert_eq!(metric.loc.ploc(), 2);
7567 assert_eq!(metric.loc.lloc(), 1);
7568 assert_eq!(metric.loc.cloc(), 3);
7569 assert_eq!(metric.loc.blank(), 0);
7570 insta::assert_json_snapshot!(metric.loc);
7571 },
7572 );
7573 }
7574
7575 #[test]
7576 fn php_cloc_hash() {
7577 check_metrics::<PhpParser>(
7578 "<?php
7579# first
7580# second
7581$a = 1;",
7582 "foo.php",
7583 |metric| {
7584 assert_eq!(metric.loc.sloc(), 4);
7585 assert_eq!(metric.loc.ploc(), 2);
7586 assert_eq!(metric.loc.lloc(), 1);
7587 assert_eq!(metric.loc.cloc(), 2);
7588 assert_eq!(metric.loc.blank(), 0);
7589 insta::assert_json_snapshot!(metric.loc);
7590 },
7591 );
7592 }
7593
7594 #[test]
7595 fn php_cloc_block() {
7596 check_metrics::<PhpParser>(
7597 "<?php
7598/*
7599 * block
7600 * comment
7601 */
7602$a = 1;",
7603 "foo.php",
7604 |metric| {
7605 assert_eq!(metric.loc.sloc(), 6);
7606 assert_eq!(metric.loc.ploc(), 2);
7607 assert_eq!(metric.loc.lloc(), 1);
7608 assert_eq!(metric.loc.cloc(), 4);
7609 assert_eq!(metric.loc.blank(), 0);
7610 insta::assert_json_snapshot!(metric.loc);
7611 },
7612 );
7613 }
7614
7615 #[test]
7616 fn php_lloc() {
7617 check_metrics::<PhpParser>(
7619 "<?php
7620$a = 1;
7621if ($a > 0) {
7622 echo $a;
7623}",
7624 "foo.php",
7625 |metric| {
7626 assert_eq!(metric.loc.sloc(), 5);
7627 assert_eq!(metric.loc.ploc(), 5);
7628 assert_eq!(metric.loc.lloc(), 3);
7629 assert_eq!(metric.loc.cloc(), 0);
7630 assert_eq!(metric.loc.blank(), 0);
7631 insta::assert_json_snapshot!(metric.loc);
7632 },
7633 );
7634 }
7635
7636 #[test]
7637 fn php_no_parenthesized_expression_lloc() {
7638 check_metrics::<PhpParser>(
7641 "<?php
7642$a = (1 + 2);",
7643 "foo.php",
7644 |metric| {
7645 assert_eq!(metric.loc.sloc(), 2);
7646 assert_eq!(metric.loc.ploc(), 2);
7647 assert_eq!(metric.loc.lloc(), 1);
7648 assert_eq!(metric.loc.cloc(), 0);
7649 assert_eq!(metric.loc.blank(), 0);
7650 insta::assert_json_snapshot!(metric.loc);
7651 },
7652 );
7653 }
7654
7655 #[test]
7656 fn php_no_compound_statement_lloc() {
7657 check_metrics::<PhpParser>(
7659 "<?php
7660function f(): void {
7661 $a = 1;
7662}",
7663 "foo.php",
7664 |metric| {
7665 assert_eq!(metric.loc.sloc(), 4);
7666 assert_eq!(metric.loc.ploc(), 4);
7667 assert_eq!(metric.loc.lloc(), 1);
7668 assert_eq!(metric.loc.cloc(), 0);
7669 assert_eq!(metric.loc.blank(), 0);
7670 insta::assert_json_snapshot!(metric.loc);
7671 },
7672 );
7673 }
7674
7675 #[test]
7676 fn php_no_colon_block_lloc() {
7677 check_metrics::<PhpParser>(
7680 "<?php
7681if (true):
7682 $a = 1;
7683endif;",
7684 "foo.php",
7685 |metric| {
7686 assert_eq!(metric.loc.sloc(), 4);
7687 assert_eq!(metric.loc.ploc(), 4);
7688 assert_eq!(metric.loc.lloc(), 2);
7689 assert_eq!(metric.loc.cloc(), 0);
7690 assert_eq!(metric.loc.blank(), 0);
7691 insta::assert_json_snapshot!(metric.loc);
7692 },
7693 );
7694 }
7695
7696 #[test]
7697 fn php_no_else_clause_lloc() {
7698 check_metrics::<PhpParser>(
7700 "<?php
7701if ($x) {
7702 $a = 1;
7703} elseif ($y) {
7704 $a = 2;
7705} else {
7706 $a = 3;
7707}",
7708 "foo.php",
7709 |metric| {
7710 assert_eq!(metric.loc.sloc(), 8);
7711 assert_eq!(metric.loc.ploc(), 8);
7712 assert_eq!(metric.loc.lloc(), 4);
7713 assert_eq!(metric.loc.cloc(), 0);
7714 assert_eq!(metric.loc.blank(), 0);
7715 insta::assert_json_snapshot!(metric.loc);
7716 },
7717 );
7718 }
7719
7720 #[test]
7721 fn php_no_case_statement_lloc() {
7722 check_metrics::<PhpParser>(
7725 "<?php
7726switch ($x) {
7727 case 1:
7728 $a = 1;
7729 break;
7730 case 2:
7731 $a = 2;
7732 break;
7733 default:
7734 $a = 0;
7735}",
7736 "foo.php",
7737 |metric| {
7738 assert_eq!(metric.loc.sloc(), 11);
7739 assert_eq!(metric.loc.ploc(), 11);
7740 assert_eq!(metric.loc.lloc(), 6);
7741 assert_eq!(metric.loc.cloc(), 0);
7742 assert_eq!(metric.loc.blank(), 0);
7743 insta::assert_json_snapshot!(metric.loc);
7744 },
7745 );
7746 }
7747
7748 #[test]
7749 fn php_no_match_arm_lloc() {
7750 check_metrics::<PhpParser>(
7753 "<?php
7754$a = match ($x) {
7755 1 => 'one',
7756 2 => 'two',
7757 default => 'other',
7758};",
7759 "foo.php",
7760 |metric| {
7761 assert_eq!(metric.loc.sloc(), 6);
7762 assert_eq!(metric.loc.ploc(), 6);
7763 assert_eq!(metric.loc.lloc(), 1);
7764 assert_eq!(metric.loc.cloc(), 0);
7765 assert_eq!(metric.loc.blank(), 0);
7766 insta::assert_json_snapshot!(metric.loc);
7767 },
7768 );
7769 }
7770
7771 #[test]
7772 fn php_no_throw_in_expression_lloc() {
7773 check_metrics::<PhpParser>(
7776 "<?php
7777$x = $y ?? throw new \\Exception('nope');",
7778 "foo.php",
7779 |metric| {
7780 assert_eq!(metric.loc.sloc(), 2);
7781 assert_eq!(metric.loc.ploc(), 2);
7782 assert_eq!(metric.loc.lloc(), 1);
7783 assert_eq!(metric.loc.cloc(), 0);
7784 assert_eq!(metric.loc.blank(), 0);
7785 insta::assert_json_snapshot!(metric.loc);
7786 },
7787 );
7788 }
7789
7790 #[test]
7791 fn php_no_closure_in_assignment_lloc() {
7792 check_metrics::<PhpParser>(
7796 "<?php
7797$f = function (): int {
7798 return 42;
7799};",
7800 "foo.php",
7801 |metric| {
7802 assert_eq!(metric.loc.sloc(), 4);
7803 assert_eq!(metric.loc.ploc(), 4);
7804 assert_eq!(metric.loc.lloc(), 2);
7805 assert_eq!(metric.loc.cloc(), 0);
7806 assert_eq!(metric.loc.blank(), 0);
7807 insta::assert_json_snapshot!(metric.loc);
7808 },
7809 );
7810 }
7811
7812 #[test]
7813 fn php_for_lloc() {
7814 check_metrics::<PhpParser>(
7817 "<?php
7818for ($i = 0; $i < 10; $i++) {
7819 echo $i;
7820}",
7821 "foo.php",
7822 |metric| {
7823 assert_eq!(metric.loc.sloc(), 4);
7824 assert_eq!(metric.loc.ploc(), 4);
7825 assert_eq!(metric.loc.lloc(), 2);
7826 assert_eq!(metric.loc.cloc(), 0);
7827 assert_eq!(metric.loc.blank(), 0);
7828 insta::assert_json_snapshot!(metric.loc);
7829 },
7830 );
7831 }
7832
7833 #[test]
7834 fn php_foreach_lloc() {
7835 check_metrics::<PhpParser>(
7836 "<?php
7837foreach ($items as $k => $v) {
7838 echo $v;
7839}",
7840 "foo.php",
7841 |metric| {
7842 assert_eq!(metric.loc.sloc(), 4);
7843 assert_eq!(metric.loc.ploc(), 4);
7844 assert_eq!(metric.loc.lloc(), 2);
7845 assert_eq!(metric.loc.cloc(), 0);
7846 assert_eq!(metric.loc.blank(), 0);
7847 insta::assert_json_snapshot!(metric.loc);
7848 },
7849 );
7850 }
7851
7852 #[test]
7853 fn php_try_lloc() {
7854 check_metrics::<PhpParser>(
7855 "<?php
7856try {
7857 $a = 1;
7858} catch (\\Exception $e) {
7859 $a = 0;
7860} finally {
7861 $b = 2;
7862}",
7863 "foo.php",
7864 |metric| {
7865 assert_eq!(metric.loc.sloc(), 8);
7866 assert_eq!(metric.loc.ploc(), 8);
7867 assert_eq!(metric.loc.lloc(), 4);
7868 assert_eq!(metric.loc.cloc(), 0);
7869 assert_eq!(metric.loc.blank(), 0);
7870 insta::assert_json_snapshot!(metric.loc);
7871 },
7872 );
7873 }
7874
7875 #[test]
7876 fn php_class_loc() {
7877 check_metrics::<PhpParser>(
7878 "<?php
7879class A {
7880 public int $x = 0;
7881 private const Y = 1;
7882 public function f(): int {
7883 return $this->x;
7884 }
7885}",
7886 "foo.php",
7887 |metric| {
7888 assert_eq!(metric.loc.sloc(), 8);
7889 assert_eq!(metric.loc.ploc(), 8);
7890 assert_eq!(metric.loc.lloc(), 3);
7891 assert_eq!(metric.loc.cloc(), 0);
7892 assert_eq!(metric.loc.blank(), 0);
7893 insta::assert_json_snapshot!(metric.loc);
7894 },
7895 );
7896 }
7897
7898 #[test]
7899 fn php_namespace_use_lloc() {
7900 check_metrics::<PhpParser>(
7901 "<?php
7902namespace App;
7903use App\\Foo;
7904use App\\Bar;
7905$a = 1;",
7906 "foo.php",
7907 |metric| {
7908 assert_eq!(metric.loc.sloc(), 5);
7909 assert_eq!(metric.loc.ploc(), 5);
7910 assert_eq!(metric.loc.lloc(), 3);
7911 assert_eq!(metric.loc.cloc(), 0);
7912 assert_eq!(metric.loc.blank(), 0);
7913 insta::assert_json_snapshot!(metric.loc);
7914 },
7915 );
7916 }
7917
7918 #[test]
7919 fn php_general_loc() {
7920 check_metrics::<PhpParser>(
7921 "<?php
7922// header
7923namespace App;
7924use App\\Foo;
7925
7926class Bar {
7927 public int $n = 0;
7928
7929 public function add(int $x): int {
7930 if ($x > 0) {
7931 return $this->n + $x;
7932 }
7933 return $this->n;
7934 }
7935}",
7936 "foo.php",
7937 |metric| {
7938 assert_eq!(metric.loc.sloc(), 15);
7939 assert_eq!(metric.loc.ploc(), 12);
7940 assert_eq!(metric.loc.lloc(), 5);
7941 assert_eq!(metric.loc.cloc(), 1);
7942 assert_eq!(metric.loc.blank(), 2);
7943 insta::assert_json_snapshot!(metric.loc);
7944 },
7945 );
7946 }
7947
7948 #[test]
7949 fn php_match_in_expression_lloc() {
7950 check_metrics::<PhpParser>(
7953 "<?php
7954$y = 10 + match ($x) { 1 => 2, default => 0 };",
7955 "foo.php",
7956 |metric| {
7957 assert_eq!(metric.loc.sloc(), 2);
7958 assert_eq!(metric.loc.ploc(), 2);
7959 assert_eq!(metric.loc.lloc(), 1);
7960 assert_eq!(metric.loc.cloc(), 0);
7961 assert_eq!(metric.loc.blank(), 0);
7962 insta::assert_json_snapshot!(metric.loc);
7963 },
7964 );
7965 }
7966
7967 #[test]
7968 fn php_html_island_ploc() {
7969 check_metrics::<PhpParser>(
7975 "<?php if ($cond): ?>
7976<div>hello</div>
7977<p>world</p>
7978<?php endif; ?>",
7979 "foo.php",
7980 |metric| {
7981 assert_eq!(metric.loc.sloc(), 4);
7982 assert_eq!(metric.loc.ploc(), 3);
7983 assert_eq!(metric.loc.lloc(), 1);
7984 assert_eq!(metric.loc.cloc(), 0);
7985 assert_eq!(metric.loc.blank(), 1);
7986 insta::assert_json_snapshot!(metric.loc);
7987 },
7988 );
7989 }
7990
7991 #[test]
7992 fn php_short_echo_tag_ploc() {
7993 check_metrics::<PhpParser>("<p><?= $name ?></p>", "foo.php", |metric| {
7997 assert_eq!(metric.loc.sloc(), 1);
7998 assert_eq!(metric.loc.ploc(), 1);
7999 assert_eq!(metric.loc.lloc(), 1);
8000 assert_eq!(metric.loc.cloc(), 0);
8001 assert_eq!(metric.loc.blank(), 0);
8002 insta::assert_json_snapshot!(metric.loc);
8003 });
8004 }
8005
8006 #[test]
8007 fn elixir_blank() {
8008 check_metrics::<ElixirParser>(
8010 "defmodule Foo do\n\n def a, do: :a\n\n def b, do: :b\nend\n",
8011 "foo.ex",
8012 |metric| {
8013 assert_eq!(metric.loc.sloc(), 6);
8014 assert_eq!(metric.loc.ploc(), 4);
8015 assert_eq!(metric.loc.lloc(), 3);
8016 assert_eq!(metric.loc.cloc(), 0);
8017 assert_eq!(metric.loc.blank(), 2);
8018 insta::assert_json_snapshot!(
8019 metric.loc,
8020 @r#"
8021 {
8022 "sloc": 6,
8023 "ploc": 4,
8024 "lloc": 3,
8025 "cloc": 0,
8026 "blank": 2,
8027 "sloc_average": 1.5,
8028 "ploc_average": 1.0,
8029 "lloc_average": 0.75,
8030 "cloc_average": 0.0,
8031 "blank_average": 0.5,
8032 "sloc_min": 1,
8033 "sloc_max": 6,
8034 "cloc_min": 0,
8035 "cloc_max": 0,
8036 "ploc_min": 1,
8037 "ploc_max": 4,
8038 "lloc_min": 1,
8039 "lloc_max": 3,
8040 "blank_min": 0,
8041 "blank_max": 2
8042 }
8043 "#
8044 );
8045 },
8046 );
8047 }
8048
8049 #[test]
8050 fn elixir_no_zero_blank() {
8051 check_metrics::<ElixirParser>(
8054 "defmodule Foo do\n def f, do: :ok\n\n def g, do: :ok # trailing\n def h, do: :ok # trailing\nend\n",
8055 "foo.ex",
8056 |metric| {
8057 assert_eq!(metric.loc.sloc(), 6);
8058 assert_eq!(metric.loc.ploc(), 5);
8059 assert_eq!(metric.loc.cloc(), 2);
8060 assert_eq!(metric.loc.blank(), 1);
8061 },
8062 );
8063 }
8064
8065 #[test]
8066 fn elixir_blank_zero_sanity() {
8067 check_metrics::<ElixirParser>(
8070 "defmodule Foo do\n def f, do: :ok\nend\n",
8071 "foo.ex",
8072 |metric| {
8073 assert_eq!(metric.loc.blank(), 0);
8074 },
8075 );
8076 }
8077
8078 #[test]
8079 fn elixir_cloc() {
8080 check_metrics::<ElixirParser>(
8083 "# top\ndefmodule Foo do\n # body\n def f, do: :ok # trailing\nend\n",
8084 "foo.ex",
8085 |metric| {
8086 assert_eq!(metric.loc.cloc(), 3);
8087 },
8088 );
8089 }
8090
8091 #[test]
8092 fn elixir_lloc() {
8093 check_metrics::<ElixirParser>(
8098 "defmodule Foo do\n def a, do: 1\n def b, do: 2\nend\n",
8099 "foo.ex",
8100 |metric| {
8101 assert_eq!(metric.loc.lloc(), 3);
8102 },
8103 );
8104 }
8105
8106 #[test]
8107 fn elixir_no_nested_call_lloc() {
8108 check_metrics::<ElixirParser>(
8112 "defmodule Foo do\n def f do\n IO.puts(Enum.join([1, 2, 3], \", \"))\n end\nend\n",
8113 "foo.ex",
8114 |metric| {
8115 assert_eq!(metric.loc.lloc(), 3);
8116 },
8117 );
8118 }
8119
8120 #[test]
8121 fn elixir_no_binary_operator_inside_call_lloc() {
8122 check_metrics::<ElixirParser>(
8128 "defmodule Foo do\n def f(a, b) do\n IO.puts(a + b)\n end\nend\n",
8129 "foo.ex",
8130 |metric| {
8131 assert_eq!(metric.loc.lloc(), 3);
8132 },
8133 );
8134 }
8135
8136 #[test]
8137 fn elixir_stab_clause_counts_lloc() {
8138 check_metrics::<ElixirParser>(
8142 "defmodule Foo do\n def f(x) do\n case x do\n 1 -> :a\n 2 -> :b\n _ -> :c\n end\n end\nend\n",
8143 "foo.ex",
8144 |metric| {
8145 assert_eq!(metric.loc.lloc(), 6);
8146 },
8147 );
8148 }
8149
8150 #[test]
8151 fn elixir_no_comment_lloc() {
8152 check_metrics::<ElixirParser>(
8157 "# leading\ndefmodule Foo do\n # inside\n def f, do: :ok\n # trailing\nend\n",
8158 "foo.ex",
8159 |metric| {
8160 assert_eq!(metric.loc.lloc(), 2);
8161 },
8162 );
8163 }
8164
8165 #[test]
8166 fn elixir_no_do_token_lloc() {
8167 check_metrics::<ElixirParser>("defmodule Foo do\n :ok\nend\n", "foo.ex", |metric| {
8172 assert_eq!(metric.loc.lloc(), 2);
8175 });
8176 }
8177
8178 #[test]
8179 fn elixir_no_keyword_pair_lloc() {
8180 check_metrics::<ElixirParser>(
8184 "defmodule Foo do\n def add(a, b), do: a + b\nend\n",
8185 "foo.ex",
8186 |metric| {
8187 assert_eq!(metric.loc.lloc(), 2);
8189 },
8190 );
8191 }
8192
8193 #[test]
8194 fn elixir_no_string_content_lloc() {
8195 check_metrics::<ElixirParser>(
8200 "defmodule Foo do\n @moduledoc \"\"\"\n line one\n line two\n \"\"\"\n def f, do: :ok\nend\n",
8201 "foo.ex",
8202 |metric| {
8203 assert_eq!(metric.loc.lloc(), 3);
8205 },
8206 );
8207 }
8208
8209 #[test]
8210 fn elixir_rescue_arm_counts_lloc() {
8211 check_metrics::<ElixirParser>(
8218 "defmodule Foo do\n def safe do\n try do\n do_it()\n rescue\n ArgumentError -> :bad\n RuntimeError -> :worse\n end\n end\nend\n",
8219 "foo.ex",
8220 |metric| {
8221 assert_eq!(metric.loc.lloc(), 7);
8222 },
8223 );
8224 }
8225
8226 #[test]
8227 fn elixir_no_arg_punctuation_lloc() {
8228 check_metrics::<ElixirParser>(
8232 "defmodule Foo do\n def add(a, b, c, d) do\n a + b + c + d\n end\nend\n",
8233 "foo.ex",
8234 |metric| {
8235 assert_eq!(metric.loc.lloc(), 3);
8237 },
8238 );
8239 }
8240
8241 #[test]
8242 fn elixir_no_list_element_lloc() {
8243 check_metrics::<ElixirParser>(
8246 "defmodule Foo do\n def f do\n [:a, :b, :c, :d]\n end\nend\n",
8247 "foo.ex",
8248 |metric| {
8249 assert_eq!(metric.loc.lloc(), 3);
8251 },
8252 );
8253 }
8254
8255 #[test]
8256 fn elixir_no_map_field_lloc() {
8257 check_metrics::<ElixirParser>(
8259 "defmodule Foo do\n def f do\n %{a: 1, b: 2, c: 3}\n end\nend\n",
8260 "foo.ex",
8261 |metric| {
8262 assert_eq!(metric.loc.lloc(), 3);
8263 },
8264 );
8265 }
8266
8267 #[test]
8268 fn elixir_anonymous_fn_body_lloc() {
8269 check_metrics::<ElixirParser>(
8277 "defmodule Foo do\n def f do\n add = fn x -> x + 1 end\n add\n end\nend\n",
8278 "foo.ex",
8279 |metric| {
8280 assert_eq!(metric.loc.lloc(), 5);
8281 },
8282 );
8283 }
8284
8285 #[test]
8286 fn ruby_blank() {
8287 check_metrics::<RubyParser>("def foo\n a = 1\n\n a + 1\nend\n", "foo.rb", |metric| {
8291 assert_eq!(metric.loc.blank(), 1);
8292 });
8293 }
8294
8295 #[test]
8296 fn ruby_no_zero_blank() {
8297 check_metrics::<RubyParser>(
8303 "def foo # entry\n pool = 0\n\n server = -42 # negative\n\n ok = false\nend\n",
8304 "foo.rb",
8305 |metric| {
8306 assert_eq!(metric.loc.blank(), 2);
8307 },
8308 );
8309 }
8310
8311 #[test]
8312 fn ruby_cloc() {
8313 check_metrics::<RubyParser>(
8315 "# one\n# two\n# three\ndef foo\nend\n",
8316 "foo.rb",
8317 |metric| {
8318 assert_eq!(metric.loc.cloc(), 3);
8319 },
8320 );
8321 }
8322
8323 #[test]
8324 fn ruby_lloc() {
8325 check_metrics::<RubyParser>(
8329 "def foo(a)\n if a\n a += 1\n end\n while a > 0\n a -= 1\n end\nend\n",
8330 "foo.rb",
8331 |metric| {
8332 assert_eq!(metric.loc.lloc(), 3);
8333 },
8334 );
8335 }
8336
8337 #[test]
8338 fn ruby_no_call_lloc() {
8339 check_metrics::<RubyParser>(
8344 "def foo\n puts 'hello'\n puts 'world'\nend\n",
8345 "foo.rb",
8346 |metric| {
8347 assert_eq!(metric.loc.lloc(), 1);
8348 },
8349 );
8350 }
8351
8352 #[test]
8353 fn ruby_no_assignment_lloc() {
8354 check_metrics::<RubyParser>(
8357 "def foo\n a = 1\n b = 2\n c = a + b\nend\n",
8358 "foo.rb",
8359 |metric| {
8360 assert_eq!(metric.loc.lloc(), 1);
8361 },
8362 );
8363 }
8364
8365 #[test]
8366 fn ruby_modifier_lloc() {
8367 check_metrics::<RubyParser>(
8373 "def foo(a)\n return a if a.nil?\n a -= 1 while a > 0\n parse(a) rescue nil\nend\n",
8374 "foo.rb",
8375 |metric| {
8376 assert_eq!(metric.loc.lloc(), 5);
8377 },
8378 );
8379 }
8380
8381 #[test]
8382 fn ruby_class_lloc() {
8383 check_metrics::<RubyParser>(
8385 "module M\n class C\n def foo\n end\n def bar\n end\n end\nend\n",
8386 "foo.rb",
8387 |metric| {
8388 assert_eq!(metric.loc.lloc(), 4);
8389 },
8390 );
8391 }
8392
8393 #[test]
8394 fn ruby_begin_rescue_lloc() {
8395 check_metrics::<RubyParser>(
8399 "def foo\n begin\n risky\n rescue StandardError\n nil\n end\nend\n",
8400 "foo.rb",
8401 |metric| {
8402 assert_eq!(metric.loc.lloc(), 2);
8403 },
8404 );
8405 }
8406
8407 #[test]
8408 fn ruby_nested_defs_lloc() {
8409 check_metrics::<RubyParser>(
8412 "def outer\n def inner\n 1\n end\nend\n",
8413 "foo.rb",
8414 |metric| {
8415 assert_eq!(metric.loc.lloc(), 2);
8416 },
8417 );
8418 }
8419
8420 #[test]
8421 fn ruby_no_block_body_lloc() {
8422 check_metrics::<RubyParser>(
8428 "[1, 2, 3].each do |x|\n puts x\nend\n",
8429 "foo.rb",
8430 |metric| {
8431 assert_eq!(metric.loc.lloc(), 0);
8432 },
8433 );
8434 }
8435
8436 #[test]
8437 fn ruby_no_lambda_body_lloc() {
8438 check_metrics::<RubyParser>("add = ->(a, b) {\n a + b\n}\n", "foo.rb", |metric| {
8443 assert_eq!(metric.loc.lloc(), 0);
8444 });
8445 }
8446
8447 #[test]
8448 fn ruby_heredoc_lloc_and_blank() {
8449 check_metrics::<RubyParser>(
8456 "def foo\n msg = <<~TXT\n one\n two\n TXT\n msg\nend\n",
8457 "foo.rb",
8458 |metric| {
8459 assert_eq!(metric.loc.sloc(), 7);
8460 assert_eq!(metric.loc.ploc(), 7);
8461 assert_eq!(metric.loc.lloc(), 1);
8462 assert_eq!(metric.loc.blank(), 0);
8463 },
8464 );
8465 }
8466
8467 #[test]
8468 fn ruby_semicolon_multistatement_lloc_undercount() {
8469 check_metrics::<RubyParser>(
8476 "def foo\n a = 1; b = 2; a + b\nend\n",
8477 "foo.rb",
8478 |metric| {
8479 assert_eq!(metric.loc.lloc(), 1);
8480 },
8481 );
8482 }
8483
8484 #[test]
8485 fn ruby_ploc_skips_comments_and_blanks() {
8486 check_metrics::<RubyParser>("# header\n\ndef foo\n a = 1\nend\n", "foo.rb", |metric| {
8489 assert_eq!(metric.loc.ploc(), 3);
8490 assert_eq!(metric.loc.cloc(), 1);
8491 assert_eq!(metric.loc.blank(), 1);
8492 });
8493 }
8494
8495 #[test]
8504 fn python_nested_def_lloc() {
8505 check_metrics::<PythonParser>(
8509 "def outer():\n def inner():\n return 1\n return inner()\n",
8510 "foo.py",
8511 |metric| {
8512 assert_eq!(metric.loc.sloc(), 4);
8513 assert_eq!(metric.loc.ploc(), 4);
8514 assert_eq!(metric.loc.lloc(), 2);
8515 assert_eq!(metric.loc.cloc(), 0);
8516 assert_eq!(metric.loc.blank(), 0);
8517 insta::assert_json_snapshot!(metric.loc);
8518 },
8519 );
8520 }
8521
8522 #[test]
8523 fn python_lambda_in_def_lloc() {
8524 check_metrics::<PythonParser>(
8528 "def outer():\n f = lambda x: x + 1\n return f(2)\n",
8529 "foo.py",
8530 |metric| {
8531 assert_eq!(metric.loc.sloc(), 3);
8532 assert_eq!(metric.loc.ploc(), 3);
8533 assert_eq!(metric.loc.lloc(), 2);
8534 assert_eq!(metric.loc.cloc(), 0);
8535 assert_eq!(metric.loc.blank(), 0);
8536 insta::assert_json_snapshot!(metric.loc);
8537 },
8538 );
8539 }
8540
8541 #[test]
8542 fn python_match_statement_lloc() {
8543 check_metrics::<PythonParser>(
8550 "def f(x):\n match x:\n case 1: return 1\n case _: return 0\n",
8551 "foo.py",
8552 |metric| {
8553 assert_eq!(metric.loc.lloc(), 3);
8554 insta::assert_json_snapshot!(metric.loc);
8555 },
8556 );
8557 }
8558
8559 #[test]
8560 fn python_match_lloc_matches_if_else() {
8561 check_metrics::<PythonParser>(
8569 "def f(x):\n if x == 1: return 1\n else: return 0\n",
8570 "foo.py",
8571 |metric| assert_eq!(metric.loc.lloc(), 3),
8572 );
8573 check_metrics::<PythonParser>(
8574 "def f(x):\n match x:\n case 1: return 1\n case _: return 0\n",
8575 "foo.py",
8576 |metric| assert_eq!(metric.loc.lloc(), 3),
8577 );
8578 }
8579
8580 #[test]
8581 fn python_type_alias_lloc() {
8582 check_metrics::<PythonParser>("type Alias = int\nx = 1\n", "foo.py", |metric| {
8587 assert_eq!(metric.loc.lloc(), 2);
8588 insta::assert_json_snapshot!(metric.loc);
8589 });
8590 }
8591
8592 #[test]
8593 fn java_local_class_in_method_lloc() {
8594 check_metrics::<JavaParser>(
8598 "class Foo {\n int bar() {\n class Local {\n int v() { return 1; }\n }\n return new Local().v();\n }\n}\n",
8599 "foo.java",
8600 |metric| {
8601 assert_eq!(metric.loc.sloc(), 8);
8602 assert_eq!(metric.loc.ploc(), 8);
8603 assert_eq!(metric.loc.lloc(), 2);
8604 assert_eq!(metric.loc.cloc(), 0);
8605 assert_eq!(metric.loc.blank(), 0);
8606 insta::assert_json_snapshot!(metric.loc);
8607 },
8608 );
8609 }
8610
8611 #[test]
8612 fn java_lambda_in_method_lloc() {
8613 check_metrics::<JavaParser>(
8617 "class Foo {\n void bar() {\n java.util.function.IntUnaryOperator f = x -> x + 1;\n f.applyAsInt(3);\n }\n}\n",
8618 "foo.java",
8619 |metric| {
8620 assert_eq!(metric.loc.sloc(), 6);
8621 assert_eq!(metric.loc.ploc(), 6);
8622 assert_eq!(metric.loc.lloc(), 2);
8623 assert_eq!(metric.loc.cloc(), 0);
8624 assert_eq!(metric.loc.blank(), 0);
8625 insta::assert_json_snapshot!(metric.loc);
8626 },
8627 );
8628 }
8629
8630 #[test]
8631 fn groovy_blank() {
8632 check_metrics::<GroovyParser>("int x = 1\n\n\nint y = 2", "foo.groovy", |metric| {
8635 assert_eq!(metric.loc.sloc(), 4);
8636 assert_eq!(metric.loc.ploc(), 2);
8637 assert_eq!(metric.loc.lloc(), 2);
8638 assert_eq!(metric.loc.blank(), 2);
8639 });
8640 }
8641
8642 #[test]
8643 fn groovy_no_zero_blank() {
8644 check_metrics::<GroovyParser>("int x = 1", "foo.groovy", |metric| {
8646 assert_eq!(metric.loc.sloc(), 1);
8647 assert_eq!(metric.loc.blank(), 0);
8648 });
8649 }
8650
8651 #[test]
8652 fn groovy_cloc_line_comments() {
8653 check_metrics::<GroovyParser>(
8654 "// first comment
8655 int x = 1
8656 // second comment
8657 int y = 2",
8658 "foo.groovy",
8659 |metric| {
8660 assert_eq!(metric.loc.cloc(), 2);
8661 assert_eq!(metric.loc.ploc(), 2);
8662 },
8663 );
8664 }
8665
8666 #[test]
8667 fn groovy_cloc_block_comment() {
8668 check_metrics::<GroovyParser>(
8669 "/* multi
8670 line
8671 comment */
8672 int x = 1",
8673 "foo.groovy",
8674 |metric| {
8675 assert_eq!(metric.loc.cloc(), 3);
8677 },
8678 );
8679 }
8680
8681 #[test]
8682 fn groovy_cloc_groovydoc_comment() {
8683 check_metrics::<GroovyParser>(
8687 "/** groovydoc */
8688class A {
8689 int x = 1
8690}",
8691 "foo.groovy",
8692 |metric| {
8693 assert_eq!(metric.loc.cloc(), 1);
8694 assert_eq!(metric.loc.ploc(), 3);
8695 },
8696 );
8697 }
8698
8699 #[test]
8700 fn groovy_simple_lloc() {
8701 check_metrics::<GroovyParser>(
8703 "int a = 1
8704 int b = 2
8705 int c = 3",
8706 "foo.groovy",
8707 |metric| {
8708 assert_eq!(metric.loc.lloc(), 3);
8709 },
8710 );
8711 }
8712
8713 #[test]
8714 fn groovy_no_local_variable_declaration_in_for_lloc() {
8715 check_metrics::<GroovyParser>(
8719 "for (int i = 0; i < 10; i++) {
8720 println(i)
8721 }",
8722 "foo.groovy",
8723 |metric| {
8724 assert_eq!(metric.loc.lloc(), 2);
8726 },
8727 );
8728 }
8729
8730 #[test]
8731 fn groovy_lambda_in_method_lloc() {
8732 check_metrics::<GroovyParser>(
8739 "class Foo {
8740 void bar() {
8741 def f = { x -> x + 1 }
8742 f(3)
8743 }
8744 }",
8745 "foo.groovy",
8746 |metric| {
8747 assert_eq!(metric.loc.lloc(), 3);
8748 },
8749 );
8750 }
8751
8752 #[test]
8753 fn groovy_try_lloc() {
8754 check_metrics::<GroovyParser>(
8757 "void f() {
8758 try {
8759 risky()
8760 } catch (Exception e) {
8761 handle(e)
8762 }
8763 }",
8764 "foo.groovy",
8765 |metric| {
8766 assert_eq!(metric.loc.lloc(), 3);
8768 },
8769 );
8770 }
8771
8772 #[test]
8773 fn groovy_class_loc() {
8774 check_metrics::<GroovyParser>(
8776 "class A {
8777 void f() {
8778 int x = 1
8779 }
8780 void g() {
8781 int y = 2
8782 }
8783 }",
8784 "foo.groovy",
8785 |metric| {
8786 assert_eq!(metric.loc.ploc(), 8);
8790 assert_eq!(metric.loc.cloc(), 0);
8791 assert_eq!(metric.loc.lloc(), 2);
8794 },
8795 );
8796 }
8797
8798 #[test]
8799 fn groovy_partial_parse_recovers_unit() {
8800 check_metrics::<GroovyParser>("def x = (((", "foo.groovy", |metric| {
8805 assert_eq!(metric.loc.sloc(), 1);
8806 assert_eq!(metric.loc.blank(), 0);
8807 });
8808 }
8809
8810 #[test]
8811 fn groovy_sloc() {
8812 check_metrics::<GroovyParser>(
8815 "int a = 1
8816 int b = 2
8817
8818 int c = 3",
8819 "foo.groovy",
8820 |metric| {
8821 assert_eq!(metric.loc.sloc(), 4);
8822 assert_eq!(metric.loc.ploc(), 3);
8823 assert_eq!(metric.loc.blank(), 1);
8824 },
8825 );
8826 }
8827
8828 #[test]
8829 fn groovy_single_ploc() {
8830 check_metrics::<GroovyParser>("int x = 42", "foo.groovy", |metric| {
8833 assert_eq!(metric.loc.ploc(), 1);
8834 assert_eq!(metric.loc.cloc(), 0);
8835 });
8836 }
8837
8838 #[test]
8839 fn groovy_multi_ploc() {
8840 check_metrics::<GroovyParser>(
8843 "int a = 1
8844 int b = 2
8845 int c = 3
8846 int d = 4",
8847 "foo.groovy",
8848 |metric| {
8849 assert_eq!(metric.loc.ploc(), 4);
8850 assert_eq!(metric.loc.lloc(), 4);
8851 },
8852 );
8853 }
8854
8855 #[test]
8856 fn groovy_single_statement_lloc() {
8857 check_metrics::<GroovyParser>("println 'hi'", "foo.groovy", |metric| {
8860 assert_eq!(metric.loc.lloc(), 1);
8861 });
8862 }
8863
8864 #[test]
8865 fn groovy_for_lloc() {
8866 check_metrics::<GroovyParser>(
8871 "for (int i = 0; i < 100; i++) {
8872 println(i)
8873 }",
8874 "foo.groovy",
8875 |metric| {
8876 assert_eq!(metric.loc.lloc(), 2);
8878 },
8879 );
8880 }
8881
8882 #[test]
8883 fn groovy_foreach_lloc() {
8884 check_metrics::<GroovyParser>(
8887 "for (item in items) {
8888 println(item)
8889 }",
8890 "foo.groovy",
8891 |metric| {
8892 assert_eq!(metric.loc.lloc(), 2);
8894 },
8895 );
8896 }
8897
8898 #[test]
8899 fn groovy_while_lloc() {
8900 check_metrics::<GroovyParser>(
8903 "int i = 0
8904 while (i < 10) {
8905 i++
8906 println(i)
8907 }",
8908 "foo.groovy",
8909 |metric| {
8910 assert_eq!(metric.loc.lloc(), 4);
8912 },
8913 );
8914 }
8915
8916 #[test]
8917 fn groovy_do_while_lloc() {
8918 check_metrics::<GroovyParser>(
8921 "int i = 0
8922 do {
8923 i++
8924 } while (i < 5)",
8925 "foo.groovy",
8926 |metric| {
8927 assert_eq!(metric.loc.lloc(), 3);
8929 },
8930 );
8931 }
8932
8933 #[test]
8934 fn groovy_continue_lloc() {
8935 check_metrics::<GroovyParser>(
8937 "for (int i = 0; i < 10; i++) {
8938 if (i == 5) {
8939 continue
8940 }
8941 println(i)
8942 }",
8943 "foo.groovy",
8944 |metric| {
8945 assert_eq!(metric.loc.lloc(), 4);
8947 },
8948 );
8949 }
8950
8951 #[test]
8952 fn groovy_expressions_lloc() {
8953 check_metrics::<GroovyParser>(
8956 "int a = 1
8957 a = 2
8958 a += 3
8959 println(a)
8960 doSomething()",
8961 "foo.groovy",
8962 |metric| {
8963 assert_eq!(metric.loc.lloc(), 5);
8965 },
8966 );
8967 }
8968
8969 #[test]
8970 fn groovy_throw_lloc() {
8971 check_metrics::<GroovyParser>(
8973 "throw new RuntimeException('bad')",
8974 "foo.groovy",
8975 |metric| {
8976 assert_eq!(metric.loc.lloc(), 1);
8977 },
8978 );
8979 }
8980
8981 #[test]
8982 fn groovy_general_loc() {
8983 check_metrics::<GroovyParser>(
8995 "class A {
8996 void f(int x) {
8997 if (x > 0) {
8998 println(x)
8999 } else {
9000 println 'neg'
9001 }
9002 return
9003 }
9004 }",
9005 "foo.groovy",
9006 |metric| {
9007 assert_eq!(metric.loc.lloc(), 4);
9008 assert_eq!(metric.loc.cloc(), 0);
9009 },
9010 );
9011 }
9012
9013 #[test]
9014 fn csharp_local_function_in_method_lloc() {
9015 check_metrics::<CsharpParser>(
9019 "class Foo {\n int Bar() {\n int Inner(int x) { return x + 1; }\n return Inner(2);\n }\n}\n",
9020 "foo.cs",
9021 |metric| {
9022 assert_eq!(metric.loc.sloc(), 6);
9023 assert_eq!(metric.loc.ploc(), 6);
9024 assert_eq!(metric.loc.lloc(), 2);
9025 assert_eq!(metric.loc.cloc(), 0);
9026 assert_eq!(metric.loc.blank(), 0);
9027 insta::assert_json_snapshot!(metric.loc);
9028 },
9029 );
9030 }
9031
9032 #[test]
9033 fn csharp_lambda_in_method_lloc() {
9034 check_metrics::<CsharpParser>(
9037 "class Foo {\n void Bar() {\n System.Func<int, int> f = x => x + 1;\n f(3);\n }\n}\n",
9038 "foo.cs",
9039 |metric| {
9040 assert_eq!(metric.loc.sloc(), 6);
9041 assert_eq!(metric.loc.ploc(), 6);
9042 assert_eq!(metric.loc.lloc(), 2);
9043 assert_eq!(metric.loc.cloc(), 0);
9044 assert_eq!(metric.loc.blank(), 0);
9045 insta::assert_json_snapshot!(metric.loc);
9046 },
9047 );
9048 }
9049
9050 #[test]
9051 fn cpp_lambda_in_function_lloc() {
9052 check_metrics::<CppParser>(
9060 "int bar() {\n auto f = [](int x) { return x + 1; };\n return f(2);\n}\n",
9061 "foo.cpp",
9062 |metric| {
9063 assert_eq!(metric.loc.sloc(), 4);
9064 assert_eq!(metric.loc.ploc(), 4);
9065 assert_eq!(metric.loc.lloc(), 3);
9066 assert_eq!(metric.loc.cloc(), 0);
9067 assert_eq!(metric.loc.blank(), 0);
9068 insta::assert_json_snapshot!(metric.loc);
9069 },
9070 );
9071 }
9072
9073 #[test]
9074 fn javascript_nested_function_lloc() {
9075 check_metrics::<JavascriptParser>(
9079 "function outer() {\n function inner() {\n return 1;\n }\n return inner();\n}\n",
9080 "foo.js",
9081 |metric| {
9082 assert_eq!(metric.loc.sloc(), 6);
9083 assert_eq!(metric.loc.ploc(), 6);
9084 assert_eq!(metric.loc.lloc(), 2);
9085 assert_eq!(metric.loc.cloc(), 0);
9086 assert_eq!(metric.loc.blank(), 0);
9087 insta::assert_json_snapshot!(metric.loc);
9088 },
9089 );
9090 }
9091
9092 #[test]
9093 fn javascript_arrow_function_lloc() {
9094 check_metrics::<JavascriptParser>(
9097 "function outer() {\n const inner = (x) => x + 1;\n return inner(2);\n}\n",
9098 "foo.js",
9099 |metric| {
9100 assert_eq!(metric.loc.sloc(), 4);
9101 assert_eq!(metric.loc.ploc(), 4);
9102 assert_eq!(metric.loc.lloc(), 1);
9103 assert_eq!(metric.loc.cloc(), 0);
9104 assert_eq!(metric.loc.blank(), 0);
9105 insta::assert_json_snapshot!(metric.loc);
9106 },
9107 );
9108 }
9109
9110 #[test]
9111 fn kotlin_lambda_literal_in_fun_lloc() {
9112 check_metrics::<KotlinParser>(
9115 "fun outer() {\n val f: (Int) -> Int = { x -> x + 1 }\n f(3)\n}\n",
9116 "foo.kt",
9117 |metric| {
9118 assert_eq!(metric.loc.sloc(), 4);
9119 assert_eq!(metric.loc.ploc(), 4);
9120 assert_eq!(metric.loc.lloc(), 2);
9121 assert_eq!(metric.loc.cloc(), 0);
9122 assert_eq!(metric.loc.blank(), 0);
9123 insta::assert_json_snapshot!(metric.loc);
9124 },
9125 );
9126 }
9127
9128 #[test]
9129 fn kotlin_local_fun_in_fun_lloc() {
9130 check_metrics::<KotlinParser>(
9134 "fun outer() {\n fun inner(x: Int): Int { return x + 1 }\n inner(3)\n}\n",
9135 "foo.kt",
9136 |metric| {
9137 assert_eq!(metric.loc.sloc(), 4);
9138 assert_eq!(metric.loc.ploc(), 4);
9139 assert_eq!(metric.loc.lloc(), 2);
9140 assert_eq!(metric.loc.cloc(), 0);
9141 assert_eq!(metric.loc.blank(), 0);
9142 insta::assert_json_snapshot!(metric.loc);
9143 },
9144 );
9145 }
9146
9147 #[test]
9148 fn kotlin_object_expression_in_fun_lloc() {
9149 check_metrics::<KotlinParser>(
9153 "fun outer() {\n val r = object : Runnable { override fun run() { println(\"hi\") } }\n r.run()\n}\n",
9154 "foo.kt",
9155 |metric| {
9156 assert_eq!(metric.loc.sloc(), 4);
9157 assert_eq!(metric.loc.ploc(), 4);
9158 assert_eq!(metric.loc.lloc(), 3);
9159 assert_eq!(metric.loc.cloc(), 0);
9160 assert_eq!(metric.loc.blank(), 0);
9161 insta::assert_json_snapshot!(metric.loc);
9162 },
9163 );
9164 }
9165
9166 #[test]
9167 fn go_function_literal_initializer_lloc() {
9168 check_metrics::<GoParser>(
9173 "package main\nfunc outer() int {\n inner := func(x int) int { return x + 1 }\n return inner(2)\n}\n",
9174 "foo.go",
9175 |metric| {
9176 assert_eq!(metric.loc.sloc(), 5);
9177 assert_eq!(metric.loc.ploc(), 5);
9178 assert_eq!(metric.loc.lloc(), 3);
9179 assert_eq!(metric.loc.cloc(), 0);
9180 assert_eq!(metric.loc.blank(), 0);
9181 insta::assert_json_snapshot!(metric.loc);
9182 },
9183 );
9184 }
9185
9186 #[test]
9187 fn php_anonymous_function_in_function_lloc() {
9188 check_metrics::<PhpParser>(
9192 "<?php\nfunction outer() {\n $f = function ($x) { return $x + 1; };\n return $f(2);\n}\n",
9193 "foo.php",
9194 |metric| {
9195 assert_eq!(metric.loc.sloc(), 5);
9196 assert_eq!(metric.loc.ploc(), 5);
9197 assert_eq!(metric.loc.lloc(), 3);
9198 assert_eq!(metric.loc.cloc(), 0);
9199 assert_eq!(metric.loc.blank(), 0);
9200 insta::assert_json_snapshot!(metric.loc);
9201 },
9202 );
9203 }
9204
9205 #[test]
9206 fn php_arrow_function_in_function_lloc() {
9207 check_metrics::<PhpParser>(
9210 "<?php\nfunction outer() {\n $f = fn ($x) => $x + 1;\n return $f(2);\n}\n",
9211 "foo.php",
9212 |metric| {
9213 assert_eq!(metric.loc.sloc(), 5);
9214 assert_eq!(metric.loc.ploc(), 5);
9215 assert_eq!(metric.loc.lloc(), 2);
9216 assert_eq!(metric.loc.cloc(), 0);
9217 assert_eq!(metric.loc.blank(), 0);
9218 insta::assert_json_snapshot!(metric.loc);
9219 },
9220 );
9221 }
9222
9223 #[test]
9224 fn lua_nested_local_function_lloc() {
9225 check_metrics::<LuaParser>(
9229 "local function outer()\n local function inner()\n return 1\n end\n return inner()\nend\n",
9230 "foo.lua",
9231 |metric| {
9232 assert_eq!(metric.loc.sloc(), 6);
9233 assert_eq!(metric.loc.ploc(), 6);
9234 assert_eq!(metric.loc.lloc(), 4);
9235 assert_eq!(metric.loc.cloc(), 0);
9236 assert_eq!(metric.loc.blank(), 0);
9237 insta::assert_json_snapshot!(metric.loc);
9238 },
9239 );
9240 }
9241
9242 #[test]
9243 fn lua_function_expression_in_local_decl_lloc() {
9244 check_metrics::<LuaParser>(
9249 "local function outer()\n local f = function (x) return x + 1 end\n return f(2)\nend\n",
9250 "foo.lua",
9251 |metric| {
9252 assert_eq!(metric.loc.sloc(), 4);
9253 assert_eq!(metric.loc.ploc(), 4);
9254 assert_eq!(metric.loc.lloc(), 4);
9255 assert_eq!(metric.loc.cloc(), 0);
9256 assert_eq!(metric.loc.blank(), 0);
9257 insta::assert_json_snapshot!(metric.loc);
9258 },
9259 );
9260 }
9261
9262 #[test]
9263 fn tcl_apply_closure_lloc() {
9264 check_metrics::<TclParser>(
9271 "proc outer {} {\n set f [list x {return [expr {$x + 1}]}]\n apply $f 2\n}\n",
9272 "foo.tcl",
9273 |metric| {
9274 assert_eq!(metric.loc.sloc(), 4);
9275 assert_eq!(metric.loc.ploc(), 4);
9276 assert_eq!(metric.loc.lloc(), 4);
9277 assert_eq!(metric.loc.cloc(), 0);
9278 assert_eq!(metric.loc.blank(), 0);
9279 insta::assert_json_snapshot!(metric.loc);
9280 },
9281 );
9282 }
9283
9284 #[test]
9285 fn perl_anonymous_sub_in_sub_lloc() {
9286 check_metrics::<PerlParser>(
9296 "sub outer {\n my $f = sub { return $_[0] + 1 };\n return $f->(2);\n}\n",
9297 "foo.pl",
9298 |metric| {
9299 assert_eq!(metric.loc.sloc(), 4);
9300 assert_eq!(metric.loc.ploc(), 4);
9301 assert_eq!(metric.loc.lloc(), 2);
9302 assert_eq!(metric.loc.cloc(), 0);
9303 assert_eq!(metric.loc.blank(), 0);
9304 insta::assert_json_snapshot!(metric.loc);
9305 },
9306 );
9307 }
9308
9309 #[test]
9310 fn perl_named_sub_in_sub_lloc() {
9311 check_metrics::<PerlParser>(
9326 "sub outer {\n sub inner { return 1 }\n return inner();\n}\n",
9327 "foo.pl",
9328 |metric| {
9329 assert_eq!(metric.loc.sloc(), 4);
9330 assert_eq!(metric.loc.ploc(), 4);
9331 assert_eq!(metric.loc.lloc(), 1);
9332 assert_eq!(metric.loc.cloc(), 0);
9333 assert_eq!(metric.loc.blank(), 0);
9334 insta::assert_json_snapshot!(metric.loc);
9335 },
9336 );
9337 }
9338
9339 #[test]
9340 fn elixir_fn_inside_def_lloc() {
9341 check_metrics::<ElixirParser>(
9345 "defmodule Foo do\n def outer do\n f = fn x -> x + 1 end\n f.(2)\n end\nend\n",
9346 "foo.ex",
9347 |metric| {
9348 assert_eq!(metric.loc.sloc(), 6);
9349 assert_eq!(metric.loc.ploc(), 6);
9350 assert_eq!(metric.loc.lloc(), 5);
9351 assert_eq!(metric.loc.cloc(), 0);
9352 assert_eq!(metric.loc.blank(), 0);
9353 insta::assert_json_snapshot!(metric.loc);
9354 },
9355 );
9356 }
9357
9358 #[test]
9370 fn rust_nested_min_max_propagates() {
9371 check_metrics::<RustParser>(
9372 "struct C;\nimpl C {\n fn small(&self) {\n let _ = 1;\n }\n fn big(&self) {\n let _ = 1;\n let _ = 2;\n let _ = 3;\n }\n}\n",
9373 "c.rs",
9374 |metric| {
9375 let loc = &metric.loc;
9381 assert!(
9382 loc.sloc_min() <= loc.sloc(),
9383 "sloc_min {} must not exceed unit sloc {}",
9384 loc.sloc_min(),
9385 loc.sloc()
9386 );
9387 assert_eq!(loc.sloc_min(), 3, "smallest leaf method span");
9388 assert_eq!(loc.sloc_max(), loc.sloc(), "largest space is the unit");
9389 assert_eq!(loc.lloc_min(), 1);
9391 },
9392 );
9393 }
9394
9395 #[test]
9400 fn java_nested_min_max_propagates() {
9401 check_metrics::<JavaParser>(
9402 "public class C {\n void small() {\n int x = 1;\n }\n void big() {\n int a = 1;\n int b = 2;\n int c = 3;\n }\n}\n",
9403 "C.java",
9404 |metric| {
9405 let loc = &metric.loc;
9407 assert!(loc.sloc_min() <= loc.sloc());
9408 assert_eq!(loc.sloc_min(), 3, "smallest leaf method span");
9409 assert_eq!(loc.sloc_max(), loc.sloc());
9410 assert_eq!(loc.lloc_min(), 1);
9411 },
9412 );
9413 }
9414
9415 #[test]
9419 fn python_nested_min_max_propagates() {
9420 check_metrics::<PythonParser>(
9421 "class C:\n def small(self):\n x = 1\n def big(self):\n a = 1\n b = 2\n c = 3\n",
9422 "c.py",
9423 |metric| {
9424 let loc = &metric.loc;
9426 assert!(loc.sloc_min() <= loc.sloc());
9427 assert_eq!(loc.sloc_min(), 2, "smallest leaf method span");
9428 assert_eq!(loc.sloc_max(), loc.sloc());
9429 assert_eq!(loc.lloc_min(), 1);
9430 },
9431 );
9432 }
9433
9434 #[test]
9447 fn blank_clamps_negative_to_zero() {
9448 let mut stats = Stats::default();
9449 stats.sloc.start = 0;
9451 stats.sloc.end_line = 1;
9453 stats.ploc.lines.insert(0);
9455 stats.cloc.only_comment_line_starts.insert(0);
9457
9458 assert_eq!(stats.sloc(), 1);
9460 assert_eq!(stats.ploc(), 1);
9461 assert_eq!(
9462 stats.blank(),
9463 0,
9464 "blank() must clamp the negative subtraction to 0"
9465 );
9466 }
9467
9468 #[test]
9483 fn sibling_spaces_sharing_a_line_count_it_once() {
9484 check_metrics::<RustParser>(
9485 "fn a() { let x = 1; } fn b() { let y = 2; }",
9486 "foo.rs",
9487 |metric| {
9488 assert_eq!(metric.loc.sloc(), 1);
9489 assert_eq!(metric.loc.ploc(), 1, "one physical row, two spaces");
9490 assert_eq!(metric.loc.blank(), 0);
9491 },
9492 );
9493
9494 check_metrics::<CppParser>(
9495 "int a() { return 1; } int b() { return 2; }",
9496 "foo.cpp",
9497 |metric| {
9498 assert_eq!(metric.loc.sloc(), 1);
9499 assert_eq!(metric.loc.ploc(), 1, "one physical row, two spaces");
9500 assert_eq!(metric.loc.blank(), 0);
9501 },
9502 );
9503
9504 check_metrics::<JavascriptParser>(
9505 "function a() { let x = 1; } function b() { let y = 2; }",
9506 "foo.js",
9507 |metric| {
9508 assert_eq!(metric.loc.sloc(), 1);
9509 assert_eq!(metric.loc.ploc(), 1, "one physical row, two spaces");
9510 assert_eq!(metric.loc.blank(), 0);
9511 },
9512 );
9513
9514 check_metrics::<PythonParser>(
9518 "def a():
9519 def b(): return 1",
9520 "foo.py",
9521 |metric| {
9522 assert_eq!(metric.loc.sloc(), 2);
9523 assert_eq!(metric.loc.ploc(), 2, "two physical rows, three spaces");
9524 assert_eq!(metric.loc.blank(), 0);
9525 },
9526 );
9527 }
9528
9529 #[test]
9537 fn sibling_spaces_sharing_a_comment_line_count_it_once() {
9538 check_metrics::<CppParser>(
9539 "int a() { /*x*/ return 1; } int b() { /*y*/ return 2; }",
9540 "foo.cpp",
9541 |metric| {
9542 assert_eq!(metric.loc.sloc(), 1);
9543 assert_eq!(metric.loc.cloc(), 1, "one comment row, two spaces");
9544 assert!(
9545 metric.loc.cloc() <= metric.loc.sloc(),
9546 "cloc must never exceed sloc"
9547 );
9548 },
9549 );
9550
9551 check_metrics::<RustParser>(
9552 "fn a() { /*x*/ let p = 1; } fn b() { /*y*/ let q = 2; }",
9553 "foo.rs",
9554 |metric| {
9555 assert_eq!(metric.loc.sloc(), 1);
9556 assert_eq!(metric.loc.cloc(), 1, "one comment row, two spaces");
9557 assert!(
9558 metric.loc.cloc() <= metric.loc.sloc(),
9559 "cloc must never exceed sloc"
9560 );
9561 },
9562 );
9563 }
9564
9565 #[test]
9573 fn a_row_folded_through_nested_spaces_counts_once() {
9574 const DEPTH: usize = 15;
9575 let source = format!(
9576 "{}let x = 1;{}",
9577 "fn f() { ".repeat(DEPTH),
9578 "} ".repeat(DEPTH)
9579 );
9580
9581 check_metrics::<RustParser>(&source, "foo.rs", |metric| {
9582 assert_eq!(metric.loc.sloc(), 1);
9583 assert_eq!(metric.loc.ploc(), 1, "one physical row, {DEPTH} spaces");
9584 assert_eq!(metric.loc.ploc_max(), 1);
9585 assert_eq!(metric.loc.blank(), 0);
9586 });
9587 }
9588
9589 #[test]
9597 fn cloc_multiple_block_comments_one_line_cpp() {
9598 check_metrics::<CppParser>(
9599 "int f(int /*a*/, int /*b*/) { return 1; }",
9600 "foo.cpp",
9601 |metric| {
9602 assert_eq!(metric.loc.cloc(), 1, "two inline comments => 1 cloc");
9603 assert!(
9604 metric.loc.cloc() <= metric.loc.sloc(),
9605 "cloc must not exceed sloc"
9606 );
9607 assert!(
9608 metric.loc.cloc() <= metric.loc.ploc(),
9609 "cloc must not exceed ploc for a single-line construct"
9610 );
9611 },
9612 );
9613 }
9614
9615 #[test]
9619 fn cloc_multiple_block_comments_one_line_rust() {
9620 check_metrics::<RustParser>(
9621 "fn f(/*a*/ x: i32, /*b*/ y: i32) -> i32 { 1 }",
9622 "foo.rs",
9623 |metric| {
9624 assert_eq!(metric.loc.cloc(), 1, "two inline comments => 1 cloc");
9625 assert!(
9626 metric.loc.cloc() <= metric.loc.sloc(),
9627 "cloc must not exceed sloc"
9628 );
9629 },
9630 );
9631 }
9632
9633 #[test]
9638 fn cloc_multiline_block_comment_counts_each_line() {
9639 check_metrics::<CppParser>(
9640 "int g() {\n /* l1\n l2\n l3 */\n return 0;\n}",
9641 "foo.cpp",
9642 |metric| {
9643 assert_eq!(
9644 metric.loc.cloc(),
9645 3,
9646 "a 3-line block comment counts 3 comment lines"
9647 );
9648 },
9649 );
9650 }
9651
9652 #[test]
9661 fn cloc_multiple_standalone_block_comments_one_line_cpp() {
9662 check_metrics::<CppParser>("/*a*/ /*b*/", "foo.cpp", |metric| {
9663 assert_eq!(
9664 metric.loc.cloc(),
9665 1,
9666 "two standalone comments on one line => 1 cloc"
9667 );
9668 assert_eq!(metric.loc.sloc(), 1);
9669 assert!(
9670 metric.loc.cloc() <= metric.loc.sloc(),
9671 "cloc must not exceed sloc"
9672 );
9673 });
9674 }
9675
9676 #[test]
9680 fn cloc_multiple_standalone_block_comments_one_line_rust() {
9681 check_metrics::<RustParser>("/*a*/ /*b*/", "foo.rs", |metric| {
9682 assert_eq!(
9683 metric.loc.cloc(),
9684 1,
9685 "two standalone comments on one line => 1 cloc"
9686 );
9687 assert_eq!(metric.loc.sloc(), 1);
9688 assert!(
9689 metric.loc.cloc() <= metric.loc.sloc(),
9690 "cloc must not exceed sloc"
9691 );
9692 });
9693 }
9694
9695 #[test]
9702 fn cloc_standalone_comments_then_code_no_double_count() {
9703 check_metrics::<CppParser>("/*a*/ /*b*/ /*c*/\nint x = 1;\n", "foo.cpp", |metric| {
9704 assert_eq!(metric.loc.sloc(), 2);
9705 assert_eq!(
9706 metric.loc.cloc(),
9707 1,
9708 "only line 1 carries comments => 1 cloc"
9709 );
9710 assert!(
9711 metric.loc.cloc() <= metric.loc.sloc(),
9712 "cloc must not exceed sloc"
9713 );
9714 });
9715 }
9716
9717 #[test]
9721 fn irules_blank() {
9722 check_metrics::<IrulesParser>(
9723 "when X {\n\n set x 1\n\n set y 2\n}\n",
9724 "foo.irule",
9725 |metric| {
9726 assert_eq!(metric.loc.sloc(), 6);
9727 assert_eq!(metric.loc.ploc(), 4);
9728 assert_eq!(metric.loc.lloc(), 3);
9729 assert_eq!(metric.loc.cloc(), 0);
9730 assert_eq!(metric.loc.blank(), 2);
9731 },
9732 );
9733 }
9734
9735 #[test]
9738 fn irules_no_zero_blank() {
9739 check_metrics::<IrulesParser>(
9740 "when HTTP_REQUEST {\n set x 1\n log local0. $x\n}\n",
9741 "foo.irule",
9742 |metric| {
9743 assert_eq!(metric.loc.sloc(), 4);
9744 assert_eq!(metric.loc.ploc(), 4);
9745 assert_eq!(metric.loc.lloc(), 3);
9746 assert_eq!(metric.loc.blank(), 0);
9747 },
9748 );
9749 }
9750
9751 #[test]
9760 fn irules_cloc() {
9761 check_metrics::<IrulesParser>(
9762 "# a\n# b\n# c\nwhen X { set x 1 }\n",
9763 "foo.irule",
9764 |metric| {
9765 assert_eq!(metric.loc.sloc(), 4);
9766 assert_eq!(metric.loc.ploc(), 1);
9767 assert_eq!(metric.loc.cloc(), 3);
9768 assert_eq!(metric.loc.blank(), 0);
9769 },
9770 );
9771 }
9772
9773 #[test]
9777 fn irules_lloc() {
9778 check_metrics::<IrulesParser>(
9779 "when X {\n if { $a } {\n set x 1\n }\n log local0. done\n}\n",
9780 "foo.irule",
9781 |metric| {
9782 assert_eq!(metric.loc.lloc(), 4);
9783 },
9784 );
9785 }
9786
9787 #[test]
9793 fn irules_no_command_substitution_lloc() {
9794 check_metrics::<IrulesParser>(
9795 "when X {\n set y [expr { 1 + 2 }]\n}\n",
9796 "foo.irule",
9797 |metric| {
9798 assert_eq!(metric.loc.lloc(), 2);
9799 },
9800 );
9801 }
9802
9803 #[test]
9807 fn irules_switch_lloc() {
9808 check_metrics::<IrulesParser>(
9809 "when X {\n switch $h {\n a { set r 1 }\n b { set r 2 }\n }\n}\n",
9810 "foo.irule",
9811 |metric| {
9812 assert_eq!(metric.loc.lloc(), 4);
9813 },
9814 );
9815 }
9816
9817 #[test]
9820 fn irules_proc_lloc() {
9821 check_metrics::<IrulesParser>(
9822 "proc f { a } {\n return $a\n}\n",
9823 "foo.irule",
9824 |metric| {
9825 assert_eq!(metric.loc.lloc(), 2);
9826 },
9827 );
9828 }
9829
9830 #[test]
9833 fn objc_blank() {
9834 check_metrics::<ObjcParser>(
9835 "
9836
9837 int a = 42;
9838
9839 int b = 43;
9840
9841 ",
9842 "foo.m",
9843 |metric| {
9844 assert_eq!(metric.loc.blank(), 1);
9845 insta::assert_json_snapshot!(metric.loc, @r#"
9846 {
9847 "sloc": 3,
9848 "ploc": 2,
9849 "lloc": 2,
9850 "cloc": 0,
9851 "blank": 1,
9852 "sloc_average": 3.0,
9853 "ploc_average": 2.0,
9854 "lloc_average": 2.0,
9855 "cloc_average": 0.0,
9856 "blank_average": 1.0,
9857 "sloc_min": 3,
9858 "sloc_max": 3,
9859 "cloc_min": 0,
9860 "cloc_max": 0,
9861 "ploc_min": 2,
9862 "ploc_max": 2,
9863 "lloc_min": 2,
9864 "lloc_max": 2,
9865 "blank_min": 1,
9866 "blank_max": 1
9867 }
9868 "#);
9869 },
9870 );
9871 }
9872
9873 #[test]
9876 fn objc_cloc() {
9877 check_metrics::<ObjcParser>(
9878 "/* Block comment
9879 still the block */
9880 // Line comment
9881 int a = 42; // trailing",
9882 "foo.m",
9883 |metric| {
9884 insta::assert_json_snapshot!(metric.loc, @r#"
9885 {
9886 "sloc": 4,
9887 "ploc": 1,
9888 "lloc": 1,
9889 "cloc": 4,
9890 "blank": 0,
9891 "sloc_average": 4.0,
9892 "ploc_average": 1.0,
9893 "lloc_average": 1.0,
9894 "cloc_average": 4.0,
9895 "blank_average": 0.0,
9896 "sloc_min": 4,
9897 "sloc_max": 4,
9898 "cloc_min": 4,
9899 "cloc_max": 4,
9900 "ploc_min": 1,
9901 "ploc_max": 1,
9902 "lloc_min": 1,
9903 "lloc_max": 1,
9904 "blank_min": 0,
9905 "blank_max": 0
9906 }
9907 "#);
9908 },
9909 );
9910 }
9911
9912 #[test]
9916 fn objc_lloc() {
9917 check_metrics::<ObjcParser>(
9918 "@implementation Foo
9919- (int)bar {
9920 int a = 1;
9921 int b = 2;
9922 return a + b;
9923}
9924@end
9925",
9926 "foo.m",
9927 |metric| {
9928 assert_eq!(metric.loc.lloc(), 3);
9931 insta::assert_json_snapshot!(metric.loc, @r#"
9932 {
9933 "sloc": 7,
9934 "ploc": 7,
9935 "lloc": 3,
9936 "cloc": 0,
9937 "blank": 0,
9938 "sloc_average": 2.3333333333333335,
9939 "ploc_average": 2.3333333333333335,
9940 "lloc_average": 1.0,
9941 "cloc_average": 0.0,
9942 "blank_average": 0.0,
9943 "sloc_min": 5,
9944 "sloc_max": 7,
9945 "cloc_min": 0,
9946 "cloc_max": 0,
9947 "ploc_min": 5,
9948 "ploc_max": 7,
9949 "lloc_min": 3,
9950 "lloc_max": 3,
9951 "blank_min": 0,
9952 "blank_max": 0
9953 }
9954 "#);
9955 },
9956 );
9957 }
9958
9959 #[test]
9965 fn objc_no_declaration_in_for_header_lloc() {
9966 check_metrics::<ObjcParser>(
9967 "@implementation Foo
9968- (void)bar {
9969 for (int i = 0; i < 10; ++i) {
9970 [self use:i];
9971 }
9972}
9973@end
9974",
9975 "foo.m",
9976 |metric| {
9977 assert_eq!(metric.loc.lloc(), 2);
9981 insta::assert_json_snapshot!(metric.loc, @r#"
9982 {
9983 "sloc": 7,
9984 "ploc": 7,
9985 "lloc": 2,
9986 "cloc": 0,
9987 "blank": 0,
9988 "sloc_average": 2.3333333333333335,
9989 "ploc_average": 2.3333333333333335,
9990 "lloc_average": 0.6666666666666666,
9991 "cloc_average": 0.0,
9992 "blank_average": 0.0,
9993 "sloc_min": 5,
9994 "sloc_max": 7,
9995 "cloc_min": 0,
9996 "cloc_max": 0,
9997 "ploc_min": 5,
9998 "ploc_max": 7,
9999 "lloc_min": 2,
10000 "lloc_max": 2,
10001 "blank_min": 0,
10002 "blank_max": 0
10003 }
10004 "#);
10005 },
10006 );
10007 }
10008
10009 #[test]
10010 fn objc_at_directives_lloc() {
10011 check_metrics::<ObjcParser>(
10017 "@implementation Foo
10018- (void)bar {
10019 @synchronized (self) {
10020 [self use];
10021 }
10022 @autoreleasepool {
10023 [self use];
10024 }
10025}
10026@end
10027",
10028 "foo.m",
10029 |metric| {
10030 assert_eq!(metric.loc.lloc(), 3);
10035 insta::assert_json_snapshot!(metric.loc, @r#"
10036 {
10037 "sloc": 10,
10038 "ploc": 10,
10039 "lloc": 3,
10040 "cloc": 0,
10041 "blank": 0,
10042 "sloc_average": 3.3333333333333335,
10043 "ploc_average": 3.3333333333333335,
10044 "lloc_average": 1.0,
10045 "cloc_average": 0.0,
10046 "blank_average": 0.0,
10047 "sloc_min": 8,
10048 "sloc_max": 10,
10049 "cloc_min": 0,
10050 "cloc_max": 0,
10051 "ploc_min": 8,
10052 "ploc_max": 10,
10053 "lloc_min": 3,
10054 "lloc_max": 3,
10055 "blank_min": 0,
10056 "blank_max": 0
10057 }
10058 "#);
10059 },
10060 );
10061 }
10062
10063 fn rust_loc(source: &[u8]) -> Stats {
10068 metrics_verbatim(crate::LANG::Rust, source, crate::MetricsOptions::default()).loc
10069 }
10070
10071 #[test]
10078 fn rust_doc_comment_at_eof_does_not_underflow() {
10079 let outer = rust_loc(b"/// x");
10082 assert_eq!(outer.cloc(), 1);
10083 assert_eq!(outer.ploc(), 0);
10084
10085 let inner = rust_loc(b"//! x");
10086 assert_eq!(inner.cloc(), 1);
10087 assert_eq!(inner.ploc(), 0);
10088
10089 let after_code = rust_loc(b"fn f(){}\n/// x");
10093 assert_eq!(after_code.cloc(), 1);
10094 assert_eq!(after_code.ploc(), 1);
10095
10096 assert_eq!(rust_loc(b"/// a\n/// b").cloc(), 2);
10099
10100 let trailing = rust_loc(b"let x = 1; /// d");
10105 assert_eq!(trailing.cloc(), 1);
10106 assert_eq!(trailing.ploc(), 1);
10107 }
10108
10109 #[test]
10114 fn rust_doc_comment_at_eof_matches_plain_comment() {
10115 let plain = rust_loc(b"// x");
10116 assert_eq!(plain.cloc(), 1);
10120 assert_eq!(plain.ploc(), 0);
10121
10122 for doc in [&b"/// x"[..], &b"//! x"[..]] {
10123 let doc = rust_loc(doc);
10124 assert_eq!(doc.cloc(), plain.cloc());
10125 assert_eq!(doc.ploc(), plain.ploc());
10126 assert_eq!(doc.sloc(), plain.sloc());
10127 assert_eq!(doc.blank(), plain.blank());
10128 }
10129 }
10130
10131 #[test]
10137 fn rust_doc_comment_with_trailing_newline_still_discounts_the_row() {
10138 assert_eq!(rust_loc(b"/// x\n").cloc(), 1);
10140 assert_eq!(rust_loc(b"/// a\n/// b\n").cloc(), 2);
10142
10143 let documented = rust_loc(b"/// doc\nfn f() {}\n");
10146 assert_eq!(documented.cloc(), 1);
10147 assert_eq!(documented.ploc(), 1);
10148 }
10149
10150 #[test]
10157 fn rust_doc_comment_crlf_still_discounts_the_row() {
10158 assert_eq!(rust_loc(b"/// x\r\n").cloc(), 1);
10160 let after_code = rust_loc(b"fn f(){}\r\n/// x");
10162 assert_eq!(after_code.cloc(), 1);
10163 assert_eq!(after_code.ploc(), 1);
10164 assert_eq!(rust_loc(b"/// x\r").cloc(), 1);
10166 }
10167
10168 const UNTERMINATED_ONE_LINERS: &[(crate::LANG, &[u8])] = &[
10191 (crate::LANG::Rust, b"fn main() {}"),
10192 (crate::LANG::C, b"int main(void) { return 0; }"),
10193 (crate::LANG::Cpp, b"int main() { return 0; }"),
10194 (crate::LANG::Mozcpp, b"int main() { return 0; }"),
10195 (crate::LANG::Objc, b"int main(void) { return 0; }"),
10196 (crate::LANG::Csharp, b"class C { void M() {} }"),
10197 (crate::LANG::Java, b"class C { void m() {} }"),
10198 (crate::LANG::Kotlin, b"fun main() {}"),
10199 (crate::LANG::Groovy, b"def f() {}"),
10200 (crate::LANG::Go, b"package main"),
10201 (crate::LANG::Javascript, b"function f() {}"),
10202 (crate::LANG::Mozjs, b"function f() {}"),
10203 (crate::LANG::Typescript, b"function f(): void {}"),
10204 (crate::LANG::Tsx, b"function f() {}"),
10205 (crate::LANG::Python, b"def f(): pass"),
10206 (crate::LANG::Ruby, b"def f; end"),
10207 (crate::LANG::Php, b"<?php function f() {}"),
10208 (crate::LANG::Perl, b"sub f { return 1; }"),
10209 (crate::LANG::Bash, b"f() { echo hi; }"),
10210 (crate::LANG::Lua, b"function f() end"),
10211 (crate::LANG::Tcl, b"proc f {} {}"),
10212 (crate::LANG::Irules, b"proc f {} {}"),
10213 (crate::LANG::Elixir, b"defmodule M do end"),
10214 ];
10215
10216 #[test]
10227 fn unterminated_one_line_file_reports_one_source_line() {
10228 for (lang, source) in UNTERMINATED_ONE_LINERS {
10229 let text = String::from_utf8_lossy(source);
10230 let loc = metrics_verbatim(*lang, source, MetricsOptions::default()).loc;
10231 assert_eq!(loc.sloc(), 1, "{lang:?} sloc for {text:?}");
10232 assert_eq!(loc.sloc_max(), 1, "{lang:?} sloc_max for {text:?}");
10234 assert!(
10240 loc.cloc() + loc.ploc() <= loc.sloc(),
10241 "{lang:?}: cloc {} + ploc {} exceeds sloc {} for {text:?}",
10242 loc.cloc(),
10243 loc.ploc(),
10244 loc.sloc(),
10245 );
10246 }
10247 }
10248
10249 #[test]
10259 fn no_op_loc_grammars_still_count_their_unterminated_row() {
10260 for (lang, source) in [
10261 (crate::LANG::Preproc, &b"#define A 1"[..]),
10262 (crate::LANG::Ccomment, &b"/* c */"[..]),
10263 ] {
10264 let bare = metrics_verbatim(lang, source, MetricsOptions::default()).loc;
10265 assert_eq!(bare.sloc(), 1, "{lang:?} unterminated sloc");
10266 let mut terminated = source.to_vec();
10267 terminated.push(b'\n');
10268 let terminated = metrics_verbatim(lang, &terminated, MetricsOptions::default()).loc;
10269 assert_eq!(
10270 bare.sloc(),
10271 terminated.sloc(),
10272 "{lang:?} sloc must not depend on the trailing newline"
10273 );
10274 assert_eq!((bare.ploc(), bare.cloc(), bare.lloc()), (0, 0, 0));
10276 }
10277 }
10278
10279 #[test]
10294 fn trailing_newline_does_not_change_loc_or_mi() {
10295 for (lang, source) in UNTERMINATED_ONE_LINERS {
10296 let text = String::from_utf8_lossy(source);
10297 let bare = metrics_verbatim(*lang, source, MetricsOptions::default());
10298 let mut newline_terminated = source.to_vec();
10299 newline_terminated.push(b'\n');
10300 let terminated =
10301 metrics_verbatim(*lang, &newline_terminated, MetricsOptions::default());
10302
10303 assert_eq!(
10304 bare.loc.sloc(),
10305 terminated.loc.sloc(),
10306 "{lang:?} sloc {text:?}"
10307 );
10308 assert_eq!(
10309 bare.loc.ploc(),
10310 terminated.loc.ploc(),
10311 "{lang:?} ploc {text:?}"
10312 );
10313 assert_eq!(
10314 bare.loc.cloc(),
10315 terminated.loc.cloc(),
10316 "{lang:?} cloc {text:?}"
10317 );
10318 assert_eq!(
10319 bare.loc.lloc(),
10320 terminated.loc.lloc(),
10321 "{lang:?} lloc {text:?}"
10322 );
10323 assert_eq!(
10324 bare.loc.blank(),
10325 terminated.loc.blank(),
10326 "{lang:?} blank {text:?}"
10327 );
10328 assert_eq!(
10334 bare.mi.original(),
10335 terminated.mi.original(),
10336 "{lang:?} mi {text:?}"
10337 );
10338 assert_eq!(
10339 bare.mi.sei(),
10340 terminated.mi.sei(),
10341 "{lang:?} mi.sei {text:?}"
10342 );
10343 assert_eq!(
10344 bare.mi.visual_studio(),
10345 terminated.mi.visual_studio(),
10346 "{lang:?} mi.visual_studio {text:?}",
10347 );
10348 assert_ne!(bare.mi.original(), 0.0, "{lang:?} mi must not be zeroed");
10349 }
10350 }
10351
10352 #[test]
10356 fn unterminated_trailing_comment_upholds_the_cloc_ploc_invariant() {
10357 let loc = rust_loc(b"fn f(){}\n/// x");
10359 assert_eq!(loc.sloc(), 2);
10360 assert_eq!(loc.ploc(), 1);
10361 assert_eq!(loc.cloc(), 1);
10362 assert_eq!(loc.blank(), 0);
10363 }
10364
10365 #[test]
10369 fn degenerate_inputs_report_their_real_row_count() {
10370 assert_eq!(rust_loc(b"").sloc(), 0);
10372 let spaces = rust_loc(b" ");
10375 assert_eq!(spaces.sloc(), 1);
10376 assert_eq!(spaces.blank(), 1);
10377 assert_eq!(rust_loc(b"\n").sloc(), 0);
10386 assert_eq!(rust_loc(b"\n\n").sloc(), 0);
10387 }
10388
10389 fn all_loc_grammars() -> impl Iterator<Item = crate::LANG> {
10398 UNTERMINATED_ONE_LINERS
10399 .iter()
10400 .map(|(lang, _)| *lang)
10401 .chain([crate::LANG::Preproc, crate::LANG::Ccomment])
10402 }
10403
10404 const WHITESPACE_ONLY_SPANNING_GRAMMARS: &[crate::LANG] = &[
10415 crate::LANG::Elixir,
10416 crate::LANG::Tcl,
10417 crate::LANG::Irules,
10418 crate::LANG::Preproc,
10419 crate::LANG::Ccomment,
10420 ];
10421
10422 #[test]
10441 fn whitespace_only_input_is_the_documented_carve_out() {
10442 for bare in [&b" "[..], b"\t\t"] {
10445 let mut newline_terminated = bare.to_vec();
10446 newline_terminated.push(b'\n');
10447 for lang in all_loc_grammars() {
10448 let text = String::from_utf8_lossy(bare);
10449 let unterminated = metrics_verbatim(lang, bare, MetricsOptions::default()).loc;
10450 let terminated =
10451 metrics_verbatim(lang, &newline_terminated, MetricsOptions::default()).loc;
10452
10453 assert_eq!(
10454 (unterminated.sloc(), unterminated.blank()),
10455 (1, 1),
10456 "{lang:?}: unterminated {text:?} is one blank row for every grammar"
10457 );
10458
10459 let expected = if WHITESPACE_ONLY_SPANNING_GRAMMARS.contains(&lang) {
10460 (1, 1)
10462 } else {
10463 (0, 0)
10465 };
10466 assert_eq!(
10467 (terminated.sloc(), terminated.blank()),
10468 expected,
10469 "{lang:?}: newline-terminated {text:?} — if this moved, the \
10470 grammar changed sides and #1087's carve-out list is stale"
10471 );
10472
10473 for loc in [&unterminated, &terminated] {
10478 assert_eq!(
10479 (loc.ploc(), loc.cloc(), loc.lloc()),
10480 (0, 0, 0),
10481 "{lang:?}: whitespace is neither code nor comment"
10482 );
10483 }
10484 }
10485 }
10486 }
10487
10488 #[test]
10495 fn perl_last_sub_does_not_absorb_the_trailing_newline() {
10496 let space = space_verbatim(
10498 crate::LANG::Perl,
10499 b"sub f {\n return 1;\n}\nsub g {\n return 2;\n}\n",
10500 MetricsOptions::default(),
10501 );
10502 assert_eq!(space.metrics.loc.sloc(), 6, "the file has six rows");
10503 let subs: Vec<u64> = space
10504 .spaces
10505 .iter()
10506 .map(|child| child.metrics.loc.sloc())
10507 .collect();
10508 assert_eq!(subs, vec![3, 3], "both subs occupy three rows");
10509 }
10510
10511 #[test]
10526 fn tcl_family_does_not_count_terminator_rows_as_code() {
10527 for lang in [crate::LANG::Tcl, crate::LANG::Irules] {
10528 let padded = metrics_verbatim(
10530 lang,
10531 b"proc f {} {}\n \nproc g {} {}\n",
10532 MetricsOptions::default(),
10533 )
10534 .loc;
10535 assert_eq!(padded.sloc(), 3, "{lang:?} sloc");
10536 assert_eq!(padded.ploc(), 2, "{lang:?} ploc");
10537 assert_eq!(padded.blank(), 1, "{lang:?} blank");
10538
10539 let empty = metrics_verbatim(
10544 lang,
10545 b"proc f {} {}\n\nproc g {} {}\n",
10546 MetricsOptions::default(),
10547 )
10548 .loc;
10549 assert_eq!(
10550 (padded.sloc(), padded.ploc(), padded.blank()),
10551 (empty.sloc(), empty.ploc(), empty.blank()),
10552 "{lang:?}: trailing whitespace on a blank row must not make it code"
10553 );
10554
10555 let commented = metrics_verbatim(
10562 lang,
10563 b"# lead-in\nproc f {} {}\n",
10564 MetricsOptions::default(),
10565 )
10566 .loc;
10567 assert_eq!(commented.sloc(), 2, "{lang:?} commented sloc");
10568 assert_eq!(commented.ploc(), 1, "{lang:?} commented ploc");
10569 assert_eq!(commented.cloc(), 1, "{lang:?} commented cloc");
10570 assert_eq!(commented.blank(), 0, "{lang:?} commented blank");
10571 }
10572 }
10573
10574 fn comment_spellings(lang: crate::LANG) -> &'static [&'static str] {
10583 use crate::LANG::*;
10584 match lang {
10585 Python | Ruby | Bash | Elixir | Tcl | Irules | Perl => &["# c"],
10586 Lua => &["-- c", "--[[ c ]]"],
10587 Php => &["# c", "/* c */", "/** c */"],
10588 Rust => &["// c", "/* c */", "/// c"],
10589 _ => &["// c", "/* c */"],
10590 }
10591 }
10592
10593 #[test]
10611 fn a_comment_row_is_never_counted_as_code() {
10612 for (lang, code) in UNTERMINATED_ONE_LINERS {
10613 let must_lead = *lang == crate::LANG::Php;
10617 for &comment in comment_spellings(*lang) {
10618 let orders: &[bool] = if must_lead { &[false] } else { &[true, false] };
10619 for &comment_first in orders {
10620 let mut src = Vec::new();
10621 let (first, second): (&[u8], &[u8]) = if comment_first {
10622 (comment.as_bytes(), code)
10623 } else {
10624 (code, comment.as_bytes())
10625 };
10626 src.extend_from_slice(first);
10627 src.push(b'\n');
10628 src.extend_from_slice(second);
10629 src.push(b'\n');
10630
10631 let loc = metrics_verbatim(*lang, &src, MetricsOptions::default()).loc;
10632 let text = String::from_utf8_lossy(&src);
10633 assert_eq!(loc.sloc(), 2, "{lang:?} sloc for {text:?}");
10634 assert_eq!(
10635 loc.ploc(),
10636 1,
10637 "{lang:?} ploc for {text:?} — the comment row is not code"
10638 );
10639 assert_eq!(loc.cloc(), 1, "{lang:?} cloc for {text:?}");
10640 assert_eq!(loc.blank(), 0, "{lang:?} blank for {text:?}");
10641 }
10642 }
10643 }
10644 }
10645}