src

Go monorepo.
git clone git://code.dwrz.net/src
Log | Files | Refs

format.go (3506B)


      1 package lintcmd
      2 
      3 import (
      4 	"encoding/json"
      5 	"fmt"
      6 	"go/token"
      7 	"io"
      8 	"os"
      9 	"path/filepath"
     10 	"text/tabwriter"
     11 
     12 	"honnef.co/go/tools/analysis/lint"
     13 )
     14 
     15 func shortPath(path string) string {
     16 	cwd, err := os.Getwd()
     17 	if err != nil {
     18 		return path
     19 	}
     20 	if rel, err := filepath.Rel(cwd, path); err == nil && len(rel) < len(path) {
     21 		return rel
     22 	}
     23 	return path
     24 }
     25 
     26 func relativePositionString(pos token.Position) string {
     27 	s := shortPath(pos.Filename)
     28 	if pos.IsValid() {
     29 		if s != "" {
     30 			s += ":"
     31 		}
     32 		s += fmt.Sprintf("%d:%d", pos.Line, pos.Column)
     33 	}
     34 	if s == "" {
     35 		s = "-"
     36 	}
     37 	return s
     38 }
     39 
     40 type statter interface {
     41 	Stats(total, errors, warnings, ignored int)
     42 }
     43 
     44 type formatter interface {
     45 	Format(checks []*lint.Analyzer, diagnostics []diagnostic)
     46 }
     47 
     48 type textFormatter struct {
     49 	W io.Writer
     50 }
     51 
     52 func (o textFormatter) Format(_ []*lint.Analyzer, ps []diagnostic) {
     53 	for _, p := range ps {
     54 		fmt.Fprintf(o.W, "%s: %s\n", relativePositionString(p.Position), p.String())
     55 		for _, r := range p.Related {
     56 			fmt.Fprintf(o.W, "\t%s: %s\n", relativePositionString(r.Position), r.Message)
     57 		}
     58 	}
     59 }
     60 
     61 type nullFormatter struct{}
     62 
     63 func (nullFormatter) Format([]*lint.Analyzer, []diagnostic) {}
     64 
     65 type jsonFormatter struct {
     66 	W io.Writer
     67 }
     68 
     69 func (o jsonFormatter) Format(_ []*lint.Analyzer, ps []diagnostic) {
     70 	type location struct {
     71 		File   string `json:"file"`
     72 		Line   int    `json:"line"`
     73 		Column int    `json:"column"`
     74 	}
     75 	type related struct {
     76 		Location location `json:"location"`
     77 		End      location `json:"end"`
     78 		Message  string   `json:"message"`
     79 	}
     80 
     81 	enc := json.NewEncoder(o.W)
     82 	for _, p := range ps {
     83 		jp := struct {
     84 			Code     string    `json:"code"`
     85 			Severity string    `json:"severity,omitempty"`
     86 			Location location  `json:"location"`
     87 			End      location  `json:"end"`
     88 			Message  string    `json:"message"`
     89 			Related  []related `json:"related,omitempty"`
     90 		}{
     91 			Code:     p.Category,
     92 			Severity: p.Severity.String(),
     93 			Location: location{
     94 				File:   p.Position.Filename,
     95 				Line:   p.Position.Line,
     96 				Column: p.Position.Column,
     97 			},
     98 			End: location{
     99 				File:   p.End.Filename,
    100 				Line:   p.End.Line,
    101 				Column: p.End.Column,
    102 			},
    103 			Message: p.Message,
    104 		}
    105 		for _, r := range p.Related {
    106 			jp.Related = append(jp.Related, related{
    107 				Location: location{
    108 					File:   r.Position.Filename,
    109 					Line:   r.Position.Line,
    110 					Column: r.Position.Column,
    111 				},
    112 				End: location{
    113 					File:   r.End.Filename,
    114 					Line:   r.End.Line,
    115 					Column: r.End.Column,
    116 				},
    117 				Message: r.Message,
    118 			})
    119 		}
    120 		_ = enc.Encode(jp)
    121 	}
    122 }
    123 
    124 type stylishFormatter struct {
    125 	W io.Writer
    126 
    127 	prevFile string
    128 	tw       *tabwriter.Writer
    129 }
    130 
    131 func (o *stylishFormatter) Format(_ []*lint.Analyzer, ps []diagnostic) {
    132 	for _, p := range ps {
    133 		pos := p.Position
    134 		if pos.Filename == "" {
    135 			pos.Filename = "-"
    136 		}
    137 
    138 		if pos.Filename != o.prevFile {
    139 			if o.prevFile != "" {
    140 				o.tw.Flush()
    141 				fmt.Fprintln(o.W)
    142 			}
    143 			fmt.Fprintln(o.W, pos.Filename)
    144 			o.prevFile = pos.Filename
    145 			o.tw = tabwriter.NewWriter(o.W, 0, 4, 2, ' ', 0)
    146 		}
    147 		fmt.Fprintf(o.tw, "  (%d, %d)\t%s\t%s\n", pos.Line, pos.Column, p.Category, p.Message)
    148 		for _, r := range p.Related {
    149 			fmt.Fprintf(o.tw, "    (%d, %d)\t\t  %s\n", r.Position.Line, r.Position.Column, r.Message)
    150 		}
    151 	}
    152 }
    153 
    154 func (o *stylishFormatter) Stats(total, errors, warnings, ignored int) {
    155 	if o.tw != nil {
    156 		o.tw.Flush()
    157 		fmt.Fprintln(o.W)
    158 	}
    159 	fmt.Fprintf(o.W, " ✖ %d problems (%d errors, %d warnings, %d ignored)\n",
    160 		total, errors, warnings, ignored)
    161 }