1use crate::checker::Checker;
2use fxhash::FxHashSet;
3use serde::ser::{SerializeStruct, Serializer};
4use serde::Serialize;
5use std::fmt;
6
7use crate::*;
8
9#[derive(Debug, Clone)]
11pub struct Sloc {
12 start: usize,
13 end: usize,
14 unit: bool,
15 sloc_min: usize,
16 sloc_max: usize,
17}
18
19impl Default for Sloc {
20 fn default() -> Self {
21 Self {
22 start: 0,
23 end: 0,
24 unit: false,
25 sloc_min: usize::MAX,
26 sloc_max: 0,
27 }
28 }
29}
30
31impl Sloc {
32 #[inline(always)]
33 pub fn sloc(&self) -> f64 {
34 let sloc = if self.unit {
38 self.end - self.start
39 } else {
40 (self.end - self.start) + 1
41 };
42 sloc as f64
43 }
44
45 #[inline(always)]
47 pub fn sloc_min(&self) -> f64 {
48 self.sloc_min as f64
49 }
50
51 #[inline(always)]
53 pub fn sloc_max(&self) -> f64 {
54 self.sloc_max as f64
55 }
56
57 #[inline(always)]
58 pub fn merge(&mut self, other: &Sloc) {
59 self.sloc_min = self.sloc_min.min(other.sloc() as usize);
60 self.sloc_max = self.sloc_max.max(other.sloc() as usize);
61 }
62
63 #[inline(always)]
64 pub(crate) fn compute_minmax(&mut self) {
65 if self.sloc_min == usize::MAX {
66 self.sloc_min = self.sloc_min.min(self.sloc() as usize);
67 self.sloc_max = self.sloc_max.max(self.sloc() as usize);
68 }
69 }
70}
71
72#[derive(Debug, Clone)]
74pub struct Ploc {
75 lines: FxHashSet<usize>,
76 ploc_min: usize,
77 ploc_max: usize,
78}
79
80impl Default for Ploc {
81 fn default() -> Self {
82 Self {
83 lines: FxHashSet::default(),
84 ploc_min: usize::MAX,
85 ploc_max: 0,
86 }
87 }
88}
89
90impl Ploc {
91 #[inline(always)]
92 pub fn ploc(&self) -> f64 {
93 self.lines.len() as f64
96 }
97
98 #[inline(always)]
100 pub fn ploc_min(&self) -> f64 {
101 self.ploc_min as f64
102 }
103
104 #[inline(always)]
106 pub fn ploc_max(&self) -> f64 {
107 self.ploc_max as f64
108 }
109
110 #[inline(always)]
111 pub fn merge(&mut self, other: &Ploc) {
112 for l in other.lines.iter() {
114 self.lines.insert(*l);
115 }
116
117 self.ploc_min = self.ploc_min.min(other.ploc() as usize);
118 self.ploc_max = self.ploc_max.max(other.ploc() as usize);
119 }
120
121 #[inline(always)]
122 pub(crate) fn compute_minmax(&mut self) {
123 if self.ploc_min == usize::MAX {
124 self.ploc_min = self.ploc_min.min(self.ploc() as usize);
125 self.ploc_max = self.ploc_max.max(self.ploc() as usize);
126 }
127 }
128}
129
130#[derive(Debug, Clone)]
132pub struct Cloc {
133 only_comment_lines: usize,
134 code_comment_lines: usize,
135 comment_line_end: Option<usize>,
136 cloc_min: usize,
137 cloc_max: usize,
138}
139
140impl Default for Cloc {
141 fn default() -> Self {
142 Self {
143 only_comment_lines: 0,
144 code_comment_lines: 0,
145 comment_line_end: Option::default(),
146 cloc_min: usize::MAX,
147 cloc_max: 0,
148 }
149 }
150}
151
152impl Cloc {
153 #[inline(always)]
154 pub fn cloc(&self) -> f64 {
155 (self.only_comment_lines + self.code_comment_lines) as f64
158 }
159
160 #[inline(always)]
162 pub fn cloc_min(&self) -> f64 {
163 self.cloc_min as f64
164 }
165
166 #[inline(always)]
168 pub fn cloc_max(&self) -> f64 {
169 self.cloc_max as f64
170 }
171
172 #[inline(always)]
173 pub fn merge(&mut self, other: &Cloc) {
174 self.only_comment_lines += other.only_comment_lines;
176 self.code_comment_lines += other.code_comment_lines;
177
178 self.cloc_min = self.cloc_min.min(other.cloc() as usize);
179 self.cloc_max = self.cloc_max.max(other.cloc() as usize);
180 }
181
182 #[inline(always)]
183 pub(crate) fn compute_minmax(&mut self) {
184 if self.cloc_min == usize::MAX {
185 self.cloc_min = self.cloc_min.min(self.cloc() as usize);
186 self.cloc_max = self.cloc_max.max(self.cloc() as usize);
187 }
188 }
189}
190
191#[derive(Debug, Clone)]
193pub struct Lloc {
194 logical_lines: usize,
195 lloc_min: usize,
196 lloc_max: usize,
197}
198
199impl Default for Lloc {
200 fn default() -> Self {
201 Self {
202 logical_lines: 0,
203 lloc_min: usize::MAX,
204 lloc_max: 0,
205 }
206 }
207}
208
209impl Lloc {
210 #[inline(always)]
211 pub fn lloc(&self) -> f64 {
212 self.logical_lines as f64
215 }
216
217 #[inline(always)]
219 pub fn lloc_min(&self) -> f64 {
220 self.lloc_min as f64
221 }
222
223 #[inline(always)]
225 pub fn lloc_max(&self) -> f64 {
226 self.lloc_max as f64
227 }
228
229 #[inline(always)]
230 pub fn merge(&mut self, other: &Lloc) {
231 self.logical_lines += other.logical_lines;
233 self.lloc_min = self.lloc_min.min(other.lloc() as usize);
234 self.lloc_max = self.lloc_max.max(other.lloc() as usize);
235 }
236
237 #[inline(always)]
238 pub(crate) fn compute_minmax(&mut self) {
239 if self.lloc_min == usize::MAX {
240 self.lloc_min = self.lloc_min.min(self.lloc() as usize);
241 self.lloc_max = self.lloc_max.max(self.lloc() as usize);
242 }
243 }
244}
245
246#[derive(Debug, Clone)]
248pub struct Stats {
249 sloc: Sloc,
250 ploc: Ploc,
251 cloc: Cloc,
252 lloc: Lloc,
253 space_count: usize,
254 blank_min: usize,
255 blank_max: usize,
256}
257
258impl Default for Stats {
259 fn default() -> Self {
260 Self {
261 sloc: Sloc::default(),
262 ploc: Ploc::default(),
263 cloc: Cloc::default(),
264 lloc: Lloc::default(),
265 space_count: 1,
266 blank_min: usize::MAX,
267 blank_max: 0,
268 }
269 }
270}
271
272impl Serialize for Stats {
273 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
274 where
275 S: Serializer,
276 {
277 let mut st = serializer.serialize_struct("loc", 20)?;
278 st.serialize_field("sloc", &self.sloc())?;
279 st.serialize_field("ploc", &self.ploc())?;
280 st.serialize_field("lloc", &self.lloc())?;
281 st.serialize_field("cloc", &self.cloc())?;
282 st.serialize_field("blank", &self.blank())?;
283 st.serialize_field("sloc_average", &self.sloc_average())?;
284 st.serialize_field("ploc_average", &self.ploc_average())?;
285 st.serialize_field("lloc_average", &self.lloc_average())?;
286 st.serialize_field("cloc_average", &self.cloc_average())?;
287 st.serialize_field("blank_average", &self.blank_average())?;
288 st.serialize_field("sloc_min", &self.sloc_min())?;
289 st.serialize_field("sloc_max", &self.sloc_max())?;
290 st.serialize_field("cloc_min", &self.cloc_min())?;
291 st.serialize_field("cloc_max", &self.cloc_max())?;
292 st.serialize_field("ploc_min", &self.ploc_min())?;
293 st.serialize_field("ploc_max", &self.ploc_max())?;
294 st.serialize_field("lloc_min", &self.lloc_min())?;
295 st.serialize_field("lloc_max", &self.lloc_max())?;
296 st.serialize_field("blank_min", &self.blank_min())?;
297 st.serialize_field("blank_max", &self.blank_max())?;
298 st.end()
299 }
300}
301
302impl fmt::Display for Stats {
303 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
304 write!(
305 f,
306 "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: {}",
307 self.sloc(),
308 self.ploc(),
309 self.lloc(),
310 self.cloc(),
311 self.blank(),
312 self.sloc_average(),
313 self.ploc_average(),
314 self.lloc_average(),
315 self.cloc_average(),
316 self.blank_average(),
317 self.sloc_min(),
318 self.sloc_max(),
319 self.cloc_min(),
320 self.cloc_max(),
321 self.ploc_min(),
322 self.ploc_max(),
323 self.lloc_min(),
324 self.lloc_max(),
325 self.blank_min(),
326 self.blank_max(),
327 )
328 }
329}
330
331impl Stats {
332 pub fn merge(&mut self, other: &Stats) {
334 self.sloc.merge(&other.sloc);
335 self.ploc.merge(&other.ploc);
336 self.cloc.merge(&other.cloc);
337 self.lloc.merge(&other.lloc);
338
339 self.space_count += other.space_count;
341
342 self.blank_min = self.blank_min.min(other.blank() as usize);
345 self.blank_max = self.blank_max.max(other.blank() as usize);
346 }
347
348 #[inline(always)]
352 pub fn sloc(&self) -> f64 {
353 self.sloc.sloc()
354 }
355
356 #[inline(always)]
360 pub fn ploc(&self) -> f64 {
361 self.ploc.ploc()
362 }
363
364 #[inline(always)]
368 pub fn lloc(&self) -> f64 {
369 self.lloc.lloc()
370 }
371
372 #[inline(always)]
376 pub fn cloc(&self) -> f64 {
377 self.cloc.cloc()
378 }
379
380 #[inline(always)]
384 pub fn blank(&self) -> f64 {
385 self.sloc() - self.ploc() - self.cloc.only_comment_lines as f64
386 }
387
388 #[inline(always)]
392 pub fn sloc_average(&self) -> f64 {
393 self.sloc() / self.space_count as f64
394 }
395
396 #[inline(always)]
400 pub fn ploc_average(&self) -> f64 {
401 self.ploc() / self.space_count as f64
402 }
403
404 #[inline(always)]
408 pub fn lloc_average(&self) -> f64 {
409 self.lloc() / self.space_count as f64
410 }
411
412 #[inline(always)]
416 pub fn cloc_average(&self) -> f64 {
417 self.cloc() / self.space_count as f64
418 }
419
420 #[inline(always)]
424 pub fn blank_average(&self) -> f64 {
425 self.blank() / self.space_count as f64
426 }
427
428 #[inline(always)]
430 pub fn sloc_min(&self) -> f64 {
431 self.sloc.sloc_min()
432 }
433
434 #[inline(always)]
436 pub fn sloc_max(&self) -> f64 {
437 self.sloc.sloc_max()
438 }
439
440 #[inline(always)]
442 pub fn cloc_min(&self) -> f64 {
443 self.cloc.cloc_min()
444 }
445
446 #[inline(always)]
448 pub fn cloc_max(&self) -> f64 {
449 self.cloc.cloc_max()
450 }
451
452 #[inline(always)]
454 pub fn ploc_min(&self) -> f64 {
455 self.ploc.ploc_min()
456 }
457
458 #[inline(always)]
460 pub fn ploc_max(&self) -> f64 {
461 self.ploc.ploc_max()
462 }
463
464 #[inline(always)]
466 pub fn lloc_min(&self) -> f64 {
467 self.lloc.lloc_min()
468 }
469
470 #[inline(always)]
472 pub fn lloc_max(&self) -> f64 {
473 self.lloc.lloc_max()
474 }
475
476 #[inline(always)]
478 pub fn blank_min(&self) -> f64 {
479 self.blank_min as f64
480 }
481
482 #[inline(always)]
484 pub fn blank_max(&self) -> f64 {
485 self.blank_max as f64
486 }
487
488 #[inline(always)]
489 pub(crate) fn compute_minmax(&mut self) {
490 self.sloc.compute_minmax();
491 self.ploc.compute_minmax();
492 self.cloc.compute_minmax();
493 self.lloc.compute_minmax();
494
495 if self.blank_min == usize::MAX {
496 self.blank_min = self.blank_min.min(self.blank() as usize);
497 self.blank_max = self.blank_max.max(self.blank() as usize);
498 }
499 }
500}
501
502#[doc(hidden)]
503pub trait Loc
504where
505 Self: Checker,
506{
507 fn compute(_node: &Node, _stats: &mut Stats, _is_func_space: bool, _is_unit: bool) {}
508}
509
510#[inline(always)]
511fn init(node: &Node, stats: &mut Stats, is_func_space: bool, is_unit: bool) -> (usize, usize) {
512 let start = node.object().start_position().row;
513 let end = node.object().end_position().row;
514
515 if is_func_space {
516 stats.sloc.start = start;
517 stats.sloc.end = end;
518 stats.sloc.unit = is_unit;
519 }
520 (start, end)
521}
522
523#[inline(always)]
524fn add_cloc_lines(stats: &mut Stats, start: usize, end: usize) {
529 let comment_diff = end - start;
530 let is_comment_after_code_line = stats.ploc.lines.contains(&start);
531 if is_comment_after_code_line && comment_diff == 0 {
532 stats.cloc.code_comment_lines += 1;
534 } else if is_comment_after_code_line && comment_diff > 0 {
535 stats.cloc.code_comment_lines += 1;
538 stats.cloc.only_comment_lines += comment_diff;
539 } else {
540 stats.cloc.only_comment_lines += (end - start) + 1;
544 stats.cloc.comment_line_end = Some(end);
547 }
548}
549
550#[inline(always)]
551fn check_comment_ends_on_code_line(stats: &mut Stats, start_code_line: usize) {
555 if let Some(end) = stats.cloc.comment_line_end {
556 if end == start_code_line && !stats.ploc.lines.contains(&start_code_line) {
557 stats.cloc.only_comment_lines -= 1;
559 stats.cloc.code_comment_lines += 1;
560 }
561 }
562}
563
564impl Loc for PythonCode {
565 fn compute(node: &Node, stats: &mut Stats, is_func_space: bool, is_unit: bool) {
566 use Python::*;
567
568 let (start, end) = init(node, stats, is_func_space, is_unit);
569
570 match node.object().kind_id().into() {
571 DQUOTE | DQUOTE2 | Block | Module => {}
572 Comment => {
573 add_cloc_lines(stats, start, end);
574 }
575 String => {
576 let parent = node.object().parent().unwrap();
577 if let ExpressionStatement = parent.kind_id().into() {
578 add_cloc_lines(stats, start, end);
579 } else if parent.start_position().row != start {
580 check_comment_ends_on_code_line(stats, start);
581 stats.ploc.lines.insert(start);
582 }
583 }
584 Statement
585 | SimpleStatements
586 | ImportStatement
587 | FutureImportStatement
588 | ImportFromStatement
589 | PrintStatement
590 | AssertStatement
591 | ReturnStatement
592 | DeleteStatement
593 | RaiseStatement
594 | PassStatement
595 | BreakStatement
596 | ContinueStatement
597 | IfStatement
598 | ForStatement
599 | WhileStatement
600 | TryStatement
601 | WithStatement
602 | GlobalStatement
603 | NonlocalStatement
604 | ExecStatement
605 | ExpressionStatement => {
606 stats.lloc.logical_lines += 1;
607 }
608 _ => {
609 check_comment_ends_on_code_line(stats, start);
610 stats.ploc.lines.insert(start);
611 }
612 }
613 }
614}
615
616impl Loc for MozjsCode {
617 fn compute(node: &Node, stats: &mut Stats, is_func_space: bool, is_unit: bool) {
618 use Mozjs::*;
619
620 let (start, end) = init(node, stats, is_func_space, is_unit);
621
622 match node.object().kind_id().into() {
623 String | DQUOTE | Program => {}
624 Comment => {
625 add_cloc_lines(stats, start, end);
626 }
627 ExpressionStatement | ExportStatement | ImportStatement | StatementBlock
628 | IfStatement | SwitchStatement | ForStatement | ForInStatement | WhileStatement
629 | DoStatement | TryStatement | WithStatement | BreakStatement | ContinueStatement
630 | DebuggerStatement | ReturnStatement | ThrowStatement | EmptyStatement
631 | StatementIdentifier => {
632 stats.lloc.logical_lines += 1;
633 }
634 _ => {
635 check_comment_ends_on_code_line(stats, start);
636 stats.ploc.lines.insert(start);
637 }
638 }
639 }
640}
641
642impl Loc for JavascriptCode {
643 fn compute(node: &Node, stats: &mut Stats, is_func_space: bool, is_unit: bool) {
644 use Javascript::*;
645
646 let (start, end) = init(node, stats, is_func_space, is_unit);
647
648 match node.object().kind_id().into() {
649 String | DQUOTE | Program => {}
650 Comment => {
651 add_cloc_lines(stats, start, end);
652 }
653 ExpressionStatement | ExportStatement | ImportStatement | StatementBlock
654 | IfStatement | SwitchStatement | ForStatement | ForInStatement | WhileStatement
655 | DoStatement | TryStatement | WithStatement | BreakStatement | ContinueStatement
656 | DebuggerStatement | ReturnStatement | ThrowStatement | EmptyStatement
657 | StatementIdentifier => {
658 stats.lloc.logical_lines += 1;
659 }
660 _ => {
661 check_comment_ends_on_code_line(stats, start);
662 stats.ploc.lines.insert(start);
663 }
664 }
665 }
666}
667
668impl Loc for TypescriptCode {
669 fn compute(node: &Node, stats: &mut Stats, is_func_space: bool, is_unit: bool) {
670 use Typescript::*;
671
672 let (start, end) = init(node, stats, is_func_space, is_unit);
673
674 match node.object().kind_id().into() {
675 String | DQUOTE | Program => {}
676 Comment => {
677 add_cloc_lines(stats, start, end);
678 }
679 ExpressionStatement | ExportStatement | ImportStatement | StatementBlock
680 | IfStatement | SwitchStatement | ForStatement | ForInStatement | WhileStatement
681 | DoStatement | TryStatement | WithStatement | BreakStatement | ContinueStatement
682 | DebuggerStatement | ReturnStatement | ThrowStatement | EmptyStatement
683 | StatementIdentifier => {
684 stats.lloc.logical_lines += 1;
685 }
686 _ => {
687 check_comment_ends_on_code_line(stats, start);
688 stats.ploc.lines.insert(start);
689 }
690 }
691 }
692}
693
694impl Loc for TsxCode {
695 fn compute(node: &Node, stats: &mut Stats, is_func_space: bool, is_unit: bool) {
696 use Tsx::*;
697
698 let (start, end) = init(node, stats, is_func_space, is_unit);
699
700 match node.object().kind_id().into() {
701 String | DQUOTE | Program => {}
702 Comment => {
703 add_cloc_lines(stats, start, end);
704 }
705 ExpressionStatement | ExportStatement | ImportStatement | StatementBlock
706 | IfStatement | SwitchStatement | ForStatement | ForInStatement | WhileStatement
707 | DoStatement | TryStatement | WithStatement | BreakStatement | ContinueStatement
708 | DebuggerStatement | ReturnStatement | ThrowStatement | EmptyStatement
709 | StatementIdentifier => {
710 stats.lloc.logical_lines += 1;
711 }
712 _ => {
713 check_comment_ends_on_code_line(stats, start);
714 stats.ploc.lines.insert(start);
715 }
716 }
717 }
718}
719
720impl Loc for RustCode {
721 fn compute(node: &Node, stats: &mut Stats, is_func_space: bool, is_unit: bool) {
722 use Rust::*;
723
724 let (start, end) = init(node, stats, is_func_space, is_unit);
725
726 match node.object().kind_id().into() {
727 StringLiteral | RawStringLiteral | Block | SourceFile => {}
728 LineComment | BlockComment => {
729 add_cloc_lines(stats, start, end);
730 }
731 Statement
732 | EmptyStatement
733 | ExpressionStatement
734 | LetDeclaration
735 | AssignmentExpression
736 | CompoundAssignmentExpr => {
737 stats.lloc.logical_lines += 1;
738 }
739 _ => {
740 check_comment_ends_on_code_line(stats, start);
741 stats.ploc.lines.insert(start);
742 }
743 }
744 }
745}
746
747impl Loc for CppCode {
748 fn compute(node: &Node, stats: &mut Stats, is_func_space: bool, is_unit: bool) {
749 use Cpp::*;
750
751 let (start, end) = init(node, stats, is_func_space, is_unit);
752
753 match node.object().kind_id().into() {
754 RawStringLiteral | StringLiteral | DeclarationList | FieldDeclarationList
755 | TranslationUnit => {}
756 Comment => {
757 add_cloc_lines(stats, start, end);
758 }
759 WhileStatement | SwitchStatement | CaseStatement | IfStatement | ForStatement
760 | ReturnStatement | BreakStatement | ContinueStatement | GotoStatement
761 | ThrowStatement | TryStatement | ExpressionStatement | LabeledStatement
762 | StatementIdentifier => {
763 stats.lloc.logical_lines += 1;
764 }
765 Declaration => {
766 if count_specific_ancestors!(
767 node,
768 WhileStatement | ForStatement | IfStatement,
769 CompoundStatement
770 ) == 0
771 {
772 stats.lloc.logical_lines += 1;
773 }
774 }
775 _ => {
776 check_comment_ends_on_code_line(stats, start);
777 stats.ploc.lines.insert(start);
778 }
779 }
780 }
781}
782
783impl Loc for JavaCode {
784 fn compute(node: &Node, stats: &mut Stats, is_func_space: bool, is_unit: bool) {
785 use Java::*;
786
787 let (start, end) = init(node, stats, is_func_space, is_unit);
788 let kind_id: Java = node.object().kind_id().into();
789 match kind_id {
792 Program => {}
793 LineComment | BlockComment => {
794 add_cloc_lines(stats, start, end);
795 }
796 AssertStatement | BreakStatement | ContinueStatement | DoStatement
797 | EnhancedForStatement | ExpressionStatement | ForStatement | IfStatement
798 | ReturnStatement | SwitchExpression | ThrowStatement | TryStatement
799 | WhileStatement => {
800 stats.lloc.logical_lines += 1;
801 }
802 LocalVariableDeclaration => {
803 if count_specific_ancestors!(node, ForStatement, Block) == 0 {
804 stats.lloc.logical_lines += 1;
808 }
809 }
810 _ => {
811 check_comment_ends_on_code_line(stats, start);
812 stats.ploc.lines.insert(start);
813 }
814 }
815 }
816}
817
818impl Loc for PreprocCode {}
819impl Loc for CcommentCode {}
820
821#[cfg(test)]
822mod tests {
823 use std::path::PathBuf;
824
825 use super::*;
826
827 #[test]
828 fn python_sloc() {
829 check_metrics!(
830 "
831
832 a = 42
833
834 ",
835 "foo.py",
836 PythonParser,
837 loc,
838 [(sloc, 1, usize), (sloc_min, 1, usize), (sloc_max, 1, usize)],
839 [(sloc_average, 1.0)] );
841 }
842
843 #[test]
844 fn python_blank() {
845 check_metrics!(
846 "
847 a = 42
848
849 b = 43
850
851 ",
852 "foo.py",
853 PythonParser,
854 loc,
855 [
856 (blank, 1, usize),
857 (blank_min, 1, usize),
858 (blank_max, 1, usize)
859 ],
860 [(blank_average, 1.0)] );
862 }
863
864 #[test]
865 fn rust_blank() {
866 check_metrics!(
867 "
868
869 let a = 42;
870
871 let b = 43;
872
873 ",
874 "foo.rs",
875 RustParser,
876 loc,
877 [
878 (blank, 1, usize),
879 (blank_min, 1, usize),
880 (blank_max, 1, usize)
881 ],
882 [(blank_average, 1.0)] );
884
885 check_metrics!(
886 "fn func() { /* comment */ }",
887 "foo.rs",
888 RustParser,
889 loc,
890 [
891 (blank, 0, usize),
892 (blank_min, 0, usize),
893 (blank_max, 0, usize)
894 ],
895 [(blank_average, 0.0)] );
897 }
898
899 #[test]
900 fn c_blank() {
901 check_metrics!(
902 "
903
904 int a = 42;
905
906 int b = 43;
907
908 ",
909 "foo.c",
910 CppParser,
911 loc,
912 [
913 (blank, 1, usize),
914 (blank_min, 1, usize),
915 (blank_max, 1, usize)
916 ],
917 [(blank_average, 1.0)] );
919 }
920
921 #[test]
922 fn python_no_zero_blank() {
923 check_metrics!(
926 "def ConnectToUpdateServer():
927 pool = 4
928
929 updateServer = -42
930 isConnected = False
931 currTry = 0
932 numRetries = 10 # Number of IPC connection retries before
933 # giving up.
934 numTries = 20 # Number of IPC connection tries before
935 # giving up.",
936 "foo.py",
937 PythonParser,
938 loc,
939 [
940 (sloc, 10, usize), (ploc, 7, usize), (lloc, 6, usize), (cloc, 4, usize), (blank, 1, usize) (sloc_min, 9, usize),
946 (ploc_min, 7, usize),
947 (lloc_min, 6, usize),
948 (cloc_min, 2, usize),
949 (blank_min, 1, usize),
950 (sloc_max, 9, usize),
951 (ploc_max, 7, usize),
952 (lloc_max, 6, usize),
953 (cloc_max, 2, usize),
954 (blank_max, 1, usize)
955 ],
956 [
957 (sloc_average, 5.0), (ploc_average, 3.5),
959 (lloc_average, 3.0),
960 (cloc_average, 2.0),
961 (blank_average, 0.5)
962 ]
963 );
964 }
965
966 #[test]
967 fn python_no_blank() {
968 check_metrics!(
971 "def ConnectToUpdateServer():
972 pool = 4
973 updateServer = -42
974 isConnected = False
975 currTry = 0
976 numRetries = 10 # Number of IPC connection retries before
977 # giving up.
978 numTries = 20 # Number of IPC connection tries before
979 # giving up.",
980 "foo.py",
981 PythonParser,
982 loc,
983 [
984 (sloc, 9, usize), (ploc, 7, usize), (lloc, 6, usize), (cloc, 4, usize), (blank, 0, usize), (sloc_min, 8, usize),
990 (ploc_min, 7, usize),
991 (lloc_min, 6, usize),
992 (cloc_min, 2, usize),
993 (blank_min, 0, usize),
994 (sloc_max, 8, usize),
995 (ploc_max, 7, usize),
996 (lloc_max, 6, usize),
997 (cloc_max, 2, usize),
998 (blank_max, 0, usize)
999 ],
1000 [
1001 (sloc_average, 4.5), (ploc_average, 3.5),
1003 (lloc_average, 3.0),
1004 (cloc_average, 2.0),
1005 (blank_average, 0.0)
1006 ]
1007 );
1008 }
1009
1010 #[test]
1011 fn python_no_zero_blank_more_comments() {
1012 check_metrics!(
1015 "def ConnectToUpdateServer():
1016 pool = 4
1017
1018 updateServer = -42
1019 isConnected = False
1020 currTry = 0 # Set this variable to 0
1021 numRetries = 10 # Number of IPC connection retries before
1022 # giving up.
1023 numTries = 20 # Number of IPC connection tries before
1024 # giving up.",
1025 "foo.py",
1026 PythonParser,
1027 loc,
1028 [
1029 (sloc, 10, usize), (ploc, 7, usize), (lloc, 6, usize), (cloc, 5, usize), (blank, 1, usize), (sloc_min, 9, usize),
1035 (ploc_min, 7, usize),
1036 (lloc_min, 6, usize),
1037 (cloc_min, 3, usize),
1038 (blank_min, 1, usize),
1039 (sloc_max, 9, usize),
1040 (ploc_max, 7, usize),
1041 (lloc_max, 6, usize),
1042 (cloc_max, 3, usize),
1043 (blank_max, 1, usize)
1044 ],
1045 [
1046 (sloc_average, 5.0), (ploc_average, 3.5),
1048 (lloc_average, 3.0),
1049 (cloc_average, 2.5),
1050 (blank_average, 0.5)
1051 ]
1052 );
1053 }
1054
1055 #[test]
1056 fn rust_no_zero_blank() {
1057 check_metrics!(
1060 "fn ConnectToUpdateServer() {
1061 let pool = 0;
1062
1063 let updateServer = -42;
1064 let isConnected = false;
1065 let currTry = 0;
1066 let numRetries = 10; // Number of IPC connection retries before
1067 // giving up.
1068 let numTries = 20; // Number of IPC connection tries before
1069 // giving up.
1070 }",
1071 "foo.rs",
1072 RustParser,
1073 loc,
1074 [
1075 (sloc, 11, usize), (ploc, 8, usize), (lloc, 6, usize), (cloc, 4, usize), (blank, 1, usize), (sloc_min, 11, usize),
1081 (ploc_min, 8, usize),
1082 (lloc_min, 6, usize),
1083 (cloc_min, 4, usize),
1084 (blank_min, 1, usize),
1085 (sloc_max, 11, usize),
1086 (ploc_max, 8, usize),
1087 (lloc_max, 6, usize),
1088 (cloc_max, 4, usize),
1089 (blank_max, 1, usize)
1090 ],
1091 [
1092 (sloc_average, 5.5), (ploc_average, 4.0),
1094 (lloc_average, 3.0),
1095 (cloc_average, 2.0),
1096 (blank_average, 0.5)
1097 ]
1098 );
1099 }
1100
1101 #[test]
1102 fn javascript_no_zero_blank() {
1103 check_metrics!(
1106 "function ConnectToUpdateServer() {
1107 var pool = 0;
1108
1109 var updateServer = -42;
1110 var isConnected = false;
1111 var currTry = 0;
1112 var numRetries = 10; // Number of IPC connection retries before
1113 // giving up.
1114 var numTries = 20; // Number of IPC connection tries before
1115 // giving up.
1116 }",
1117 "foo.js",
1118 JavascriptParser,
1119 loc,
1120 [
1121 (sloc, 11, usize), (ploc, 8, usize), (lloc, 1, usize), (cloc, 4, usize), (blank, 1, usize), (sloc_min, 11, usize),
1127 (ploc_min, 8, usize),
1128 (lloc_min, 1, usize),
1129 (cloc_min, 4, usize),
1130 (blank_min, 1, usize),
1131 (sloc_max, 11, usize),
1132 (ploc_max, 8, usize),
1133 (lloc_max, 1, usize),
1134 (cloc_max, 4, usize),
1135 (blank_max, 1, usize)
1136 ],
1137 [
1138 (sloc_average, 5.5), (ploc_average, 4.0),
1140 (lloc_average, 0.5),
1141 (cloc_average, 2.0),
1142 (blank_average, 0.5),
1143 ]
1144 );
1145 }
1146
1147 #[test]
1148 fn cpp_no_zero_blank() {
1149 check_metrics!(
1152 "void ConnectToUpdateServer() {
1153 int pool;
1154
1155 int updateServer = -42;
1156 bool isConnected = false;
1157 int currTry = 0;
1158 const int numRetries = 10; // Number of IPC connection retries before
1159 // giving up.
1160 const int numTries = 20; // Number of IPC connection tries before
1161 // giving up.
1162 }",
1163 "foo.cpp",
1164 CppParser,
1165 loc,
1166 [
1167 (sloc, 11, usize), (ploc, 8, usize), (lloc, 6, usize), (cloc, 4, usize), (blank, 1, usize), (sloc_min, 11, usize),
1173 (ploc_min, 8, usize),
1174 (lloc_min, 6, usize),
1175 (cloc_min, 4, usize),
1176 (blank_min, 1, usize),
1177 (sloc_max, 11, usize),
1178 (ploc_max, 8, usize),
1179 (lloc_max, 6, usize),
1180 (cloc_max, 4, usize),
1181 (blank_max, 1, usize)
1182 ],
1183 [
1184 (sloc_average, 5.5), (ploc_average, 4.0),
1186 (lloc_average, 3.0),
1187 (cloc_average, 2.0),
1188 (blank_average, 0.5)
1189 ]
1190 );
1191 }
1192
1193 #[test]
1194 fn cpp_code_line_start_block_blank() {
1195 check_metrics!(
1198 "void ConnectToUpdateServer() {
1199 int pool;
1200
1201 int updateServer = -42;
1202 bool isConnected = false;
1203 int currTry = 0;
1204 const int numRetries = 10; /* Number of IPC connection retries
1205 before
1206 giving up. */
1207 const int numTries = 20; // Number of IPC connection tries before
1208 // giving up.
1209 }",
1210 "foo.cpp",
1211 CppParser,
1212 loc,
1213 [
1214 (sloc, 12, usize), (ploc, 8, usize), (lloc, 6, usize), (cloc, 5, usize), (blank, 1, usize), (sloc_min, 12, usize),
1220 (ploc_min, 8, usize),
1221 (lloc_min, 6, usize),
1222 (cloc_min, 5, usize),
1223 (blank_min, 1, usize),
1224 (sloc_max, 12, usize),
1225 (ploc_max, 8, usize),
1226 (lloc_max, 6, usize),
1227 (cloc_max, 5, usize),
1228 (blank_max, 1, usize)
1229 ],
1230 [
1231 (sloc_average, 6.0), (ploc_average, 4.0),
1233 (lloc_average, 3.0),
1234 (cloc_average, 2.5),
1235 (blank_average, 0.5)
1236 ]
1237 );
1238 }
1239
1240 #[test]
1241 fn cpp_block_comment_blank() {
1242 check_metrics!(
1245 "void ConnectToUpdateServer() {
1246 int pool;
1247
1248 int updateServer = -42;
1249 bool isConnected = false;
1250 int currTry = 0;
1251 /* Number of IPC connection retries
1252 before
1253 giving up. */
1254 const int numRetries = 10;
1255 const int numTries = 20; // Number of IPC connection tries before
1256 // giving up.
1257 }",
1258 "foo.cpp",
1259 CppParser,
1260 loc,
1261 [
1262 (sloc, 13, usize), (ploc, 8, usize), (lloc, 6, usize), (cloc, 5, usize), (blank, 1, usize), (sloc_min, 13, usize),
1268 (ploc_min, 8, usize),
1269 (lloc_min, 6, usize),
1270 (cloc_min, 5, usize),
1271 (blank_min, 1, usize),
1272 (sloc_max, 13, usize),
1273 (ploc_max, 8, usize),
1274 (lloc_max, 6, usize),
1275 (cloc_max, 5, usize),
1276 (blank_max, 1, usize)
1277 ],
1278 [
1279 (sloc_average, 6.5), (ploc_average, 4.0),
1281 (lloc_average, 3.0),
1282 (cloc_average, 2.5),
1283 (blank_average, 0.5)
1284 ]
1285 );
1286 }
1287
1288 #[test]
1289 fn cpp_code_line_block_one_line_blank() {
1290 check_metrics!(
1293 "void ConnectToUpdateServer() {
1294 int pool;
1295
1296 int updateServer = -42;
1297 bool isConnected = false;
1298 int currTry = 0;
1299 /* Number of IPC connection retries before giving up. */ const int numRetries = 10;
1300 const int numTries = 20; // Number of IPC connection tries before
1301 // giving up.
1302 }",
1303 "foo.cpp",
1304 CppParser,
1305 loc,
1306 [
1307 (sloc, 10, usize), (ploc, 8, usize), (lloc, 6, usize), (cloc, 3, usize), (blank, 1, usize), (sloc_min, 10, usize),
1313 (ploc_min, 8, usize),
1314 (lloc_min, 6, usize),
1315 (cloc_min, 3, usize),
1316 (blank_min, 1, usize),
1317 (sloc_max, 10, usize),
1318 (ploc_max, 8, usize),
1319 (lloc_max, 6, usize),
1320 (cloc_max, 3, usize),
1321 (blank_max, 1, usize)
1322 ],
1323 [
1324 (sloc_average, 5.0), (ploc_average, 4.0),
1326 (lloc_average, 3.0),
1327 (cloc_average, 1.5),
1328 (blank_average, 0.5)
1329 ]
1330 );
1331 }
1332
1333 #[test]
1334 fn cpp_code_line_end_block_blank() {
1335 check_metrics!(
1338 "void ConnectToUpdateServer() {
1339 int pool;
1340
1341 int updateServer = -42;
1342 bool isConnected = false;
1343 int currTry = 0;
1344 /* Number of IPC connection retries
1345 before
1346 giving up. */ const int numRetries = 10;
1347 const int numTries = 20; // Number of IPC connection tries before
1348 // giving up.
1349 }",
1350 "foo.cpp",
1351 CppParser,
1352 loc,
1353 [
1354 (sloc, 12, usize), (ploc, 8, usize), (lloc, 6, usize), (cloc, 5, usize), (blank, 1, usize), (sloc_min, 12, usize),
1360 (ploc_min, 8, usize),
1361 (lloc_min, 6, usize),
1362 (cloc_min, 5, usize),
1363 (blank_min, 1, usize),
1364 (sloc_max, 12, usize),
1365 (ploc_max, 8, usize),
1366 (lloc_max, 6, usize),
1367 (cloc_max, 5, usize),
1368 (blank_max, 1, usize)
1369 ],
1370 [
1371 (sloc_average, 6.0), (ploc_average, 4.0),
1373 (lloc_average, 3.0),
1374 (cloc_average, 2.5),
1375 (blank_average, 0.5)
1376 ]
1377 );
1378 }
1379
1380 #[test]
1381 fn python_cloc() {
1382 check_metrics!(
1383 "\"\"\"Block comment
1384 Block comment
1385 \"\"\"
1386 # Line Comment
1387 a = 42 # Line Comment",
1388 "foo.py",
1389 PythonParser,
1390 loc,
1391 [(cloc, 5, usize), (cloc_min, 5, usize), (cloc_max, 5, usize)],
1392 [(cloc_average, 5.0)] );
1394 }
1395
1396 #[test]
1397 fn rust_cloc() {
1398 check_metrics!(
1399 "/*Block comment
1400 Block Comment*/
1401 //Line Comment
1402 /*Block Comment*/ let a = 42; // Line Comment",
1403 "foo.rs",
1404 RustParser,
1405 loc,
1406 [(cloc, 5, usize), (cloc_min, 5, usize), (cloc_max, 5, usize)],
1407 [(cloc_average, 5.0)] );
1409 }
1410
1411 #[test]
1412 fn c_cloc() {
1413 check_metrics!(
1414 "/*Block comment
1415 Block Comment*/
1416 //Line Comment
1417 /*Block Comment*/ int a = 42; // Line Comment",
1418 "foo.c",
1419 CppParser,
1420 loc,
1421 [(cloc, 5, usize), (cloc_min, 5, usize), (cloc_max, 5, usize)],
1422 [(cloc_average, 5.0)] );
1424 }
1425
1426 #[test]
1427 fn python_lloc() {
1428 check_metrics!(
1429 "for x in range(0,42):
1430 if x % 2 == 0:
1431 print(x)",
1432 "foo.py",
1433 PythonParser,
1434 loc,
1435 [(lloc, 3, usize), (lloc_min, 3, usize), (lloc_max, 3, usize)],
1436 [(lloc_average, 3.0)] );
1438 }
1439
1440 #[test]
1441 fn rust_lloc() {
1442 check_metrics!(
1443 "for x in 0..42 {
1444 if x % 2 == 0 {
1445 println!(\"{}\", x);
1446 }
1447 }",
1448 "foo.rs",
1449 RustParser,
1450 loc,
1451 [(lloc, 3, usize), (lloc_min, 3, usize), (lloc_max, 3, usize)],
1452 [(lloc_average, 3.0)] );
1454
1455 check_metrics!(
1457 "let a = 42;
1458 if true {
1459 42
1460 } else {
1461 43
1462 };",
1463 "foo.rs",
1464 RustParser,
1465 loc,
1466 [(lloc, 3, usize), (lloc_min, 3, usize), (lloc_max, 3, usize)],
1467 [(lloc_average, 3.0)] );
1469 }
1470
1471 #[test]
1472 fn c_lloc() {
1473 check_metrics!(
1474 "for (;;)
1475 break;",
1476 "foo.c",
1477 CppParser,
1478 loc,
1479 [(lloc, 2, usize), (lloc_min, 2, usize), (lloc_max, 2, usize)],
1480 [(lloc_average, 2.0)] );
1482 }
1483
1484 #[test]
1485 fn cpp_lloc() {
1486 check_metrics!(
1487 "nsTArray<xpcGCCallback> callbacks(extraGCCallbacks.Clone());
1488 for (uint32_t i = 0; i < callbacks.Length(); ++i) {
1489 callbacks[i](status);
1490 }",
1491 "foo.cpp",
1492 CppParser,
1493 loc,
1494 [(lloc, 3, usize), (lloc_min, 3, usize), (lloc_max, 3, usize)], [(lloc_average, 3.0)] );
1497 }
1498
1499 #[test]
1500 fn cpp_return_lloc() {
1501 check_metrics!(
1502 "uint8_t* pixel_data = frame.GetFrameDataAtPos(DesktopVector(x, y));
1503 return RgbaColor(pixel_data) == blank_pixel_;",
1504 "foo.cpp",
1505 CppParser,
1506 loc,
1507 [(lloc, 2, usize), (lloc_min, 2, usize), (lloc_max, 2, usize)], [(lloc_average, 2.0)] );
1510 }
1511
1512 #[test]
1513 fn cpp_for_lloc() {
1514 check_metrics!(
1515 "for (; start != end; ++start) {
1516 const unsigned char idx = *start;
1517 if (idx > 127 || !kValidTokenMap[idx]) return false;
1518 }",
1519 "foo.cpp",
1520 CppParser,
1521 loc,
1522 [(lloc, 4, usize), (lloc_min, 4, usize), (lloc_max, 4, usize)], [(lloc_average, 4.0)] );
1525 }
1526
1527 #[test]
1528 fn cpp_while_lloc() {
1529 check_metrics!(
1530 "while (sHeapAtoms) {
1531 HttpHeapAtom* next = sHeapAtoms->next;
1532 free(sHeapAtoms);
1533 }",
1534 "foo.cpp",
1535 CppParser,
1536 loc,
1537 [(lloc, 3, usize), (lloc_min, 3, usize), (lloc_max, 3, usize)], [(lloc_average, 3.0)] );
1540 }
1541
1542 #[test]
1543 fn python_string_on_new_line() {
1544 check_metrics!(
1546 "capabilities[\"goog:chromeOptions\"][\"androidPackage\"] = \\
1547 \"org.chromium.weblayer.shell\"",
1548 "foo.py",
1549 PythonParser,
1550 loc,
1551 [
1552 (sloc, 2, usize),
1553 (ploc, 2, usize),
1554 (lloc, 1, usize),
1555 (cloc, 0, usize),
1556 (blank, 0, usize),
1557 (sloc_min, 2, usize),
1558 (ploc_min, 2, usize),
1559 (lloc_min, 1, usize),
1560 (cloc_min, 0, usize),
1561 (blank_min, 0, usize),
1562 (sloc_max, 2, usize),
1563 (ploc_max, 2, usize),
1564 (lloc_max, 1, usize),
1565 (cloc_max, 0, usize),
1566 (blank_max, 0, usize)
1567 ],
1568 [
1569 (sloc_average, 2.0), (ploc_average, 2.0),
1571 (lloc_average, 1.0),
1572 (cloc_average, 0.0),
1573 (blank_average, 0.0)
1574 ]
1575 );
1576 }
1577
1578 #[test]
1579 fn rust_no_field_expression_lloc() {
1580 check_metrics!(
1581 "struct Foo {
1582 field: usize,
1583 }
1584 let foo = Foo { 42 };
1585 foo.field;",
1586 "foo.rs",
1587 RustParser,
1588 loc,
1589 [(lloc, 2, usize), (lloc_min, 2, usize), (lloc_max, 2, usize)],
1590 [(lloc_average, 2.0)] );
1592 }
1593
1594 #[test]
1595 fn rust_no_parenthesized_expression_lloc() {
1596 check_metrics!(
1597 "let a = (42 + 0);",
1598 "foo.rs",
1599 RustParser,
1600 loc,
1601 [(lloc, 1, usize), (lloc_min, 1, usize), (lloc_max, 1, usize)],
1602 [(lloc_average, 1.0)] );
1604 }
1605
1606 #[test]
1607 fn rust_no_array_expression_lloc() {
1608 check_metrics!(
1609 "let a = [0; 42];",
1610 "foo.rs",
1611 RustParser,
1612 loc,
1613 [(lloc, 1, usize), (lloc_min, 1, usize), (lloc_max, 1, usize)],
1614 [(lloc_average, 1.0)] );
1616 }
1617
1618 #[test]
1619 fn rust_no_tuple_expression_lloc() {
1620 check_metrics!(
1621 "let a = (0, 42);",
1622 "foo.rs",
1623 RustParser,
1624 loc,
1625 [(lloc, 1, usize), (lloc_min, 1, usize), (lloc_max, 1, usize)],
1626 [(lloc_average, 1.0)] );
1628 }
1629
1630 #[test]
1631 fn rust_no_unit_expression_lloc() {
1632 check_metrics!(
1633 "let a = ();",
1634 "foo.rs",
1635 RustParser,
1636 loc,
1637 [(lloc, 1, usize), (lloc_min, 1, usize), (lloc_max, 1, usize)],
1638 [(lloc_average, 1.0)] );
1640 }
1641
1642 #[test]
1643 fn rust_call_function_lloc() {
1644 check_metrics!(
1645 "let a = foo(); // +1
1646 foo(); // +1
1647 k!(foo()); // +1",
1648 "foo.rs",
1649 RustParser,
1650 loc,
1651 [(lloc, 3, usize), (lloc_min, 3, usize), (lloc_max, 3, usize)],
1652 [(lloc_average, 3.0)] );
1654 }
1655
1656 #[test]
1657 fn rust_macro_invocation_lloc() {
1658 check_metrics!(
1659 "let a = foo!(); // +1
1660 foo!(); // +1
1661 k(foo!()); // +1",
1662 "foo.rs",
1663 RustParser,
1664 loc,
1665 [(lloc, 3, usize), (lloc_min, 3, usize), (lloc_max, 3, usize)],
1666 [(lloc_average, 3.0)] );
1668 }
1669
1670 #[test]
1671 fn rust_function_in_loop_lloc() {
1672 check_metrics!(
1673 "for (a, b) in c.iter().enumerate() {} // +1
1674 while (a, b) in c.iter().enumerate() {} // +1
1675 while let Some(a) = c.strip_prefix(\"hi\") {} // +1",
1676 "foo.rs",
1677 RustParser,
1678 loc,
1679 [(lloc, 3, usize), (lloc_min, 3, usize), (lloc_max, 3, usize)],
1680 [(lloc_average, 3.0)] );
1682 }
1683
1684 #[test]
1685 fn rust_function_in_if_lloc() {
1686 check_metrics!(
1687 "if foo() {} // +1
1688 if let Some(a) = foo() {} // +1",
1689 "foo.rs",
1690 RustParser,
1691 loc,
1692 [(lloc, 2, usize), (lloc_min, 2, usize), (lloc_max, 2, usize)],
1693 [(lloc_average, 2.0)] );
1695 }
1696
1697 #[test]
1698 fn rust_function_in_return_lloc() {
1699 check_metrics!(
1700 "return foo();
1701 await foo();",
1702 "foo.rs",
1703 RustParser,
1704 loc,
1705 [(lloc, 2, usize), (lloc_min, 2, usize), (lloc_max, 2, usize)],
1706 [(lloc_average, 2.0)] );
1708 }
1709
1710 #[test]
1711 fn rust_closure_expression_lloc() {
1712 check_metrics!(
1713 "let a = |i: i32| -> i32 { i + 1 }; // +1
1714 a(42); // +1
1715 k(b.iter().map(|n| n.parse.ok().unwrap_or(42))); // +1",
1716 "foo.rs",
1717 RustParser,
1718 loc,
1719 [(lloc, 3, usize), (lloc_min, 0, usize), (lloc_max, 0, usize)],
1720 [(lloc_average, 1.0)] );
1722 }
1723
1724 #[test]
1725 fn python_general_loc() {
1726 check_metrics!(
1727 "def func(a,
1728 b,
1729 c):
1730 print(a)
1731 print(b)
1732 print(c)",
1733 "foo.py",
1734 PythonParser,
1735 loc,
1736 [
1737 (sloc, 6, usize), (ploc, 6, usize), (lloc, 3, usize), (cloc, 0, usize), (blank, 0, usize), (sloc_min, 6, usize),
1743 (ploc_min, 6, usize),
1744 (lloc_min, 3, usize),
1745 (cloc_min, 0, usize),
1746 (blank_min, 0, usize),
1747 (sloc_max, 6, usize),
1748 (ploc_max, 6, usize),
1749 (lloc_max, 3, usize),
1750 (cloc_max, 0, usize),
1751 (blank_max, 0, usize)
1752 ],
1753 [
1754 (sloc_average, 3.0), (ploc_average, 3.0),
1756 (lloc_average, 1.5),
1757 (cloc_average, 0.0),
1758 (blank_average, 0.0)
1759 ]
1760 );
1761 }
1762
1763 #[test]
1764 fn python_real_loc() {
1765 check_metrics!(
1766 "def web_socket_transfer_data(request):
1767 while True:
1768 line = request.ws_stream.receive_message()
1769 if line is None:
1770 return
1771 code, reason = line.split(' ', 1)
1772 if code is None or reason is None:
1773 return
1774 request.ws_stream.close_connection(int(code), reason)
1775 # close_connection() initiates closing handshake. It validates code
1776 # and reason. If you want to send a broken close frame for a test,
1777 # following code will be useful.
1778 # > data = struct.pack('!H', int(code)) + reason.encode('UTF-8')
1779 # > request.connection.write(stream.create_close_frame(data))
1780 # > # Suppress to re-respond client responding close frame.
1781 # > raise Exception(\"customized server initiated closing handshake\")",
1782 "foo.py",
1783 PythonParser,
1784 loc,
1785 [
1786 (sloc, 16, usize), (ploc, 9, usize), (lloc, 8, usize), (cloc, 7, usize), (blank, 0, usize), (sloc_min, 16, usize),
1792 (ploc_min, 9, usize),
1793 (lloc_min, 8, usize),
1794 (cloc_min, 7, usize),
1795 (blank_min, 0, usize),
1796 (sloc_max, 16, usize),
1797 (ploc_max, 9, usize),
1798 (lloc_max, 8, usize),
1799 (cloc_max, 7, usize),
1800 (blank_max, 0, usize)
1801 ],
1802 [
1803 (sloc_average, 8.0), (ploc_average, 4.5),
1805 (lloc_average, 4.0),
1806 (cloc_average, 3.5),
1807 (blank_average, 0.0)
1808 ]
1809 );
1810 }
1811
1812 #[test]
1813 fn javascript_real_loc() {
1814 check_metrics!(
1815 "assert.throws(Test262Error, function() {
1816 for (let { poisoned: x = ++initEvalCount } = poisonedProperty; ; ) {
1817 return;
1818 }
1819 });",
1820 "foo.js",
1821 JavascriptParser,
1822 loc,
1823 [
1824 (sloc, 5, usize), (ploc, 5, usize), (lloc, 6, usize), (cloc, 0, usize), (blank, 0, usize), (sloc_min, 5, usize),
1830 (ploc_min, 5, usize),
1831 (lloc_min, 5, usize),
1832 (cloc_min, 0, usize),
1833 (blank_min, 0, usize),
1834 (sloc_max, 5, usize),
1835 (ploc_max, 5, usize),
1836 (lloc_max, 5, usize),
1837 (cloc_max, 0, usize),
1838 (blank_max, 0, usize)
1839 ],
1840 [
1841 (sloc_average, 2.5), (ploc_average, 2.5),
1843 (lloc_average, 3.0),
1844 (cloc_average, 0.0),
1845 (blank_average, 0.0)
1846 ]
1847 );
1848 }
1849
1850 #[test]
1851 fn mozjs_real_loc() {
1852 check_metrics!(
1853 "assert.throws(Test262Error, function() {
1854 for (let { poisoned: x = ++initEvalCount } = poisonedProperty; ; ) {
1855 return;
1856 }
1857 });",
1858 "foo.js",
1859 MozjsParser,
1860 loc,
1861 [
1862 (sloc, 5, usize), (ploc, 5, usize), (lloc, 6, usize), (cloc, 0, usize), (blank, 0, usize), (sloc_min, 5, usize),
1868 (ploc_min, 5, usize),
1869 (lloc_min, 5, usize),
1870 (cloc_min, 0, usize),
1871 (blank_min, 0, usize),
1872 (sloc_max, 5, usize),
1873 (ploc_max, 5, usize),
1874 (lloc_max, 5, usize),
1875 (cloc_max, 0, usize),
1876 (blank_max, 0, usize)
1877 ],
1878 [
1879 (sloc_average, 2.5), (ploc_average, 2.5),
1881 (lloc_average, 3.0),
1882 (cloc_average, 0.0),
1883 (blank_average, 0.0)
1884 ]
1885 );
1886 }
1887
1888 #[test]
1889 fn cpp_namespace_loc() {
1890 check_metrics!(
1891 "namespace mozilla::dom::quota {} // namespace mozilla::dom::quota",
1892 "foo.cpp",
1893 CppParser,
1894 loc,
1895 [
1896 (sloc, 1, usize), (ploc, 1, usize), (lloc, 0, usize), (cloc, 1, usize), (blank, 0, usize), (sloc_min, 1, usize),
1902 (ploc_min, 1, usize),
1903 (lloc_min, 0, usize),
1904 (cloc_min, 0, usize),
1905 (blank_min, 0, usize),
1906 (sloc_max, 1, usize),
1907 (ploc_max, 1, usize),
1908 (lloc_max, 0, usize),
1909 (cloc_max, 0, usize),
1910 (blank_max, 0, usize)
1911 ],
1912 [
1913 (sloc_average, 0.5), (ploc_average, 0.5),
1915 (lloc_average, 0.0),
1916 (cloc_average, 0.5),
1917 (blank_average, 0.0)
1918 ]
1919 );
1920 }
1921
1922 #[test]
1923 fn java_comments() {
1924 check_metrics!(
1925 "for (int i = 0; i < 100; i++) { \
1926 // Print hello
1927 System.out.println(\"hello\"); \
1928 // Print world
1929 System.out.println(\"hello\"); \
1930 }",
1931 "foo.java",
1932 JavaParser,
1933 loc,
1934 [
1935 (cloc, 2, usize), ]
1937 );
1938 }
1939
1940 #[test]
1941 fn java_blank() {
1942 check_metrics!(
1943 "int x = 1;
1944
1945
1946 int y = 2;",
1947 "foo.java",
1948 JavaParser,
1949 loc,
1950 [
1951 (blank, 2, usize), ]
1953 );
1954 }
1955
1956 #[test]
1957 fn java_sloc() {
1958 check_metrics!(
1959 "for (int i = 0; i < 100; i++) {
1960 System.out.println(i);
1961 }",
1962 "foo.java",
1963 JavaParser,
1964 loc,
1965 [
1966 (sloc, 3, usize), ]
1968 );
1969 }
1970
1971 #[test]
1972 fn java_module_sloc() {
1973 check_metrics!(
1974 "module helloworld{
1975 exports com.test;
1976 }",
1977 "foo.java",
1978 JavaParser,
1979 loc,
1980 [
1981 (sloc, 3, usize), ]
1983 );
1984 }
1985
1986 #[test]
1987 fn java_single_ploc() {
1988 check_metrics!(
1989 "int x = 1;",
1990 "foo.java",
1991 JavaParser,
1992 loc,
1993 [
1994 (ploc, 1, usize), ]
1996 );
1997 }
1998
1999 #[test]
2000 fn java_simple_ploc() {
2001 check_metrics!(
2002 "for (int i = 0; i < 100; i = i++) {
2003 System.out.println(i);
2004 }",
2005 "foo.java",
2006 JavaParser,
2007 loc,
2008 [
2009 (ploc, 3, usize), ]
2011 );
2012 }
2013
2014 #[test]
2015 fn java_multi_ploc() {
2016 check_metrics!(
2017 "int x = 1;
2018 for (int i = 0; i < 100; i++) {
2019 System.out.println(i);
2020 }",
2021 "foo.java",
2022 JavaParser,
2023 loc,
2024 [
2025 (ploc, 4, usize), ]
2027 );
2028 }
2029
2030 #[test]
2031 fn java_single_statement_lloc() {
2032 check_metrics!(
2033 "int max = 10;",
2034 "foo.java",
2035 JavaParser,
2036 loc,
2037 [
2038 (lloc, 1, usize), ]
2040 );
2041 }
2042
2043 #[test]
2044 fn java_for_lloc() {
2045 check_metrics!(
2046 "for (int i = 0; i < 100; i++) { // + 1
2047 System.out.println(i); // + 1
2048 }",
2049 "foo.java",
2050 JavaParser,
2051 loc,
2052 [
2053 (lloc, 2, usize), ]
2055 );
2056 }
2057
2058 #[test]
2059 fn java_foreach_lloc() {
2060 check_metrics!(
2061 "
2062 int arr[]={12,13,14,44}; // +1
2063 for (int i:arr) { // +1
2064 System.out.println(i); // +1
2065 }",
2066 "foo.java",
2067 JavaParser,
2068 loc,
2069 [
2070 (lloc, 3, usize), ]
2072 );
2073 }
2074
2075 #[test]
2076 fn java_while_lloc() {
2077 check_metrics!(
2078 "
2079 int i=0; // +1
2080 while(i < 10) { // +1
2081 i++; // +1
2082 System.out.println(i); // +1
2083 }",
2084 "foo.java",
2085 JavaParser,
2086 loc,
2087 [
2088 (lloc, 4, usize), ]
2090 );
2091 }
2092
2093 #[test]
2094 fn java_do_while_lloc() {
2095 check_metrics!(
2096 "
2097 int i=0; // +1
2098 do { // +1
2099 i++; // +1
2100 System.out.println(i); // +1
2101 } while(i < 10)",
2102 "foo.java",
2103 JavaParser,
2104 loc,
2105 [
2106 (lloc, 4, usize), ]
2108 );
2109 }
2110
2111 #[test]
2112 fn java_switch_lloc() {
2113 check_metrics!(
2114 "switch(grade) { // +1
2115 case 'A' :
2116 System.out.println(\"Pass with distinction\"); // +1
2117 break; // +1
2118 case 'B' :
2119 case 'C' :
2120 System.out.println(\"Pass\"); // +1
2121 break; // +1
2122 case 'D' :
2123 System.out.println(\"At risk\"); // +1
2124 case 'F' :
2125 System.out.println(\"Fail\"); // +1
2126 break; // +1
2127 default :
2128 System.out.println(\"Invalid grade\"); // +1
2129 }",
2130 "foo.java",
2131 JavaParser,
2132 loc,
2133 [
2134 (lloc, 9, usize), ]
2136 );
2137 }
2138
2139 #[test]
2140 fn java_continue_lloc() {
2141 check_metrics!(
2142 "int max = 10; // +1
2143
2144 for (int i = 0; i < max; i++) { // +1
2145 if(i % 2 == 0) { continue;} + 2
2146 System.out.println(i); // +1
2147 }",
2148 "foo.java",
2149 JavaParser,
2150 loc,
2151 [
2152 (lloc, 5, usize), ]
2154 );
2155 }
2156
2157 #[test]
2158 fn java_try_lloc() {
2159 check_metrics!(
2160 "try { // +1
2161 int[] myNumbers = {1, 2, 3}; // +1
2162 System.out.println(myNumbers[10]); // +1
2163 } catch (Exception e) {
2164 System.out.println(e.getMessage()); // +1
2165 throw e; // +1
2166 }",
2167 "foo.java",
2168 JavaParser,
2169 loc,
2170 [
2171 (lloc, 5, usize), ]
2173 );
2174 }
2175
2176 #[test]
2177 fn java_class_loc() {
2178 check_metrics!(
2179 "
2180 public class Person {
2181 private String name;
2182 public Person(String name){
2183 this.name = name; // +1
2184 }
2185 public String getName() {
2186 return name; // +1
2187 }
2188 }",
2189 "foo.java",
2190 JavaParser,
2191 loc,
2192 [
2193 (lloc, 2, usize), ]
2195 );
2196 }
2197
2198 #[test]
2199 fn java_expressions_lloc() {
2200 check_metrics!(
2201 "int x = 10; // +1 local var declaration
2202 x=+89; // +1 expression statement
2203 int y = x * 2; // +1 local var declaration
2204 IntFunction double = (n) -> n*2; // +1 local var declaration
2205 int y2 = double(x); // +1 local var declaration
2206 System.out.println(\"double \" + x + \" = \" + y2); // +1 expression statement
2207 String message = (x % 2) == 0 ? \"Evenly done.\" : \"Oddly done.\"; // +1 local var declaration
2208 Object done = (Runnable) () -> { System.out.println(\"Done!\"); }; // +2 local var declaration + expression statement
2209 String s = \"string\"; // +1 local var declaration
2210 boolean isS = (s instanceof String); // +1 local var declaration
2211 done.run(); // +1 expression statement
2212 ",
2213 "foo.java",
2214 JavaParser,
2215 loc,
2216 [
2217 (lloc, 12, usize), ]
2219 );
2220 }
2221
2222 #[test]
2223 fn java_statement_inline_loc() {
2224 check_metrics!(
2225 "for (int i = 0; i < 100; i++) { System.out.println(\"hello\"); }",
2226 "foo.java",
2227 JavaParser,
2228 loc,
2229 [
2230 (ploc, 1, usize), (lloc, 2, usize), (cloc, 0, usize), ]
2234 );
2235 }
2236
2237 #[test]
2238 fn java_general_loc() {
2239 check_metrics!(
2240 "int max = 100;
2241
2242 /*
2243 Loop through and print
2244 from: 0
2245 to: max
2246 */
2247 for (int i = 0; i < max; i++) {
2248 // Print the value
2249 System.out.println(i);
2250 }",
2251 "foo.java",
2252 JavaParser,
2253 loc,
2254 [
2255 (sloc, 11, usize), (ploc, 4, usize), (lloc, 3, usize), (cloc, 6, usize), (blank, 1, usize) ]
2261 );
2262 }
2263
2264 #[test]
2265 fn java_main_class_loc() {
2266 check_metrics!(
2267 "package com.company;
2268 /**
2269 * The HelloWorldApp class implements an application that
2270 * simply prints \"Hello World!\" to standard output.
2271 */
2272
2273 class HelloWorldApp {
2274 public void main(String[] args) {
2275 String message = args.length == 0 ? \"Hello empty world\" : \"Hello world\"; // +1 lloc : 1 var assignment
2276 System.out.println(message); // Display the string. +1 lloc
2277 }
2278 }",
2279 "foo.java",
2280 JavaParser,
2281 loc,
2282 [
2283 (sloc, 12, usize), (ploc, 7, usize), (lloc, 2, usize), (cloc, 6, usize), (blank, 1, usize) ]
2289 );
2290 }
2291}