/// <summary> /// Finds all members defined or referenced in <paramref name="project"/> which may have a parameter that is of or derived from <paramref name="type"/>. /// </summary> public static async Task <List <ISymbol> > FindInstanceAsParameterAsync(this ITypeSymbol type, Project project, CancellationToken cancellationToken = default) { var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false); var members = new List <ISymbol>(10); ImmutableArray <IParameterSymbol> parameters; var assembly = compilation.Assembly; foreach (var typeSymbol in compilation.GlobalNamespace.GetAllTypes(cancellationToken)) { foreach (var member in typeSymbol.GetMembers()) { if (cancellationToken.IsCancellationRequested) { return(members); } if (member.Kind != SymbolKind.Field && member.CanBeReferencedByName && (parameters = member.GetParameters()).IsDefaultOrEmpty == false) { if (parameters.Any(p => type.CanConvertTo(p.Type) && p.Type.IsCommonClass() == false) && type.CanAccess(member, assembly)) { members.Add(member); } } } } return(members); }
/// <summary> /// Finds all members defined or referenced in <paramref name="project"/> which may return an instance of <paramref name="type"/>. /// </summary> public static async Task <List <ISymbol> > FindSymbolInstanceProducerAsync(this ITypeSymbol type, Project project, bool strict, CancellationToken cancellationToken = default) { var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false); var assembly = compilation.Assembly; var members = new List <ISymbol>(10); var paramComparer = strict ? (Func <IParameterSymbol, bool>)(p => p.Type == type && p.RefKind != RefKind.None) : (p => p.Type.CanConvertTo(type) && p.RefKind != RefKind.None); foreach (var typeSymbol in compilation.GlobalNamespace.GetAllTypes(cancellationToken)) { foreach (var member in typeSymbol.GetMembers()) { if (cancellationToken.IsCancellationRequested) { return(members); } ITypeSymbol mt; if (member.Kind == SymbolKind.Field) { if (member.CanBeReferencedByName && (mt = member.GetReturnType()) != null && (mt == type || strict == false && mt.CanConvertTo(type) || (mt as INamedTypeSymbol).ContainsTypeArgument(type)) && type.CanAccess(member, assembly)) { members.Add(member); } } else if (member.CanBeReferencedByName && ((mt = member.GetReturnType()) != null && (mt == type || strict == false && mt.CanConvertTo(type) || (mt as INamedTypeSymbol).ContainsTypeArgument(type)) || member.Kind == SymbolKind.Method && member.GetParameters().Any(paramComparer)) && type.CanAccess(member, assembly)) { members.Add(member); } } } return(members); }
/// <summary> /// Finds all members defined or referenced in <paramref name="project"/> which may return an instance of <paramref name="type"/>. /// </summary> public static List <ISymbol> FindSymbolInstanceProducer(this ITypeSymbol type, Project project, CancellationToken cancellationToken = default(CancellationToken)) { var compilation = project.GetCompilationAsync(cancellationToken).Result; var assembly = compilation.Assembly; //todo cache types var members = new List <ISymbol>(10); foreach (var typeSymbol in compilation.GlobalNamespace.GetAllTypes(cancellationToken)) { foreach (var member in typeSymbol.GetMembers()) { ITypeSymbol mt; if (member.Kind != SymbolKind.Field && member.CanBeReferencedByName && ((mt = member.GetReturnType()) != null && mt.CanConvertTo(type) || member.Kind == SymbolKind.Method && member.GetParameters().Any(p => p.Type.CanConvertTo(type) && p.RefKind != RefKind.None)) && type.CanAccess(member, assembly)) { members.Add(member); } } } return(members); }
/// <summary> /// Returns whether a given type <paramref name="from"/> can access symbol <paramref name="target"/>. /// </summary> public static bool CanAccess(this ITypeSymbol from, ISymbol target, IAssemblySymbol assembly) { if (target == null) { return(false); } switch (target.DeclaredAccessibility) { case Accessibility.Public: return(true && (target.ContainingType == null || from.CanAccess(target.ContainingType, assembly))); case Accessibility.Private: return(target.ContainingType.Equals(from) || target.FirstSourceLocation() != null); case Accessibility.Internal: return(target.ContainingAssembly.GivesAccessTo(assembly) && (target.ContainingType == null || from.CanAccess(target.ContainingType, assembly))); case Accessibility.ProtectedOrInternal: if (target.ContainingAssembly.GivesAccessTo(assembly)) { return(true); } goto case Accessibility.Protected; case Accessibility.Protected: target = target.ContainingType; if (target.ContainingType != null && from.CanAccess(target.ContainingType, assembly) == false) { return(false); } do { if (from.Equals(target)) { return(true); } } while ((from = from.BaseType) != null); return(false); case Accessibility.ProtectedAndInternal: if (target.ContainingAssembly.GivesAccessTo(assembly)) { target = target.ContainingType; if (target.ContainingType != null && from.CanAccess(target.ContainingType, null) == false) { return(false); } do { if (from.Equals(target)) { return(true); } } while ((from = from.BaseType) != null); return(false); } return(false); } return(false); }