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  }