File: INamedTypeSymbolExtensions.cs
Web Access
Project: src\src\tools\illink\src\ILLink.RoslynAnalyzer\ILLink.RoslynAnalyzer.csproj (ILLink.RoslynAnalyzer)
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
using System;
using System.Collections.Generic;
using Microsoft.CodeAnalysis;
 
namespace ILLink.RoslynAnalyzer
{
	static class INamedTypeSymbolExtensions
	{
		/// <summary>
		/// Returns true if <see paramref="type" /> has the same name as <see paramref="typename" />
		/// </summary>
		internal static bool HasName (this INamedTypeSymbol type, string typeName)
		{
			var roSpan = typeName.AsSpan ();
			INamespaceOrTypeSymbol? currentType = type;
			while (roSpan.Length > 0) {
				var dot = roSpan.LastIndexOf ('.');
				var currentName = dot < 0 ? roSpan : roSpan.Slice (dot + 1);
				if (currentType is null ||
					!currentName.Equals (currentType.Name.AsSpan (), StringComparison.Ordinal)) {
					return false;
				}
				currentType = (INamespaceOrTypeSymbol?) currentType.ContainingType ?? currentType.ContainingNamespace;
				roSpan = roSpan.Slice (0, dot > 0 ? dot : 0);
			}
 
			return true;
		}
 
		internal static IEnumerable<(ISymbol InterfaceMember, ISymbol ImplementationMember)> GetMemberInterfaceImplementationPairs (this INamedTypeSymbol namedType)
		{
			var interfaces = namedType.Interfaces;
			foreach (INamedTypeSymbol iface in interfaces) {
				foreach (var pair in GetMatchingMembers (namedType, iface)) {
					yield return pair;
				}
			}
		}
 
		private static IEnumerable<(ISymbol InterfaceMember, ISymbol ImplementationMember)> GetMatchingMembers (INamedTypeSymbol implementationSymbol, INamedTypeSymbol interfaceSymbol)
		{
			var members = interfaceSymbol.GetMembers ();
			foreach (ISymbol interfaceMember in members) {
				if (implementationSymbol.FindImplementationForInterfaceMember (interfaceMember) is ISymbol implementationMember) {
					yield return (InterfaceMember: interfaceMember, ImplementationMember: implementationMember);
				}
			}
			foreach (var iface in interfaceSymbol.Interfaces) {
				foreach (var pair in GetMatchingMembers (implementationSymbol, iface)) {
					yield return pair;
				}
			}
		}
	}
}