github.com/nozzle/golangci-lint@v1.49.0-nz3/pkg/printers/checkstyle.go (about)

     1  package printers
     2  
     3  import (
     4  	"context"
     5  	"encoding/xml"
     6  	"fmt"
     7  	"io"
     8  	"sort"
     9  
    10  	"github.com/go-xmlfmt/xmlfmt"
    11  
    12  	"github.com/golangci/golangci-lint/pkg/result"
    13  )
    14  
    15  type checkstyleOutput struct {
    16  	XMLName xml.Name          `xml:"checkstyle"`
    17  	Version string            `xml:"version,attr"`
    18  	Files   []*checkstyleFile `xml:"file"`
    19  }
    20  
    21  type checkstyleFile struct {
    22  	Name   string             `xml:"name,attr"`
    23  	Errors []*checkstyleError `xml:"error"`
    24  }
    25  
    26  type checkstyleError struct {
    27  	Column   int    `xml:"column,attr"`
    28  	Line     int    `xml:"line,attr"`
    29  	Message  string `xml:"message,attr"`
    30  	Severity string `xml:"severity,attr"`
    31  	Source   string `xml:"source,attr"`
    32  }
    33  
    34  const defaultCheckstyleSeverity = "error"
    35  
    36  type Checkstyle struct {
    37  	w io.Writer
    38  }
    39  
    40  func NewCheckstyle(w io.Writer) *Checkstyle {
    41  	return &Checkstyle{w: w}
    42  }
    43  
    44  func (p Checkstyle) Print(ctx context.Context, issues []result.Issue) error {
    45  	out := checkstyleOutput{
    46  		Version: "5.0",
    47  	}
    48  
    49  	files := map[string]*checkstyleFile{}
    50  
    51  	for i := range issues {
    52  		issue := &issues[i]
    53  		file, ok := files[issue.FilePath()]
    54  		if !ok {
    55  			file = &checkstyleFile{
    56  				Name: issue.FilePath(),
    57  			}
    58  
    59  			files[issue.FilePath()] = file
    60  		}
    61  
    62  		severity := defaultCheckstyleSeverity
    63  		if issue.Severity != "" {
    64  			severity = issue.Severity
    65  		}
    66  
    67  		newError := &checkstyleError{
    68  			Column:   issue.Column(),
    69  			Line:     issue.Line(),
    70  			Message:  issue.Text,
    71  			Source:   issue.FromLinter,
    72  			Severity: severity,
    73  		}
    74  
    75  		file.Errors = append(file.Errors, newError)
    76  	}
    77  
    78  	out.Files = make([]*checkstyleFile, 0, len(files))
    79  	for _, file := range files {
    80  		out.Files = append(out.Files, file)
    81  	}
    82  
    83  	sort.Slice(out.Files, func(i, j int) bool {
    84  		return out.Files[i].Name < out.Files[j].Name
    85  	})
    86  
    87  	data, err := xml.Marshal(&out)
    88  	if err != nil {
    89  		return err
    90  	}
    91  
    92  	_, err = fmt.Fprintf(p.w, "%s%s\n", xml.Header, xmlfmt.FormatXML(string(data), "", "  "))
    93  	if err != nil {
    94  		return err
    95  	}
    96  
    97  	return nil
    98  }