github.com/amarpal/go-tools@v0.0.0-20240422043104-40142f59f616/staticcheck/sa9003/sa9003.go (about)

     1  package sa9003
     2  
     3  import (
     4  	"go/ast"
     5  
     6  	"github.com/amarpal/go-tools/analysis/facts/generated"
     7  	"github.com/amarpal/go-tools/analysis/lint"
     8  	"github.com/amarpal/go-tools/analysis/report"
     9  	"github.com/amarpal/go-tools/go/ir/irutil"
    10  	"github.com/amarpal/go-tools/internal/passes/buildir"
    11  	"golang.org/x/tools/go/analysis"
    12  )
    13  
    14  var SCAnalyzer = lint.InitializeAnalyzer(&lint.Analyzer{
    15  	Analyzer: &analysis.Analyzer{
    16  		Name:     "SA9003",
    17  		Run:      run,
    18  		Requires: []*analysis.Analyzer{buildir.Analyzer, generated.Analyzer},
    19  	},
    20  	Doc: &lint.Documentation{
    21  		Title:      `Empty body in an if or else branch`,
    22  		Since:      "2017.1",
    23  		NonDefault: true,
    24  		Severity:   lint.SeverityWarning,
    25  		MergeIf:    lint.MergeIfAny,
    26  	},
    27  })
    28  
    29  var Analyzer = SCAnalyzer.Analyzer
    30  
    31  func run(pass *analysis.Pass) (interface{}, error) {
    32  	for _, fn := range pass.ResultOf[buildir.Analyzer].(*buildir.IR).SrcFuncs {
    33  		if fn.Source() == nil {
    34  			continue
    35  		}
    36  		if irutil.IsExample(fn) {
    37  			continue
    38  		}
    39  		cb := func(node ast.Node) bool {
    40  			ifstmt, ok := node.(*ast.IfStmt)
    41  			if !ok {
    42  				return true
    43  			}
    44  			if ifstmt.Else != nil {
    45  				b, ok := ifstmt.Else.(*ast.BlockStmt)
    46  				if !ok || len(b.List) != 0 {
    47  					return true
    48  				}
    49  				report.Report(pass, ifstmt.Else, "empty branch", report.FilterGenerated(), report.ShortRange())
    50  			}
    51  			if len(ifstmt.Body.List) != 0 {
    52  				return true
    53  			}
    54  			report.Report(pass, ifstmt, "empty branch", report.FilterGenerated(), report.ShortRange())
    55  			return true
    56  		}
    57  		if source := fn.Source(); source != nil {
    58  			ast.Inspect(source, cb)
    59  		}
    60  	}
    61  	return nil, nil
    62  }