diff --git a/README.md b/README.md index 2c558f7..3ad8372 100644 --- a/README.md +++ b/README.md @@ -96,7 +96,8 @@ go get -u github.com/mgechev/revive - `ndjson` - outputs the failures as stream in newline delimited JSON (NDJSON) format. - `friendly` - outputs the failures when found. Shows summary of all the failures. - `stylish` - formats the failures in a table. Keep in mind that it doesn't stream the output so it might be perceived as slower compared to others. - + - `checkstyle` - outputs the failures in XML format compatible with that of Java's [Checkstyle](https://checkstyle.org/). + ### Sample Invocations ```shell diff --git a/config.go b/config.go index 7eb491b..4ce1020 100644 --- a/config.go +++ b/config.go @@ -63,6 +63,7 @@ var allFormatters = []lint.Formatter{ &formatter.JSON{}, &formatter.NDJSON{}, &formatter.Default{}, + &formatter.Checkstyle{}, } func getFormatters() map[string]lint.Formatter { diff --git a/formatter/checkstyle.go b/formatter/checkstyle.go new file mode 100644 index 0000000..6f7e20a --- /dev/null +++ b/formatter/checkstyle.go @@ -0,0 +1,76 @@ +package formatter + +import ( + "bytes" + "encoding/xml" + "github.com/mgechev/revive/lint" + plainTemplate "text/template" +) + +// Checkstyle is an implementation of the Formatter interface +// which formats the errors to Checkstyle-like format. +type Checkstyle struct { + Metadata lint.FormatterMetadata +} + +// Name returns the name of the formatter +func (f *Checkstyle) Name() string { + return "checkstyle" +} + +type issue struct { + Line int + Col int + What string + Confidence float64 + Severity lint.Severity + RuleName string +} + +// Format formats the failures gotten from the lint. +func (f *Checkstyle) Format(failures <-chan lint.Failure, config lint.RulesConfig) (string, error) { + var issues = map[string][]issue{} + for failure := range failures { + buf := new(bytes.Buffer) + xml.Escape(buf, []byte(failure.Failure)) + what := buf.String() + iss := issue{ + Line: failure.Position.Start.Line, + Col: failure.Position.Start.Column, + What: what, + Confidence: failure.Confidence, + Severity: severity(config, failure), + RuleName: failure.RuleName, + } + fn := failure.GetFilename() + if issues[fn] == nil { + issues[fn] = make([]issue, 0) + } + issues[fn] = append(issues[fn], iss) + } + + t, err := plainTemplate.New("revive").Parse(checkstyleTemplate) + if err != nil { + return "", err + } + + buf := new(bytes.Buffer) + + err = t.Execute(buf, issues) + if err != nil { + return "", err + } + + return buf.String(), nil +} + +const checkstyleTemplate = ` + +{{- range $k, $v := . }} + + {{- range $i, $issue := $v }} + + {{- end }} + +{{- end }} +`