From 191a16a0855877a143ae82f49ae84e2eccfd98aa Mon Sep 17 00:00:00 2001 From: Steve Ramage Date: Thu, 5 Dec 2024 10:31:57 -0800 Subject: [PATCH] Resolves #54 - Allow reduction of nil AstNode --- external/epsearchast/v3/reduce.go | 3 + external/epsearchast/v3/reduce_test.go | 20 ++++++ .../epsearchast/v3/semantic_reduce_test.go | 71 +++++++++++++++++++ 3 files changed, 94 insertions(+) create mode 100644 external/epsearchast/v3/reduce_test.go create mode 100644 external/epsearchast/v3/semantic_reduce_test.go 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") +}