diff --git a/ast/node.go b/ast/node.go index d037926c1..ea2ddfd30 100644 --- a/ast/node.go +++ b/ast/node.go @@ -17,7 +17,6 @@ type Node interface { } func Patch(node *Node, newNode Node) { - newNode.SetType((*node).Type()) newNode.SetLocation((*node).Location()) *node = newNode } diff --git a/checker/checker.go b/checker/checker.go index da46b6f9f..0f6f34b5b 100644 --- a/checker/checker.go +++ b/checker/checker.go @@ -536,6 +536,14 @@ func (v *checker) SliceNode(node *ast.SliceNode) (reflect.Type, info) { } func (v *checker) CallNode(node *ast.CallNode) (reflect.Type, info) { + t, i := v.functionReturnType(node) + if node.Type() != nil { + return node.Type(), i + } + return t, i +} + +func (v *checker) functionReturnType(node *ast.CallNode) (reflect.Type, info) { fn, fnInfo := v.visit(node.Callee) if fnInfo.fn != nil { diff --git a/test/patch/set_type/set_type_test.go b/test/patch/set_type/set_type_test.go new file mode 100644 index 000000000..bdeee7d68 --- /dev/null +++ b/test/patch/set_type/set_type_test.go @@ -0,0 +1,56 @@ +package set_type_test + +import ( + "reflect" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/antonmedv/expr" + "github.com/antonmedv/expr/ast" +) + +func TestPatch_SetType(t *testing.T) { + _, err := expr.Compile( + `Value + "string"`, + expr.Env(Env{}), + expr.Function( + "getValue", + func(params ...any) (any, error) { + return params[0].(Value).Int, nil + }, + // We can set function type right here, + // but we want to check what SetType in + // getValuePatcher will take an effect. + ), + expr.Patch(getValuePatcher{}), + ) + require.Error(t, err) +} + +type Value struct { + Int int +} + +type Env struct { + Value Value +} + +var valueType = reflect.TypeOf((*Value)(nil)).Elem() + +type getValuePatcher struct{} + +func (getValuePatcher) Visit(node *ast.Node) { + id, ok := (*node).(*ast.IdentifierNode) + if !ok { + return + } + if id.Type() == valueType { + newNode := &ast.CallNode{ + Callee: &ast.IdentifierNode{Value: "getValue"}, + Arguments: []ast.Node{id}, + } + newNode.SetType(reflect.TypeOf(0)) + ast.Patch(node, newNode) + } +}