main + printer [unstable]

This commit is contained in:
Adrien Marquès 2019-11-23 02:13:54 +01:00
parent 0ea53661f8
commit d40f92f496
2 changed files with 247 additions and 2 deletions

116
main.go Normal file
View File

@ -0,0 +1,116 @@
package main
import (
"flag"
"fmt"
"os"
"os/exec"
"path"
"strings"
"git.xdrm.io/go/cliverage/coverage"
)
func main() {
var codepath string
var coverfile string
var filepath string
var showUsage bool
flag.StringVar(&codepath, "d", "", "path to where lives your code")
flag.StringVar(&coverfile, "c", "", "path to the coverage file")
flag.StringVar(&filepath, "f", ".", "path to the file to print relative to -d option")
flag.BoolVar(&showUsage, "h", false, "")
flag.Usage = usage
flag.Parse()
// 1. show usage
if showUsage {
flag.Usage()
os.Exit(0)
}
// 2. missing required arguments
if len(codepath) < 1 || len(coverfile) < 1 {
fmt.Printf("%s missing arguments.\n\n", warning("/!\\"))
fmt.Printf("run -h to show usage.\n")
os.Exit(1)
}
// 3. check codepath
if info, err := os.Stat(codepath); true {
if err != nil && os.IsNotExist(err) {
fmt.Printf("%s codepath does not exist.\n\n", warning("/!\\"))
os.Exit(1)
}
if !info.IsDir() {
fmt.Printf("%s codepath is not a directory.\n\n", warning("/!\\"))
os.Exit(1)
}
if err != nil {
fmt.Printf("%s invalid codepath: %s.\n\n", warning("/!\\"), err)
os.Exit(1)
}
}
// 4. check coverfile
if info, err := os.Stat(coverfile); true {
if err != nil && os.IsNotExist(err) {
fmt.Printf("%s coverfile does not exist.\n\n", warning("/!\\"))
os.Exit(1)
}
if info.IsDir() {
fmt.Printf("%s coverfile is not a file.\n\n", warning("/!\\"))
os.Exit(1)
}
if err != nil {
fmt.Printf("%s invalid coverfile: %s.\n\n", warning("/!\\"), err)
os.Exit(1)
}
}
// 5. extract package path
os.Chdir(codepath)
var getGoPkgPath = exec.Command("go", "list", ".")
pkgPath, err := getGoPkgPath.Output()
if err != nil {
fmt.Printf("%s cannot get go package path: %s.\n\n", warning("/!\\"), err)
os.Exit(1)
}
// 6. parse coverfile
fdCoverfile, err := os.OpenFile(coverfile, os.O_RDONLY, 0755)
if err != nil {
fmt.Printf("%s cannot open coverfile: %s.\n\n", warning("/!\\"), err)
os.Exit(1)
}
defer fdCoverfile.Close()
parsedCoverage, err := coverage.Parse(fdCoverfile, strings.Trim(string(pkgPath), " \t\r\n"))
if err != nil {
fmt.Printf("%s error reading coverfile: %s.\n\n", warning("/!\\"), err)
os.Exit(1)
}
// 7. iterate over files
coveredFiles := parsedCoverage.GetFile(filepath)
for fname, coveredChunks := range coveredFiles.Files {
path := path.Join(codepath, fname)
fmt.Printf("----- %s -----\n", fname)
fdFile, err := os.OpenFile(path, os.O_RDONLY, 0755)
if err != nil {
fmt.Printf("%s cannot open file '%s': %s.\n\n", warning("/!\\"), path, err)
continue
}
defer fdFile.Close()
printCoverage(fdFile, os.Stdout, coveredChunks)
fmt.Printf("\n\n")
}
os.Exit(0)
}

133
print.go
View File

