github.com/elek/golangci-lint@v1.42.2-0.20211208090441-c05b7fcb3a9a/pkg/golinters/gomodguard.go (about)

     1  package golinters
     2  
     3  import (
     4  	"sync"
     5  
     6  	"github.com/ryancurrah/gomodguard"
     7  	"golang.org/x/tools/go/analysis"
     8  
     9  	"github.com/elek/golangci-lint/pkg/golinters/goanalysis"
    10  	"github.com/elek/golangci-lint/pkg/lint/linter"
    11  	"github.com/elek/golangci-lint/pkg/result"
    12  )
    13  
    14  const (
    15  	gomodguardName = "gomodguard"
    16  	gomodguardDesc = "Allow and block list linter for direct Go module dependencies. " +
    17  		"This is different from depguard where there are different block " +
    18  		"types for example version constraints and module recommendations."
    19  )
    20  
    21  // NewGomodguard returns a new Gomodguard linter.
    22  func NewGomodguard() *goanalysis.Linter {
    23  	var (
    24  		issues   []goanalysis.Issue
    25  		mu       = sync.Mutex{}
    26  		analyzer = &analysis.Analyzer{
    27  			Name: goanalysis.TheOnlyAnalyzerName,
    28  			Doc:  goanalysis.TheOnlyanalyzerDoc,
    29  		}
    30  	)
    31  
    32  	return goanalysis.NewLinter(
    33  		gomodguardName,
    34  		gomodguardDesc,
    35  		[]*analysis.Analyzer{analyzer},
    36  		nil,
    37  	).WithContextSetter(func(lintCtx *linter.Context) {
    38  		linterCfg := lintCtx.Cfg.LintersSettings.Gomodguard
    39  
    40  		processorCfg := &gomodguard.Configuration{}
    41  		processorCfg.Allowed.Modules = linterCfg.Allowed.Modules
    42  		processorCfg.Allowed.Domains = linterCfg.Allowed.Domains
    43  		processorCfg.Blocked.LocalReplaceDirectives = linterCfg.Blocked.LocalReplaceDirectives
    44  
    45  		for n := range linterCfg.Blocked.Modules {
    46  			for k, v := range linterCfg.Blocked.Modules[n] {
    47  				m := map[string]gomodguard.BlockedModule{k: {
    48  					Recommendations: v.Recommendations,
    49  					Reason:          v.Reason,
    50  				}}
    51  				processorCfg.Blocked.Modules = append(processorCfg.Blocked.Modules, m)
    52  				break
    53  			}
    54  		}
    55  
    56  		for n := range linterCfg.Blocked.Versions {
    57  			for k, v := range linterCfg.Blocked.Versions[n] {
    58  				m := map[string]gomodguard.BlockedVersion{k: {
    59  					Version: v.Version,
    60  					Reason:  v.Reason,
    61  				}}
    62  				processorCfg.Blocked.Versions = append(processorCfg.Blocked.Versions, m)
    63  				break
    64  			}
    65  		}
    66  
    67  		processor, err := gomodguard.NewProcessor(processorCfg)
    68  		if err != nil {
    69  			lintCtx.Log.Warnf("running gomodguard failed: %s: if you are not using go modules "+
    70  				"it is suggested to disable this linter", err)
    71  			return
    72  		}
    73  
    74  		analyzer.Run = func(pass *analysis.Pass) (interface{}, error) {
    75  			var files []string
    76  
    77  			for _, file := range pass.Files {
    78  				files = append(files, pass.Fset.PositionFor(file.Pos(), false).Filename)
    79  			}
    80  
    81  			gomodguardIssues := processor.ProcessFiles(files)
    82  
    83  			mu.Lock()
    84  			defer mu.Unlock()
    85  
    86  			for _, gomodguardIssue := range gomodguardIssues {
    87  				issues = append(issues, goanalysis.NewIssue(&result.Issue{
    88  					FromLinter: gomodguardName,
    89  					Pos:        gomodguardIssue.Position,
    90  					Text:       gomodguardIssue.Reason,
    91  				}, pass))
    92  			}
    93  
    94  			return nil, nil
    95  		}
    96  	}).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue {
    97  		return issues
    98  	}).WithLoadMode(goanalysis.LoadModeSyntax)
    99  }