github.com/nozzle/golangci-lint@v1.49.0-nz3/pkg/golinters/nolintlint.go (about)

     1  package golinters
     2  
     3  import (
     4  	"fmt"
     5  	"go/ast"
     6  	"sync"
     7  
     8  	"golang.org/x/tools/go/analysis"
     9  
    10  	"github.com/golangci/golangci-lint/pkg/config"
    11  	"github.com/golangci/golangci-lint/pkg/golinters/goanalysis"
    12  	"github.com/golangci/golangci-lint/pkg/golinters/nolintlint"
    13  	"github.com/golangci/golangci-lint/pkg/lint/linter"
    14  	"github.com/golangci/golangci-lint/pkg/result"
    15  )
    16  
    17  const NoLintLintName = "nolintlint"
    18  
    19  //nolint:dupl
    20  func NewNoLintLint(settings *config.NoLintLintSettings) *goanalysis.Linter {
    21  	var mu sync.Mutex
    22  	var resIssues []goanalysis.Issue
    23  
    24  	analyzer := &analysis.Analyzer{
    25  		Name: NoLintLintName,
    26  		Doc:  goanalysis.TheOnlyanalyzerDoc,
    27  		Run: func(pass *analysis.Pass) (interface{}, error) {
    28  			issues, err := runNoLintLint(pass, settings)
    29  			if err != nil {
    30  				return nil, err
    31  			}
    32  
    33  			if len(issues) == 0 {
    34  				return nil, nil
    35  			}
    36  
    37  			mu.Lock()
    38  			resIssues = append(resIssues, issues...)
    39  			mu.Unlock()
    40  
    41  			return nil, nil
    42  		},
    43  	}
    44  
    45  	return goanalysis.NewLinter(
    46  		NoLintLintName,
    47  		"Reports ill-formed or insufficient nolint directives",
    48  		[]*analysis.Analyzer{analyzer},
    49  		nil,
    50  	).WithIssuesReporter(func(*linter.Context) []goanalysis.Issue {
    51  		return resIssues
    52  	}).WithLoadMode(goanalysis.LoadModeSyntax)
    53  }
    54  
    55  func runNoLintLint(pass *analysis.Pass, settings *config.NoLintLintSettings) ([]goanalysis.Issue, error) {
    56  	var needs nolintlint.Needs
    57  	if settings.RequireExplanation {
    58  		needs |= nolintlint.NeedsExplanation
    59  	}
    60  	if settings.RequireSpecific {
    61  		needs |= nolintlint.NeedsSpecific
    62  	}
    63  	if !settings.AllowUnused {
    64  		needs |= nolintlint.NeedsUnused
    65  	}
    66  
    67  	lnt, err := nolintlint.NewLinter(needs, settings.AllowNoExplanation)
    68  	if err != nil {
    69  		return nil, err
    70  	}
    71  
    72  	nodes := make([]ast.Node, 0, len(pass.Files))
    73  	for _, n := range pass.Files {
    74  		nodes = append(nodes, n)
    75  	}
    76  
    77  	lintIssues, err := lnt.Run(pass.Fset, nodes...)
    78  	if err != nil {
    79  		return nil, fmt.Errorf("linter failed to run: %s", err)
    80  	}
    81  
    82  	var issues []goanalysis.Issue
    83  
    84  	for _, i := range lintIssues {
    85  		expectNoLint := false
    86  		var expectedNolintLinter string
    87  		if ii, ok := i.(nolintlint.UnusedCandidate); ok {
    88  			expectedNolintLinter = ii.ExpectedLinter
    89  			expectNoLint = true
    90  		}
    91  
    92  		issue := &result.Issue{
    93  			FromLinter:           NoLintLintName,
    94  			Text:                 i.Details(),
    95  			Pos:                  i.Position(),
    96  			ExpectNoLint:         expectNoLint,
    97  			ExpectedNoLintLinter: expectedNolintLinter,
    98  			Replacement:          i.Replacement(),
    99  		}
   100  
   101  		issues = append(issues, goanalysis.NewIssue(issue, pass))
   102  	}
   103  
   104  	return issues, nil
   105  }