| File: FindSymbols\FindReferences\DependentTypeFinder_ImplementingTypes.cs | Web Access |
| Project: src\roslyn\src\Workspaces\Core\Portable\Microsoft.CodeAnalysis.Workspaces.csproj (Microsoft.CodeAnalysis.Workspaces) |
// 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.Generic; using System.Collections.Immutable; using System.Threading; using System.Threading.Tasks; namespace Microsoft.CodeAnalysis.FindSymbols; internal static partial class DependentTypeFinder { private static async Task<ImmutableArray<INamedTypeSymbol>> FindImplementingTypesInCurrentProcessAsync( INamedTypeSymbol type, Solution solution, IImmutableSet<Project>? projects, bool transitive, CancellationToken cancellationToken) { // Only an interface can be implemented. if (type?.TypeKind == TypeKind.Interface) { // Note: it is intentional that we do TypeHasBaseTypeInSet even though we're searching for interfaces // (which are never in the BaseType chain of a type). The reason for this is the following case: // // interface IGoo { } // // class Base : IGoo { } // // class Derived : Base { } // // In this case, IGoo has two implementations (Base and Derived). When searching we'll first find the // 'Base' match and will add to the set. Then, we'll look for types that have 'Base' in their // inheritance chain, and we need to match that by looking in the .BaseType inheritance chain when // looking at 'Derived'. static bool TypeMatches(INamedTypeSymbol type, HashSet<INamedTypeSymbol> set) => TypeHasBaseTypeInSet(type, set) || TypeHasInterfaceInSet(type, set); // As long as we keep hitting derived interfaces or implementing non-sealed classes we need to keep // looking (as those types themselves may have more derived classes that would b implementations of this // interface). If we hit structs/sealed-classes though we can stop as they can't have any more types // that inherit from them. var allTypes = await DescendInheritanceTreeAsync(type, solution, projects, typeMatches: TypeMatches, shouldContinueSearching: s_isInterfaceOrNonSealedClass, transitive: transitive, cancellationToken: cancellationToken).ConfigureAwait(false); // Only classes/struct/delegates/enums implement interface types. Derived interfaces can be found with // FindDerivedInterfacesAsync. Delegates/Enums only happen in a few corner cases. For example, enums // implement IComparable, and delegates implement ICloneable. return allTypes.WhereAsArray( t => t.TypeKind is TypeKind.Class or TypeKind.Struct or TypeKind.Delegate or TypeKind.Enum); } return []; } }