sdk/Sdk.Generators/Extensions/ISymbolExtensions.cs (86 lines of code) (raw):

// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. using System; using System.Collections.Generic; using System.Linq; using System.Text; using Microsoft.CodeAnalysis; namespace Microsoft.Azure.Functions.Worker.Sdk.Generators { internal static class ISymbolExtensions { /// <summary> /// Walks the symbol tree to generate the fully qualified name of a type symbol. /// Ex input: A Symbol for "Task" token /// Output: "System.Threading.Tasks.Task" /// </summary> internal static string GetFullName(this ITypeSymbol typeSymbol) { var symbol = typeSymbol as ISymbol; if (symbol == null || IsRootNamespace(symbol)) { return string.Empty; } var sb = new StringBuilder(symbol.MetadataName); if (symbol is IArrayTypeSymbol arraySymbol) // arrays need to be handled differently b/c the properties used to get the full name for other symbols are null for IArrayTypeSymbols { sb.Append(arraySymbol.ElementType.GetFullName()); // ex: for string[], the ElementType is System.String and that is the full name returned at this step. sb.Append("[]"); // System.Byte[], System.String[] are the full names for array types of element type Byte, String and we auto-add the brackets here. } else { symbol = symbol.ContainingSymbol; while (!IsRootNamespace(symbol)) { sb.Insert(0, '.'); sb.Insert(0, symbol.MetadataName); symbol = symbol.ContainingSymbol; } } return sb.ToString(); } private static bool IsRootNamespace(ISymbol symbol) { if (symbol is INamespaceSymbol namespaceSymbol) { return namespaceSymbol.IsGlobalNamespace; } return false; } internal static bool IsOrDerivedFrom(this ITypeSymbol symbol, ITypeSymbol? other) { if (other is null) { return false; } var current = symbol; while (current != null) { if(SymbolEqualityComparer.Default.Equals(current, other) || SymbolEqualityComparer.Default.Equals(current.OriginalDefinition, other)) { return true; } current = current.BaseType; } return false; } internal static bool IsOrImplements(this ITypeSymbol symbol, ITypeSymbol? other) { if (other is null) { return false; } var current = symbol; while (current != null) { foreach (var member in current.Interfaces) { if (member.IsOrDerivedFrom(other)) { return true; } } current = current.BaseType; } return false; } internal static bool IsOrImplementsOrDerivesFrom(this ITypeSymbol symbol, ITypeSymbol? other) { return symbol.IsOrImplements(other) || symbol.IsOrDerivedFrom(other); } } }