1
0
mirror of https://github.com/mgechev/revive.git synced 2024-11-28 08:49:11 +02:00
revive/internal/ifelse/func.go
Miles Delahunty 4bb48df5d2
refactor: extract shared code for linting if-else chains (#821)
* refactor: extract shared code for linting if-else chains

The rules "early-return", "indent-error-flow" and
"superfluous-else" have a similar structure. This
moves the common logic for classifying if-else chains
to a common package.

A few side benefits:
- "early-return" now handles os.Exit/log.Panicf/etc
- "superfluous-else" now handles (builtin) panic
- "superfluous-else" and "indent-error-flow" now handle if/else
  chains with 2+ "if" branches

* internal/ifelse: style fixes, renames, spelling
2023-05-17 13:51:35 +02:00

52 lines
1.2 KiB
Go

package ifelse
import (
"fmt"
"go/ast"
)
// Call contains the name of a function that deviates control flow.
type Call struct {
Pkg string // The package qualifier of the function, if not built-in.
Name string // The function name.
}
// DeviatingFuncs lists known control flow deviating function calls.
var DeviatingFuncs = map[Call]BranchKind{
{"os", "Exit"}: Exit,
{"log", "Fatal"}: Exit,
{"log", "Fatalf"}: Exit,
{"log", "Fatalln"}: Exit,
{"", "panic"}: Panic,
{"log", "Panic"}: Panic,
{"log", "Panicf"}: Panic,
{"log", "Panicln"}: Panic,
}
// ExprCall gets the Call of an ExprStmt, if any.
func ExprCall(expr *ast.ExprStmt) (Call, bool) {
call, ok := expr.X.(*ast.CallExpr)
if !ok {
return Call{}, false
}
switch v := call.Fun.(type) {
case *ast.Ident:
return Call{Name: v.Name}, true
case *ast.SelectorExpr:
if ident, ok := v.X.(*ast.Ident); ok {
return Call{Name: v.Sel.Name, Pkg: ident.Name}, true
}
}
return Call{}, false
}
// String returns the function name with package qualifier (if any)
func (f Call) String() string {
switch {
case f.Pkg != "":
return fmt.Sprintf("%s.%s", f.Pkg, f.Name)
default:
return f.Name
}
}