package s1023 import ( "go/ast" "go/token" "honnef.co/go/tools/analysis/code" "honnef.co/go/tools/analysis/facts/generated" "honnef.co/go/tools/analysis/lint" "honnef.co/go/tools/analysis/report" "golang.org/x/tools/go/analysis" "golang.org/x/tools/go/analysis/passes/inspect" ) var SCAnalyzer = lint.InitializeAnalyzer(&lint.Analyzer{ Analyzer: &analysis.Analyzer{ Name: "S1023", Run: run, Requires: []*analysis.Analyzer{inspect.Analyzer, generated.Analyzer}, }, Doc: &lint.RawDocumentation{ Title: `Omit redundant control flow`, Text: `Functions that have no return value do not need a return statement as the final statement of the function. Switches in Go do not have automatic fallthrough, unlike languages like C. It is not necessary to have a break statement as the final statement in a case block.`, Since: "2017.1", MergeIf: lint.MergeIfAny, }, }) var Analyzer = SCAnalyzer.Analyzer func run(pass *analysis.Pass) (interface{}, error) { fn1 := func(node ast.Node) { clause := node.(*ast.CaseClause) if len(clause.Body) < 2 { return } branch, ok := clause.Body[len(clause.Body)-1].(*ast.BranchStmt) if !ok || branch.Tok != token.BREAK || branch.Label != nil { return } report.Report(pass, branch, "redundant break statement", report.FilterGenerated()) } fn2 := func(node ast.Node) { var ret *ast.FieldList var body *ast.BlockStmt switch x := node.(type) { case *ast.FuncDecl: ret = x.Type.Results body = x.Body case *ast.FuncLit: ret = x.Type.Results body = x.Body default: lint.ExhaustiveTypeSwitch(node) } // if the func has results, a return can't be redundant. // similarly, if there are no statements, there can be // no return. if ret != nil || body == nil || len(body.List) < 1 { return } rst, ok := body.List[len(body.List)-1].(*ast.ReturnStmt) if !ok { return } // we don't need to check rst.Results as we already // checked x.Type.Results to be nil. report.Report(pass, rst, "redundant return statement", report.FilterGenerated()) } code.Preorder(pass, fn1, (*ast.CaseClause)(nil)) code.Preorder(pass, fn2, (*ast.FuncDecl)(nil), (*ast.FuncLit)(nil)) return nil, nil }