in src/Bicep.Core/TypeSystem/Providers/Az/AzResourceTypeProvider.cs [279:371]
private static ObjectType SetBicepResourceProperties(ObjectType objectType, ResourceScope validParentScopes, ResourceTypeReference typeReference, ResourceTypeGenerationFlags flags)
{
// Local function.
static NamedTypeProperty UpdateFlags(NamedTypeProperty typeProperty, TypePropertyFlags flags) =>
new(typeProperty.Name, typeProperty.TypeReference, flags, typeProperty.Description);
var properties = objectType.Properties;
var isExistingResource = flags.HasFlag(ResourceTypeGenerationFlags.ExistingResource);
var scopePropertyFlags = TypePropertyFlags.WriteOnly | TypePropertyFlags.DeployTimeConstant | TypePropertyFlags.ReadableAtDeployTime | TypePropertyFlags.DisallowAny | TypePropertyFlags.LoopVariant | TypePropertyFlags.SystemProperty;
if (validParentScopes == ResourceScope.Resource && typeReference.TypeSegments.Length < 2)
{
// resource can only be deployed as an extension resource - scope should be required
scopePropertyFlags |= TypePropertyFlags.Required;
}
// TODO: remove 'dependsOn' from the type library
properties = properties.SetItem(LanguageConstants.ResourceDependsOnPropertyName, new(LanguageConstants.ResourceDependsOnPropertyName, LanguageConstants.ResourceOrResourceCollectionRefArray, TypePropertyFlags.WriteOnly | TypePropertyFlags.DisallowAny | TypePropertyFlags.SystemProperty));
if (isExistingResource)
{
// we can refer to a resource at any scope if it is an existing resource not being deployed by this file
properties = properties.SetItem(LanguageConstants.ResourceScopePropertyName, ScopeHelper.CreateExistingResourceScopeProperty(validParentScopes, scopePropertyFlags));
}
else
{
if (ScopeHelper.TryCreateNonExistingResourceScopeProperty(validParentScopes, scopePropertyFlags) is { } scopeProperty)
{
properties = properties.SetItem(LanguageConstants.ResourceScopePropertyName, scopeProperty);
}
// TODO: move this to the type library.
foreach (var propertyName in WriteOnlyDeployTimeConstantPropertyNames)
{
if (properties.TryGetValue(propertyName, out var typeProperty))
{
// Update tags for deploy-time constant properties that are not readable at deploy-time.
properties = properties.SetItem(propertyName, UpdateFlags(typeProperty, typeProperty.Flags | TypePropertyFlags.DeployTimeConstant));
}
}
}
// TODO: move this to the type library.
foreach (var propertyName in ReadWriteDeployTimeConstantPropertyNames)
{
if (properties.TryGetValue(propertyName, out var typeProperty))
{
// Update tags for standardized resource properties that are always readable at deploy-time.
properties = properties.SetItem(propertyName, UpdateFlags(typeProperty, typeProperty.Flags | TypePropertyFlags.ReadableAtDeployTime));
}
}
// add the loop variant and system flags to the name property (if it exists)
if (properties.TryGetValue(ResourceNamePropertyName, out var nameProperty))
{
properties = properties.SetItem(ResourceNamePropertyName, UpdateFlags(nameProperty, nameProperty.Flags | TypePropertyFlags.LoopVariant | TypePropertyFlags.SystemProperty));
}
// add the 'parent' property for child resource types that are not nested inside a parent resource
if (typeReference.TypeSegments.Length > 2 && !flags.HasFlag(ResourceTypeGenerationFlags.NestedResource))
{
var parentType = new ResourceParentType(typeReference);
var parentFlags = TypePropertyFlags.WriteOnly | TypePropertyFlags.DeployTimeConstant | TypePropertyFlags.ReadableAtDeployTime | TypePropertyFlags.DisallowAny | TypePropertyFlags.LoopVariant | TypePropertyFlags.SystemProperty;
properties = properties.SetItem(LanguageConstants.ResourceParentPropertyName, new(LanguageConstants.ResourceParentPropertyName, parentType, parentFlags));
}
// Deployments RP
if (StringComparer.OrdinalIgnoreCase.Equals(typeReference.FormatType(), ResourceTypeDeployments))
{
properties = properties.SetItem("resourceGroup", new("resourceGroup", LanguageConstants.String, TypePropertyFlags.DeployTimeConstant | TypePropertyFlags.SystemProperty));
properties = properties.SetItem("subscriptionId", new("subscriptionId", LanguageConstants.String, TypePropertyFlags.DeployTimeConstant | TypePropertyFlags.SystemProperty));
}
var functions = objectType.MethodResolver.functionOverloads.Concat(GetBicepMethods(typeReference));
foreach (var item in KnownTopLevelResourceProperties())
{
if (!properties.ContainsKey(item.Name))
{
properties = properties.Add(item.Name, new(item.Name, item.TypeReference, item.Flags | TypePropertyFlags.FallbackProperty));
}
}
return new ObjectType(
objectType.Name,
objectType.ValidationFlags,
isExistingResource ? ConvertToReadOnly(properties.Values) : properties.Values,
isExistingResource && objectType.AdditionalProperties is not null
? objectType.AdditionalProperties with { Flags = ConvertToReadOnly(objectType.AdditionalProperties.Flags) }
: objectType.AdditionalProperties,
functions);
}