From 08315e74e0762bb7757dfb00b66931843bd02c5e Mon Sep 17 00:00:00 2001 From: Sergey Vilgelm Date: Thu, 25 Feb 2021 10:38:25 -0600 Subject: [PATCH 1/2] Printing out SuggestedFixes --- pkg/golinters/goanalysis/linter.go | 85 ++++++++++++++++++++++++++++++ pkg/printers/text.go | 8 +++ pkg/result/issue.go | 5 +- 3 files changed, 96 insertions(+), 2 deletions(-) diff --git a/pkg/golinters/goanalysis/linter.go b/pkg/golinters/goanalysis/linter.go index ef49e4284aa3..a119a8200dbc 100644 --- a/pkg/golinters/goanalysis/linter.go +++ b/pkg/golinters/goanalysis/linter.go @@ -144,6 +144,91 @@ func (lnt *Linter) configure() error { return nil } +func parseError(srcErr packages.Error) (*result.Issue, error) { + pos, err := libpackages.ParseErrorPosition(srcErr.Pos) + if err != nil { + return nil, err + } + + return &result.Issue{ + Pos: *pos, + Text: srcErr.Msg, + FromLinter: "typecheck", + }, nil +} + +func buildIssuesFromErrorsForTypecheckMode(errs []error, lintCtx *linter.Context) ([]result.Issue, error) { + var issues []result.Issue + uniqReportedIssues := map[string]bool{} + for _, err := range errs { + itErr, ok := errors.Cause(err).(*IllTypedError) + if !ok { + return nil, err + } + for _, err := range libpackages.ExtractErrors(itErr.Pkg) { + i, perr := parseError(err) + if perr != nil { // failed to parse + if uniqReportedIssues[err.Msg] { + continue + } + uniqReportedIssues[err.Msg] = true + lintCtx.Log.Errorf("typechecking error: %s", err.Msg) + } else { + i.Pkg = itErr.Pkg // to save to cache later + issues = append(issues, *i) + } + } + } + return issues, nil +} + +func buildIssues(diags []Diagnostic, linterNameBuilder func(diag *Diagnostic) string) []result.Issue { + var issues []result.Issue + for i := range diags { + diag := &diags[i] + linterName := linterNameBuilder(diag) + + var text string + if diag.Analyzer.Name == linterName { + text = diag.Message + } else { + text = fmt.Sprintf("%s: %s", diag.Analyzer.Name, diag.Message) + } + + var suggestedFixes string + if len(diag.SuggestedFixes) > 0 { + elems := []string{} + for _, fix := range diag.SuggestedFixes { + elems = append(elems, fix.Message) + for _, text := range fix.TextEdits { + elems = append(elems, string(text.NewText)) + } + } + suggestedFixes = strings.Join(elems, "\n") + } + + issues = append(issues, result.Issue{ + FromLinter: linterName, + Text: text, + SuggestedFixes: suggestedFixes, + Pos: diag.Position, + Pkg: diag.Pkg, + }) + + if len(diag.Related) > 0 { + for _, info := range diag.Related { + issues = append(issues, result.Issue{ + FromLinter: linterName, + Text: fmt.Sprintf("%s(related information): %s", diag.Analyzer.Name, info.Message), + Pos: diag.Pkg.Fset.Position(info.Pos), + Pkg: diag.Pkg, + }) + } + } + } + return issues +} + func (lnt *Linter) preRun(lintCtx *linter.Context) error { if err := analysis.Validate(lnt.analyzers); err != nil { return errors.Wrap(err, "failed to validate analyzers") diff --git a/pkg/printers/text.go b/pkg/printers/text.go index 1814528884c4..eeac4bd4aa12 100644 --- a/pkg/printers/text.go +++ b/pkg/printers/text.go @@ -47,6 +47,7 @@ func (p *Text) Print(ctx context.Context, issues []result.Issue) error { p.printSourceCode(&issues[i]) p.printUnderLinePointer(&issues[i]) + p.printSuggestedFixes(&issues[i]) } return nil @@ -64,6 +65,13 @@ func (p Text) printIssue(i *result.Issue) { fmt.Fprintf(logutils.StdOut, "%s: %s\n", pos, text) } +func (p Text) printSuggestedFixes(i *result.Issue) { + suggestedFixes := strings.TrimSpace(i.SuggestedFixes) + if suggestedFixes != "" { + fmt.Fprintln(logutils.StdOut, suggestedFixes) + } +} + func (p Text) printSourceCode(i *result.Issue) { for _, line := range i.SourceLines { fmt.Fprintln(logutils.StdOut, line) diff --git a/pkg/result/issue.go b/pkg/result/issue.go index 707a2b17cd95..809d16f69979 100644 --- a/pkg/result/issue.go +++ b/pkg/result/issue.go @@ -25,8 +25,9 @@ type InlineFix struct { } type Issue struct { - FromLinter string - Text string + FromLinter string + Text string + SuggestedFixes string Severity string From 16a3dfd278dc7ee28e8497291ac62fc7df8648ce Mon Sep 17 00:00:00 2001 From: Sergey Vilgelm Date: Thu, 25 Feb 2021 14:05:40 -0600 Subject: [PATCH 2/2] print with colors the Message and code --- pkg/golinters/goanalysis/linter.go | 85 ----------------------------- pkg/golinters/goanalysis/runners.go | 9 +-- pkg/printers/text.go | 17 +++++- pkg/result/issue.go | 3 +- 4 files changed, 21 insertions(+), 93 deletions(-) diff --git a/pkg/golinters/goanalysis/linter.go b/pkg/golinters/goanalysis/linter.go index a119a8200dbc..ef49e4284aa3 100644 --- a/pkg/golinters/goanalysis/linter.go +++ b/pkg/golinters/goanalysis/linter.go @@ -144,91 +144,6 @@ func (lnt *Linter) configure() error { return nil } -func parseError(srcErr packages.Error) (*result.Issue, error) { - pos, err := libpackages.ParseErrorPosition(srcErr.Pos) - if err != nil { - return nil, err - } - - return &result.Issue{ - Pos: *pos, - Text: srcErr.Msg, - FromLinter: "typecheck", - }, nil -} - -func buildIssuesFromErrorsForTypecheckMode(errs []error, lintCtx *linter.Context) ([]result.Issue, error) { - var issues []result.Issue - uniqReportedIssues := map[string]bool{} - for _, err := range errs { - itErr, ok := errors.Cause(err).(*IllTypedError) - if !ok { - return nil, err - } - for _, err := range libpackages.ExtractErrors(itErr.Pkg) { - i, perr := parseError(err) - if perr != nil { // failed to parse - if uniqReportedIssues[err.Msg] { - continue - } - uniqReportedIssues[err.Msg] = true - lintCtx.Log.Errorf("typechecking error: %s", err.Msg) - } else { - i.Pkg = itErr.Pkg // to save to cache later - issues = append(issues, *i) - } - } - } - return issues, nil -} - -func buildIssues(diags []Diagnostic, linterNameBuilder func(diag *Diagnostic) string) []result.Issue { - var issues []result.Issue - for i := range diags { - diag := &diags[i] - linterName := linterNameBuilder(diag) - - var text string - if diag.Analyzer.Name == linterName { - text = diag.Message - } else { - text = fmt.Sprintf("%s: %s", diag.Analyzer.Name, diag.Message) - } - - var suggestedFixes string - if len(diag.SuggestedFixes) > 0 { - elems := []string{} - for _, fix := range diag.SuggestedFixes { - elems = append(elems, fix.Message) - for _, text := range fix.TextEdits { - elems = append(elems, string(text.NewText)) - } - } - suggestedFixes = strings.Join(elems, "\n") - } - - issues = append(issues, result.Issue{ - FromLinter: linterName, - Text: text, - SuggestedFixes: suggestedFixes, - Pos: diag.Position, - Pkg: diag.Pkg, - }) - - if len(diag.Related) > 0 { - for _, info := range diag.Related { - issues = append(issues, result.Issue{ - FromLinter: linterName, - Text: fmt.Sprintf("%s(related information): %s", diag.Analyzer.Name, info.Message), - Pos: diag.Pkg.Fset.Position(info.Pos), - Pkg: diag.Pkg, - }) - } - } - } - return issues -} - func (lnt *Linter) preRun(lintCtx *linter.Context) error { if err := analysis.Validate(lnt.analyzers); err != nil { return errors.Wrap(err, "failed to validate analyzers") diff --git a/pkg/golinters/goanalysis/runners.go b/pkg/golinters/goanalysis/runners.go index 7e4cf902e79c..8e63cb5a35eb 100644 --- a/pkg/golinters/goanalysis/runners.go +++ b/pkg/golinters/goanalysis/runners.go @@ -98,10 +98,11 @@ func buildIssues(diags []Diagnostic, linterNameBuilder func(diag *Diagnostic) st } issues = append(issues, result.Issue{ - FromLinter: linterName, - Text: text, - Pos: diag.Position, - Pkg: diag.Pkg, + FromLinter: linterName, + Text: text, + SuggestedFixes: diag.SuggestedFixes, + Pos: diag.Position, + Pkg: diag.Pkg, }) if len(diag.Related) > 0 { diff --git a/pkg/printers/text.go b/pkg/printers/text.go index eeac4bd4aa12..39e4840c3223 100644 --- a/pkg/printers/text.go +++ b/pkg/printers/text.go @@ -66,9 +66,20 @@ func (p Text) printIssue(i *result.Issue) { } func (p Text) printSuggestedFixes(i *result.Issue) { - suggestedFixes := strings.TrimSpace(i.SuggestedFixes) - if suggestedFixes != "" { - fmt.Fprintln(logutils.StdOut, suggestedFixes) + var text string + if len(i.SuggestedFixes) > 0 { + for _, fix := range i.SuggestedFixes { + text += p.SprintfColored(color.FgRed, "%s\n", strings.TrimSpace(fix.Message)) + elems := []string{} + for _, text := range fix.TextEdits { + elems = append(elems, strings.TrimSpace(string(text.NewText))) + } + text += strings.Join(elems, "\n") + "\n" + } + } + + if text != "" { + fmt.Fprintln(logutils.StdOut, text) } } diff --git a/pkg/result/issue.go b/pkg/result/issue.go index 809d16f69979..a31b6c713658 100644 --- a/pkg/result/issue.go +++ b/pkg/result/issue.go @@ -5,6 +5,7 @@ import ( "fmt" "go/token" + "golang.org/x/tools/go/analysis" "golang.org/x/tools/go/packages" ) @@ -27,7 +28,7 @@ type InlineFix struct { type Issue struct { FromLinter string Text string - SuggestedFixes string + SuggestedFixes []analysis.SuggestedFix Severity string