Пример #1
0
        /// <summary>
        /// Looks up the indexers on the target type.
        /// </summary>
        public IList <MethodListWithDeclaringType> LookupIndexers(Expression targetExpression)
        {
            if (targetExpression == null)
            {
                throw new ArgumentNullException("targetExpression");
            }

            IType targetType                       = targetExpression.Type;
            bool  allowProtectedAccess             = IsProtectedAccessAllowed(targetExpression);
            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);
        }
Пример #2
0
        IList <Expression> GetArgumentsWithConversions(Expression targetExpression, IParameterizedMember bestCandidateForNamedArguments)
        {
            var conversions = this.ArgumentConversions;

            Expression[] args = new Expression[arguments.Length];
            for (int i = 0; i < args.Length; i++)
            {
                var argument = arguments[i];
                if (this.IsExtensionMethodInvocation && i == 0 && targetExpression != null)
                {
                    argument = targetExpression;
                }
                int parameterIndex = bestCandidate.ArgumentToParameterMap[i];
                if (parameterIndex >= 0 && conversions[i] != Conversion.IdentityConversion)
                {
                    // Wrap argument in ConversionResolveResult
                    IType parameterType = bestCandidate.ParameterTypes[parameterIndex];
                    if (parameterType.Kind != TypeKind.Unknown)
                    {
                        if (arguments[i].IsCompileTimeConstant && conversions[i].IsValid && !conversions[i].IsUserDefined)
                        {
                            argument = new CastExpression(parameterType, argument).DoResolve(new ResolveContext(compilation).WithCheckForOverflow(CheckForOverflow));
                        }
                        else
                        {
                            argument = new AST.CastExpression(parameterType, argument, conversions[i], CheckForOverflow);
                        }
                    }
                }
                if (bestCandidateForNamedArguments != null && argumentNames[i] != null)
                {
                    // Wrap argument in NamedArgumentResolveResult
                    if (parameterIndex >= 0)
                    {
                        argument = new NamedArgumentExpression(bestCandidateForNamedArguments.Parameters[parameterIndex], argument, bestCandidateForNamedArguments);
                    }
                    else
                    {
                        argument = new NamedArgumentExpression(argumentNames[i], argument);
                    }
                }
                args[i] = argument;
            }
            return(args);
        }
Пример #3
0
        /// <summary>
        /// Creates a ResolveResult representing the result of overload resolution.
        /// </summary>
        /// <param name="targetExpression">
        /// The target expression of the call. May be <c>null</c> for static methods/constructors.
        /// </param>
        /// <param name="initializerStatements">
        /// Statements for Objects/Collections initializer.
        /// <see cref="InvocationExpression.InitializerStatements"/>
        /// <param name="returnTypeOverride">
        /// If not null, use this instead of the ReturnType of the member as the type of the created resolve result.
        /// </param>
        public Invocation CreateInvocation(Expression targetExpression, IList <Expression> initializerStatements = null, IType returnTypeOverride = null)
        {
            IParameterizedMember member = GetBestCandidateWithSubstitutedTypeArguments();

            if (member == null)
            {
                throw new InvalidOperationException();
            }

            return(new Invocation(targetExpression,
                                  member,
                                  GetArgumentsWithConversions(targetExpression, member),
                                  this.BestCandidateErrors,
                                  this.IsExtensionMethodInvocation,
                                  this.BestCandidateIsExpandedForm,
                                  isDelegateInvocation: false,
                                  argumentToParameterMap: this.GetArgumentToParameterMap(),
                                  initializerStatements: initializerStatements,
                                  returnTypeOverride: returnTypeOverride));
        }
