update rtnstate detection, support blocks, and binary expressions

This commit is contained in:
sawka 2023-12-18 15:02:55 -08:00
parent 7a37fdb942
commit 8d71f5538c
2 changed files with 42 additions and 16 deletions

View File

@ -208,6 +208,45 @@ func getCallExprLitArg(callExpr *syntax.CallExpr, argNum int) string {
return lit.Value
}
func isRtnStateCmd(cmd syntax.Command) bool {
if cmd == nil {
return false
}
if _, ok := cmd.(*syntax.FuncDecl); ok {
return true
}
if blockExpr, ok := cmd.(*syntax.Block); ok {
for _, stmt := range blockExpr.Stmts {
if isRtnStateCmd(stmt.Cmd) {
return true
}
}
return false
}
if binExpr, ok := cmd.(*syntax.BinaryCmd); ok {
if isRtnStateCmd(binExpr.X.Cmd) || isRtnStateCmd(binExpr.Y.Cmd) {
return true
}
} else if callExpr, ok := cmd.(*syntax.CallExpr); ok {
if len(callExpr.Assigns) > 0 && len(callExpr.Args) == 0 {
return true
}
arg0 := getCallExprLitArg(callExpr, 0)
if arg0 != "" && utilfn.ContainsStr(literalRtnStateCommands, arg0) {
return true
}
if arg0 == "git" {
arg1 := getCallExprLitArg(callExpr, 1)
if arg1 == "checkout" || arg1 == "switch" {
return true
}
}
} else if _, ok := cmd.(*syntax.DeclClause); ok {
return true
}
return false
}
// detects: export, declare, ., source, X=1, unset
func IsReturnStateCommand(cmdStr string) bool {
cmdReader := strings.NewReader(cmdStr)
@ -217,21 +256,7 @@ func IsReturnStateCommand(cmdStr string) bool {
return false
}
for _, stmt := range file.Stmts {
if callExpr, ok := stmt.Cmd.(*syntax.CallExpr); ok {
if len(callExpr.Assigns) > 0 && len(callExpr.Args) == 0 {
return true
}
arg0 := getCallExprLitArg(callExpr, 0)
if arg0 != "" && utilfn.ContainsStr(literalRtnStateCommands, arg0) {
return true
}
if arg0 == "git" {
arg1 := getCallExprLitArg(callExpr, 1)
if arg1 == "checkout" || arg1 == "switch" {
return true
}
}
} else if _, ok := stmt.Cmd.(*syntax.DeclClause); ok {
if isRtnStateCmd(stmt.Cmd) {
return true
}
}

View File

@ -58,5 +58,6 @@ func TestIsReturnStateCommand(t *testing.T) {
testRSC(t, "unset FOO BAR", true)
testRSC(t, "FOO=1; ls", true)
testRSC(t, ". ./test", true)
testRSC(t, "{ FOO=6; }", false)
testRSC(t, "{ FOO=6; }", true)
testRSC(t, "cd foo && ls -l", true)
}