EvalBool and Interpolation fixes (#424)

* A new attempt at Interpolation and EvalBool

* One small merge fix

* Remove some fmt.Printfs
This commit is contained in:
Torbjørn Vatn
2020-11-17 18:31:05 +01:00
committed by GitHub
parent 3f4998a4ed
commit 8ba3306aa4
6 changed files with 762 additions and 117 deletions

View File

@@ -16,11 +16,12 @@ import (
"gopkg.in/godo.v2/glob"
)
var contextPattern, expressionPattern *regexp.Regexp
var contextPattern, expressionPattern, operatorPattern *regexp.Regexp
func init() {
contextPattern = regexp.MustCompile(`^(\w+(?:\[.+])*)(?:\.([\w-]+))?(.*)$`)
contextPattern = regexp.MustCompile(`^([^.]*(?:\[.+])*)(?:\.([\w-]+))?(.*)$`)
expressionPattern = regexp.MustCompile(`\${{\s*(.+?)\s*}}`)
operatorPattern = regexp.MustCompile("^[!=><|&]+$")
}
// NewExpressionEvaluator creates a new evaluator
@@ -49,8 +50,9 @@ func (sc *StepContext) NewExpressionEvaluator() ExpressionEvaluator {
// ExpressionEvaluator is the interface for evaluating expressions
type ExpressionEvaluator interface {
Evaluate(string) (string, error)
Evaluate(string) (string, bool, error)
Interpolate(string) string
InterpolateWithStringCheck(string) (string, bool)
Rewrite(string) string
}
@@ -58,7 +60,7 @@ type expressionEvaluator struct {
vm *otto.Otto
}
func (ee *expressionEvaluator) Evaluate(in string) (string, error) {
func (ee *expressionEvaluator) Evaluate(in string) (string, bool, error) {
re := ee.Rewrite(in)
if re != in {
log.Debugf("Evaluating '%s' instead of '%s'", re, in)
@@ -66,32 +68,40 @@ func (ee *expressionEvaluator) Evaluate(in string) (string, error) {
val, err := ee.vm.Run(re)
if err != nil {
return "", err
return "", false, err
}
if val.IsNull() || val.IsUndefined() {
return "", nil
return "", false, nil
}
return val.ToString()
valAsString, err := val.ToString()
if err != nil {
return "", false, err
}
return valAsString, val.IsString(), err
}
func (ee *expressionEvaluator) Interpolate(in string) string {
func (ee *expressionEvaluator) Interpolate(in string) string{
interpolated, _ := ee.InterpolateWithStringCheck(in)
return interpolated
}
func (ee *expressionEvaluator) InterpolateWithStringCheck(in string) (string, bool) {
errList := make([]error, 0)
out := in
isString := false
for {
out = expressionPattern.ReplaceAllStringFunc(in, func(match string) string {
// Extract and trim the actual expression inside ${{...}} delimiters
expression := expressionPattern.ReplaceAllString(match, "$1")
// Evaluate the expression and retrieve errors if any
negatedExpression := strings.HasPrefix(expression, "!")
evaluated, err := ee.Evaluate(strings.ReplaceAll(expression, "!", ""))
evaluated, evaluatedIsString, err := ee.Evaluate(expression)
if err != nil {
errList = append(errList, err)
}
if negatedExpression {
evaluated = fmt.Sprintf("!%s", evaluated)
}
isString = evaluatedIsString
return evaluated
})
if len(errList) > 0 {
@@ -104,7 +114,7 @@ func (ee *expressionEvaluator) Interpolate(in string) string {
}
in = out
}
return out
return out, isString
}
// Rewrite tries to transform any javascript property accessor into its bracket notation.