mirror of
https://github.com/chylex/.NET-Community-Toolkit.git
synced 2024-11-23 22:42:47 +01:00
120 lines
4.9 KiB
C#
120 lines
4.9 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.Collections.Immutable;
|
|
using Microsoft.CodeAnalysis;
|
|
|
|
namespace CommunityToolkit.Mvvm.SourceGenerators.Extensions;
|
|
|
|
/// <summary>
|
|
/// Extension methods for the <see cref="ISymbol"/> type.
|
|
/// </summary>
|
|
internal static class ISymbolExtensions
|
|
{
|
|
/// <summary>
|
|
/// Gets the fully qualified name for a given symbol.
|
|
/// </summary>
|
|
/// <param name="symbol">The input <see cref="ISymbol"/> instance.</param>
|
|
/// <returns>The fully qualified name for <paramref name="symbol"/>.</returns>
|
|
public static string GetFullyQualifiedName(this ISymbol symbol)
|
|
{
|
|
return symbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the fully qualified name for a given symbol, including nullability annotations
|
|
/// </summary>
|
|
/// <param name="symbol">The input <see cref="ISymbol"/> instance.</param>
|
|
/// <returns>The fully qualified name for <paramref name="symbol"/>.</returns>
|
|
public static string GetFullyQualifiedNameWithNullabilityAnnotations(this ISymbol symbol)
|
|
{
|
|
return symbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat.AddMiscellaneousOptions(SymbolDisplayMiscellaneousOptions.IncludeNullableReferenceTypeModifier));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Checks whether or not a given type symbol has a specified full name.
|
|
/// </summary>
|
|
/// <param name="symbol">The input <see cref="ISymbol"/> instance to check.</param>
|
|
/// <param name="name">The full name to check.</param>
|
|
/// <returns>Whether <paramref name="symbol"/> has a full name equals to <paramref name="name"/>.</returns>
|
|
public static bool HasFullyQualifiedName(this ISymbol symbol, string name)
|
|
{
|
|
return symbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat) == name;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Checks whether or not a given symbol has an attribute with the specified full name.
|
|
/// </summary>
|
|
/// <param name="symbol">The input <see cref="ISymbol"/> instance to check.</param>
|
|
/// <param name="name">The attribute name to look for.</param>
|
|
/// <returns>Whether or not <paramref name="symbol"/> has an attribute with the specified name.</returns>
|
|
public static bool HasAttributeWithFullyQualifiedName(this ISymbol symbol, string name)
|
|
{
|
|
ImmutableArray<AttributeData> attributes = symbol.GetAttributes();
|
|
|
|
foreach (AttributeData attribute in attributes)
|
|
{
|
|
if (attribute.AttributeClass?.HasFullyQualifiedName(name) == true)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Calculates the effective accessibility for a given symbol.
|
|
/// </summary>
|
|
/// <param name="symbol">The <see cref="ISymbol"/> instance to check.</param>
|
|
/// <returns>The effective accessibility for <paramref name="symbol"/>.</returns>
|
|
public static Accessibility GetEffectiveAccessibility(this ISymbol symbol)
|
|
{
|
|
// Start by assuming it's visible
|
|
Accessibility visibility = Accessibility.Public;
|
|
|
|
// Handle special cases
|
|
switch (symbol.Kind)
|
|
{
|
|
case SymbolKind.Alias: return Accessibility.Private;
|
|
case SymbolKind.Parameter: return GetEffectiveAccessibility(symbol.ContainingSymbol);
|
|
case SymbolKind.TypeParameter: return Accessibility.Private;
|
|
}
|
|
|
|
// Traverse the symbol hierarchy to determine the effective accessibility
|
|
while (symbol is not null && symbol.Kind != SymbolKind.Namespace)
|
|
{
|
|
switch (symbol.DeclaredAccessibility)
|
|
{
|
|
case Accessibility.NotApplicable:
|
|
case Accessibility.Private:
|
|
return Accessibility.Private;
|
|
case Accessibility.Internal:
|
|
case Accessibility.ProtectedAndInternal:
|
|
visibility = Accessibility.Internal;
|
|
break;
|
|
}
|
|
|
|
symbol = symbol.ContainingSymbol;
|
|
}
|
|
|
|
return visibility;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Checks whether or not a given symbol can be accessed from a specified assembly.
|
|
/// </summary>
|
|
/// <param name="symbol">The input <see cref="ISymbol"/> instance to check.</param>
|
|
/// <param name="assembly">The assembly to check the accessibility of <paramref name="symbol"/> for.</param>
|
|
/// <returns>Whether <paramref name="assembly"/> can access <paramref name="symbol"/>.</returns>
|
|
public static bool CanBeAccessedFrom(this ISymbol symbol, IAssemblySymbol assembly)
|
|
{
|
|
Accessibility accessibility = symbol.GetEffectiveAccessibility();
|
|
|
|
return
|
|
accessibility == Accessibility.Public ||
|
|
accessibility == Accessibility.Internal && symbol.ContainingAssembly.GivesAccessTo(assembly);
|
|
}
|
|
}
|