2018-05-08 11:54:30 +03:00

90 lines
2.1 KiB
Go

package printers
import (
"bytes"
"fmt"
"io/ioutil"
"time"
"github.com/fatih/color"
"github.com/golangci/golangci-lint/pkg/result"
"github.com/sirupsen/logrus"
)
type Text struct {
printIssuedLine bool
useColors bool
}
func NewText(printIssuedLine bool, useColors bool) *Text {
return &Text{
printIssuedLine: printIssuedLine,
useColors: useColors,
}
}
type linesCache [][]byte
type filesCache map[string]linesCache
func (p Text) SprintfColored(ca color.Attribute, format string, args ...interface{}) string {
if !p.useColors {
return fmt.Sprintf(format, args...)
}
c := color.New(ca)
return c.Sprintf(format, args...)
}
func (p Text) Print(issues chan result.Issue) (bool, error) {
var issuedLineExtractingDuration time.Duration
defer func() {
logrus.Infof("Extracting issued lines took %s", issuedLineExtractingDuration)
}()
gotAnyIssue := false
cache := filesCache{}
out := getOutWriter()
for i := range issues {
gotAnyIssue = true
text := p.SprintfColored(color.FgRed, "%s", i.Text)
pos := p.SprintfColored(color.Bold, "%s:%d", i.FilePath(), i.Line())
fmt.Fprintf(out, "%s: %s\n", pos, text)
if !p.printIssuedLine {
continue
}
fc := cache[i.FilePath()]
if fc == nil {
startedAt := time.Now()
// TODO: make more optimal algorithm: don't load all files into memory
fileBytes, err := ioutil.ReadFile(i.FilePath())
if err != nil {
return false, fmt.Errorf("can't read file %s for printing issued line: %s", i.FilePath(), err)
}
lines := bytes.Split(fileBytes, []byte("\n")) // TODO: what about \r\n?
fc = lines
cache[i.FilePath()] = fc
issuedLineExtractingDuration += time.Since(startedAt)
}
lineRange := i.GetLineRange()
for line := lineRange.From; line <= lineRange.To; line++ {
zeroIndexedLine := line - 1
if zeroIndexedLine >= len(fc) {
logrus.Warnf("No line %d in file %s", line, i.FilePath())
break
}
fmt.Fprintln(out, string(bytes.Trim(fc[zeroIndexedLine], "\r")))
}
}
if !gotAnyIssue {
outStr := p.SprintfColored(color.FgGreen, "Congrats! No issues were found.")
fmt.Fprintln(out, outStr)
}
return gotAnyIssue, nil
}