From c8bd9549a5b665fdf569de3088a06e1b8c5ebad3 Mon Sep 17 00:00:00 2001 From: Sergey Vilgelm Date: Sat, 18 Jul 2020 21:33:47 -0500 Subject: [PATCH] Support --fix for gofumpt (#1239) --- go.mod | 1 + go.sum | 2 ++ pkg/golinters/gofmt.go | 2 +- pkg/golinters/gofmt_common.go | 42 ++++++++++++++++------------- pkg/golinters/gofumpt.go | 34 +++++++++++++++-------- pkg/golinters/goimports.go | 2 +- test/testdata/fix/in/gofumpt.go | 9 +++++++ test/testdata/fix/out/gofumpt.go | 9 +++++++ test/testdata/gofumpt.go | 5 +--- test/testdata/gofumpt_with_extra.go | 9 +++++++ 10 files changed, 80 insertions(+), 35 deletions(-) create mode 100644 test/testdata/fix/in/gofumpt.go create mode 100644 test/testdata/fix/out/gofumpt.go create mode 100644 test/testdata/gofumpt_with_extra.go diff --git a/go.mod b/go.mod index 085d605fa7c0..aa0b8cce4cdd 100644 --- a/go.mod +++ b/go.mod @@ -39,6 +39,7 @@ require ( github.com/ryancurrah/gomodguard v1.1.0 github.com/ryanrolds/sqlclosecheck v0.3.0 github.com/securego/gosec/v2 v2.3.0 + github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c github.com/shirou/gopsutil v0.0.0-20190901111213-e4ec7b275ada // v2.19.8 github.com/sirupsen/logrus v1.6.0 github.com/sonatard/noctx v0.0.1 diff --git a/go.sum b/go.sum index b97684db8b2d..e39eac0981a6 100644 --- a/go.sum +++ b/go.sum @@ -307,6 +307,8 @@ github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/securego/gosec/v2 v2.3.0 h1:y/9mCF2WPDbSDpL3QDWZD3HHGrSYw0QSHnCqTfs4JPE= github.com/securego/gosec/v2 v2.3.0/go.mod h1:UzeVyUXbxukhLeHKV3VVqo7HdoQR9MrRfFmZYotn8ME= +github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c h1:W65qqJCIOVP4jpqPQ0YvHYKwcMEMVWIzWC5iNQQfBTU= +github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c/go.mod h1:/PevMnwAxekIXwN8qQyfc5gl2NlkB3CQlkizAbOkeBs= github.com/shirou/gopsutil v0.0.0-20190901111213-e4ec7b275ada h1:WokF3GuxBeL+n4Lk4Fa8v9mbdjlrl7bHuneF4N1bk2I= github.com/shirou/gopsutil v0.0.0-20190901111213-e4ec7b275ada/go.mod h1:WWnYX4lzhCH5h/3YBfyVA3VbLYjlMZZAQcW9ojMexNc= github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4 h1:udFKJ0aHUL60LboW/A+DfgoHVedieIzIXE8uylPue0U= diff --git a/pkg/golinters/gofmt.go b/pkg/golinters/gofmt.go index a7bd88a738da..aa340dcf3c4e 100644 --- a/pkg/golinters/gofmt.go +++ b/pkg/golinters/gofmt.go @@ -46,7 +46,7 @@ func NewGofmt() *goanalysis.Linter { continue } - is, err := extractIssuesFromPatch(string(diff), lintCtx.Log, lintCtx, false) + is, err := extractIssuesFromPatch(string(diff), lintCtx.Log, lintCtx, gofmtName) if err != nil { return nil, errors.Wrapf(err, "can't extract issues from gofmt diff output %q", string(diff)) } diff --git a/pkg/golinters/gofmt_common.go b/pkg/golinters/gofmt_common.go index fb1e3f6623f9..afb0d0c1bcc2 100644 --- a/pkg/golinters/gofmt_common.go +++ b/pkg/golinters/gofmt_common.go @@ -207,7 +207,29 @@ func (p *hunkChangesParser) parse(h *diffpkg.Hunk) []Change { return p.ret } -func extractIssuesFromPatch(patch string, log logutils.Log, lintCtx *linter.Context, isGoimports bool) ([]result.Issue, error) { +func getErrorTextForLinter(lintCtx *linter.Context, linterName string) string { + text := "File is not formatted" + switch linterName { + case gofumptName: + text = "File is not `gofumpt`-ed" + if lintCtx.Settings().Gofumpt.ExtraRules { + text += " with `-extra`" + } + case gofmtName: + text = "File is not `gofmt`-ed" + if lintCtx.Settings().Gofmt.Simplify { + text += " with `-s`" + } + case goimportsName: + text = "File is not `goimports`-ed" + if lintCtx.Settings().Goimports.LocalPrefixes != "" { + text += " with -local " + lintCtx.Settings().Goimports.LocalPrefixes + } + } + return text +} + +func extractIssuesFromPatch(patch string, log logutils.Log, lintCtx *linter.Context, linterName string) ([]result.Issue, error) { diffs, err := diffpkg.ParseMultiFileDiff([]byte(patch)) if err != nil { return nil, errors.Wrap(err, "can't parse patch") @@ -225,35 +247,19 @@ func extractIssuesFromPatch(patch string, log logutils.Log, lintCtx *linter.Cont } for _, hunk := range d.Hunks { - var text string - if isGoimports { - text = "File is not `goimports`-ed" - if lintCtx.Settings().Goimports.LocalPrefixes != "" { - text += " with -local " + lintCtx.Settings().Goimports.LocalPrefixes - } - } else { - text = "File is not `gofmt`-ed" - if lintCtx.Settings().Gofmt.Simplify { - text += " with `-s`" - } - } p := hunkChangesParser{ log: log, } changes := p.parse(hunk) for _, change := range changes { change := change // fix scope - linterName := gofmtName - if isGoimports { - linterName = goimportsName - } i := result.Issue{ FromLinter: linterName, Pos: token.Position{ Filename: d.NewName, Line: change.LineRange.From, }, - Text: text, + Text: getErrorTextForLinter(lintCtx, linterName), Replacement: &change.Replacement, } if change.LineRange.From != change.LineRange.To { diff --git a/pkg/golinters/gofumpt.go b/pkg/golinters/gofumpt.go index eebd3c05aabe..e91e54eeafcc 100644 --- a/pkg/golinters/gofumpt.go +++ b/pkg/golinters/gofumpt.go @@ -3,17 +3,16 @@ package golinters import ( "bytes" "fmt" - "go/token" "io/ioutil" - "strings" "sync" + "github.com/pkg/errors" + "github.com/shazow/go-diff/difflib" "golang.org/x/tools/go/analysis" "mvdan.cc/gofumpt/format" "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" "github.com/golangci/golangci-lint/pkg/lint/linter" - "github.com/golangci/golangci-lint/pkg/result" ) const gofumptName = "gofumpt" @@ -21,6 +20,7 @@ const gofumptName = "gofumpt" func NewGofumpt() *goanalysis.Linter { var mu sync.Mutex var resIssues []goanalysis.Issue + differ := difflib.New() analyzer := &analysis.Analyzer{ Name: gofumptName, @@ -53,14 +53,26 @@ func NewGofumpt() *goanalysis.Linter { return nil, fmt.Errorf("error while running gofumpt: %w", err) } if !bytes.Equal(input, output) { - issues = append(issues, goanalysis.NewIssue(&result.Issue{ - FromLinter: gofumptName, - Text: "File is not `gofumpt`-ed", - Pos: token.Position{ - Filename: f, - Line: strings.Count(string(input), "\n"), - }, - }, pass)) + out := bytes.Buffer{} + _, err = out.WriteString(fmt.Sprintf("--- %[1]s\n+++ %[1]s\n", f)) + if err != nil { + return nil, fmt.Errorf("error while running gofumpt: %w", err) + } + + err = differ.Diff(&out, bytes.NewReader(input), bytes.NewReader(output)) + if err != nil { + return nil, fmt.Errorf("error while running gofumpt: %w", err) + } + + diff := out.String() + is, err := extractIssuesFromPatch(diff, lintCtx.Log, lintCtx, gofumptName) + if err != nil { + return nil, errors.Wrapf(err, "can't extract issues from gofumpt diff output %q", diff) + } + + for i := range is { + issues = append(issues, goanalysis.NewIssue(&is[i], pass)) + } } } diff --git a/pkg/golinters/goimports.go b/pkg/golinters/goimports.go index 97767db8b984..9ea4558f40cc 100644 --- a/pkg/golinters/goimports.go +++ b/pkg/golinters/goimports.go @@ -47,7 +47,7 @@ func NewGoimports() *goanalysis.Linter { continue } - is, err := extractIssuesFromPatch(string(diff), lintCtx.Log, lintCtx, true) + is, err := extractIssuesFromPatch(string(diff), lintCtx.Log, lintCtx, goimportsName) if err != nil { return nil, errors.Wrapf(err, "can't extract issues from gofmt diff output %q", string(diff)) } diff --git a/test/testdata/fix/in/gofumpt.go b/test/testdata/fix/in/gofumpt.go new file mode 100644 index 000000000000..762bfb4d7dbe --- /dev/null +++ b/test/testdata/fix/in/gofumpt.go @@ -0,0 +1,9 @@ +//args: -Egofumpt +//config: linters-settings.gofumpt.extra-rules=true +package testdata + +import "fmt" + +func GofmtNotExtra(bar string, baz string) { + fmt.Print(bar, baz) +} diff --git a/test/testdata/fix/out/gofumpt.go b/test/testdata/fix/out/gofumpt.go new file mode 100644 index 000000000000..91d9261c2c76 --- /dev/null +++ b/test/testdata/fix/out/gofumpt.go @@ -0,0 +1,9 @@ +//args: -Egofumpt +//config: linters-settings.gofumpt.extra-rules=true +package testdata + +import "fmt" + +func GofmtNotExtra(bar, baz string) { + fmt.Print(bar, baz) +} diff --git a/test/testdata/gofumpt.go b/test/testdata/gofumpt.go index a428f4d0d262..66d97d6e8d23 100644 --- a/test/testdata/gofumpt.go +++ b/test/testdata/gofumpt.go @@ -4,8 +4,5 @@ package testdata import "fmt" func GofumptNewLine() { - - fmt.Println("foo") + fmt.Println( "foo" ) // ERROR "File is not `gofumpt`-ed" } - -// ERROR "File is not `gofumpt`-ed" diff --git a/test/testdata/gofumpt_with_extra.go b/test/testdata/gofumpt_with_extra.go new file mode 100644 index 000000000000..e5012396d241 --- /dev/null +++ b/test/testdata/gofumpt_with_extra.go @@ -0,0 +1,9 @@ +//args: -Egofumpt +//config: linters-settings.gofumpt.extra-rules=true +package testdata + +import "fmt" + +func GofmtNotExtra(bar string, baz string) { // ERROR "File is not `gofumpt`-ed with `-extra`" + fmt.Print("foo") +}