.NET-Community-Toolkit/CommunityToolkit.Mvvm.Sourc.../Extensions/ITypeSymbolExtensions.cs

132 lines
5.3 KiB
C#

// 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.
using System;
using System.Linq;
using Microsoft.CodeAnalysis;
namespace CommunityToolkit.Mvvm.SourceGenerators.Extensions;
/// <summary>
/// Extension methods for the <see cref="ITypeSymbol"/> type.
/// </summary>
internal static class ITypeSymbolExtensions
{
/// <summary>
/// Checks whether or not a given <see cref="ITypeSymbol"/> has or inherits from a specified type.
/// </summary>
/// <param name="typeSymbol">The target <see cref="ITypeSymbol"/> instance to check.</param>
/// <param name="name">The full name of the type to check for inheritance.</param>
/// <returns>Whether or not <paramref name="typeSymbol"/> is or inherits from <paramref name="name"/>.</returns>
public static bool HasOrInheritsFromFullyQualifiedName(this ITypeSymbol typeSymbol, string name)
{
for (ITypeSymbol? currentType = typeSymbol; currentType is not null; currentType = currentType.BaseType)
{
if (currentType.HasFullyQualifiedName(name))
{
return true;
}
}
return false;
}
/// <summary>
/// Checks whether or not a given <see cref="ITypeSymbol"/> inherits from a specified type.
/// </summary>
/// <param name="typeSymbol">The target <see cref="ITypeSymbol"/> instance to check.</param>
/// <param name="name">The full name of the type to check for inheritance.</param>
/// <returns>Whether or not <paramref name="typeSymbol"/> inherits from <paramref name="name"/>.</returns>
public static bool InheritsFromFullyQualifiedName(this ITypeSymbol typeSymbol, string name)
{
INamedTypeSymbol? baseType = typeSymbol.BaseType;
while (baseType != null)
{
if (baseType.HasFullyQualifiedName(name))
{
return true;
}
baseType = baseType.BaseType;
}
return false;
}
/// <summary>
/// Checks whether or not a given <see cref="ITypeSymbol"/> implements an interface with a specified name.
/// </summary>
/// <param name="typeSymbol">The target <see cref="ITypeSymbol"/> instance to check.</param>
/// <param name="name">The full name of the type to check for interface implementation.</param>
/// <returns>Whether or not <paramref name="typeSymbol"/> has an interface with the specified name.</returns>
public static bool HasInterfaceWithFullyQualifiedName(this ITypeSymbol typeSymbol, string name)
{
foreach (INamedTypeSymbol interfaceType in typeSymbol.AllInterfaces)
{
if (interfaceType.HasFullyQualifiedName(name))
{
return true;
}
}
return false;
}
/// <summary>
/// Checks whether or not a given <see cref="ITypeSymbol"/> has or inherits a specified attribute.
/// </summary>
/// <param name="typeSymbol">The target <see cref="ITypeSymbol"/> instance to check.</param>
/// <param name="predicate">The predicate used to match available attributes.</param>
/// <returns>Whether or not <paramref name="typeSymbol"/> has an attribute matching <paramref name="predicate"/>.</returns>
public static bool HasOrInheritsAttribute(this ITypeSymbol typeSymbol, Func<AttributeData, bool> predicate)
{
for (ITypeSymbol? currentType = typeSymbol; currentType is not null; currentType = currentType.BaseType)
{
if (currentType.GetAttributes().Any(predicate))
{
return true;
}
}
return false;
}
/// <summary>
/// Checks whether or not a given <see cref="ITypeSymbol"/> has or inherits a specified attribute.
/// </summary>
/// <param name="typeSymbol">The target <see cref="ITypeSymbol"/> instance to check.</param>
/// <param name="name">The name of the attribute to look for.</param>
/// <returns>Whether or not <paramref name="typeSymbol"/> has an attribute with the specified type name.</returns>
public static bool HasOrInheritsAttributeWithFullyQualifiedName(this ITypeSymbol typeSymbol, string name)
{
for (ITypeSymbol? currentType = typeSymbol; currentType is not null; currentType = currentType.BaseType)
{
if (currentType.HasAttributeWithFullyQualifiedName(name))
{
return true;
}
}
return false;
}
/// <summary>
/// Checks whether or not a given <see cref="ITypeSymbol"/> inherits a specified attribute.
/// If the type has no base type, this method will automatically handle that and return <see langword="false"/>.
/// </summary>
/// <param name="typeSymbol">The target <see cref="ITypeSymbol"/> instance to check.</param>
/// <param name="name">The name of the attribute to look for.</param>
/// <returns>Whether or not <paramref name="typeSymbol"/> has an attribute with the specified type name.</returns>
public static bool InheritsAttributeWithFullyQualifiedName(this ITypeSymbol typeSymbol, string name)
{
if (typeSymbol.BaseType is INamedTypeSymbol baseTypeSymbol)
{
return HasOrInheritsAttributeWithFullyQualifiedName(baseTypeSymbol, name);
}
return false;
}
}