Skip to content

Commit 195ac5b

Browse files
taras-zakantonmedv
andcommitted
Add compile checks for undefined variables (#85)
* Add compile checks for undefined variables * Update expr_test.go Co-authored-by: Anton Medvedev <[email protected]>
1 parent 6702ac6 commit 195ac5b

File tree

4 files changed

+52
-8
lines changed

4 files changed

+52
-8
lines changed

checker/checker.go

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ func Check(tree *parser.Tree, config *conf.Config) (t reflect.Type, err error) {
2929
v.operators = config.Operators
3030
v.expect = config.Expect
3131
v.undefVars = config.AllowUndefinedVariables
32+
v.undefVarsType = config.UndefinedVariableType
3233
}
3334

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

5455
type visitor struct {
55-
types conf.TypesTable
56-
operators conf.OperatorsTable
57-
expect reflect.Kind
58-
collections []reflect.Type
59-
undefVars bool
56+
types conf.TypesTable
57+
operators conf.OperatorsTable
58+
expect reflect.Kind
59+
collections []reflect.Type
60+
undefVars bool
61+
undefVarsType reflect.Type
6062
}
6163

6264
func (v *visitor) visit(node ast.Node) reflect.Type {
@@ -130,6 +132,9 @@ func (v *visitor) IdentifierNode(node *ast.IdentifierNode) reflect.Type {
130132
return t.Type
131133
}
132134
if v.undefVars {
135+
if v.undefVarsType != nil {
136+
return v.undefVarsType
137+
}
133138
return interfaceType
134139
}
135140
panic(v.error(node, "unknown name %v", node.Value))

expr.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ func Env(i interface{}) Option {
4848
return func(c *conf.Config) {
4949
if _, ok := i.(map[string]interface{}); ok {
5050
c.MapEnv = true
51+
} else {
52+
if reflect.ValueOf(i).Kind() == reflect.Map {
53+
c.UndefinedVariableType = reflect.TypeOf(i).Elem()
54+
}
5155
}
5256
c.CheckTypes = true
5357
c.Types = conf.CreateTypesTable(i)

expr_test.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -853,6 +853,26 @@ func TestExpr_map_default_values(t *testing.T) {
853853
require.Equal(t, true, output)
854854
}
855855

856+
func TestExpr_map_default_values_compile_check(t *testing.T) {
857+
tests := []struct {
858+
env interface{}
859+
input string
860+
}{
861+
{
862+
mockMapStringStringEnv{"foo": "bar"},
863+
`Split(foo, sep)`,
864+
},
865+
{
866+
mockMapStringIntEnv{"foo": 1},
867+
`foo / bar`,
868+
},
869+
}
870+
for _, tt := range tests {
871+
_, err := expr.Compile(tt.input, expr.Env(tt.env), expr.AllowUndefinedVariables())
872+
require.NoError(t, err)
873+
}
874+
}
875+
856876
//
857877
// Mock types
858878
//
@@ -973,3 +993,11 @@ type mockMapEnv map[string]interface{}
973993
func (mockMapEnv) Swipe(in string) string {
974994
return strings.Replace(in, "world", "user", 1)
975995
}
996+
997+
type mockMapStringStringEnv map[string]string
998+
999+
func (m mockMapStringStringEnv) Split(s, sep string) []string {
1000+
return strings.Split(s, sep)
1001+
}
1002+
1003+
type mockMapStringIntEnv map[string]int

internal/conf/config.go

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,25 @@ type Config struct {
1313
Expect reflect.Kind
1414
Optimize bool
1515
AllowUndefinedVariables bool
16+
UndefinedVariableType reflect.Type
1617
}
1718

1819
func New(i interface{}) *Config {
1920
var mapEnv bool
21+
var mapValueType reflect.Type
2022
if _, ok := i.(map[string]interface{}); ok {
2123
mapEnv = true
24+
} else {
25+
if reflect.ValueOf(i).Kind() == reflect.Map {
26+
mapValueType = reflect.TypeOf(i).Elem()
27+
}
2228
}
2329

2430
return &Config{
25-
MapEnv: mapEnv,
26-
Types: CreateTypesTable(i),
27-
Optimize: true,
31+
MapEnv: mapEnv,
32+
Types: CreateTypesTable(i),
33+
Optimize: true,
34+
UndefinedVariableType: mapValueType,
2835
}
2936
}
3037

0 commit comments

Comments
 (0)