Example #1
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 (lookupGroups.Count > 1)
            {
                return(new AmbiguousMemberResolveResult(targetResolveResult, resultGroup.NonMethod,
                                                        resultGroup.NonMethod.ReturnType.Resolve(context)));
            }
            else
            {
                return(new MemberResolveResult(targetResolveResult, resultGroup.NonMethod, context));
            }
        }
Example #2
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(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
        /// <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 <IProperty> filter = delegate(IProperty property) {
                return(property.IsIndexer && IsAccessible(property, allowProtectedAccess));
            };

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

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

                IEnumerable <IType> typeBaseTypes = null;

                var members = type.GetProperties(context, filter, GetMemberOptions.IgnoreInheritedMembers);
                AddMembers(type, members, 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);
        }
Example #4
0
        public void CannotInferFromMethodParameterTypes()
        {
            // static void M<A, B>(Func<A, B> f) {}
            // M(int.Parse); // type inference fails
            var A = new DefaultTypeParameter(compilation, EntityType.Method, 0, "A");
            var B = new DefaultTypeParameter(compilation, EntityType.Method, 1, "B");

            IType declType = compilation.FindType(typeof(int));
            var   methods  = new MethodListWithDeclaringType(declType, declType.GetMethods(m => m.Name == "Parse"));
            var   argument = new MethodGroupResolveResult(new TypeResolveResult(declType), "Parse", new[] { methods }, new IType[0]);

            bool success;

            ti.InferTypeArguments(new [] { A, B }, new [] { argument },
                                  new [] { new ParameterizedType(compilation.FindType(typeof(Func <,>)).GetDefinition(), new[] { A, B }) },
                                  out success);
            Assert.IsFalse(success);
        }
Example #5
0
        public void InferFromMethodReturnType()
        {
            // static void M<T>(Func<T> f) {}
            // M(Console.ReadKey); // type inference produces ConsoleKeyInfo

            var T = new DefaultTypeParameter(compilation, EntityType.Method, 0, "T");

            IType declType = compilation.FindType(typeof(Console));
            var   methods  = new MethodListWithDeclaringType(declType, declType.GetMethods(m => m.Name == "ReadKey"));
            var   argument = new MethodGroupResolveResult(new TypeResolveResult(declType), "ReadKey", new[] { methods }, new IType[0]);

            bool success;

            Assert.AreEqual(
                new [] { compilation.FindType(typeof(ConsoleKeyInfo)) },
                ti.InferTypeArguments(new [] { T }, new [] { argument },
                                      new [] { new ParameterizedType(compilation.FindType(typeof(Func <>)).GetDefinition(), new[] { T }) },
                                      out success));
            Assert.IsTrue(success);
        }