package coverage import ( "bufio" "fmt" "io" "strconv" "strings" ) // Parse creates a coverage files struct from a coverage file format // you must provide @gopkg which is the package name func Parse(r io.Reader, gopkg string) (*Files, error) { reader := bufio.NewReader(r) eof := false var n uint = 0 files := &Files{ files: make(map[string]File), packagePath: gopkg, } // read loop for true { n++ if eof { break } notrim, err := reader.ReadString('\n') if err == io.EOF { if len(notrim) > 0 { eof = true } else { break } } line := strings.Trim(notrim, " \t\r\n") if len(line) < 1 { continue } // ignore first line if n == 1 && line == "mode: set" { continue } // extract features from line var cover = Coverage{} // format: filename:startLine.startColumn,endLine.endColumn occurences count splitFile := strings.Split(line, ":") if len(splitFile) != 2 { return nil, fmt.Errorf("invalid format line %d", n) } filename := splitFile[0] if !strings.HasPrefix(filename, gopkg) { return nil, fmt.Errorf("invalid package name '%s' on line %d", gopkg, n) } filename = strings.TrimPrefix(filename, gopkg) if len(filename) < 2 { return nil, fmt.Errorf("invalid format line %d", n) } // remove starting '/' if filename[0] == '/' { filename = filename[1:] } splitSpace := strings.Split(splitFile[1], " ") if len(splitSpace) != 3 { return nil, fmt.Errorf("invalid format line %d", n) } separators := strings.Split(splitSpace[0], ",") if len(separators) != 2 { return nil, fmt.Errorf("invalid format line %d", n) } splitStart := strings.Split(separators[0], ".") if len(splitStart) != 2 { return nil, fmt.Errorf("invalid format line %d", n) } cover.StartLine, err = strconv.ParseUint(splitStart[0], 10, 64) if err != nil { return nil, fmt.Errorf("invalid format line %d", n) } cover.StartColumn, err = strconv.ParseUint(splitStart[1], 10, 64) if err != nil { return nil, fmt.Errorf("invalid format line %d", n) } splitEnd := strings.Split(separators[1], ".") if len(splitEnd) != 2 { return nil, fmt.Errorf("invalid format line %d", n) } cover.EndLine, err = strconv.ParseUint(splitEnd[0], 10, 64) if err != nil { return nil, fmt.Errorf("invalid format line %d", n) } cover.EndColumn, err = strconv.ParseUint(splitEnd[1], 10, 64) if err != nil { return nil, fmt.Errorf("invalid format line %d", n) } // append to files _, isset := files.files[filename] if !isset { files.files[filename] = make(File, 0) } files.files[filename] = append(files.files[filename], cover) } return files, nil }