diff --git a/go.mod b/go.mod index 5dd94aea..4766d4a5 100644 --- a/go.mod +++ b/go.mod @@ -112,7 +112,7 @@ require ( github.com/tomarrell/wrapcheck/v2 v2.8.1 github.com/tommy-muehle/go-mnd/v2 v2.5.1 github.com/ultraware/funlen v0.1.0 - github.com/ultraware/whitespace v0.0.5 + github.com/ultraware/whitespace v0.1.0 github.com/uudashr/gocognit v1.1.2 github.com/valyala/quicktemplate v1.7.0 github.com/xen0n/gosmopolitan v1.2.2 diff --git a/go.sum b/go.sum index 734a283f..00abceb9 100644 --- a/go.sum +++ b/go.sum @@ -562,8 +562,8 @@ github.com/tommy-muehle/go-mnd/v2 v2.5.1 h1:NowYhSdyE/1zwK9QCLeRb6USWdoif80Ie+v+ github.com/tommy-muehle/go-mnd/v2 v2.5.1/go.mod h1:WsUAkMJMYww6l/ufffCD3m+P7LEvr8TnZn9lwVDlgzw= github.com/ultraware/funlen v0.1.0 h1:BuqclbkY6pO+cvxoq7OsktIXZpgBSkYTQtmwhAK81vI= github.com/ultraware/funlen v0.1.0/go.mod h1:XJqmOQja6DpxarLj6Jj1U7JuoS8PvL4nEqDaQhy22p4= -github.com/ultraware/whitespace v0.0.5 h1:hh+/cpIcopyMYbZNVov9iSxvJU3OYQg78Sfaqzi/CzI= -github.com/ultraware/whitespace v0.0.5/go.mod h1:aVMh/gQve5Maj9hQ/hg+F75lr/X5A89uZnzAmWSineA= +github.com/ultraware/whitespace v0.1.0 h1:O1HKYoh0kIeqE8sFqZf1o0qbORXUCOQFrlaQyZsczZw= +github.com/ultraware/whitespace v0.1.0/go.mod h1:/se4r3beMFNmewJ4Xmz0nMQ941GJt+qmSHGP9emHYe0= github.com/uudashr/gocognit v1.1.2 h1:l6BAEKJqQH2UpKAPKdMfZf5kE4W/2xk8pfU1OVLvniI= github.com/uudashr/gocognit v1.1.2/go.mod h1:aAVdLURqcanke8h3vg35BC++eseDm66Z7KmchI5et4k= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= diff --git a/pkg/golinters/revive.go b/pkg/golinters/revive.go index 28231957..1953b1f3 100644 --- a/pkg/golinters/revive.go +++ b/pkg/golinters/revive.go @@ -34,7 +34,7 @@ type jsonObject struct { // NewRevive returns a new Revive linter. // -//nolint:dupl + func NewRevive(settings *config.ReviveSettings) *goanalysis.Linter { var mu sync.Mutex var resIssues []goanalysis.Issue diff --git a/pkg/golinters/whitespace.go b/pkg/golinters/whitespace.go index e5941fa5..8fef6be9 100644 --- a/pkg/golinters/whitespace.go +++ b/pkg/golinters/whitespace.go @@ -2,7 +2,6 @@ package golinters import ( "fmt" - "go/token" "sync" "github.com/ultraware/whitespace" @@ -16,7 +15,6 @@ import ( const whitespaceName = "whitespace" -//nolint:dupl func NewWhitespace(settings *config.WhitespaceSettings) *goanalysis.Linter { var mu sync.Mutex var resIssues []goanalysis.Issue @@ -24,25 +22,22 @@ func NewWhitespace(settings *config.WhitespaceSettings) *goanalysis.Linter { var wsSettings whitespace.Settings if settings != nil { wsSettings = whitespace.Settings{ + Mode: whitespace.RunningModeGolangCI, MultiIf: settings.MultiIf, MultiFunc: settings.MultiFunc, } } - analyzer := &analysis.Analyzer{ - Name: whitespaceName, - Doc: goanalysis.TheOnlyanalyzerDoc, - Run: goanalysis.DummyRun, - } + a := whitespace.NewAnalyzer(&wsSettings) return goanalysis.NewLinter( - whitespaceName, - "Tool for detection of leading and trailing whitespace", - []*analysis.Analyzer{analyzer}, + a.Name, + a.Doc, + []*analysis.Analyzer{a}, nil, ).WithContextSetter(func(lintCtx *linter.Context) { - analyzer.Run = func(pass *analysis.Pass) (any, error) { - issues, err := runWhitespace(lintCtx, pass, wsSettings) + a.Run = func(pass *analysis.Pass) (any, error) { + issues, err := runWhitespace(pass, wsSettings) if err != nil { return nil, err } @@ -62,46 +57,45 @@ func NewWhitespace(settings *config.WhitespaceSettings) *goanalysis.Linter { }).WithLoadMode(goanalysis.LoadModeSyntax) } -func runWhitespace(lintCtx *linter.Context, pass *analysis.Pass, wsSettings whitespace.Settings) ([]goanalysis.Issue, error) { - var messages []whitespace.Message - for _, file := range pass.Files { - messages = append(messages, whitespace.Run(file, pass.Fset, wsSettings)...) - } +func runWhitespace(pass *analysis.Pass, wsSettings whitespace.Settings) ([]goanalysis.Issue, error) { + lintIssues := whitespace.Run(pass, &wsSettings) - if len(messages) == 0 { - return nil, nil - } - - issues := make([]goanalysis.Issue, len(messages)) - for k, i := range messages { - issue := result.Issue{ - Pos: token.Position{ - Filename: i.Pos.Filename, - Line: i.Pos.Line, - }, - LineRange: &result.Range{From: i.Pos.Line, To: i.Pos.Line}, - Text: i.Message, - FromLinter: whitespaceName, - Replacement: &result.Replacement{}, + issues := make([]goanalysis.Issue, len(lintIssues)) + for i, issue := range lintIssues { + report := &result.Issue{ + FromLinter: whitespaceName, + Pos: pass.Fset.PositionFor(issue.Diagnostic, false), + Text: issue.Message, } - bracketLine, err := lintCtx.LineCache.GetLine(issue.Pos.Filename, issue.Pos.Line) - if err != nil { - return nil, fmt.Errorf("failed to get line %s:%d: %w", issue.Pos.Filename, issue.Pos.Line, err) + switch issue.MessageType { + case whitespace.MessageTypeRemove: + if len(issue.LineNumbers) == 0 { + continue + } + + report.LineRange = &result.Range{ + From: issue.LineNumbers[0], + To: issue.LineNumbers[len(issue.LineNumbers)-1], + } + + report.Replacement = &result.Replacement{NeedOnlyDelete: true} + + case whitespace.MessageTypeAdd: + report.Pos = pass.Fset.PositionFor(issue.FixStart, false) + report.Replacement = &result.Replacement{ + Inline: &result.InlineFix{ + StartCol: 0, + Length: 1, + NewString: "\n\t", + }, + } + + default: + return nil, fmt.Errorf("unknown message type: %v", issue.MessageType) } - switch i.Type { - case whitespace.MessageTypeLeading: - issue.LineRange.To++ // cover two lines by the issue: opening bracket "{" (issue.Pos.Line) and following empty line - case whitespace.MessageTypeTrailing: - issue.LineRange.From-- // cover two lines by the issue: closing bracket "}" (issue.Pos.Line) and preceding empty line - issue.Pos.Line-- // set in sync with LineRange.From to not break fixer and other code features - case whitespace.MessageTypeAddAfter: - bracketLine += "\n" - } - issue.Replacement.NewLines = []string{bracketLine} - - issues[k] = goanalysis.NewIssue(&issue, pass) + issues[i] = goanalysis.NewIssue(report, pass) } return issues, nil diff --git a/test/testdata/fix/in/whitespace.go b/test/testdata/fix/in/whitespace.go index 20c20315..028d9d25 100644 --- a/test/testdata/fix/in/whitespace.go +++ b/test/testdata/fix/in/whitespace.go @@ -5,6 +5,7 @@ package p import "fmt" +//line yaccpar:1 func oneLeadingNewline() { fmt.Println("Hello world") @@ -58,4 +59,26 @@ func multiIfFunc() { 2 == 2 { fmt.Println("Hello multi-line world") } + + if true { + if true { + if true { + if 1 == 1 && + 2 == 2 { + fmt.Println("Hello nested multi-line world") + } + } + } + } +} + +func notGoFmted() { + + + + + fmt.Println("Hello world") + + + } diff --git a/test/testdata/fix/out/whitespace.go b/test/testdata/fix/out/whitespace.go index 16be0dcd..ec8d4065 100644 --- a/test/testdata/fix/out/whitespace.go +++ b/test/testdata/fix/out/whitespace.go @@ -5,6 +5,7 @@ package p import "fmt" +//line yaccpar:1 func oneLeadingNewline() { fmt.Println("Hello world") } @@ -40,7 +41,6 @@ func oneLeadingNewlineWithCommentFunc() { } func twoLeadingNewlines() { - fmt.Println("Hello world") } @@ -56,4 +56,20 @@ func multiIfFunc() { fmt.Println("Hello multi-line world") } + + if true { + if true { + if true { + if 1 == 1 && + 2 == 2 { + + fmt.Println("Hello nested multi-line world") + } + } + } + } +} + +func notGoFmted() { + fmt.Println("Hello world") }