Example #1
0
        /// <inheritdoc cref="FindImplementationsAsync(INamedTypeSymbol, Solution, bool, IImmutableSet{Project}, CancellationToken)"/>
        /// <remarks> Use this overload to avoid boxing the result into an <see cref="IEnumerable{T}"/>.</remarks>
        internal static async Task <ImmutableArray <INamedTypeSymbol> > FindImplementationsArrayAsync(
            INamedTypeSymbol type, Solution solution, bool transitive, IImmutableSet <Project> projects = null, CancellationToken cancellationToken = default)
        {
            var types = await DependentTypeFinder.FindTypesAsync(
                type, solution, projects, transitive, DependentTypesKind.ImplementingTypes, cancellationToken).ConfigureAwait(false);

            return(types.WhereAsArray(t => IsAccessible(t)));
        }
Example #2
0
        internal static async Task <ImmutableArray <SymbolAndProjectId> > FindImplementationsAsync(
            SymbolAndProjectId symbolAndProjectId, Solution solution, IImmutableSet <Project> projects = null, CancellationToken cancellationToken = default)
        {
            // A symbol can only have implementations if it's an interface or a
            // method/property/event from an interface.
            var symbol = symbolAndProjectId.Symbol;

            if (symbol is INamedTypeSymbol namedTypeSymbol)
            {
                var implementingTypes = await DependentTypeFinder.FindTransitivelyImplementingStructuresAndClassesAsync(
                    symbolAndProjectId.WithSymbol(namedTypeSymbol), solution, projects, cancellationToken).ConfigureAwait(false);

                return(implementingTypes.Select(s => (SymbolAndProjectId)s)
                       .Where(IsAccessible)
                       .ToImmutableArray());
            }
            else if (symbol.IsImplementableMember())
            {
                var containingType = symbol.ContainingType.OriginalDefinition;
                var allTypes       = await DependentTypeFinder.FindTransitivelyImplementingStructuresClassesAndInterfacesAsync(
                    symbolAndProjectId.WithSymbol(containingType), solution, projects, cancellationToken).ConfigureAwait(false);

                ImmutableArray <SymbolAndProjectId> .Builder results = null;
                foreach (var t in allTypes.Convert <INamedTypeSymbol, ITypeSymbol>())
                {
                    var implementations = await t.FindImplementationsForInterfaceMemberAsync(symbolAndProjectId, solution, cancellationToken).ConfigureAwait(false);

                    foreach (var implementation in implementations)
                    {
                        var sourceDef = await FindSourceDefinitionAsync(implementation, solution, cancellationToken).ConfigureAwait(false);

                        var bestDef = sourceDef.Symbol != null ? sourceDef : implementation;
                        if (IsAccessible(bestDef))
                        {
                            results ??= ImmutableArray.CreateBuilder <SymbolAndProjectId>();
                            results.Add(bestDef.WithSymbol(bestDef.Symbol.OriginalDefinition));
                        }
                    }
                }

                if (results != null)
                {
                    return(results.Distinct(SymbolAndProjectIdComparer.SymbolEquivalenceInstance)
                           .ToImmutableArray());
                }
            }

            return(ImmutableArray <SymbolAndProjectId> .Empty);
        }
        /// <summary>
        /// Finds the derived classes of the given type. Implementations of an interface are not considered "derived", but can be found
        /// with <see cref="FindImplementationsAsync"/>.
        /// </summary>
        /// <param name="type">The symbol to find derived types of.</param>
        /// <param name="solution">The solution to search in.</param>
        /// <param name="projects">The projects to search. Can be null to search the entire solution.</param>
        /// <param name="cancellationToken"></param>
        /// <returns>The derived types of the symbol. The symbol passed in is not included in this list.</returns>
        public static Task <IEnumerable <INamedTypeSymbol> > FindDerivedClassesAsync(
            INamedTypeSymbol type, Solution solution, IImmutableSet <Project> projects = null, CancellationToken cancellationToken = default(CancellationToken))
        {
            if (type == null)
            {
                throw new ArgumentNullException(nameof(type));
            }

            if (solution == null)
            {
                throw new ArgumentNullException(nameof(solution));
            }

            return(DependentTypeFinder.FindDerivedClassesAsync(type, solution, projects, cancellationToken));
        }
