Exemple #1
0
 /// <summary>
 /// Gets whether access to protected instance members of the target expression is possible.
 /// </summary>
 public bool IsProtectedAccessAllowed(AST.Expression targetResolveResult)
 {
     return(targetResolveResult is SelfReference || IsProtectedAccessAllowed(targetResolveResult.Type));
 }
Exemple #2
0
        /// <summary>
        /// Performs a member lookup.
        /// </summary>
        public AST.Expression Lookup(AST.Expression targetResolveResult, string name, IList <IType> typeArguments, bool isInvocation)
        {
            if (targetResolveResult == null)
            {
                throw new ArgumentNullException("targetResolveResult");
            }
            if (name == null)
            {
                throw new ArgumentNullException("name");
            }
            if (typeArguments == null)
            {
                throw new ArgumentNullException("typeArguments");
            }

            bool targetIsTypeParameter = targetResolveResult.Type.Kind == TypeKind.TypeParameter;

            bool allowProtectedAccess = IsProtectedAccessAllowed(targetResolveResult);
            Predicate <ITypeDefinition> nestedTypeFilter = delegate(ITypeDefinition entity)
            {
                return(entity.Name == name && IsAccessible(entity, allowProtectedAccess));
            };
            Predicate <IUnresolvedMember> memberFilter = delegate(IUnresolvedMember entity)
            {
                // NOTE: Atm destructors can be looked up with 'Finalize'
                return(entity.SymbolKind != SymbolKind.Indexer &&
                       entity.SymbolKind != SymbolKind.Operator &&
                       entity.Name == name);
            };

            List <LookupGroup> lookupGroups = new List <LookupGroup>();

            // This loop will handle base types before derived types.
            // The loop performs three jobs:
            // 1) It marks entries in lookup groups from base classes as removed when those members
            //    are hidden by a derived class.
            // 2) It adds a new lookup group with the members from a declaring type.
            // 3) It replaces virtual members with the overridden version, placing the override in the
            //    lookup group belonging to the base class.
            foreach (IType type in targetResolveResult.Type.GetNonInterfaceBaseTypes())
            {
                List <IType> newNestedTypes            = null;
                List <IParameterizedMember> newMethods = null;
                IMember newNonMethod = null;

                IEnumerable <IType> typeBaseTypes = null;

                if (!isInvocation && !targetIsTypeParameter)
                {
                    // Consider nested types only if it's not an invocation.
                    // type.GetNestedTypes() is checking the type parameter count for an exact match,
                    // so we don't need to do that in our filter.
                    var nestedTypes = type.GetNestedTypes(typeArguments, nestedTypeFilter, GetMemberOptions.IgnoreInheritedMembers);
                    AddNestedTypes(type, nestedTypes, typeArguments.Count, lookupGroups, ref typeBaseTypes, ref newNestedTypes);
                }

                IEnumerable <IMember> members;
                if (typeArguments.Count == 0)
                {
                    // Note: IsInvocable-checking cannot be done as part of the filter;
                    // because it must be done after type substitution.
                    members = type.GetMembers(memberFilter, GetMemberOptions.IgnoreInheritedMembers);
                    if (isInvocation)
                    {
                        members = members.Where(m => IsInvocable(m));
                    }
                }
                else
                {
                    // No need to check for isInvocation/isInvocable here:
                    // we only fetch methods
                    members = type.GetMethods(typeArguments, memberFilter, GetMemberOptions.IgnoreInheritedMembers);
                }
                AddMembers(type, members, allowProtectedAccess, lookupGroups, false, ref typeBaseTypes, ref newMethods, ref newNonMethod);

                if (newNestedTypes != null || newMethods != null || newNonMethod != null)
                {
                    lookupGroups.Add(new LookupGroup(type, newNestedTypes, newMethods, newNonMethod));
                }
            }

            // Remove interface members hidden by class members.
            if (targetIsTypeParameter)
            {
                // This can happen only with type parameters.
                RemoveInterfaceMembersHiddenByClassMembers(lookupGroups);
            }

            return(CreateResult(targetResolveResult, lookupGroups, name, typeArguments));
        }