Пример #1
0
        /// <summary>
        /// Adds all candidates from the method lists.
        ///
        /// This method implements the logic that causes applicable methods in derived types to hide
        /// all methods in base types.
        /// </summary>
        /// <param name="methodLists">The methods, grouped by declaring type. Base types must come first in the list.</param>
        public void AddMethodLists(IReadOnlyList <MethodListWithDeclaringType> methodLists)
        {
            if (methodLists == null)
            {
                throw new ArgumentNullException("methodLists");
            }
            // Base types come first, so go through the list backwards (derived types first)
            bool[] isHiddenByDerivedType;
            if (methodLists.Count > 1)
            {
                isHiddenByDerivedType = new bool[methodLists.Count];
            }
            else
            {
                isHiddenByDerivedType = null;
            }
            for (int i = methodLists.Count - 1; i >= 0; i--)
            {
                if (isHiddenByDerivedType != null && isHiddenByDerivedType[i])
                {
                    Log.WriteLine("  Skipping methods in {0} because they are hidden by an applicable method in a derived type", methodLists[i].DeclaringType);
                    continue;
                }

                MethodListWithDeclaringType methodList     = methodLists[i];
                bool foundApplicableCandidateInCurrentList = false;

                for (int j = 0; j < methodList.Count; j++)
                {
                    IParameterizedMember method = methodList[j];
                    Log.Indent();
                    OverloadResolutionErrors errors = AddCandidate(method);
                    Log.Unindent();
                    LogCandidateAddingResult("  Candidate", method, errors);

                    foundApplicableCandidateInCurrentList |= IsApplicable(errors);
                }

                if (foundApplicableCandidateInCurrentList && i > 0)
                {
                    foreach (IType baseType in methodList.DeclaringType.GetAllBaseTypes())
                    {
                        for (int j = 0; j < i; j++)
                        {
                            if (!isHiddenByDerivedType[j] && baseType.Equals(methodLists[j].DeclaringType))
                            {
                                isHiddenByDerivedType[j] = true;
                            }
                        }
                    }
                }
            }
        }
Пример #2
0
        /// <summary>
        /// Looks up the indexers on the target type.
        /// </summary>
        public IReadOnlyList <MethodListWithDeclaringType> LookupIndexers(ResolveResult targetResolveResult)
        {
            if (targetResolveResult == null)
            {
                throw new ArgumentNullException(nameof(targetResolveResult));
            }

            IType targetType             = targetResolveResult.Type;
            bool  allowProtectedAccess   = IsProtectedAccessAllowed(targetResolveResult);
            Predicate <IProperty> filter = p => p.IsIndexer && !p.IsExplicitInterfaceImplementation;

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

            foreach (IType type in targetType.GetNonInterfaceBaseTypes())
            {
                List <IParameterizedMember> newMethods = null;
                IMember newNonMethod = null;

                IEnumerable <IType> typeBaseTypes = null;

                var members = type.GetProperties(filter, GetMemberOptions.IgnoreInheritedMembers);
                AddMembers(type, members, allowProtectedAccess, lookupGroups, true, ref typeBaseTypes, ref newMethods, ref newNonMethod);

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

            // Remove interface members hidden by class members.
            if (targetType.Kind == TypeKind.TypeParameter)
            {
                // This can happen only with type parameters.
                RemoveInterfaceMembersHiddenByClassMembers(lookupGroups);
            }

            // Remove all hidden groups
            lookupGroups.RemoveAll(g => g.MethodsAreHidden || g.Methods.Count == 0);

            MethodListWithDeclaringType[] methodLists = new MethodListWithDeclaringType[lookupGroups.Count];
            for (int i = 0; i < methodLists.Length; i++)
            {
                methodLists[i] = new MethodListWithDeclaringType(lookupGroups[i].DeclaringType, lookupGroups[i].Methods);
            }
            return(methodLists);
        }
Пример #3
0
        ResolveResult CreateResult(ResolveResult targetResolveResult, List <LookupGroup> lookupGroups, string name, IReadOnlyList <IType> typeArguments)
        {
            // Remove all hidden groups
            lookupGroups.RemoveAll(g => g.AllHidden);

            if (lookupGroups.Count == 0)
            {
                // No members found
                return(new UnknownMemberResolveResult(targetResolveResult.Type, name, typeArguments));
            }

            if (lookupGroups.Any(g => !g.MethodsAreHidden && g.Methods.Count > 0))
            {
                // If there are methods, make a MethodGroupResolveResult.
                // Note that a conflict between a member and a method (possible with multiple interface inheritance)
                // is only a warning, not an error, and the C# compiler will prefer the method group.
                List <MethodListWithDeclaringType> methodLists = new List <MethodListWithDeclaringType>();
                foreach (var lookupGroup in lookupGroups)
                {
                    if (!lookupGroup.MethodsAreHidden && lookupGroup.Methods.Count > 0)
                    {
                        var methodListWithDeclType = new MethodListWithDeclaringType(lookupGroup.DeclaringType);
                        foreach (var method in lookupGroup.Methods)
                        {
                            methodListWithDeclType.Add((IMethod)method);
                        }
                        methodLists.Add(methodListWithDeclType);
                    }
                }

                return(new MethodGroupResolveResult(targetResolveResult, name, methodLists, typeArguments));
            }

            // If there are ambiguities, report the most-derived result (last group)
            LookupGroup resultGroup = lookupGroups[lookupGroups.Count - 1];

            if (resultGroup.NestedTypes != null && resultGroup.NestedTypes.Count > 0)
            {
                if (resultGroup.NestedTypes.Count > 1 || !resultGroup.NonMethodIsHidden || lookupGroups.Count > 1)
                {
                    return(new AmbiguousTypeResolveResult(resultGroup.NestedTypes[0]));
                }
                else
                {
                    return(new TypeResolveResult(resultGroup.NestedTypes[0]));
                }
            }

            if (resultGroup.NonMethod.IsStatic && targetResolveResult is ThisResolveResult)
            {
                targetResolveResult = new TypeResolveResult(targetResolveResult.Type);
            }

            if (lookupGroups.Count > 1)
            {
                return(new AmbiguousMemberResolveResult(targetResolveResult, resultGroup.NonMethod));
            }
            else
            {
                if (isInEnumMemberInitializer)
                {
                    IField field = resultGroup.NonMethod as IField;
                    if (field != null && field.DeclaringTypeDefinition != null && field.DeclaringTypeDefinition.Kind == TypeKind.Enum)
                    {
                        return(new MemberResolveResult(
                                   targetResolveResult, field,
                                   field.DeclaringTypeDefinition.EnumUnderlyingType,
                                   field.IsConst, field.GetConstantValue()));
                    }
                }
                return(new MemberResolveResult(targetResolveResult, resultGroup.NonMethod));
            }
        }