1
0
mirror of https://github.com/chylex/.NET-Community-Toolkit.git synced 2025-08-16 23:31:47 +02:00
Files
.github
CommunityToolkit.Common
CommunityToolkit.Diagnostics
CommunityToolkit.HighPerformance
CommunityToolkit.Mvvm
CommunityToolkit.Mvvm.SourceGenerators
Attributes
ComponentModel
Diagnostics
EmbeddedResources
Extensions
AttributeDataExtensions.cs
CompilationExtensions.cs
HashCodeExtensions.cs
IEqualityComparerExtensions.cs
INamedTypeSymbolExtensions.cs
ISymbolExtensions.cs
ITypeSymbolExtensions.cs
IncrementalGeneratorInitializationContextExtensions.cs
IncrementalValuesProviderExtensions.cs
MemberDeclarationSyntaxExtensions.cs
SyntaxNodeExtensions.cs
Helpers
Input
Messaging
Models
System.Runtime.CompilerServices
AnalyzerReleases.Shipped.md
AnalyzerReleases.Unshipped.md
CommunityToolkit.Mvvm.SourceGenerators.csproj
build
tests
.editorconfig
.git-blame-ignore-revs
.gitattributes
.gitignore
.runsettings
CODE_OF_CONDUCT.md
Contributing.md
Directory.Build.props
Directory.Build.targets
License.md
README.md
ThirdPartyNotices.txt
azure-pipelines.yml
dotnet Community Toolkit.sln
toolkit.snk
version.json
2022-03-25 22:27:18 +01:00

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