Add support for multiple outputs (#2386)
This commit is contained in:
parent
669852edbb
commit
d209389625
@ -62,6 +62,10 @@ run:
|
|||||||
output:
|
output:
|
||||||
# colored-line-number|line-number|json|tab|checkstyle|code-climate|junit-xml|github-actions
|
# colored-line-number|line-number|json|tab|checkstyle|code-climate|junit-xml|github-actions
|
||||||
# default is "colored-line-number"
|
# default is "colored-line-number"
|
||||||
|
# multiple can be specified by separating them by comma, output can be provided
|
||||||
|
# for each of them by separating format name and path by colon symbol.
|
||||||
|
# Output path can be either `stdout`, `stderr` or path to the file to write to.
|
||||||
|
# Example "checkstyle:report.json,colored-line-number"
|
||||||
format: colored-line-number
|
format: colored-line-number
|
||||||
|
|
||||||
# print lines of code with issue, default is true
|
# print lines of code with issue, default is true
|
||||||
|
@ -26,6 +26,8 @@ import (
|
|||||||
"github.com/golangci/golangci-lint/pkg/result/processors"
|
"github.com/golangci/golangci-lint/pkg/result/processors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const defaultFileMode = 0644
|
||||||
|
|
||||||
func getDefaultIssueExcludeHelp() string {
|
func getDefaultIssueExcludeHelp() string {
|
||||||
parts := []string{"Use or not use default excludes:"}
|
parts := []string{"Use or not use default excludes:"}
|
||||||
for _, ep := range config.DefaultExcludePatterns {
|
for _, ep := range config.DefaultExcludePatterns {
|
||||||
@ -400,44 +402,89 @@ func (e *Executor) runAndPrint(ctx context.Context, args []string) error {
|
|||||||
return err // XXX: don't loose type
|
return err // XXX: don't loose type
|
||||||
}
|
}
|
||||||
|
|
||||||
p, err := e.createPrinter()
|
formats := strings.Split(e.cfg.Output.Format, ",")
|
||||||
if err != nil {
|
for _, format := range formats {
|
||||||
return err
|
out := strings.SplitN(format, ":", 2)
|
||||||
|
if len(out) < 2 {
|
||||||
|
out = append(out, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
err := e.printReports(ctx, issues, out[1], out[0])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
e.setExitCodeIfIssuesFound(issues)
|
e.setExitCodeIfIssuesFound(issues)
|
||||||
|
|
||||||
if err = p.Print(ctx, issues); err != nil {
|
|
||||||
return fmt.Errorf("can't print %d issues: %s", len(issues), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
e.fileCache.PrintStats(e.log)
|
e.fileCache.PrintStats(e.log)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Executor) createPrinter() (printers.Printer, error) {
|
func (e *Executor) printReports(ctx context.Context, issues []result.Issue, path, format string) error {
|
||||||
|
w, shouldClose, err := e.createWriter(path)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("can't create output for %s: %w", path, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
p, err := e.createPrinter(format, w)
|
||||||
|
if err != nil {
|
||||||
|
if file, ok := w.(io.Closer); shouldClose && ok {
|
||||||
|
_ = file.Close()
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = p.Print(ctx, issues); err != nil {
|
||||||
|
if file, ok := w.(io.Closer); shouldClose && ok {
|
||||||
|
_ = file.Close()
|
||||||
|
}
|
||||||
|
return fmt.Errorf("can't print %d issues: %s", len(issues), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if file, ok := w.(io.Closer); shouldClose && ok {
|
||||||
|
_ = file.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Executor) createWriter(path string) (io.Writer, bool, error) {
|
||||||
|
if path == "" || path == "stdout" {
|
||||||
|
return logutils.StdOut, false, nil
|
||||||
|
}
|
||||||
|
if path == "stderr" {
|
||||||
|
return logutils.StdErr, false, nil
|
||||||
|
}
|
||||||
|
f, err := os.OpenFile(path, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, defaultFileMode)
|
||||||
|
if err != nil {
|
||||||
|
return nil, false, err
|
||||||
|
}
|
||||||
|
return f, true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Executor) createPrinter(format string, w io.Writer) (printers.Printer, error) {
|
||||||
var p printers.Printer
|
var p printers.Printer
|
||||||
format := e.cfg.Output.Format
|
|
||||||
switch format {
|
switch format {
|
||||||
case config.OutFormatJSON:
|
case config.OutFormatJSON:
|
||||||
p = printers.NewJSON(&e.reportData)
|
p = printers.NewJSON(&e.reportData, w)
|
||||||
case config.OutFormatColoredLineNumber, config.OutFormatLineNumber:
|
case config.OutFormatColoredLineNumber, config.OutFormatLineNumber:
|
||||||
p = printers.NewText(e.cfg.Output.PrintIssuedLine,
|
p = printers.NewText(e.cfg.Output.PrintIssuedLine,
|
||||||
format == config.OutFormatColoredLineNumber, e.cfg.Output.PrintLinterName,
|
format == config.OutFormatColoredLineNumber, e.cfg.Output.PrintLinterName,
|
||||||
e.log.Child("text_printer"))
|
e.log.Child("text_printer"), w)
|
||||||
case config.OutFormatTab:
|
case config.OutFormatTab:
|
||||||
p = printers.NewTab(e.cfg.Output.PrintLinterName, e.log.Child("tab_printer"))
|
p = printers.NewTab(e.cfg.Output.PrintLinterName, e.log.Child("tab_printer"), w)
|
||||||
case config.OutFormatCheckstyle:
|
case config.OutFormatCheckstyle:
|
||||||
p = printers.NewCheckstyle()
|
p = printers.NewCheckstyle(w)
|
||||||
case config.OutFormatCodeClimate:
|
case config.OutFormatCodeClimate:
|
||||||
p = printers.NewCodeClimate()
|
p = printers.NewCodeClimate(w)
|
||||||
case config.OutFormatHTML:
|
case config.OutFormatHTML:
|
||||||
p = printers.NewHTML()
|
p = printers.NewHTML(w)
|
||||||
case config.OutFormatJunitXML:
|
case config.OutFormatJunitXML:
|
||||||
p = printers.NewJunitXML()
|
p = printers.NewJunitXML(w)
|
||||||
case config.OutFormatGithubActions:
|
case config.OutFormatGithubActions:
|
||||||
p = printers.NewGithub()
|
p = printers.NewGithub(w)
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("unknown output format %s", format)
|
return nil, fmt.Errorf("unknown output format %s", format)
|
||||||
}
|
}
|
||||||
|
@ -4,10 +4,10 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
|
|
||||||
"github.com/go-xmlfmt/xmlfmt"
|
"github.com/go-xmlfmt/xmlfmt"
|
||||||
|
|
||||||
"github.com/golangci/golangci-lint/pkg/logutils"
|
|
||||||
"github.com/golangci/golangci-lint/pkg/result"
|
"github.com/golangci/golangci-lint/pkg/result"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -32,13 +32,15 @@ type checkstyleError struct {
|
|||||||
|
|
||||||
const defaultCheckstyleSeverity = "error"
|
const defaultCheckstyleSeverity = "error"
|
||||||
|
|
||||||
type Checkstyle struct{}
|
type Checkstyle struct {
|
||||||
|
w io.Writer
|
||||||
func NewCheckstyle() *Checkstyle {
|
|
||||||
return &Checkstyle{}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (Checkstyle) Print(ctx context.Context, issues []result.Issue) error {
|
func NewCheckstyle(w io.Writer) *Checkstyle {
|
||||||
|
return &Checkstyle{w: w}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p Checkstyle) Print(ctx context.Context, issues []result.Issue) error {
|
||||||
out := checkstyleOutput{
|
out := checkstyleOutput{
|
||||||
Version: "5.0",
|
Version: "5.0",
|
||||||
}
|
}
|
||||||
@ -82,6 +84,10 @@ func (Checkstyle) Print(ctx context.Context, issues []result.Issue) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Fprintf(logutils.StdOut, "%s%s\n", xml.Header, xmlfmt.FormatXML(string(data), "", " "))
|
_, err = fmt.Fprintf(p.w, "%s%s\n", xml.Header, xmlfmt.FormatXML(string(data), "", " "))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -4,8 +4,8 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
|
|
||||||
"github.com/golangci/golangci-lint/pkg/logutils"
|
|
||||||
"github.com/golangci/golangci-lint/pkg/result"
|
"github.com/golangci/golangci-lint/pkg/result"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -24,10 +24,11 @@ type CodeClimateIssue struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type CodeClimate struct {
|
type CodeClimate struct {
|
||||||
|
w io.Writer
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewCodeClimate() *CodeClimate {
|
func NewCodeClimate(w io.Writer) *CodeClimate {
|
||||||
return &CodeClimate{}
|
return &CodeClimate{w: w}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p CodeClimate) Print(ctx context.Context, issues []result.Issue) error {
|
func (p CodeClimate) Print(ctx context.Context, issues []result.Issue) error {
|
||||||
@ -52,6 +53,9 @@ func (p CodeClimate) Print(ctx context.Context, issues []result.Issue) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Fprint(logutils.StdOut, string(outputJSON))
|
_, err = fmt.Fprint(p.w, string(outputJSON))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -3,20 +3,21 @@ package printers
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
|
|
||||||
"github.com/golangci/golangci-lint/pkg/logutils"
|
|
||||||
"github.com/golangci/golangci-lint/pkg/result"
|
"github.com/golangci/golangci-lint/pkg/result"
|
||||||
)
|
)
|
||||||
|
|
||||||
type github struct {
|
type github struct {
|
||||||
|
w io.Writer
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaultGithubSeverity = "error"
|
const defaultGithubSeverity = "error"
|
||||||
|
|
||||||
// NewGithub output format outputs issues according to GitHub actions format:
|
// NewGithub output format outputs issues according to GitHub actions format:
|
||||||
// https://help.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-an-error-message
|
// https://help.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-an-error-message
|
||||||
func NewGithub() Printer {
|
func NewGithub(w io.Writer) Printer {
|
||||||
return &github{}
|
return &github{w: w}
|
||||||
}
|
}
|
||||||
|
|
||||||
// print each line as: ::error file=app.js,line=10,col=15::Something went wrong
|
// print each line as: ::error file=app.js,line=10,col=15::Something went wrong
|
||||||
@ -35,9 +36,9 @@ func formatIssueAsGithub(issue *result.Issue) string {
|
|||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *github) Print(_ context.Context, issues []result.Issue) error {
|
func (p *github) Print(_ context.Context, issues []result.Issue) error {
|
||||||
for ind := range issues {
|
for ind := range issues {
|
||||||
_, err := fmt.Fprintln(logutils.StdOut, formatIssueAsGithub(&issues[ind]))
|
_, err := fmt.Fprintln(p.w, formatIssueAsGithub(&issues[ind]))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -4,9 +4,9 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"html/template"
|
"html/template"
|
||||||
|
"io"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/golangci/golangci-lint/pkg/logutils"
|
|
||||||
"github.com/golangci/golangci-lint/pkg/result"
|
"github.com/golangci/golangci-lint/pkg/result"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -123,13 +123,15 @@ type htmlIssue struct {
|
|||||||
Code string
|
Code string
|
||||||
}
|
}
|
||||||
|
|
||||||
type HTML struct{}
|
type HTML struct {
|
||||||
|
w io.Writer
|
||||||
func NewHTML() *HTML {
|
|
||||||
return &HTML{}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h HTML) Print(_ context.Context, issues []result.Issue) error {
|
func NewHTML(w io.Writer) *HTML {
|
||||||
|
return &HTML{w: w}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p HTML) Print(_ context.Context, issues []result.Issue) error {
|
||||||
var htmlIssues []htmlIssue
|
var htmlIssues []htmlIssue
|
||||||
|
|
||||||
for i := range issues {
|
for i := range issues {
|
||||||
@ -151,5 +153,5 @@ func (h HTML) Print(_ context.Context, issues []result.Issue) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return t.Execute(logutils.StdOut, struct{ Issues []htmlIssue }{Issues: htmlIssues})
|
return t.Execute(p.w, struct{ Issues []htmlIssue }{Issues: htmlIssues})
|
||||||
}
|
}
|
||||||
|
@ -3,20 +3,21 @@ package printers
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"io"
|
||||||
|
|
||||||
"github.com/golangci/golangci-lint/pkg/logutils"
|
|
||||||
"github.com/golangci/golangci-lint/pkg/report"
|
"github.com/golangci/golangci-lint/pkg/report"
|
||||||
"github.com/golangci/golangci-lint/pkg/result"
|
"github.com/golangci/golangci-lint/pkg/result"
|
||||||
)
|
)
|
||||||
|
|
||||||
type JSON struct {
|
type JSON struct {
|
||||||
rd *report.Data
|
rd *report.Data
|
||||||
|
w io.Writer
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewJSON(rd *report.Data) *JSON {
|
func NewJSON(rd *report.Data, w io.Writer) *JSON {
|
||||||
return &JSON{
|
return &JSON{
|
||||||
rd: rd,
|
rd: rd,
|
||||||
|
w: w,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -34,11 +35,5 @@ func (p JSON) Print(ctx context.Context, issues []result.Issue) error {
|
|||||||
res.Issues = []result.Issue{}
|
res.Issues = []result.Issue{}
|
||||||
}
|
}
|
||||||
|
|
||||||
outputJSON, err := json.Marshal(res)
|
return json.NewEncoder(p.w).Encode(res)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Fprint(logutils.StdOut, string(outputJSON))
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
@ -3,9 +3,9 @@ package printers
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
|
"io"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/golangci/golangci-lint/pkg/logutils"
|
|
||||||
"github.com/golangci/golangci-lint/pkg/result"
|
"github.com/golangci/golangci-lint/pkg/result"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -35,13 +35,14 @@ type failureXML struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type JunitXML struct {
|
type JunitXML struct {
|
||||||
|
w io.Writer
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewJunitXML() *JunitXML {
|
func NewJunitXML(w io.Writer) *JunitXML {
|
||||||
return &JunitXML{}
|
return &JunitXML{w: w}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (JunitXML) Print(ctx context.Context, issues []result.Issue) error {
|
func (p JunitXML) Print(ctx context.Context, issues []result.Issue) error {
|
||||||
suites := make(map[string]testSuiteXML) // use a map to group by file
|
suites := make(map[string]testSuiteXML) // use a map to group by file
|
||||||
|
|
||||||
for ind := range issues {
|
for ind := range issues {
|
||||||
@ -70,7 +71,7 @@ func (JunitXML) Print(ctx context.Context, issues []result.Issue) error {
|
|||||||
res.TestSuites = append(res.TestSuites, val)
|
res.TestSuites = append(res.TestSuites, val)
|
||||||
}
|
}
|
||||||
|
|
||||||
enc := xml.NewEncoder(logutils.StdOut)
|
enc := xml.NewEncoder(p.w)
|
||||||
enc.Indent("", " ")
|
enc.Indent("", " ")
|
||||||
if err := enc.Encode(res); err != nil {
|
if err := enc.Encode(res); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -15,12 +15,14 @@ import (
|
|||||||
type Tab struct {
|
type Tab struct {
|
||||||
printLinterName bool
|
printLinterName bool
|
||||||
log logutils.Log
|
log logutils.Log
|
||||||
|
w io.Writer
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTab(printLinterName bool, log logutils.Log) *Tab {
|
func NewTab(printLinterName bool, log logutils.Log, w io.Writer) *Tab {
|
||||||
return &Tab{
|
return &Tab{
|
||||||
printLinterName: printLinterName,
|
printLinterName: printLinterName,
|
||||||
log: log,
|
log: log,
|
||||||
|
w: w,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -30,7 +32,7 @@ func (p Tab) SprintfColored(ca color.Attribute, format string, args ...interface
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *Tab) Print(ctx context.Context, issues []result.Issue) error {
|
func (p *Tab) Print(ctx context.Context, issues []result.Issue) error {
|
||||||
w := tabwriter.NewWriter(logutils.StdOut, 0, 0, 2, ' ', 0)
|
w := tabwriter.NewWriter(p.w, 0, 0, 2, ' ', 0)
|
||||||
|
|
||||||
for i := range issues {
|
for i := range issues {
|
||||||
p.printIssue(&issues[i], w)
|
p.printIssue(&issues[i], w)
|
||||||
|
@ -3,6 +3,7 @@ package printers
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/fatih/color"
|
"github.com/fatih/color"
|
||||||
@ -17,14 +18,16 @@ type Text struct {
|
|||||||
printLinterName bool
|
printLinterName bool
|
||||||
|
|
||||||
log logutils.Log
|
log logutils.Log
|
||||||
|
w io.Writer
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewText(printIssuedLine, useColors, printLinterName bool, log logutils.Log) *Text {
|
func NewText(printIssuedLine, useColors, printLinterName bool, log logutils.Log, w io.Writer) *Text {
|
||||||
return &Text{
|
return &Text{
|
||||||
printIssuedLine: printIssuedLine,
|
printIssuedLine: printIssuedLine,
|
||||||
useColors: useColors,
|
useColors: useColors,
|
||||||
printLinterName: printLinterName,
|
printLinterName: printLinterName,
|
||||||
log: log,
|
log: log,
|
||||||
|
w: w,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,12 +64,12 @@ func (p Text) printIssue(i *result.Issue) {
|
|||||||
if i.Pos.Column != 0 {
|
if i.Pos.Column != 0 {
|
||||||
pos += fmt.Sprintf(":%d", i.Pos.Column)
|
pos += fmt.Sprintf(":%d", i.Pos.Column)
|
||||||
}
|
}
|
||||||
fmt.Fprintf(logutils.StdOut, "%s: %s\n", pos, text)
|
fmt.Fprintf(p.w, "%s: %s\n", pos, text)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Text) printSourceCode(i *result.Issue) {
|
func (p Text) printSourceCode(i *result.Issue) {
|
||||||
for _, line := range i.SourceLines {
|
for _, line := range i.SourceLines {
|
||||||
fmt.Fprintln(logutils.StdOut, line)
|
fmt.Fprintln(p.w, line)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,5 +90,5 @@ func (p Text) printUnderLinePointer(i *result.Issue) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Fprintf(logutils.StdOut, "%s%s\n", string(prefixRunes), p.SprintfColored(color.FgYellow, "^"))
|
fmt.Fprintf(p.w, "%s%s\n", string(prefixRunes), p.SprintfColored(color.FgYellow, "^"))
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,10 @@ package test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
@ -97,6 +99,64 @@ func TestGciLocal(t *testing.T) {
|
|||||||
ExpectHasIssue("testdata/gci/gci.go:7: File is not `gci`-ed")
|
ExpectHasIssue("testdata/gci/gci.go:7: File is not `gci`-ed")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestMultipleOutputs(t *testing.T) {
|
||||||
|
sourcePath := filepath.Join(testdataDir, "gci", "gci.go")
|
||||||
|
args := []string{
|
||||||
|
"--disable-all", "--print-issued-lines=false", "--print-linter-name=false", "--out-format=line-number,json:stdout",
|
||||||
|
sourcePath,
|
||||||
|
}
|
||||||
|
rc := extractRunContextFromComments(t, sourcePath)
|
||||||
|
args = append(args, rc.args...)
|
||||||
|
|
||||||
|
cfg, err := yaml.Marshal(rc.config)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
testshared.NewLintRunner(t).RunWithYamlConfig(string(cfg), args...).
|
||||||
|
ExpectHasIssue("testdata/gci/gci.go:7: File is not `gci`-ed").
|
||||||
|
ExpectOutputContains(`"Issues":[`)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStderrOutput(t *testing.T) {
|
||||||
|
sourcePath := filepath.Join(testdataDir, "gci", "gci.go")
|
||||||
|
args := []string{
|
||||||
|
"--disable-all", "--print-issued-lines=false", "--print-linter-name=false", "--out-format=line-number,json:stderr",
|
||||||
|
sourcePath,
|
||||||
|
}
|
||||||
|
rc := extractRunContextFromComments(t, sourcePath)
|
||||||
|
args = append(args, rc.args...)
|
||||||
|
|
||||||
|
cfg, err := yaml.Marshal(rc.config)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
testshared.NewLintRunner(t).RunWithYamlConfig(string(cfg), args...).
|
||||||
|
ExpectHasIssue("testdata/gci/gci.go:7: File is not `gci`-ed").
|
||||||
|
ExpectOutputContains(`"Issues":[`)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFileOutput(t *testing.T) {
|
||||||
|
resultPath := path.Join(t.TempDir(), "golangci_lint_test_result")
|
||||||
|
|
||||||
|
sourcePath := filepath.Join(testdataDir, "gci", "gci.go")
|
||||||
|
args := []string{
|
||||||
|
"--disable-all", "--print-issued-lines=false", "--print-linter-name=false",
|
||||||
|
fmt.Sprintf("--out-format=json:%s,line-number", resultPath),
|
||||||
|
sourcePath,
|
||||||
|
}
|
||||||
|
rc := extractRunContextFromComments(t, sourcePath)
|
||||||
|
args = append(args, rc.args...)
|
||||||
|
|
||||||
|
cfg, err := yaml.Marshal(rc.config)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
testshared.NewLintRunner(t).RunWithYamlConfig(string(cfg), args...).
|
||||||
|
ExpectHasIssue("testdata/gci/gci.go:7: File is not `gci`-ed").
|
||||||
|
ExpectOutputNotContains(`"Issues":[`)
|
||||||
|
|
||||||
|
b, err := os.ReadFile(resultPath)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Contains(t, string(b), `"Issues":[`)
|
||||||
|
}
|
||||||
|
|
||||||
func saveConfig(t *testing.T, cfg map[string]interface{}) (cfgPath string, finishFunc func()) {
|
func saveConfig(t *testing.T, cfg map[string]interface{}) (cfgPath string, finishFunc func()) {
|
||||||
f, err := os.CreateTemp("", "golangci_lint_test")
|
f, err := os.CreateTemp("", "golangci_lint_test")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
@ -76,6 +76,11 @@ func (r *RunResult) ExpectOutputContains(s string) *RunResult {
|
|||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *RunResult) ExpectOutputNotContains(s string) *RunResult {
|
||||||
|
assert.NotContains(r.t, r.output, s, "exit code is %d", r.exitCode)
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
func (r *RunResult) ExpectOutputEq(s string) *RunResult {
|
func (r *RunResult) ExpectOutputEq(s string) *RunResult {
|
||||||
assert.Equal(r.t, s, r.output, "exit code is %d", r.exitCode)
|
assert.Equal(r.t, s, r.output, "exit code is %d", r.exitCode)
|
||||||
return r
|
return r
|
||||||
|
Loading…
x
Reference in New Issue
Block a user