github.com/covergates/covergates@v0.2.2-0.20201009050117-42ef8a19fb95/service/perl/file.go (about) 1 package perl 2 3 import ( 4 "sort" 5 6 "github.com/covergates/covergates/core" 7 log "github.com/sirupsen/logrus" 8 ) 9 10 // FileCollection of Perl source codes 11 type FileCollection struct { 12 collect map[string][]*core.File 13 } 14 15 type statementSlice []*core.StatementHit 16 17 func (s statementSlice) Len() int { return len(s) } 18 func (s statementSlice) Less(i, j int) bool { return s[i].LineNumber < s[j].LineNumber } 19 func (s statementSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] } 20 21 func newStatementHits(digest *coverDigest) []*core.StatementHit { 22 statements := make([]*core.StatementHit, len(digest.Statement)) 23 for i, line := range digest.Statement { 24 statements[i] = &core.StatementHit{ 25 LineNumber: line, 26 } 27 } 28 return statements 29 } 30 31 func newFile(name string, count *coverCount, digest *coverDigest) *core.File { 32 statements := newStatementHits(digest) 33 if len(count.Statement) > len(statements) { 34 log.Warningf("%s statement count does match to digest, will ignore extra statements", name) 35 log.Debug(count) 36 log.Debug(digest) 37 } 38 for i, c := range count.Statement { 39 if i >= len(statements) { 40 continue 41 } 42 statements[i].Hits = c 43 } 44 return &core.File{ 45 Name: name, 46 StatementHits: statements, 47 } 48 } 49 50 func newFileCollection() *FileCollection { 51 return &FileCollection{ 52 collect: make(map[string][]*core.File), 53 } 54 } 55 56 func (c *FileCollection) add(file *core.File) { 57 files, ok := c.collect[file.Name] 58 if !ok { 59 files = make([]*core.File, 0) 60 } 61 c.collect[file.Name] = append(files, file) 62 } 63 64 func sumStatementCoverage(hits []*core.StatementHit) float64 { 65 if len(hits) <= 0 { 66 return 0.0 67 } 68 s := 0 69 for _, hit := range hits { 70 if hit.Hits > 0 { 71 s++ 72 } 73 } 74 return float64(s) / float64(len(hits)) 75 } 76 77 func mergeFiles(files []*core.File) *core.File { 78 if len(files) <= 0 { 79 return nil 80 } 81 seed := files[0] 82 hits := make([]*core.StatementHit, len(seed.StatementHits)) 83 for i, hit := range seed.StatementHits { 84 hits[i] = hit.Copy() 85 } 86 merged := &core.File{ 87 Name: seed.Name, 88 StatementHits: hits, 89 } 90 for _, file := range files[1:] { 91 for i, hit := range file.StatementHits { 92 merged.StatementHits[i].Hits += hit.Hits 93 } 94 } 95 merged.StatementCoverage = sumStatementCoverage(merged.StatementHits) 96 return merged 97 } 98 99 func (c *FileCollection) mergedFiles() []*core.File { 100 files := make([]*core.File, 0) 101 for _, collect := range c.collect { 102 merged := mergeFiles(collect) 103 mergeStatementHist(merged) 104 files = append(files, merged) 105 } 106 return files 107 } 108 109 func mergeStatementHist(file *core.File) { 110 hitMap := make(map[int]*core.StatementHit) 111 for _, hit := range file.StatementHits { 112 if h, ok := hitMap[hit.LineNumber]; ok { 113 hit.Hits += h.Hits 114 } 115 hitMap[hit.LineNumber] = hit 116 } 117 statements := make(statementSlice, 0) 118 for _, hit := range hitMap { 119 statements = append(statements, hit) 120 } 121 sort.Sort(statements) 122 file.StatementHits = statements 123 }