142 lines
3.2 KiB
Go
142 lines
3.2 KiB
Go
package printers
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"strings"
|
|
|
|
"github.com/golangci/golangci-lint/pkg/config"
|
|
"github.com/golangci/golangci-lint/pkg/logutils"
|
|
"github.com/golangci/golangci-lint/pkg/report"
|
|
"github.com/golangci/golangci-lint/pkg/result"
|
|
)
|
|
|
|
const defaultFileMode = 0o644
|
|
|
|
type issuePrinter interface {
|
|
Print(issues []result.Issue) error
|
|
}
|
|
|
|
// Printer prints issues
|
|
type Printer struct {
|
|
cfg *config.Output
|
|
reportData *report.Data
|
|
|
|
log logutils.Log
|
|
|
|
stdOut io.Writer
|
|
stdErr io.Writer
|
|
}
|
|
|
|
// NewPrinter creates a new Printer.
|
|
func NewPrinter(log logutils.Log, cfg *config.Output, reportData *report.Data) (*Printer, error) {
|
|
if log == nil {
|
|
return nil, errors.New("missing log argument in constructor")
|
|
}
|
|
if cfg == nil {
|
|
return nil, errors.New("missing config argument in constructor")
|
|
}
|
|
if reportData == nil {
|
|
return nil, errors.New("missing reportData argument in constructor")
|
|
}
|
|
|
|
return &Printer{
|
|
cfg: cfg,
|
|
reportData: reportData,
|
|
log: log,
|
|
stdOut: logutils.StdOut,
|
|
stdErr: logutils.StdErr,
|
|
}, nil
|
|
}
|
|
|
|
// Print prints issues based on the formats defined
|
|
func (c *Printer) Print(issues []result.Issue) error {
|
|
formats := strings.Split(c.cfg.Format, ",")
|
|
|
|
for _, item := range formats {
|
|
format, path, _ := strings.Cut(item, ":")
|
|
err := c.printReports(issues, path, format)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (c *Printer) printReports(issues []result.Issue, path, format string) error {
|
|
w, shouldClose, err := c.createWriter(path)
|
|
if err != nil {
|
|
return fmt.Errorf("can't create output for %s: %w", path, err)
|
|
}
|
|
|
|
defer func() {
|
|
if file, ok := w.(io.Closer); shouldClose && ok {
|
|
_ = file.Close()
|
|
}
|
|
}()
|
|
|
|
p, err := c.createPrinter(format, w)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if err = p.Print(issues); err != nil {
|
|
return fmt.Errorf("can't print %d issues: %w", len(issues), err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (c *Printer) createWriter(path string) (io.Writer, bool, error) {
|
|
if path == "" || path == "stdout" {
|
|
return c.stdOut, false, nil
|
|
}
|
|
|
|
if path == "stderr" {
|
|
return c.stdErr, false, nil
|
|
}
|
|
|
|
f, err := os.OpenFile(path, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, defaultFileMode)
|
|
if err != nil {
|
|
return nil, false, err
|
|
}
|
|
|
|
return f, true, nil
|
|
}
|
|
|
|
func (c *Printer) createPrinter(format string, w io.Writer) (issuePrinter, error) {
|
|
var p issuePrinter
|
|
|
|
switch format {
|
|
case config.OutFormatJSON:
|
|
p = NewJSON(c.reportData, w)
|
|
case config.OutFormatColoredLineNumber, config.OutFormatLineNumber:
|
|
p = NewText(c.cfg.PrintIssuedLine,
|
|
format == config.OutFormatColoredLineNumber, c.cfg.PrintLinterName,
|
|
c.log.Child(logutils.DebugKeyTextPrinter), w)
|
|
case config.OutFormatTab, config.OutFormatColoredTab:
|
|
p = NewTab(c.cfg.PrintLinterName,
|
|
format == config.OutFormatColoredTab,
|
|
c.log.Child(logutils.DebugKeyTabPrinter), w)
|
|
case config.OutFormatCheckstyle:
|
|
p = NewCheckstyle(w)
|
|
case config.OutFormatCodeClimate:
|
|
p = NewCodeClimate(w)
|
|
case config.OutFormatHTML:
|
|
p = NewHTML(w)
|
|
case config.OutFormatJunitXML:
|
|
p = NewJunitXML(w)
|
|
case config.OutFormatGithubActions:
|
|
p = NewGitHub(w)
|
|
case config.OutFormatTeamCity:
|
|
p = NewTeamCity(w)
|
|
default:
|
|
return nil, fmt.Errorf("unknown output format %s", format)
|
|
}
|
|
|
|
return p, nil
|
|
}
|