Пример #1
0
        private static bool MatchesFilter(ISymbol candidate, Name name, BindingFlags flags, Types types)
        {
            if (candidate.MetadataName != name.MetadataName)
            {
                if (candidate.MetadataName != ".cctor" ||
                    name.MetadataName != Name.Ctor.MetadataName)
                {
                    return(false);
                }
            }

            if (candidate is IFieldSymbol field &&
                field.CorrespondingTupleField is IFieldSymbol tupleField &&
                tupleField.Name != field.Name)
            {
                return(false);
            }

            if (candidate.DeclaredAccessibility == Accessibility.Public &&
                !flags.HasFlagFast(BindingFlags.Public))
            {
                return(false);
            }

            if (candidate.DeclaredAccessibility != Accessibility.Public &&
                !flags.HasFlagFast(BindingFlags.NonPublic))
            {
                return(false);
            }

            if (!(candidate is ITypeSymbol))
            {
                if (candidate.IsStatic &&
                    !flags.HasFlagFast(BindingFlags.Static))
                {
                    return(false);
                }

                if (!candidate.IsStatic &&
                    !flags.HasFlagFast(BindingFlags.Instance))
                {
                    return(false);
                }
            }

            if (types.Argument != null)
            {
                switch (candidate)
                {
                case IMethodSymbol method when !types.Matches(method.Parameters):
                    return(false);
                }
            }

            return(true);
        }
Пример #2
0
        internal static bool HasVisibleMembers(ITypeSymbol type, BindingFlags flags)
        {
            if (!flags.HasFlagFast(BindingFlags.NonPublic))
            {
                return(true);
            }

            if (flags.HasFlagFast(BindingFlags.DeclaredOnly))
            {
                return(HasVisibleNonPublicMembers(type, recursive: false));
            }

            if (!flags.HasFlagFast(BindingFlags.Instance) &&
                !flags.HasFlagFast(BindingFlags.FlattenHierarchy))
            {
                return(HasVisibleNonPublicMembers(type, recursive: false));
            }

            return(HasVisibleNonPublicMembers(type, recursive: true));
        }
Пример #3
0
        internal static string ToDisplayString(this BindingFlags flags, SyntaxNode?location)
        {
            var usingStatic = IsUsingStatic(location);
            var builder     = StringBuilderPool.Borrow();

            //// below is in specific order.
            AppendIf(BindingFlags.Public);
            AppendIf(BindingFlags.NonPublic);
            AppendIf(BindingFlags.Static);
            AppendIf(BindingFlags.Instance);
            AppendIf(BindingFlags.DeclaredOnly);
            AppendIf(BindingFlags.FlattenHierarchy);

            // below is in no specific order
            AppendIf(BindingFlags.CreateInstance);
            AppendIf(BindingFlags.Default);
            AppendIf(BindingFlags.ExactBinding);
            AppendIf(BindingFlags.GetField);
            AppendIf(BindingFlags.GetProperty);
            AppendIf(BindingFlags.IgnoreCase);
            AppendIf(BindingFlags.InvokeMethod);
            AppendIf(BindingFlags.IgnoreReturn);
            AppendIf(BindingFlags.OptionalParamBinding);
            AppendIf(BindingFlags.PutDispProperty);
            AppendIf(BindingFlags.PutRefDispProperty);
            AppendIf(BindingFlags.SetField);
            AppendIf(BindingFlags.SetProperty);
            AppendIf(BindingFlags.SuppressChangeType);
            AppendIf(BindingFlags.DoNotWrapExceptions);

            return(builder.Return());

            void AppendIf(BindingFlags flag)
            {
                if (flags.HasFlagFast(flag))
                {
                    if (builder.Length != 0)
                    {
                        _ = builder.Append(" | ");
                    }

                    if (!usingStatic)
                    {
                        _ = builder.Append("BindingFlags.");
                    }

                    _ = builder.Append(flag.Name());
                }
            }
        }
