public void EmitCopyObject(string?name, ForSyntax syntax, SyntaxBase?input, string?copyIndexOverride = null) { writer.WriteStartObject(); if (name is not null) { this.EmitProperty("name", name); } // construct the length ARM expression from the Bicep array expression // type check has already ensured that the array expression is an array this.EmitPropertyWithTransform( "count", syntax.Expression, arrayExpression => new FunctionExpression("length", new[] { arrayExpression }, Array.Empty <LanguageExpression>())); if (input != null) { if (copyIndexOverride == null) { this.EmitProperty("input", input); } else { this.EmitPropertyWithTransform("input", input, expression => { // the named copy index in the serialized expression is incorrect // because the object syntax here does not match the JSON equivalent due to the presence of { "value": ... } wrappers // for now, we will manually replace the copy index in the converted expression // this approach will not work for nested property loops var visitor = new LanguageExpressionVisitor { OnFunctionExpression = function => { if (string.Equals(function.Function, "copyIndex") && function.Parameters.Length == 1 && function.Parameters[0] is JTokenExpression) { // it's an invocation of the copyIndex function with 1 argument with a literal value // replace the argument with the correct value function.Parameters = new LanguageExpression[] { new JTokenExpression("value") }; } } }; // mutate the expression expression.Accept(visitor); return(expression); }); } } writer.WriteEndObject(); }
public static void VisitExpressions <TToken>(TToken input, Action <LanguageExpression> visitFunc) where TToken : JToken { var visitor = new LanguageExpressionVisitor { OnFunctionExpression = visitFunc, OnJTokenExpression = visitFunc, }; void VisitLanguageExpressions(string value) { if (ExpressionsEngine.IsLanguageExpression(value)) { var expression = ExpressionsEngine.ParseLanguageExpression(value); expression.Accept(visitor); } } if (input is JValue jValue && jValue.ToObject <string>() is { } value) { VisitLanguageExpressions(value); return; } JsonUtility.WalkJsonRecursive( input, objectAction: @object => { foreach (var property in @object.Properties()) { VisitLanguageExpressions(property.Name); } }, tokenAction: token => { if (token.Type == JTokenType.String && token.ToObject <string>() is { } value) { VisitLanguageExpressions(value); } });