Example #4
0
        internal static Task <ImmutableArray <SymbolAndProjectId <INamedTypeSymbol> > > FindDerivedClassesAsync(
            SymbolAndProjectId <INamedTypeSymbol> typeAndProjectId, Solution solution, IImmutableSet <Project> projects = null, CancellationToken cancellationToken = default)
        {
            var type = typeAndProjectId.Symbol;

            if (type == null)
            {
                throw new ArgumentNullException(nameof(type));
            }

            if (solution == null)
            {
                throw new ArgumentNullException(nameof(solution));
            }

            return(DependentTypeFinder.FindTransitivelyDerivedClassesAsync(type, solution, projects, cancellationToken));
        }
Example #5
0
        internal static async Task <IEnumerable <SymbolAndProjectId> > FindImplementationsAsync(
            SymbolAndProjectId symbolAndProjectId, Solution solution, IImmutableSet <Project> projects = null, CancellationToken cancellationToken = default(CancellationToken))
        {
            // A symbol can only have implementations if it's an interface or a
            // method/property/event from an interface.
            var symbol = symbolAndProjectId.Symbol;

            if (symbol is INamedTypeSymbol)
            {
                var namedTypeSymbol   = (INamedTypeSymbol)symbol;
                var implementingTypes = await DependentTypeFinder.FindTransitivelyImplementingTypesAsync(namedTypeSymbol, solution, projects, cancellationToken).ConfigureAwait(false);

                return(implementingTypes.Select(s => (SymbolAndProjectId)s)
                       .Where(IsAccessible)
                       .ToList());
            }
            else if (symbol.IsImplementableMember())
            {
                var containingType = symbol.ContainingType.OriginalDefinition;
                var allTypes       = await DependentTypeFinder.FindTransitivelyImplementingTypesAsync(containingType, solution, projects, cancellationToken).ConfigureAwait(false);

                List <SymbolAndProjectId> results = null;
                foreach (var t in allTypes.Convert <INamedTypeSymbol, ITypeSymbol>())
                {
                    foreach (var m in t.FindImplementationsForInterfaceMember(symbol, solution.Workspace, cancellationToken))
                    {
                        var sourceDef = await FindSourceDefinitionAsync(m, solution, cancellationToken).ConfigureAwait(false);

                        var bestDef = sourceDef.Symbol != null ? sourceDef : m;
                        if (IsAccessible(bestDef))
                        {
                            results = results ?? new List <SymbolAndProjectId>();
                            results.Add(bestDef.WithSymbol(bestDef.Symbol.OriginalDefinition));
                        }
                    }
                }

                if (results != null)
                {
                    return(results.Distinct(SymbolAndProjectIdComparer.SymbolEquivalenceInstance));
                }
            }

            return(SpecializedCollections.EmptyEnumerable <SymbolAndProjectId>());
        }
Example #6
0
        /// <summary>
        /// Finds the derived classes of the given type. Implementations of an interface are not considered "derived", but can be found
        /// with <see cref="FindImplementationsAsync(ISymbol, Solution, IImmutableSet{Project}, CancellationToken)"/>.
        /// </summary>
        /// <param name="type">The symbol to find derived types of.</param>
        /// <param name="solution">The solution to search in.</param>
        /// <param name="projects">The projects to search. Can be null to search the entire solution.</param>
        /// <param name="cancellationToken"></param>
        /// <returns>The derived types of the symbol. The symbol passed in is not included in this list.</returns>
        public static async Task <IEnumerable <INamedTypeSymbol> > FindDerivedClassesAsync(
            INamedTypeSymbol type, Solution solution, IImmutableSet <Project> projects = null, CancellationToken cancellationToken = default)
        {
            if (type == null)
            {
                throw new ArgumentNullException(nameof(type));
            }

            if (solution == null)
            {
                throw new ArgumentNullException(nameof(solution));
            }

            if (solution.GetOriginatingProjectId(type) == null)
            {
                throw new ArgumentException(WorkspacesResources.Symbols_project_could_not_be_found_in_the_provided_solution, nameof(type));
            }

            return(await DependentTypeFinder.FindTransitivelyDerivedClassesAsync(
                       type, solution, projects, cancellationToken).ConfigureAwait(false));
        }
