Ejemplo n.º 1
0
        /// <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);
        }
Ejemplo n.º 2
0
        /// <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);
        }
Ejemplo n.º 3
0
        /// <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);
        }
Ejemplo n.º 4
0
        /// <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);
        }