Пример #4
0
        private static FilterMatch TryGetMember(IMethodSymbol getX, ITypeSymbol type, Name name, BindingFlags flags, Types types, SyntaxNodeAnalysisContext context, out ISymbol member)
        {
            member = null;
            if (type is ITypeParameterSymbol typeParameter)
            {
                if (typeParameter.ConstraintTypes.Length == 0)
                {
                    return(TryGetMember(getX, context.Compilation.GetSpecialType(SpecialType.System_Object), name, flags, types, context, out member));
                }

                foreach (var constraintType in typeParameter.ConstraintTypes)
                {
                    var result = TryGetMember(getX, constraintType, name, flags, types, context, out member);
                    if (result != FilterMatch.NoMatch)
                    {
                        return(result);
                    }
                }

                return(TryGetMember(getX, context.Compilation.GetSpecialType(SpecialType.System_Object), name, flags, types, context, out member));
            }

            var isAmbiguous = false;

            if (getX == KnownSymbol.Type.GetNestedType ||
                getX == KnownSymbol.Type.GetConstructor ||
                flags.HasFlagFast(BindingFlags.DeclaredOnly) ||
                (flags.HasFlagFast(BindingFlags.Static) &&
                 !flags.HasFlagFast(BindingFlags.Instance) &&
                 !flags.HasFlagFast(BindingFlags.FlattenHierarchy)))
            {
                foreach (var candidate in type.GetMembers())
                {
                    if (!MatchesFilter(candidate, name, flags, types))
                    {
                        continue;
                    }

                    if (types.TryMostSpecific(member, candidate, out member))
                    {
                        isAmbiguous = false;
                        if (IsWrongMemberType(member))
                        {
                            return(FilterMatch.WrongMemberType);
                        }
                    }
                    else
                    {
                        isAmbiguous = true;
                    }
                }
            }
            else
            {
                var current = type;
                while (current != null)
                {
                    foreach (var candidate in current.GetMembers())
                    {
                        if (!MatchesFilter(candidate, name, flags, types))
                        {
                            continue;
                        }

                        if (IsOverriding(member, candidate))
                        {
                            continue;
                        }

                        if (types.TryMostSpecific(member, candidate, out member))
                        {
                            isAmbiguous = false;
                            if (IsUseContainingType(member))
                            {
                                return(FilterMatch.UseContainingType);
                            }

                            if (candidate.IsStatic &&
                                !current.Equals(type) &&
                                !flags.HasFlagFast(BindingFlags.FlattenHierarchy))
                            {
                                return(FilterMatch.WrongFlags);
                            }

                            if (IsWrongMemberType(candidate))
                            {
                                return(FilterMatch.WrongMemberType);
                            }
                        }
                        else
                        {
                            isAmbiguous = true;
                        }
                    }

                    current = current.BaseType;
                }
            }

            if (isAmbiguous)
            {
                return(FilterMatch.Ambiguous);
            }

            if (member != null)
            {
                return(FilterMatch.Single);
            }

            if (type == KnownSymbol.Delegate &&
                name.MetadataName == "Invoke")
            {
                return(FilterMatch.Single);
            }

            if (type.TryFindFirstMemberRecursive(x => MatchesFilter(x, name, Flags.MatchAll.Effective, Types.Any), out member))
            {
                if (IsUseContainingType(member))
                {
                    return(FilterMatch.UseContainingType);
                }

                if (!Type.HasVisibleMembers(type, flags))
                {
                    return(FilterMatch.PotentiallyInvisible);
                }

                if (IsWrongFlags(member))
                {
                    return(FilterMatch.WrongFlags);
                }

                if (IsWrongTypes(member))
                {
                    return(FilterMatch.WrongTypes);
                }
            }

            if (!Type.HasVisibleMembers(type, flags))
            {
                // Assigning member if it is explicit. Useful info but we can't be sure still.
                _ = IsExplicitImplementation(out member);
                return(FilterMatch.PotentiallyInvisible);
            }

            if (IsExplicitImplementation(out member))
            {
                return(FilterMatch.ExplicitImplementation);
            }

            return(FilterMatch.NoMatch);

            bool IsWrongMemberType(ISymbol symbol)
            {
                if (getX.ReturnType == KnownSymbol.EventInfo &&
                    !(symbol is IEventSymbol))
                {
                    return(true);
                }

                if (getX.ReturnType == KnownSymbol.FieldInfo &&
                    !(symbol is IFieldSymbol))
                {
                    return(true);
                }

                if (getX.ReturnType == KnownSymbol.MethodInfo &&
                    !(symbol is IMethodSymbol))
                {
                    return(true);
                }

                if (getX.ReturnType == KnownSymbol.PropertyInfo &&
                    !(symbol is IPropertySymbol))
                {
                    return(true);
                }

                if (getX.ReturnType == KnownSymbol.Type &&
                    !(symbol is ITypeSymbol))
                {
                    return(true);
                }

                return(false);
            }

            bool IsOverriding(ISymbol symbol, ISymbol candidateBase)
            {
                if (symbol == null)
                {
                    return(false);
                }

                if (symbol.IsOverride)
                {
                    switch (symbol)
                    {
                    case IEventSymbol eventSymbol:
                        return(Equals(eventSymbol.OverriddenEvent, candidateBase) ||
                               IsOverriding(eventSymbol.OverriddenEvent, candidateBase));

                    case IMethodSymbol method:
                        return(Equals(method.OverriddenMethod, candidateBase) ||
                               IsOverriding(method.OverriddenMethod, candidateBase));

                    case IPropertySymbol property:
                        return(Equals(property.OverriddenProperty, candidateBase) ||
                               IsOverriding(property.OverriddenProperty, candidateBase));
                    }
                }

                return(false);
            }

            bool IsUseContainingType(ISymbol symbol)
            {
                if (type.Equals(symbol.ContainingType))
                {
                    return(false);
                }

                return(getX == KnownSymbol.Type.GetNestedType ||
                       symbol.DeclaredAccessibility == Accessibility.Private);
            }

            bool IsWrongFlags(ISymbol symbol)
            {
                if (symbol.MetadataName == name.MetadataName &&
                    !MatchesFilter(symbol, name, flags, Types.Any))
                {
                    return(true);
                }

                if (!symbol.ContainingType.Equals(type) &&
                    (symbol.IsStatic ||
                     flags.HasFlagFast(BindingFlags.DeclaredOnly)))
                {
                    return(true);
                }

                return(false);
            }

            bool IsWrongTypes(ISymbol symbol)
            {
                if (types.Argument == null)
                {
                    return(false);
                }

                const BindingFlags everything = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance | BindingFlags.FlattenHierarchy;

                return(symbol.MetadataName == name.MetadataName &&
                       !MatchesFilter(symbol, name, everything, types));
            }

            bool IsExplicitImplementation(out ISymbol result)
            {
                foreach (var @interface in type.AllInterfaces)
                {
                    if (@interface.TryFindFirstMember(x => MatchesFilter(x, name, Flags.MatchAll.Effective, types), out result))
                    {
                        return(true);
                    }
                }

                result = null;
                return(false);
            }
        }