Пример #4
0
        Expression CreateResult(Expression targetExpression, 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 UnknownMemberExpression(targetExpression.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 V# 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 MethodGroupExpression(targetExpression, 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]); // TODO:ERROR AMBIGIOUS
                    return(null);
                }
                else
                {
                    return(new TypeExpression(resultGroup.NestedTypes[0]));
                }
            }

            if (resultGroup.NonMethod.IsStatic && targetExpression is SelfReference)
            {
                targetExpression = new TypeExpression(targetExpression.Type);
            }

            if (lookupGroups.Count > 1)
            {
                throw new ArgumentException(string.Format("Ambigious member {1} found on target {0}",
                                                          targetExpression.GetSignatureForError(), resultGroup.NonMethod));
            }
            else
            {
                if (isInEnumMemberInitializer)
                {
                    IField field = resultGroup.NonMethod as IField;
                    if (field != null && field.DeclaringTypeDefinition != null && field.DeclaringTypeDefinition.Kind == TypeKind.Enum)
                    {
                        return(new MemberExpressionStatement(
                                   targetExpression, field,
                                   field.DeclaringTypeDefinition.EnumUnderlyingType,
                                   field.IsConst, field.ConstantValue));
                    }
                }
                return(new MemberExpressionStatement(targetExpression, resultGroup.NonMethod));
            }
        }
Пример #5
0
        /// <summary>
        /// Retrieves all members that are accessible and not hidden (by being overridden or shadowed).
        /// Returns both members and nested type definitions. Does not include extension methods.
        /// </summary>
        public IEnumerable <IEntity> GetAccessibleMembers(Expression targetExpression)
        {
            if (targetExpression == null)
            {
                throw new ArgumentNullException("targetExpression");
            }

            bool targetIsTypeParameter = targetExpression.Type.Kind == TypeKind.TypeParameter;
            bool allowProtectedAccess  = IsProtectedAccessAllowed(targetExpression);

            // maps the member name to the list of lookup groups
            var lookupGroupDict = new Dictionary <string, 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 targetExpression.Type.GetNonInterfaceBaseTypes())
            {
                List <IEntity> entities = new List <IEntity>();
                entities.AddRange(type.GetMembers(options: GetMemberOptions.IgnoreInheritedMembers));
                if (!targetIsTypeParameter)
                {
                    var nestedTypes = type.GetNestedTypes(options: GetMemberOptions.IgnoreInheritedMembers | GetMemberOptions.ReturnMemberDefinitions);
                    // GetDefinition() might return null if some IType has a strange implementation of GetNestedTypes.
                    entities.AddRange(nestedTypes.Select(t => t.GetDefinition()).Where(td => td != null));
                }

                foreach (var entityGroup in entities.GroupBy(e => e.Name))
                {
                    List <LookupGroup> lookupGroups = new List <LookupGroup>();
                    if (!lookupGroupDict.TryGetValue(entityGroup.Key, out lookupGroups))
                    {
                        lookupGroupDict.Add(entityGroup.Key, lookupGroups = new List <LookupGroup>());
                    }

                    List <IType> newNestedTypes            = null;
                    List <IParameterizedMember> newMethods = null;
                    IMember newNonMethod = null;

                    IEnumerable <IType> typeBaseTypes = null;

                    if (!targetIsTypeParameter)
                    {
                        AddNestedTypes(type, entityGroup.OfType <IType>(), 0, lookupGroups, ref typeBaseTypes, ref newNestedTypes);
                    }
                    AddMembers(type, entityGroup.OfType <IMember>(), allowProtectedAccess, lookupGroups, false, ref typeBaseTypes, ref newMethods, ref newNonMethod);

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

            foreach (List <LookupGroup> lookupGroups in lookupGroupDict.Values)
            {
                // Remove interface members hidden by class members.
                if (targetIsTypeParameter)
                {
                    // This can happen only with type parameters.
                    RemoveInterfaceMembersHiddenByClassMembers(lookupGroups);
                }

                // Now report the results:
                foreach (LookupGroup lookupGroup in lookupGroups)
                {
                    if (!lookupGroup.MethodsAreHidden)
                    {
                        foreach (IMethod method in lookupGroup.Methods)
                        {
                            yield return(method);
                        }
                    }
                    if (!lookupGroup.NonMethodIsHidden)
                    {
                        yield return(lookupGroup.NonMethod);
                    }
                    if (lookupGroup.NestedTypes != null)
                    {
                        foreach (IType type in lookupGroup.NestedTypes)
                        {
                            ITypeDefinition typeDef = type.GetDefinition();
                            if (typeDef != null)
                            {
                                yield return(typeDef);
                            }
                        }
                    }
                }
            }
        }