Skip to content

Commit

Permalink
Add compile checks for undefined variables (#85)
Browse files Browse the repository at this point in the history
* Add compile checks for undefined variables

* Update expr_test.go

Co-authored-by: Anton Medvedev <[email protected]>
  • Loading branch information
taras-zak and antonmedv committed Jan 24, 2020
1 parent 6702ac6 commit 195ac5b
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 8 deletions.
15 changes: 10 additions & 5 deletions checker/checker.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ func Check(tree *parser.Tree, config *conf.Config) (t reflect.Type, err error) {
v.operators = config.Operators
v.expect = config.Expect
v.undefVars = config.AllowUndefinedVariables
v.undefVarsType = config.UndefinedVariableType
}

t = v.visit(tree.Node)
Expand All @@ -52,11 +53,12 @@ okay:
}

type visitor struct {
types conf.TypesTable
operators conf.OperatorsTable
expect reflect.Kind
collections []reflect.Type
undefVars bool
types conf.TypesTable
operators conf.OperatorsTable
expect reflect.Kind
collections []reflect.Type
undefVars bool
undefVarsType reflect.Type
}

func (v *visitor) visit(node ast.Node) reflect.Type {
Expand Down Expand Up @@ -130,6 +132,9 @@ func (v *visitor) IdentifierNode(node *ast.IdentifierNode) reflect.Type {
return t.Type
}
if v.undefVars {
if v.undefVarsType != nil {
return v.undefVarsType
}
return interfaceType
}
panic(v.error(node, "unknown name %v", node.Value))
Expand Down
4 changes: 4 additions & 0 deletions expr.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ func Env(i interface{}) Option {
return func(c *conf.Config) {
if _, ok := i.(map[string]interface{}); ok {
c.MapEnv = true
} else {
if reflect.ValueOf(i).Kind() == reflect.Map {
c.UndefinedVariableType = reflect.TypeOf(i).Elem()
}
}
c.CheckTypes = true
c.Types = conf.CreateTypesTable(i)
Expand Down
28 changes: 28 additions & 0 deletions expr_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -853,6 +853,26 @@ func TestExpr_map_default_values(t *testing.T) {
require.Equal(t, true, output)
}

func TestExpr_map_default_values_compile_check(t *testing.T) {
tests := []struct {
env interface{}
input string
}{
{
mockMapStringStringEnv{"foo": "bar"},
`Split(foo, sep)`,
},
{
mockMapStringIntEnv{"foo": 1},
`foo / bar`,
},
}
for _, tt := range tests {
_, err := expr.Compile(tt.input, expr.Env(tt.env), expr.AllowUndefinedVariables())
require.NoError(t, err)
}
}

//
// Mock types
//
Expand Down Expand Up @@ -973,3 +993,11 @@ type mockMapEnv map[string]interface{}
func (mockMapEnv) Swipe(in string) string {
return strings.Replace(in, "world", "user", 1)
}

type mockMapStringStringEnv map[string]string

func (m mockMapStringStringEnv) Split(s, sep string) []string {
return strings.Split(s, sep)
}

type mockMapStringIntEnv map[string]int
13 changes: 10 additions & 3 deletions internal/conf/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,25 @@ type Config struct {
Expect reflect.Kind
Optimize bool
AllowUndefinedVariables bool
UndefinedVariableType reflect.Type
}

func New(i interface{}) *Config {
var mapEnv bool
var mapValueType reflect.Type
if _, ok := i.(map[string]interface{}); ok {
mapEnv = true
} else {
if reflect.ValueOf(i).Kind() == reflect.Map {
mapValueType = reflect.TypeOf(i).Elem()
}
}

return &Config{
MapEnv: mapEnv,
Types: CreateTypesTable(i),
Optimize: true,
MapEnv: mapEnv,
Types: CreateTypesTable(i),
Optimize: true,
UndefinedVariableType: mapValueType,
}
}

Expand Down

0 comments on commit 195ac5b

Please sign in to comment.