in sdk/Sdk.Generators/FunctionMetadataProviderGenerator/FunctionMetadataProviderGenerator.Parser.cs [613:676]
private bool TryGetAttributeProperties(AttributeData attributeData, Location? attribLocation, out IDictionary<string, object?>? attrProperties)
{
attrProperties = new Dictionary<string, object?>();
if (attributeData.ConstructorArguments.Any())
{
if (!TryLoadConstructorArguments(attributeData, attrProperties, attribLocation))
{
attrProperties = null;
return false;
}
}
foreach (var namedArgument in attributeData.NamedArguments)
{
if (IsArrayOrNotNull(namedArgument.Value))
{
if (string.Equals(namedArgument.Key, Constants.FunctionMetadataBindingProps.IsBatchedKey)
&& !attrProperties.ContainsKey("cardinality") && namedArgument.Value.Value != null)
{
var argValue = (bool)namedArgument.Value.Value; // isBatched only takes in booleans and the generator will parse it as a bool so we can type cast this to use in the next line
attrProperties["cardinality"] = argValue ? "Many" : "One";
}
else
{
if (TryParseValueByType(namedArgument.Value, out object? argValue))
{
attrProperties[namedArgument.Key] = argValue;
}
else
{
_context.ReportDiagnostic(Diagnostic.Create(DiagnosticDescriptors.InvalidBindingAttributeArgument, attribLocation));
return false;
}
}
}
}
// some properties have default values, so if these properties were not already defined in constructor or named arguments, we will auto-add them here
foreach (var member in attributeData.AttributeClass!.GetMembers().Where(a => a is IPropertySymbol))
{
var defaultValAttrList = member.GetAttributes().Where(attr => SymbolEqualityComparer.Default.Equals(attr.AttributeClass, _knownFunctionMetadataTypes.DefaultValue));
if (defaultValAttrList.SingleOrDefault() is { } defaultValAttr) // list will only be of size one b/c there cannot be duplicates of an attribute on one piece of syntax
{
var argName = member.Name;
object arg = defaultValAttr.ConstructorArguments.SingleOrDefault().Value!; // only one constructor arg in DefaultValue attribute (the default value)
if (arg is bool b && string.Equals(argName, Constants.FunctionMetadataBindingProps.IsBatchedKey))
{
if (!attrProperties.Keys.Contains("cardinality"))
{
attrProperties["cardinality"] = b ? "Many" : "One";
}
}
else if (!attrProperties.Keys.Any(a => string.Equals(a, argName, StringComparison.OrdinalIgnoreCase))) // check if this property has been assigned a value already in constructor or named args
{
attrProperties[argName] = arg;
}
}
}
return true;
}