github.com/vanstinator/golangci-lint@v0.0.0-20240223191551-cc572f00d9d1/pkg/golinters/whitespace.go (about) 1 package golinters 2 3 import ( 4 "fmt" 5 "sync" 6 7 "github.com/ultraware/whitespace" 8 "golang.org/x/tools/go/analysis" 9 10 "github.com/vanstinator/golangci-lint/pkg/config" 11 "github.com/vanstinator/golangci-lint/pkg/golinters/goanalysis" 12 "github.com/vanstinator/golangci-lint/pkg/lint/linter" 13 "github.com/vanstinator/golangci-lint/pkg/result" 14 ) 15 16 const whitespaceName = "whitespace" 17 18 func NewWhitespace(settings *config.WhitespaceSettings) *goanalysis.Linter { 19 var mu sync.Mutex 20 var resIssues []goanalysis.Issue 21 22 var wsSettings whitespace.Settings 23 if settings != nil { 24 wsSettings = whitespace.Settings{ 25 Mode: whitespace.RunningModeGolangCI, 26 MultiIf: settings.MultiIf, 27 MultiFunc: settings.MultiFunc, 28 } 29 } 30 31 a := whitespace.NewAnalyzer(&wsSettings) 32 33 return goanalysis.NewLinter( 34 a.Name, 35 a.Doc, 36 []*analysis.Analyzer{a}, 37 nil, 38 ).WithContextSetter(func(lintCtx *linter.Context) { 39 a.Run = func(pass *analysis.Pass) (any, error) { 40 issues, err := runWhitespace(pass, wsSettings) 41 if err != nil { 42 return nil, err 43 } 44 45 if len(issues) == 0 { 46 return nil, nil 47 } 48 49 mu.Lock() 50 resIssues = append(resIssues, issues...) 51 mu.Unlock() 52 53 return nil, nil 54 } 55 }).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { 56 return resIssues 57 }).WithLoadMode(goanalysis.LoadModeSyntax) 58 } 59 60 func runWhitespace(pass *analysis.Pass, wsSettings whitespace.Settings) ([]goanalysis.Issue, error) { 61 lintIssues := whitespace.Run(pass, &wsSettings) 62 63 issues := make([]goanalysis.Issue, len(lintIssues)) 64 for i, issue := range lintIssues { 65 report := &result.Issue{ 66 FromLinter: whitespaceName, 67 Pos: pass.Fset.PositionFor(issue.Diagnostic, false), 68 Text: issue.Message, 69 } 70 71 switch issue.MessageType { 72 case whitespace.MessageTypeRemove: 73 if len(issue.LineNumbers) == 0 { 74 continue 75 } 76 77 report.LineRange = &result.Range{ 78 From: issue.LineNumbers[0], 79 To: issue.LineNumbers[len(issue.LineNumbers)-1], 80 } 81 82 report.Replacement = &result.Replacement{NeedOnlyDelete: true} 83 84 case whitespace.MessageTypeAdd: 85 report.Pos = pass.Fset.PositionFor(issue.FixStart, false) 86 report.Replacement = &result.Replacement{ 87 Inline: &result.InlineFix{ 88 StartCol: 0, 89 Length: 1, 90 NewString: "\n\t", 91 }, 92 } 93 94 default: 95 return nil, fmt.Errorf("unknown message type: %v", issue.MessageType) 96 } 97 98 issues[i] = goanalysis.NewIssue(report, pass) 99 } 100 101 return issues, nil 102 }