public static Task <IEnumerable <INamedTypeSymbol> > FindDerivedClassesAsync( this INamedTypeSymbol type, Solution solution, IImmutableSet <Project> projects, CancellationToken cancellationToken) { return(DependentTypeFinder.FindDerivedClassesAsync(type, solution, projects, cancellationToken)); }
public override async ValueTask <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 = await Task.WhenAll(symbol.ConstraintTypes.Select(async ct => { var derivedAndImplementedTypes = new List <INamedTypeSymbol>(); var derivedClasses = await SymbolFinder.FindDerivedClassesAsync((INamedTypeSymbol)ct, _solution, immutableProjects, _cancellationToken).ConfigureAwait(false); var implementedTypes = await DependentTypeFinder.FindTransitivelyImplementingStructuresAndClassesAsync((INamedTypeSymbol)ct, _solution, immutableProjects, _cancellationToken).ConfigureAwait(false); return(derivedClasses.Concat(implementedTypes.Select(s => s.Symbol)).ToList()); })).ConfigureAwait(false); 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 = await resultantIntersectingType.Accept(this).ConfigureAwait(false); 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> > FindAndCacheImplementingTypesAsync( PinnedSolutionInfo solutionInfo, SerializableSymbolAndProjectId typeAndProjectId, ProjectId[] projectIds, bool transitive, CancellationToken cancellationToken) { return(FindAndCacheTypesAsync( solutionInfo, typeAndProjectId, projectIds, (nt, s, ps) => DependentTypeFinder.FindAndCacheImplementingTypesAsync(nt, s, ps, transitive, cancellationToken), cancellationToken)); }
private async Task <ISet <INamedTypeSymbol> > GetDerivedAndImplementedTypesAsync( INamedTypeSymbol constraintType, IImmutableSet <Project> projects) { var solution = _project.Solution; var symbolAndProjectId = SymbolAndProjectId.Create(constraintType, _project.Id); var derivedClasses = await SymbolFinder.FindDerivedClassesAsync( symbolAndProjectId, solution, projects, _cancellationToken).ConfigureAwait(false); var implementedTypes = await DependentTypeFinder.FindTransitivelyImplementingStructuresAndClassesAsync( symbolAndProjectId, solution, projects, _cancellationToken).ConfigureAwait(false); return(derivedClasses.Concat(implementedTypes).Select(t => t.Symbol).ToSet()); }
public async Task ImmediatelyDerivedTypes_CSharp_AliasedNames() { var solution = new AdhocWorkspace().CurrentSolution; // create portable assembly with an abstract base class solution = AddProjectWithMetadataReferences(solution, "PortableProject", LanguageNames.CSharp, @" namespace N { public abstract class BaseClass { } } ", MscorlibRefPortable); var portableProject = GetPortableProject(solution); // create a normal assembly with a type derived from the portable abstract base solution = AddProjectWithMetadataReferences(solution, "NormalProject", LanguageNames.CSharp, @" using N; using Alias1 = N.BaseClass; namespace M { using Alias2 = Alias1; public class DerivedClass : Alias2 { } } ", MscorlibRef, portableProject.Id); // get symbols for types var portableCompilation = await GetPortableProject(solution).GetCompilationAsync(); var baseClassSymbol = portableCompilation.GetTypeByMetadataName("N.BaseClass"); var normalCompilation = await solution.Projects.Single(p => p.Name == "NormalProject").GetCompilationAsync(); var derivedClassSymbol = normalCompilation.GetTypeByMetadataName("M.DerivedClass"); // verify that the symbols are different (due to retargeting) Assert.NotEqual(baseClassSymbol, derivedClassSymbol.BaseType); // verify that the dependent types of `N.BaseClass` correctly resolve to `M.DerivedCLass` var derivedFromBase = await DependentTypeFinder.FindImmediatelyDerivedClassesAsync( SymbolAndProjectId.Create(baseClassSymbol, portableProject.Id), solution, CancellationToken.None); var derivedDependentType = derivedFromBase.Single(); Assert.Equal(derivedClassSymbol, derivedDependentType.Symbol); }
public async Task ImmediatelyDerivedTypes_VisualBasic() { var solution = new AdhocWorkspace().CurrentSolution; // create portable assembly with an abstract base class solution = AddProjectWithMetadataReferences(solution, "PortableProject", LanguageNames.VisualBasic, @" Namespace N Public MustInherit Class BaseClass End Class End Namespace ", MscorlibRefPortable); var portableProject = GetPortableProject(solution); // create a normal assembly with a type derived from the portable abstract base solution = AddProjectWithMetadataReferences(solution, "NormalProject", LanguageNames.VisualBasic, @" Imports N Namespace M Public Class DerivedClass Inherits BaseClass End Class End Namespace ", MscorlibRef, portableProject.Id); // get symbols for types var portableCompilation = await GetPortableProject(solution).GetCompilationAsync(); var baseClassSymbol = portableCompilation.GetTypeByMetadataName("N.BaseClass"); var normalCompilation = await solution.Projects.Single(p => p.Name == "NormalProject").GetCompilationAsync(); var derivedClassSymbol = normalCompilation.GetTypeByMetadataName("M.DerivedClass"); // verify that the symbols are different (due to retargeting) Assert.NotEqual(baseClassSymbol, derivedClassSymbol.BaseType); // verify that the dependent types of `N.BaseClass` correctly resolve to `M.DerivedCLass` var derivedFromBase = await DependentTypeFinder.FindImmediatelyDerivedClassesAsync( baseClassSymbol, solution, CancellationToken.None); var derivedDependentType = derivedFromBase.Single(); Assert.Equal(derivedClassSymbol, derivedDependentType); }
public async Task ImmediatelyDerivedInterfaces_VisualBasic() { var solution = new AdhocWorkspace().CurrentSolution; // create portable assembly with an interface solution = AddProjectWithMetadataReferences(solution, "PortableProject", LanguageNames.VisualBasic, @" Namespace N Public Interface IBaseInterface End Interface End Namespace ", MscorlibRefPortable); var portableProject = GetPortableProject(solution); // create a normal assembly with a type implementing that interface solution = AddProjectWithMetadataReferences(solution, "NormalProject", LanguageNames.VisualBasic, @" Imports N Namespace M Public Class ImplementingClass Implements IBaseInterface End Class End Namespace ", MscorlibRef, portableProject.Id); // get symbols for types var portableCompilation = await GetPortableProject(solution).GetCompilationAsync(); var baseInterfaceSymbol = portableCompilation.GetTypeByMetadataName("N.IBaseInterface"); var normalCompilation = await solution.Projects.Single(p => p.Name == "NormalProject").GetCompilationAsync(); var implementingClassSymbol = normalCompilation.GetTypeByMetadataName("M.ImplementingClass"); // verify that the symbols are different (due to retargeting) Assert.NotEqual(baseInterfaceSymbol, implementingClassSymbol.Interfaces.Single()); // verify that the implementing types of `N.IBaseInterface` correctly resolve to `M.ImplementingClass` var typesThatImplementInterface = await DependentTypeFinder.FindImmediatelyDerivedAndImplementingTypesAsync( SymbolAndProjectId.Create(baseInterfaceSymbol, portableProject.Id), solution, CancellationToken.None); Assert.Equal(implementingClassSymbol, typesThatImplementInterface.Single().Symbol); }
public async Task <GraphBuilder> GetGraphAsync(Solution solution, IGraphContext context, CancellationToken cancellationToken) { var graphBuilder = await GraphBuilder.CreateForInputNodesAsync(solution, context.InputNodes, cancellationToken).ConfigureAwait(false); foreach (var node in context.InputNodes) { var symbol = graphBuilder.GetSymbol(node); if (!(symbol is INamedTypeSymbol namedType)) { continue; } if (namedType.TypeKind == TypeKind.Class) { var derivedTypes = await DependentTypeFinder.FindImmediatelyDerivedClassesAsync( namedType, solution, cancellationToken).ConfigureAwait(false); foreach (var derivedType in derivedTypes) { var symbolNode = await graphBuilder.AddNodeAsync( derivedType, relatedNode : node).ConfigureAwait(false); graphBuilder.AddLink(symbolNode, CodeLinkCategories.InheritsFrom, node); } } else if (namedType.TypeKind == TypeKind.Interface) { var derivedTypes = await DependentTypeFinder.FindImmediatelyDerivedAndImplementingTypesAsync( namedType, solution, cancellationToken).ConfigureAwait(false); foreach (var derivedType in derivedTypes) { var symbolNode = await graphBuilder.AddNodeAsync( derivedType, relatedNode : node).ConfigureAwait(false); graphBuilder.AddLink(symbolNode, CodeLinkCategories.InheritsFrom, node); } } } return(graphBuilder); }
public async Task ImmediatelyDerivedInterfaces_CSharp() { var solution = new AdhocWorkspace().CurrentSolution; // create portable assembly with an interface solution = AddProjectWithMetadataReferences(solution, "PortableProject", LanguageNames.CSharp, @" namespace N { public interface IBaseInterface { } } ", MscorlibRefPortable); // create a normal assembly with a type implementing that interface solution = AddProjectWithMetadataReferences(solution, "NormalProject", LanguageNames.CSharp, @" using N; namespace M { public class ImplementingClass : IBaseInterface { } } ", MscorlibRef, solution.Projects.Single(pid => pid.Name == "PortableProject").Id); // get symbols for types var portableCompilation = await solution.Projects.Single(p => p.Name == "PortableProject").GetCompilationAsync(); var baseInterfaceSymbol = portableCompilation.GetTypeByMetadataName("N.IBaseInterface"); var normalCompilation = await solution.Projects.Single(p => p.Name == "NormalProject").GetCompilationAsync(); var implementingClassSymbol = normalCompilation.GetTypeByMetadataName("M.ImplementingClass"); // verify that the symbols are different (due to retargeting) Assert.NotEqual(baseInterfaceSymbol, implementingClassSymbol.Interfaces.Single()); // verify that the implementing types of `N.IBaseInterface` correctly resolve to `M.ImplementingClass` var typesThatImplementInterface = await DependentTypeFinder.FindImmediatelyDerivedAndImplementingTypesAsync( baseInterfaceSymbol, solution, CancellationToken.None); Assert.Equal(implementingClassSymbol, typesThatImplementInterface.Single().Symbol); }