github.com/golangci/go-tools@v0.0.0-20190318060251-af6baa5dc196/lint/lintutil/format/format.go (about) 1 // Package format provides formatters for linter problems. 2 package format 3 4 import ( 5 "encoding/json" 6 "fmt" 7 "go/token" 8 "io" 9 "os" 10 "path/filepath" 11 "text/tabwriter" 12 13 "github.com/golangci/go-tools/lint" 14 ) 15 16 func shortPath(path string) string { 17 cwd, err := os.Getwd() 18 if err != nil { 19 return path 20 } 21 if rel, err := filepath.Rel(cwd, path); err == nil && len(rel) < len(path) { 22 return rel 23 } 24 return path 25 } 26 27 func relativePositionString(pos token.Position) string { 28 s := shortPath(pos.Filename) 29 if pos.IsValid() { 30 if s != "" { 31 s += ":" 32 } 33 s += fmt.Sprintf("%d:%d", pos.Line, pos.Column) 34 } 35 if s == "" { 36 s = "-" 37 } 38 return s 39 } 40 41 type Statter interface { 42 Stats(total, errors, warnings int) 43 } 44 45 type Formatter interface { 46 Format(p lint.Problem) 47 } 48 49 type Text struct { 50 W io.Writer 51 } 52 53 func (o Text) Format(p lint.Problem) { 54 fmt.Fprintf(o.W, "%v: %s\n", relativePositionString(p.Position), p.String()) 55 } 56 57 type JSON struct { 58 W io.Writer 59 } 60 61 func severity(s lint.Severity) string { 62 switch s { 63 case lint.Error: 64 return "error" 65 case lint.Warning: 66 return "warning" 67 case lint.Ignored: 68 return "ignored" 69 } 70 return "" 71 } 72 73 func (o JSON) Format(p lint.Problem) { 74 type location struct { 75 File string `json:"file"` 76 Line int `json:"line"` 77 Column int `json:"column"` 78 } 79 jp := struct { 80 Code string `json:"code"` 81 Severity string `json:"severity,omitempty"` 82 Location location `json:"location"` 83 Message string `json:"message"` 84 }{ 85 Code: p.Check, 86 Severity: severity(p.Severity), 87 Location: location{ 88 File: p.Position.Filename, 89 Line: p.Position.Line, 90 Column: p.Position.Column, 91 }, 92 Message: p.Text, 93 } 94 _ = json.NewEncoder(o.W).Encode(jp) 95 } 96 97 type Stylish struct { 98 W io.Writer 99 100 prevFile string 101 tw *tabwriter.Writer 102 } 103 104 func (o *Stylish) Format(p lint.Problem) { 105 if p.Position.Filename == "" { 106 p.Position.Filename = "-" 107 } 108 109 if p.Position.Filename != o.prevFile { 110 if o.prevFile != "" { 111 o.tw.Flush() 112 fmt.Fprintln(o.W) 113 } 114 fmt.Fprintln(o.W, p.Position.Filename) 115 o.prevFile = p.Position.Filename 116 o.tw = tabwriter.NewWriter(o.W, 0, 4, 2, ' ', 0) 117 } 118 fmt.Fprintf(o.tw, " (%d, %d)\t%s\t%s\n", p.Position.Line, p.Position.Column, p.Check, p.Text) 119 } 120 121 func (o *Stylish) Stats(total, errors, warnings int) { 122 if o.tw != nil { 123 o.tw.Flush() 124 fmt.Fprintln(o.W) 125 } 126 fmt.Fprintf(o.W, " ✖ %d problems (%d errors, %d warnings)\n", 127 total, errors, warnings) 128 }