github.com/coveo/gotemplate@v2.7.7+incompatible/template/razor_repl_assign.go (about) 1 package template 2 3 import ( 4 "fmt" 5 "os" 6 "strings" 7 8 "github.com/coveo/gotemplate/utils" 9 "github.com/fatih/color" 10 ) 11 12 var alreadyIssued = make(map[string]int) 13 14 func assignExpression(repl replacement, match string) string { 15 return assignExpressionInternal(repl, match, false) 16 } 17 18 func assignExpressionAcceptError(repl replacement, match string) string { 19 return assignExpressionInternal(repl, match, true) 20 } 21 22 // TODO: Deprecated, to remove in future version 23 var deprecatedAssign = String(os.Getenv(EnvDeprecatedAssign)).ParseBool() 24 25 func assignExpressionInternal(repl replacement, match string, acceptError bool) string { 26 // TODO: Deprecated, to remove in future version 27 if strings.HasPrefix(match, repl.delimiters[0]) || strings.HasPrefix(match, repl.delimiters[2]+"(") { 28 // This is an already go template assignation 29 return match 30 } 31 if strings.HasPrefix(match, "$") { 32 if deprecatedAssign { 33 return match 34 } 35 } 36 37 matches, _ := utils.MultiMatch(match, repl.re) 38 tp := matches["type"] 39 id := matches["id"] 40 expr := matches["expr"] 41 assign := matches["assign"] 42 if tp == "" || id == "" || expr == "" || assign == "" { 43 log.Errorf("Invalid assign regex %s: %s, must contains type, id and expr", repl.name, repl.expr) 44 return match 45 } 46 47 local := (tp == "$" || tp == "@{" || tp == "@$") && idRegex.MatchString(id) 48 var err error 49 if expr, err = expressionParserInternal(exprRepl, expr, true, !local); err != nil && !acceptError { 50 return match 51 } 52 53 if local { 54 if strings.HasPrefix(match, "$") { 55 // TODO: Deprecated, to remove in future version 56 Log.Warningf("$var := value assignation is deprecated, use @{var} := value instead. In: %s", color.HiBlackString(match)) 57 } 58 59 return fmt.Sprintf("%s- $%s %s %s %s", repl.delimiters[0], id, assign, expr, repl.delimiters[1]) 60 } 61 62 parts := strings.Split(id, ".") 63 object := strings.Join(parts[:len(parts)-1], ".") 64 id = parts[len(parts)-1] 65 66 if tp == "$" { 67 if len(parts) < 2 { 68 if alreadyIssued[match] == 0 { 69 log.Errorf("Invalid local assignment: %s", match) 70 alreadyIssued[match]++ 71 } 72 return match 73 } 74 object = "$" + object 75 } else if strings.HasSuffix(tp, ".") { 76 object = "." + object 77 } else { 78 object = iif(object == "", "$", "$."+object).(string) 79 } 80 81 // To avoid breaking change, we issue a warning instead of assertion if the variable has not been declared before being set 82 // or declared more than once and the feature flag GOTEMPLATE_DEPRECATED_ASSIGN is not set 83 validateFunction := iif(deprecatedAssign, "assert", "assertWarning") 84 validateCode := fmt.Sprintf(map[bool]string{ 85 true: `%[2]s (not (isNil %[1]s)) "%[1]s does not exist, use := to declare new variable"`, 86 false: `%[2]s (isNil %[1]s) "%[1]s has already been declared, use = to overwrite existing value"`, 87 }[assign == "="], fmt.Sprintf("%s%s", iif(strings.HasSuffix(object, "."), object, object+"."), id), validateFunction) 88 89 return fmt.Sprintf(`%[1]s- %[3]s %[2]s%[1]s- set %[4]s "%[5]s" %s %[2]s`, repl.delimiters[0], repl.delimiters[1], validateCode, object, id, expr, repl.delimiters[1]) 90 }