Example #7
0
            > FindDerivedInterfacesArrayAsync(
            INamedTypeSymbol type,
            Solution solution,
            bool transitive,
            IImmutableSet <Project> projects    = null,
            CancellationToken cancellationToken = default
            )
        {
            var types = await DependentTypeFinder
                        .FindTypesAsync(
                type,
                solution,
                projects,
                transitive,
                DependentTypesKind.DerivedInterfaces,
                cancellationToken
                )
                        .ConfigureAwait(false);

            return(types.WhereAsArray(t => IsAccessible(t)));
        }
        /// <summary>
        /// Finds the symbols that implement an interface or interface member.
        /// </summary>
        public static async Task <IEnumerable <ISymbol> > FindImplementationsAsync(
            ISymbol symbol, Solution solution, IImmutableSet <Project> projects = null, CancellationToken cancellationToken = default(CancellationToken))
        {
            // A symbol can only have implementations if it's an interface or a
            // method/property/event from an interface.
            if (symbol is INamedTypeSymbol)
            {
                var namedTypeSymbol   = (INamedTypeSymbol)symbol;
                var implementingTypes = await DependentTypeFinder.FindImplementingTypesAsync(namedTypeSymbol, solution, projects, cancellationToken).ConfigureAwait(false);

                return(implementingTypes.Where(IsAccessible));
            }
            else if (symbol.IsImplementableMember())
            {
                var containingType = symbol.ContainingType.OriginalDefinition;
                var allTypes       = await DependentTypeFinder.FindImplementingTypesAsync(containingType, solution, projects, cancellationToken).ConfigureAwait(false);

                List <ISymbol> results = null;
                foreach (var t in allTypes)
                {
                    foreach (var m in t.FindImplementationsForInterfaceMember(symbol, solution.Workspace, cancellationToken))
                    {
                        var s = await FindSourceDefinitionAsync(m, solution, cancellationToken).ConfigureAwait(false) ?? m;

                        if (IsAccessible(s))
                        {
                            results = results ?? new List <ISymbol>();
                            results.Add(s.OriginalDefinition);
                        }
                    }
                }

                if (results != null)
                {
                    return(results.Distinct(SymbolEquivalenceComparer.Instance));
                }
            }

            return(SpecializedCollections.EmptyEnumerable <ISymbol>());
        }
        /// <summary>
        /// Find symbols for members that override the specified member symbol.
        /// </summary>
        public static async Task <IEnumerable <ISymbol> > FindOverridesAsync(
            ISymbol symbol, Solution solution, IImmutableSet <Project> projects = null, CancellationToken cancellationToken = default(CancellationToken))
        {
            // Method can only have overrides if its a virtual, abstract or override and is not
            // sealed.
            if (symbol.IsOverridable())
            {
                // To find the overrides, we need to walk down the type hierarchy and check all
                // derived types.  TODO(cyrusn): This seems extremely costly.  Is there any way to
                // speed this up?
                var containingType = symbol.ContainingType.OriginalDefinition;
                var derivedTypes   = await FindDerivedClassesAsync(containingType, solution, projects, cancellationToken).ConfigureAwait(false);

                List <ISymbol> results = null;
                foreach (var type in derivedTypes)
                {
                    foreach (var m in type.GetMembers(symbol.Name))
                    {
                        var member = await FindSourceDefinitionAsync(m, solution, cancellationToken).ConfigureAwait(false) ?? m;

                        if (member != null &&
                            member.IsOverride &&
                            member.OverriddenMember() != null &&
                            DependentTypeFinder.OriginalSymbolsMatch(member.OverriddenMember().OriginalDefinition, symbol.OriginalDefinition, solution, cancellationToken))
                        {
                            results = results ?? new List <ISymbol>();
                            results.Add(member);
                        }
                    }
                }

                if (results != null)
                {
                    return(results);
                }
            }

            return(SpecializedCollections.EmptyEnumerable <ISymbol>());
        }