coverage.go
1 package language 2 3 import ( 4 "encoding/json" 5 "errors" 6 "os" 7 "regexp" 8 9 pkgerrors "github.com/pkg/errors" 10 "github.com/symflower/eval-dev-quality/log" 11 ) 12 13 // CoverageBlockUnfolded is an unfolded representation of a coverage data block. 14 type CoverageBlockUnfolded struct { 15 // FileRange holds the file range. 16 FileRange string 17 // CoverageType holds the covered coverage type. 18 CoverageType string 19 // Count holds the execution count. 20 Count uint 21 } 22 23 // FileRangeMatch match a textual file range with lines and columns. 24 var FileRangeMatch = regexp.MustCompile(`^(.+):(\d+):(\d+)-(.+):(\d+):(\d+)$`) 25 26 // CoverageObjectCountOfFile parses the given coverage file and returns its coverage object count. 27 func CoverageObjectCountOfFile(logger *log.Logger, coverageFilePath string) (coverageObjectCount uint64, err error) { 28 coverageFile, err := os.ReadFile(coverageFilePath) 29 if err != nil { 30 return 0, pkgerrors.WithMessage(pkgerrors.WithStack(err), coverageFilePath) 31 } 32 33 // Log coverage objects. 34 logger.Printf("coverage objects: %s", string(coverageFile)) 35 36 var coverageData []CoverageBlockUnfolded 37 if err := json.Unmarshal(coverageFile, &coverageData); err != nil { 38 return 0, pkgerrors.WithMessage(pkgerrors.WithStack(err), string(coverageFile)) 39 } 40 for _, c := range coverageData { 41 if c.Count == 0 { 42 continue 43 } 44 45 fr := FileRangeMatch.FindStringSubmatch(c.FileRange) 46 if fr == nil { 47 return 0, pkgerrors.WithMessage(pkgerrors.WithStack(errors.New("could not match file range")), c.FileRange) 48 } 49 50 coverageObjectCount++ 51 } 52 53 return coverageObjectCount, nil 54 }