// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
// This file is ported and adapted from ComputeSharp (Sergio0694/ComputeSharp),
// more info in ThirdPartyNotices.txt in the root of the project.
using System.Collections.Generic;
using Microsoft.CodeAnalysis;
namespace CommunityToolkit.Mvvm.SourceGenerators.Extensions;
///
/// Extension methods for the type.
///
internal static class AttributeDataExtensions
{
///
/// Checks whether a given instance contains a specified named argument.
///
/// The type of argument to check.
/// The target instance to check.
/// The name of the argument to check.
/// The expected value for the target named argument.
/// Whether or not contains an argument named with the expected value.
public static bool HasNamedArgument(this AttributeData attributeData, string name, T? value)
{
foreach (KeyValuePair properties in attributeData.NamedArguments)
{
if (properties.Key == name)
{
return
properties.Value.Value is T argumentValue &&
EqualityComparer.Default.Equals(argumentValue, value);
}
}
return false;
}
///
/// Gets a given named argument value from an instance, or a fallback value.
///
/// The type of argument to check.
/// The target instance to check.
/// The name of the argument to check.
/// The fallback value to use if the named argument is not present.
/// The argument named , or a fallback value.
public static T? GetNamedArgument(this AttributeData attributeData, string name, T? fallback = default)
{
if (attributeData.TryGetNamedArgument(name, out T? value))
{
return value;
}
return fallback;
}
///
/// Tries to get a given named argument value from an instance, if present.
///
/// The type of argument to check.
/// The target instance to check.
/// The name of the argument to check.
/// The resulting argument value, if present.
/// Whether or not contains an argument named with a valid value.
public static bool TryGetNamedArgument(this AttributeData attributeData, string name, out T? value)
{
foreach (KeyValuePair properties in attributeData.NamedArguments)
{
if (properties.Key == name)
{
value = (T?)properties.Value.Value;
return true;
}
}
value = default;
return false;
}
///
/// Enumerates all items in a flattened sequence of constructor arguments for a given instance.
///
/// The type of constructor arguments to retrieve.
/// The target instance to get the arguments from.
/// A sequence of all constructor arguments of the specified type from .
public static IEnumerable GetConstructorArguments(this AttributeData attributeData)
where T : class
{
static IEnumerable Enumerate(IEnumerable constants)
{
foreach (TypedConstant constant in constants)
{
if (constant.IsNull)
{
yield return null;
}
if (constant.Kind == TypedConstantKind.Primitive &&
constant.Value is T value)
{
yield return value;
}
else if (constant.Kind == TypedConstantKind.Array)
{
foreach (T? item in Enumerate(constant.Values))
{
yield return item;
}
}
}
}
return Enumerate(attributeData.ConstructorArguments);
}
}