github.com/elek/golangci-lint@v1.42.2-0.20211208090441-c05b7fcb3a9a/pkg/golinters/goimports.go (about) 1 package golinters 2 3 import ( 4 "sync" 5 6 goimportsAPI "github.com/golangci/gofmt/goimports" 7 "github.com/pkg/errors" 8 "golang.org/x/tools/go/analysis" 9 "golang.org/x/tools/imports" 10 11 "github.com/elek/golangci-lint/pkg/golinters/goanalysis" 12 "github.com/elek/golangci-lint/pkg/lint/linter" 13 ) 14 15 const goimportsName = "goimports" 16 17 func NewGoimports() *goanalysis.Linter { 18 var mu sync.Mutex 19 var resIssues []goanalysis.Issue 20 21 analyzer := &analysis.Analyzer{ 22 Name: goimportsName, 23 Doc: goanalysis.TheOnlyanalyzerDoc, 24 } 25 return goanalysis.NewLinter( 26 goimportsName, 27 "In addition to fixing imports, goimports also formats your code in the same style as gofmt.", 28 []*analysis.Analyzer{analyzer}, 29 nil, 30 ).WithContextSetter(func(lintCtx *linter.Context) { 31 imports.LocalPrefix = lintCtx.Settings().Goimports.LocalPrefixes 32 analyzer.Run = func(pass *analysis.Pass) (interface{}, error) { 33 var fileNames []string 34 for _, f := range pass.Files { 35 pos := pass.Fset.PositionFor(f.Pos(), false) 36 fileNames = append(fileNames, pos.Filename) 37 } 38 39 var issues []goanalysis.Issue 40 41 for _, f := range fileNames { 42 diff, err := goimportsAPI.Run(f) 43 if err != nil { // TODO: skip 44 return nil, err 45 } 46 if diff == nil { 47 continue 48 } 49 50 is, err := extractIssuesFromPatch(string(diff), lintCtx.Log, lintCtx, goimportsName) 51 if err != nil { 52 return nil, errors.Wrapf(err, "can't extract issues from gofmt diff output %q", string(diff)) 53 } 54 55 for i := range is { 56 issues = append(issues, goanalysis.NewIssue(&is[i], pass)) 57 } 58 } 59 60 if len(issues) == 0 { 61 return nil, nil 62 } 63 64 mu.Lock() 65 resIssues = append(resIssues, issues...) 66 mu.Unlock() 67 68 return nil, nil 69 } 70 }).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { 71 return resIssues 72 }).WithLoadMode(goanalysis.LoadModeSyntax) 73 }