// 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; /// /// Represents information about a type hierarchy in a source code file. /// internal sealed partial class HierarchyInfo : IEquatable { /// /// Initializes a new instance of the class. /// /// The filename hint for the type (including namespace) without extension. /// The containing namespace for the type. /// The current hierarchy for the type. /// is null or empty. private HierarchyInfo(string fileNameHint, string @namespace, ImmutableArray hierarchy) { if ( string.IsNullOrWhiteSpace(fileNameHint) ) { throw new ArgumentException($"'{nameof(fileNameHint)}' cannot be null or empty.", nameof(fileNameHint)); } FileNameHint = fileNameHint; Hierarchy = hierarchy; Namespace = @namespace; } /// /// Gets the file name hint (including full namespace) for the type hierarchy. /// public string FileNameHint { get; } /// /// Gets a collection of representing the hierarchy of types. /// public ImmutableArray Hierarchy { get; } /// /// Gets the namespace of the type hierarchy. /// public string Namespace { get; } public static HierarchyInfo From(INamedTypeSymbol typeSymbol) { if ( typeSymbol is null ) { throw new ArgumentNullException(nameof(typeSymbol)); } LinkedList 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); } /// 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); } /// public override bool Equals(object? obj) { return ReferenceEquals(this, obj) || ( obj is HierarchyInfo other && Equals(other) ); } /// public override int GetHashCode() { unchecked { return ( StringComparer.OrdinalIgnoreCase.GetHashCode(FileNameHint) * 397 ) ^ StringComparer.OrdinalIgnoreCase.GetHashCode(Namespace); } } }