github.com/chenfeining/golangci-lint@v1.0.2-0.20230730162517-14c6c67868df/pkg/printers/checkstyle.go (about)

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