// 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); } }