public ExpressionEmitter(JsonTextWriter writer, EmitterContext context) { this.writer = writer; this.context = context; this.converter = new ExpressionConverter(context); }
public static LanguageExpression FormatCrossScopeResourceId(ExpressionConverter expressionConverter, ScopeData scopeData, string fullyQualifiedType, IEnumerable <LanguageExpression> nameSegments) { var arguments = new List <LanguageExpression>(); switch (scopeData.RequestedScope) { case ResourceScopeType.TenantScope: arguments.Add(new JTokenExpression(fullyQualifiedType)); arguments.AddRange(nameSegments); return(new FunctionExpression("tenantResourceId", arguments.ToArray(), Array.Empty <LanguageExpression>())); case ResourceScopeType.SubscriptionScope: if (scopeData.SubscriptionIdProperty != null) { arguments.Add(expressionConverter.ConvertExpression(scopeData.SubscriptionIdProperty)); } arguments.Add(new JTokenExpression(fullyQualifiedType)); arguments.AddRange(nameSegments); return(new FunctionExpression("subscriptionResourceId", arguments.ToArray(), Array.Empty <LanguageExpression>())); case ResourceScopeType.ResourceGroupScope: // We avoid using the 'resourceId' function at all here, because its behavior differs depending on the scope that it is called FROM. LanguageExpression scope; if (scopeData.SubscriptionIdProperty == null) { if (scopeData.ResourceGroupProperty == null) { scope = new FunctionExpression("resourceGroup", Array.Empty <LanguageExpression>(), new LanguageExpression[] { new JTokenExpression("id") }); } else { var subscriptionId = new FunctionExpression("subscription", Array.Empty <LanguageExpression>(), new LanguageExpression[] { new JTokenExpression("subscriptionId") }); var resourceGroup = expressionConverter.ConvertExpression(scopeData.ResourceGroupProperty); scope = ExpressionConverter.GenerateResourceGroupScope(subscriptionId, resourceGroup); } } else { if (scopeData.ResourceGroupProperty == null) { throw new NotImplementedException($"Cannot format resourceId with non-null subscription and null resourceGroup"); } var subscriptionId = expressionConverter.ConvertExpression(scopeData.SubscriptionIdProperty); var resourceGroup = expressionConverter.ConvertExpression(scopeData.ResourceGroupProperty); scope = ExpressionConverter.GenerateResourceGroupScope(subscriptionId, resourceGroup); } // We've got to DIY it, unfortunately. The resourceId() function behaves differently when used at different scopes, so is unsuitable here. return(ExpressionConverter.GenerateScopedResourceId(scope, fullyQualifiedType, nameSegments)); case ResourceScopeType.ManagementGroupScope: if (scopeData.ManagementGroupNameProperty != null) { var managementGroupScope = expressionConverter.GenerateManagementGroupResourceId(scopeData.ManagementGroupNameProperty, true); return(ExpressionConverter.GenerateScopedResourceId(managementGroupScope, fullyQualifiedType, nameSegments)); } // We need to do things slightly differently for Management Groups, because there is no IL to output for "Give me a fully-qualified resource id at the current scope", // and we don't even have a mechanism for reliably getting the current scope (e.g. something like 'deployment().scope'). There are plans to add a managementGroupResourceId function, // but until we have it, we should generate unqualified resource Ids. There should not be a risk of collision, because we do not allow mixing of resource scopes in a single bicep file. return(ExpressionConverter.GenerateUnqualifiedResourceId(fullyQualifiedType, nameSegments)); default: throw new NotImplementedException($"Cannot format resourceId for scope {scopeData.RequestedScope}"); } }
public void EmitResourceIdReference(ModuleSymbol moduleSymbol, SyntaxBase?indexExpression, SyntaxBase newContext) { var converterForContext = this.converter.CreateConverterForIndexReplacement(ExpressionConverter.GetModuleNameSyntax(moduleSymbol), indexExpression, newContext); var resourceIdExpression = converterForContext.GetFullyQualifiedResourceId(moduleSymbol); var serialized = ExpressionSerializer.SerializeExpression(resourceIdExpression); writer.WriteValue(serialized); }