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:
@@ -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,
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
32
rule/utils_test.go
Normal 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)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user