2025-11-15 20:24:16 +02:00
|
|
|
package ifelse_test
|
2025-06-25 14:51:18 +03:00
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"go/ast"
|
|
|
|
|
"go/token"
|
|
|
|
|
"testing"
|
2025-11-15 20:24:16 +02:00
|
|
|
|
|
|
|
|
"github.com/mgechev/revive/internal/ifelse"
|
2025-06-25 14:51:18 +03:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
func TestBlockBranch(t *testing.T) {
|
|
|
|
|
t.Run("empty", func(t *testing.T) {
|
|
|
|
|
block := &ast.BlockStmt{List: []ast.Stmt{}}
|
2025-11-15 20:24:16 +02:00
|
|
|
b := ifelse.BlockBranch(block)
|
|
|
|
|
if b.BranchKind != ifelse.Empty {
|
2025-06-25 14:51:18 +03:00
|
|
|
t.Errorf("want Empty branch, got %v", b.BranchKind)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
t.Run("non empty", func(t *testing.T) {
|
|
|
|
|
stmt := &ast.ReturnStmt{}
|
|
|
|
|
block := &ast.BlockStmt{List: []ast.Stmt{stmt}}
|
2025-11-15 20:24:16 +02:00
|
|
|
b := ifelse.BlockBranch(block)
|
|
|
|
|
if b.BranchKind != ifelse.Return {
|
2025-06-25 14:51:18 +03:00
|
|
|
t.Errorf("want Return branch, got %v", b.BranchKind)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestStmtBranch(t *testing.T) {
|
|
|
|
|
cases := []struct {
|
|
|
|
|
name string
|
|
|
|
|
stmt ast.Stmt
|
2025-11-15 20:24:16 +02:00
|
|
|
kind ifelse.BranchKind
|
|
|
|
|
call *ifelse.Call
|
2025-06-25 14:51:18 +03:00
|
|
|
}{
|
|
|
|
|
{
|
|
|
|
|
name: "ReturnStmt",
|
|
|
|
|
stmt: &ast.ReturnStmt{},
|
2025-11-15 20:24:16 +02:00
|
|
|
kind: ifelse.Return,
|
2025-06-25 14:51:18 +03:00
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "BreakStmt",
|
|
|
|
|
stmt: &ast.BranchStmt{Tok: token.BREAK},
|
2025-11-15 20:24:16 +02:00
|
|
|
kind: ifelse.Break,
|
2025-06-25 14:51:18 +03:00
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "ContinueStmt",
|
|
|
|
|
stmt: &ast.BranchStmt{Tok: token.CONTINUE},
|
2025-11-15 20:24:16 +02:00
|
|
|
kind: ifelse.Continue,
|
2025-06-25 14:51:18 +03:00
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "GotoStmt",
|
|
|
|
|
stmt: &ast.BranchStmt{Tok: token.GOTO},
|
2025-11-15 20:24:16 +02:00
|
|
|
kind: ifelse.Goto,
|
2025-06-25 14:51:18 +03:00
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "EmptyStmt",
|
|
|
|
|
stmt: &ast.EmptyStmt{},
|
2025-11-15 20:24:16 +02:00
|
|
|
kind: ifelse.Empty,
|
2025-06-25 14:51:18 +03:00
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "ExprStmt with DeviatingFunc (panic)",
|
|
|
|
|
stmt: &ast.ExprStmt{
|
|
|
|
|
X: &ast.CallExpr{
|
|
|
|
|
Fun: &ast.Ident{Name: "panic"},
|
|
|
|
|
},
|
|
|
|
|
},
|
2025-11-15 20:24:16 +02:00
|
|
|
kind: ifelse.Panic,
|
|
|
|
|
call: &ifelse.Call{Name: "panic"},
|
2025-06-25 14:51:18 +03:00
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "ExprStmt with DeviatingFunc (os.Exit)",
|
|
|
|
|
stmt: &ast.ExprStmt{
|
|
|
|
|
X: &ast.CallExpr{
|
|
|
|
|
Fun: &ast.SelectorExpr{
|
|
|
|
|
X: &ast.Ident{Name: "os"},
|
|
|
|
|
Sel: &ast.Ident{Name: "Exit"},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
2025-11-15 20:24:16 +02:00
|
|
|
kind: ifelse.Exit,
|
|
|
|
|
call: &ifelse.Call{Pkg: "os", Name: "Exit"},
|
2025-06-25 14:51:18 +03:00
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "ExprStmt with non-deviating func",
|
|
|
|
|
stmt: &ast.ExprStmt{
|
|
|
|
|
X: &ast.CallExpr{
|
|
|
|
|
Fun: &ast.Ident{Name: "foo"},
|
|
|
|
|
},
|
|
|
|
|
},
|
2025-11-15 20:24:16 +02:00
|
|
|
kind: ifelse.Regular,
|
2025-06-25 14:51:18 +03:00
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "LabeledStmt wrapping ReturnStmt",
|
|
|
|
|
stmt: &ast.LabeledStmt{
|
|
|
|
|
Label: &ast.Ident{Name: "lbl"},
|
|
|
|
|
Stmt: &ast.ReturnStmt{},
|
|
|
|
|
},
|
2025-11-15 20:24:16 +02:00
|
|
|
kind: ifelse.Return,
|
2025-06-25 14:51:18 +03:00
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "LabeledStmt wrapping ExprStmt",
|
|
|
|
|
stmt: &ast.LabeledStmt{
|
|
|
|
|
Label: &ast.Ident{Name: "lbl"},
|
|
|
|
|
Stmt: &ast.ExprStmt{X: &ast.CallExpr{Fun: &ast.Ident{Name: "foo"}}},
|
|
|
|
|
},
|
2025-11-15 20:24:16 +02:00
|
|
|
kind: ifelse.Regular,
|
2025-06-25 14:51:18 +03:00
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "BlockStmt with ReturnStmt",
|
|
|
|
|
stmt: &ast.BlockStmt{List: []ast.Stmt{&ast.ReturnStmt{}}},
|
2025-11-15 20:24:16 +02:00
|
|
|
kind: ifelse.Return,
|
2025-06-25 14:51:18 +03:00
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "BlockStmt with ExprStmt",
|
|
|
|
|
stmt: &ast.BlockStmt{List: []ast.Stmt{&ast.ExprStmt{X: &ast.CallExpr{Fun: &ast.Ident{Name: "foo"}}}}},
|
2025-11-15 20:24:16 +02:00
|
|
|
kind: ifelse.Regular,
|
2025-06-25 14:51:18 +03:00
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
for _, c := range cases {
|
2025-11-15 20:24:16 +02:00
|
|
|
b := ifelse.StmtBranch(c.stmt)
|
2025-06-25 14:51:18 +03:00
|
|
|
if b.BranchKind != c.kind {
|
|
|
|
|
t.Errorf("%s: want %v, got %v", c.name, c.kind, b.BranchKind)
|
|
|
|
|
}
|
|
|
|
|
if c.call != nil {
|
|
|
|
|
if b.Call != *c.call {
|
|
|
|
|
t.Errorf("%s: want Call %+v, got %+v", c.name, *c.call, b.Call)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestBranch_String_LongString(t *testing.T) {
|
|
|
|
|
tests := []struct {
|
|
|
|
|
name string
|
2025-11-15 20:24:16 +02:00
|
|
|
branch ifelse.Branch
|
2025-06-25 14:51:18 +03:00
|
|
|
wantStr string
|
|
|
|
|
wantLong string
|
|
|
|
|
}{
|
|
|
|
|
{
|
|
|
|
|
name: "Return branch",
|
2025-11-15 20:24:16 +02:00
|
|
|
branch: ifelse.Branch{BranchKind: ifelse.Return},
|
2025-06-25 14:51:18 +03:00
|
|
|
wantStr: "{ ... return }",
|
|
|
|
|
wantLong: "a return statement",
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "Panic branch with Call",
|
2025-11-15 20:24:16 +02:00
|
|
|
branch: ifelse.Branch{BranchKind: ifelse.Panic, Call: ifelse.Call{Name: "panic"}},
|
2025-06-25 14:51:18 +03:00
|
|
|
wantStr: "{ ... panic() }",
|
|
|
|
|
wantLong: "call to panic function",
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "Exit branch with Call",
|
2025-11-15 20:24:16 +02:00
|
|
|
branch: ifelse.Branch{BranchKind: ifelse.Exit, Call: ifelse.Call{Pkg: "os", Name: "Exit"}},
|
2025-06-25 14:51:18 +03:00
|
|
|
wantStr: "{ ... os.Exit() }",
|
|
|
|
|
wantLong: "call to os.Exit function",
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "Empty branch",
|
2025-11-15 20:24:16 +02:00
|
|
|
branch: ifelse.Branch{BranchKind: ifelse.Empty},
|
2025-06-25 14:51:18 +03:00
|
|
|
wantStr: "{ }",
|
|
|
|
|
wantLong: "an empty block",
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "Regular branch",
|
2025-11-15 20:24:16 +02:00
|
|
|
branch: ifelse.Branch{BranchKind: ifelse.Regular},
|
2025-06-25 14:51:18 +03:00
|
|
|
wantStr: "{ ... }",
|
|
|
|
|
wantLong: "a regular statement",
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
for _, tt := range tests {
|
|
|
|
|
if got := tt.branch.String(); got != tt.wantStr {
|
|
|
|
|
t.Errorf("%s: String() = %q, want %q", tt.name, got, tt.wantStr)
|
|
|
|
|
}
|
|
|
|
|
if got := tt.branch.LongString(); got != tt.wantLong {
|
|
|
|
|
t.Errorf("%s: LongString() = %q, want %q", tt.name, got, tt.wantLong)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestBranch_HasDecls(t *testing.T) {
|
|
|
|
|
tests := []struct {
|
|
|
|
|
name string
|
2025-11-15 20:24:16 +02:00
|
|
|
block *ast.BlockStmt
|
2025-06-25 14:51:18 +03:00
|
|
|
want bool
|
|
|
|
|
}{
|
|
|
|
|
{
|
|
|
|
|
name: "DeclStmt",
|
2025-11-15 20:24:16 +02:00
|
|
|
block: &ast.BlockStmt{List: []ast.Stmt{&ast.DeclStmt{}}},
|
2025-06-25 14:51:18 +03:00
|
|
|
want: true,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "AssignStmt with :=",
|
2025-11-15 20:24:16 +02:00
|
|
|
block: &ast.BlockStmt{List: []ast.Stmt{&ast.AssignStmt{Tok: token.DEFINE}}},
|
2025-06-25 14:51:18 +03:00
|
|
|
want: true,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "ExprStmt",
|
2025-11-15 20:24:16 +02:00
|
|
|
block: &ast.BlockStmt{List: []ast.Stmt{&ast.ExprStmt{}}},
|
2025-06-25 14:51:18 +03:00
|
|
|
want: false,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
for _, tt := range tests {
|
2025-11-15 20:24:16 +02:00
|
|
|
b := ifelse.BlockBranch(tt.block)
|
2025-06-25 14:51:18 +03:00
|
|
|
if got := b.HasDecls(); got != tt.want {
|
|
|
|
|
t.Errorf("%s: want HasDecls to be %v, got %v", tt.name, tt.want, got)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestBranch_IsShort(t *testing.T) {
|
|
|
|
|
tests := []struct {
|
|
|
|
|
name string
|
2025-11-15 20:24:16 +02:00
|
|
|
block *ast.BlockStmt
|
2025-06-25 14:51:18 +03:00
|
|
|
want bool
|
|
|
|
|
}{
|
|
|
|
|
{
|
|
|
|
|
name: "nil block",
|
2025-11-15 20:24:16 +02:00
|
|
|
block: &ast.BlockStmt{},
|
2025-06-25 14:51:18 +03:00
|
|
|
want: true,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "single ExprStmt",
|
2025-11-15 20:24:16 +02:00
|
|
|
block: &ast.BlockStmt{List: []ast.Stmt{&ast.ExprStmt{}}},
|
2025-06-25 14:51:18 +03:00
|
|
|
want: true,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "single BlockStmt",
|
2025-11-15 20:24:16 +02:00
|
|
|
block: &ast.BlockStmt{List: []ast.Stmt{&ast.BlockStmt{}}},
|
2025-06-25 14:51:18 +03:00
|
|
|
want: false,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "two short statements",
|
2025-11-15 20:24:16 +02:00
|
|
|
block: &ast.BlockStmt{List: []ast.Stmt{&ast.ExprStmt{}, &ast.ExprStmt{}}},
|
2025-06-25 14:51:18 +03:00
|
|
|
want: true,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "second non-short statement",
|
2025-11-15 20:24:16 +02:00
|
|
|
block: &ast.BlockStmt{List: []ast.Stmt{&ast.ExprStmt{}, &ast.BlockStmt{}}},
|
2025-06-25 14:51:18 +03:00
|
|
|
want: false,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "three statements (should return false)",
|
2025-11-15 20:24:16 +02:00
|
|
|
block: &ast.BlockStmt{List: []ast.Stmt{&ast.ExprStmt{}, &ast.ExprStmt{}, &ast.ExprStmt{}}},
|
2025-06-25 14:51:18 +03:00
|
|
|
want: false,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
for _, tt := range tests {
|
2025-11-15 20:24:16 +02:00
|
|
|
b := ifelse.BlockBranch(tt.block)
|
2025-06-25 14:51:18 +03:00
|
|
|
if got := b.IsShort(); got != tt.want {
|
|
|
|
|
t.Errorf("%s: want IsShort to be %v, got %v", tt.name, tt.want, got)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|