| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161 |
- package lintcmd
- import (
- "encoding/json"
- "fmt"
- "go/token"
- "io"
- "os"
- "path/filepath"
- "text/tabwriter"
- "honnef.co/go/tools/analysis/lint"
- )
- func shortPath(path string) string {
- cwd, err := os.Getwd()
- if err != nil {
- return path
- }
- if rel, err := filepath.Rel(cwd, path); err == nil && len(rel) < len(path) {
- return rel
- }
- return path
- }
- func relativePositionString(pos token.Position) string {
- s := shortPath(pos.Filename)
- if pos.IsValid() {
- if s != "" {
- s += ":"
- }
- s += fmt.Sprintf("%d:%d", pos.Line, pos.Column)
- }
- if s == "" {
- s = "-"
- }
- return s
- }
- type statter interface {
- Stats(total, errors, warnings, ignored int)
- }
- type formatter interface {
- Format(checks []*lint.Analyzer, diagnostics []diagnostic)
- }
- type textFormatter struct {
- W io.Writer
- }
- func (o textFormatter) Format(_ []*lint.Analyzer, ps []diagnostic) {
- for _, p := range ps {
- fmt.Fprintf(o.W, "%s: %s\n", relativePositionString(p.Position), p.String())
- for _, r := range p.Related {
- fmt.Fprintf(o.W, "\t%s: %s\n", relativePositionString(r.Position), r.Message)
- }
- }
- }
- type nullFormatter struct{}
- func (nullFormatter) Format([]*lint.Analyzer, []diagnostic) {}
- type jsonFormatter struct {
- W io.Writer
- }
- func (o jsonFormatter) Format(_ []*lint.Analyzer, ps []diagnostic) {
- type location struct {
- File string `json:"file"`
- Line int `json:"line"`
- Column int `json:"column"`
- }
- type related struct {
- Location location `json:"location"`
- End location `json:"end"`
- Message string `json:"message"`
- }
- enc := json.NewEncoder(o.W)
- for _, p := range ps {
- jp := struct {
- Code string `json:"code"`
- Severity string `json:"severity,omitempty"`
- Location location `json:"location"`
- End location `json:"end"`
- Message string `json:"message"`
- Related []related `json:"related,omitempty"`
- }{
- Code: p.Category,
- Severity: p.Severity.String(),
- Location: location{
- File: p.Position.Filename,
- Line: p.Position.Line,
- Column: p.Position.Column,
- },
- End: location{
- File: p.End.Filename,
- Line: p.End.Line,
- Column: p.End.Column,
- },
- Message: p.Message,
- }
- for _, r := range p.Related {
- jp.Related = append(jp.Related, related{
- Location: location{
- File: r.Position.Filename,
- Line: r.Position.Line,
- Column: r.Position.Column,
- },
- End: location{
- File: r.End.Filename,
- Line: r.End.Line,
- Column: r.End.Column,
- },
- Message: r.Message,
- })
- }
- _ = enc.Encode(jp)
- }
- }
- type stylishFormatter struct {
- W io.Writer
- prevFile string
- tw *tabwriter.Writer
- }
- func (o *stylishFormatter) Format(_ []*lint.Analyzer, ps []diagnostic) {
- for _, p := range ps {
- pos := p.Position
- if pos.Filename == "" {
- pos.Filename = "-"
- }
- if pos.Filename != o.prevFile {
- if o.prevFile != "" {
- o.tw.Flush()
- fmt.Fprintln(o.W)
- }
- fmt.Fprintln(o.W, pos.Filename)
- o.prevFile = pos.Filename
- o.tw = tabwriter.NewWriter(o.W, 0, 4, 2, ' ', 0)
- }
- fmt.Fprintf(o.tw, " (%d, %d)\t%s\t%s\n", pos.Line, pos.Column, p.Category, p.Message)
- for _, r := range p.Related {
- fmt.Fprintf(o.tw, " (%d, %d)\t\t %s\n", r.Position.Line, r.Position.Column, r.Message)
- }
- }
- }
- func (o *stylishFormatter) Stats(total, errors, warnings, ignored int) {
- if o.tw != nil {
- o.tw.Flush()
- fmt.Fprintln(o.W)
- }
- fmt.Fprintf(o.W, " ✖ %d problems (%d errors, %d warnings, %d ignored)\n",
- total, errors, warnings, ignored)
- }
|