1
0
mirror of https://github.com/mgechev/revive.git synced 2025-11-25 22:12:38 +02:00

refactor: avoid duplicated exitFunctions map (#1145)

This commit is contained in:
Oleksandr Redko
2024-11-28 09:47:10 +02:00
committed by GitHub
parent d2778f36f1
commit 777abc9c35
4 changed files with 56 additions and 34 deletions

View File

@@ -17,20 +17,7 @@ func (*DeepExitRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure {
failures = append(failures, failure) failures = append(failures, failure)
} }
exitFunctions := map[string]map[string]bool{ w := lintDeepExit{onFailure: onFailure, isTestFile: file.IsTest()}
"os": {"Exit": true},
"syscall": {"Exit": true},
"log": {
"Fatal": true,
"Fatalf": true,
"Fatalln": true,
"Panic": true,
"Panicf": true,
"Panicln": true,
},
}
w := lintDeepExit{onFailure, exitFunctions, file.IsTest()}
ast.Walk(w, file.AST) ast.Walk(w, file.AST)
return failures return failures
} }
@@ -41,9 +28,8 @@ func (*DeepExitRule) Name() string {
} }
type lintDeepExit struct { type lintDeepExit struct {
onFailure func(lint.Failure) onFailure func(lint.Failure)
exitFunctions map[string]map[string]bool isTestFile bool
isTestFile bool
} }
func (w lintDeepExit) Visit(node ast.Node) ast.Visitor { func (w lintDeepExit) Visit(node ast.Node) ast.Visitor {
@@ -75,8 +61,7 @@ func (w lintDeepExit) Visit(node ast.Node) ast.Visitor {
pkg := id.Name pkg := id.Name
fn := fc.Sel.Name fn := fc.Sel.Name
isACallToExitFunction := w.exitFunctions[pkg] != nil && w.exitFunctions[pkg][fn] if isCallToExitFunction(pkg, fn) {
if isACallToExitFunction {
w.onFailure(lint.Failure{ w.onFailure(lint.Failure{
Confidence: 1, Confidence: 1,
Node: ce, Node: ce,

View File

@@ -152,19 +152,6 @@ func (w *lintUnconditionalRecursionRule) updateFuncStatus(node ast.Node) {
w.currentFunc.seenConditionalExit = w.hasControlExit(node) w.currentFunc.seenConditionalExit = w.hasControlExit(node)
} }
var exitFunctions = map[string]map[string]bool{
"os": {"Exit": true},
"syscall": {"Exit": true},
"log": {
"Fatal": true,
"Fatalf": true,
"Fatalln": true,
"Panic": true,
"Panicf": true,
"Panicln": true,
},
}
func (lintUnconditionalRecursionRule) hasControlExit(node ast.Node) bool { func (lintUnconditionalRecursionRule) hasControlExit(node ast.Node) bool {
// isExit returns true if the given node makes control exit the function // isExit returns true if the given node makes control exit the function
isExit := func(node ast.Node) bool { isExit := func(node ast.Node) bool {
@@ -187,8 +174,7 @@ func (lintUnconditionalRecursionRule) hasControlExit(node ast.Node) bool {
functionName := se.Sel.Name functionName := se.Sel.Name
pkgName := id.Name pkgName := id.Name
isCallToExitFunction := exitFunctions[pkgName] != nil && exitFunctions[pkgName][functionName] if isCallToExitFunction(pkgName, functionName) {
if isCallToExitFunction {
return true return true
} }
} }

View File

@@ -11,6 +11,20 @@ import (
"github.com/mgechev/revive/lint" "github.com/mgechev/revive/lint"
) )
// exitFunctions is a map of std packages and functions that are considered as exit functions.
var exitFunctions = map[string]map[string]bool{
"os": {"Exit": true},
"syscall": {"Exit": true},
"log": {
"Fatal": true,
"Fatalf": true,
"Fatalln": true,
"Panic": true,
"Panicf": true,
"Panicln": true,
},
}
func isCgoExported(f *ast.FuncDecl) bool { func isCgoExported(f *ast.FuncDecl) bool {
if f.Recv != nil || f.Doc == nil { if f.Recv != nil || f.Doc == nil {
return false return false
@@ -102,3 +116,8 @@ var directiveCommentRE = regexp.MustCompile("^//(line |extern |export |[a-z0-9]+
func isDirectiveComment(line string) bool { func isDirectiveComment(line string) bool {
return directiveCommentRE.MatchString(line) return directiveCommentRE.MatchString(line)
} }
// isCallToExitFunction checks if the function call is a call to an exit function.
func isCallToExitFunction(pkgName, functionName string) bool {
return exitFunctions[pkgName] != nil && exitFunctions[pkgName][functionName]
}

32
rule/utils_test.go Normal file
View File

@@ -0,0 +1,32 @@
package rule
import (
"fmt"
"testing"
)
func TestIsCallToExitFunction(t *testing.T) {
tests := []struct {
pkgName string
functionName string
expected bool
}{
{"os", "Exit", true},
{"syscall", "Exit", true},
{"log", "Fatal", true},
{"log", "Fatalf", true},
{"log", "Fatalln", true},
{"log", "Panic", true},
{"log", "Panicf", true},
{"log", "Print", false},
{"fmt", "Errorf", false},
}
for _, tt := range tests {
t.Run(fmt.Sprintf("%s.%s", tt.pkgName, tt.functionName), func(t *testing.T) {
if got := isCallToExitFunction(tt.pkgName, tt.functionName); got != tt.expected {
t.Errorf("isCallToExitFunction(%s, %s) = %v; want %v", tt.pkgName, tt.functionName, got, tt.expected)
}
})
}
}