in src/Bicep.Decompiler/TemplateConverter.cs [579:686]
private SyntaxBase ParseFunctionExpression(FunctionExpression expression)
{
SyntaxBase? baseSyntax = null;
switch (expression.Function.ToLowerInvariant())
{
case "parameters":
{
baseSyntax = ParseParamOrVarFunctionExpression(expression, NameType.Parameter);
break;
}
case "variables":
{
baseSyntax = ParseParamOrVarFunctionExpression(expression, NameType.Variable);
break;
}
case "reference":
{
if (expression.Parameters.Length == 1 && expression.Parameters[0] is FunctionExpression resourceIdExpression && resourceIdExpression.NameEquals("resourceid"))
{
// reference(resourceId(<...>))
// check if it's a reference to a known resource
if (TryLookupResource(expression.Parameters[0]) is { } resourceName)
{
baseSyntax = new PropertyAccessSyntax(
new VariableAccessSyntax(SyntaxFactory.CreateIdentifier(resourceName)),
SyntaxFactory.DotToken,
null,
SyntaxFactory.CreateIdentifier("properties"));
}
}
else if (expression.Parameters.Length == 1)
{
// reference(<name>)
// let's try looking the name up directly
if (TryLookupResource(expression.Parameters[0]) is { } resourceName)
{
baseSyntax = new PropertyAccessSyntax(
new VariableAccessSyntax(SyntaxFactory.CreateIdentifier(resourceName)),
SyntaxFactory.DotToken,
null,
SyntaxFactory.CreateIdentifier("properties"));
}
}
break;
}
case "resourceid":
{
var resourceName = TryLookupResource(expression);
if (resourceName != null)
{
baseSyntax = new PropertyAccessSyntax(
new VariableAccessSyntax(SyntaxFactory.CreateIdentifier(resourceName)),
SyntaxFactory.DotToken,
null,
SyntaxFactory.CreateIdentifier("id"));
}
break;
}
case "format":
{
baseSyntax = TryParseStringExpression(expression);
break;
}
case "concat":
{
if (!CanInterpolate(expression))
{
// we might be dealing with an array
break;
}
baseSyntax = TryParseStringExpression(expression);
break;
}
default:
if (TryReplaceBannedFunction(expression, out var replacedBannedSyntax))
{
baseSyntax = replacedBannedSyntax;
}
break;
}
if (baseSyntax == null)
{
// Try to correct the name - ARM JSON is case-insensitive, but Bicep is sensitive
var functionName = SyntaxHelpers.CorrectWellKnownFunctionCasing(expression.Function);
var expressions = expression.Parameters.Select(ParseLanguageExpression).ToArray();
if (expression.Function.Split('.') is { } funcNameArr &&
funcNameArr.Length == 2 &&
nameResolver.TryLookupName(NameType.Function, GetBicepFunctionName(funcNameArr[0], funcNameArr[1])) is { } resolvedUdfName)
{
// This is a reference to a user-defined function
return SyntaxFactory.CreateFunctionCall(resolvedUdfName, expressions);
}
baseSyntax = SyntaxFactory.CreateFunctionCall(functionName, expressions);
}
foreach (var property in expression.Properties)
{
baseSyntax = ParsePropertyAccess(baseSyntax, property);
}
return baseSyntax;
}