github.com/elek/golangci-lint@v1.42.2-0.20211208090441-c05b7fcb3a9a/pkg/golinters/depguard.go (about) 1 package golinters 2 3 import ( 4 "fmt" 5 "strings" 6 "sync" 7 8 "github.com/OpenPeeDeeP/depguard" 9 "golang.org/x/tools/go/analysis" 10 "golang.org/x/tools/go/loader" //nolint:staticcheck // require changes in github.com/OpenPeeDeeP/depguard 11 12 "github.com/elek/golangci-lint/pkg/golinters/goanalysis" 13 "github.com/elek/golangci-lint/pkg/lint/linter" 14 "github.com/elek/golangci-lint/pkg/result" 15 ) 16 17 func setDepguardListType(dg *depguard.Depguard, lintCtx *linter.Context) error { 18 listType := lintCtx.Settings().Depguard.ListType 19 var found bool 20 dg.ListType, found = depguard.StringToListType[strings.ToLower(listType)] 21 if !found { 22 if listType != "" { 23 return fmt.Errorf("unsure what list type %s is", listType) 24 } 25 dg.ListType = depguard.LTBlacklist 26 } 27 28 return nil 29 } 30 31 func setupDepguardPackages(dg *depguard.Depguard, lintCtx *linter.Context) { 32 if dg.ListType == depguard.LTBlacklist { 33 // if the list type was a blacklist the packages with error messages should 34 // be included in the blacklist package list 35 36 noMessagePackages := make(map[string]bool) 37 for _, pkg := range dg.Packages { 38 noMessagePackages[pkg] = true 39 } 40 41 for pkg := range lintCtx.Settings().Depguard.PackagesWithErrorMessage { 42 if _, ok := noMessagePackages[pkg]; !ok { 43 dg.Packages = append(dg.Packages, pkg) 44 } 45 } 46 } 47 } 48 49 func NewDepguard() *goanalysis.Linter { 50 const linterName = "depguard" 51 var mu sync.Mutex 52 var resIssues []goanalysis.Issue 53 54 analyzer := &analysis.Analyzer{ 55 Name: linterName, 56 Doc: goanalysis.TheOnlyanalyzerDoc, 57 } 58 return goanalysis.NewLinter( 59 linterName, 60 "Go linter that checks if package imports are in a list of acceptable packages", 61 []*analysis.Analyzer{analyzer}, 62 nil, 63 ).WithContextSetter(func(lintCtx *linter.Context) { 64 dgSettings := &lintCtx.Settings().Depguard 65 analyzer.Run = func(pass *analysis.Pass) (interface{}, error) { 66 prog := goanalysis.MakeFakeLoaderProgram(pass) 67 dg := &depguard.Depguard{ 68 Packages: dgSettings.Packages, 69 IncludeGoRoot: dgSettings.IncludeGoRoot, 70 } 71 if err := setDepguardListType(dg, lintCtx); err != nil { 72 return nil, err 73 } 74 setupDepguardPackages(dg, lintCtx) 75 76 loadConfig := &loader.Config{ 77 Cwd: "", // fallbacked to os.Getcwd 78 Build: nil, // fallbacked to build.Default 79 } 80 issues, err := dg.Run(loadConfig, prog) 81 if err != nil { 82 return nil, err 83 } 84 if len(issues) == 0 { 85 return nil, nil 86 } 87 msgSuffix := "is in the blacklist" 88 if dg.ListType == depguard.LTWhitelist { 89 msgSuffix = "is not in the whitelist" 90 } 91 res := make([]goanalysis.Issue, 0, len(issues)) 92 for _, i := range issues { 93 userSuppliedMsgSuffix := dgSettings.PackagesWithErrorMessage[i.PackageName] 94 if userSuppliedMsgSuffix != "" { 95 userSuppliedMsgSuffix = ": " + userSuppliedMsgSuffix 96 } 97 res = append(res, goanalysis.NewIssue(&result.Issue{ 98 Pos: i.Position, 99 Text: fmt.Sprintf("%s %s%s", formatCode(i.PackageName, lintCtx.Cfg), msgSuffix, userSuppliedMsgSuffix), 100 FromLinter: linterName, 101 }, pass)) 102 } 103 mu.Lock() 104 resIssues = append(resIssues, res...) 105 mu.Unlock() 106 107 return nil, nil 108 } 109 }).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue { 110 return resIssues 111 }).WithLoadMode(goanalysis.LoadModeTypesInfo) 112 }