116 lines
4.0 KiB
C#
116 lines
4.0 KiB
C#
// This file is ported and adapted from CommunityToolkit.Mvvm (CommunityToolkit/dotnet)
|
|
|
|
namespace MapperSourceGen.SourceGenerator.Model;
|
|
|
|
using System.Collections.Immutable;
|
|
using Microsoft.CodeAnalysis;
|
|
using static Microsoft.CodeAnalysis.SymbolDisplayTypeQualificationStyle;
|
|
|
|
/// <summary>
|
|
/// Represents information about a type hierarchy in a source code file.
|
|
/// </summary>
|
|
internal sealed partial class HierarchyInfo : IEquatable<HierarchyInfo>
|
|
{
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="HierarchyInfo" /> class.
|
|
/// </summary>
|
|
/// <param name="fileNameHint">The filename hint for the type (including namespace) without extension.</param>
|
|
/// <param name="namespace">The containing namespace for the type.</param>
|
|
/// <param name="hierarchy">The current hierarchy for the type.</param>
|
|
/// <exception cref="ArgumentException"><paramref name="fileNameHint" /> is <c>null</c> or empty.</exception>
|
|
private HierarchyInfo(string fileNameHint, string @namespace, ImmutableArray<TypeInfo> hierarchy)
|
|
{
|
|
if ( string.IsNullOrWhiteSpace(fileNameHint) )
|
|
{
|
|
throw new ArgumentException($"'{nameof(fileNameHint)}' cannot be null or empty.", nameof(fileNameHint));
|
|
}
|
|
|
|
FileNameHint = fileNameHint;
|
|
Hierarchy = hierarchy;
|
|
Namespace = @namespace;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the file name hint (including full namespace) for the type hierarchy.
|
|
/// </summary>
|
|
public string FileNameHint { get; }
|
|
|
|
/// <summary>
|
|
/// Gets a collection of <see cref="TypeInfo" /> representing the hierarchy of types.
|
|
/// </summary>
|
|
public ImmutableArray<TypeInfo> Hierarchy { get; }
|
|
|
|
/// <summary>
|
|
/// Gets the namespace of the type hierarchy.
|
|
/// </summary>
|
|
public string Namespace { get; }
|
|
|
|
public static HierarchyInfo From(INamedTypeSymbol typeSymbol)
|
|
{
|
|
if ( typeSymbol is null )
|
|
{
|
|
throw new ArgumentNullException(nameof(typeSymbol));
|
|
}
|
|
|
|
LinkedList<TypeInfo> hierarchy = [];
|
|
|
|
for ( INamedTypeSymbol? parent = typeSymbol;
|
|
parent is not null;
|
|
parent = parent.ContainingType )
|
|
{
|
|
hierarchy.AddLast(new TypeInfo(parent.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat),
|
|
parent.TypeKind,
|
|
parent.DeclaredAccessibility,
|
|
parent.IsRecord,
|
|
parent.IsSealed));
|
|
}
|
|
|
|
return new HierarchyInfo(typeSymbol.ToDisplayString(new SymbolDisplayFormat(typeQualificationStyle: NameAndContainingTypesAndNamespaces)),
|
|
typeSymbol.ContainingNamespace.ToDisplayString(new SymbolDisplayFormat(typeQualificationStyle: NameAndContainingTypesAndNamespaces)),
|
|
[..hierarchy]);
|
|
}
|
|
|
|
public static bool operator ==(HierarchyInfo? left, HierarchyInfo? right)
|
|
{
|
|
return Equals(left, right);
|
|
}
|
|
|
|
public static bool operator !=(HierarchyInfo? left, HierarchyInfo? right)
|
|
{
|
|
return !Equals(left, right);
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public bool Equals(HierarchyInfo? other)
|
|
{
|
|
if ( other is null )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if ( ReferenceEquals(this, other) )
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return string.Equals(FileNameHint, other.FileNameHint, StringComparison.OrdinalIgnoreCase)
|
|
&& string.Equals(Namespace, other.Namespace, StringComparison.OrdinalIgnoreCase);
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public override bool Equals(object? obj)
|
|
{
|
|
return ReferenceEquals(this, obj) || ( obj is HierarchyInfo other && Equals(other) );
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public override int GetHashCode()
|
|
{
|
|
unchecked
|
|
{
|
|
return ( StringComparer.OrdinalIgnoreCase.GetHashCode(FileNameHint) * 397 )
|
|
^ StringComparer.OrdinalIgnoreCase.GetHashCode(Namespace);
|
|
}
|
|
}
|
|
}
|