@ -1,6 +1,13 @@
package main package main
import "fmt" import (
"bufio"
"fmt"
"io"
"sort"
"git.xdrm.io/go/cliverage/coverage"
)
func bold(str string) string { func bold(str string) string {
return fmt.Sprintf("\x1b[1m%s\x1b[0m", str) return fmt.Sprintf("\x1b[1m%s\x1b[0m", str)
@ -10,6 +17,128 @@ func success(str string) string {
return fmt.Sprintf("\x1b[38;2;26;221;120m%s\x1b[0m", str) return fmt.Sprintf("\x1b[38;2;26;221;120m%s\x1b[0m", str)
} }
func error(str string) string { func warning(str string) string {
return fmt.Sprintf("\x1b[38;2;221;26;120m%s\x1b[0m", str) return fmt.Sprintf("\x1b[38;2;221;26;120m%s\x1b[0m", str)
} }
func printCoverage(r io.Reader, w io.Writer, chunks []coverage.Coverage) error {
reader := bufio.NewReader(r)
linen := uint64(0)
eof := false
coverPrefix := "\x1b[38;2;26;221;120m"
coverSuffix := "\x1b[0m"
// coverPrefix := "<<<"
// coverSuffix := ">>>"
for true {
linen++
if eof {
break
}
line, err := reader.ReadString('\n')
if err == io.EOF {
if len(line) < 1 {
break
} else {
eof = true
}
} else if err != nil {
return err
}
// check if we got a chunk start
concerned := make([]coverage.Coverage, 0)
for _, c := range chunks {
if c.StartLine == linen || c.EndLine == linen {
concerned = append(concerned, c)
}
}
// sort by max column before
sort.Slice(concerned, sortChunksByColumn(concerned, linen))
// if no coverage, write directly
if len(concerned) < 1 {
_, err := w.Write([]byte(fmt.Sprintf("%d\t| %s", linen, line)))
if err != nil {
return err
}
continue
}
// position each column with its prefix/suffix
for _, chunk := range concerned {
isStart := chunk.StartLine == linen
isEnd := chunk.EndLine == linen
if isStart && isEnd {
firstColumn := chunk.StartColumn
prefix := coverPrefix
lastColumn := chunk.EndColumn
suffix := coverSuffix
if chunk.EndColumn > chunk.StartColumn {
firstColumn = chunk.EndColumn
prefix = coverSuffix
lastColumn = chunk.StartColumn
suffix = coverPrefix
}
line = line[0:firstColumn-1] + prefix + line[firstColumn-1:]
if firstColumn != lastColumn {
line = line[0:lastColumn-1] + suffix + line[lastColumn-1:]
}
continue
}
if isEnd {
line = line[0:chunk.EndColumn-1] + coverSuffix + line[chunk.EndColumn-1:]
} else if isStart {
line = line[0:chunk.StartColumn-1] + coverPrefix + line[chunk.StartColumn-1:]
continue
}
}
_, err = w.Write([]byte(fmt.Sprintf("%d\t| %s", linen, line)))
if err != nil {
return err
}
}
return nil
}
func sortChunksByColumn(chunks []coverage.Coverage, lineNumber uint64) func(i, j int) bool {
return func(i, j int) bool {
// if start is concerned
iConcernedColumn := chunks[i].StartColumn
if chunks[i].EndLine == lineNumber {
iConcernedColumn = chunks[i].EndColumn
if chunks[i].StartLine == lineNumber && chunks[i].StartColumn > iConcernedColumn {
iConcernedColumn = chunks[i].StartColumn
}
}
jConcernedColumn := chunks[j].StartColumn
if chunks[j].EndLine == lineNumber {
jConcernedColumn = chunks[j].EndColumn
if chunks[j].StartLine == lineNumber && chunks[j].StartColumn > jConcernedColumn {
jConcernedColumn = chunks[j].StartColumn
}
}
if iConcernedColumn == jConcernedColumn {
// return the closing chunk before
if chunks[i].StartLine == lineNumber && chunks[j].EndLine == lineNumber {
return true
}
if chunks[i].EndLine == lineNumber && chunks[j].StartLine == lineNumber {
return false
}
}
return iConcernedColumn >= jConcernedColumn
}
}