in sdk/Sdk.Generators/FunctionMetadataProviderGenerator/FunctionMetadataProviderGenerator.Parser.cs [241:327]
private bool TryGetParameterInputAndTriggerBindings(IMethodSymbol method, out bool supportsRetryOptions, out bool hasHttpTrigger, out IList<IDictionary<string, object>>? bindingsList)
{
supportsRetryOptions = false;
hasHttpTrigger = false;
bindingsList = new List<IDictionary<string, object>>();
foreach (IParameterSymbol parameter in method.Parameters)
{
// If there's no attribute, we can assume that this parameter is not a binding
if (!parameter.GetAttributes().Any())
{
continue;
}
// Check to see if any of the attributes associated with this parameter is a BindingAttribute
foreach (var attribute in parameter.GetAttributes())
{
if (SymbolEqualityComparer.Default.Equals(attribute.AttributeClass?.BaseType?.BaseType, _knownFunctionMetadataTypes.BindingAttribute))
{
if (SymbolEqualityComparer.Default.Equals(attribute.AttributeClass, _knownFunctionMetadataTypes.HttpTriggerBinding))
{
hasHttpTrigger = true;
}
DataType dataType = _dataTypeParser.GetDataType(parameter.Type);
bool cardinalityValidated = false;
bool supportsDeferredBinding = SupportsDeferredBinding(attribute, parameter.Type.ToString());
if (_cardinalityParser.IsCardinalitySupported(attribute))
{
DataType updatedDataType = DataType.Undefined;
if (!_cardinalityParser.IsCardinalityValid(parameter, attribute, out updatedDataType))
{
_context.ReportDiagnostic(Diagnostic.Create(DiagnosticDescriptors.InvalidCardinality, Location.None, parameter.Name));
bindingsList = null;
return false;
}
// update the DataType of this binding with the updated type found during call to IsCardinalityValid
// ex. IList<String> would be evaluated as "Undefined" by the call to GetDataType
// but it would be correctly evaluated as "String" during the call to IsCardinalityValid which parses iterable collections
dataType = updatedDataType;
cardinalityValidated = true;
}
string bindingName = parameter.Name;
if (!TryCreateBindingDictionary(attribute, bindingName, Location.None, out IDictionary<string, object>? bindings, supportsDeferredBinding))
{
bindings = null;
return false;
}
// If cardinality is supported and validated, but was not found in named args, constructor args, or default value attributes
// default to Cardinality: One to stay in sync with legacy generator.
if (cardinalityValidated && !bindings!.Keys.Contains("cardinality"))
{
bindings!.Add("cardinality", "One");
}
if (dataType is not DataType.Undefined)
{
bindings!.Add("dataType", Enum.GetName(typeof(DataType), dataType));
}
// check for binding capabilities
var bindingCapabilitiesAttr = attribute?.AttributeClass?.GetAttributes().Where(a => (SymbolEqualityComparer.Default.Equals(a.AttributeClass, _knownFunctionMetadataTypes.BindingCapabilitiesAttribute)));
if (bindingCapabilitiesAttr.FirstOrDefault() is not null)
{
var bindingCapabilities = bindingCapabilitiesAttr.FirstOrDefault().ConstructorArguments;
if (bindingCapabilities.Any(s => string.Equals(s.Values.FirstOrDefault().Value?.ToString(), Constants.BindingCapabilities.FunctionLevelRetry, StringComparison.OrdinalIgnoreCase)))
{
supportsRetryOptions = true;
}
}
bindingsList.Add(bindings!);
}
}
}
return true;
}