@@ -18,7 +18,7 @@ use semver::Version;
18
18
use std:: {
19
19
collections:: BTreeMap ,
20
20
fmt:: Display ,
21
- ops:: { AddAssign , Deref , DerefMut } ,
21
+ ops:: { Deref , DerefMut , Range } ,
22
22
path:: { Path , PathBuf } ,
23
23
sync:: Arc ,
24
24
} ;
@@ -82,40 +82,29 @@ impl CoverageReport {
82
82
self . anchors . extend ( anchors) ;
83
83
}
84
84
85
- /// Get coverage summaries by source file path.
86
- pub fn summary_by_file ( & self ) -> impl Iterator < Item = ( PathBuf , CoverageSummary ) > {
87
- let mut summaries = BTreeMap :: new ( ) ;
88
-
89
- for ( version, items) in self . items . iter ( ) {
90
- for item in items {
91
- let Some ( path) =
92
- self . source_paths . get ( & ( version. clone ( ) , item. loc . source_id ) ) . cloned ( )
93
- else {
94
- continue ;
95
- } ;
96
- * summaries. entry ( path) . or_default ( ) += item;
97
- }
98
- }
99
-
100
- summaries. into_iter ( )
85
+ /// Returns an iterator over coverage summaries by source file path.
86
+ pub fn summary_by_file ( & self ) -> impl Iterator < Item = ( & Path , CoverageSummary ) > {
87
+ self . by_file ( |summary : & mut CoverageSummary , item| summary. add_item ( item) )
101
88
}
102
89
103
- /// Get coverage items by source file path.
104
- pub fn items_by_source ( & self ) -> impl Iterator < Item = ( PathBuf , Vec < CoverageItem > ) > {
105
- let mut items_by_source: BTreeMap < _ , Vec < _ > > = BTreeMap :: new ( ) ;
90
+ /// Returns an iterator over coverage items by source file path.
91
+ pub fn items_by_file ( & self ) -> impl Iterator < Item = ( & Path , Vec < & CoverageItem > ) > {
92
+ self . by_file ( |list : & mut Vec < _ > , item| list. push ( item) )
93
+ }
106
94
107
- for ( version, items) in self . items . iter ( ) {
95
+ fn by_file < ' a , T : Default > (
96
+ & ' a self ,
97
+ mut f : impl FnMut ( & mut T , & ' a CoverageItem ) ,
98
+ ) -> impl Iterator < Item = ( & ' a Path , T ) > {
99
+ let mut by_file: BTreeMap < & Path , T > = BTreeMap :: new ( ) ;
100
+ for ( version, items) in & self . items {
108
101
for item in items {
109
- let Some ( path) =
110
- self . source_paths . get ( & ( version. clone ( ) , item. loc . source_id ) ) . cloned ( )
111
- else {
112
- continue ;
113
- } ;
114
- items_by_source. entry ( path) . or_default ( ) . push ( item. clone ( ) ) ;
102
+ let key = ( version. clone ( ) , item. loc . source_id ) ;
103
+ let Some ( path) = self . source_paths . get ( & key) else { continue } ;
104
+ f ( by_file. entry ( path) . or_default ( ) , item) ;
115
105
}
116
106
}
117
-
118
- items_by_source. into_iter ( )
107
+ by_file. into_iter ( )
119
108
}
120
109
121
110
/// Processes data from a [`HitMap`] and sets hit counts for coverage items in this coverage
@@ -345,30 +334,34 @@ impl Display for CoverageItem {
345
334
}
346
335
}
347
336
337
+ /// A source location.
348
338
#[ derive( Clone , Debug ) ]
349
339
pub struct SourceLocation {
350
340
/// The source ID.
351
341
pub source_id : usize ,
352
342
/// The contract this source range is in.
353
343
pub contract_name : Arc < str > ,
354
- /// Start byte in the source code.
355
- pub start : u32 ,
356
- /// Number of bytes in the source code.
357
- pub length : Option < u32 > ,
358
- /// The line in the source code.
359
- pub line : usize ,
344
+ /// Byte range.
345
+ pub bytes : Range < u32 > ,
346
+ /// Line range. Indices are 1-based.
347
+ pub lines : Range < u32 > ,
360
348
}
361
349
362
350
impl Display for SourceLocation {
363
351
fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
364
- write ! (
365
- f,
366
- "source ID {}, line {}, chars {}-{}" ,
367
- self . source_id,
368
- self . line,
369
- self . start,
370
- self . length. map_or( self . start, |length| self . start + length)
371
- )
352
+ write ! ( f, "source ID {}, lines {:?}, bytes {:?}" , self . source_id, self . lines, self . bytes)
353
+ }
354
+ }
355
+
356
+ impl SourceLocation {
357
+ /// Returns the length of the byte range.
358
+ pub fn len ( & self ) -> u32 {
359
+ self . bytes . len ( ) as u32
360
+ }
361
+
362
+ /// Returns true if the byte range is empty.
363
+ pub fn is_empty ( & self ) -> bool {
364
+ self . len ( ) == 0
372
365
}
373
366
}
374
367
@@ -393,21 +386,43 @@ pub struct CoverageSummary {
393
386
pub function_hits : usize ,
394
387
}
395
388
396
- impl AddAssign < & Self > for CoverageSummary {
397
- fn add_assign ( & mut self , other : & Self ) {
398
- self . line_count += other. line_count ;
399
- self . line_hits += other. line_hits ;
400
- self . statement_count += other. statement_count ;
401
- self . statement_hits += other. statement_hits ;
402
- self . branch_count += other. branch_count ;
403
- self . branch_hits += other. branch_hits ;
404
- self . function_count += other. function_count ;
405
- self . function_hits += other. function_hits ;
389
+ impl CoverageSummary {
390
+ /// Creates a new, empty coverage summary.
391
+ pub fn new ( ) -> Self {
392
+ Self :: default ( )
393
+ }
394
+
395
+ /// Creates a coverage summary from a collection of coverage items.
396
+ pub fn from_items < ' a > ( items : impl IntoIterator < Item = & ' a CoverageItem > ) -> Self {
397
+ let mut summary = Self :: default ( ) ;
398
+ summary. add_items ( items) ;
399
+ summary
406
400
}
407
- }
408
401
409
- impl AddAssign < & CoverageItem > for CoverageSummary {
410
- fn add_assign ( & mut self , item : & CoverageItem ) {
402
+ /// Adds another coverage summary to this one.
403
+ pub fn merge ( & mut self , other : & Self ) {
404
+ let Self {
405
+ line_count,
406
+ line_hits,
407
+ statement_count,
408
+ statement_hits,
409
+ branch_count,
410
+ branch_hits,
411
+ function_count,
412
+ function_hits,
413
+ } = self ;
414
+ * line_count += other. line_count ;
415
+ * line_hits += other. line_hits ;
416
+ * statement_count += other. statement_count ;
417
+ * statement_hits += other. statement_hits ;
418
+ * branch_count += other. branch_count ;
419
+ * branch_hits += other. branch_hits ;
420
+ * function_count += other. function_count ;
421
+ * function_hits += other. function_hits ;
422
+ }
423
+
424
+ /// Adds a coverage item to this summary.
425
+ pub fn add_item ( & mut self , item : & CoverageItem ) {
411
426
match item. kind {
412
427
CoverageItemKind :: Line => {
413
428
self . line_count += 1 ;
@@ -435,4 +450,11 @@ impl AddAssign<&CoverageItem> for CoverageSummary {
435
450
}
436
451
}
437
452
}
453
+
454
+ /// Adds multiple coverage items to this summary.
455
+ pub fn add_items < ' a > ( & mut self , items : impl IntoIterator < Item = & ' a CoverageItem > ) {
456
+ for item in items {
457
+ self . add_item ( item) ;
458
+ }
459
+ }
438
460
}
0 commit comments