Exemplo n.º 1
0
 public static Task <IEnumerable <INamedTypeSymbol> > FindImplementingTypesAsync(
     this INamedTypeSymbol type,
     Solution solution,
     IImmutableSet <Project> projects,
     CancellationToken cancellationToken)
 {
     return(DependentTypeFinder.FindImplementingTypesAsync(type, solution, projects, cancellationToken));
 }
            public override ITypeSymbol VisitTypeParameter(ITypeParameterSymbol symbol)
            {
                if (_availableTypeParameterNames.Contains(symbol.Name))
                {
                    return(symbol);
                }

                switch (symbol.ConstraintTypes.Length)
                {
                case 0:
                    // If there are no constraint then there is no replacement required
                    // Just return the symbol
                    return(symbol);

                case 1:
                    // If there is one constraint which is a INamedTypeSymbol then return the INamedTypeSymbol
                    // because the TypeParameter is expected to be of that type
                    // else return the original symbol
                    return(symbol.ConstraintTypes.ElementAt(0) as INamedTypeSymbol ?? (ITypeSymbol)symbol);

                // More than one
                default:
                    if (symbol.ConstraintTypes.All(t => t is INamedTypeSymbol))
                    {
                        var immutableProjects = _solution.Projects.ToImmutableHashSet();
                        var derivedImplementedTypesOfEachConstraintType = symbol.ConstraintTypes.Select(ct =>
                        {
                            var derivedAndImplementedTypes = new List <INamedTypeSymbol>();
                            return(SymbolFinder.FindDerivedClassesAsync((INamedTypeSymbol)ct, _solution, immutableProjects, _cancellationToken).WaitAndGetResult(_cancellationToken)
                                   .Concat(DependentTypeFinder.FindImplementingTypesAsync((INamedTypeSymbol)ct, _solution, immutableProjects, _cancellationToken).WaitAndGetResult(_cancellationToken))
                                   .ToList());
                        });

                        var intersectingTypes = derivedImplementedTypesOfEachConstraintType.Aggregate((x, y) => x.Intersect(y).ToList());

                        // If there was any intersecting derived type among the constraint types then pick the first of the lot.
                        if (intersectingTypes.Any())
                        {
                            var resultantIntersectingType = intersectingTypes.First();

                            // If the resultant intersecting type contains any Type arguments that could be replaced
                            // using the type constraints then recursively update the type until all constraints are appropriately handled
                            var typeConstraintConvertedType    = resultantIntersectingType.Accept(this);
                            var knownSimilarTypesInCompilation = SymbolFinder.FindSimilarSymbols(typeConstraintConvertedType, _compilation, _cancellationToken);
                            if (knownSimilarTypesInCompilation.Any())
                            {
                                return(knownSimilarTypesInCompilation.First());
                            }

                            var resultantSimilarKnownTypes = SymbolFinder.FindSimilarSymbols(resultantIntersectingType, _compilation, _cancellationToken);
                            return(resultantSimilarKnownTypes.FirstOrDefault() ?? (ITypeSymbol)symbol);
                        }
                    }

                    return(symbol);
                }
            }
 public Task <ImmutableArray <SerializableSymbolAndProjectId> > FindImplementingTypesAsync(
     PinnedSolutionInfo solutionInfo,
     SerializableSymbolAndProjectId typeAndProjectId,
     ProjectId[] projectIds,
     bool transitive,
     CancellationToken cancellationToken)
 {
     return(FindTypesAsync(
                solutionInfo, typeAndProjectId, projectIds,
                (nt, s, ps) => DependentTypeFinder.FindImplementingTypesAsync(nt, s, ps, transitive, cancellationToken),
                cancellationToken));
 }