diff --git a/external/epsearchast/v3/reduce.go b/external/epsearchast/v3/reduce.go index 46286d5..a2d0636 100644 --- a/external/epsearchast/v3/reduce.go +++ b/external/epsearchast/v3/reduce.go @@ -7,6 +7,9 @@ package epsearchast_v3 // // Depending on what you are doing you may find that [epsearchast_v3.SemanticReduceAst] to be simpler. func ReduceAst[T any](a *AstNode, f func(*AstNode, []*T) (*T, error)) (*T, error) { + if a == nil { + return nil, nil + } collector := make([]*T, 0, len(a.Children)) for _, n := range a.Children { v, err := ReduceAst(n, f) diff --git a/external/epsearchast/v3/reduce_test.go b/external/epsearchast/v3/reduce_test.go new file mode 100644 index 0000000..aba3242 --- /dev/null +++ b/external/epsearchast/v3/reduce_test.go @@ -0,0 +1,20 @@ +package epsearchast_v3 + +import ( + "github.com/stretchr/testify/require" + "testing" +) + +func TestReduceNilAstDoesNotPanic(t *testing.T) { + // Fixture Setup + var ast *AstNode = nil + + // Execute SUT + result, err := ReduceAst(ast, func(*AstNode, []*string) (*string, error) { + panic("should not be called") + }) + + // Verification + require.NoError(t, err) + require.Nil(t, result) +} diff --git a/external/epsearchast/v3/semantic_reduce_test.go b/external/epsearchast/v3/semantic_reduce_test.go new file mode 100644 index 0000000..85afbaf --- /dev/null +++ b/external/epsearchast/v3/semantic_reduce_test.go @@ -0,0 +1,71 @@ +package epsearchast_v3 + +import ( + "github.com/stretchr/testify/require" + "testing" +) + +func TestSemanticReduceNilAstDoesNotPanic(t *testing.T) { + // Fixture Setup + var ast *AstNode = nil + + // Execute SUT + reducer := PanicyReducer{} + + result, err := SemanticReduceAst(ast, reducer) + + // Verification + require.NoError(t, err) + require.Nil(t, result) +} + +type PanicyReducer struct { +} + +func (p PanicyReducer) PostVisitAnd(rs []*string) (*string, error) { + panic("not called") +} + +func (p PanicyReducer) VisitIn(args ...string) (*string, error) { + panic("not called") +} + +func (p PanicyReducer) VisitEq(first, second string) (*string, error) { + panic("not called") +} + +func (p PanicyReducer) VisitLe(first, second string) (*string, error) { + panic("not called") +} + +func (p PanicyReducer) VisitLt(first, second string) (*string, error) { + panic("not called") +} + +func (p PanicyReducer) VisitGe(first, second string) (*string, error) { + panic("not called") +} + +func (p PanicyReducer) VisitGt(first, second string) (*string, error) { + panic("not called") +} + +func (p PanicyReducer) VisitLike(first, second string) (*string, error) { + panic("not called") +} + +func (p PanicyReducer) VisitILike(first, second string) (*string, error) { + panic("not called") +} + +func (p PanicyReducer) VisitContains(first, second string) (*string, error) { + panic("not called") +} + +func (p PanicyReducer) VisitText(first, second string) (*string, error) { + panic("not called") +} + +func (p PanicyReducer) VisitIsNull(first string) (*string, error) { + panic("not called") +}