Example #1
0
        /// <summary>
        /// Looks up the indexers on the target type.
        /// </summary>
        public IList <MethodListWithDeclaringType> LookupIndexers(IType targetType)
        {
            if (targetType == null)
            {
                throw new ArgumentNullException("targetType");
            }

            bool allowProtectedAccess = IsProtectedAccessAllowed(targetType);
            Predicate <IUnresolvedProperty> filter = p => p.IsIndexer;

            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);
        }
		/// <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(IList<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;
						}
					}
				}
			}
		}
Example #3
0
        ResolveResult CreateResult(ResolveResult targetResolveResult, List <LookupGroup> lookupGroups, string name, IList <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.ConstantValue));
                    }
                }
                return(new MemberResolveResult(targetResolveResult, resultGroup.NonMethod));
            }
        }