/
custom_funcdecl.go
109 lines (94 loc) · 2.12 KB
/
custom_funcdecl.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
// Copyright(C) 2023 github.com/fsgo All Rights Reserved.
// Author: hidu <duv123@gmail.com>
// Date: 2023/9/10
package simplify
import "go/ast"
type cFuncDecl struct {
customBase
}
func (c *cFuncDecl) fixFuncDecl(node *ast.FuncDecl) {
// c.shortReturnBool(node.Type, node.Body)
}
func (c *cFuncDecl) fixFuncLit(node *ast.FuncLit) {
// c.shortReturnBool(node.Type, node.Body)
}
// 对应case: custom13.go.input
//
//nolint:gocyclo
//lint:ignore U1000 临时忽略
func (c *cFuncDecl) shortReturnBool(ft *ast.FuncType, funBody *ast.BlockStmt) {
if funBody == nil || len(funBody.List) < 2 {
// 函数已经很简单
return
}
ret := ft.Results
if ret == nil || len(ret.List) != 1 {
return
}
// 函数的返回值只有一个并且是 bool 类型,如:
// func ok() bool
r1Type, ok := ret.List[0].Type.(*ast.Ident)
if !ok || r1Type.Name != "bool" {
return
}
st2If, ok2 := funBody.List[len(funBody.List)-2].(*ast.IfStmt)
if !ok2 || st2If.Body == nil || len(st2If.Body.List) != 1 {
return
}
if st2If.Init != nil {
return
}
if _, ok21 := toBoolIdentExpr(st2If.Cond); ok21 {
// 忽略:这种可能是临时调试代码
// if true {}
// if false {}
return
}
st2rt, ok21 := st2If.Body.List[0].(*ast.ReturnStmt)
if !ok21 || len(st2rt.Results) != 1 {
return
}
st2Bi, ok22 := toBoolIdentExpr(st2rt.Results[0])
if !ok22 {
return
}
st1, ok1 := funBody.List[len(funBody.List)-1].(*ast.ReturnStmt)
if !ok1 || len(st1.Results) != 1 {
// 语法错误,忽略
return
}
st1Bi, ok3 := toBoolIdentExpr(st1.Results[0])
if !ok3 {
return
}
if st2Bi.Name == st1Bi.Name {
// 可能存在 bug (返回一样的值):
// if ok1(){
// return true
// }
// return true
return
}
var cond ast.Expr
if st2Bi.Name == "true" {
// if cond(){
// return true
// }
// return false
cond = st2If.Cond
} else {
// if cond(){
// return false
// }
// return true
cond = conditionToNot(st2If.Cond)
}
stNew := &ast.ReturnStmt{
Return: st2If.Pos(),
Results: []ast.Expr{
cond,
},
}
funBody.List[len(funBody.List)-2] = stNew
funBody.List = funBody.List[0 : len(funBody.List)-1]
}