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 std::collections::HashSet;
26
27use crate::checker::Checker;
28use serde::Serialize;
29use serde::ser::{SerializeStruct, Serializer};
30use std::fmt;
31
32use crate::macros::implement_metric_trait;
33use crate::*;
34
35#[inline]
40fn min_or_zero(v: usize) -> f64 {
41 if v == usize::MAX { 0.0 } else { v as f64 }
42}
43
44#[derive(Debug, Clone)]
46pub struct Sloc {
47 start: usize,
48 end: usize,
49 unit: bool,
50 sloc_min: usize,
51 sloc_max: usize,
52}
53
54impl Default for Sloc {
55 fn default() -> Self {
56 Self {
57 start: 0,
58 end: 0,
59 unit: false,
60 sloc_min: usize::MAX,
61 sloc_max: 0,
62 }
63 }
64}
65
66impl Sloc {
67 #[inline]
69 #[must_use]
70 pub fn sloc(&self) -> f64 {
71 let sloc = if self.unit {
75 self.end - self.start
76 } else {
77 (self.end - self.start) + 1
78 };
79 sloc as f64
80 }
81
82 #[inline]
85 #[must_use]
86 pub fn sloc_min(&self) -> f64 {
87 min_or_zero(self.sloc_min)
88 }
89
90 #[inline]
92 #[must_use]
93 pub fn sloc_max(&self) -> f64 {
94 self.sloc_max as f64
95 }
96
97 #[inline]
99 pub fn merge(&mut self, other: &Sloc) {
100 self.sloc_min = self.sloc_min.min(other.sloc() as usize);
101 self.sloc_max = self.sloc_max.max(other.sloc() as usize);
102 }
103
104 #[inline]
105 pub(crate) fn compute_minmax(&mut self) {
106 if self.sloc_min == usize::MAX {
107 self.sloc_min = self.sloc_min.min(self.sloc() as usize);
108 self.sloc_max = self.sloc_max.max(self.sloc() as usize);
109 }
110 }
111}
112
113#[derive(Debug, Clone)]
115pub struct Ploc {
116 lines: HashSet<usize>,
117 ploc_min: usize,
118 ploc_max: usize,
119}
120
121impl Default for Ploc {
122 fn default() -> Self {
123 Self {
124 lines: HashSet::default(),
125 ploc_min: usize::MAX,
126 ploc_max: 0,
127 }
128 }
129}
130
131impl Ploc {
132 #[inline]
134 #[must_use]
135 pub fn ploc(&self) -> f64 {
136 self.lines.len() as f64
139 }
140
141 #[inline]
144 #[must_use]
145 pub fn ploc_min(&self) -> f64 {
146 min_or_zero(self.ploc_min)
147 }
148
149 #[inline]
151 #[must_use]
152 pub fn ploc_max(&self) -> f64 {
153 self.ploc_max as f64
154 }
155
156 #[inline]
158 pub fn merge(&mut self, other: &Ploc) {
159 for l in &other.lines {
161 self.lines.insert(*l);
162 }
163
164 self.ploc_min = self.ploc_min.min(other.ploc() as usize);
165 self.ploc_max = self.ploc_max.max(other.ploc() as usize);
166 }
167
168 #[inline]
169 pub(crate) fn compute_minmax(&mut self) {
170 if self.ploc_min == usize::MAX {
171 self.ploc_min = self.ploc_min.min(self.ploc() as usize);
172 self.ploc_max = self.ploc_max.max(self.ploc() as usize);
173 }
174 }
175}
176
177#[derive(Debug, Clone)]
179pub struct Cloc {
180 only_comment_lines: usize,
181 code_comment_lines: usize,
182 comment_line_end: Option<usize>,
183 cloc_min: usize,
184 cloc_max: usize,
185}
186
187impl Default for Cloc {
188 fn default() -> Self {
189 Self {
190 only_comment_lines: 0,
191 code_comment_lines: 0,
192 comment_line_end: Option::default(),
193 cloc_min: usize::MAX,
194 cloc_max: 0,
195 }
196 }
197}
198
199impl Cloc {
200 #[inline]
202 #[must_use]
203 pub fn cloc(&self) -> f64 {
204 (self.only_comment_lines + self.code_comment_lines) as f64
207 }
208
209 #[inline]
212 #[must_use]
213 pub fn cloc_min(&self) -> f64 {
214 min_or_zero(self.cloc_min)
215 }
216
217 #[inline]
219 #[must_use]
220 pub fn cloc_max(&self) -> f64 {
221 self.cloc_max as f64
222 }
223
224 #[inline]
226 pub fn merge(&mut self, other: &Cloc) {
227 self.only_comment_lines += other.only_comment_lines;
229 self.code_comment_lines += other.code_comment_lines;
230
231 self.cloc_min = self.cloc_min.min(other.cloc() as usize);
232 self.cloc_max = self.cloc_max.max(other.cloc() as usize);
233 }
234
235 #[inline]
236 pub(crate) fn compute_minmax(&mut self) {
237 if self.cloc_min == usize::MAX {
238 self.cloc_min = self.cloc_min.min(self.cloc() as usize);
239 self.cloc_max = self.cloc_max.max(self.cloc() as usize);
240 }
241 }
242}
243
244#[derive(Debug, Clone)]
246pub struct Lloc {
247 logical_lines: usize,
248 lloc_min: usize,
249 lloc_max: usize,
250}
251
252impl Default for Lloc {
253 fn default() -> Self {
254 Self {
255 logical_lines: 0,
256 lloc_min: usize::MAX,
257 lloc_max: 0,
258 }
259 }
260}
261
262impl Lloc {
263 #[inline]
265 #[must_use]
266 pub fn lloc(&self) -> f64 {
267 self.logical_lines as f64
270 }
271
272 #[inline]
275 #[must_use]
276 pub fn lloc_min(&self) -> f64 {
277 min_or_zero(self.lloc_min)
278 }
279
280 #[inline]
282 #[must_use]
283 pub fn lloc_max(&self) -> f64 {
284 self.lloc_max as f64
285 }
286
287 #[inline]
289 pub fn merge(&mut self, other: &Lloc) {
290 self.logical_lines += other.logical_lines;
292 self.lloc_min = self.lloc_min.min(other.lloc() as usize);
293 self.lloc_max = self.lloc_max.max(other.lloc() as usize);
294 }
295
296 #[inline]
297 pub(crate) fn compute_minmax(&mut self) {
298 if self.lloc_min == usize::MAX {
299 self.lloc_min = self.lloc_min.min(self.lloc() as usize);
300 self.lloc_max = self.lloc_max.max(self.lloc() as usize);
301 }
302 }
303}
304
305#[derive(Debug, Clone)]
307pub struct Stats {
308 sloc: Sloc,
309 ploc: Ploc,
310 cloc: Cloc,
311 lloc: Lloc,
312 space_count: usize,
313 blank_min: usize,
314 blank_max: usize,
315}
316
317impl Default for Stats {
318 fn default() -> Self {
319 Self {
320 sloc: Sloc::default(),
321 ploc: Ploc::default(),
322 cloc: Cloc::default(),
323 lloc: Lloc::default(),
324 space_count: 1,
325 blank_min: usize::MAX,
326 blank_max: 0,
327 }
328 }
329}
330
331impl Serialize for Stats {
332 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
333 where
334 S: Serializer,
335 {
336 let mut st = serializer.serialize_struct("loc", 20)?;
337 st.serialize_field("sloc", &self.sloc())?;
338 st.serialize_field("ploc", &self.ploc())?;
339 st.serialize_field("lloc", &self.lloc())?;
340 st.serialize_field("cloc", &self.cloc())?;
341 st.serialize_field("blank", &self.blank())?;
342 st.serialize_field("sloc_average", &self.sloc_average())?;
343 st.serialize_field("ploc_average", &self.ploc_average())?;
344 st.serialize_field("lloc_average", &self.lloc_average())?;
345 st.serialize_field("cloc_average", &self.cloc_average())?;
346 st.serialize_field("blank_average", &self.blank_average())?;
347 st.serialize_field("sloc_min", &self.sloc_min())?;
348 st.serialize_field("sloc_max", &self.sloc_max())?;
349 st.serialize_field("cloc_min", &self.cloc_min())?;
350 st.serialize_field("cloc_max", &self.cloc_max())?;
351 st.serialize_field("ploc_min", &self.ploc_min())?;
352 st.serialize_field("ploc_max", &self.ploc_max())?;
353 st.serialize_field("lloc_min", &self.lloc_min())?;
354 st.serialize_field("lloc_max", &self.lloc_max())?;
355 st.serialize_field("blank_min", &self.blank_min())?;
356 st.serialize_field("blank_max", &self.blank_max())?;
357 st.end()
358 }
359}
360
361impl fmt::Display for Stats {
362 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
363 write!(
364 f,
365 "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: {}",
366 self.sloc(),
367 self.ploc(),
368 self.lloc(),
369 self.cloc(),
370 self.blank(),
371 self.sloc_average(),
372 self.ploc_average(),
373 self.lloc_average(),
374 self.cloc_average(),
375 self.blank_average(),
376 self.sloc_min(),
377 self.sloc_max(),
378 self.cloc_min(),
379 self.cloc_max(),
380 self.ploc_min(),
381 self.ploc_max(),
382 self.lloc_min(),
383 self.lloc_max(),
384 self.blank_min(),
385 self.blank_max(),
386 )
387 }
388}
389
390impl Stats {
391 pub fn merge(&mut self, other: &Stats) {
393 self.sloc.merge(&other.sloc);
394 self.ploc.merge(&other.ploc);
395 self.cloc.merge(&other.cloc);
396 self.lloc.merge(&other.lloc);
397
398 self.space_count += other.space_count;
400
401 self.blank_min = self.blank_min.min(other.blank() as usize);
404 self.blank_max = self.blank_max.max(other.blank() as usize);
405 }
406
407 #[inline]
411 #[must_use]
412 pub fn sloc(&self) -> f64 {
413 self.sloc.sloc()
414 }
415
416 #[inline]
420 #[must_use]
421 pub fn ploc(&self) -> f64 {
422 self.ploc.ploc()
423 }
424
425 #[inline]
429 #[must_use]
430 pub fn lloc(&self) -> f64 {
431 self.lloc.lloc()
432 }
433
434 #[inline]
438 #[must_use]
439 pub fn cloc(&self) -> f64 {
440 self.cloc.cloc()
441 }
442
443 #[inline]
447 #[must_use]
448 pub fn blank(&self) -> f64 {
449 self.sloc() - self.ploc() - self.cloc.only_comment_lines as f64
450 }
451
452 #[inline]
456 #[must_use]
457 pub fn sloc_average(&self) -> f64 {
458 self.sloc() / self.space_count as f64
459 }
460
461 #[inline]
465 #[must_use]
466 pub fn ploc_average(&self) -> f64 {
467 self.ploc() / self.space_count as f64
468 }
469
470 #[inline]
474 #[must_use]
475 pub fn lloc_average(&self) -> f64 {
476 self.lloc() / self.space_count as f64
477 }
478
479 #[inline]
483 #[must_use]
484 pub fn cloc_average(&self) -> f64 {
485 self.cloc() / self.space_count as f64
486 }
487
488 #[inline]
492 #[must_use]
493 pub fn blank_average(&self) -> f64 {
494 self.blank() / self.space_count as f64
495 }
496
497 #[inline]
499 #[must_use]
500 pub fn sloc_min(&self) -> f64 {
501 self.sloc.sloc_min()
502 }
503
504 #[inline]
506 #[must_use]
507 pub fn sloc_max(&self) -> f64 {
508 self.sloc.sloc_max()
509 }
510
511 #[inline]
513 #[must_use]
514 pub fn cloc_min(&self) -> f64 {
515 self.cloc.cloc_min()
516 }
517
518 #[inline]
520 #[must_use]
521 pub fn cloc_max(&self) -> f64 {
522 self.cloc.cloc_max()
523 }
524
525 #[inline]
527 #[must_use]
528 pub fn ploc_min(&self) -> f64 {
529 self.ploc.ploc_min()
530 }
531
532 #[inline]
534 #[must_use]
535 pub fn ploc_max(&self) -> f64 {
536 self.ploc.ploc_max()
537 }
538
539 #[inline]
541 #[must_use]
542 pub fn lloc_min(&self) -> f64 {
543 self.lloc.lloc_min()
544 }
545
546 #[inline]
548 #[must_use]
549 pub fn lloc_max(&self) -> f64 {
550 self.lloc.lloc_max()
551 }
552
553 #[inline]
556 #[must_use]
557 pub fn blank_min(&self) -> f64 {
558 min_or_zero(self.blank_min)
559 }
560
561 #[inline]
563 #[must_use]
564 pub fn blank_max(&self) -> f64 {
565 self.blank_max as f64
566 }
567
568 #[inline]
569 pub(crate) fn compute_minmax(&mut self) {
570 self.sloc.compute_minmax();
571 self.ploc.compute_minmax();
572 self.cloc.compute_minmax();
573 self.lloc.compute_minmax();
574
575 if self.blank_min == usize::MAX {
576 self.blank_min = self.blank_min.min(self.blank() as usize);
577 self.blank_max = self.blank_max.max(self.blank() as usize);
578 }
579 }
580
581 pub(crate) fn init_unit_span(&mut self, start: usize, end: usize) {
582 self.sloc.start = start;
583 self.sloc.end = end;
584 self.sloc.unit = true;
585 }
586}
587
588#[doc(hidden)]
589pub trait Loc
591where
592 Self: Checker,
593{
594 fn compute(node: &Node, stats: &mut Stats, is_func_space: bool, is_unit: bool);
597}
598
599#[inline]
600fn init(node: &Node, stats: &mut Stats, is_func_space: bool, is_unit: bool) -> (usize, usize) {
601 let start = node.start_row();
602 let end = node.end_row();
603
604 if is_func_space {
605 stats.sloc.start = start;
606 stats.sloc.end = end;
607 stats.sloc.unit = is_unit;
608 }
609 (start, end)
610}
611
612#[inline]
613fn add_cloc_lines(stats: &mut Stats, start: usize, end: usize) {
618 let comment_diff = end - start;
619 let is_comment_after_code_line = stats.ploc.lines.contains(&start);
620 if is_comment_after_code_line && comment_diff == 0 {
621 stats.cloc.code_comment_lines += 1;
623 } else if is_comment_after_code_line && comment_diff > 0 {
624 stats.cloc.code_comment_lines += 1;
627 stats.cloc.only_comment_lines += comment_diff;
628 } else {
629 stats.cloc.only_comment_lines += (end - start) + 1;
633 stats.cloc.comment_line_end = Some(end);
636 }
637}
638
639#[inline]
640fn check_comment_ends_on_code_line(stats: &mut Stats, start_code_line: usize) {
644 if let Some(end) = stats.cloc.comment_line_end
645 && end == start_code_line
646 && !stats.ploc.lines.contains(&start_code_line)
647 {
648 stats.cloc.only_comment_lines -= 1;
650 stats.cloc.code_comment_lines += 1;
651 }
652}
653
654impl Loc for PythonCode {
655 fn compute(node: &Node, stats: &mut Stats, is_func_space: bool, is_unit: bool) {
656 use Python::*;
657
658 let (start, end) = init(node, stats, is_func_space, is_unit);
659
660 match node.kind_id().into() {
661 StringStart | StringEnd | StringContent | Block | Module => {}
662 Comment => {
663 add_cloc_lines(stats, start, end);
664 }
665 String => {
666 let Some(parent) = node.parent() else { return };
667 if let ExpressionStatement = parent.kind_id().into() {
668 add_cloc_lines(stats, start, end);
669 } else if parent.start_row() != start {
670 check_comment_ends_on_code_line(stats, start);
671 stats.ploc.lines.insert(start);
672 }
673 }
674 Statement
675 | SimpleStatements
676 | ImportStatement
677 | FutureImportStatement
678 | ImportFromStatement
679 | PrintStatement
680 | AssertStatement
681 | ReturnStatement
682 | DeleteStatement
683 | RaiseStatement
684 | PassStatement
685 | BreakStatement
686 | ContinueStatement
687 | IfStatement
688 | ForStatement
689 | WhileStatement
690 | TryStatement
691 | WithStatement
692 | GlobalStatement
693 | NonlocalStatement
694 | ExecStatement
695 | ExpressionStatement => {
696 stats.lloc.logical_lines += 1;
697 }
698 _ => {
699 check_comment_ends_on_code_line(stats, start);
700 stats.ploc.lines.insert(start);
701 }
702 }
703 }
704}
705
706impl Loc for MozjsCode {
707 fn compute(node: &Node, stats: &mut Stats, is_func_space: bool, is_unit: bool) {
708 use Mozjs::*;
709
710 let (start, end) = init(node, stats, is_func_space, is_unit);
711
712 match node.kind_id().into() {
713 String | DQUOTE | Program => {}
714 Comment => {
715 add_cloc_lines(stats, start, end);
716 }
717 ExpressionStatement | ExportStatement | ImportStatement | StatementBlock
718 | IfStatement | SwitchStatement | ForStatement | ForInStatement | WhileStatement
719 | DoStatement | TryStatement | WithStatement | BreakStatement | ContinueStatement
720 | DebuggerStatement | ReturnStatement | ThrowStatement | EmptyStatement
721 | StatementIdentifier => {
722 stats.lloc.logical_lines += 1;
723 }
724 _ => {
725 check_comment_ends_on_code_line(stats, start);
726 stats.ploc.lines.insert(start);
727 }
728 }
729 }
730}
731
732impl Loc for JavascriptCode {
733 fn compute(node: &Node, stats: &mut Stats, is_func_space: bool, is_unit: bool) {
734 use Javascript::*;
735
736 let (start, end) = init(node, stats, is_func_space, is_unit);
737
738 match node.kind_id().into() {
739 String | DQUOTE | Program => {}
740 Comment => {
741 add_cloc_lines(stats, start, end);
742 }
743 ExpressionStatement | ExportStatement | ImportStatement | StatementBlock
744 | IfStatement | SwitchStatement | ForStatement | ForInStatement | WhileStatement
745 | DoStatement | TryStatement | WithStatement | BreakStatement | ContinueStatement
746 | DebuggerStatement | ReturnStatement | ThrowStatement | EmptyStatement
747 | StatementIdentifier => {
748 stats.lloc.logical_lines += 1;
749 }
750 _ => {
751 check_comment_ends_on_code_line(stats, start);
752 stats.ploc.lines.insert(start);
753 }
754 }
755 }
756}
757
758impl Loc for TypescriptCode {
759 fn compute(node: &Node, stats: &mut Stats, is_func_space: bool, is_unit: bool) {
760 use Typescript::*;
761
762 let (start, end) = init(node, stats, is_func_space, is_unit);
763
764 match node.kind_id().into() {
765 String | DQUOTE | Program => {}
766 Comment => {
767 add_cloc_lines(stats, start, end);
768 }
769 ExpressionStatement | ExportStatement | ImportStatement | StatementBlock
770 | IfStatement | SwitchStatement | ForStatement | ForInStatement | WhileStatement
771 | DoStatement | TryStatement | WithStatement | BreakStatement | ContinueStatement
772 | DebuggerStatement | ReturnStatement | ThrowStatement | EmptyStatement
773 | StatementIdentifier => {
774 stats.lloc.logical_lines += 1;
775 }
776 _ => {
777 check_comment_ends_on_code_line(stats, start);
778 stats.ploc.lines.insert(start);
779 }
780 }
781 }
782}
783
784impl Loc for TsxCode {
785 fn compute(node: &Node, stats: &mut Stats, is_func_space: bool, is_unit: bool) {
786 use Tsx::*;
787
788 let (start, end) = init(node, stats, is_func_space, is_unit);
789
790 match node.kind_id().into() {
791 String | DQUOTE | Program => {}
792 Comment => {
793 add_cloc_lines(stats, start, end);
794 }
795 ExpressionStatement | ExportStatement | ImportStatement | StatementBlock
796 | IfStatement | SwitchStatement | ForStatement | ForInStatement | WhileStatement
797 | DoStatement | TryStatement | WithStatement | BreakStatement | ContinueStatement
798 | DebuggerStatement | ReturnStatement | ThrowStatement | EmptyStatement
799 | StatementIdentifier => {
800 stats.lloc.logical_lines += 1;
801 }
802 _ => {
803 check_comment_ends_on_code_line(stats, start);
804 stats.ploc.lines.insert(start);
805 }
806 }
807 }
808}
809
810impl Loc for RustCode {
811 fn compute(node: &Node, stats: &mut Stats, is_func_space: bool, is_unit: bool) {
812 use Rust::*;
813
814 let (start, end) = init(node, stats, is_func_space, is_unit);
815
816 match node.kind_id().into() {
817 StringLiteral
818 | RawStringLiteral
819 | Block
820 | SourceFile
821 | SLASH
822 | SLASHSLASH
823 | SLASHSTAR
824 | STARSLASH
825 | OuterDocCommentMarker
826 | OuterDocCommentMarker2
827 | DocComment
828 | InnerDocCommentMarker
829 | BANG => {}
830 BlockComment => {
831 add_cloc_lines(stats, start, end);
832 }
833 LineComment => {
834 let end = if node.is_child(DocComment as u16) {
838 end - 1
839 } else {
840 end
841 };
842 add_cloc_lines(stats, start, end);
843 }
844 Statement
845 | EmptyStatement
846 | ExpressionStatement
847 | LetDeclaration
848 | AssignmentExpression
849 | CompoundAssignmentExpr => {
850 stats.lloc.logical_lines += 1;
851 }
852 _ => {
853 check_comment_ends_on_code_line(stats, start);
854 stats.ploc.lines.insert(start);
855 }
856 }
857 }
858}
859
860impl Loc for CppCode {
861 fn compute(node: &Node, stats: &mut Stats, is_func_space: bool, is_unit: bool) {
862 use Cpp::*;
863
864 let (start, end) = init(node, stats, is_func_space, is_unit);
865
866 match node.kind_id().into() {
867 RawStringLiteral | StringLiteral | DeclarationList | FieldDeclarationList
868 | TranslationUnit => {}
869 Comment => {
870 add_cloc_lines(stats, start, end);
871 }
872 WhileStatement | SwitchStatement | CaseStatement | IfStatement | ForStatement
873 | ReturnStatement | BreakStatement | ContinueStatement | GotoStatement
874 | ThrowStatement | TryStatement | TryStatement2 | ExpressionStatement
875 | ExpressionStatement2 | LabeledStatement | StatementIdentifier => {
876 stats.lloc.logical_lines += 1;
877 }
878 Declaration => {
879 if node.count_specific_ancestors::<CppParser>(
880 |node| {
881 matches!(
882 node.kind_id().into(),
883 WhileStatement | ForStatement | IfStatement
884 )
885 },
886 |node| node.kind_id() == CompoundStatement,
887 ) == 0
888 {
889 stats.lloc.logical_lines += 1;
890 }
891 }
892 _ => {
893 check_comment_ends_on_code_line(stats, start);
894 stats.ploc.lines.insert(start);
895
896 if let PreprocArg = node.kind_id().into() {
900 (node.start_row() + 1..=node.end_row()).for_each(|line| {
901 stats.ploc.lines.insert(line);
902 });
903 }
904 }
905 }
906 }
907}
908
909impl Loc for JavaCode {
910 fn compute(node: &Node, stats: &mut Stats, is_func_space: bool, is_unit: bool) {
911 use Java::*;
912
913 let (start, end) = init(node, stats, is_func_space, is_unit);
914 let kind_id: Java = node.kind_id().into();
915 match kind_id {
918 Program => {}
919 LineComment | BlockComment => {
920 add_cloc_lines(stats, start, end);
921 }
922 AssertStatement | BreakStatement | ContinueStatement | DoStatement
923 | EnhancedForStatement | ExpressionStatement | ForStatement | IfStatement
924 | ReturnStatement | SwitchExpression | ThrowStatement | TryStatement
925 | WhileStatement => {
926 stats.lloc.logical_lines += 1;
927 }
928 LocalVariableDeclaration => {
929 if node.count_specific_ancestors::<JavaParser>(
930 |node| node.kind_id() == ForStatement,
931 |node| node.kind_id() == Block,
932 ) == 0
933 {
934 stats.lloc.logical_lines += 1;
938 }
939 }
940 _ => {
941 check_comment_ends_on_code_line(stats, start);
942 stats.ploc.lines.insert(start);
943 }
944 }
945 }
946}
947
948impl Loc for GroovyCode {
949 fn compute(node: &Node, stats: &mut Stats, is_func_space: bool, is_unit: bool) {
950 use Groovy::*;
951
952 let (start, end) = init(node, stats, is_func_space, is_unit);
953 let kind_id: Groovy = node.kind_id().into();
954 match kind_id {
967 SourceFile => {}
968 LineComment | BlockComment | GroovydocComment => {
969 add_cloc_lines(stats, start, end);
970 }
971 ExpressionStatement if node.child(0).is_some_and(|c| c.kind_id() == Closure) => {
982 }
984 AssertStatement | BreakStatement | CommandChain | ContinueStatement
985 | DoWhileStatement | ExpressionStatement | ForInStatement | ForStatement
986 | IfStatement | PipelineStatement | ReturnStatement | SwitchExpression
987 | ThrowStatement | TryStatement | WhileStatement | YieldStatement => {
988 stats.lloc.logical_lines += 1;
989 }
990 LocalVariableDeclaration => {
991 if node.count_specific_ancestors::<GroovyParser>(
992 |node| node.kind_id() == ForStatement,
993 |node| node.kind_id() == Block,
994 ) == 0
995 {
996 stats.lloc.logical_lines += 1;
999 }
1000 }
1001 _ => {
1002 check_comment_ends_on_code_line(stats, start);
1003 stats.ploc.lines.insert(start);
1004 }
1005 }
1006 }
1007}
1008
1009impl Loc for CsharpCode {
1010 fn compute(node: &Node, stats: &mut Stats, is_func_space: bool, is_unit: bool) {
1011 use Csharp::*;
1012
1013 let (start, end) = init(node, stats, is_func_space, is_unit);
1014 let kind_id: Csharp = node.kind_id().into();
1015 match kind_id {
1016 CompilationUnit => {}
1017 Comment => {
1018 add_cloc_lines(stats, start, end);
1019 }
1020 BreakStatement | CheckedStatement | ContinueStatement | DoStatement
1021 | ExpressionStatement | FixedStatement | ForStatement | ForeachStatement
1022 | GotoStatement | IfStatement | LabeledStatement | LockStatement | ReturnStatement
1023 | SwitchStatement | ThrowStatement | TryStatement | UnsafeStatement
1024 | UsingStatement | WhileStatement | YieldStatement => {
1025 stats.lloc.logical_lines += 1;
1026 }
1027 LocalDeclarationStatement => {
1028 if node.count_specific_ancestors::<CsharpParser>(
1032 |n| n.kind_id() == ForStatement,
1033 |n| n.kind_id() == Block,
1034 ) == 0
1035 {
1036 stats.lloc.logical_lines += 1;
1037 }
1038 }
1039 _ => {
1040 check_comment_ends_on_code_line(stats, start);
1041 stats.ploc.lines.insert(start);
1042 }
1043 }
1044 }
1045}
1046
1047impl Loc for GoCode {
1048 fn compute(node: &Node, stats: &mut Stats, is_func_space: bool, is_unit: bool) {
1049 use Go as G;
1052
1053 let (start, end) = init(node, stats, is_func_space, is_unit);
1054
1055 match node.kind_id().into() {
1056 G::SourceFile | G::RawStringLiteral | G::InterpretedStringLiteral => {}
1057 G::Comment => {
1058 add_cloc_lines(stats, start, end);
1059 }
1060 G::FallthroughStatement
1061 | G::BreakStatement
1062 | G::ContinueStatement
1063 | G::GotoStatement
1064 | G::ReturnStatement
1065 | G::GoStatement
1066 | G::DeferStatement
1067 | G::IfStatement
1068 | G::ForStatement
1069 | G::ExpressionSwitchStatement
1070 | G::TypeSwitchStatement
1071 | G::SelectStatement
1072 | G::LabeledStatement => {
1073 stats.lloc.logical_lines += 1;
1074 }
1075 G::ExpressionStatement
1076 | G::SendStatement
1077 | G::IncStatement
1078 | G::DecStatement
1079 | G::AssignmentStatement
1080 | G::ShortVarDeclaration
1081 | G::VarDeclaration
1082 | G::ConstDeclaration => {
1083 if node.count_specific_ancestors::<GoParser>(
1088 |n| n.kind_id() == G::ForClause,
1089 |n| n.kind_id() == G::Block,
1090 ) == 0
1091 {
1092 stats.lloc.logical_lines += 1;
1093 }
1094 }
1095 _ => {
1096 check_comment_ends_on_code_line(stats, start);
1097 stats.ploc.lines.insert(start);
1098 }
1099 }
1100 }
1101}
1102
1103impl Loc for PerlCode {
1104 fn compute(node: &Node, stats: &mut Stats, is_func_space: bool, is_unit: bool) {
1105 use Perl as P;
1106
1107 let (start, end) = init(node, stats, is_func_space, is_unit);
1108
1109 match node.kind_id().into() {
1110 P::SourceFile
1111 | P::Block
1112 | P::StandaloneBlock
1113 | P::HeredocBodyStatement
1114 | P::HeredocContent
1115 | P::PodContent
1116 | P::StringSingleQuoted
1117 | P::StringDoubleQuoted
1118 | P::StringQQuoted
1119 | P::StringQqQuoted
1120 | P::BacktickQuoted
1121 | P::CommandQxQuoted
1122 | P::SQUOTE
1125 | P::DQUOTE
1126 | P::StringContent
1127 | P::StringSingleQuotedContent
1128 | P::StringSingleQQuotedContent
1129 | P::StringQqQuotedContent
1130 | P::StringDoubleQuotedContent
1131 | P::EscapeSequence
1132 | P::EscapeSequenceToken1
1133 | P::Interpolation => {}
1134 P::Comments | P::PodStatement => {
1135 add_cloc_lines(stats, start, end);
1136 }
1137 P::SingleLineStatement
1138 | P::IfStatement
1139 | P::UnlessStatement
1140 | P::WhileStatement
1141 | P::UntilStatement
1142 | P::ForStatement1
1143 | P::ForStatement2
1144 | P::LoopControlStatement
1145 | P::PackageStatement
1146 | P::RequireStatement
1147 | P::UseNoStatement
1148 | P::UseNoFeatureStatement
1149 | P::UseNoIfStatement
1150 | P::UseNoSubsStatement
1151 | P::UseConstantStatement
1152 | P::UseParentStatement
1153 | P::UseNoVersion
1154 | P::EllipsisStatement => {
1155 stats.lloc.logical_lines += 1;
1156 }
1157 P::SEMI => {
1158 if let Some(parent) = node.parent()
1164 && matches!(parent.kind_id().into(), P::SourceFile | P::Block)
1165 {
1166 stats.lloc.logical_lines += 1;
1167 }
1168 check_comment_ends_on_code_line(stats, start);
1169 stats.ploc.lines.insert(start);
1170 }
1171 _ => {
1172 check_comment_ends_on_code_line(stats, start);
1173 stats.ploc.lines.insert(start);
1174 }
1175 }
1176 }
1177}
1178
1179impl Loc for LuaCode {
1180 fn compute(node: &Node, stats: &mut Stats, is_func_space: bool, is_unit: bool) {
1181 let (start, end) = init(node, stats, is_func_space, is_unit);
1182
1183 match node.kind_id().into() {
1184 Lua::Chunk | Lua::String => {}
1186
1187 Lua::DASHDASH | Lua::CommentContent | Lua::CommentContent2 => {}
1195 Lua::LBRACKLBRACK | Lua::RBRACKRBRACK
1196 if node.parent().is_some_and(|p| p.kind_id() == Lua::Comment) => {}
1197
1198 Lua::Comment => {
1199 add_cloc_lines(stats, start, end);
1200 }
1201
1202 Lua::AssignmentStatement | Lua::AssignmentStatement2
1205 if !node.parent().is_some_and(|p| {
1206 matches!(
1207 p.kind_id().into(),
1208 Lua::VariableDeclaration
1209 | Lua::VariableDeclaration2
1210 | Lua::ImplicitVariableDeclaration
1211 )
1212 }) =>
1213 {
1214 stats.lloc.logical_lines += 1;
1215 }
1216
1217 Lua::IfStatement
1218 | Lua::ForStatement
1219 | Lua::WhileStatement
1220 | Lua::RepeatStatement
1221 | Lua::DoStatement
1222 | Lua::ReturnStatement
1223 | Lua::BreakStatement
1224 | Lua::GotoStatement
1225 | Lua::LabelStatement
1226 | Lua::VariableDeclaration
1227 | Lua::VariableDeclaration2
1228 | Lua::ImplicitVariableDeclaration
1229 | Lua::FunctionDeclaration
1230 | Lua::FunctionDeclaration2
1231 | Lua::FunctionDeclaration3 => {
1232 stats.lloc.logical_lines += 1;
1233 }
1234
1235 _ => {
1236 check_comment_ends_on_code_line(stats, start);
1237 stats.ploc.lines.insert(start);
1238 }
1239 }
1240 }
1241}
1242
1243impl Loc for KotlinCode {
1244 fn compute(node: &Node, stats: &mut Stats, is_func_space: bool, is_unit: bool) {
1245 use Kotlin::*;
1246
1247 let (start, end) = init(node, stats, is_func_space, is_unit);
1248
1249 match node.kind_id().into() {
1250 SourceFile => {}
1251 LineComment | BlockComment => {
1252 add_cloc_lines(stats, start, end);
1253 }
1254 ForStatement | WhileStatement | DoWhileStatement | IfExpression | WhenExpression
1255 | TryExpression | ThrowExpression | ReturnExpression | Assignment
1256 | PropertyDeclaration => {
1257 stats.lloc.logical_lines += 1;
1258 }
1259 CallExpression | NavigationExpression => {
1265 if let Some(parent) = node.parent()
1266 && matches!(
1267 parent.kind_id().into(),
1268 Block | FunctionBody | SourceFile | CatchBlock | FinallyBlock
1269 )
1270 {
1271 stats.lloc.logical_lines += 1;
1272 } else {
1273 check_comment_ends_on_code_line(stats, start);
1274 stats.ploc.lines.insert(start);
1275 }
1276 }
1277 _ => {
1278 check_comment_ends_on_code_line(stats, start);
1279 stats.ploc.lines.insert(start);
1280 }
1281 }
1282 }
1283}
1284
1285impl Loc for PhpCode {
1286 fn compute(node: &Node, stats: &mut Stats, is_func_space: bool, is_unit: bool) {
1287 use Php::*;
1288
1289 let (start, end) = init(node, stats, is_func_space, is_unit);
1290
1291 match node.kind_id().into() {
1292 Program => {}
1293 Comment => {
1294 add_cloc_lines(stats, start, end);
1295 }
1296 ExpressionStatement
1298 | EchoStatement
1299 | EmptyStatement
1300 | IfStatement
1301 | SwitchStatement
1302 | ForStatement
1303 | ForeachStatement
1304 | WhileStatement
1305 | DoStatement
1306 | TryStatement
1307 | ReturnStatement
1308 | BreakStatement
1309 | ContinueStatement
1310 | GotoStatement
1311 | UnsetStatement
1312 | DeclareStatement
1313 | NamespaceUseDeclaration
1314 | GlobalDeclaration
1315 | FunctionStaticDeclaration
1316 | ConstDeclaration
1317 | ConstDeclaration2
1318 | PropertyDeclaration
1319 | NamedLabelStatement => {
1320 stats.lloc.logical_lines += 1;
1321 }
1322 _ => {
1323 check_comment_ends_on_code_line(stats, start);
1324 stats.ploc.lines.insert(start);
1325 }
1326 }
1327 }
1328}
1329
1330implement_metric_trait!(Loc, PreprocCode, CcommentCode);
1334
1335impl Loc for RubyCode {
1336 fn compute(node: &Node, stats: &mut Stats, is_func_space: bool, is_unit: bool) {
1337 use Ruby as R;
1338
1339 let (start, end) = init(node, stats, is_func_space, is_unit);
1340 match node.kind_id().into() {
1341 R::Program => {}
1342 R::Comment => {
1343 add_cloc_lines(stats, start, end);
1344 }
1345 R::If
1354 | R::Unless
1355 | R::Elsif
1356 | R::While
1357 | R::Until
1358 | R::For
1359 | R::Case
1360 | R::CaseMatch
1361 | R::Begin
1362 | R::IfModifier
1363 | R::UnlessModifier
1364 | R::WhileModifier
1365 | R::UntilModifier
1366 | R::RescueModifier
1367 | R::RescueModifier2
1368 | R::RescueModifier3
1369 | R::Return
1370 | R::Return2
1371 | R::Yield
1372 | R::Yield2
1373 | R::Break
1374 | R::Break2
1375 | R::Next
1376 | R::Next2
1377 | R::Redo
1378 | R::Retry
1379 | R::Method
1380 | R::SingletonMethod
1381 | R::Class
1382 | R::SingletonClass
1383 | R::Module
1384 | R::BeginBlock
1385 | R::EndBlock
1386 | R::Undef
1387 | R::Alias
1388 | R::EmptyStatement => {
1389 stats.lloc.logical_lines += 1;
1390 }
1391 _ => {
1392 check_comment_ends_on_code_line(stats, start);
1393 stats.ploc.lines.insert(start);
1394 }
1395 }
1396 }
1397}
1398
1399impl Loc for ElixirCode {
1400 fn compute(node: &Node, stats: &mut Stats, is_func_space: bool, is_unit: bool) {
1401 use Elixir as E;
1402
1403 let (start, end) = init(node, stats, is_func_space, is_unit);
1404
1405 match node.kind_id().into() {
1406 E::Source => {}
1408
1409 E::Comment => add_cloc_lines(stats, start, end),
1411
1412 E::StabClause => {}
1422
1423 _ => {
1433 if node.0.is_named()
1434 && node.parent().is_some_and(|p| {
1435 matches!(
1436 p.kind_id().into(),
1437 E::Source
1438 | E::Body
1439 | E::Block
1440 | E::DoBlock
1441 | E::AfterBlock
1442 | E::RescueBlock
1443 | E::CatchBlock
1444 | E::ElseBlock
1445 )
1446 })
1447 {
1448 stats.lloc.logical_lines += 1;
1449 }
1450 if node.child_count() == 0 {
1451 check_comment_ends_on_code_line(stats, start);
1452 stats.ploc.lines.insert(start);
1453 }
1454 }
1455 }
1456 }
1457}
1458
1459impl Loc for BashCode {
1460 fn compute(node: &Node, stats: &mut Stats, is_func_space: bool, is_unit: bool) {
1461 use Bash::*;
1462
1463 let (start, end) = init(node, stats, is_func_space, is_unit);
1464
1465 match node.kind_id().into() {
1466 Program => {}
1467 Comment => {
1468 add_cloc_lines(stats, start, end);
1469 }
1470 Command | VariableAssignment | DeclarationCommand | UnsetCommand | IfStatement
1474 | ForStatement | CStyleForStatement | WhileStatement | CaseStatement
1475 | FunctionDefinition => {
1476 stats.lloc.logical_lines += 1;
1477 }
1478 _ => {
1479 if node.child_count() == 0 {
1480 stats.ploc.lines.insert(start);
1481 }
1482 }
1483 }
1484 }
1485}
1486
1487impl Loc for TclCode {
1488 fn compute(node: &Node, stats: &mut Stats, is_func_space: bool, is_unit: bool) {
1489 let (start, end) = init(node, stats, is_func_space, is_unit);
1490
1491 match node.kind_id().into() {
1492 Tcl::SourceFile => {}
1493
1494 Tcl::Comment => {
1495 add_cloc_lines(stats, start, end);
1496 }
1497
1498 Tcl::Procedure
1499 | Tcl::If
1500 | Tcl::Elseif
1501 | Tcl::Foreach
1502 | Tcl::While
1503 | Tcl::Set
1504 | Tcl::Global
1505 | Tcl::Namespace
1506 | Tcl::Try
1507 | Tcl::Catch
1508 | Tcl::Regexp => {
1509 stats.lloc.logical_lines += 1;
1510 }
1511
1512 Tcl::ExprCmd
1515 | Tcl::Command
1517 if node
1518 .parent()
1519 .is_none_or(|p| p.kind_id() != Tcl::CommandSubstitution) =>
1520 {
1521 stats.lloc.logical_lines += 1;
1522 }
1523
1524 _ => {
1525 check_comment_ends_on_code_line(stats, start);
1526 stats.ploc.lines.insert(start);
1527 }
1528 }
1529 }
1530}
1531
1532#[cfg(test)]
1533#[allow(
1534 clippy::float_cmp,
1535 clippy::cast_precision_loss,
1536 clippy::cast_possible_truncation,
1537 clippy::cast_sign_loss,
1538 clippy::similar_names,
1539 clippy::doc_markdown,
1540 clippy::needless_raw_string_hashes,
1541 clippy::too_many_lines
1542)]
1543mod tests {
1544 use crate::tools::check_metrics;
1545
1546 use super::*;
1547
1548 #[test]
1554 fn loc_empty_file_min_is_zero() {
1555 let stats = Stats::default();
1556 assert_eq!(stats.sloc_min(), 0.0);
1557 assert_eq!(stats.ploc_min(), 0.0);
1558 assert_eq!(stats.lloc_min(), 0.0);
1559 assert_eq!(stats.cloc_min(), 0.0);
1560 assert_eq!(stats.blank_min(), 0.0);
1561 }
1562
1563 #[cfg(test)]
1569 fn assert_perl_parses_cleanly(source: &str) {
1570 use crate::traits::ParserTrait;
1571 let path = std::path::PathBuf::from("foo.pl");
1575 let mut bytes = source.trim_end_matches('\n').as_bytes().to_vec();
1576 bytes.push(b'\n');
1577 let parser = PerlParser::new(bytes, &path, None);
1578 assert!(
1579 !parser.get_root().has_error(),
1580 "tree-sitter-perl returned an error tree for snippet:\n{source}"
1581 );
1582 }
1583
1584 #[test]
1585 fn python_sloc() {
1586 check_metrics::<PythonParser>(
1587 "
1588
1589 a = 42
1590
1591 ",
1592 "foo.py",
1593 |metric| {
1594 insta::assert_json_snapshot!(
1596 metric.loc,
1597 @r###"
1598 {
1599 "sloc": 1.0,
1600 "ploc": 1.0,
1601 "lloc": 1.0,
1602 "cloc": 0.0,
1603 "blank": 0.0,
1604 "sloc_average": 1.0,
1605 "ploc_average": 1.0,
1606 "lloc_average": 1.0,
1607 "cloc_average": 0.0,
1608 "blank_average": 0.0,
1609 "sloc_min": 1.0,
1610 "sloc_max": 1.0,
1611 "cloc_min": 0.0,
1612 "cloc_max": 0.0,
1613 "ploc_min": 1.0,
1614 "ploc_max": 1.0,
1615 "lloc_min": 1.0,
1616 "lloc_max": 1.0,
1617 "blank_min": 0.0,
1618 "blank_max": 0.0
1619 }"###
1620 );
1621 },
1622 );
1623 }
1624
1625 #[test]
1626 fn python_blank() {
1627 check_metrics::<PythonParser>(
1628 "
1629 a = 42
1630
1631 b = 43
1632
1633 ",
1634 "foo.py",
1635 |metric| {
1636 insta::assert_json_snapshot!(
1638 metric.loc,
1639 @r###"
1640 {
1641 "sloc": 3.0,
1642 "ploc": 2.0,
1643 "lloc": 2.0,
1644 "cloc": 0.0,
1645 "blank": 1.0,
1646 "sloc_average": 3.0,
1647 "ploc_average": 2.0,
1648 "lloc_average": 2.0,
1649 "cloc_average": 0.0,
1650 "blank_average": 1.0,
1651 "sloc_min": 3.0,
1652 "sloc_max": 3.0,
1653 "cloc_min": 0.0,
1654 "cloc_max": 0.0,
1655 "ploc_min": 2.0,
1656 "ploc_max": 2.0,
1657 "lloc_min": 2.0,
1658 "lloc_max": 2.0,
1659 "blank_min": 1.0,
1660 "blank_max": 1.0
1661 }"###
1662 );
1663 },
1664 );
1665 }
1666
1667 #[test]
1668 fn rust_blank() {
1669 check_metrics::<RustParser>(
1670 "
1671
1672 let a = 42;
1673
1674 let b = 43;
1675
1676 ",
1677 "foo.rs",
1678 |metric| {
1679 insta::assert_json_snapshot!(
1681 metric.loc,
1682 @r###"
1683 {
1684 "sloc": 3.0,
1685 "ploc": 2.0,
1686 "lloc": 2.0,
1687 "cloc": 0.0,
1688 "blank": 1.0,
1689 "sloc_average": 3.0,
1690 "ploc_average": 2.0,
1691 "lloc_average": 2.0,
1692 "cloc_average": 0.0,
1693 "blank_average": 1.0,
1694 "sloc_min": 3.0,
1695 "sloc_max": 3.0,
1696 "cloc_min": 0.0,
1697 "cloc_max": 0.0,
1698 "ploc_min": 2.0,
1699 "ploc_max": 2.0,
1700 "lloc_min": 2.0,
1701 "lloc_max": 2.0,
1702 "blank_min": 1.0,
1703 "blank_max": 1.0
1704 }"###
1705 );
1706 },
1707 );
1708
1709 check_metrics::<RustParser>("fn func() { /* comment */ }", "foo.rs", |metric| {
1710 insta::assert_json_snapshot!(
1712 metric.loc,
1713 @r###"
1714 {
1715 "sloc": 1.0,
1716 "ploc": 1.0,
1717 "lloc": 0.0,
1718 "cloc": 1.0,
1719 "blank": 0.0,
1720 "sloc_average": 0.5,
1721 "ploc_average": 0.5,
1722 "lloc_average": 0.0,
1723 "cloc_average": 0.5,
1724 "blank_average": 0.0,
1725 "sloc_min": 1.0,
1726 "sloc_max": 1.0,
1727 "cloc_min": 1.0,
1728 "cloc_max": 1.0,
1729 "ploc_min": 1.0,
1730 "ploc_max": 1.0,
1731 "lloc_min": 0.0,
1732 "lloc_max": 0.0,
1733 "blank_min": 0.0,
1734 "blank_max": 0.0
1735 }"###
1736 );
1737 });
1738 }
1739
1740 #[test]
1741 fn c_blank() {
1742 check_metrics::<CppParser>(
1743 "
1744
1745 int a = 42;
1746
1747 int b = 43;
1748
1749 ",
1750 "foo.c",
1751 |metric| {
1752 insta::assert_json_snapshot!(
1754 metric.loc,
1755 @r###"
1756 {
1757 "sloc": 3.0,
1758 "ploc": 2.0,
1759 "lloc": 2.0,
1760 "cloc": 0.0,
1761 "blank": 1.0,
1762 "sloc_average": 3.0,
1763 "ploc_average": 2.0,
1764 "lloc_average": 2.0,
1765 "cloc_average": 0.0,
1766 "blank_average": 1.0,
1767 "sloc_min": 3.0,
1768 "sloc_max": 3.0,
1769 "cloc_min": 0.0,
1770 "cloc_max": 0.0,
1771 "ploc_min": 2.0,
1772 "ploc_max": 2.0,
1773 "lloc_min": 2.0,
1774 "lloc_max": 2.0,
1775 "blank_min": 1.0,
1776 "blank_max": 1.0
1777 }"###
1778 );
1779 },
1780 );
1781 }
1782
1783 #[test]
1784 fn python_no_zero_blank() {
1785 check_metrics::<PythonParser>(
1788 "def ConnectToUpdateServer():
1789 pool = 4
1790
1791 updateServer = -42
1792 isConnected = False
1793 currTry = 0
1794 numRetries = 10 # Number of IPC connection retries before
1795 # giving up.
1796 numTries = 20 # Number of IPC connection tries before
1797 # giving up.",
1798 "foo.py",
1799 |metric| {
1800 insta::assert_json_snapshot!(
1802 metric.loc,
1803 @r###"
1804 {
1805 "sloc": 10.0,
1806 "ploc": 7.0,
1807 "lloc": 6.0,
1808 "cloc": 4.0,
1809 "blank": 1.0,
1810 "sloc_average": 5.0,
1811 "ploc_average": 3.5,
1812 "lloc_average": 3.0,
1813 "cloc_average": 2.0,
1814 "blank_average": 0.5,
1815 "sloc_min": 10.0,
1816 "sloc_max": 10.0,
1817 "cloc_min": 4.0,
1818 "cloc_max": 4.0,
1819 "ploc_min": 7.0,
1820 "ploc_max": 7.0,
1821 "lloc_min": 6.0,
1822 "lloc_max": 6.0,
1823 "blank_min": 1.0,
1824 "blank_max": 1.0
1825 }"###
1826 );
1827 },
1828 );
1829 }
1830
1831 #[test]
1832 fn python_no_blank() {
1833 check_metrics::<PythonParser>(
1836 "def ConnectToUpdateServer():
1837 pool = 4
1838 updateServer = -42
1839 isConnected = False
1840 currTry = 0
1841 numRetries = 10 # Number of IPC connection retries before
1842 # giving up.
1843 numTries = 20 # Number of IPC connection tries before
1844 # giving up.",
1845 "foo.py",
1846 |metric| {
1847 insta::assert_json_snapshot!(
1849 metric.loc,
1850 @r###"
1851 {
1852 "sloc": 9.0,
1853 "ploc": 7.0,
1854 "lloc": 6.0,
1855 "cloc": 4.0,
1856 "blank": 0.0,
1857 "sloc_average": 4.5,
1858 "ploc_average": 3.5,
1859 "lloc_average": 3.0,
1860 "cloc_average": 2.0,
1861 "blank_average": 0.0,
1862 "sloc_min": 9.0,
1863 "sloc_max": 9.0,
1864 "cloc_min": 4.0,
1865 "cloc_max": 4.0,
1866 "ploc_min": 7.0,
1867 "ploc_max": 7.0,
1868 "lloc_min": 6.0,
1869 "lloc_max": 6.0,
1870 "blank_min": 0.0,
1871 "blank_max": 0.0
1872 }"###
1873 );
1874 },
1875 );
1876 }
1877
1878 #[test]
1879 fn python_no_zero_blank_more_comments() {
1880 check_metrics::<PythonParser>(
1883 "def ConnectToUpdateServer():
1884 pool = 4
1885
1886 updateServer = -42
1887 isConnected = False
1888 currTry = 0 # Set this variable to 0
1889 numRetries = 10 # Number of IPC connection retries before
1890 # giving up.
1891 numTries = 20 # Number of IPC connection tries before
1892 # giving up.",
1893 "foo.py",
1894 |metric| {
1895 insta::assert_json_snapshot!(
1897 metric.loc,
1898 @r###"
1899 {
1900 "sloc": 10.0,
1901 "ploc": 7.0,
1902 "lloc": 6.0,
1903 "cloc": 5.0,
1904 "blank": 1.0,
1905 "sloc_average": 5.0,
1906 "ploc_average": 3.5,
1907 "lloc_average": 3.0,
1908 "cloc_average": 2.5,
1909 "blank_average": 0.5,
1910 "sloc_min": 10.0,
1911 "sloc_max": 10.0,
1912 "cloc_min": 5.0,
1913 "cloc_max": 5.0,
1914 "ploc_min": 7.0,
1915 "ploc_max": 7.0,
1916 "lloc_min": 6.0,
1917 "lloc_max": 6.0,
1918 "blank_min": 1.0,
1919 "blank_max": 1.0
1920 }"###
1921 );
1922 },
1923 );
1924 }
1925
1926 #[test]
1927 fn rust_no_zero_blank() {
1928 check_metrics::<RustParser>(
1931 "fn ConnectToUpdateServer() {
1932 let pool = 0;
1933
1934 let updateServer = -42;
1935 let isConnected = false;
1936 let currTry = 0;
1937 let numRetries = 10; // Number of IPC connection retries before
1938 // giving up.
1939 let numTries = 20; // Number of IPC connection tries before
1940 // giving up.
1941 }",
1942 "foo.rs",
1943 |metric| {
1944 insta::assert_json_snapshot!(
1946 metric.loc,
1947 @r###"
1948 {
1949 "sloc": 11.0,
1950 "ploc": 8.0,
1951 "lloc": 6.0,
1952 "cloc": 4.0,
1953 "blank": 1.0,
1954 "sloc_average": 5.5,
1955 "ploc_average": 4.0,
1956 "lloc_average": 3.0,
1957 "cloc_average": 2.0,
1958 "blank_average": 0.5,
1959 "sloc_min": 11.0,
1960 "sloc_max": 11.0,
1961 "cloc_min": 4.0,
1962 "cloc_max": 4.0,
1963 "ploc_min": 8.0,
1964 "ploc_max": 8.0,
1965 "lloc_min": 6.0,
1966 "lloc_max": 6.0,
1967 "blank_min": 1.0,
1968 "blank_max": 1.0
1969 }"###
1970 );
1971 },
1972 );
1973 }
1974
1975 #[test]
1976 fn javascript_no_zero_blank() {
1977 check_metrics::<JavascriptParser>(
1980 "function ConnectToUpdateServer() {
1981 var pool = 0;
1982
1983 var updateServer = -42;
1984 var isConnected = false;
1985 var currTry = 0;
1986 var numRetries = 10; // Number of IPC connection retries before
1987 // giving up.
1988 var numTries = 20; // Number of IPC connection tries before
1989 // giving up.
1990 }",
1991 "foo.js",
1992 |metric| {
1993 insta::assert_json_snapshot!(
1995 metric.loc,
1996 @r###"
1997 {
1998 "sloc": 11.0,
1999 "ploc": 8.0,
2000 "lloc": 1.0,
2001 "cloc": 4.0,
2002 "blank": 1.0,
2003 "sloc_average": 5.5,
2004 "ploc_average": 4.0,
2005 "lloc_average": 0.5,
2006 "cloc_average": 2.0,
2007 "blank_average": 0.5,
2008 "sloc_min": 11.0,
2009 "sloc_max": 11.0,
2010 "cloc_min": 4.0,
2011 "cloc_max": 4.0,
2012 "ploc_min": 8.0,
2013 "ploc_max": 8.0,
2014 "lloc_min": 1.0,
2015 "lloc_max": 1.0,
2016 "blank_min": 1.0,
2017 "blank_max": 1.0
2018 }"###
2019 );
2020 },
2021 );
2022 }
2023
2024 #[test]
2025 fn cpp_no_zero_blank() {
2026 check_metrics::<CppParser>(
2029 "void ConnectToUpdateServer() {
2030 int pool;
2031
2032 int updateServer = -42;
2033 bool isConnected = false;
2034 int currTry = 0;
2035 const int numRetries = 10; // Number of IPC connection retries before
2036 // giving up.
2037 const int numTries = 20; // Number of IPC connection tries before
2038 // giving up.
2039 }",
2040 "foo.cpp",
2041 |metric| {
2042 insta::assert_json_snapshot!(
2044 metric.loc,
2045 @r###"
2046 {
2047 "sloc": 11.0,
2048 "ploc": 8.0,
2049 "lloc": 6.0,
2050 "cloc": 4.0,
2051 "blank": 1.0,
2052 "sloc_average": 5.5,
2053 "ploc_average": 4.0,
2054 "lloc_average": 3.0,
2055 "cloc_average": 2.0,
2056 "blank_average": 0.5,
2057 "sloc_min": 11.0,
2058 "sloc_max": 11.0,
2059 "cloc_min": 4.0,
2060 "cloc_max": 4.0,
2061 "ploc_min": 8.0,
2062 "ploc_max": 8.0,
2063 "lloc_min": 6.0,
2064 "lloc_max": 6.0,
2065 "blank_min": 1.0,
2066 "blank_max": 1.0
2067 }"###
2068 );
2069 },
2070 );
2071 }
2072
2073 #[test]
2074 fn cpp_code_line_start_block_blank() {
2075 check_metrics::<CppParser>(
2078 "void ConnectToUpdateServer() {
2079 int pool;
2080
2081 int updateServer = -42;
2082 bool isConnected = false;
2083 int currTry = 0;
2084 const int numRetries = 10; /* Number of IPC connection retries
2085 before
2086 giving up. */
2087 const int numTries = 20; // Number of IPC connection tries before
2088 // giving up.
2089 }",
2090 "foo.cpp",
2091 |metric| {
2092 insta::assert_json_snapshot!(
2094 metric.loc,
2095 @r###"
2096 {
2097 "sloc": 12.0,
2098 "ploc": 8.0,
2099 "lloc": 6.0,
2100 "cloc": 5.0,
2101 "blank": 1.0,
2102 "sloc_average": 6.0,
2103 "ploc_average": 4.0,
2104 "lloc_average": 3.0,
2105 "cloc_average": 2.5,
2106 "blank_average": 0.5,
2107 "sloc_min": 12.0,
2108 "sloc_max": 12.0,
2109 "cloc_min": 5.0,
2110 "cloc_max": 5.0,
2111 "ploc_min": 8.0,
2112 "ploc_max": 8.0,
2113 "lloc_min": 6.0,
2114 "lloc_max": 6.0,
2115 "blank_min": 1.0,
2116 "blank_max": 1.0
2117 }"###
2118 );
2119 },
2120 );
2121 }
2122
2123 #[test]
2124 fn cpp_block_comment_blank() {
2125 check_metrics::<CppParser>(
2128 "void ConnectToUpdateServer() {
2129 int pool;
2130
2131 int updateServer = -42;
2132 bool isConnected = false;
2133 int currTry = 0;
2134 /* Number of IPC connection retries
2135 before
2136 giving up. */
2137 const int numRetries = 10;
2138 const int numTries = 20; // Number of IPC connection tries before
2139 // giving up.
2140 }",
2141 "foo.cpp",
2142 |metric| {
2143 insta::assert_json_snapshot!(
2145 metric.loc,
2146 @r###"
2147 {
2148 "sloc": 13.0,
2149 "ploc": 8.0,
2150 "lloc": 6.0,
2151 "cloc": 5.0,
2152 "blank": 1.0,
2153 "sloc_average": 6.5,
2154 "ploc_average": 4.0,
2155 "lloc_average": 3.0,
2156 "cloc_average": 2.5,
2157 "blank_average": 0.5,
2158 "sloc_min": 13.0,
2159 "sloc_max": 13.0,
2160 "cloc_min": 5.0,
2161 "cloc_max": 5.0,
2162 "ploc_min": 8.0,
2163 "ploc_max": 8.0,
2164 "lloc_min": 6.0,
2165 "lloc_max": 6.0,
2166 "blank_min": 1.0,
2167 "blank_max": 1.0
2168 }"###
2169 );
2170 },
2171 );
2172 }
2173
2174 #[test]
2175 fn cpp_code_line_block_one_line_blank() {
2176 check_metrics::<CppParser>(
2179 "void ConnectToUpdateServer() {
2180 int pool;
2181
2182 int updateServer = -42;
2183 bool isConnected = false;
2184 int currTry = 0;
2185 /* Number of IPC connection retries before giving up. */ const int numRetries = 10;
2186 const int numTries = 20; // Number of IPC connection tries before
2187 // giving up.
2188 }",
2189 "foo.cpp",
2190 |metric| {
2191 insta::assert_json_snapshot!(
2193 metric.loc,
2194 @r###"
2195 {
2196 "sloc": 10.0,
2197 "ploc": 8.0,
2198 "lloc": 6.0,
2199 "cloc": 3.0,
2200 "blank": 1.0,
2201 "sloc_average": 5.0,
2202 "ploc_average": 4.0,
2203 "lloc_average": 3.0,
2204 "cloc_average": 1.5,
2205 "blank_average": 0.5,
2206 "sloc_min": 10.0,
2207 "sloc_max": 10.0,
2208 "cloc_min": 3.0,
2209 "cloc_max": 3.0,
2210 "ploc_min": 8.0,
2211 "ploc_max": 8.0,
2212 "lloc_min": 6.0,
2213 "lloc_max": 6.0,
2214 "blank_min": 1.0,
2215 "blank_max": 1.0
2216 }"###
2217 );
2218 },
2219 );
2220 }
2221
2222 #[test]
2223 fn cpp_code_line_end_block_blank() {
2224 check_metrics::<CppParser>(
2227 "void ConnectToUpdateServer() {
2228 int pool;
2229
2230 int updateServer = -42;
2231 bool isConnected = false;
2232 int currTry = 0;
2233 /* Number of IPC connection retries
2234 before
2235 giving up. */ const int numRetries = 10;
2236 const int numTries = 20; // Number of IPC connection tries before
2237 // giving up.
2238 }",
2239 "foo.cpp",
2240 |metric| {
2241 insta::assert_json_snapshot!(
2243 metric.loc,
2244 @r###"
2245 {
2246 "sloc": 12.0,
2247 "ploc": 8.0,
2248 "lloc": 6.0,
2249 "cloc": 5.0,
2250 "blank": 1.0,
2251 "sloc_average": 6.0,
2252 "ploc_average": 4.0,
2253 "lloc_average": 3.0,
2254 "cloc_average": 2.5,
2255 "blank_average": 0.5,
2256 "sloc_min": 12.0,
2257 "sloc_max": 12.0,
2258 "cloc_min": 5.0,
2259 "cloc_max": 5.0,
2260 "ploc_min": 8.0,
2261 "ploc_max": 8.0,
2262 "lloc_min": 6.0,
2263 "lloc_max": 6.0,
2264 "blank_min": 1.0,
2265 "blank_max": 1.0
2266 }"###
2267 );
2268 },
2269 );
2270 }
2271
2272 #[test]
2273 fn python_cloc() {
2274 check_metrics::<PythonParser>(
2275 "\"\"\"Block comment
2276 Block comment
2277 \"\"\"
2278 # Line Comment
2279 a = 42 # Line Comment",
2280 "foo.py",
2281 |metric| {
2282 insta::assert_json_snapshot!(
2284 metric.loc,
2285 @r###"
2286 {
2287 "sloc": 5.0,
2288 "ploc": 1.0,
2289 "lloc": 2.0,
2290 "cloc": 5.0,
2291 "blank": 0.0,
2292 "sloc_average": 5.0,
2293 "ploc_average": 1.0,
2294 "lloc_average": 2.0,
2295 "cloc_average": 5.0,
2296 "blank_average": 0.0,
2297 "sloc_min": 5.0,
2298 "sloc_max": 5.0,
2299 "cloc_min": 5.0,
2300 "cloc_max": 5.0,
2301 "ploc_min": 1.0,
2302 "ploc_max": 1.0,
2303 "lloc_min": 2.0,
2304 "lloc_max": 2.0,
2305 "blank_min": 0.0,
2306 "blank_max": 0.0
2307 }"###
2308 );
2309 },
2310 );
2311 }
2312
2313 #[test]
2314 fn rust_cloc() {
2315 check_metrics::<RustParser>(
2316 "/*Block comment
2317 Block Comment*/
2318 //Line Comment
2319 /*Block Comment*/ let a = 42; // Line Comment",
2320 "foo.rs",
2321 |metric| {
2322 insta::assert_json_snapshot!(
2324 metric.loc,
2325 @r###"
2326 {
2327 "sloc": 4.0,
2328 "ploc": 1.0,
2329 "lloc": 1.0,
2330 "cloc": 5.0,
2331 "blank": 0.0,
2332 "sloc_average": 4.0,
2333 "ploc_average": 1.0,
2334 "lloc_average": 1.0,
2335 "cloc_average": 5.0,
2336 "blank_average": 0.0,
2337 "sloc_min": 4.0,
2338 "sloc_max": 4.0,
2339 "cloc_min": 5.0,
2340 "cloc_max": 5.0,
2341 "ploc_min": 1.0,
2342 "ploc_max": 1.0,
2343 "lloc_min": 1.0,
2344 "lloc_max": 1.0,
2345 "blank_min": 0.0,
2346 "blank_max": 0.0
2347 }"###
2348 );
2349 },
2350 );
2351 }
2352
2353 #[test]
2354 fn c_cloc() {
2355 check_metrics::<CppParser>(
2356 "/*Block comment
2357 Block Comment*/
2358 //Line Comment
2359 /*Block Comment*/ int a = 42; // Line Comment",
2360 "foo.c",
2361 |metric| {
2362 insta::assert_json_snapshot!(
2364 metric.loc,
2365 @r###"
2366 {
2367 "sloc": 4.0,
2368 "ploc": 1.0,
2369 "lloc": 1.0,
2370 "cloc": 5.0,
2371 "blank": 0.0,
2372 "sloc_average": 4.0,
2373 "ploc_average": 1.0,
2374 "lloc_average": 1.0,
2375 "cloc_average": 5.0,
2376 "blank_average": 0.0,
2377 "sloc_min": 4.0,
2378 "sloc_max": 4.0,
2379 "cloc_min": 5.0,
2380 "cloc_max": 5.0,
2381 "ploc_min": 1.0,
2382 "ploc_max": 1.0,
2383 "lloc_min": 1.0,
2384 "lloc_max": 1.0,
2385 "blank_min": 0.0,
2386 "blank_max": 0.0
2387 }"###
2388 );
2389 },
2390 );
2391 }
2392
2393 #[test]
2394 fn python_lloc() {
2395 check_metrics::<PythonParser>(
2396 "for x in range(0,42):
2397 if x % 2 == 0:
2398 print(x)",
2399 "foo.py",
2400 |metric| {
2401 insta::assert_json_snapshot!(
2403 metric.loc,
2404 @r###"
2405 {
2406 "sloc": 3.0,
2407 "ploc": 3.0,
2408 "lloc": 3.0,
2409 "cloc": 0.0,
2410 "blank": 0.0,
2411 "sloc_average": 3.0,
2412 "ploc_average": 3.0,
2413 "lloc_average": 3.0,
2414 "cloc_average": 0.0,
2415 "blank_average": 0.0,
2416 "sloc_min": 3.0,
2417 "sloc_max": 3.0,
2418 "cloc_min": 0.0,
2419 "cloc_max": 0.0,
2420 "ploc_min": 3.0,
2421 "ploc_max": 3.0,
2422 "lloc_min": 3.0,
2423 "lloc_max": 3.0,
2424 "blank_min": 0.0,
2425 "blank_max": 0.0
2426 }"###
2427 );
2428 },
2429 );
2430 }
2431
2432 #[test]
2433 fn rust_lloc() {
2434 check_metrics::<RustParser>(
2435 "for x in 0..42 {
2436 if x % 2 == 0 {
2437 println!(\"{}\", x);
2438 }
2439 }",
2440 "foo.rs",
2441 |metric| {
2442 insta::assert_json_snapshot!(
2444 metric.loc,
2445 @r###"
2446 {
2447 "sloc": 5.0,
2448 "ploc": 5.0,
2449 "lloc": 3.0,
2450 "cloc": 0.0,
2451 "blank": 0.0,
2452 "sloc_average": 5.0,
2453 "ploc_average": 5.0,
2454 "lloc_average": 3.0,
2455 "cloc_average": 0.0,
2456 "blank_average": 0.0,
2457 "sloc_min": 5.0,
2458 "sloc_max": 5.0,
2459 "cloc_min": 0.0,
2460 "cloc_max": 0.0,
2461 "ploc_min": 5.0,
2462 "ploc_max": 5.0,
2463 "lloc_min": 3.0,
2464 "lloc_max": 3.0,
2465 "blank_min": 0.0,
2466 "blank_max": 0.0
2467 }"###
2468 );
2469 },
2470 );
2471
2472 check_metrics::<RustParser>(
2474 "let a = 42;
2475 if true {
2476 42
2477 } else {
2478 43
2479 };",
2480 "foo.rs",
2481 |metric| {
2482 insta::assert_json_snapshot!(
2484 metric.loc,
2485 @r###"
2486 {
2487 "sloc": 6.0,
2488 "ploc": 6.0,
2489 "lloc": 3.0,
2490 "cloc": 0.0,
2491 "blank": 0.0,
2492 "sloc_average": 6.0,
2493 "ploc_average": 6.0,
2494 "lloc_average": 3.0,
2495 "cloc_average": 0.0,
2496 "blank_average": 0.0,
2497 "sloc_min": 6.0,
2498 "sloc_max": 6.0,
2499 "cloc_min": 0.0,
2500 "cloc_max": 0.0,
2501 "ploc_min": 6.0,
2502 "ploc_max": 6.0,
2503 "lloc_min": 3.0,
2504 "lloc_max": 3.0,
2505 "blank_min": 0.0,
2506 "blank_max": 0.0
2507 }"###
2508 );
2509 },
2510 );
2511 }
2512
2513 #[test]
2514 fn c_lloc() {
2515 check_metrics::<CppParser>(
2516 "for (;;)
2517 break;",
2518 "foo.c",
2519 |metric| {
2520 insta::assert_json_snapshot!(
2522 metric.loc,
2523 @r###"
2524 {
2525 "sloc": 2.0,
2526 "ploc": 2.0,
2527 "lloc": 2.0,
2528 "cloc": 0.0,
2529 "blank": 0.0,
2530 "sloc_average": 2.0,
2531 "ploc_average": 2.0,
2532 "lloc_average": 2.0,
2533 "cloc_average": 0.0,
2534 "blank_average": 0.0,
2535 "sloc_min": 2.0,
2536 "sloc_max": 2.0,
2537 "cloc_min": 0.0,
2538 "cloc_max": 0.0,
2539 "ploc_min": 2.0,
2540 "ploc_max": 2.0,
2541 "lloc_min": 2.0,
2542 "lloc_max": 2.0,
2543 "blank_min": 0.0,
2544 "blank_max": 0.0
2545 }"###
2546 );
2547 },
2548 );
2549 }
2550
2551 #[test]
2552 fn cpp_lloc() {
2553 check_metrics::<CppParser>(
2554 "nsTArray<xpcGCCallback> callbacks(extraGCCallbacks.Clone());
2555 for (uint32_t i = 0; i < callbacks.Length(); ++i) {
2556 callbacks[i](status);
2557 }",
2558 "foo.cpp",
2559 |metric| {
2560 insta::assert_json_snapshot!(
2563 metric.loc,
2564 @r###"
2565 {
2566 "sloc": 4.0,
2567 "ploc": 4.0,
2568 "lloc": 3.0,
2569 "cloc": 0.0,
2570 "blank": 0.0,
2571 "sloc_average": 4.0,
2572 "ploc_average": 4.0,
2573 "lloc_average": 3.0,
2574 "cloc_average": 0.0,
2575 "blank_average": 0.0,
2576 "sloc_min": 4.0,
2577 "sloc_max": 4.0,
2578 "cloc_min": 0.0,
2579 "cloc_max": 0.0,
2580 "ploc_min": 4.0,
2581 "ploc_max": 4.0,
2582 "lloc_min": 3.0,
2583 "lloc_max": 3.0,
2584 "blank_min": 0.0,
2585 "blank_max": 0.0
2586 }"###
2587 );
2588 },
2589 );
2590 }
2591
2592 #[test]
2593 fn cpp_return_lloc() {
2594 check_metrics::<CppParser>(
2595 "uint8_t* pixel_data = frame.GetFrameDataAtPos(DesktopVector(x, y));
2596 return RgbaColor(pixel_data) == blank_pixel_;",
2597 "foo.cpp",
2598 |metric| {
2599 insta::assert_json_snapshot!(
2602 metric.loc,
2603 @r###"
2604 {
2605 "sloc": 2.0,
2606 "ploc": 2.0,
2607 "lloc": 2.0,
2608 "cloc": 0.0,
2609 "blank": 0.0,
2610 "sloc_average": 2.0,
2611 "ploc_average": 2.0,
2612 "lloc_average": 2.0,
2613 "cloc_average": 0.0,
2614 "blank_average": 0.0,
2615 "sloc_min": 2.0,
2616 "sloc_max": 2.0,
2617 "cloc_min": 0.0,
2618 "cloc_max": 0.0,
2619 "ploc_min": 2.0,
2620 "ploc_max": 2.0,
2621 "lloc_min": 2.0,
2622 "lloc_max": 2.0,
2623 "blank_min": 0.0,
2624 "blank_max": 0.0
2625 }"###
2626 );
2627 },
2628 );
2629 }
2630
2631 #[test]
2632 fn cpp_for_lloc() {
2633 check_metrics::<CppParser>(
2634 "for (; start != end; ++start) {
2635 const unsigned char idx = *start;
2636 if (idx > 127 || !kValidTokenMap[idx]) return false;
2637 }",
2638 "foo.cpp",
2639 |metric| {
2640 insta::assert_json_snapshot!(
2643 metric.loc,
2644 @r###"
2645 {
2646 "sloc": 4.0,
2647 "ploc": 4.0,
2648 "lloc": 4.0,
2649 "cloc": 0.0,
2650 "blank": 0.0,
2651 "sloc_average": 4.0,
2652 "ploc_average": 4.0,
2653 "lloc_average": 4.0,
2654 "cloc_average": 0.0,
2655 "blank_average": 0.0,
2656 "sloc_min": 4.0,
2657 "sloc_max": 4.0,
2658 "cloc_min": 0.0,
2659 "cloc_max": 0.0,
2660 "ploc_min": 4.0,
2661 "ploc_max": 4.0,
2662 "lloc_min": 4.0,
2663 "lloc_max": 4.0,
2664 "blank_min": 0.0,
2665 "blank_max": 0.0
2666 }"###
2667 );
2668 },
2669 );
2670 }
2671
2672 #[test]
2673 fn cpp_while_lloc() {
2674 check_metrics::<CppParser>(
2675 "while (sHeapAtoms) {
2676 HttpHeapAtom* next = sHeapAtoms->next;
2677 free(sHeapAtoms);
2678 }",
2679 "foo.cpp",
2680 |metric| {
2681 insta::assert_json_snapshot!(
2684 metric.loc,
2685 @r###"
2686 {
2687 "sloc": 4.0,
2688 "ploc": 4.0,
2689 "lloc": 3.0,
2690 "cloc": 0.0,
2691 "blank": 0.0,
2692 "sloc_average": 4.0,
2693 "ploc_average": 4.0,
2694 "lloc_average": 3.0,
2695 "cloc_average": 0.0,
2696 "blank_average": 0.0,
2697 "sloc_min": 4.0,
2698 "sloc_max": 4.0,
2699 "cloc_min": 0.0,
2700 "cloc_max": 0.0,
2701 "ploc_min": 4.0,
2702 "ploc_max": 4.0,
2703 "lloc_min": 3.0,
2704 "lloc_max": 3.0,
2705 "blank_min": 0.0,
2706 "blank_max": 0.0
2707 }"###
2708 );
2709 },
2710 );
2711 }
2712
2713 #[test]
2714 fn python_string_on_new_line() {
2715 check_metrics::<PythonParser>(
2717 "capabilities[\"goog:chromeOptions\"][\"androidPackage\"] = \\
2718 \"org.chromium.weblayer.shell\"",
2719 "foo.py",
2720 |metric| {
2721 insta::assert_json_snapshot!(
2723 metric.loc,
2724 @r###"
2725 {
2726 "sloc": 2.0,
2727 "ploc": 2.0,
2728 "lloc": 1.0,
2729 "cloc": 0.0,
2730 "blank": 0.0,
2731 "sloc_average": 2.0,
2732 "ploc_average": 2.0,
2733 "lloc_average": 1.0,
2734 "cloc_average": 0.0,
2735 "blank_average": 0.0,
2736 "sloc_min": 2.0,
2737 "sloc_max": 2.0,
2738 "cloc_min": 0.0,
2739 "cloc_max": 0.0,
2740 "ploc_min": 2.0,
2741 "ploc_max": 2.0,
2742 "lloc_min": 1.0,
2743 "lloc_max": 1.0,
2744 "blank_min": 0.0,
2745 "blank_max": 0.0
2746 }"###
2747 );
2748 },
2749 );
2750 }
2751
2752 #[test]
2753 fn rust_no_field_expression_lloc() {
2754 check_metrics::<RustParser>(
2755 "struct Foo {
2756 field: usize,
2757 }
2758 let foo = Foo { 42 };
2759 foo.field;",
2760 "foo.rs",
2761 |metric| {
2762 insta::assert_json_snapshot!(
2764 metric.loc,
2765 @r###"
2766 {
2767 "sloc": 5.0,
2768 "ploc": 5.0,
2769 "lloc": 2.0,
2770 "cloc": 0.0,
2771 "blank": 0.0,
2772 "sloc_average": 5.0,
2773 "ploc_average": 5.0,
2774 "lloc_average": 2.0,
2775 "cloc_average": 0.0,
2776 "blank_average": 0.0,
2777 "sloc_min": 5.0,
2778 "sloc_max": 5.0,
2779 "cloc_min": 0.0,
2780 "cloc_max": 0.0,
2781 "ploc_min": 5.0,
2782 "ploc_max": 5.0,
2783 "lloc_min": 2.0,
2784 "lloc_max": 2.0,
2785 "blank_min": 0.0,
2786 "blank_max": 0.0
2787 }"###
2788 );
2789 },
2790 );
2791 }
2792
2793 #[test]
2794 fn rust_no_parenthesized_expression_lloc() {
2795 check_metrics::<RustParser>("let a = (42 + 0);", "foo.rs", |metric| {
2796 insta::assert_json_snapshot!(
2798 metric.loc,
2799 @r###"
2800 {
2801 "sloc": 1.0,
2802 "ploc": 1.0,
2803 "lloc": 1.0,
2804 "cloc": 0.0,
2805 "blank": 0.0,
2806 "sloc_average": 1.0,
2807 "ploc_average": 1.0,
2808 "lloc_average": 1.0,
2809 "cloc_average": 0.0,
2810 "blank_average": 0.0,
2811 "sloc_min": 1.0,
2812 "sloc_max": 1.0,
2813 "cloc_min": 0.0,
2814 "cloc_max": 0.0,
2815 "ploc_min": 1.0,
2816 "ploc_max": 1.0,
2817 "lloc_min": 1.0,
2818 "lloc_max": 1.0,
2819 "blank_min": 0.0,
2820 "blank_max": 0.0
2821 }"###
2822 );
2823 });
2824 }
2825
2826 #[test]
2827 fn rust_no_array_expression_lloc() {
2828 check_metrics::<RustParser>("let a = [0; 42];", "foo.rs", |metric| {
2829 insta::assert_json_snapshot!(
2831 metric.loc,
2832 @r###"
2833 {
2834 "sloc": 1.0,
2835 "ploc": 1.0,
2836 "lloc": 1.0,
2837 "cloc": 0.0,
2838 "blank": 0.0,
2839 "sloc_average": 1.0,
2840 "ploc_average": 1.0,
2841 "lloc_average": 1.0,
2842 "cloc_average": 0.0,
2843 "blank_average": 0.0,
2844 "sloc_min": 1.0,
2845 "sloc_max": 1.0,
2846 "cloc_min": 0.0,
2847 "cloc_max": 0.0,
2848 "ploc_min": 1.0,
2849 "ploc_max": 1.0,
2850 "lloc_min": 1.0,
2851 "lloc_max": 1.0,
2852 "blank_min": 0.0,
2853 "blank_max": 0.0
2854 }"###
2855 );
2856 });
2857 }
2858
2859 #[test]
2860 fn rust_no_tuple_expression_lloc() {
2861 check_metrics::<RustParser>("let a = (0, 42);", "foo.rs", |metric| {
2862 insta::assert_json_snapshot!(
2864 metric.loc,
2865 @r###"
2866 {
2867 "sloc": 1.0,
2868 "ploc": 1.0,
2869 "lloc": 1.0,
2870 "cloc": 0.0,
2871 "blank": 0.0,
2872 "sloc_average": 1.0,
2873 "ploc_average": 1.0,
2874 "lloc_average": 1.0,
2875 "cloc_average": 0.0,
2876 "blank_average": 0.0,
2877 "sloc_min": 1.0,
2878 "sloc_max": 1.0,
2879 "cloc_min": 0.0,
2880 "cloc_max": 0.0,
2881 "ploc_min": 1.0,
2882 "ploc_max": 1.0,
2883 "lloc_min": 1.0,
2884 "lloc_max": 1.0,
2885 "blank_min": 0.0,
2886 "blank_max": 0.0
2887 }"###
2888 );
2889 });
2890 }
2891
2892 #[test]
2893 fn rust_no_unit_expression_lloc() {
2894 check_metrics::<RustParser>("let a = ();", "foo.rs", |metric| {
2895 insta::assert_json_snapshot!(
2897 metric.loc,
2898 @r###"
2899 {
2900 "sloc": 1.0,
2901 "ploc": 1.0,
2902 "lloc": 1.0,
2903 "cloc": 0.0,
2904 "blank": 0.0,
2905 "sloc_average": 1.0,
2906 "ploc_average": 1.0,
2907 "lloc_average": 1.0,
2908 "cloc_average": 0.0,
2909 "blank_average": 0.0,
2910 "sloc_min": 1.0,
2911 "sloc_max": 1.0,
2912 "cloc_min": 0.0,
2913 "cloc_max": 0.0,
2914 "ploc_min": 1.0,
2915 "ploc_max": 1.0,
2916 "lloc_min": 1.0,
2917 "lloc_max": 1.0,
2918 "blank_min": 0.0,
2919 "blank_max": 0.0
2920 }"###
2921 );
2922 });
2923 }
2924
2925 #[test]
2926 fn rust_call_function_lloc() {
2927 check_metrics::<RustParser>(
2928 "let a = foo(); // +1
2929 foo(); // +1
2930 k!(foo()); // +1",
2931 "foo.rs",
2932 |metric| {
2933 insta::assert_json_snapshot!(
2935 metric.loc,
2936 @r###"
2937 {
2938 "sloc": 3.0,
2939 "ploc": 3.0,
2940 "lloc": 3.0,
2941 "cloc": 3.0,
2942 "blank": 0.0,
2943 "sloc_average": 3.0,
2944 "ploc_average": 3.0,
2945 "lloc_average": 3.0,
2946 "cloc_average": 3.0,
2947 "blank_average": 0.0,
2948 "sloc_min": 3.0,
2949 "sloc_max": 3.0,
2950 "cloc_min": 3.0,
2951 "cloc_max": 3.0,
2952 "ploc_min": 3.0,
2953 "ploc_max": 3.0,
2954 "lloc_min": 3.0,
2955 "lloc_max": 3.0,
2956 "blank_min": 0.0,
2957 "blank_max": 0.0
2958 }"###
2959 );
2960 },
2961 );
2962 }
2963
2964 #[test]
2965 fn rust_macro_invocation_lloc() {
2966 check_metrics::<RustParser>(
2967 "let a = foo!(); // +1
2968 foo!(); // +1
2969 k(foo!()); // +1",
2970 "foo.rs",
2971 |metric| {
2972 insta::assert_json_snapshot!(
2974 metric.loc,
2975 @r###"
2976 {
2977 "sloc": 3.0,
2978 "ploc": 3.0,
2979 "lloc": 3.0,
2980 "cloc": 3.0,
2981 "blank": 0.0,
2982 "sloc_average": 3.0,
2983 "ploc_average": 3.0,
2984 "lloc_average": 3.0,
2985 "cloc_average": 3.0,
2986 "blank_average": 0.0,
2987 "sloc_min": 3.0,
2988 "sloc_max": 3.0,
2989 "cloc_min": 3.0,
2990 "cloc_max": 3.0,
2991 "ploc_min": 3.0,
2992 "ploc_max": 3.0,
2993 "lloc_min": 3.0,
2994 "lloc_max": 3.0,
2995 "blank_min": 0.0,
2996 "blank_max": 0.0
2997 }"###
2998 );
2999 },
3000 );
3001 }
3002
3003 #[test]
3004 fn rust_function_in_loop_lloc() {
3005 check_metrics::<RustParser>(
3006 "for (a, b) in c.iter().enumerate() {} // +1
3007 while (a, b) in c.iter().enumerate() {} // +1
3008 while let Some(a) = c.strip_prefix(\"hi\") {} // +1",
3009 "foo.rs",
3010 |metric| {
3011 insta::assert_json_snapshot!(
3013 metric.loc,
3014 @r###"
3015 {
3016 "sloc": 3.0,
3017 "ploc": 3.0,
3018 "lloc": 3.0,
3019 "cloc": 3.0,
3020 "blank": 0.0,
3021 "sloc_average": 3.0,
3022 "ploc_average": 3.0,
3023 "lloc_average": 3.0,
3024 "cloc_average": 3.0,
3025 "blank_average": 0.0,
3026 "sloc_min": 3.0,
3027 "sloc_max": 3.0,
3028 "cloc_min": 3.0,
3029 "cloc_max": 3.0,
3030 "ploc_min": 3.0,
3031 "ploc_max": 3.0,
3032 "lloc_min": 3.0,
3033 "lloc_max": 3.0,
3034 "blank_min": 0.0,
3035 "blank_max": 0.0
3036 }"###
3037 );
3038 },
3039 );
3040 }
3041
3042 #[test]
3043 fn rust_function_in_if_lloc() {
3044 check_metrics::<RustParser>(
3045 "if foo() {} // +1
3046 if let Some(a) = foo() {} // +1",
3047 "foo.rs",
3048 |metric| {
3049 insta::assert_json_snapshot!(
3051 metric.loc,
3052 @r###"
3053 {
3054 "sloc": 2.0,
3055 "ploc": 2.0,
3056 "lloc": 2.0,
3057 "cloc": 2.0,
3058 "blank": 0.0,
3059 "sloc_average": 2.0,
3060 "ploc_average": 2.0,
3061 "lloc_average": 2.0,
3062 "cloc_average": 2.0,
3063 "blank_average": 0.0,
3064 "sloc_min": 2.0,
3065 "sloc_max": 2.0,
3066 "cloc_min": 2.0,
3067 "cloc_max": 2.0,
3068 "ploc_min": 2.0,
3069 "ploc_max": 2.0,
3070 "lloc_min": 2.0,
3071 "lloc_max": 2.0,
3072 "blank_min": 0.0,
3073 "blank_max": 0.0
3074 }"###
3075 );
3076 },
3077 );
3078 }
3079
3080 #[test]
3081 fn rust_function_in_return_lloc() {
3082 check_metrics::<RustParser>(
3083 "return foo();
3084 await foo();",
3085 "foo.rs",
3086 |metric| {
3087 insta::assert_json_snapshot!(
3089 metric.loc,
3090 @r###"
3091 {
3092 "sloc": 2.0,
3093 "ploc": 2.0,
3094 "lloc": 2.0,
3095 "cloc": 0.0,
3096 "blank": 0.0,
3097 "sloc_average": 2.0,
3098 "ploc_average": 2.0,
3099 "lloc_average": 2.0,
3100 "cloc_average": 0.0,
3101 "blank_average": 0.0,
3102 "sloc_min": 2.0,
3103 "sloc_max": 2.0,
3104 "cloc_min": 0.0,
3105 "cloc_max": 0.0,
3106 "ploc_min": 2.0,
3107 "ploc_max": 2.0,
3108 "lloc_min": 2.0,
3109 "lloc_max": 2.0,
3110 "blank_min": 0.0,
3111 "blank_max": 0.0
3112 }"###
3113 );
3114 },
3115 );
3116 }
3117
3118 #[test]
3119 fn rust_closure_expression_lloc() {
3120 check_metrics::<RustParser>(
3121 "let a = |i: i32| -> i32 { i + 1 }; // +1
3122 a(42); // +1
3123 k(b.iter().map(|n| n.parse.ok().unwrap_or(42))); // +1",
3124 "foo.rs",
3125 |metric| {
3126 insta::assert_json_snapshot!(
3128 metric.loc,
3129 @r###"
3130 {
3131 "sloc": 3.0,
3132 "ploc": 3.0,
3133 "lloc": 3.0,
3134 "cloc": 3.0,
3135 "blank": 0.0,
3136 "sloc_average": 1.0,
3137 "ploc_average": 1.0,
3138 "lloc_average": 1.0,
3139 "cloc_average": 1.0,
3140 "blank_average": 0.0,
3141 "sloc_min": 1.0,
3142 "sloc_max": 1.0,
3143 "cloc_min": 0.0,
3144 "cloc_max": 0.0,
3145 "ploc_min": 1.0,
3146 "ploc_max": 1.0,
3147 "lloc_min": 0.0,
3148 "lloc_max": 0.0,
3149 "blank_min": 0.0,
3150 "blank_max": 0.0
3151 }"###
3152 );
3153 },
3154 );
3155 }
3156
3157 #[test]
3158 fn python_general_loc() {
3159 check_metrics::<PythonParser>(
3160 "def func(a,
3161 b,
3162 c):
3163 print(a)
3164 print(b)
3165 print(c)",
3166 "foo.py",
3167 |metric| {
3168 insta::assert_json_snapshot!(
3170 metric.loc,
3171 @r###"
3172 {
3173 "sloc": 6.0,
3174 "ploc": 6.0,
3175 "lloc": 3.0,
3176 "cloc": 0.0,
3177 "blank": 0.0,
3178 "sloc_average": 3.0,
3179 "ploc_average": 3.0,
3180 "lloc_average": 1.5,
3181 "cloc_average": 0.0,
3182 "blank_average": 0.0,
3183 "sloc_min": 6.0,
3184 "sloc_max": 6.0,
3185 "cloc_min": 0.0,
3186 "cloc_max": 0.0,
3187 "ploc_min": 6.0,
3188 "ploc_max": 6.0,
3189 "lloc_min": 3.0,
3190 "lloc_max": 3.0,
3191 "blank_min": 0.0,
3192 "blank_max": 0.0
3193 }"###
3194 );
3195 },
3196 );
3197 }
3198
3199 #[test]
3200 fn python_real_loc() {
3201 check_metrics::<PythonParser>(
3202 "def web_socket_transfer_data(request):
3203 while True:
3204 line = request.ws_stream.receive_message()
3205 if line is None:
3206 return
3207 code, reason = line.split(' ', 1)
3208 if code is None or reason is None:
3209 return
3210 request.ws_stream.close_connection(int(code), reason)
3211 # close_connection() initiates closing handshake. It validates code
3212 # and reason. If you want to send a broken close frame for a test,
3213 # following code will be useful.
3214 # > data = struct.pack('!H', int(code)) + reason.encode('UTF-8')
3215 # > request.connection.write(stream.create_close_frame(data))
3216 # > # Suppress to re-respond client responding close frame.
3217 # > raise Exception(\"customized server initiated closing handshake\")",
3218 "foo.py",
3219 |metric| {
3220 insta::assert_json_snapshot!(
3222 metric.loc,
3223 @r###"
3224 {
3225 "sloc": 16.0,
3226 "ploc": 9.0,
3227 "lloc": 8.0,
3228 "cloc": 7.0,
3229 "blank": 0.0,
3230 "sloc_average": 8.0,
3231 "ploc_average": 4.5,
3232 "lloc_average": 4.0,
3233 "cloc_average": 3.5,
3234 "blank_average": 0.0,
3235 "sloc_min": 16.0,
3236 "sloc_max": 16.0,
3237 "cloc_min": 7.0,
3238 "cloc_max": 7.0,
3239 "ploc_min": 9.0,
3240 "ploc_max": 9.0,
3241 "lloc_min": 8.0,
3242 "lloc_max": 8.0,
3243 "blank_min": 0.0,
3244 "blank_max": 0.0
3245 }"###
3246 );
3247 },
3248 );
3249 }
3250
3251 #[test]
3252 fn javascript_real_loc() {
3253 check_metrics::<JavascriptParser>(
3254 "assert.throws(Test262Error, function() {
3255 for (let { poisoned: x = ++initEvalCount } = poisonedProperty; ; ) {
3256 return;
3257 }
3258 });",
3259 "foo.js",
3260 |metric| {
3261 insta::assert_json_snapshot!(
3263 metric.loc,
3264 @r###"
3265 {
3266 "sloc": 5.0,
3267 "ploc": 5.0,
3268 "lloc": 6.0,
3269 "cloc": 0.0,
3270 "blank": 0.0,
3271 "sloc_average": 2.5,
3272 "ploc_average": 2.5,
3273 "lloc_average": 3.0,
3274 "cloc_average": 0.0,
3275 "blank_average": 0.0,
3276 "sloc_min": 5.0,
3277 "sloc_max": 5.0,
3278 "cloc_min": 0.0,
3279 "cloc_max": 0.0,
3280 "ploc_min": 5.0,
3281 "ploc_max": 5.0,
3282 "lloc_min": 5.0,
3283 "lloc_max": 5.0,
3284 "blank_min": 0.0,
3285 "blank_max": 0.0
3286 }"###
3287 );
3288 },
3289 );
3290 }
3291
3292 #[test]
3293 fn mozjs_real_loc() {
3294 check_metrics::<MozjsParser>(
3295 "assert.throws(Test262Error, function() {
3296 for (let { poisoned: x = ++initEvalCount } = poisonedProperty; ; ) {
3297 return;
3298 }
3299 });",
3300 "foo.js",
3301 |metric| {
3302 insta::assert_json_snapshot!(
3304 metric.loc,
3305 @r###"
3306 {
3307 "sloc": 5.0,
3308 "ploc": 5.0,
3309 "lloc": 6.0,
3310 "cloc": 0.0,
3311 "blank": 0.0,
3312 "sloc_average": 2.5,
3313 "ploc_average": 2.5,
3314 "lloc_average": 3.0,
3315 "cloc_average": 0.0,
3316 "blank_average": 0.0,
3317 "sloc_min": 5.0,
3318 "sloc_max": 5.0,
3319 "cloc_min": 0.0,
3320 "cloc_max": 0.0,
3321 "ploc_min": 5.0,
3322 "ploc_max": 5.0,
3323 "lloc_min": 5.0,
3324 "lloc_max": 5.0,
3325 "blank_min": 0.0,
3326 "blank_max": 0.0
3327 }"###
3328 );
3329 },
3330 );
3331 }
3332
3333 #[test]
3334 fn mozjs_blank_and_comment_loc() {
3335 check_metrics::<MozjsParser>(
3336 "// a comment
3337 function f() {
3338
3339 var x = 1;
3340
3341 }",
3342 "foo.js",
3343 |metric| {
3344 insta::assert_json_snapshot!(
3345 metric.loc,
3346 @r###"
3347 {
3348 "sloc": 6.0,
3349 "ploc": 3.0,
3350 "lloc": 1.0,
3351 "cloc": 1.0,
3352 "blank": 2.0,
3353 "sloc_average": 3.0,
3354 "ploc_average": 1.5,
3355 "lloc_average": 0.5,
3356 "cloc_average": 0.5,
3357 "blank_average": 1.0,
3358 "sloc_min": 5.0,
3359 "sloc_max": 5.0,
3360 "cloc_min": 0.0,
3361 "cloc_max": 0.0,
3362 "ploc_min": 3.0,
3363 "ploc_max": 3.0,
3364 "lloc_min": 1.0,
3365 "lloc_max": 1.0,
3366 "blank_min": 2.0,
3367 "blank_max": 2.0
3368 }"###
3369 );
3370 },
3371 );
3372 }
3373
3374 #[test]
3375 fn cpp_namespace_loc() {
3376 check_metrics::<CppParser>(
3377 "namespace mozilla::dom::quota {} // namespace mozilla::dom::quota",
3378 "foo.cpp",
3379 |metric| {
3380 insta::assert_json_snapshot!(
3382 metric.loc,
3383 @r###"
3384 {
3385 "sloc": 1.0,
3386 "ploc": 1.0,
3387 "lloc": 0.0,
3388 "cloc": 1.0,
3389 "blank": 0.0,
3390 "sloc_average": 0.5,
3391 "ploc_average": 0.5,
3392 "lloc_average": 0.0,
3393 "cloc_average": 0.5,
3394 "blank_average": 0.0,
3395 "sloc_min": 1.0,
3396 "sloc_max": 1.0,
3397 "cloc_min": 0.0,
3398 "cloc_max": 0.0,
3399 "ploc_min": 1.0,
3400 "ploc_max": 1.0,
3401 "lloc_min": 0.0,
3402 "lloc_max": 0.0,
3403 "blank_min": 0.0,
3404 "blank_max": 0.0
3405 }"###
3406 );
3407 },
3408 );
3409 }
3410
3411 #[test]
3412 fn java_comments() {
3413 check_metrics::<JavaParser>(
3414 "for (int i = 0; i < 100; i++) { \
3415 // Print hello
3416 System.out.println(\"hello\"); \
3417 // Print world
3418 System.out.println(\"hello\"); \
3419 }",
3420 "foo.java",
3421 |metric| {
3422 insta::assert_json_snapshot!(
3424 metric.loc,
3425 @r###"
3426 {
3427 "sloc": 3.0,
3428 "ploc": 3.0,
3429 "lloc": 3.0,
3430 "cloc": 2.0,
3431 "blank": 0.0,
3432 "sloc_average": 3.0,
3433 "ploc_average": 3.0,
3434 "lloc_average": 3.0,
3435 "cloc_average": 2.0,
3436 "blank_average": 0.0,
3437 "sloc_min": 3.0,
3438 "sloc_max": 3.0,
3439 "cloc_min": 2.0,
3440 "cloc_max": 2.0,
3441 "ploc_min": 3.0,
3442 "ploc_max": 3.0,
3443 "lloc_min": 3.0,
3444 "lloc_max": 3.0,
3445 "blank_min": 0.0,
3446 "blank_max": 0.0
3447 }"###
3448 );
3449 },
3450 );
3451 }
3452
3453 #[test]
3454 fn java_blank() {
3455 check_metrics::<JavaParser>(
3456 "int x = 1;
3457
3458
3459 int y = 2;",
3460 "foo.java",
3461 |metric| {
3462 insta::assert_json_snapshot!(
3464 metric.loc,
3465 @r###"
3466 {
3467 "sloc": 4.0,
3468 "ploc": 2.0,
3469 "lloc": 2.0,
3470 "cloc": 0.0,
3471 "blank": 2.0,
3472 "sloc_average": 4.0,
3473 "ploc_average": 2.0,
3474 "lloc_average": 2.0,
3475 "cloc_average": 0.0,
3476 "blank_average": 2.0,
3477 "sloc_min": 4.0,
3478 "sloc_max": 4.0,
3479 "cloc_min": 0.0,
3480 "cloc_max": 0.0,
3481 "ploc_min": 2.0,
3482 "ploc_max": 2.0,
3483 "lloc_min": 2.0,
3484 "lloc_max": 2.0,
3485 "blank_min": 2.0,
3486 "blank_max": 2.0
3487 }"###
3488 );
3489 },
3490 );
3491 }
3492
3493 #[test]
3494 fn java_sloc() {
3495 check_metrics::<JavaParser>(
3496 "for (int i = 0; i < 100; i++) {
3497 System.out.println(i);
3498 }",
3499 "foo.java",
3500 |metric| {
3501 insta::assert_json_snapshot!(
3503 metric.loc,
3504 @r###"
3505 {
3506 "sloc": 3.0,
3507 "ploc": 3.0,
3508 "lloc": 2.0,
3509 "cloc": 0.0,
3510 "blank": 0.0,
3511 "sloc_average": 3.0,
3512 "ploc_average": 3.0,
3513 "lloc_average": 2.0,
3514 "cloc_average": 0.0,
3515 "blank_average": 0.0,
3516 "sloc_min": 3.0,
3517 "sloc_max": 3.0,
3518 "cloc_min": 0.0,
3519 "cloc_max": 0.0,
3520 "ploc_min": 3.0,
3521 "ploc_max": 3.0,
3522 "lloc_min": 2.0,
3523 "lloc_max": 2.0,
3524 "blank_min": 0.0,
3525 "blank_max": 0.0
3526 }"###
3527 );
3528 },
3529 );
3530 }
3531
3532 #[test]
3533 fn java_module_sloc() {
3534 check_metrics::<JavaParser>(
3535 "module helloworld{
3536 exports com.test;
3537 }",
3538 "foo.java",
3539 |metric| {
3540 insta::assert_json_snapshot!(
3542 metric.loc,
3543 @r###"
3544 {
3545 "sloc": 3.0,
3546 "ploc": 3.0,
3547 "lloc": 0.0,
3548 "cloc": 0.0,
3549 "blank": 0.0,
3550 "sloc_average": 3.0,
3551 "ploc_average": 3.0,
3552 "lloc_average": 0.0,
3553 "cloc_average": 0.0,
3554 "blank_average": 0.0,
3555 "sloc_min": 3.0,
3556 "sloc_max": 3.0,
3557 "cloc_min": 0.0,
3558 "cloc_max": 0.0,
3559 "ploc_min": 3.0,
3560 "ploc_max": 3.0,
3561 "lloc_min": 0.0,
3562 "lloc_max": 0.0,
3563 "blank_min": 0.0,
3564 "blank_max": 0.0
3565 }"###
3566 );
3567 },
3568 );
3569 }
3570
3571 #[test]
3572 fn java_single_ploc() {
3573 check_metrics::<JavaParser>("int x = 1;", "foo.java", |metric| {
3574 insta::assert_json_snapshot!(
3576 metric.loc,
3577 @r###"
3578 {
3579 "sloc": 1.0,
3580 "ploc": 1.0,
3581 "lloc": 1.0,
3582 "cloc": 0.0,
3583 "blank": 0.0,
3584 "sloc_average": 1.0,
3585 "ploc_average": 1.0,
3586 "lloc_average": 1.0,
3587 "cloc_average": 0.0,
3588 "blank_average": 0.0,
3589 "sloc_min": 1.0,
3590 "sloc_max": 1.0,
3591 "cloc_min": 0.0,
3592 "cloc_max": 0.0,
3593 "ploc_min": 1.0,
3594 "ploc_max": 1.0,
3595 "lloc_min": 1.0,
3596 "lloc_max": 1.0,
3597 "blank_min": 0.0,
3598 "blank_max": 0.0
3599 }"###
3600 );
3601 });
3602 }
3603
3604 #[test]
3605 fn java_simple_ploc() {
3606 check_metrics::<JavaParser>(
3607 "for (int i = 0; i < 100; i = i++) {
3608 System.out.println(i);
3609 }",
3610 "foo.java",
3611 |metric| {
3612 insta::assert_json_snapshot!(
3614 metric.loc,
3615 @r###"
3616 {
3617 "sloc": 3.0,
3618 "ploc": 3.0,
3619 "lloc": 2.0,
3620 "cloc": 0.0,
3621 "blank": 0.0,
3622 "sloc_average": 3.0,
3623 "ploc_average": 3.0,
3624 "lloc_average": 2.0,
3625 "cloc_average": 0.0,
3626 "blank_average": 0.0,
3627 "sloc_min": 3.0,
3628 "sloc_max": 3.0,
3629 "cloc_min": 0.0,
3630 "cloc_max": 0.0,
3631 "ploc_min": 3.0,
3632 "ploc_max": 3.0,
3633 "lloc_min": 2.0,
3634 "lloc_max": 2.0,
3635 "blank_min": 0.0,
3636 "blank_max": 0.0
3637 }"###
3638 );
3639 },
3640 );
3641 }
3642
3643 #[test]
3644 fn java_multi_ploc() {
3645 check_metrics::<JavaParser>(
3646 "int x = 1;
3647 for (int i = 0; i < 100; i++) {
3648 System.out.println(i);
3649 }",
3650 "foo.java",
3651 |metric| {
3652 insta::assert_json_snapshot!(
3654 metric.loc,
3655 @r###"
3656 {
3657 "sloc": 4.0,
3658 "ploc": 4.0,
3659 "lloc": 3.0,
3660 "cloc": 0.0,
3661 "blank": 0.0,
3662 "sloc_average": 4.0,
3663 "ploc_average": 4.0,
3664 "lloc_average": 3.0,
3665 "cloc_average": 0.0,
3666 "blank_average": 0.0,
3667 "sloc_min": 4.0,
3668 "sloc_max": 4.0,
3669 "cloc_min": 0.0,
3670 "cloc_max": 0.0,
3671 "ploc_min": 4.0,
3672 "ploc_max": 4.0,
3673 "lloc_min": 3.0,
3674 "lloc_max": 3.0,
3675 "blank_min": 0.0,
3676 "blank_max": 0.0
3677 }"###
3678 );
3679 },
3680 );
3681 }
3682
3683 #[test]
3684 fn java_single_statement_lloc() {
3685 check_metrics::<JavaParser>("int max = 10;", "foo.java", |metric| {
3686 insta::assert_json_snapshot!(
3688 metric.loc,
3689 @r###"
3690 {
3691 "sloc": 1.0,
3692 "ploc": 1.0,
3693 "lloc": 1.0,
3694 "cloc": 0.0,
3695 "blank": 0.0,
3696 "sloc_average": 1.0,
3697 "ploc_average": 1.0,
3698 "lloc_average": 1.0,
3699 "cloc_average": 0.0,
3700 "blank_average": 0.0,
3701 "sloc_min": 1.0,
3702 "sloc_max": 1.0,
3703 "cloc_min": 0.0,
3704 "cloc_max": 0.0,
3705 "ploc_min": 1.0,
3706 "ploc_max": 1.0,
3707 "lloc_min": 1.0,
3708 "lloc_max": 1.0,
3709 "blank_min": 0.0,
3710 "blank_max": 0.0
3711 }"###
3712 );
3713 });
3714 }
3715
3716 #[test]
3717 fn java_for_lloc() {
3718 check_metrics::<JavaParser>(
3719 "for (int i = 0; i < 100; i++) { // + 1
3720 System.out.println(i); // + 1
3721 }",
3722 "foo.java",
3723 |metric| {
3724 insta::assert_json_snapshot!(
3726 metric.loc,
3727 @r###"
3728 {
3729 "sloc": 3.0,
3730 "ploc": 3.0,
3731 "lloc": 2.0,
3732 "cloc": 2.0,
3733 "blank": 0.0,
3734 "sloc_average": 3.0,
3735 "ploc_average": 3.0,
3736 "lloc_average": 2.0,
3737 "cloc_average": 2.0,
3738 "blank_average": 0.0,
3739 "sloc_min": 3.0,
3740 "sloc_max": 3.0,
3741 "cloc_min": 2.0,
3742 "cloc_max": 2.0,
3743 "ploc_min": 3.0,
3744 "ploc_max": 3.0,
3745 "lloc_min": 2.0,
3746 "lloc_max": 2.0,
3747 "blank_min": 0.0,
3748 "blank_max": 0.0
3749 }"###
3750 );
3751 },
3752 );
3753 }
3754
3755 #[test]
3756 fn java_foreach_lloc() {
3757 check_metrics::<JavaParser>(
3758 "
3759 int arr[]={12,13,14,44}; // +1
3760 for (int i:arr) { // +1
3761 System.out.println(i); // +1
3762 }",
3763 "foo.java",
3764 |metric| {
3765 insta::assert_json_snapshot!(
3767 metric.loc,
3768 @r###"
3769 {
3770 "sloc": 4.0,
3771 "ploc": 4.0,
3772 "lloc": 3.0,
3773 "cloc": 3.0,
3774 "blank": 0.0,
3775 "sloc_average": 4.0,
3776 "ploc_average": 4.0,
3777 "lloc_average": 3.0,
3778 "cloc_average": 3.0,
3779 "blank_average": 0.0,
3780 "sloc_min": 4.0,
3781 "sloc_max": 4.0,
3782 "cloc_min": 3.0,
3783 "cloc_max": 3.0,
3784 "ploc_min": 4.0,
3785 "ploc_max": 4.0,
3786 "lloc_min": 3.0,
3787 "lloc_max": 3.0,
3788 "blank_min": 0.0,
3789 "blank_max": 0.0
3790 }"###
3791 );
3792 },
3793 );
3794 }
3795
3796 #[test]
3797 fn java_while_lloc() {
3798 check_metrics::<JavaParser>(
3799 "
3800 int i=0; // +1
3801 while(i < 10) { // +1
3802 i++; // +1
3803 System.out.println(i); // +1
3804 }",
3805 "foo.java",
3806 |metric| {
3807 insta::assert_json_snapshot!(
3809 metric.loc,
3810 @r###"
3811 {
3812 "sloc": 5.0,
3813 "ploc": 5.0,
3814 "lloc": 4.0,
3815 "cloc": 4.0,
3816 "blank": 0.0,
3817 "sloc_average": 5.0,
3818 "ploc_average": 5.0,
3819 "lloc_average": 4.0,
3820 "cloc_average": 4.0,
3821 "blank_average": 0.0,
3822 "sloc_min": 5.0,
3823 "sloc_max": 5.0,
3824 "cloc_min": 4.0,
3825 "cloc_max": 4.0,
3826 "ploc_min": 5.0,
3827 "ploc_max": 5.0,
3828 "lloc_min": 4.0,
3829 "lloc_max": 4.0,
3830 "blank_min": 0.0,
3831 "blank_max": 0.0
3832 }"###
3833 );
3834 },
3835 );
3836 }
3837
3838 #[test]
3839 fn java_do_while_lloc() {
3840 check_metrics::<JavaParser>(
3841 "
3842 int i=0; // +1
3843 do { // +1
3844 i++; // +1
3845 System.out.println(i); // +1
3846 } while(i < 10)",
3847 "foo.java",
3848 |metric| {
3849 insta::assert_json_snapshot!(
3851 metric.loc,
3852 @r###"
3853 {
3854 "sloc": 5.0,
3855 "ploc": 5.0,
3856 "lloc": 4.0,
3857 "cloc": 4.0,
3858 "blank": 0.0,
3859 "sloc_average": 5.0,
3860 "ploc_average": 5.0,
3861 "lloc_average": 4.0,
3862 "cloc_average": 4.0,
3863 "blank_average": 0.0,
3864 "sloc_min": 5.0,
3865 "sloc_max": 5.0,
3866 "cloc_min": 4.0,
3867 "cloc_max": 4.0,
3868 "ploc_min": 5.0,
3869 "ploc_max": 5.0,
3870 "lloc_min": 4.0,
3871 "lloc_max": 4.0,
3872 "blank_min": 0.0,
3873 "blank_max": 0.0
3874 }"###
3875 );
3876 },
3877 );
3878 }
3879
3880 #[test]
3881 fn java_switch_lloc() {
3882 check_metrics::<JavaParser>(
3883 "switch(grade) { // +1
3884 case 'A' :
3885 System.out.println(\"Pass with distinction\"); // +1
3886 break; // +1
3887 case 'B' :
3888 case 'C' :
3889 System.out.println(\"Pass\"); // +1
3890 break; // +1
3891 case 'D' :
3892 System.out.println(\"At risk\"); // +1
3893 case 'F' :
3894 System.out.println(\"Fail\"); // +1
3895 break; // +1
3896 default :
3897 System.out.println(\"Invalid grade\"); // +1
3898 }",
3899 "foo.java",
3900 |metric| {
3901 insta::assert_json_snapshot!(
3903 metric.loc,
3904 @r###"
3905 {
3906 "sloc": 16.0,
3907 "ploc": 16.0,
3908 "lloc": 9.0,
3909 "cloc": 9.0,
3910 "blank": 0.0,
3911 "sloc_average": 16.0,
3912 "ploc_average": 16.0,
3913 "lloc_average": 9.0,
3914 "cloc_average": 9.0,
3915 "blank_average": 0.0,
3916 "sloc_min": 16.0,
3917 "sloc_max": 16.0,
3918 "cloc_min": 9.0,
3919 "cloc_max": 9.0,
3920 "ploc_min": 16.0,
3921 "ploc_max": 16.0,
3922 "lloc_min": 9.0,
3923 "lloc_max": 9.0,
3924 "blank_min": 0.0,
3925 "blank_max": 0.0
3926 }"###
3927 );
3928 },
3929 );
3930 }
3931
3932 #[test]
3933 fn java_continue_lloc() {
3934 check_metrics::<JavaParser>(
3935 "int max = 10; // +1
3936
3937 for (int i = 0; i < max; i++) { // +1
3938 if(i % 2 == 0) { continue;} + 2
3939 System.out.println(i); // +1
3940 }",
3941 "foo.java",
3942 |metric| {
3943 insta::assert_json_snapshot!(
3945 metric.loc,
3946 @r###"
3947 {
3948 "sloc": 6.0,
3949 "ploc": 5.0,
3950 "lloc": 5.0,
3951 "cloc": 3.0,
3952 "blank": 1.0,
3953 "sloc_average": 6.0,
3954 "ploc_average": 5.0,
3955 "lloc_average": 5.0,
3956 "cloc_average": 3.0,
3957 "blank_average": 1.0,
3958 "sloc_min": 6.0,
3959 "sloc_max": 6.0,
3960 "cloc_min": 3.0,
3961 "cloc_max": 3.0,
3962 "ploc_min": 5.0,
3963 "ploc_max": 5.0,
3964 "lloc_min": 5.0,
3965 "lloc_max": 5.0,
3966 "blank_min": 1.0,
3967 "blank_max": 1.0
3968 }"###
3969 );
3970 },
3971 );
3972 }
3973
3974 #[test]
3975 fn java_try_lloc() {
3976 check_metrics::<JavaParser>(
3977 "try { // +1
3978 int[] myNumbers = {1, 2, 3}; // +1
3979 System.out.println(myNumbers[10]); // +1
3980 } catch (Exception e) {
3981 System.out.println(e.getMessage()); // +1
3982 throw e; // +1
3983 }",
3984 "foo.java",
3985 |metric| {
3986 insta::assert_json_snapshot!(
3988 metric.loc,
3989 @r###"
3990 {
3991 "sloc": 7.0,
3992 "ploc": 7.0,
3993 "lloc": 5.0,
3994 "cloc": 5.0,
3995 "blank": 0.0,
3996 "sloc_average": 7.0,
3997 "ploc_average": 7.0,
3998 "lloc_average": 5.0,
3999 "cloc_average": 5.0,
4000 "blank_average": 0.0,
4001 "sloc_min": 7.0,
4002 "sloc_max": 7.0,
4003 "cloc_min": 5.0,
4004 "cloc_max": 5.0,
4005 "ploc_min": 7.0,
4006 "ploc_max": 7.0,
4007 "lloc_min": 5.0,
4008 "lloc_max": 5.0,
4009 "blank_min": 0.0,
4010 "blank_max": 0.0
4011 }"###
4012 );
4013 },
4014 );
4015 }
4016
4017 #[test]
4018 fn java_class_loc() {
4019 check_metrics::<JavaParser>(
4020 "
4021 public class Person {
4022 private String name;
4023 public Person(String name){
4024 this.name = name; // +1
4025 }
4026 public String getName() {
4027 return name; // +1
4028 }
4029 }",
4030 "foo.java",
4031 |metric| {
4032 insta::assert_json_snapshot!(
4034 metric.loc,
4035 @r###"
4036 {
4037 "sloc": 9.0,
4038 "ploc": 9.0,
4039 "lloc": 2.0,
4040 "cloc": 2.0,
4041 "blank": 0.0,
4042 "sloc_average": 2.25,
4043 "ploc_average": 2.25,
4044 "lloc_average": 0.5,
4045 "cloc_average": 0.5,
4046 "blank_average": 0.0,
4047 "sloc_min": 9.0,
4048 "sloc_max": 9.0,
4049 "cloc_min": 2.0,
4050 "cloc_max": 2.0,
4051 "ploc_min": 9.0,
4052 "ploc_max": 9.0,
4053 "lloc_min": 2.0,
4054 "lloc_max": 2.0,
4055 "blank_min": 0.0,
4056 "blank_max": 0.0
4057 }"###
4058 );
4059 },
4060 );
4061 }
4062
4063 #[test]
4064 fn java_expressions_lloc() {
4065 check_metrics::<JavaParser>(
4066 "int x = 10; // +1 local var declaration
4067 x=+89; // +1 expression statement
4068 int y = x * 2; // +1 local var declaration
4069 IntFunction double = (n) -> n*2; // +1 local var declaration
4070 int y2 = double(x); // +1 local var declaration
4071 System.out.println(\"double \" + x + \" = \" + y2); // +1 expression statement
4072 String message = (x % 2) == 0 ? \"Evenly done.\" : \"Oddly done.\"; // +1 local var declaration
4073 Object done = (Runnable) () -> { System.out.println(\"Done!\"); }; // +2 local var declaration + expression statement
4074 String s = \"string\"; // +1 local var declaration
4075 boolean isS = (s instanceof String); // +1 local var declaration
4076 done.run(); // +1 expression statement
4077 ",
4078 "foo.java",
4079 |metric| {
4080 insta::assert_json_snapshot!(
4082 metric.loc,
4083 @r###"
4084 {
4085 "sloc": 11.0,
4086 "ploc": 11.0,
4087 "lloc": 12.0,
4088 "cloc": 11.0,
4089 "blank": 0.0,
4090 "sloc_average": 11.0,
4091 "ploc_average": 11.0,
4092 "lloc_average": 12.0,
4093 "cloc_average": 11.0,
4094 "blank_average": 0.0,
4095 "sloc_min": 11.0,
4096 "sloc_max": 11.0,
4097 "cloc_min": 11.0,
4098 "cloc_max": 11.0,
4099 "ploc_min": 11.0,
4100 "ploc_max": 11.0,
4101 "lloc_min": 12.0,
4102 "lloc_max": 12.0,
4103 "blank_min": 0.0,
4104 "blank_max": 0.0
4105 }"###
4106 );
4107 },
4108 );
4109 }
4110
4111 #[test]
4112 fn java_statement_inline_loc() {
4113 check_metrics::<JavaParser>(
4114 "for (int i = 0; i < 100; i++) { System.out.println(\"hello\"); }",
4115 "foo.java",
4116 |metric| {
4117 insta::assert_json_snapshot!(
4119 metric.loc,
4120 @r###"
4121 {
4122 "sloc": 1.0,
4123 "ploc": 1.0,
4124 "lloc": 2.0,
4125 "cloc": 0.0,
4126 "blank": 0.0,
4127 "sloc_average": 1.0,
4128 "ploc_average": 1.0,
4129 "lloc_average": 2.0,
4130 "cloc_average": 0.0,
4131 "blank_average": 0.0,
4132 "sloc_min": 1.0,
4133 "sloc_max": 1.0,
4134 "cloc_min": 0.0,
4135 "cloc_max": 0.0,
4136 "ploc_min": 1.0,
4137 "ploc_max": 1.0,
4138 "lloc_min": 2.0,
4139 "lloc_max": 2.0,
4140 "blank_min": 0.0,
4141 "blank_max": 0.0
4142 }"###
4143 );
4144 },
4145 );
4146 }
4147
4148 #[test]
4149 fn java_general_loc() {
4150 check_metrics::<JavaParser>(
4151 "int max = 100;
4152
4153 /*
4154 Loop through and print
4155 from: 0
4156 to: max
4157 */
4158 for (int i = 0; i < max; i++) {
4159 // Print the value
4160 System.out.println(i);
4161 }",
4162 "foo.java",
4163 |metric| {
4164 insta::assert_json_snapshot!(
4166 metric.loc,
4167 @r###"
4168 {
4169 "sloc": 11.0,
4170 "ploc": 4.0,
4171 "lloc": 3.0,
4172 "cloc": 6.0,
4173 "blank": 1.0,
4174 "sloc_average": 11.0,
4175 "ploc_average": 4.0,
4176 "lloc_average": 3.0,
4177 "cloc_average": 6.0,
4178 "blank_average": 1.0,
4179 "sloc_min": 11.0,
4180 "sloc_max": 11.0,
4181 "cloc_min": 6.0,
4182 "cloc_max": 6.0,
4183 "ploc_min": 4.0,
4184 "ploc_max": 4.0,
4185 "lloc_min": 3.0,
4186 "lloc_max": 3.0,
4187 "blank_min": 1.0,
4188 "blank_max": 1.0
4189 }"###
4190 );
4191 },
4192 );
4193 }
4194
4195 #[test]
4196 fn java_main_class_loc() {
4197 check_metrics::<JavaParser>(
4198 "package com.company;
4199 /**
4200 * The HelloWorldApp class implements an application that
4201 * simply prints \"Hello World!\" to standard output.
4202 */
4203
4204 class HelloWorldApp {
4205 public void main(String[] args) {
4206 String message = args.length == 0 ? \"Hello empty world\" : \"Hello world\"; // +1 lloc : 1 var assignment
4207 System.out.println(message); // Display the string. +1 lloc
4208 }
4209 }",
4210 "foo.java",
4211 |metric| {
4212 insta::assert_json_snapshot!(
4214 metric.loc,
4215 @r###"
4216 {
4217 "sloc": 12.0,
4218 "ploc": 7.0,
4219 "lloc": 2.0,
4220 "cloc": 6.0,
4221 "blank": 1.0,
4222 "sloc_average": 4.0,
4223 "ploc_average": 2.3333333333333335,
4224 "lloc_average": 0.6666666666666666,
4225 "cloc_average": 2.0,
4226 "blank_average": 0.3333333333333333,
4227 "sloc_min": 6.0,
4228 "sloc_max": 6.0,
4229 "cloc_min": 2.0,
4230 "cloc_max": 2.0,
4231 "ploc_min": 6.0,
4232 "ploc_max": 6.0,
4233 "lloc_min": 2.0,
4234 "lloc_max": 2.0,
4235 "blank_min": 0.0,
4236 "blank_max": 0.0
4237 }"###
4238 );
4239 },
4240 );
4241 }
4242
4243 #[test]
4244 fn go_general_loc() {
4245 check_metrics::<GoParser>(
4246 "package main
4247
4248 // entrypoint
4249 func main() {
4250 /* loop body */
4251 for i := 0; i < 10; i++ {
4252 fmt.Println(i)
4253 }
4254 }",
4255 "foo.go",
4256 |metric| {
4257 insta::assert_json_snapshot!(
4262 metric.loc,
4263 @r###"
4264 {
4265 "sloc": 9.0,
4266 "ploc": 6.0,
4267 "lloc": 2.0,
4268 "cloc": 2.0,
4269 "blank": 1.0,
4270 "sloc_average": 4.5,
4271 "ploc_average": 3.0,
4272 "lloc_average": 1.0,
4273 "cloc_average": 1.0,
4274 "blank_average": 0.5,
4275 "sloc_min": 6.0,
4276 "sloc_max": 6.0,
4277 "cloc_min": 1.0,
4278 "cloc_max": 1.0,
4279 "ploc_min": 5.0,
4280 "ploc_max": 5.0,
4281 "lloc_min": 2.0,
4282 "lloc_max": 2.0,
4283 "blank_min": 0.0,
4284 "blank_max": 0.0
4285 }"###
4286 );
4287 },
4288 );
4289 }
4290
4291 #[test]
4292 fn go_for_clause_does_not_double_count_lloc() {
4293 check_metrics::<GoParser>(
4297 "package main
4298 func f(n int) int {
4299 for i := 0; i < n; i++ {
4300 return i
4301 }
4302 return 0
4303 }",
4304 "foo.go",
4305 |metric| {
4306 assert_eq!(metric.loc.lloc(), 3.0);
4309 },
4310 );
4311 }
4312
4313 #[test]
4314 fn go_blank() {
4315 check_metrics::<GoParser>(
4316 "package main
4317
4318 func foo() {
4319 x := 1
4320
4321 y := 2
4322 }",
4323 "foo.go",
4324 |metric| {
4325 insta::assert_json_snapshot!(
4328 metric.loc,
4329 @r#"
4330 {
4331 "sloc": 7.0,
4332 "ploc": 5.0,
4333 "lloc": 2.0,
4334 "cloc": 0.0,
4335 "blank": 2.0,
4336 "sloc_average": 3.5,
4337 "ploc_average": 2.5,
4338 "lloc_average": 1.0,
4339 "cloc_average": 0.0,
4340 "blank_average": 1.0,
4341 "sloc_min": 5.0,
4342 "sloc_max": 5.0,
4343 "cloc_min": 0.0,
4344 "cloc_max": 0.0,
4345 "ploc_min": 4.0,
4346 "ploc_max": 4.0,
4347 "lloc_min": 2.0,
4348 "lloc_max": 2.0,
4349 "blank_min": 1.0,
4350 "blank_max": 1.0
4351 }
4352 "#
4353 );
4354 },
4355 );
4356 }
4357
4358 #[test]
4359 fn go_cloc_line_comments() {
4360 check_metrics::<GoParser>(
4361 "package main
4362
4363 // helper adds two numbers.
4364 // It returns their sum.
4365 func add(a, b int) int {
4366 // compute the result
4367 return a + b
4368 }",
4369 "foo.go",
4370 |metric| {
4371 insta::assert_json_snapshot!(
4374 metric.loc,
4375 @r#"
4376 {
4377 "sloc": 8.0,
4378 "ploc": 4.0,
4379 "lloc": 1.0,
4380 "cloc": 3.0,
4381 "blank": 1.0,
4382 "sloc_average": 4.0,
4383 "ploc_average": 2.0,
4384 "lloc_average": 0.5,
4385 "cloc_average": 1.5,
4386 "blank_average": 0.5,
4387 "sloc_min": 4.0,
4388 "sloc_max": 4.0,
4389 "cloc_min": 1.0,
4390 "cloc_max": 1.0,
4391 "ploc_min": 3.0,
4392 "ploc_max": 3.0,
4393 "lloc_min": 1.0,
4394 "lloc_max": 1.0,
4395 "blank_min": 0.0,
4396 "blank_max": 0.0
4397 }
4398 "#
4399 );
4400 },
4401 );
4402 }
4403
4404 #[test]
4405 fn go_cloc_block_comments() {
4406 check_metrics::<GoParser>(
4407 "package main
4408
4409 /* block comment
4410 spanning two lines */
4411 func foo() {
4412 x := 1 /* inline block */
4413 }",
4414 "foo.go",
4415 |metric| {
4416 insta::assert_json_snapshot!(
4419 metric.loc,
4420 @r#"
4421 {
4422 "sloc": 7.0,
4423 "ploc": 4.0,
4424 "lloc": 1.0,
4425 "cloc": 3.0,
4426 "blank": 1.0,
4427 "sloc_average": 3.5,
4428 "ploc_average": 2.0,
4429 "lloc_average": 0.5,
4430 "cloc_average": 1.5,
4431 "blank_average": 0.5,
4432 "sloc_min": 3.0,
4433 "sloc_max": 3.0,
4434 "cloc_min": 1.0,
4435 "cloc_max": 1.0,
4436 "ploc_min": 3.0,
4437 "ploc_max": 3.0,
4438 "lloc_min": 1.0,
4439 "lloc_max": 1.0,
4440 "blank_min": 0.0,
4441 "blank_max": 0.0
4442 }
4443 "#
4444 );
4445 },
4446 );
4447 }
4448
4449 #[test]
4450 fn go_lloc_if_for_switch() {
4451 check_metrics::<GoParser>(
4452 "package main
4453
4454 func foo(n int) int {
4455 if n > 0 {
4456 for i := 0; i < n; i++ {
4457 switch i {
4458 }
4459 }
4460 }
4461 return n
4462 }",
4463 "foo.go",
4464 |metric| {
4465 insta::assert_json_snapshot!(
4468 metric.loc,
4469 @r#"
4470 {
4471 "sloc": 11.0,
4472 "ploc": 10.0,
4473 "lloc": 4.0,
4474 "cloc": 0.0,
4475 "blank": 1.0,
4476 "sloc_average": 5.5,
4477 "ploc_average": 5.0,
4478 "lloc_average": 2.0,
4479 "cloc_average": 0.0,
4480 "blank_average": 0.5,
4481 "sloc_min": 9.0,
4482 "sloc_max": 9.0,
4483 "cloc_min": 0.0,
4484 "cloc_max": 0.0,
4485 "ploc_min": 9.0,
4486 "ploc_max": 9.0,
4487 "lloc_min": 4.0,
4488 "lloc_max": 4.0,
4489 "blank_min": 0.0,
4490 "blank_max": 0.0
4491 }
4492 "#
4493 );
4494 },
4495 );
4496 }
4497
4498 #[test]
4499 fn go_lloc_go_defer() {
4500 check_metrics::<GoParser>(
4501 "package main
4502
4503 func foo() {
4504 go run()
4505 defer cleanup()
4506 }",
4507 "foo.go",
4508 |metric| {
4509 insta::assert_json_snapshot!(
4512 metric.loc,
4513 @r#"
4514 {
4515 "sloc": 6.0,
4516 "ploc": 5.0,
4517 "lloc": 2.0,
4518 "cloc": 0.0,
4519 "blank": 1.0,
4520 "sloc_average": 3.0,
4521 "ploc_average": 2.5,
4522 "lloc_average": 1.0,
4523 "cloc_average": 0.0,
4524 "blank_average": 0.5,
4525 "sloc_min": 4.0,
4526 "sloc_max": 4.0,
4527 "cloc_min": 0.0,
4528 "cloc_max": 0.0,
4529 "ploc_min": 4.0,
4530 "ploc_max": 4.0,
4531 "lloc_min": 2.0,
4532 "lloc_max": 2.0,
4533 "blank_min": 0.0,
4534 "blank_max": 0.0
4535 }
4536 "#
4537 );
4538 },
4539 );
4540 }
4541
4542 #[test]
4543 fn go_lloc_var_const_declarations() {
4544 check_metrics::<GoParser>(
4545 "package main
4546
4547 func foo() {
4548 var x int
4549 var y = 10
4550 const z = 42
4551 a := 3
4552 a = 4
4553 }",
4554 "foo.go",
4555 |metric| {
4556 insta::assert_json_snapshot!(
4560 metric.loc,
4561 @r#"
4562 {
4563 "sloc": 9.0,
4564 "ploc": 8.0,
4565 "lloc": 5.0,
4566 "cloc": 0.0,
4567 "blank": 1.0,
4568 "sloc_average": 4.5,
4569 "ploc_average": 4.0,
4570 "lloc_average": 2.5,
4571 "cloc_average": 0.0,
4572 "blank_average": 0.5,
4573 "sloc_min": 7.0,
4574 "sloc_max": 7.0,
4575 "cloc_min": 0.0,
4576 "cloc_max": 0.0,
4577 "ploc_min": 7.0,
4578 "ploc_max": 7.0,
4579 "lloc_min": 5.0,
4580 "lloc_max": 5.0,
4581 "blank_min": 0.0,
4582 "blank_max": 0.0
4583 }
4584 "#
4585 );
4586 },
4587 );
4588 }
4589
4590 #[test]
4591 fn go_lloc_select() {
4592 check_metrics::<GoParser>(
4593 "package main
4594
4595 func foo(ch chan int) {
4596 select {
4597 case v := <-ch:
4598 _ = v
4599 }
4600 }",
4601 "foo.go",
4602 |metric| {
4603 insta::assert_json_snapshot!(
4608 metric.loc,
4609 @r#"
4610 {
4611 "sloc": 8.0,
4612 "ploc": 7.0,
4613 "lloc": 2.0,
4614 "cloc": 0.0,
4615 "blank": 1.0,
4616 "sloc_average": 4.0,
4617 "ploc_average": 3.5,
4618 "lloc_average": 1.0,
4619 "cloc_average": 0.0,
4620 "blank_average": 0.5,
4621 "sloc_min": 6.0,
4622 "sloc_max": 6.0,
4623 "cloc_min": 0.0,
4624 "cloc_max": 0.0,
4625 "ploc_min": 6.0,
4626 "ploc_max": 6.0,
4627 "lloc_min": 2.0,
4628 "lloc_max": 2.0,
4629 "blank_min": 0.0,
4630 "blank_max": 0.0
4631 }
4632 "#
4633 );
4634 },
4635 );
4636 }
4637
4638 #[test]
4639 fn go_sloc_multiline_function() {
4640 check_metrics::<GoParser>(
4641 "package main
4642
4643 func add(
4644 a int,
4645 b int,
4646 ) int {
4647 return a + b
4648 }",
4649 "foo.go",
4650 |metric| {
4651 insta::assert_json_snapshot!(
4654 metric.loc,
4655 @r#"
4656 {
4657 "sloc": 8.0,
4658 "ploc": 7.0,
4659 "lloc": 1.0,
4660 "cloc": 0.0,
4661 "blank": 1.0,
4662 "sloc_average": 4.0,
4663 "ploc_average": 3.5,
4664 "lloc_average": 0.5,
4665 "cloc_average": 0.0,
4666 "blank_average": 0.5,
4667 "sloc_min": 6.0,
4668 "sloc_max": 6.0,
4669 "cloc_min": 0.0,
4670 "cloc_max": 0.0,
4671 "ploc_min": 6.0,
4672 "ploc_max": 6.0,
4673 "lloc_min": 1.0,
4674 "lloc_max": 1.0,
4675 "blank_min": 0.0,
4676 "blank_max": 0.0
4677 }
4678 "#
4679 );
4680 },
4681 );
4682 }
4683
4684 #[test]
4685 fn go_code_comment_same_line() {
4686 check_metrics::<GoParser>(
4687 "package main
4688
4689 func foo() {
4690 x := 1 // initialize x
4691 y := 2 // initialize y
4692 }",
4693 "foo.go",
4694 |metric| {
4695 insta::assert_json_snapshot!(
4700 metric.loc,
4701 @r#"
4702 {
4703 "sloc": 6.0,
4704 "ploc": 5.0,
4705 "lloc": 2.0,
4706 "cloc": 2.0,
4707 "blank": 1.0,
4708 "sloc_average": 3.0,
4709 "ploc_average": 2.5,
4710 "lloc_average": 1.0,
4711 "cloc_average": 1.0,
4712 "blank_average": 0.5,
4713 "sloc_min": 4.0,
4714 "sloc_max": 4.0,
4715 "cloc_min": 2.0,
4716 "cloc_max": 2.0,
4717 "ploc_min": 4.0,
4718 "ploc_max": 4.0,
4719 "lloc_min": 2.0,
4720 "lloc_max": 2.0,
4721 "blank_min": 0.0,
4722 "blank_max": 0.0
4723 }
4724 "#
4725 );
4726 },
4727 );
4728 }
4729
4730 #[test]
4731 fn perl_grammar_smoke() {
4732 assert_perl_parses_cleanly(
4738 "use strict;
4739use warnings;
4740
4741# line comment
4742
4743=pod
4744multi-line POD
4745=cut
4746
4747sub factorial {
4748 my ($n) = @_;
4749 return 1 if $n <= 1;
4750 return $n * factorial($n - 1);
4751}
4752
4753my @arr = (1, 2, 3);
4754my %hash = (a => 1, b => 2);
4755my $closure = sub { return $_[0] + 1; };
4756
4757for my $i (1..3) {
4758 if ($i % 2 == 0) {
4759 print \"even\\n\";
4760 } elsif ($i == 1) {
4761 print \"one\\n\";
4762 } else {
4763 print \"odd\\n\";
4764 }
4765}
4766
4767while ($x > 0) {
4768 last if $x == 0;
4769 $x--;
4770}
4771
4772unless ($done) {
4773 next;
4774}
4775
4776my $heredoc = <<END;
4777hello
4778END
4779",
4780 );
4781 }
4782
4783 #[test]
4784 fn perl_blank() {
4785 check_metrics::<PerlParser>(
4786 "
4787
4788my $a = 42;
4789
4790my $b = 43;
4791
4792",
4793 "foo.pl",
4794 |metric| {
4795 insta::assert_json_snapshot!(metric.loc, @r#"
4796 {
4797 "sloc": 3.0,
4798 "ploc": 2.0,
4799 "lloc": 2.0,
4800 "cloc": 0.0,
4801 "blank": 1.0,
4802 "sloc_average": 3.0,
4803 "ploc_average": 2.0,
4804 "lloc_average": 2.0,
4805 "cloc_average": 0.0,
4806 "blank_average": 1.0,
4807 "sloc_min": 3.0,
4808 "sloc_max": 3.0,
4809 "cloc_min": 0.0,
4810 "cloc_max": 0.0,
4811 "ploc_min": 2.0,
4812 "ploc_max": 2.0,
4813 "lloc_min": 2.0,
4814 "lloc_max": 2.0,
4815 "blank_min": 1.0,
4816 "blank_max": 1.0
4817 }
4818 "#);
4819 },
4820 );
4821 }
4822
4823 #[test]
4824 fn perl_no_zero_blank() {
4825 check_metrics::<PerlParser>(
4828 "my $a = 1;
4829my $b = 2;
4830
4831my $c = 3; # trailing
4832my $d = 4; # trailing
4833my $e = 5;",
4834 "foo.pl",
4835 |metric| {
4836 assert_eq!(metric.loc.sloc(), 6.0);
4837 assert_eq!(metric.loc.ploc(), 5.0);
4838 assert_eq!(metric.loc.cloc(), 2.0);
4839 assert_eq!(metric.loc.blank(), 1.0);
4840 insta::assert_json_snapshot!(metric.loc);
4841 },
4842 );
4843 }
4844
4845 #[test]
4846 fn perl_blank_zero_sanity() {
4847 check_metrics::<PerlParser>(
4850 "my $a = 1;
4851my $b = 2;",
4852 "foo.pl",
4853 |metric| {
4854 assert_eq!(metric.loc.sloc(), 2.0);
4855 assert_eq!(metric.loc.ploc(), 2.0);
4856 assert_eq!(metric.loc.lloc(), 2.0);
4857 assert_eq!(metric.loc.cloc(), 0.0);
4858 assert_eq!(metric.loc.blank(), 0.0);
4859 },
4860 );
4861 }
4862
4863 #[test]
4864 fn perl_cloc_line_comments() {
4865 check_metrics::<PerlParser>(
4866 "# top comment
4867my $a = 1; # trailing
4868my $b = 2;",
4869 "foo.pl",
4870 |metric| {
4871 insta::assert_json_snapshot!(metric.loc, @r#"
4872 {
4873 "sloc": 3.0,
4874 "ploc": 3.0,
4875 "lloc": 2.0,
4876 "cloc": 2.0,
4877 "blank": 0.0,
4878 "sloc_average": 3.0,
4879 "ploc_average": 3.0,
4880 "lloc_average": 2.0,
4881 "cloc_average": 2.0,
4882 "blank_average": 0.0,
4883 "sloc_min": 3.0,
4884 "sloc_max": 3.0,
4885 "cloc_min": 2.0,
4886 "cloc_max": 2.0,
4887 "ploc_min": 3.0,
4888 "ploc_max": 3.0,
4889 "lloc_min": 2.0,
4890 "lloc_max": 2.0,
4891 "blank_min": 0.0,
4892 "blank_max": 0.0
4893 }
4894 "#);
4895 },
4896 );
4897 }
4898
4899 #[test]
4900 fn perl_cloc_pod_block() {
4901 check_metrics::<PerlParser>(
4902 "my $x = 1;
4903=pod
4904multi-line
4905pod block
4906=cut
4907my $y = 2;",
4908 "foo.pl",
4909 |metric| {
4910 insta::assert_json_snapshot!(metric.loc, @r#"
4911 {
4912 "sloc": 6.0,
4913 "ploc": 2.0,
4914 "lloc": 2.0,
4915 "cloc": 4.0,
4916 "blank": 0.0,
4917 "sloc_average": 6.0,
4918 "ploc_average": 2.0,
4919 "lloc_average": 2.0,
4920 "cloc_average": 4.0,
4921 "blank_average": 0.0,
4922 "sloc_min": 6.0,
4923 "sloc_max": 6.0,
4924 "cloc_min": 4.0,
4925 "cloc_max": 4.0,
4926 "ploc_min": 2.0,
4927 "ploc_max": 2.0,
4928 "lloc_min": 2.0,
4929 "lloc_max": 2.0,
4930 "blank_min": 0.0,
4931 "blank_max": 0.0
4932 }
4933 "#);
4934 },
4935 );
4936 }
4937
4938 #[test]
4939 fn perl_lloc_simple_statements() {
4940 check_metrics::<PerlParser>(
4941 "my $a = 1;
4942my $b = 2;
4943my $c = 3;",
4944 "foo.pl",
4945 |metric| {
4946 insta::assert_json_snapshot!(metric.loc, @r#"
4947 {
4948 "sloc": 3.0,
4949 "ploc": 3.0,
4950 "lloc": 3.0,
4951 "cloc": 0.0,
4952 "blank": 0.0,
4953 "sloc_average": 3.0,
4954 "ploc_average": 3.0,
4955 "lloc_average": 3.0,
4956 "cloc_average": 0.0,
4957 "blank_average": 0.0,
4958 "sloc_min": 3.0,
4959 "sloc_max": 3.0,
4960 "cloc_min": 0.0,
4961 "cloc_max": 0.0,
4962 "ploc_min": 3.0,
4963 "ploc_max": 3.0,
4964 "lloc_min": 3.0,
4965 "lloc_max": 3.0,
4966 "blank_min": 0.0,
4967 "blank_max": 0.0
4968 }
4969 "#);
4970 },
4971 );
4972 }
4973
4974 #[test]
4975 fn perl_lloc_compound_statements() {
4976 check_metrics::<PerlParser>(
4977 "if ($x) {
4978 print 'a';
4979}
4980while ($n > 0) {
4981 $n--;
4982}",
4983 "foo.pl",
4984 |metric| {
4985 insta::assert_json_snapshot!(metric.loc, @r#"
4986 {
4987 "sloc": 6.0,
4988 "ploc": 6.0,
4989 "lloc": 4.0,
4990 "cloc": 0.0,
4991 "blank": 0.0,
4992 "sloc_average": 6.0,
4993 "ploc_average": 6.0,
4994 "lloc_average": 4.0,
4995 "cloc_average": 0.0,
4996 "blank_average": 0.0,
4997 "sloc_min": 6.0,
4998 "sloc_max": 6.0,
4999 "cloc_min": 0.0,
5000 "cloc_max": 0.0,
5001 "ploc_min": 6.0,
5002 "ploc_max": 6.0,
5003 "lloc_min": 4.0,
5004 "lloc_max": 4.0,
5005 "blank_min": 0.0,
5006 "blank_max": 0.0
5007 }
5008 "#);
5009 },
5010 );
5011 }
5012
5013 #[test]
5014 fn perl_lloc_postfix_form_counts_once() {
5015 check_metrics::<PerlParser>(
5019 "sub f {
5020 return 1 if $_[0];
5021}",
5022 "foo.pl",
5023 |metric| {
5024 assert_eq!(metric.loc.lloc(), 1.0);
5025 },
5026 );
5027 }
5028
5029 #[test]
5030 fn perl_lloc_use_statement() {
5031 check_metrics::<PerlParser>(
5032 "use strict;
5033use warnings;
5034my $x = 1;",
5035 "foo.pl",
5036 |metric| {
5037 insta::assert_json_snapshot!(metric.loc, @r#"
5038 {
5039 "sloc": 3.0,
5040 "ploc": 3.0,
5041 "lloc": 3.0,
5042 "cloc": 0.0,
5043 "blank": 0.0,
5044 "sloc_average": 3.0,
5045 "ploc_average": 3.0,
5046 "lloc_average": 3.0,
5047 "cloc_average": 0.0,
5048 "blank_average": 0.0,
5049 "sloc_min": 3.0,
5050 "sloc_max": 3.0,
5051 "cloc_min": 0.0,
5052 "cloc_max": 0.0,
5053 "ploc_min": 3.0,
5054 "ploc_max": 3.0,
5055 "lloc_min": 3.0,
5056 "lloc_max": 3.0,
5057 "blank_min": 0.0,
5058 "blank_max": 0.0
5059 }
5060 "#);
5061 },
5062 );
5063 }
5064
5065 #[test]
5066 fn perl_lloc_for_loop() {
5067 check_metrics::<PerlParser>(
5068 "for my $i (1..3) {
5069 print $i;
5070}",
5071 "foo.pl",
5072 |metric| {
5073 assert_eq!(metric.loc.lloc(), 2.0);
5075 },
5076 );
5077 }
5078
5079 #[test]
5080 fn perl_lloc_loop_control_statement() {
5081 check_metrics::<PerlParser>(
5082 "while (1) {
5083 last if $done;
5084}",
5085 "foo.pl",
5086 |metric| {
5087 assert_eq!(metric.loc.lloc(), 2.0);
5089 },
5090 );
5091 }
5092
5093 #[test]
5094 fn perl_lloc_no_double_count_inside_single_line_statement() {
5095 check_metrics::<PerlParser>(
5098 "sub f {
5099 print 'a' unless $_[0];
5100}",
5101 "foo.pl",
5102 |metric| {
5103 assert_eq!(metric.loc.lloc(), 1.0);
5104 },
5105 );
5106 }
5107
5108 #[test]
5109 fn perl_lloc_function_definition_not_counted() {
5110 check_metrics::<PerlParser>(
5113 "sub f {
5114 my $x = 1;
5115}",
5116 "foo.pl",
5117 |metric| {
5118 assert_eq!(metric.loc.lloc(), 1.0);
5119 },
5120 );
5121 }
5122
5123 #[test]
5124 fn perl_lloc_anonymous_function() {
5125 check_metrics::<PerlParser>("my $f = sub { return 1; };", "foo.pl", |metric| {
5129 assert_eq!(metric.loc.lloc(), 2.0);
5130 });
5131 }
5132
5133 #[test]
5134 fn perl_lloc_string_content_excluded_from_ploc() {
5135 check_metrics::<PerlParser>(
5140 "my $s = \"line1
5141line2
5142line3\";",
5143 "foo.pl",
5144 |metric| {
5145 assert_eq!(metric.loc.ploc(), 2.0);
5148 },
5149 );
5150 }
5151
5152 #[test]
5153 fn perl_lloc_unless_until() {
5154 check_metrics::<PerlParser>(
5155 "unless ($x) {
5156 print 'a';
5157}
5158until ($n == 0) {
5159 $n--;
5160}",
5161 "foo.pl",
5162 |metric| {
5163 assert_eq!(metric.loc.lloc(), 4.0);
5166 },
5167 );
5168 }
5169
5170 #[test]
5171 fn perl_lloc_heredoc_body_not_counted() {
5172 check_metrics::<PerlParser>(
5175 "my $s = <<END;
5176line1
5177line2
5178END
5179my $x = 1;",
5180 "foo.pl",
5181 |metric| {
5182 assert_eq!(metric.loc.lloc(), 2.0);
5185 },
5186 );
5187 assert_perl_parses_cleanly(
5191 "my $s = <<END;
5192line1
5193line2
5194END
5195my $x = 1;",
5196 );
5197 }
5198
5199 #[test]
5200 fn perl_lloc_package_and_require() {
5201 check_metrics::<PerlParser>(
5202 "package Foo;
5203require 5.010;
5204my $x = 1;",
5205 "foo.pl",
5206 |metric| {
5207 insta::assert_json_snapshot!(metric.loc, @r#"
5208 {
5209 "sloc": 3.0,
5210 "ploc": 3.0,
5211 "lloc": 3.0,
5212 "cloc": 0.0,
5213 "blank": 0.0,
5214 "sloc_average": 3.0,
5215 "ploc_average": 3.0,
5216 "lloc_average": 3.0,
5217 "cloc_average": 0.0,
5218 "blank_average": 0.0,
5219 "sloc_min": 3.0,
5220 "sloc_max": 3.0,
5221 "cloc_min": 0.0,
5222 "cloc_max": 0.0,
5223 "ploc_min": 3.0,
5224 "ploc_max": 3.0,
5225 "lloc_min": 3.0,
5226 "lloc_max": 3.0,
5227 "blank_min": 0.0,
5228 "blank_max": 0.0
5229 }
5230 "#);
5231 },
5232 );
5233 }
5234
5235 #[test]
5236 fn lua_blank() {
5237 check_metrics::<LuaParser>(
5238 "local x = 1
5239
5240local y = 2",
5241 "foo.lua",
5242 |metric| {
5243 assert_eq!(metric.loc.sloc(), 3.0);
5244 assert_eq!(metric.loc.ploc(), 2.0);
5245 assert_eq!(metric.loc.lloc(), 2.0);
5246 assert_eq!(metric.loc.cloc(), 0.0);
5247 assert_eq!(metric.loc.blank(), 1.0);
5248 insta::assert_json_snapshot!(metric.loc);
5249 },
5250 );
5251 }
5252
5253 #[test]
5254 fn lua_no_zero_blank() {
5255 check_metrics::<LuaParser>(
5258 "local a = 1
5259local b = 2
5260
5261local c = 3 -- trailing
5262local d = 4 -- trailing
5263local e = 5",
5264 "foo.lua",
5265 |metric| {
5266 assert_eq!(metric.loc.sloc(), 6.0);
5267 assert_eq!(metric.loc.ploc(), 5.0);
5268 assert_eq!(metric.loc.cloc(), 2.0);
5269 assert_eq!(metric.loc.blank(), 1.0);
5270 insta::assert_json_snapshot!(metric.loc);
5271 },
5272 );
5273 }
5274
5275 #[test]
5276 fn lua_blank_zero_sanity() {
5277 check_metrics::<LuaParser>(
5280 "local x = 1
5281local y = 2",
5282 "foo.lua",
5283 |metric| {
5284 assert_eq!(metric.loc.sloc(), 2.0);
5285 assert_eq!(metric.loc.ploc(), 2.0);
5286 assert_eq!(metric.loc.lloc(), 2.0);
5287 assert_eq!(metric.loc.cloc(), 0.0);
5288 assert_eq!(metric.loc.blank(), 0.0);
5289 },
5290 );
5291 }
5292
5293 #[test]
5294 fn lua_cloc() {
5295 check_metrics::<LuaParser>(
5296 "-- single line comment
5297local x = 1
5298--[[
5299 block comment
5300 second line
5301]]",
5302 "foo.lua",
5303 |metric| {
5304 assert_eq!(metric.loc.sloc(), 6.0);
5305 assert_eq!(metric.loc.ploc(), 1.0);
5306 assert_eq!(metric.loc.lloc(), 1.0);
5307 assert_eq!(metric.loc.cloc(), 5.0);
5308 assert_eq!(metric.loc.blank(), 0.0);
5309 insta::assert_json_snapshot!(metric.loc);
5310 },
5311 );
5312 }
5313
5314 #[test]
5315 fn lua_lloc() {
5316 check_metrics::<LuaParser>(
5317 "local function f(x)
5318 if x > 0 then
5319 local y = x + 1
5320 return y
5321 end
5322 return 0
5323end",
5324 "foo.lua",
5325 |metric| {
5326 assert_eq!(metric.loc.sloc(), 7.0);
5327 assert_eq!(metric.loc.ploc(), 7.0);
5328 assert_eq!(metric.loc.lloc(), 5.0);
5329 assert_eq!(metric.loc.cloc(), 0.0);
5330 assert_eq!(metric.loc.blank(), 0.0);
5331 insta::assert_json_snapshot!(metric.loc);
5332 },
5333 );
5334 }
5335
5336 #[test]
5337 fn lua_no_string_lloc() {
5338 check_metrics::<LuaParser>(
5340 "local s = [[
5341 line one
5342 line two
5343]]",
5344 "foo.lua",
5345 |metric| {
5346 assert_eq!(metric.loc.sloc(), 4.0);
5347 assert_eq!(metric.loc.ploc(), 2.0);
5348 assert_eq!(metric.loc.lloc(), 1.0);
5349 assert_eq!(metric.loc.cloc(), 0.0);
5350 assert_eq!(metric.loc.blank(), 2.0);
5351 insta::assert_json_snapshot!(metric.loc);
5352 },
5353 );
5354 }
5355
5356 #[test]
5357 fn lua_no_functiondefinition_lloc() {
5358 check_metrics::<LuaParser>(
5361 "local f = function(x)
5362 return x + 1
5363end",
5364 "foo.lua",
5365 |metric| {
5366 assert_eq!(metric.loc.sloc(), 3.0);
5367 assert_eq!(metric.loc.ploc(), 3.0);
5368 assert_eq!(metric.loc.lloc(), 2.0);
5369 assert_eq!(metric.loc.cloc(), 0.0);
5370 assert_eq!(metric.loc.blank(), 0.0);
5371 insta::assert_json_snapshot!(metric.loc);
5372 },
5373 );
5374 }
5375
5376 #[test]
5377 fn lua_no_elseif_lloc() {
5378 check_metrics::<LuaParser>(
5380 "local function f(x)
5381 if x > 0 then
5382 return 1
5383 elseif x < 0 then
5384 return -1
5385 else
5386 return 0
5387 end
5388end",
5389 "foo.lua",
5390 |metric| {
5391 assert_eq!(metric.loc.sloc(), 9.0);
5392 assert_eq!(metric.loc.ploc(), 9.0);
5393 assert_eq!(metric.loc.lloc(), 5.0);
5394 assert_eq!(metric.loc.cloc(), 0.0);
5395 assert_eq!(metric.loc.blank(), 0.0);
5396 insta::assert_json_snapshot!(metric.loc);
5397 },
5398 );
5399 }
5400
5401 #[test]
5402 fn lua_no_else_lloc() {
5403 check_metrics::<LuaParser>(
5405 "local function f(x)
5406 if x > 0 then
5407 return 1
5408 else
5409 return 0
5410 end
5411end",
5412 "foo.lua",
5413 |metric| {
5414 assert_eq!(metric.loc.sloc(), 7.0);
5415 assert_eq!(metric.loc.ploc(), 7.0);
5416 assert_eq!(metric.loc.lloc(), 4.0);
5417 assert_eq!(metric.loc.cloc(), 0.0);
5418 assert_eq!(metric.loc.blank(), 0.0);
5419 insta::assert_json_snapshot!(metric.loc);
5420 },
5421 );
5422 }
5423
5424 #[test]
5425 fn lua_functiondeclaration_lloc() {
5426 check_metrics::<LuaParser>(
5428 "function f()
5429 return 1
5430end",
5431 "foo.lua",
5432 |metric| {
5433 assert_eq!(metric.loc.sloc(), 3.0);
5434 assert_eq!(metric.loc.ploc(), 3.0);
5435 assert_eq!(metric.loc.lloc(), 2.0);
5436 assert_eq!(metric.loc.cloc(), 0.0);
5437 assert_eq!(metric.loc.blank(), 0.0);
5438 insta::assert_json_snapshot!(metric.loc);
5439 },
5440 );
5441 }
5442
5443 #[test]
5444 fn lua_local_function_lloc() {
5445 check_metrics::<LuaParser>(
5447 "local function g()
5448 return 2
5449end",
5450 "foo.lua",
5451 |metric| {
5452 assert_eq!(metric.loc.sloc(), 3.0);
5453 assert_eq!(metric.loc.ploc(), 3.0);
5454 assert_eq!(metric.loc.lloc(), 2.0);
5455 assert_eq!(metric.loc.cloc(), 0.0);
5456 assert_eq!(metric.loc.blank(), 0.0);
5457 insta::assert_json_snapshot!(metric.loc);
5458 },
5459 );
5460 }
5461
5462 #[test]
5463 fn lua_for_numeric_lloc() {
5464 check_metrics::<LuaParser>(
5465 "for i = 1, 10 do
5466 print(i)
5467end",
5468 "foo.lua",
5469 |metric| {
5470 assert_eq!(metric.loc.sloc(), 3.0);
5471 assert_eq!(metric.loc.ploc(), 3.0);
5472 assert_eq!(metric.loc.lloc(), 1.0);
5473 assert_eq!(metric.loc.cloc(), 0.0);
5474 assert_eq!(metric.loc.blank(), 0.0);
5475 insta::assert_json_snapshot!(metric.loc);
5476 },
5477 );
5478 }
5479
5480 #[test]
5481 fn lua_for_generic_lloc() {
5482 check_metrics::<LuaParser>(
5483 "for k, v in pairs(t) do
5484 print(k, v)
5485end",
5486 "foo.lua",
5487 |metric| {
5488 assert_eq!(metric.loc.sloc(), 3.0);
5489 assert_eq!(metric.loc.ploc(), 3.0);
5490 assert_eq!(metric.loc.lloc(), 1.0);
5491 assert_eq!(metric.loc.cloc(), 0.0);
5492 assert_eq!(metric.loc.blank(), 0.0);
5493 insta::assert_json_snapshot!(metric.loc);
5494 },
5495 );
5496 }
5497
5498 #[test]
5499 fn lua_repeat_lloc() {
5500 check_metrics::<LuaParser>(
5501 "local i = 0
5502repeat
5503 i = i + 1
5504until i >= 10",
5505 "foo.lua",
5506 |metric| {
5507 assert_eq!(metric.loc.sloc(), 4.0);
5508 assert_eq!(metric.loc.ploc(), 4.0);
5509 assert_eq!(metric.loc.lloc(), 3.0);
5510 assert_eq!(metric.loc.cloc(), 0.0);
5511 assert_eq!(metric.loc.blank(), 0.0);
5512 insta::assert_json_snapshot!(metric.loc);
5513 },
5514 );
5515 }
5516
5517 #[test]
5518 fn lua_local_decl_lloc() {
5519 check_metrics::<LuaParser>(
5520 "local x = 1
5521local y, z = 2, 3",
5522 "foo.lua",
5523 |metric| {
5524 assert_eq!(metric.loc.sloc(), 2.0);
5525 assert_eq!(metric.loc.ploc(), 2.0);
5526 assert_eq!(metric.loc.lloc(), 2.0);
5527 assert_eq!(metric.loc.cloc(), 0.0);
5528 assert_eq!(metric.loc.blank(), 0.0);
5529 insta::assert_json_snapshot!(metric.loc);
5530 },
5531 );
5532 }
5533
5534 #[test]
5535 fn lua_function_call_lloc() {
5536 check_metrics::<LuaParser>(
5539 "print(\"hello\")
5540local x = 1",
5541 "foo.lua",
5542 |metric| {
5543 assert_eq!(metric.loc.sloc(), 2.0);
5544 assert_eq!(metric.loc.ploc(), 2.0);
5545 assert_eq!(metric.loc.lloc(), 1.0);
5546 assert_eq!(metric.loc.cloc(), 0.0);
5547 assert_eq!(metric.loc.blank(), 0.0);
5548 insta::assert_json_snapshot!(metric.loc);
5549 },
5550 );
5551 }
5552
5553 #[test]
5554 fn lua_toplevel_assignment_lloc() {
5555 check_metrics::<LuaParser>(
5558 "x = 1
5559y, z = 2, 3",
5560 "foo.lua",
5561 |metric| {
5562 assert_eq!(metric.loc.sloc(), 2.0);
5563 assert_eq!(metric.loc.ploc(), 2.0);
5564 assert_eq!(metric.loc.lloc(), 2.0);
5565 assert_eq!(metric.loc.cloc(), 0.0);
5566 assert_eq!(metric.loc.blank(), 0.0);
5567 insta::assert_json_snapshot!(metric.loc);
5568 },
5569 );
5570 }
5571
5572 #[test]
5573 fn tsx_basic_loc() {
5574 check_metrics::<TsxParser>(
5575 "// A simple utility function
5576 function add(a: number, b: number): number {
5577 /* multi-line
5578 comment */
5579 return a + b;
5580 }
5581
5582 const greet = (name: string) => {
5583 return `Hello, ${name}`;
5584 };",
5585 "foo.tsx",
5586 |metric| {
5587 insta::assert_json_snapshot!(
5588 metric.loc,
5589 @r###"
5590 {
5591 "sloc": 10.0,
5592 "ploc": 6.0,
5593 "lloc": 4.0,
5594 "cloc": 3.0,
5595 "blank": 1.0,
5596 "sloc_average": 3.3333333333333335,
5597 "ploc_average": 2.0,
5598 "lloc_average": 1.3333333333333333,
5599 "cloc_average": 1.0,
5600 "blank_average": 0.3333333333333333,
5601 "sloc_min": 3.0,
5602 "sloc_max": 5.0,
5603 "cloc_min": 0.0,
5604 "cloc_max": 2.0,
5605 "ploc_min": 3.0,
5606 "ploc_max": 3.0,
5607 "lloc_min": 2.0,
5608 "lloc_max": 2.0,
5609 "blank_min": 0.0,
5610 "blank_max": 0.0
5611 }"###
5612 );
5613 },
5614 );
5615 }
5616
5617 #[test]
5618 fn typescript_basic_loc() {
5619 check_metrics::<TypescriptParser>(
5620 "// Line comment
5621 /* Block
5622 comment */
5623 function greet(name: string): string {
5624 return `Hello, ${name}`;
5625 }
5626
5627 const add = (a: number, b: number): number => a + b;",
5628 "foo.ts",
5629 |metric| {
5630 insta::assert_json_snapshot!(
5631 metric.loc,
5632 @r###"
5633 {
5634 "sloc": 8.0,
5635 "ploc": 4.0,
5636 "lloc": 2.0,
5637 "cloc": 3.0,
5638 "blank": 1.0,
5639 "sloc_average": 2.6666666666666665,
5640 "ploc_average": 1.3333333333333333,
5641 "lloc_average": 0.6666666666666666,
5642 "cloc_average": 1.0,
5643 "blank_average": 0.3333333333333333,
5644 "sloc_min": 1.0,
5645 "sloc_max": 3.0,
5646 "cloc_min": 0.0,
5647 "cloc_max": 0.0,
5648 "ploc_min": 1.0,
5649 "ploc_max": 3.0,
5650 "lloc_min": 0.0,
5651 "lloc_max": 2.0,
5652 "blank_min": 0.0,
5653 "blank_max": 0.0
5654 }"###
5655 );
5656 },
5657 );
5658 }
5659
5660 #[test]
5661 fn csharp_comments() {
5662 check_metrics::<CsharpParser>(
5663 "for (int i = 0; i < 100; i++) {
5664 // Print hello
5665 System.Console.WriteLine(\"hello\");
5666 /// XML doc comment
5667 System.Console.WriteLine(\"hello\");
5668 }",
5669 "foo.cs",
5670 |metric| {
5671 assert_eq!(metric.loc.sloc(), 6.0);
5672 assert_eq!(metric.loc.ploc(), 4.0);
5673 assert_eq!(metric.loc.lloc(), 3.0);
5674 assert_eq!(metric.loc.cloc(), 2.0);
5675 assert_eq!(metric.loc.blank(), 0.0);
5676 insta::assert_json_snapshot!(metric.loc);
5677 },
5678 );
5679 }
5680
5681 #[test]
5682 fn csharp_blank() {
5683 check_metrics::<CsharpParser>(
5684 "int x = 1;
5685
5686
5687 int y = 2;",
5688 "foo.cs",
5689 |metric| {
5690 assert_eq!(metric.loc.sloc(), 4.0);
5691 assert_eq!(metric.loc.ploc(), 2.0);
5692 assert_eq!(metric.loc.lloc(), 2.0);
5693 assert_eq!(metric.loc.cloc(), 0.0);
5694 assert_eq!(metric.loc.blank(), 2.0);
5695 insta::assert_json_snapshot!(metric.loc);
5696 },
5697 );
5698 }
5699
5700 #[test]
5701 fn csharp_sloc() {
5702 check_metrics::<CsharpParser>(
5703 "for (int i = 0; i < 100; i++) {
5704 System.Console.WriteLine(i);
5705 }",
5706 "foo.cs",
5707 |metric| {
5708 assert_eq!(metric.loc.sloc(), 3.0);
5709 assert_eq!(metric.loc.ploc(), 3.0);
5710 assert_eq!(metric.loc.lloc(), 2.0);
5711 assert_eq!(metric.loc.cloc(), 0.0);
5712 assert_eq!(metric.loc.blank(), 0.0);
5713 insta::assert_json_snapshot!(metric.loc);
5714 },
5715 );
5716 }
5717
5718 #[test]
5719 fn csharp_module_sloc() {
5720 check_metrics::<CsharpParser>(
5721 "namespace HelloWorld {
5722 class Program { }
5723 }",
5724 "foo.cs",
5725 |metric| {
5726 assert_eq!(metric.loc.sloc(), 3.0);
5727 assert_eq!(metric.loc.ploc(), 3.0);
5728 assert_eq!(metric.loc.lloc(), 0.0);
5729 assert_eq!(metric.loc.cloc(), 0.0);
5730 assert_eq!(metric.loc.blank(), 0.0);
5731 insta::assert_json_snapshot!(metric.loc);
5732 },
5733 );
5734 }
5735
5736 #[test]
5737 fn csharp_single_ploc() {
5738 check_metrics::<CsharpParser>("int x = 1;", "foo.cs", |metric| {
5739 assert_eq!(metric.loc.sloc(), 1.0);
5740 assert_eq!(metric.loc.ploc(), 1.0);
5741 assert_eq!(metric.loc.lloc(), 1.0);
5742 assert_eq!(metric.loc.cloc(), 0.0);
5743 assert_eq!(metric.loc.blank(), 0.0);
5744 insta::assert_json_snapshot!(metric.loc);
5745 });
5746 }
5747
5748 #[test]
5749 fn csharp_simple_ploc() {
5750 check_metrics::<CsharpParser>(
5751 "for (int i = 0; i < 100; i++) {
5752 System.Console.WriteLine(i);
5753 }",
5754 "foo.cs",
5755 |metric| {
5756 assert_eq!(metric.loc.sloc(), 3.0);
5757 assert_eq!(metric.loc.ploc(), 3.0);
5758 assert_eq!(metric.loc.lloc(), 2.0);
5759 assert_eq!(metric.loc.cloc(), 0.0);
5760 assert_eq!(metric.loc.blank(), 0.0);
5761 insta::assert_json_snapshot!(metric.loc);
5762 },
5763 );
5764 }
5765
5766 #[test]
5767 fn csharp_multi_ploc() {
5768 check_metrics::<CsharpParser>(
5769 "int x = 1;
5770 for (int i = 0; i < 100; i++) {
5771 System.Console.WriteLine(i);
5772 }",
5773 "foo.cs",
5774 |metric| {
5775 assert_eq!(metric.loc.sloc(), 4.0);
5776 assert_eq!(metric.loc.ploc(), 4.0);
5777 assert_eq!(metric.loc.lloc(), 3.0);
5778 assert_eq!(metric.loc.cloc(), 0.0);
5779 assert_eq!(metric.loc.blank(), 0.0);
5780 insta::assert_json_snapshot!(metric.loc);
5781 },
5782 );
5783 }
5784
5785 #[test]
5786 fn csharp_single_statement_lloc() {
5787 check_metrics::<CsharpParser>("int max = 10;", "foo.cs", |metric| {
5788 assert_eq!(metric.loc.sloc(), 1.0);
5789 assert_eq!(metric.loc.ploc(), 1.0);
5790 assert_eq!(metric.loc.lloc(), 1.0);
5791 assert_eq!(metric.loc.cloc(), 0.0);
5792 assert_eq!(metric.loc.blank(), 0.0);
5793 insta::assert_json_snapshot!(metric.loc);
5794 });
5795 }
5796
5797 #[test]
5798 fn csharp_for_lloc() {
5799 check_metrics::<CsharpParser>(
5800 "for (int i = 0; i < 10; i++) {
5801 System.Console.WriteLine(i);
5802 }",
5803 "foo.cs",
5804 |metric| {
5805 assert_eq!(metric.loc.sloc(), 3.0);
5806 assert_eq!(metric.loc.ploc(), 3.0);
5807 assert_eq!(metric.loc.lloc(), 2.0);
5808 assert_eq!(metric.loc.cloc(), 0.0);
5809 assert_eq!(metric.loc.blank(), 0.0);
5810 insta::assert_json_snapshot!(metric.loc);
5811 },
5812 );
5813 }
5814
5815 #[test]
5816 fn csharp_foreach_lloc() {
5817 check_metrics::<CsharpParser>(
5818 "foreach (var item in items) {
5819 System.Console.WriteLine(item);
5820 }",
5821 "foo.cs",
5822 |metric| {
5823 assert_eq!(metric.loc.sloc(), 3.0);
5824 assert_eq!(metric.loc.ploc(), 3.0);
5825 assert_eq!(metric.loc.lloc(), 2.0);
5826 assert_eq!(metric.loc.cloc(), 0.0);
5827 assert_eq!(metric.loc.blank(), 0.0);
5828 insta::assert_json_snapshot!(metric.loc);
5829 },
5830 );
5831 }
5832
5833 #[test]
5834 fn csharp_while_lloc() {
5835 check_metrics::<CsharpParser>(
5836 "int i = 0;
5837 while (i < 10) {
5838 i++;
5839 }",
5840 "foo.cs",
5841 |metric| {
5842 assert_eq!(metric.loc.sloc(), 4.0);
5843 assert_eq!(metric.loc.ploc(), 4.0);
5844 assert_eq!(metric.loc.lloc(), 3.0);
5845 assert_eq!(metric.loc.cloc(), 0.0);
5846 assert_eq!(metric.loc.blank(), 0.0);
5847 insta::assert_json_snapshot!(metric.loc);
5848 },
5849 );
5850 }
5851
5852 #[test]
5853 fn csharp_do_while_lloc() {
5854 check_metrics::<CsharpParser>(
5855 "int i = 0;
5856 do {
5857 i++;
5858 } while (i < 10);",
5859 "foo.cs",
5860 |metric| {
5861 assert_eq!(metric.loc.sloc(), 4.0);
5862 assert_eq!(metric.loc.ploc(), 4.0);
5863 assert_eq!(metric.loc.lloc(), 3.0);
5864 assert_eq!(metric.loc.cloc(), 0.0);
5865 assert_eq!(metric.loc.blank(), 0.0);
5866 insta::assert_json_snapshot!(metric.loc);
5867 },
5868 );
5869 }
5870
5871 #[test]
5872 fn csharp_switch_lloc() {
5873 check_metrics::<CsharpParser>(
5874 "switch (x) {
5875 case 1: System.Console.WriteLine(1); break;
5876 case 2: System.Console.WriteLine(2); break;
5877 default: System.Console.WriteLine(0); break;
5878 }
5879 string s = x switch { 1 => \"one\", _ => \"other\" };",
5880 "foo.cs",
5881 |metric| {
5882 assert_eq!(metric.loc.sloc(), 6.0);
5883 assert_eq!(metric.loc.ploc(), 6.0);
5884 assert_eq!(metric.loc.lloc(), 8.0);
5885 assert_eq!(metric.loc.cloc(), 0.0);
5886 assert_eq!(metric.loc.blank(), 0.0);
5887 insta::assert_json_snapshot!(metric.loc);
5888 },
5889 );
5890 }
5891
5892 #[test]
5893 fn csharp_continue_lloc() {
5894 check_metrics::<CsharpParser>(
5895 "for (int i = 0; i < 10; i++) {
5896 if (i == 5) continue;
5897 System.Console.WriteLine(i);
5898 }",
5899 "foo.cs",
5900 |metric| {
5901 assert_eq!(metric.loc.sloc(), 4.0);
5902 assert_eq!(metric.loc.ploc(), 4.0);
5903 assert_eq!(metric.loc.lloc(), 4.0);
5904 assert_eq!(metric.loc.cloc(), 0.0);
5905 assert_eq!(metric.loc.blank(), 0.0);
5906 insta::assert_json_snapshot!(metric.loc);
5907 },
5908 );
5909 }
5910
5911 #[test]
5912 fn csharp_try_lloc() {
5913 check_metrics::<CsharpParser>(
5914 "try {
5915 System.Console.WriteLine(\"try\");
5916 } catch (System.Exception e) {
5917 throw new System.Exception(\"caught\");
5918 } finally {
5919 System.Console.WriteLine(\"done\");
5920 }",
5921 "foo.cs",
5922 |metric| {
5923 assert_eq!(metric.loc.sloc(), 7.0);
5924 assert_eq!(metric.loc.ploc(), 7.0);
5925 assert_eq!(metric.loc.lloc(), 4.0);
5926 assert_eq!(metric.loc.cloc(), 0.0);
5927 assert_eq!(metric.loc.blank(), 0.0);
5928 insta::assert_json_snapshot!(metric.loc);
5929 },
5930 );
5931 }
5932
5933 #[test]
5934 fn csharp_class_loc() {
5935 check_metrics::<CsharpParser>(
5936 "class A {
5937 int x;
5938 public void M() {
5939 System.Console.WriteLine(x);
5940 }
5941 }",
5942 "foo.cs",
5943 |metric| {
5944 assert_eq!(metric.loc.sloc(), 6.0);
5945 assert_eq!(metric.loc.ploc(), 6.0);
5946 assert_eq!(metric.loc.lloc(), 1.0);
5947 assert_eq!(metric.loc.cloc(), 0.0);
5948 assert_eq!(metric.loc.blank(), 0.0);
5949 insta::assert_json_snapshot!(metric.loc);
5950 },
5951 );
5952 }
5953
5954 #[test]
5955 fn csharp_expressions_lloc() {
5956 check_metrics::<CsharpParser>(
5957 "int a = 1;
5958 int b = 2;
5959 int c = a + b;
5960 System.Console.WriteLine(c);",
5961 "foo.cs",
5962 |metric| {
5963 assert_eq!(metric.loc.sloc(), 4.0);
5964 assert_eq!(metric.loc.ploc(), 4.0);
5965 assert_eq!(metric.loc.lloc(), 4.0);
5966 assert_eq!(metric.loc.cloc(), 0.0);
5967 assert_eq!(metric.loc.blank(), 0.0);
5968 insta::assert_json_snapshot!(metric.loc);
5969 },
5970 );
5971 }
5972
5973 #[test]
5974 fn csharp_statement_inline_loc() {
5975 check_metrics::<CsharpParser>(
5976 "if (x > 0) System.Console.WriteLine(x);",
5977 "foo.cs",
5978 |metric| {
5979 assert_eq!(metric.loc.sloc(), 1.0);
5980 assert_eq!(metric.loc.ploc(), 1.0);
5981 assert_eq!(metric.loc.lloc(), 2.0);
5982 assert_eq!(metric.loc.cloc(), 0.0);
5983 assert_eq!(metric.loc.blank(), 0.0);
5984 insta::assert_json_snapshot!(metric.loc);
5985 },
5986 );
5987 }
5988
5989 #[test]
5990 fn csharp_general_loc() {
5991 check_metrics::<CsharpParser>(
5992 "using System;
5993 namespace Demo {
5994 class A {
5995 public void M() {
5996 Console.WriteLine(\"hi\");
5997 }
5998 }
5999 class B {
6000 public int N() { return 0; }
6001 }
6002 }",
6003 "foo.cs",
6004 |metric| {
6005 assert_eq!(metric.loc.sloc(), 11.0);
6006 assert_eq!(metric.loc.ploc(), 11.0);
6007 assert_eq!(metric.loc.lloc(), 2.0);
6008 assert_eq!(metric.loc.cloc(), 0.0);
6009 assert_eq!(metric.loc.blank(), 0.0);
6010 insta::assert_json_snapshot!(metric.loc);
6011 },
6012 );
6013 }
6014
6015 #[test]
6016 fn csharp_using_lloc() {
6017 check_metrics::<CsharpParser>(
6022 "using System;
6023 using System.IO;
6024 class A {
6025 public void M() {
6026 using (var s = File.OpenRead(\"x\")) {
6027 Console.WriteLine(s);
6028 }
6029 using var t = File.OpenRead(\"y\");
6030 Console.WriteLine(t);
6031 }
6032 }",
6033 "foo.cs",
6034 |metric| {
6035 assert_eq!(metric.loc.sloc(), 11.0);
6036 assert_eq!(metric.loc.ploc(), 11.0);
6037 assert_eq!(metric.loc.lloc(), 4.0);
6038 assert_eq!(metric.loc.cloc(), 0.0);
6039 assert_eq!(metric.loc.blank(), 0.0);
6040 insta::assert_json_snapshot!(metric.loc);
6041 },
6042 );
6043 }
6044
6045 #[test]
6046 fn kotlin_loc_basic() {
6047 check_metrics::<KotlinParser>(
6048 "// A simple function
6049 fun greet(name: String): String {
6050 val greeting = \"Hello, \" + name
6051 if (name.isEmpty()) {
6052 return \"Hello, World!\"
6053 }
6054 return greeting
6055 }",
6056 "foo.kt",
6057 |metric| {
6058 insta::assert_json_snapshot!(
6059 metric.loc,
6060 @r###"
6061 {
6062 "sloc": 8.0,
6063 "ploc": 7.0,
6064 "lloc": 4.0,
6065 "cloc": 1.0,
6066 "blank": 0.0,
6067 "sloc_average": 4.0,
6068 "ploc_average": 3.5,
6069 "lloc_average": 2.0,
6070 "cloc_average": 0.5,
6071 "blank_average": 0.0,
6072 "sloc_min": 7.0,
6073 "sloc_max": 7.0,
6074 "cloc_min": 0.0,
6075 "cloc_max": 0.0,
6076 "ploc_min": 7.0,
6077 "ploc_max": 7.0,
6078 "lloc_min": 4.0,
6079 "lloc_max": 4.0,
6080 "blank_min": 0.0,
6081 "blank_max": 0.0
6082 }
6083 "###
6084 );
6085 },
6086 );
6087 }
6088
6089 #[test]
6090 fn kotlin_loc_bare_expression() {
6091 check_metrics::<KotlinParser>(
6092 "fun main() {
6093 val x = 42
6094 println(x)
6095 listOf(1, 2, 3).forEach { println(it) }
6096 }",
6097 "foo.kt",
6098 |metric| {
6099 insta::assert_json_snapshot!(
6103 metric.loc,
6104 @r#"
6105 {
6106 "sloc": 5.0,
6107 "ploc": 5.0,
6108 "lloc": 3.0,
6109 "cloc": 0.0,
6110 "blank": 0.0,
6111 "sloc_average": 2.5,
6112 "ploc_average": 2.5,
6113 "lloc_average": 1.5,
6114 "cloc_average": 0.0,
6115 "blank_average": 0.0,
6116 "sloc_min": 5.0,
6117 "sloc_max": 5.0,
6118 "cloc_min": 0.0,
6119 "cloc_max": 0.0,
6120 "ploc_min": 5.0,
6121 "ploc_max": 5.0,
6122 "lloc_min": 3.0,
6123 "lloc_max": 3.0,
6124 "blank_min": 0.0,
6125 "blank_max": 0.0
6126 }
6127 "#
6128 );
6129 },
6130 );
6131 }
6132
6133 #[test]
6134 fn bash_loc() {
6135 check_metrics::<BashParser>(
6136 "#!/bin/bash
6137# This is a comment
6138f() {
6139 echo 'hello'
6140}
6141
6142# Another comment
6143f",
6144 "foo.sh",
6145 |metric| {
6146 assert_eq!(metric.loc.sloc(), 8.0);
6147 assert_eq!(metric.loc.ploc(), 4.0);
6148 assert_eq!(metric.loc.lloc(), 3.0);
6149 assert_eq!(metric.loc.cloc(), 3.0);
6150 assert_eq!(metric.loc.blank(), 1.0);
6151 insta::assert_json_snapshot!(metric.loc);
6152 },
6153 );
6154 }
6155
6156 #[test]
6160 fn python_cloc_crlf_matches_lf() {
6161 check_metrics::<PythonParser>("# comment\nx = 1", "foo.py", |m| {
6162 assert_eq!(m.loc.cloc(), 1.0);
6163 assert_eq!(m.loc.ploc(), 1.0);
6164 assert_eq!(m.loc.sloc(), 2.0);
6165 assert_eq!(m.loc.blank(), 0.0);
6166 });
6167 check_metrics::<PythonParser>("# comment\r\nx = 1", "foo.py", |m| {
6168 assert_eq!(m.loc.cloc(), 1.0);
6169 assert_eq!(m.loc.ploc(), 1.0);
6170 assert_eq!(m.loc.sloc(), 2.0);
6171 assert_eq!(m.loc.blank(), 0.0);
6172 });
6173 check_metrics::<PythonParser>("# comment\rx = 1", "foo.py", |m| {
6177 assert_eq!(m.loc.cloc(), 1.0);
6178 assert_eq!(m.loc.ploc(), 1.0);
6179 assert_eq!(m.loc.sloc(), 2.0);
6180 assert_eq!(m.loc.blank(), 0.0);
6181 });
6182 }
6183
6184 #[test]
6185 fn python_blank_crlf_matches_lf() {
6186 check_metrics::<PythonParser>("# comment\n\nx = 1", "foo.py", |m| {
6187 assert_eq!(m.loc.blank(), 1.0);
6188 });
6189 check_metrics::<PythonParser>("# comment\r\n\r\nx = 1", "foo.py", |m| {
6190 assert_eq!(m.loc.blank(), 1.0);
6191 });
6192 check_metrics::<PythonParser>("# comment\r\rx = 1", "foo.py", |m| {
6194 assert_eq!(m.loc.blank(), 1.0);
6195 });
6196 }
6197
6198 #[test]
6199 fn rust_cloc_crlf_matches_lf() {
6200 check_metrics::<RustParser>(
6201 "fn f() {\n // comment\n let x = 1;\n}",
6202 "foo.rs",
6203 |m| {
6204 assert_eq!(m.loc.cloc(), 1.0);
6205 assert_eq!(m.loc.sloc(), 4.0);
6206 },
6207 );
6208 check_metrics::<RustParser>(
6209 "fn f() {\r\n // comment\r\n let x = 1;\r\n}",
6210 "foo.rs",
6211 |m| {
6212 assert_eq!(m.loc.cloc(), 1.0);
6213 assert_eq!(m.loc.sloc(), 4.0);
6214 },
6215 );
6216 check_metrics::<RustParser>(
6219 "fn f() {\r // comment\r let x = 1;\r}",
6220 "foo.rs",
6221 |m| {
6222 assert_eq!(m.loc.cloc(), 1.0);
6223 assert_eq!(m.loc.sloc(), 4.0);
6224 },
6225 );
6226 }
6227
6228 #[test]
6229 fn tcl_blank() {
6230 check_metrics::<TclParser>("set x 1\n\nset y 2", "foo.tcl", |metric| {
6231 assert_eq!(metric.loc.sloc(), 3.0);
6232 assert_eq!(metric.loc.ploc(), 2.0);
6233 assert_eq!(metric.loc.lloc(), 2.0);
6234 assert_eq!(metric.loc.cloc(), 0.0);
6235 assert_eq!(metric.loc.blank(), 1.0);
6236 insta::assert_json_snapshot!(metric.loc);
6237 });
6238 }
6239
6240 #[test]
6241 fn tcl_no_zero_blank() {
6242 check_metrics::<TclParser>(
6246 "set a 1\nset b 2\n\nset c 3 ;# trailing\nset d 4 ;# trailing\nset e 5",
6247 "foo.tcl",
6248 |metric| {
6249 assert_eq!(metric.loc.sloc(), 6.0);
6250 assert_eq!(metric.loc.ploc(), 5.0);
6251 assert_eq!(metric.loc.cloc(), 2.0);
6252 assert_eq!(metric.loc.blank(), 1.0);
6253 },
6254 );
6255 }
6256
6257 #[test]
6258 fn tcl_cloc() {
6259 check_metrics::<TclParser>("# This is a comment\nset x 1", "foo.tcl", |metric| {
6260 assert_eq!(metric.loc.sloc(), 2.0);
6261 assert_eq!(metric.loc.ploc(), 2.0);
6262 assert_eq!(metric.loc.lloc(), 1.0);
6263 assert_eq!(metric.loc.cloc(), 1.0);
6264 assert_eq!(metric.loc.blank(), 0.0);
6265 insta::assert_json_snapshot!(metric.loc);
6266 });
6267 }
6268
6269 #[test]
6270 fn tcl_lloc() {
6271 check_metrics::<TclParser>(
6272 "proc f {x} {
6273 while {$x > 0} {
6274 if {$x > 10} {
6275 set x [expr {$x - 1}]
6276 }
6277 }
6278}",
6279 "foo.tcl",
6280 |metric| {
6281 assert_eq!(metric.loc.sloc(), 7.0);
6282 assert_eq!(metric.loc.ploc(), 7.0);
6283 assert_eq!(metric.loc.lloc(), 4.0);
6284 assert_eq!(metric.loc.cloc(), 0.0);
6285 assert_eq!(metric.loc.blank(), 0.0);
6286 insta::assert_json_snapshot!(metric.loc);
6287 },
6288 );
6289 }
6290
6291 #[test]
6292 fn tcl_no_command_substitution_lloc() {
6293 check_metrics::<TclParser>("puts [string toupper x]", "foo.tcl", |metric| {
6295 assert_eq!(metric.loc.sloc(), 1.0);
6296 assert_eq!(metric.loc.ploc(), 1.0);
6297 assert_eq!(metric.loc.lloc(), 1.0);
6298 assert_eq!(metric.loc.cloc(), 0.0);
6299 assert_eq!(metric.loc.blank(), 0.0);
6300 insta::assert_json_snapshot!(metric.loc);
6301 });
6302 }
6303
6304 #[test]
6305 fn tcl_procedure_lloc() {
6306 check_metrics::<TclParser>("proc foo {} {\n puts hello\n}", "foo.tcl", |metric| {
6307 assert_eq!(metric.loc.sloc(), 3.0);
6308 assert_eq!(metric.loc.ploc(), 3.0);
6309 assert_eq!(metric.loc.lloc(), 2.0);
6310 assert_eq!(metric.loc.cloc(), 0.0);
6311 assert_eq!(metric.loc.blank(), 0.0);
6312 insta::assert_json_snapshot!(metric.loc);
6313 });
6314 }
6315
6316 #[test]
6317 fn tcl_if_lloc() {
6318 check_metrics::<TclParser>("if {1} {\n puts hello\n}", "foo.tcl", |metric| {
6319 assert_eq!(metric.loc.sloc(), 3.0);
6320 assert_eq!(metric.loc.ploc(), 3.0);
6321 assert_eq!(metric.loc.lloc(), 2.0);
6322 assert_eq!(metric.loc.cloc(), 0.0);
6323 assert_eq!(metric.loc.blank(), 0.0);
6324 insta::assert_json_snapshot!(metric.loc);
6325 });
6326 }
6327
6328 #[test]
6329 fn tcl_elseif_lloc() {
6330 check_metrics::<TclParser>(
6332 "if {$x > 10} {
6333 puts big
6334} elseif {$x > 5} {
6335 puts medium
6336} else {
6337 puts small
6338}",
6339 "foo.tcl",
6340 |metric| {
6341 assert_eq!(metric.loc.sloc(), 7.0);
6342 assert_eq!(metric.loc.ploc(), 7.0);
6343 assert_eq!(metric.loc.lloc(), 5.0);
6344 assert_eq!(metric.loc.cloc(), 0.0);
6345 assert_eq!(metric.loc.blank(), 0.0);
6346 insta::assert_json_snapshot!(metric.loc);
6347 },
6348 );
6349 }
6350
6351 #[test]
6352 fn tcl_while_lloc() {
6353 check_metrics::<TclParser>(
6354 "while {$x > 0} {\n set x [expr {$x - 1}]\n}",
6355 "foo.tcl",
6356 |metric| {
6357 assert_eq!(metric.loc.sloc(), 3.0);
6358 assert_eq!(metric.loc.ploc(), 3.0);
6359 assert_eq!(metric.loc.lloc(), 2.0);
6360 assert_eq!(metric.loc.cloc(), 0.0);
6361 assert_eq!(metric.loc.blank(), 0.0);
6362 insta::assert_json_snapshot!(metric.loc);
6363 },
6364 );
6365 }
6366
6367 #[test]
6368 fn tcl_foreach_lloc() {
6369 check_metrics::<TclParser>(
6370 "foreach item {a b c} {\n puts $item\n}",
6371 "foo.tcl",
6372 |metric| {
6373 assert_eq!(metric.loc.sloc(), 3.0);
6374 assert_eq!(metric.loc.ploc(), 3.0);
6375 assert_eq!(metric.loc.lloc(), 2.0);
6376 assert_eq!(metric.loc.cloc(), 0.0);
6377 assert_eq!(metric.loc.blank(), 0.0);
6378 insta::assert_json_snapshot!(metric.loc);
6379 },
6380 );
6381 }
6382
6383 #[test]
6384 fn tcl_set_lloc() {
6385 check_metrics::<TclParser>("set x 42", "foo.tcl", |metric| {
6386 assert_eq!(metric.loc.sloc(), 1.0);
6387 assert_eq!(metric.loc.ploc(), 1.0);
6388 assert_eq!(metric.loc.lloc(), 1.0);
6389 assert_eq!(metric.loc.cloc(), 0.0);
6390 assert_eq!(metric.loc.blank(), 0.0);
6391 insta::assert_json_snapshot!(metric.loc);
6392 });
6393 }
6394
6395 #[test]
6396 fn tcl_global_lloc() {
6397 check_metrics::<TclParser>("global x", "foo.tcl", |metric| {
6398 assert_eq!(metric.loc.sloc(), 1.0);
6399 assert_eq!(metric.loc.ploc(), 1.0);
6400 assert_eq!(metric.loc.lloc(), 1.0);
6401 assert_eq!(metric.loc.cloc(), 0.0);
6402 assert_eq!(metric.loc.blank(), 0.0);
6403 insta::assert_json_snapshot!(metric.loc);
6404 });
6405 }
6406
6407 #[test]
6408 fn tcl_try_catch_lloc() {
6409 check_metrics::<TclParser>(
6411 "catch {
6412 set x 1
6413} result
6414try {
6415 set y 2
6416} on error {msg} {
6417 puts $msg
6418}",
6419 "foo.tcl",
6420 |metric| {
6421 assert_eq!(metric.loc.sloc(), 8.0);
6422 assert_eq!(metric.loc.ploc(), 8.0);
6423 assert_eq!(metric.loc.lloc(), 5.0);
6424 assert_eq!(metric.loc.cloc(), 0.0);
6425 assert_eq!(metric.loc.blank(), 0.0);
6426 insta::assert_json_snapshot!(metric.loc);
6427 },
6428 );
6429 }
6430
6431 #[test]
6432 fn tcl_namespace_lloc() {
6433 check_metrics::<TclParser>(
6434 "namespace eval myns {\n set x 1\n}",
6435 "foo.tcl",
6436 |metric| {
6437 assert_eq!(metric.loc.sloc(), 3.0);
6438 assert_eq!(metric.loc.ploc(), 3.0);
6439 assert_eq!(metric.loc.lloc(), 2.0);
6440 assert_eq!(metric.loc.cloc(), 0.0);
6441 assert_eq!(metric.loc.blank(), 0.0);
6442 insta::assert_json_snapshot!(metric.loc);
6443 },
6444 );
6445 }
6446
6447 #[test]
6448 fn tcl_regexp_lloc() {
6449 check_metrics::<TclParser>("regexp {^[0-9]+$} $x", "foo.tcl", |metric| {
6450 assert_eq!(metric.loc.sloc(), 1.0);
6451 assert_eq!(metric.loc.ploc(), 1.0);
6452 assert_eq!(metric.loc.lloc(), 1.0);
6453 assert_eq!(metric.loc.cloc(), 0.0);
6454 assert_eq!(metric.loc.blank(), 0.0);
6455 insta::assert_json_snapshot!(metric.loc);
6456 });
6457 }
6458
6459 #[test]
6460 fn tcl_expr_cmd_lloc() {
6461 check_metrics::<TclParser>("expr {1 + 2}", "foo.tcl", |metric| {
6462 assert_eq!(metric.loc.sloc(), 1.0);
6463 assert_eq!(metric.loc.ploc(), 1.0);
6464 assert_eq!(metric.loc.lloc(), 1.0);
6465 assert_eq!(metric.loc.cloc(), 0.0);
6466 assert_eq!(metric.loc.blank(), 0.0);
6467 insta::assert_json_snapshot!(metric.loc);
6468 });
6469 }
6470
6471 #[test]
6472 fn tcl_no_expr_cmd_substitution_lloc() {
6473 check_metrics::<TclParser>("set x [expr {1 + 2}]", "foo.tcl", |metric| {
6475 assert_eq!(metric.loc.sloc(), 1.0);
6476 assert_eq!(metric.loc.ploc(), 1.0);
6477 assert_eq!(metric.loc.lloc(), 1.0);
6478 assert_eq!(metric.loc.cloc(), 0.0);
6479 assert_eq!(metric.loc.blank(), 0.0);
6480 insta::assert_json_snapshot!(metric.loc);
6481 });
6482 }
6483
6484 #[test]
6485 fn tcl_nested_commands_lloc() {
6486 check_metrics::<TclParser>(
6488 "proc f {x} {
6489 set y [expr {$x * 2}]
6490 puts $y
6491}",
6492 "foo.tcl",
6493 |metric| {
6494 assert_eq!(metric.loc.sloc(), 4.0);
6495 assert_eq!(metric.loc.ploc(), 4.0);
6496 assert_eq!(metric.loc.lloc(), 3.0);
6497 assert_eq!(metric.loc.cloc(), 0.0);
6498 assert_eq!(metric.loc.blank(), 0.0);
6499 insta::assert_json_snapshot!(metric.loc);
6500 },
6501 );
6502 }
6503
6504 #[test]
6505 fn tcl_command_lloc() {
6506 check_metrics::<TclParser>("puts hello", "foo.tcl", |metric| {
6507 assert_eq!(metric.loc.sloc(), 1.0);
6508 assert_eq!(metric.loc.ploc(), 1.0);
6509 assert_eq!(metric.loc.lloc(), 1.0);
6510 assert_eq!(metric.loc.cloc(), 0.0);
6511 assert_eq!(metric.loc.blank(), 0.0);
6512 insta::assert_json_snapshot!(metric.loc);
6513 });
6514 }
6515
6516 #[test]
6517 fn tcl_no_else_lloc() {
6518 check_metrics::<TclParser>(
6520 "if {1} {\n puts yes\n} else {\n puts no\n}",
6521 "foo.tcl",
6522 |metric| {
6523 assert_eq!(metric.loc.sloc(), 5.0);
6524 assert_eq!(metric.loc.ploc(), 5.0);
6525 assert_eq!(metric.loc.lloc(), 3.0);
6526 assert_eq!(metric.loc.cloc(), 0.0);
6527 assert_eq!(metric.loc.blank(), 0.0);
6528 insta::assert_json_snapshot!(metric.loc);
6529 },
6530 );
6531 }
6532
6533 #[test]
6534 fn tcl_no_finally_lloc() {
6535 check_metrics::<TclParser>(
6538 "proc f {} {\n try {\n puts hi\n } finally {\n puts done\n }\n}",
6539 "foo.tcl",
6540 |metric| {
6541 assert_eq!(
6542 metric.loc.lloc(),
6543 4.0,
6544 "finally adds 0 lloc; would be 5 if finally counted"
6545 );
6546 },
6547 );
6548 }
6549
6550 #[test]
6551 fn tcl_multiline_block() {
6552 check_metrics::<TclParser>(
6553 "proc f {x} {
6554 set a 1
6555
6556 set b 2
6557 return [expr {$a + $b}]
6558}",
6559 "foo.tcl",
6560 |metric| {
6561 assert_eq!(metric.loc.sloc(), 6.0);
6562 assert_eq!(metric.loc.ploc(), 5.0);
6563 assert_eq!(metric.loc.lloc(), 4.0);
6564 assert_eq!(metric.loc.cloc(), 0.0);
6565 assert_eq!(metric.loc.blank(), 1.0);
6566 insta::assert_json_snapshot!(metric.loc);
6567 },
6568 );
6569 }
6570
6571 #[test]
6572 fn tcl_no_string_lloc() {
6573 check_metrics::<TclParser>(
6578 "set s \"line one\nline two\nline three\"",
6579 "foo.tcl",
6580 |metric| {
6581 assert_eq!(metric.loc.sloc(), 3.0);
6582 assert_eq!(metric.loc.ploc(), 2.0);
6583 assert_eq!(metric.loc.lloc(), 1.0);
6584 assert_eq!(metric.loc.cloc(), 0.0);
6585 assert_eq!(metric.loc.blank(), 1.0);
6586 insta::assert_json_snapshot!(metric.loc);
6587 },
6588 );
6589 }
6590
6591 #[test]
6592 fn javascript_blank() {
6593 check_metrics::<JavascriptParser>(
6594 "// header comment
6595 function f() {
6596
6597 var x = 1;
6598
6599 var y = 2;
6600 }",
6601 "foo.js",
6602 |metric| {
6603 assert_eq!(metric.loc.sloc(), 7.0);
6604 assert_eq!(metric.loc.ploc(), 4.0);
6605 assert_eq!(metric.loc.lloc(), 1.0);
6606 assert_eq!(metric.loc.cloc(), 1.0);
6607 assert_eq!(metric.loc.blank(), 2.0);
6608 insta::assert_json_snapshot!(metric.loc);
6609 },
6610 );
6611 }
6612
6613 #[test]
6614 fn javascript_cloc() {
6615 check_metrics::<JavascriptParser>(
6616 "// line comment
6617 /* block
6618 comment */
6619 function f() {
6620 return 1; // inline
6621 }",
6622 "foo.js",
6623 |metric| {
6624 assert_eq!(metric.loc.sloc(), 6.0);
6625 assert_eq!(metric.loc.ploc(), 3.0);
6626 assert_eq!(metric.loc.lloc(), 2.0);
6627 assert_eq!(metric.loc.cloc(), 4.0);
6628 assert_eq!(metric.loc.blank(), 0.0);
6629 insta::assert_json_snapshot!(metric.loc);
6630 },
6631 );
6632 }
6633
6634 #[test]
6635 fn mozjs_blank() {
6636 check_metrics::<MozjsParser>(
6637 "function f() {
6638
6639 var x = 1;
6640
6641 }",
6642 "foo.js",
6643 |metric| {
6644 assert_eq!(metric.loc.sloc(), 5.0);
6645 assert_eq!(metric.loc.ploc(), 3.0);
6646 assert_eq!(metric.loc.lloc(), 1.0);
6647 assert_eq!(metric.loc.cloc(), 0.0);
6648 assert_eq!(metric.loc.blank(), 2.0);
6649 insta::assert_json_snapshot!(metric.loc);
6650 },
6651 );
6652 }
6653
6654 #[test]
6655 fn mozjs_cloc() {
6656 check_metrics::<MozjsParser>(
6657 "// header
6658 /* block comment */
6659 function f() {
6660 return 42;
6661 }",
6662 "foo.js",
6663 |metric| {
6664 assert_eq!(metric.loc.sloc(), 5.0);
6665 assert_eq!(metric.loc.ploc(), 3.0);
6666 assert_eq!(metric.loc.lloc(), 2.0);
6667 assert_eq!(metric.loc.cloc(), 2.0);
6668 assert_eq!(metric.loc.blank(), 0.0);
6669 insta::assert_json_snapshot!(metric.loc);
6670 },
6671 );
6672 }
6673
6674 #[test]
6675 fn mozjs_no_zero_blank() {
6676 check_metrics::<MozjsParser>(
6679 "function f() {
6680 var a = 1;
6681
6682 var b = 2; // trailing
6683 var c = 3; // trailing
6684}",
6685 "foo.js",
6686 |metric| {
6687 assert_eq!(metric.loc.sloc(), 6.0);
6688 assert_eq!(metric.loc.ploc(), 5.0);
6689 assert_eq!(metric.loc.cloc(), 2.0);
6690 assert_eq!(metric.loc.blank(), 1.0);
6691 insta::assert_json_snapshot!(metric.loc);
6692 },
6693 );
6694 }
6695
6696 #[test]
6697 fn mozjs_arrow_function_loc() {
6698 check_metrics::<MozjsParser>(
6699 "const add = (a, b) => a + b;
6700 const greet = name => {
6701 return 'Hello ' + name;
6702 };",
6703 "foo.js",
6704 |metric| {
6705 assert_eq!(metric.loc.sloc(), 4.0);
6706 assert_eq!(metric.loc.ploc(), 4.0);
6707 assert_eq!(metric.loc.lloc(), 2.0);
6708 assert_eq!(metric.loc.cloc(), 0.0);
6709 assert_eq!(metric.loc.blank(), 0.0);
6710 insta::assert_json_snapshot!(metric.loc);
6711 },
6712 );
6713 }
6714
6715 #[test]
6716 fn mozjs_multiple_functions_loc() {
6717 check_metrics::<MozjsParser>(
6718 "function f() {
6719 return 1;
6720 }
6721 function g() {
6722 return 2;
6723 }",
6724 "foo.js",
6725 |metric| {
6726 assert_eq!(metric.loc.sloc(), 6.0);
6727 assert_eq!(metric.loc.ploc(), 6.0);
6728 assert_eq!(metric.loc.lloc(), 4.0);
6729 assert_eq!(metric.loc.cloc(), 0.0);
6730 assert_eq!(metric.loc.blank(), 0.0);
6731 insta::assert_json_snapshot!(metric.loc);
6732 },
6733 );
6734 }
6735
6736 #[test]
6737 fn mozjs_nested_function_loc() {
6738 check_metrics::<MozjsParser>(
6739 "function outer() {
6740 function inner() {
6741 return 1;
6742 }
6743 return inner();
6744 }",
6745 "foo.js",
6746 |metric| {
6747 assert_eq!(metric.loc.sloc(), 6.0);
6748 assert_eq!(metric.loc.ploc(), 6.0);
6749 assert_eq!(metric.loc.lloc(), 4.0);
6750 assert_eq!(metric.loc.cloc(), 0.0);
6751 assert_eq!(metric.loc.blank(), 0.0);
6752 insta::assert_json_snapshot!(metric.loc);
6753 },
6754 );
6755 }
6756
6757 #[test]
6758 fn mozjs_if_lloc() {
6759 check_metrics::<MozjsParser>(
6760 "function f(x) {
6761 if (x > 0) {
6762 return 1;
6763 } else {
6764 return -1;
6765 }
6766 }",
6767 "foo.js",
6768 |metric| {
6769 assert_eq!(metric.loc.sloc(), 7.0);
6770 assert_eq!(metric.loc.ploc(), 7.0);
6771 assert_eq!(metric.loc.lloc(), 6.0);
6772 assert_eq!(metric.loc.cloc(), 0.0);
6773 assert_eq!(metric.loc.blank(), 0.0);
6774 insta::assert_json_snapshot!(metric.loc);
6775 },
6776 );
6777 }
6778
6779 #[test]
6780 fn mozjs_for_lloc() {
6781 check_metrics::<MozjsParser>(
6782 "function f(n) {
6783 var s = 0;
6784 for (var i = 0; i < n; i++) {
6785 s += i;
6786 }
6787 return s;
6788 }",
6789 "foo.js",
6790 |metric| {
6791 assert_eq!(metric.loc.sloc(), 7.0);
6792 assert_eq!(metric.loc.ploc(), 7.0);
6793 assert_eq!(metric.loc.lloc(), 5.0);
6794 assert_eq!(metric.loc.cloc(), 0.0);
6795 assert_eq!(metric.loc.blank(), 0.0);
6796 insta::assert_json_snapshot!(metric.loc);
6797 },
6798 );
6799 }
6800
6801 #[test]
6802 fn bash_blank() {
6803 check_metrics::<BashParser>(
6804 "#!/bin/bash
6805
6806 f() {
6807
6808 echo hello
6809
6810 }",
6811 "foo.sh",
6812 |metric| {
6813 assert_eq!(metric.loc.sloc(), 7.0);
6814 assert_eq!(metric.loc.ploc(), 3.0);
6815 assert_eq!(metric.loc.lloc(), 2.0);
6816 assert_eq!(metric.loc.cloc(), 1.0);
6817 assert_eq!(metric.loc.blank(), 3.0);
6818 insta::assert_json_snapshot!(metric.loc);
6819 },
6820 );
6821 }
6822
6823 #[test]
6824 fn bash_cloc() {
6825 check_metrics::<BashParser>(
6826 "# header comment
6827 f() {
6828 # body comment
6829 echo hello
6830 }",
6831 "foo.sh",
6832 |metric| {
6833 assert_eq!(metric.loc.sloc(), 5.0);
6834 assert_eq!(metric.loc.ploc(), 3.0);
6835 assert_eq!(metric.loc.lloc(), 2.0);
6836 assert_eq!(metric.loc.cloc(), 2.0);
6837 assert_eq!(metric.loc.blank(), 0.0);
6838 insta::assert_json_snapshot!(metric.loc);
6839 },
6840 );
6841 }
6842
6843 #[test]
6844 fn bash_no_zero_blank() {
6845 check_metrics::<BashParser>(
6848 "f() {
6849 echo a
6850
6851 echo b # trailing
6852 echo c # trailing
6853}",
6854 "foo.sh",
6855 |metric| {
6856 assert_eq!(metric.loc.sloc(), 6.0);
6857 assert_eq!(metric.loc.ploc(), 5.0);
6858 assert_eq!(metric.loc.cloc(), 2.0);
6859 assert_eq!(metric.loc.blank(), 1.0);
6860 insta::assert_json_snapshot!(metric.loc);
6861 },
6862 );
6863 }
6864
6865 #[test]
6866 fn bash_if_lloc() {
6867 check_metrics::<BashParser>(
6868 "f() {
6869 if [ $1 -gt 0 ]; then
6870 echo positive
6871 else
6872 echo negative
6873 fi
6874 }",
6875 "foo.sh",
6876 |metric| {
6877 assert_eq!(metric.loc.sloc(), 7.0);
6878 assert_eq!(metric.loc.ploc(), 7.0);
6879 assert_eq!(metric.loc.lloc(), 4.0);
6880 assert_eq!(metric.loc.cloc(), 0.0);
6881 assert_eq!(metric.loc.blank(), 0.0);
6882 insta::assert_json_snapshot!(metric.loc);
6883 },
6884 );
6885 }
6886
6887 #[test]
6888 fn bash_for_lloc() {
6889 check_metrics::<BashParser>(
6890 "f() {
6891 for i in 1 2 3; do
6892 echo $i
6893 done
6894 }",
6895 "foo.sh",
6896 |metric| {
6897 assert_eq!(metric.loc.sloc(), 5.0);
6898 assert_eq!(metric.loc.ploc(), 5.0);
6899 assert_eq!(metric.loc.lloc(), 3.0);
6900 assert_eq!(metric.loc.cloc(), 0.0);
6901 assert_eq!(metric.loc.blank(), 0.0);
6902 insta::assert_json_snapshot!(metric.loc);
6903 },
6904 );
6905 }
6906
6907 #[test]
6908 fn bash_while_lloc() {
6909 check_metrics::<BashParser>(
6910 "f() {
6911 local n=5
6912 while [ $n -gt 0 ]; do
6913 echo $n
6914 n=$((n - 1))
6915 done
6916 }",
6917 "foo.sh",
6918 |metric| {
6919 assert_eq!(metric.loc.sloc(), 7.0);
6920 assert_eq!(metric.loc.ploc(), 7.0);
6921 assert_eq!(metric.loc.lloc(), 4.0);
6922 assert_eq!(metric.loc.cloc(), 0.0);
6923 assert_eq!(metric.loc.blank(), 0.0);
6924 insta::assert_json_snapshot!(metric.loc);
6925 },
6926 );
6927 }
6928
6929 #[test]
6930 fn bash_case_lloc() {
6931 check_metrics::<BashParser>(
6932 "f() {
6933 case $1 in
6934 start) echo starting ;;
6935 stop) echo stopping ;;
6936 *) echo unknown ;;
6937 esac
6938 }",
6939 "foo.sh",
6940 |metric| {
6941 assert_eq!(metric.loc.sloc(), 7.0);
6942 assert_eq!(metric.loc.ploc(), 7.0);
6943 assert_eq!(metric.loc.lloc(), 5.0);
6944 assert_eq!(metric.loc.cloc(), 0.0);
6945 assert_eq!(metric.loc.blank(), 0.0);
6946 insta::assert_json_snapshot!(metric.loc);
6947 },
6948 );
6949 }
6950
6951 #[test]
6952 fn bash_multiple_functions_loc() {
6953 check_metrics::<BashParser>(
6954 "f() {
6955 echo hello
6956 }
6957 g() {
6958 echo world
6959 }",
6960 "foo.sh",
6961 |metric| {
6962 assert_eq!(metric.loc.sloc(), 6.0);
6963 assert_eq!(metric.loc.ploc(), 6.0);
6964 assert_eq!(metric.loc.lloc(), 4.0);
6965 assert_eq!(metric.loc.cloc(), 0.0);
6966 assert_eq!(metric.loc.blank(), 0.0);
6967 insta::assert_json_snapshot!(metric.loc);
6968 },
6969 );
6970 }
6971
6972 #[test]
6973 fn bash_nested_function_loc() {
6974 check_metrics::<BashParser>(
6975 "outer() {
6976 inner() {
6977 echo inner
6978 }
6979 inner
6980 echo outer
6981 }",
6982 "foo.sh",
6983 |metric| {
6984 assert_eq!(metric.loc.sloc(), 7.0);
6985 assert_eq!(metric.loc.ploc(), 7.0);
6986 assert_eq!(metric.loc.lloc(), 5.0);
6987 assert_eq!(metric.loc.cloc(), 0.0);
6988 assert_eq!(metric.loc.blank(), 0.0);
6989 insta::assert_json_snapshot!(metric.loc);
6990 },
6991 );
6992 }
6993
6994 #[test]
6995 fn bash_heredoc_loc() {
6996 check_metrics::<BashParser>(
6997 "f() {
6998 cat <<EOF
6999line1
7000line2
7001EOF
7002 }",
7003 "foo.sh",
7004 |metric| {
7005 assert_eq!(metric.loc.sloc(), 6.0);
7006 assert_eq!(metric.loc.ploc(), 5.0);
7007 assert_eq!(metric.loc.lloc(), 2.0);
7008 assert_eq!(metric.loc.cloc(), 0.0);
7009 assert_eq!(metric.loc.blank(), 1.0);
7010 insta::assert_json_snapshot!(metric.loc);
7011 },
7012 );
7013 }
7014
7015 #[test]
7016 fn kotlin_loc_blank() {
7017 check_metrics::<KotlinParser>(
7018 "fun f(): Int {
7019
7020 val x = 1
7021
7022 return x
7023 }",
7024 "foo.kt",
7025 |metric| {
7026 assert_eq!(metric.loc.sloc(), 6.0);
7027 assert_eq!(metric.loc.ploc(), 4.0);
7028 assert_eq!(metric.loc.lloc(), 2.0);
7029 assert_eq!(metric.loc.cloc(), 0.0);
7030 assert_eq!(metric.loc.blank(), 2.0);
7031 insta::assert_json_snapshot!(metric.loc);
7032 },
7033 );
7034 }
7035
7036 #[test]
7037 fn kotlin_loc_cloc() {
7038 check_metrics::<KotlinParser>(
7039 "// header comment
7040 /* block
7041 comment */
7042 fun f(): Int {
7043 return 42 // inline
7044 }",
7045 "foo.kt",
7046 |metric| {
7047 assert_eq!(metric.loc.sloc(), 6.0);
7048 assert_eq!(metric.loc.ploc(), 3.0);
7049 assert_eq!(metric.loc.lloc(), 1.0);
7050 assert_eq!(metric.loc.cloc(), 4.0);
7051 assert_eq!(metric.loc.blank(), 0.0);
7052 insta::assert_json_snapshot!(metric.loc);
7053 },
7054 );
7055 }
7056
7057 #[test]
7058 fn kotlin_loc_no_zero_blank() {
7059 check_metrics::<KotlinParser>(
7062 "fun connectToUpdateServer() {
7063 val pool = 0
7064
7065 val updateServer = -42
7066 val isConnected = false
7067 val currTry = 0
7068 val numRetries = 10 // Number of IPC connection retries before
7069 // giving up.
7070 val numTries = 20 // Number of IPC connection tries before
7071 // giving up.
7072 }",
7073 "foo.kt",
7074 |metric| {
7075 assert_eq!(metric.loc.sloc(), 11.0);
7078 assert_eq!(metric.loc.ploc(), 8.0);
7079 assert_eq!(metric.loc.cloc(), 4.0);
7080 assert_eq!(metric.loc.blank(), 1.0);
7081 insta::assert_json_snapshot!(
7082 metric.loc,
7083 @r###"
7084 {
7085 "sloc": 11.0,
7086 "ploc": 8.0,
7087 "lloc": 6.0,
7088 "cloc": 4.0,
7089 "blank": 1.0,
7090 "sloc_average": 5.5,
7091 "ploc_average": 4.0,
7092 "lloc_average": 3.0,
7093 "cloc_average": 2.0,
7094 "blank_average": 0.5,
7095 "sloc_min": 11.0,
7096 "sloc_max": 11.0,
7097 "cloc_min": 4.0,
7098 "cloc_max": 4.0,
7099 "ploc_min": 8.0,
7100 "ploc_max": 8.0,
7101 "lloc_min": 6.0,
7102 "lloc_max": 6.0,
7103 "blank_min": 1.0,
7104 "blank_max": 1.0
7105 }"###
7106 );
7107 },
7108 );
7109 }
7110
7111 #[test]
7112 fn kotlin_loc_blank_zero_sanity() {
7113 check_metrics::<KotlinParser>(
7118 "fun f(): Int {
7119 val x = 1 // x
7120 val y = 2 // y
7121 return x + y
7122 }",
7123 "foo.kt",
7124 |metric| {
7125 assert_eq!(metric.loc.sloc(), 5.0);
7126 assert_eq!(metric.loc.ploc(), 5.0);
7127 assert_eq!(metric.loc.lloc(), 3.0);
7128 assert_eq!(metric.loc.cloc(), 2.0);
7129 assert_eq!(metric.loc.blank(), 0.0);
7130 },
7131 );
7132 }
7133
7134 #[test]
7135 fn kotlin_loc_if_lloc() {
7136 check_metrics::<KotlinParser>(
7137 "fun classify(n: Int): String {
7138 if (n > 0) {
7139 return \"positive\"
7140 } else if (n < 0) {
7141 return \"negative\"
7142 }
7143 return \"zero\"
7144 }",
7145 "foo.kt",
7146 |metric| {
7147 assert_eq!(metric.loc.sloc(), 8.0);
7148 assert_eq!(metric.loc.ploc(), 8.0);
7149 assert_eq!(metric.loc.lloc(), 5.0);
7150 assert_eq!(metric.loc.cloc(), 0.0);
7151 assert_eq!(metric.loc.blank(), 0.0);
7152 insta::assert_json_snapshot!(metric.loc);
7153 },
7154 );
7155 }
7156
7157 #[test]
7158 fn kotlin_loc_for_lloc() {
7159 check_metrics::<KotlinParser>(
7160 "fun sum(n: Int): Int {
7161 var s = 0
7162 for (i in 1..n) {
7163 s += i
7164 }
7165 return s
7166 }",
7167 "foo.kt",
7168 |metric| {
7169 assert_eq!(metric.loc.sloc(), 7.0);
7170 assert_eq!(metric.loc.ploc(), 7.0);
7171 assert_eq!(metric.loc.lloc(), 4.0);
7172 assert_eq!(metric.loc.cloc(), 0.0);
7173 assert_eq!(metric.loc.blank(), 0.0);
7174 insta::assert_json_snapshot!(metric.loc);
7175 },
7176 );
7177 }
7178
7179 #[test]
7180 fn kotlin_loc_when_lloc() {
7181 check_metrics::<KotlinParser>(
7182 "fun describe(x: Int): String {
7183 return when (x) {
7184 1 -> \"one\"
7185 2 -> \"two\"
7186 else -> \"other\"
7187 }
7188 }",
7189 "foo.kt",
7190 |metric| {
7191 assert_eq!(metric.loc.sloc(), 7.0);
7192 assert_eq!(metric.loc.ploc(), 7.0);
7193 assert_eq!(metric.loc.lloc(), 2.0);
7194 assert_eq!(metric.loc.cloc(), 0.0);
7195 assert_eq!(metric.loc.blank(), 0.0);
7196 insta::assert_json_snapshot!(metric.loc);
7197 },
7198 );
7199 }
7200
7201 #[test]
7202 fn kotlin_loc_lambda_lloc() {
7203 check_metrics::<KotlinParser>(
7204 "fun f(list: List<Int>): List<Int> {
7205 return list.filter { it > 0 }
7206 .map { it * 2 }
7207 }",
7208 "foo.kt",
7209 |metric| {
7210 assert_eq!(metric.loc.sloc(), 4.0);
7211 assert_eq!(metric.loc.ploc(), 4.0);
7212 assert_eq!(metric.loc.lloc(), 1.0);
7213 assert_eq!(metric.loc.cloc(), 0.0);
7214 assert_eq!(metric.loc.blank(), 0.0);
7215 insta::assert_json_snapshot!(metric.loc);
7216 },
7217 );
7218 }
7219
7220 #[test]
7221 fn kotlin_loc_class_loc() {
7222 check_metrics::<KotlinParser>(
7223 "class Counter {
7224 private var count = 0
7225 fun increment() { count++ }
7226 fun get(): Int = count
7227 }",
7228 "foo.kt",
7229 |metric| {
7230 assert_eq!(metric.loc.sloc(), 5.0);
7231 assert_eq!(metric.loc.ploc(), 5.0);
7232 assert_eq!(metric.loc.lloc(), 1.0);
7233 assert_eq!(metric.loc.cloc(), 0.0);
7234 assert_eq!(metric.loc.blank(), 0.0);
7235 insta::assert_json_snapshot!(metric.loc);
7236 },
7237 );
7238 }
7239
7240 #[test]
7241 fn kotlin_loc_multiple_functions_loc() {
7242 check_metrics::<KotlinParser>(
7243 "fun f(): Int {
7244 return 1
7245 }
7246 fun g(): Int {
7247 return 2
7248 }",
7249 "foo.kt",
7250 |metric| {
7251 assert_eq!(metric.loc.sloc(), 6.0);
7252 assert_eq!(metric.loc.ploc(), 6.0);
7253 assert_eq!(metric.loc.lloc(), 2.0);
7254 assert_eq!(metric.loc.cloc(), 0.0);
7255 assert_eq!(metric.loc.blank(), 0.0);
7256 insta::assert_json_snapshot!(metric.loc);
7257 },
7258 );
7259 }
7260
7261 #[test]
7262 fn kotlin_loc_while_lloc() {
7263 check_metrics::<KotlinParser>(
7264 "fun countdown(n: Int) {
7265 var i = n
7266 while (i > 0) {
7267 println(i)
7268 i--
7269 }
7270 }",
7271 "foo.kt",
7272 |metric| {
7273 assert_eq!(metric.loc.sloc(), 7.0);
7274 assert_eq!(metric.loc.ploc(), 7.0);
7275 assert_eq!(metric.loc.lloc(), 3.0);
7276 assert_eq!(metric.loc.cloc(), 0.0);
7277 assert_eq!(metric.loc.blank(), 0.0);
7278 insta::assert_json_snapshot!(metric.loc);
7279 },
7280 );
7281 }
7282
7283 #[test]
7284 fn typescript_blank() {
7285 check_metrics::<TypescriptParser>(
7286 "function f(): void {
7287
7288 const x = 1;
7289
7290 }",
7291 "foo.ts",
7292 |metric| {
7293 assert_eq!(metric.loc.sloc(), 5.0);
7294 assert_eq!(metric.loc.ploc(), 3.0);
7295 assert_eq!(metric.loc.lloc(), 1.0);
7296 assert_eq!(metric.loc.cloc(), 0.0);
7297 assert_eq!(metric.loc.blank(), 2.0);
7298 insta::assert_json_snapshot!(metric.loc);
7299 },
7300 );
7301 }
7302
7303 #[test]
7304 fn typescript_cloc() {
7305 check_metrics::<TypescriptParser>(
7306 "// header
7307 /* block
7308 comment */
7309 function f(): number {
7310 return 42; // inline
7311 }",
7312 "foo.ts",
7313 |metric| {
7314 assert_eq!(metric.loc.sloc(), 6.0);
7315 assert_eq!(metric.loc.ploc(), 3.0);
7316 assert_eq!(metric.loc.lloc(), 2.0);
7317 assert_eq!(metric.loc.cloc(), 4.0);
7318 assert_eq!(metric.loc.blank(), 0.0);
7319 insta::assert_json_snapshot!(metric.loc);
7320 },
7321 );
7322 }
7323
7324 #[test]
7325 fn typescript_no_zero_blank() {
7326 check_metrics::<TypescriptParser>(
7329 "function f(): void {
7330 const a = 1;
7331
7332 const b = 2; // trailing
7333 const c = 3; // trailing
7334}",
7335 "foo.ts",
7336 |metric| {
7337 assert_eq!(metric.loc.sloc(), 6.0);
7338 assert_eq!(metric.loc.ploc(), 5.0);
7339 assert_eq!(metric.loc.cloc(), 2.0);
7340 assert_eq!(metric.loc.blank(), 1.0);
7341 insta::assert_json_snapshot!(metric.loc);
7342 },
7343 );
7344 }
7345
7346 #[test]
7347 fn typescript_if_lloc() {
7348 check_metrics::<TypescriptParser>(
7349 "function classify(n: number): string {
7350 if (n > 0) {
7351 return 'positive';
7352 } else {
7353 return 'non-positive';
7354 }
7355 }",
7356 "foo.ts",
7357 |metric| {
7358 assert_eq!(metric.loc.sloc(), 7.0);
7359 assert_eq!(metric.loc.ploc(), 7.0);
7360 assert_eq!(metric.loc.lloc(), 6.0);
7361 assert_eq!(metric.loc.cloc(), 0.0);
7362 assert_eq!(metric.loc.blank(), 0.0);
7363 insta::assert_json_snapshot!(metric.loc);
7364 },
7365 );
7366 }
7367
7368 #[test]
7369 fn typescript_for_lloc() {
7370 check_metrics::<TypescriptParser>(
7371 "function sum(n: number): number {
7372 let s = 0;
7373 for (let i = 0; i < n; i++) {
7374 s += i;
7375 }
7376 return s;
7377 }",
7378 "foo.ts",
7379 |metric| {
7380 assert_eq!(metric.loc.sloc(), 7.0);
7381 assert_eq!(metric.loc.ploc(), 7.0);
7382 assert_eq!(metric.loc.lloc(), 5.0);
7383 assert_eq!(metric.loc.cloc(), 0.0);
7384 assert_eq!(metric.loc.blank(), 0.0);
7385 insta::assert_json_snapshot!(metric.loc);
7386 },
7387 );
7388 }
7389
7390 #[test]
7391 fn typescript_while_lloc() {
7392 check_metrics::<TypescriptParser>(
7393 "function countdown(n: number): void {
7394 let i = n;
7395 while (i > 0) {
7396 console.log(i);
7397 i--;
7398 }
7399 }",
7400 "foo.ts",
7401 |metric| {
7402 assert_eq!(metric.loc.sloc(), 7.0);
7403 assert_eq!(metric.loc.ploc(), 7.0);
7404 assert_eq!(metric.loc.lloc(), 5.0);
7405 assert_eq!(metric.loc.cloc(), 0.0);
7406 assert_eq!(metric.loc.blank(), 0.0);
7407 insta::assert_json_snapshot!(metric.loc);
7408 },
7409 );
7410 }
7411
7412 #[test]
7413 fn typescript_switch_lloc() {
7414 check_metrics::<TypescriptParser>(
7415 "function describe(x: number): string {
7416 switch (x) {
7417 case 1: return 'one';
7418 case 2: return 'two';
7419 default: return 'other';
7420 }
7421 }",
7422 "foo.ts",
7423 |metric| {
7424 assert_eq!(metric.loc.sloc(), 7.0);
7425 assert_eq!(metric.loc.ploc(), 7.0);
7426 assert_eq!(metric.loc.lloc(), 5.0);
7427 assert_eq!(metric.loc.cloc(), 0.0);
7428 assert_eq!(metric.loc.blank(), 0.0);
7429 insta::assert_json_snapshot!(metric.loc);
7430 },
7431 );
7432 }
7433
7434 #[test]
7435 fn typescript_class_loc() {
7436 check_metrics::<TypescriptParser>(
7437 "class Counter {
7438 private count: number = 0;
7439 increment(): void { this.count++; }
7440 get(): number { return this.count; }
7441 }",
7442 "foo.ts",
7443 |metric| {
7444 assert_eq!(metric.loc.sloc(), 5.0);
7445 assert_eq!(metric.loc.ploc(), 5.0);
7446 assert_eq!(metric.loc.lloc(), 4.0);
7447 assert_eq!(metric.loc.cloc(), 0.0);
7448 assert_eq!(metric.loc.blank(), 0.0);
7449 insta::assert_json_snapshot!(metric.loc);
7450 },
7451 );
7452 }
7453
7454 #[test]
7455 fn typescript_arrow_function_loc() {
7456 check_metrics::<TypescriptParser>(
7457 "const add = (a: number, b: number): number => a + b;
7458 const greet = (name: string): string => {
7459 return `Hello, ${name}`;
7460 };",
7461 "foo.ts",
7462 |metric| {
7463 assert_eq!(metric.loc.sloc(), 4.0);
7464 assert_eq!(metric.loc.ploc(), 4.0);
7465 assert_eq!(metric.loc.lloc(), 2.0);
7466 assert_eq!(metric.loc.cloc(), 0.0);
7467 assert_eq!(metric.loc.blank(), 0.0);
7468 insta::assert_json_snapshot!(metric.loc);
7469 },
7470 );
7471 }
7472
7473 #[test]
7474 fn typescript_interface_loc() {
7475 check_metrics::<TypescriptParser>(
7476 "interface Shape {
7477 area(): number;
7478 perimeter(): number;
7479 }
7480 function describe(s: Shape): string {
7481 return `area=${s.area()}`;
7482 }",
7483 "foo.ts",
7484 |metric| {
7485 assert_eq!(metric.loc.sloc(), 7.0);
7486 assert_eq!(metric.loc.ploc(), 7.0);
7487 assert_eq!(metric.loc.lloc(), 2.0);
7488 assert_eq!(metric.loc.cloc(), 0.0);
7489 assert_eq!(metric.loc.blank(), 0.0);
7490 insta::assert_json_snapshot!(metric.loc);
7491 },
7492 );
7493 }
7494
7495 #[test]
7496 fn typescript_multiple_functions_loc() {
7497 check_metrics::<TypescriptParser>(
7498 "function f(): number {
7499 return 1;
7500 }
7501 function g(): number {
7502 return 2;
7503 }
7504 function h(): number {
7505 return 3;
7506 }",
7507 "foo.ts",
7508 |metric| {
7509 assert_eq!(metric.loc.sloc(), 9.0);
7510 assert_eq!(metric.loc.ploc(), 9.0);
7511 assert_eq!(metric.loc.lloc(), 6.0);
7512 assert_eq!(metric.loc.cloc(), 0.0);
7513 assert_eq!(metric.loc.blank(), 0.0);
7514 insta::assert_json_snapshot!(metric.loc);
7515 },
7516 );
7517 }
7518
7519 #[test]
7520 fn typescript_try_catch_lloc() {
7521 check_metrics::<TypescriptParser>(
7522 "function safe(x: number): number {
7523 try {
7524 return 1 / x;
7525 } catch (e) {
7526 return 0;
7527 }
7528 }",
7529 "foo.ts",
7530 |metric| {
7531 assert_eq!(metric.loc.sloc(), 7.0);
7532 assert_eq!(metric.loc.ploc(), 7.0);
7533 assert_eq!(metric.loc.lloc(), 6.0);
7534 assert_eq!(metric.loc.cloc(), 0.0);
7535 assert_eq!(metric.loc.blank(), 0.0);
7536 insta::assert_json_snapshot!(metric.loc);
7537 },
7538 );
7539 }
7540
7541 #[test]
7542 fn typescript_nested_functions_loc() {
7543 check_metrics::<TypescriptParser>(
7544 "function outer(x: number): number {
7545 function inner(y: number): number {
7546 return y * 2;
7547 }
7548 return inner(x) + 1;
7549 }",
7550 "foo.ts",
7551 |metric| {
7552 assert_eq!(metric.loc.sloc(), 6.0);
7553 assert_eq!(metric.loc.ploc(), 6.0);
7554 assert_eq!(metric.loc.lloc(), 4.0);
7555 assert_eq!(metric.loc.cloc(), 0.0);
7556 assert_eq!(metric.loc.blank(), 0.0);
7557 insta::assert_json_snapshot!(metric.loc);
7558 },
7559 );
7560 }
7561
7562 #[test]
7563 fn typescript_generic_function_loc() {
7564 check_metrics::<TypescriptParser>(
7565 "function identity<T>(value: T): T {
7566 return value;
7567 }
7568 function first<T>(arr: T[]): T | undefined {
7569 return arr[0];
7570 }",
7571 "foo.ts",
7572 |metric| {
7573 assert_eq!(metric.loc.sloc(), 6.0);
7574 assert_eq!(metric.loc.ploc(), 6.0);
7575 assert_eq!(metric.loc.lloc(), 4.0);
7576 assert_eq!(metric.loc.cloc(), 0.0);
7577 assert_eq!(metric.loc.blank(), 0.0);
7578 insta::assert_json_snapshot!(metric.loc);
7579 },
7580 );
7581 }
7582
7583 #[test]
7584 fn tsx_blank() {
7585 check_metrics::<TsxParser>(
7586 "function f(): void {
7587
7588 const x = 1;
7589
7590 }",
7591 "foo.tsx",
7592 |metric| {
7593 assert_eq!(metric.loc.sloc(), 5.0);
7594 assert_eq!(metric.loc.ploc(), 3.0);
7595 assert_eq!(metric.loc.lloc(), 1.0);
7596 assert_eq!(metric.loc.cloc(), 0.0);
7597 assert_eq!(metric.loc.blank(), 2.0);
7598 insta::assert_json_snapshot!(metric.loc);
7599 },
7600 );
7601 }
7602
7603 #[test]
7604 fn tsx_cloc() {
7605 check_metrics::<TsxParser>(
7606 "// header
7607 /* block
7608 comment */
7609 function f(): number {
7610 return 42; // inline
7611 }",
7612 "foo.tsx",
7613 |metric| {
7614 assert_eq!(metric.loc.sloc(), 6.0);
7615 assert_eq!(metric.loc.ploc(), 3.0);
7616 assert_eq!(metric.loc.lloc(), 2.0);
7617 assert_eq!(metric.loc.cloc(), 4.0);
7618 assert_eq!(metric.loc.blank(), 0.0);
7619 insta::assert_json_snapshot!(metric.loc);
7620 },
7621 );
7622 }
7623
7624 #[test]
7625 fn tsx_no_zero_blank() {
7626 check_metrics::<TsxParser>(
7629 "function f(): void {
7630 const a = 1;
7631
7632 const b = 2; // trailing
7633 const c = 3; // trailing
7634}",
7635 "foo.tsx",
7636 |metric| {
7637 assert_eq!(metric.loc.sloc(), 6.0);
7638 assert_eq!(metric.loc.ploc(), 5.0);
7639 assert_eq!(metric.loc.cloc(), 2.0);
7640 assert_eq!(metric.loc.blank(), 1.0);
7641 insta::assert_json_snapshot!(metric.loc);
7642 },
7643 );
7644 }
7645
7646 #[test]
7647 fn tsx_if_lloc() {
7648 check_metrics::<TsxParser>(
7649 "function classify(n: number): string {
7650 if (n > 0) {
7651 return 'positive';
7652 } else {
7653 return 'non-positive';
7654 }
7655 }",
7656 "foo.tsx",
7657 |metric| {
7658 assert_eq!(metric.loc.sloc(), 7.0);
7659 assert_eq!(metric.loc.ploc(), 7.0);
7660 assert_eq!(metric.loc.lloc(), 6.0);
7661 assert_eq!(metric.loc.cloc(), 0.0);
7662 assert_eq!(metric.loc.blank(), 0.0);
7663 insta::assert_json_snapshot!(metric.loc);
7664 },
7665 );
7666 }
7667
7668 #[test]
7669 fn tsx_for_lloc() {
7670 check_metrics::<TsxParser>(
7671 "function sum(n: number): number {
7672 let s = 0;
7673 for (let i = 0; i < n; i++) {
7674 s += i;
7675 }
7676 return s;
7677 }",
7678 "foo.tsx",
7679 |metric| {
7680 assert_eq!(metric.loc.sloc(), 7.0);
7681 assert_eq!(metric.loc.ploc(), 7.0);
7682 assert_eq!(metric.loc.lloc(), 5.0);
7683 assert_eq!(metric.loc.cloc(), 0.0);
7684 assert_eq!(metric.loc.blank(), 0.0);
7685 insta::assert_json_snapshot!(metric.loc);
7686 },
7687 );
7688 }
7689
7690 #[test]
7691 fn tsx_while_lloc() {
7692 check_metrics::<TsxParser>(
7693 "function countdown(n: number): void {
7694 let i = n;
7695 while (i > 0) {
7696 console.log(i);
7697 i--;
7698 }
7699 }",
7700 "foo.tsx",
7701 |metric| {
7702 assert_eq!(metric.loc.sloc(), 7.0);
7703 assert_eq!(metric.loc.ploc(), 7.0);
7704 assert_eq!(metric.loc.lloc(), 5.0);
7705 assert_eq!(metric.loc.cloc(), 0.0);
7706 assert_eq!(metric.loc.blank(), 0.0);
7707 insta::assert_json_snapshot!(metric.loc);
7708 },
7709 );
7710 }
7711
7712 #[test]
7713 fn tsx_switch_lloc() {
7714 check_metrics::<TsxParser>(
7715 "function describe(x: number): string {
7716 switch (x) {
7717 case 1: return 'one';
7718 case 2: return 'two';
7719 default: return 'other';
7720 }
7721 }",
7722 "foo.tsx",
7723 |metric| {
7724 assert_eq!(metric.loc.sloc(), 7.0);
7725 assert_eq!(metric.loc.ploc(), 7.0);
7726 assert_eq!(metric.loc.lloc(), 5.0);
7727 assert_eq!(metric.loc.cloc(), 0.0);
7728 assert_eq!(metric.loc.blank(), 0.0);
7729 insta::assert_json_snapshot!(metric.loc);
7730 },
7731 );
7732 }
7733
7734 #[test]
7735 fn tsx_class_loc() {
7736 check_metrics::<TsxParser>(
7737 "class Counter {
7738 private count: number = 0;
7739 increment(): void { this.count++; }
7740 get(): number { return this.count; }
7741 }",
7742 "foo.tsx",
7743 |metric| {
7744 assert_eq!(metric.loc.sloc(), 5.0);
7745 assert_eq!(metric.loc.ploc(), 5.0);
7746 assert_eq!(metric.loc.lloc(), 4.0);
7747 assert_eq!(metric.loc.cloc(), 0.0);
7748 assert_eq!(metric.loc.blank(), 0.0);
7749 insta::assert_json_snapshot!(metric.loc);
7750 },
7751 );
7752 }
7753
7754 #[test]
7755 fn tsx_arrow_function_loc() {
7756 check_metrics::<TsxParser>(
7757 "const add = (a: number, b: number): number => a + b;
7758 const greet = (name: string): string => {
7759 return `Hello, ${name}`;
7760 };",
7761 "foo.tsx",
7762 |metric| {
7763 assert_eq!(metric.loc.sloc(), 4.0);
7764 assert_eq!(metric.loc.ploc(), 4.0);
7765 assert_eq!(metric.loc.lloc(), 2.0);
7766 assert_eq!(metric.loc.cloc(), 0.0);
7767 assert_eq!(metric.loc.blank(), 0.0);
7768 insta::assert_json_snapshot!(metric.loc);
7769 },
7770 );
7771 }
7772
7773 #[test]
7774 fn tsx_multiple_functions_loc() {
7775 check_metrics::<TsxParser>(
7776 "function f(): number {
7777 return 1;
7778 }
7779 function g(): number {
7780 return 2;
7781 }
7782 function h(): number {
7783 return 3;
7784 }",
7785 "foo.tsx",
7786 |metric| {
7787 assert_eq!(metric.loc.sloc(), 9.0);
7788 assert_eq!(metric.loc.ploc(), 9.0);
7789 assert_eq!(metric.loc.lloc(), 6.0);
7790 assert_eq!(metric.loc.cloc(), 0.0);
7791 assert_eq!(metric.loc.blank(), 0.0);
7792 insta::assert_json_snapshot!(metric.loc);
7793 },
7794 );
7795 }
7796
7797 #[test]
7798 fn tsx_try_catch_lloc() {
7799 check_metrics::<TsxParser>(
7800 "function safe(x: number): number {
7801 try {
7802 return 1 / x;
7803 } catch (e) {
7804 return 0;
7805 }
7806 }",
7807 "foo.tsx",
7808 |metric| {
7809 assert_eq!(metric.loc.sloc(), 7.0);
7810 assert_eq!(metric.loc.ploc(), 7.0);
7811 assert_eq!(metric.loc.lloc(), 6.0);
7812 assert_eq!(metric.loc.cloc(), 0.0);
7813 assert_eq!(metric.loc.blank(), 0.0);
7814 insta::assert_json_snapshot!(metric.loc);
7815 },
7816 );
7817 }
7818
7819 #[test]
7820 fn tsx_nested_functions_loc() {
7821 check_metrics::<TsxParser>(
7822 "function outer(x: number): number {
7823 function inner(y: number): number {
7824 return y * 2;
7825 }
7826 return inner(x) + 1;
7827 }",
7828 "foo.tsx",
7829 |metric| {
7830 assert_eq!(metric.loc.sloc(), 6.0);
7831 assert_eq!(metric.loc.ploc(), 6.0);
7832 assert_eq!(metric.loc.lloc(), 4.0);
7833 assert_eq!(metric.loc.cloc(), 0.0);
7834 assert_eq!(metric.loc.blank(), 0.0);
7835 insta::assert_json_snapshot!(metric.loc);
7836 },
7837 );
7838 }
7839
7840 #[test]
7841 fn tsx_interface_loc() {
7842 check_metrics::<TsxParser>(
7843 "interface Shape {
7844 area(): number;
7845 perimeter(): number;
7846 }
7847 function describe(s: Shape): string {
7848 return `area=${s.area()}`;
7849 }",
7850 "foo.tsx",
7851 |metric| {
7852 assert_eq!(metric.loc.sloc(), 7.0);
7853 assert_eq!(metric.loc.ploc(), 7.0);
7854 assert_eq!(metric.loc.lloc(), 2.0);
7855 assert_eq!(metric.loc.cloc(), 0.0);
7856 assert_eq!(metric.loc.blank(), 0.0);
7857 insta::assert_json_snapshot!(metric.loc);
7858 },
7859 );
7860 }
7861
7862 #[test]
7863 fn tsx_generic_function_loc() {
7864 check_metrics::<TsxParser>(
7865 "function identity<T>(value: T): T {
7866 return value;
7867 }
7868 function first<T>(arr: T[]): T | undefined {
7869 return arr[0];
7870 }",
7871 "foo.tsx",
7872 |metric| {
7873 assert_eq!(metric.loc.sloc(), 6.0);
7874 assert_eq!(metric.loc.ploc(), 6.0);
7875 assert_eq!(metric.loc.lloc(), 4.0);
7876 assert_eq!(metric.loc.cloc(), 0.0);
7877 assert_eq!(metric.loc.blank(), 0.0);
7878 insta::assert_json_snapshot!(metric.loc);
7879 },
7880 );
7881 }
7882
7883 #[test]
7884 fn php_blank() {
7885 check_metrics::<PhpParser>(
7886 "<?php
7887
7888$a = 1;
7889
7890$b = 2;
7891
7892",
7893 "foo.php",
7894 |metric| {
7895 assert_eq!(metric.loc.sloc(), 5.0);
7896 assert_eq!(metric.loc.ploc(), 3.0);
7897 assert_eq!(metric.loc.lloc(), 2.0);
7898 assert_eq!(metric.loc.cloc(), 0.0);
7899 assert_eq!(metric.loc.blank(), 2.0);
7900 insta::assert_json_snapshot!(metric.loc);
7901 },
7902 );
7903 }
7904
7905 #[test]
7906 fn php_no_zero_blank() {
7907 check_metrics::<PhpParser>(
7910 "<?php
7911$a = 1;
7912
7913$b = 2; // trailing
7914$c = 3; // trailing
7915",
7916 "foo.php",
7917 |metric| {
7918 assert_eq!(metric.loc.sloc(), 5.0);
7919 assert_eq!(metric.loc.ploc(), 4.0);
7920 assert_eq!(metric.loc.cloc(), 2.0);
7921 assert_eq!(metric.loc.blank(), 1.0);
7922 insta::assert_json_snapshot!(metric.loc);
7923 },
7924 );
7925 }
7926
7927 #[test]
7928 fn php_cloc_double_slash() {
7929 check_metrics::<PhpParser>(
7930 "<?php
7931// first
7932// second
7933$a = 1; // trailing",
7934 "foo.php",
7935 |metric| {
7936 assert_eq!(metric.loc.sloc(), 4.0);
7937 assert_eq!(metric.loc.ploc(), 2.0);
7938 assert_eq!(metric.loc.lloc(), 1.0);
7939 assert_eq!(metric.loc.cloc(), 3.0);
7940 assert_eq!(metric.loc.blank(), 0.0);
7941 insta::assert_json_snapshot!(metric.loc);
7942 },
7943 );
7944 }
7945
7946 #[test]
7947 fn php_cloc_hash() {
7948 check_metrics::<PhpParser>(
7949 "<?php
7950# first
7951# second
7952$a = 1;",
7953 "foo.php",
7954 |metric| {
7955 assert_eq!(metric.loc.sloc(), 4.0);
7956 assert_eq!(metric.loc.ploc(), 2.0);
7957 assert_eq!(metric.loc.lloc(), 1.0);
7958 assert_eq!(metric.loc.cloc(), 2.0);
7959 assert_eq!(metric.loc.blank(), 0.0);
7960 insta::assert_json_snapshot!(metric.loc);
7961 },
7962 );
7963 }
7964
7965 #[test]
7966 fn php_cloc_block() {
7967 check_metrics::<PhpParser>(
7968 "<?php
7969/*
7970 * block
7971 * comment
7972 */
7973$a = 1;",
7974 "foo.php",
7975 |metric| {
7976 assert_eq!(metric.loc.sloc(), 6.0);
7977 assert_eq!(metric.loc.ploc(), 2.0);
7978 assert_eq!(metric.loc.lloc(), 1.0);
7979 assert_eq!(metric.loc.cloc(), 4.0);
7980 assert_eq!(metric.loc.blank(), 0.0);
7981 insta::assert_json_snapshot!(metric.loc);
7982 },
7983 );
7984 }
7985
7986 #[test]
7987 fn php_lloc() {
7988 check_metrics::<PhpParser>(
7990 "<?php
7991$a = 1;
7992if ($a > 0) {
7993 echo $a;
7994}",
7995 "foo.php",
7996 |metric| {
7997 assert_eq!(metric.loc.sloc(), 5.0);
7998 assert_eq!(metric.loc.ploc(), 5.0);
7999 assert_eq!(metric.loc.lloc(), 3.0);
8000 assert_eq!(metric.loc.cloc(), 0.0);
8001 assert_eq!(metric.loc.blank(), 0.0);
8002 insta::assert_json_snapshot!(metric.loc);
8003 },
8004 );
8005 }
8006
8007 #[test]
8008 fn php_no_parenthesized_expression_lloc() {
8009 check_metrics::<PhpParser>(
8012 "<?php
8013$a = (1 + 2);",
8014 "foo.php",
8015 |metric| {
8016 assert_eq!(metric.loc.sloc(), 2.0);
8017 assert_eq!(metric.loc.ploc(), 2.0);
8018 assert_eq!(metric.loc.lloc(), 1.0);
8019 assert_eq!(metric.loc.cloc(), 0.0);
8020 assert_eq!(metric.loc.blank(), 0.0);
8021 insta::assert_json_snapshot!(metric.loc);
8022 },
8023 );
8024 }
8025
8026 #[test]
8027 fn php_no_compound_statement_lloc() {
8028 check_metrics::<PhpParser>(
8030 "<?php
8031function f(): void {
8032 $a = 1;
8033}",
8034 "foo.php",
8035 |metric| {
8036 assert_eq!(metric.loc.sloc(), 4.0);
8037 assert_eq!(metric.loc.ploc(), 4.0);
8038 assert_eq!(metric.loc.lloc(), 1.0);
8039 assert_eq!(metric.loc.cloc(), 0.0);
8040 assert_eq!(metric.loc.blank(), 0.0);
8041 insta::assert_json_snapshot!(metric.loc);
8042 },
8043 );
8044 }
8045
8046 #[test]
8047 fn php_no_colon_block_lloc() {
8048 check_metrics::<PhpParser>(
8051 "<?php
8052if (true):
8053 $a = 1;
8054endif;",
8055 "foo.php",
8056 |metric| {
8057 assert_eq!(metric.loc.sloc(), 4.0);
8058 assert_eq!(metric.loc.ploc(), 4.0);
8059 assert_eq!(metric.loc.lloc(), 2.0);
8060 assert_eq!(metric.loc.cloc(), 0.0);
8061 assert_eq!(metric.loc.blank(), 0.0);
8062 insta::assert_json_snapshot!(metric.loc);
8063 },
8064 );
8065 }
8066
8067 #[test]
8068 fn php_no_else_clause_lloc() {
8069 check_metrics::<PhpParser>(
8071 "<?php
8072if ($x) {
8073 $a = 1;
8074} elseif ($y) {
8075 $a = 2;
8076} else {
8077 $a = 3;
8078}",
8079 "foo.php",
8080 |metric| {
8081 assert_eq!(metric.loc.sloc(), 8.0);
8082 assert_eq!(metric.loc.ploc(), 8.0);
8083 assert_eq!(metric.loc.lloc(), 4.0);
8084 assert_eq!(metric.loc.cloc(), 0.0);
8085 assert_eq!(metric.loc.blank(), 0.0);
8086 insta::assert_json_snapshot!(metric.loc);
8087 },
8088 );
8089 }
8090
8091 #[test]
8092 fn php_no_case_statement_lloc() {
8093 check_metrics::<PhpParser>(
8096 "<?php
8097switch ($x) {
8098 case 1:
8099 $a = 1;
8100 break;
8101 case 2:
8102 $a = 2;
8103 break;
8104 default:
8105 $a = 0;
8106}",
8107 "foo.php",
8108 |metric| {
8109 assert_eq!(metric.loc.sloc(), 11.0);
8110 assert_eq!(metric.loc.ploc(), 11.0);
8111 assert_eq!(metric.loc.lloc(), 6.0);
8112 assert_eq!(metric.loc.cloc(), 0.0);
8113 assert_eq!(metric.loc.blank(), 0.0);
8114 insta::assert_json_snapshot!(metric.loc);
8115 },
8116 );
8117 }
8118
8119 #[test]
8120 fn php_no_match_arm_lloc() {
8121 check_metrics::<PhpParser>(
8124 "<?php
8125$a = match ($x) {
8126 1 => 'one',
8127 2 => 'two',
8128 default => 'other',
8129};",
8130 "foo.php",
8131 |metric| {
8132 assert_eq!(metric.loc.sloc(), 6.0);
8133 assert_eq!(metric.loc.ploc(), 6.0);
8134 assert_eq!(metric.loc.lloc(), 1.0);
8135 assert_eq!(metric.loc.cloc(), 0.0);
8136 assert_eq!(metric.loc.blank(), 0.0);
8137 insta::assert_json_snapshot!(metric.loc);
8138 },
8139 );
8140 }
8141
8142 #[test]
8143 fn php_no_throw_in_expression_lloc() {
8144 check_metrics::<PhpParser>(
8147 "<?php
8148$x = $y ?? throw new \\Exception('nope');",
8149 "foo.php",
8150 |metric| {
8151 assert_eq!(metric.loc.sloc(), 2.0);
8152 assert_eq!(metric.loc.ploc(), 2.0);
8153 assert_eq!(metric.loc.lloc(), 1.0);
8154 assert_eq!(metric.loc.cloc(), 0.0);
8155 assert_eq!(metric.loc.blank(), 0.0);
8156 insta::assert_json_snapshot!(metric.loc);
8157 },
8158 );
8159 }
8160
8161 #[test]
8162 fn php_no_closure_in_assignment_lloc() {
8163 check_metrics::<PhpParser>(
8167 "<?php
8168$f = function (): int {
8169 return 42;
8170};",
8171 "foo.php",
8172 |metric| {
8173 assert_eq!(metric.loc.sloc(), 4.0);
8174 assert_eq!(metric.loc.ploc(), 4.0);
8175 assert_eq!(metric.loc.lloc(), 2.0);
8176 assert_eq!(metric.loc.cloc(), 0.0);
8177 assert_eq!(metric.loc.blank(), 0.0);
8178 insta::assert_json_snapshot!(metric.loc);
8179 },
8180 );
8181 }
8182
8183 #[test]
8184 fn php_for_lloc() {
8185 check_metrics::<PhpParser>(
8188 "<?php
8189for ($i = 0; $i < 10; $i++) {
8190 echo $i;
8191}",
8192 "foo.php",
8193 |metric| {
8194 assert_eq!(metric.loc.sloc(), 4.0);
8195 assert_eq!(metric.loc.ploc(), 4.0);
8196 assert_eq!(metric.loc.lloc(), 2.0);
8197 assert_eq!(metric.loc.cloc(), 0.0);
8198 assert_eq!(metric.loc.blank(), 0.0);
8199 insta::assert_json_snapshot!(metric.loc);
8200 },
8201 );
8202 }
8203
8204 #[test]
8205 fn php_foreach_lloc() {
8206 check_metrics::<PhpParser>(
8207 "<?php
8208foreach ($items as $k => $v) {
8209 echo $v;
8210}",
8211 "foo.php",
8212 |metric| {
8213 assert_eq!(metric.loc.sloc(), 4.0);
8214 assert_eq!(metric.loc.ploc(), 4.0);
8215 assert_eq!(metric.loc.lloc(), 2.0);
8216 assert_eq!(metric.loc.cloc(), 0.0);
8217 assert_eq!(metric.loc.blank(), 0.0);
8218 insta::assert_json_snapshot!(metric.loc);
8219 },
8220 );
8221 }
8222
8223 #[test]
8224 fn php_try_lloc() {
8225 check_metrics::<PhpParser>(
8226 "<?php
8227try {
8228 $a = 1;
8229} catch (\\Exception $e) {
8230 $a = 0;
8231} finally {
8232 $b = 2;
8233}",
8234 "foo.php",
8235 |metric| {
8236 assert_eq!(metric.loc.sloc(), 8.0);
8237 assert_eq!(metric.loc.ploc(), 8.0);
8238 assert_eq!(metric.loc.lloc(), 4.0);
8239 assert_eq!(metric.loc.cloc(), 0.0);
8240 assert_eq!(metric.loc.blank(), 0.0);
8241 insta::assert_json_snapshot!(metric.loc);
8242 },
8243 );
8244 }
8245
8246 #[test]
8247 fn php_class_loc() {
8248 check_metrics::<PhpParser>(
8249 "<?php
8250class A {
8251 public int $x = 0;
8252 private const Y = 1;
8253 public function f(): int {
8254 return $this->x;
8255 }
8256}",
8257 "foo.php",
8258 |metric| {
8259 assert_eq!(metric.loc.sloc(), 8.0);
8260 assert_eq!(metric.loc.ploc(), 8.0);
8261 assert_eq!(metric.loc.lloc(), 3.0);
8262 assert_eq!(metric.loc.cloc(), 0.0);
8263 assert_eq!(metric.loc.blank(), 0.0);
8264 insta::assert_json_snapshot!(metric.loc);
8265 },
8266 );
8267 }
8268
8269 #[test]
8270 fn php_namespace_use_lloc() {
8271 check_metrics::<PhpParser>(
8272 "<?php
8273namespace App;
8274use App\\Foo;
8275use App\\Bar;
8276$a = 1;",
8277 "foo.php",
8278 |metric| {
8279 assert_eq!(metric.loc.sloc(), 5.0);
8280 assert_eq!(metric.loc.ploc(), 5.0);
8281 assert_eq!(metric.loc.lloc(), 3.0);
8282 assert_eq!(metric.loc.cloc(), 0.0);
8283 assert_eq!(metric.loc.blank(), 0.0);
8284 insta::assert_json_snapshot!(metric.loc);
8285 },
8286 );
8287 }
8288
8289 #[test]
8290 fn php_general_loc() {
8291 check_metrics::<PhpParser>(
8292 "<?php
8293// header
8294namespace App;
8295use App\\Foo;
8296
8297class Bar {
8298 public int $n = 0;
8299
8300 public function add(int $x): int {
8301 if ($x > 0) {
8302 return $this->n + $x;
8303 }
8304 return $this->n;
8305 }
8306}",
8307 "foo.php",
8308 |metric| {
8309 assert_eq!(metric.loc.sloc(), 15.0);
8310 assert_eq!(metric.loc.ploc(), 12.0);
8311 assert_eq!(metric.loc.lloc(), 5.0);
8312 assert_eq!(metric.loc.cloc(), 1.0);
8313 assert_eq!(metric.loc.blank(), 2.0);
8314 insta::assert_json_snapshot!(metric.loc);
8315 },
8316 );
8317 }
8318
8319 #[test]
8320 fn php_match_in_expression_lloc() {
8321 check_metrics::<PhpParser>(
8324 "<?php
8325$y = 10 + match ($x) { 1 => 2, default => 0 };",
8326 "foo.php",
8327 |metric| {
8328 assert_eq!(metric.loc.sloc(), 2.0);
8329 assert_eq!(metric.loc.ploc(), 2.0);
8330 assert_eq!(metric.loc.lloc(), 1.0);
8331 assert_eq!(metric.loc.cloc(), 0.0);
8332 assert_eq!(metric.loc.blank(), 0.0);
8333 insta::assert_json_snapshot!(metric.loc);
8334 },
8335 );
8336 }
8337
8338 #[test]
8339 fn php_html_island_ploc() {
8340 check_metrics::<PhpParser>(
8346 "<?php if ($cond): ?>
8347<div>hello</div>
8348<p>world</p>
8349<?php endif; ?>",
8350 "foo.php",
8351 |metric| {
8352 assert_eq!(metric.loc.sloc(), 4.0);
8353 assert_eq!(metric.loc.ploc(), 3.0);
8354 assert_eq!(metric.loc.lloc(), 1.0);
8355 assert_eq!(metric.loc.cloc(), 0.0);
8356 assert_eq!(metric.loc.blank(), 1.0);
8357 insta::assert_json_snapshot!(metric.loc);
8358 },
8359 );
8360 }
8361
8362 #[test]
8363 fn php_short_echo_tag_ploc() {
8364 check_metrics::<PhpParser>("<p><?= $name ?></p>", "foo.php", |metric| {
8368 assert_eq!(metric.loc.sloc(), 1.0);
8369 assert_eq!(metric.loc.ploc(), 1.0);
8370 assert_eq!(metric.loc.lloc(), 1.0);
8371 assert_eq!(metric.loc.cloc(), 0.0);
8372 assert_eq!(metric.loc.blank(), 0.0);
8373 insta::assert_json_snapshot!(metric.loc);
8374 });
8375 }
8376
8377 #[test]
8378 fn elixir_blank() {
8379 check_metrics::<ElixirParser>(
8381 "defmodule Foo do\n\n def a, do: :a\n\n def b, do: :b\nend\n",
8382 "foo.ex",
8383 |metric| {
8384 assert_eq!(metric.loc.sloc(), 6.0);
8385 assert_eq!(metric.loc.ploc(), 4.0);
8386 assert_eq!(metric.loc.lloc(), 3.0);
8387 assert_eq!(metric.loc.cloc(), 0.0);
8388 assert_eq!(metric.loc.blank(), 2.0);
8389 insta::assert_json_snapshot!(
8390 metric.loc,
8391 @r#"
8392 {
8393 "sloc": 6.0,
8394 "ploc": 4.0,
8395 "lloc": 3.0,
8396 "cloc": 0.0,
8397 "blank": 2.0,
8398 "sloc_average": 1.5,
8399 "ploc_average": 1.0,
8400 "lloc_average": 0.75,
8401 "cloc_average": 0.0,
8402 "blank_average": 0.5,
8403 "sloc_min": 6.0,
8404 "sloc_max": 6.0,
8405 "cloc_min": 0.0,
8406 "cloc_max": 0.0,
8407 "ploc_min": 4.0,
8408 "ploc_max": 4.0,
8409 "lloc_min": 3.0,
8410 "lloc_max": 3.0,
8411 "blank_min": 2.0,
8412 "blank_max": 2.0
8413 }
8414 "#
8415 );
8416 },
8417 );
8418 }
8419
8420 #[test]
8421 fn elixir_no_zero_blank() {
8422 check_metrics::<ElixirParser>(
8425 "defmodule Foo do\n def f, do: :ok\n\n def g, do: :ok # trailing\n def h, do: :ok # trailing\nend\n",
8426 "foo.ex",
8427 |metric| {
8428 assert_eq!(metric.loc.sloc(), 6.0);
8429 assert_eq!(metric.loc.ploc(), 5.0);
8430 assert_eq!(metric.loc.cloc(), 2.0);
8431 assert_eq!(metric.loc.blank(), 1.0);
8432 },
8433 );
8434 }
8435
8436 #[test]
8437 fn elixir_blank_zero_sanity() {
8438 check_metrics::<ElixirParser>(
8441 "defmodule Foo do\n def f, do: :ok\nend\n",
8442 "foo.ex",
8443 |metric| {
8444 assert_eq!(metric.loc.blank(), 0.0);
8445 },
8446 );
8447 }
8448
8449 #[test]
8450 fn elixir_cloc() {
8451 check_metrics::<ElixirParser>(
8454 "# top\ndefmodule Foo do\n # body\n def f, do: :ok # trailing\nend\n",
8455 "foo.ex",
8456 |metric| {
8457 assert_eq!(metric.loc.cloc(), 3.0);
8458 },
8459 );
8460 }
8461
8462 #[test]
8463 fn elixir_lloc() {
8464 check_metrics::<ElixirParser>(
8469 "defmodule Foo do\n def a, do: 1\n def b, do: 2\nend\n",
8470 "foo.ex",
8471 |metric| {
8472 assert_eq!(metric.loc.lloc(), 3.0);
8473 },
8474 );
8475 }
8476
8477 #[test]
8478 fn elixir_no_nested_call_lloc() {
8479 check_metrics::<ElixirParser>(
8483 "defmodule Foo do\n def f do\n IO.puts(Enum.join([1, 2, 3], \", \"))\n end\nend\n",
8484 "foo.ex",
8485 |metric| {
8486 assert_eq!(metric.loc.lloc(), 3.0);
8487 },
8488 );
8489 }
8490
8491 #[test]
8492 fn elixir_no_binary_operator_inside_call_lloc() {
8493 check_metrics::<ElixirParser>(
8499 "defmodule Foo do\n def f(a, b) do\n IO.puts(a + b)\n end\nend\n",
8500 "foo.ex",
8501 |metric| {
8502 assert_eq!(metric.loc.lloc(), 3.0);
8503 },
8504 );
8505 }
8506
8507 #[test]
8508 fn elixir_stab_clause_counts_lloc() {
8509 check_metrics::<ElixirParser>(
8513 "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",
8514 "foo.ex",
8515 |metric| {
8516 assert_eq!(metric.loc.lloc(), 6.0);
8517 },
8518 );
8519 }
8520
8521 #[test]
8522 fn elixir_no_comment_lloc() {
8523 check_metrics::<ElixirParser>(
8528 "# leading\ndefmodule Foo do\n # inside\n def f, do: :ok\n # trailing\nend\n",
8529 "foo.ex",
8530 |metric| {
8531 assert_eq!(metric.loc.lloc(), 2.0);
8532 },
8533 );
8534 }
8535
8536 #[test]
8537 fn elixir_no_do_token_lloc() {
8538 check_metrics::<ElixirParser>("defmodule Foo do\n :ok\nend\n", "foo.ex", |metric| {
8543 assert_eq!(metric.loc.lloc(), 2.0);
8546 });
8547 }
8548
8549 #[test]
8550 fn elixir_no_keyword_pair_lloc() {
8551 check_metrics::<ElixirParser>(
8555 "defmodule Foo do\n def add(a, b), do: a + b\nend\n",
8556 "foo.ex",
8557 |metric| {
8558 assert_eq!(metric.loc.lloc(), 2.0);
8560 },
8561 );
8562 }
8563
8564 #[test]
8565 fn elixir_no_string_content_lloc() {
8566 check_metrics::<ElixirParser>(
8571 "defmodule Foo do\n @moduledoc \"\"\"\n line one\n line two\n \"\"\"\n def f, do: :ok\nend\n",
8572 "foo.ex",
8573 |metric| {
8574 assert_eq!(metric.loc.lloc(), 3.0);
8576 },
8577 );
8578 }
8579
8580 #[test]
8581 fn elixir_rescue_arm_counts_lloc() {
8582 check_metrics::<ElixirParser>(
8589 "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",
8590 "foo.ex",
8591 |metric| {
8592 assert_eq!(metric.loc.lloc(), 7.0);
8593 },
8594 );
8595 }
8596
8597 #[test]
8598 fn elixir_no_arg_punctuation_lloc() {
8599 check_metrics::<ElixirParser>(
8603 "defmodule Foo do\n def add(a, b, c, d) do\n a + b + c + d\n end\nend\n",
8604 "foo.ex",
8605 |metric| {
8606 assert_eq!(metric.loc.lloc(), 3.0);
8608 },
8609 );
8610 }
8611
8612 #[test]
8613 fn elixir_no_list_element_lloc() {
8614 check_metrics::<ElixirParser>(
8617 "defmodule Foo do\n def f do\n [:a, :b, :c, :d]\n end\nend\n",
8618 "foo.ex",
8619 |metric| {
8620 assert_eq!(metric.loc.lloc(), 3.0);
8622 },
8623 );
8624 }
8625
8626 #[test]
8627 fn elixir_no_map_field_lloc() {
8628 check_metrics::<ElixirParser>(
8630 "defmodule Foo do\n def f do\n %{a: 1, b: 2, c: 3}\n end\nend\n",
8631 "foo.ex",
8632 |metric| {
8633 assert_eq!(metric.loc.lloc(), 3.0);
8634 },
8635 );
8636 }
8637
8638 #[test]
8639 fn elixir_anonymous_fn_body_lloc() {
8640 check_metrics::<ElixirParser>(
8648 "defmodule Foo do\n def f do\n add = fn x -> x + 1 end\n add\n end\nend\n",
8649 "foo.ex",
8650 |metric| {
8651 assert_eq!(metric.loc.lloc(), 5.0);
8652 },
8653 );
8654 }
8655
8656 #[test]
8657 fn ruby_blank() {
8658 check_metrics::<RubyParser>("def foo\n a = 1\n\n a + 1\nend\n", "foo.rb", |metric| {
8662 assert_eq!(metric.loc.blank(), 1.0);
8663 });
8664 }
8665
8666 #[test]
8667 fn ruby_no_zero_blank() {
8668 check_metrics::<RubyParser>(
8674 "def foo # entry\n pool = 0\n\n server = -42 # negative\n\n ok = false\nend\n",
8675 "foo.rb",
8676 |metric| {
8677 assert_eq!(metric.loc.blank(), 2.0);
8678 },
8679 );
8680 }
8681
8682 #[test]
8683 fn ruby_cloc() {
8684 check_metrics::<RubyParser>(
8686 "# one\n# two\n# three\ndef foo\nend\n",
8687 "foo.rb",
8688 |metric| {
8689 assert_eq!(metric.loc.cloc(), 3.0);
8690 },
8691 );
8692 }
8693
8694 #[test]
8695 fn ruby_lloc() {
8696 check_metrics::<RubyParser>(
8700 "def foo(a)\n if a\n a += 1\n end\n while a > 0\n a -= 1\n end\nend\n",
8701 "foo.rb",
8702 |metric| {
8703 assert_eq!(metric.loc.lloc(), 3.0);
8704 },
8705 );
8706 }
8707
8708 #[test]
8709 fn ruby_no_call_lloc() {
8710 check_metrics::<RubyParser>(
8715 "def foo\n puts 'hello'\n puts 'world'\nend\n",
8716 "foo.rb",
8717 |metric| {
8718 assert_eq!(metric.loc.lloc(), 1.0);
8719 },
8720 );
8721 }
8722
8723 #[test]
8724 fn ruby_no_assignment_lloc() {
8725 check_metrics::<RubyParser>(
8728 "def foo\n a = 1\n b = 2\n c = a + b\nend\n",
8729 "foo.rb",
8730 |metric| {
8731 assert_eq!(metric.loc.lloc(), 1.0);
8732 },
8733 );
8734 }
8735
8736 #[test]
8737 fn ruby_modifier_lloc() {
8738 check_metrics::<RubyParser>(
8744 "def foo(a)\n return a if a.nil?\n a -= 1 while a > 0\n parse(a) rescue nil\nend\n",
8745 "foo.rb",
8746 |metric| {
8747 assert_eq!(metric.loc.lloc(), 5.0);
8748 },
8749 );
8750 }
8751
8752 #[test]
8753 fn ruby_class_lloc() {
8754 check_metrics::<RubyParser>(
8756 "module M\n class C\n def foo\n end\n def bar\n end\n end\nend\n",
8757 "foo.rb",
8758 |metric| {
8759 assert_eq!(metric.loc.lloc(), 4.0);
8760 },
8761 );
8762 }
8763
8764 #[test]
8765 fn ruby_begin_rescue_lloc() {
8766 check_metrics::<RubyParser>(
8770 "def foo\n begin\n risky\n rescue StandardError\n nil\n end\nend\n",
8771 "foo.rb",
8772 |metric| {
8773 assert_eq!(metric.loc.lloc(), 2.0);
8774 },
8775 );
8776 }
8777
8778 #[test]
8779 fn ruby_nested_defs_lloc() {
8780 check_metrics::<RubyParser>(
8783 "def outer\n def inner\n 1\n end\nend\n",
8784 "foo.rb",
8785 |metric| {
8786 assert_eq!(metric.loc.lloc(), 2.0);
8787 },
8788 );
8789 }
8790
8791 #[test]
8792 fn ruby_no_block_body_lloc() {
8793 check_metrics::<RubyParser>(
8799 "[1, 2, 3].each do |x|\n puts x\nend\n",
8800 "foo.rb",
8801 |metric| {
8802 assert_eq!(metric.loc.lloc(), 0.0);
8803 },
8804 );
8805 }
8806
8807 #[test]
8808 fn ruby_no_lambda_body_lloc() {
8809 check_metrics::<RubyParser>("add = ->(a, b) {\n a + b\n}\n", "foo.rb", |metric| {
8814 assert_eq!(metric.loc.lloc(), 0.0);
8815 });
8816 }
8817
8818 #[test]
8819 fn ruby_heredoc_lloc_and_blank() {
8820 check_metrics::<RubyParser>(
8829 "def foo\n msg = <<~TXT\n one\n two\n TXT\n msg\nend\n",
8830 "foo.rb",
8831 |metric| {
8832 assert_eq!(metric.loc.sloc(), 7.0);
8833 assert_eq!(metric.loc.ploc(), 5.0);
8834 assert_eq!(metric.loc.lloc(), 1.0);
8835 assert_eq!(metric.loc.blank(), 2.0);
8836 },
8837 );
8838 }
8839
8840 #[test]
8841 fn ruby_semicolon_multistatement_lloc_undercount() {
8842 check_metrics::<RubyParser>(
8849 "def foo\n a = 1; b = 2; a + b\nend\n",
8850 "foo.rb",
8851 |metric| {
8852 assert_eq!(metric.loc.lloc(), 1.0);
8853 },
8854 );
8855 }
8856
8857 #[test]
8858 fn ruby_ploc_skips_comments_and_blanks() {
8859 check_metrics::<RubyParser>("# header\n\ndef foo\n a = 1\nend\n", "foo.rb", |metric| {
8862 assert_eq!(metric.loc.ploc(), 3.0);
8863 assert_eq!(metric.loc.cloc(), 1.0);
8864 assert_eq!(metric.loc.blank(), 1.0);
8865 });
8866 }
8867
8868 #[test]
8877 fn python_nested_def_lloc() {
8878 check_metrics::<PythonParser>(
8882 "def outer():\n def inner():\n return 1\n return inner()\n",
8883 "foo.py",
8884 |metric| {
8885 assert_eq!(metric.loc.sloc(), 4.0);
8886 assert_eq!(metric.loc.ploc(), 4.0);
8887 assert_eq!(metric.loc.lloc(), 2.0);
8888 assert_eq!(metric.loc.cloc(), 0.0);
8889 assert_eq!(metric.loc.blank(), 0.0);
8890 insta::assert_json_snapshot!(metric.loc);
8891 },
8892 );
8893 }
8894
8895 #[test]
8896 fn python_lambda_in_def_lloc() {
8897 check_metrics::<PythonParser>(
8901 "def outer():\n f = lambda x: x + 1\n return f(2)\n",
8902 "foo.py",
8903 |metric| {
8904 assert_eq!(metric.loc.sloc(), 3.0);
8905 assert_eq!(metric.loc.ploc(), 3.0);
8906 assert_eq!(metric.loc.lloc(), 2.0);
8907 assert_eq!(metric.loc.cloc(), 0.0);
8908 assert_eq!(metric.loc.blank(), 0.0);
8909 insta::assert_json_snapshot!(metric.loc);
8910 },
8911 );
8912 }
8913
8914 #[test]
8915 fn java_local_class_in_method_lloc() {
8916 check_metrics::<JavaParser>(
8920 "class Foo {\n int bar() {\n class Local {\n int v() { return 1; }\n }\n return new Local().v();\n }\n}\n",
8921 "foo.java",
8922 |metric| {
8923 assert_eq!(metric.loc.sloc(), 8.0);
8924 assert_eq!(metric.loc.ploc(), 8.0);
8925 assert_eq!(metric.loc.lloc(), 2.0);
8926 assert_eq!(metric.loc.cloc(), 0.0);
8927 assert_eq!(metric.loc.blank(), 0.0);
8928 insta::assert_json_snapshot!(metric.loc);
8929 },
8930 );
8931 }
8932
8933 #[test]
8934 fn java_lambda_in_method_lloc() {
8935 check_metrics::<JavaParser>(
8939 "class Foo {\n void bar() {\n java.util.function.IntUnaryOperator f = x -> x + 1;\n f.applyAsInt(3);\n }\n}\n",
8940 "foo.java",
8941 |metric| {
8942 assert_eq!(metric.loc.sloc(), 6.0);
8943 assert_eq!(metric.loc.ploc(), 6.0);
8944 assert_eq!(metric.loc.lloc(), 2.0);
8945 assert_eq!(metric.loc.cloc(), 0.0);
8946 assert_eq!(metric.loc.blank(), 0.0);
8947 insta::assert_json_snapshot!(metric.loc);
8948 },
8949 );
8950 }
8951
8952 #[test]
8953 fn groovy_blank() {
8954 check_metrics::<GroovyParser>("int x = 1\n\n\nint y = 2", "foo.groovy", |metric| {
8957 assert_eq!(metric.loc.sloc(), 4.0);
8958 assert_eq!(metric.loc.ploc(), 2.0);
8959 assert_eq!(metric.loc.lloc(), 2.0);
8960 assert_eq!(metric.loc.blank(), 2.0);
8961 });
8962 }
8963
8964 #[test]
8965 fn groovy_no_zero_blank() {
8966 check_metrics::<GroovyParser>("int x = 1", "foo.groovy", |metric| {
8968 assert_eq!(metric.loc.sloc(), 1.0);
8969 assert_eq!(metric.loc.blank(), 0.0);
8970 });
8971 }
8972
8973 #[test]
8974 fn groovy_cloc_line_comments() {
8975 check_metrics::<GroovyParser>(
8976 "// first comment
8977 int x = 1
8978 // second comment
8979 int y = 2",
8980 "foo.groovy",
8981 |metric| {
8982 assert_eq!(metric.loc.cloc(), 2.0);
8983 assert_eq!(metric.loc.ploc(), 2.0);
8984 },
8985 );
8986 }
8987
8988 #[test]
8989 fn groovy_cloc_block_comment() {
8990 check_metrics::<GroovyParser>(
8991 "/* multi
8992 line
8993 comment */
8994 int x = 1",
8995 "foo.groovy",
8996 |metric| {
8997 assert_eq!(metric.loc.cloc(), 3.0);
8999 },
9000 );
9001 }
9002
9003 #[test]
9004 fn groovy_simple_lloc() {
9005 check_metrics::<GroovyParser>(
9007 "int a = 1
9008 int b = 2
9009 int c = 3",
9010 "foo.groovy",
9011 |metric| {
9012 assert_eq!(metric.loc.lloc(), 3.0);
9013 },
9014 );
9015 }
9016
9017 #[test]
9018 fn groovy_no_local_variable_declaration_in_for_lloc() {
9019 check_metrics::<GroovyParser>(
9023 "for (int i = 0; i < 10; i++) {
9024 println(i)
9025 }",
9026 "foo.groovy",
9027 |metric| {
9028 assert_eq!(metric.loc.lloc(), 2.0);
9030 },
9031 );
9032 }
9033
9034 #[test]
9035 fn groovy_lambda_in_method_lloc() {
9036 check_metrics::<GroovyParser>(
9043 "class Foo {
9044 void bar() {
9045 def f = { x -> x + 1 }
9046 f(3)
9047 }
9048 }",
9049 "foo.groovy",
9050 |metric| {
9051 assert_eq!(metric.loc.lloc(), 3.0);
9052 },
9053 );
9054 }
9055
9056 #[test]
9057 fn groovy_try_lloc() {
9058 check_metrics::<GroovyParser>(
9061 "void f() {
9062 try {
9063 risky()
9064 } catch (Exception e) {
9065 handle(e)
9066 }
9067 }",
9068 "foo.groovy",
9069 |metric| {
9070 assert_eq!(metric.loc.lloc(), 3.0);
9072 },
9073 );
9074 }
9075
9076 #[test]
9077 fn groovy_class_loc() {
9078 check_metrics::<GroovyParser>(
9080 "class A {
9081 void f() {
9082 int x = 1
9083 }
9084 void g() {
9085 int y = 2
9086 }
9087 }",
9088 "foo.groovy",
9089 |metric| {
9090 assert_eq!(metric.loc.ploc(), 8.0);
9094 assert_eq!(metric.loc.cloc(), 0.0);
9095 assert_eq!(metric.loc.lloc(), 2.0);
9098 },
9099 );
9100 }
9101
9102 #[test]
9103 fn groovy_partial_parse_recovers_unit() {
9104 check_metrics::<GroovyParser>("def x = (((", "foo.groovy", |metric| {
9109 assert_eq!(metric.loc.sloc(), 1.0);
9110 assert_eq!(metric.loc.blank(), 0.0);
9111 });
9112 }
9113
9114 #[test]
9115 fn groovy_sloc() {
9116 check_metrics::<GroovyParser>(
9119 "int a = 1
9120 int b = 2
9121
9122 int c = 3",
9123 "foo.groovy",
9124 |metric| {
9125 assert_eq!(metric.loc.sloc(), 4.0);
9126 assert_eq!(metric.loc.ploc(), 3.0);
9127 assert_eq!(metric.loc.blank(), 1.0);
9128 },
9129 );
9130 }
9131
9132 #[test]
9133 fn groovy_single_ploc() {
9134 check_metrics::<GroovyParser>("int x = 42", "foo.groovy", |metric| {
9137 assert_eq!(metric.loc.ploc(), 1.0);
9138 assert_eq!(metric.loc.cloc(), 0.0);
9139 });
9140 }
9141
9142 #[test]
9143 fn groovy_multi_ploc() {
9144 check_metrics::<GroovyParser>(
9147 "int a = 1
9148 int b = 2
9149 int c = 3
9150 int d = 4",
9151 "foo.groovy",
9152 |metric| {
9153 assert_eq!(metric.loc.ploc(), 4.0);
9154 assert_eq!(metric.loc.lloc(), 4.0);
9155 },
9156 );
9157 }
9158
9159 #[test]
9160 fn groovy_single_statement_lloc() {
9161 check_metrics::<GroovyParser>("println 'hi'", "foo.groovy", |metric| {
9164 assert_eq!(metric.loc.lloc(), 1.0);
9165 });
9166 }
9167
9168 #[test]
9169 fn groovy_for_lloc() {
9170 check_metrics::<GroovyParser>(
9175 "for (int i = 0; i < 100; i++) {
9176 println(i)
9177 }",
9178 "foo.groovy",
9179 |metric| {
9180 assert_eq!(metric.loc.lloc(), 2.0);
9182 },
9183 );
9184 }
9185
9186 #[test]
9187 fn groovy_foreach_lloc() {
9188 check_metrics::<GroovyParser>(
9191 "for (item in items) {
9192 println(item)
9193 }",
9194 "foo.groovy",
9195 |metric| {
9196 assert_eq!(metric.loc.lloc(), 2.0);
9198 },
9199 );
9200 }
9201
9202 #[test]
9203 fn groovy_while_lloc() {
9204 check_metrics::<GroovyParser>(
9207 "int i = 0
9208 while (i < 10) {
9209 i++
9210 println(i)
9211 }",
9212 "foo.groovy",
9213 |metric| {
9214 assert_eq!(metric.loc.lloc(), 4.0);
9216 },
9217 );
9218 }
9219
9220 #[test]
9221 fn groovy_do_while_lloc() {
9222 check_metrics::<GroovyParser>(
9225 "int i = 0
9226 do {
9227 i++
9228 } while (i < 5)",
9229 "foo.groovy",
9230 |metric| {
9231 assert_eq!(metric.loc.lloc(), 3.0);
9233 },
9234 );
9235 }
9236
9237 #[test]
9238 fn groovy_continue_lloc() {
9239 check_metrics::<GroovyParser>(
9241 "for (int i = 0; i < 10; i++) {
9242 if (i == 5) {
9243 continue
9244 }
9245 println(i)
9246 }",
9247 "foo.groovy",
9248 |metric| {
9249 assert_eq!(metric.loc.lloc(), 4.0);
9251 },
9252 );
9253 }
9254
9255 #[test]
9256 fn groovy_expressions_lloc() {
9257 check_metrics::<GroovyParser>(
9260 "int a = 1
9261 a = 2
9262 a += 3
9263 println(a)
9264 doSomething()",
9265 "foo.groovy",
9266 |metric| {
9267 assert_eq!(metric.loc.lloc(), 5.0);
9269 },
9270 );
9271 }
9272
9273 #[test]
9274 fn groovy_throw_lloc() {
9275 check_metrics::<GroovyParser>(
9277 "throw new RuntimeException('bad')",
9278 "foo.groovy",
9279 |metric| {
9280 assert_eq!(metric.loc.lloc(), 1.0);
9281 },
9282 );
9283 }
9284
9285 #[test]
9286 fn groovy_general_loc() {
9287 check_metrics::<GroovyParser>(
9299 "class A {
9300 void f(int x) {
9301 if (x > 0) {
9302 println(x)
9303 } else {
9304 println 'neg'
9305 }
9306 return
9307 }
9308 }",
9309 "foo.groovy",
9310 |metric| {
9311 assert_eq!(metric.loc.lloc(), 4.0);
9312 assert_eq!(metric.loc.cloc(), 0.0);
9313 },
9314 );
9315 }
9316
9317 #[test]
9318 fn csharp_local_function_in_method_lloc() {
9319 check_metrics::<CsharpParser>(
9323 "class Foo {\n int Bar() {\n int Inner(int x) { return x + 1; }\n return Inner(2);\n }\n}\n",
9324 "foo.cs",
9325 |metric| {
9326 assert_eq!(metric.loc.sloc(), 6.0);
9327 assert_eq!(metric.loc.ploc(), 6.0);
9328 assert_eq!(metric.loc.lloc(), 2.0);
9329 assert_eq!(metric.loc.cloc(), 0.0);
9330 assert_eq!(metric.loc.blank(), 0.0);
9331 insta::assert_json_snapshot!(metric.loc);
9332 },
9333 );
9334 }
9335
9336 #[test]
9337 fn csharp_lambda_in_method_lloc() {
9338 check_metrics::<CsharpParser>(
9341 "class Foo {\n void Bar() {\n System.Func<int, int> f = x => x + 1;\n f(3);\n }\n}\n",
9342 "foo.cs",
9343 |metric| {
9344 assert_eq!(metric.loc.sloc(), 6.0);
9345 assert_eq!(metric.loc.ploc(), 6.0);
9346 assert_eq!(metric.loc.lloc(), 2.0);
9347 assert_eq!(metric.loc.cloc(), 0.0);
9348 assert_eq!(metric.loc.blank(), 0.0);
9349 insta::assert_json_snapshot!(metric.loc);
9350 },
9351 );
9352 }
9353
9354 #[test]
9355 fn cpp_lambda_in_function_lloc() {
9356 check_metrics::<CppParser>(
9364 "int bar() {\n auto f = [](int x) { return x + 1; };\n return f(2);\n}\n",
9365 "foo.cpp",
9366 |metric| {
9367 assert_eq!(metric.loc.sloc(), 4.0);
9368 assert_eq!(metric.loc.ploc(), 4.0);
9369 assert_eq!(metric.loc.lloc(), 3.0);
9370 assert_eq!(metric.loc.cloc(), 0.0);
9371 assert_eq!(metric.loc.blank(), 0.0);
9372 insta::assert_json_snapshot!(metric.loc);
9373 },
9374 );
9375 }
9376
9377 #[test]
9378 fn javascript_nested_function_lloc() {
9379 check_metrics::<JavascriptParser>(
9383 "function outer() {\n function inner() {\n return 1;\n }\n return inner();\n}\n",
9384 "foo.js",
9385 |metric| {
9386 assert_eq!(metric.loc.sloc(), 6.0);
9387 assert_eq!(metric.loc.ploc(), 6.0);
9388 assert_eq!(metric.loc.lloc(), 4.0);
9389 assert_eq!(metric.loc.cloc(), 0.0);
9390 assert_eq!(metric.loc.blank(), 0.0);
9391 insta::assert_json_snapshot!(metric.loc);
9392 },
9393 );
9394 }
9395
9396 #[test]
9397 fn javascript_arrow_function_lloc() {
9398 check_metrics::<JavascriptParser>(
9401 "function outer() {\n const inner = (x) => x + 1;\n return inner(2);\n}\n",
9402 "foo.js",
9403 |metric| {
9404 assert_eq!(metric.loc.sloc(), 4.0);
9405 assert_eq!(metric.loc.ploc(), 4.0);
9406 assert_eq!(metric.loc.lloc(), 2.0);
9407 assert_eq!(metric.loc.cloc(), 0.0);
9408 assert_eq!(metric.loc.blank(), 0.0);
9409 insta::assert_json_snapshot!(metric.loc);
9410 },
9411 );
9412 }
9413
9414 #[test]
9415 fn kotlin_lambda_literal_in_fun_lloc() {
9416 check_metrics::<KotlinParser>(
9419 "fun outer() {\n val f: (Int) -> Int = { x -> x + 1 }\n f(3)\n}\n",
9420 "foo.kt",
9421 |metric| {
9422 assert_eq!(metric.loc.sloc(), 4.0);
9423 assert_eq!(metric.loc.ploc(), 4.0);
9424 assert_eq!(metric.loc.lloc(), 2.0);
9425 assert_eq!(metric.loc.cloc(), 0.0);
9426 assert_eq!(metric.loc.blank(), 0.0);
9427 insta::assert_json_snapshot!(metric.loc);
9428 },
9429 );
9430 }
9431
9432 #[test]
9433 fn kotlin_local_fun_in_fun_lloc() {
9434 check_metrics::<KotlinParser>(
9438 "fun outer() {\n fun inner(x: Int): Int { return x + 1 }\n inner(3)\n}\n",
9439 "foo.kt",
9440 |metric| {
9441 assert_eq!(metric.loc.sloc(), 4.0);
9442 assert_eq!(metric.loc.ploc(), 4.0);
9443 assert_eq!(metric.loc.lloc(), 2.0);
9444 assert_eq!(metric.loc.cloc(), 0.0);
9445 assert_eq!(metric.loc.blank(), 0.0);
9446 insta::assert_json_snapshot!(metric.loc);
9447 },
9448 );
9449 }
9450
9451 #[test]
9452 fn kotlin_object_expression_in_fun_lloc() {
9453 check_metrics::<KotlinParser>(
9457 "fun outer() {\n val r = object : Runnable { override fun run() { println(\"hi\") } }\n r.run()\n}\n",
9458 "foo.kt",
9459 |metric| {
9460 assert_eq!(metric.loc.sloc(), 4.0);
9461 assert_eq!(metric.loc.ploc(), 4.0);
9462 assert_eq!(metric.loc.lloc(), 3.0);
9463 assert_eq!(metric.loc.cloc(), 0.0);
9464 assert_eq!(metric.loc.blank(), 0.0);
9465 insta::assert_json_snapshot!(metric.loc);
9466 },
9467 );
9468 }
9469
9470 #[test]
9471 fn go_function_literal_initializer_lloc() {
9472 check_metrics::<GoParser>(
9477 "package main\nfunc outer() int {\n inner := func(x int) int { return x + 1 }\n return inner(2)\n}\n",
9478 "foo.go",
9479 |metric| {
9480 assert_eq!(metric.loc.sloc(), 5.0);
9481 assert_eq!(metric.loc.ploc(), 5.0);
9482 assert_eq!(metric.loc.lloc(), 3.0);
9483 assert_eq!(metric.loc.cloc(), 0.0);
9484 assert_eq!(metric.loc.blank(), 0.0);
9485 insta::assert_json_snapshot!(metric.loc);
9486 },
9487 );
9488 }
9489
9490 #[test]
9491 fn php_anonymous_function_in_function_lloc() {
9492 check_metrics::<PhpParser>(
9496 "<?php\nfunction outer() {\n $f = function ($x) { return $x + 1; };\n return $f(2);\n}\n",
9497 "foo.php",
9498 |metric| {
9499 assert_eq!(metric.loc.sloc(), 5.0);
9500 assert_eq!(metric.loc.ploc(), 5.0);
9501 assert_eq!(metric.loc.lloc(), 3.0);
9502 assert_eq!(metric.loc.cloc(), 0.0);
9503 assert_eq!(metric.loc.blank(), 0.0);
9504 insta::assert_json_snapshot!(metric.loc);
9505 },
9506 );
9507 }
9508
9509 #[test]
9510 fn php_arrow_function_in_function_lloc() {
9511 check_metrics::<PhpParser>(
9514 "<?php\nfunction outer() {\n $f = fn ($x) => $x + 1;\n return $f(2);\n}\n",
9515 "foo.php",
9516 |metric| {
9517 assert_eq!(metric.loc.sloc(), 5.0);
9518 assert_eq!(metric.loc.ploc(), 5.0);
9519 assert_eq!(metric.loc.lloc(), 2.0);
9520 assert_eq!(metric.loc.cloc(), 0.0);
9521 assert_eq!(metric.loc.blank(), 0.0);
9522 insta::assert_json_snapshot!(metric.loc);
9523 },
9524 );
9525 }
9526
9527 #[test]
9528 fn lua_nested_local_function_lloc() {
9529 check_metrics::<LuaParser>(
9533 "local function outer()\n local function inner()\n return 1\n end\n return inner()\nend\n",
9534 "foo.lua",
9535 |metric| {
9536 assert_eq!(metric.loc.sloc(), 6.0);
9537 assert_eq!(metric.loc.ploc(), 6.0);
9538 assert_eq!(metric.loc.lloc(), 4.0);
9539 assert_eq!(metric.loc.cloc(), 0.0);
9540 assert_eq!(metric.loc.blank(), 0.0);
9541 insta::assert_json_snapshot!(metric.loc);
9542 },
9543 );
9544 }
9545
9546 #[test]
9547 fn lua_function_expression_in_local_decl_lloc() {
9548 check_metrics::<LuaParser>(
9553 "local function outer()\n local f = function (x) return x + 1 end\n return f(2)\nend\n",
9554 "foo.lua",
9555 |metric| {
9556 assert_eq!(metric.loc.sloc(), 4.0);
9557 assert_eq!(metric.loc.ploc(), 4.0);
9558 assert_eq!(metric.loc.lloc(), 4.0);
9559 assert_eq!(metric.loc.cloc(), 0.0);
9560 assert_eq!(metric.loc.blank(), 0.0);
9561 insta::assert_json_snapshot!(metric.loc);
9562 },
9563 );
9564 }
9565
9566 #[test]
9567 fn tcl_apply_closure_lloc() {
9568 check_metrics::<TclParser>(
9575 "proc outer {} {\n set f [list x {return [expr {$x + 1}]}]\n apply $f 2\n}\n",
9576 "foo.tcl",
9577 |metric| {
9578 assert_eq!(metric.loc.sloc(), 4.0);
9579 assert_eq!(metric.loc.ploc(), 4.0);
9580 assert_eq!(metric.loc.lloc(), 4.0);
9581 assert_eq!(metric.loc.cloc(), 0.0);
9582 assert_eq!(metric.loc.blank(), 0.0);
9583 insta::assert_json_snapshot!(metric.loc);
9584 },
9585 );
9586 }
9587
9588 #[test]
9589 fn perl_anonymous_sub_in_sub_lloc() {
9590 check_metrics::<PerlParser>(
9600 "sub outer {\n my $f = sub { return $_[0] + 1 };\n return $f->(2);\n}\n",
9601 "foo.pl",
9602 |metric| {
9603 assert_eq!(metric.loc.sloc(), 4.0);
9604 assert_eq!(metric.loc.ploc(), 4.0);
9605 assert_eq!(metric.loc.lloc(), 2.0);
9606 assert_eq!(metric.loc.cloc(), 0.0);
9607 assert_eq!(metric.loc.blank(), 0.0);
9608 insta::assert_json_snapshot!(metric.loc);
9609 },
9610 );
9611 }
9612
9613 #[test]
9614 fn perl_named_sub_in_sub_lloc() {
9615 check_metrics::<PerlParser>(
9630 "sub outer {\n sub inner { return 1 }\n return inner();\n}\n",
9631 "foo.pl",
9632 |metric| {
9633 assert_eq!(metric.loc.sloc(), 4.0);
9634 assert_eq!(metric.loc.ploc(), 4.0);
9635 assert_eq!(metric.loc.lloc(), 1.0);
9636 assert_eq!(metric.loc.cloc(), 0.0);
9637 assert_eq!(metric.loc.blank(), 0.0);
9638 insta::assert_json_snapshot!(metric.loc);
9639 },
9640 );
9641 }
9642
9643 #[test]
9644 fn elixir_fn_inside_def_lloc() {
9645 check_metrics::<ElixirParser>(
9649 "defmodule Foo do\n def outer do\n f = fn x -> x + 1 end\n f.(2)\n end\nend\n",
9650 "foo.ex",
9651 |metric| {
9652 assert_eq!(metric.loc.sloc(), 6.0);
9653 assert_eq!(metric.loc.ploc(), 6.0);
9654 assert_eq!(metric.loc.lloc(), 5.0);
9655 assert_eq!(metric.loc.cloc(), 0.0);
9656 assert_eq!(metric.loc.blank(), 0.0);
9657 insta::assert_json_snapshot!(metric.loc);
9658 },
9659 );
9660 }
9661}