コード例 #1
0
        // Resolve any dynamic params to the type of the target parameters list (for PlayScript only).
        public bool AsTryResolveDynamicArgs(ResolveContext ec, System.Collections.IEnumerable candidates)
        {
            AParametersCollection parameters = null;

            foreach (MemberSpec memberSpec in candidates)
            {
                AParametersCollection possibleParams = null;
                int fixedArgsLen = 0;

                if (memberSpec is MethodSpec)
                {
                    MethodSpec methodSpec = memberSpec as MethodSpec;
                    possibleParams = methodSpec.Parameters;
                    fixedArgsLen   = possibleParams.FixedParameters.Length;
                    if (methodSpec.IsExtensionMethod)
                    {
                        fixedArgsLen--;
                    }
                }
                else if (memberSpec is IndexerSpec)
                {
                    IndexerSpec indexerSpec = memberSpec as IndexerSpec;
                    possibleParams = indexerSpec.Parameters;
                    fixedArgsLen   = possibleParams.FixedParameters.Length;
                }

                if (fixedArgsLen == args.Count)
                {
                    if (parameters != null)
                    {
                        parameters = null;                              // Can't be more than one - or we give up and do a dynamic call..
                        break;
                    }
                    parameters = possibleParams;
                }
            }

            if (parameters != null)
            {
                for (var i = 0; i < args.Count; i++)
                {
                    var arg       = args [i];
                    var paramType = parameters.Types [i];
                    if (arg.Expr.Type == ec.BuiltinTypes.Dynamic)
                    {
                        var parCastType = paramType.BuiltinType == BuiltinTypeSpec.Type.Dynamic ? ec.BuiltinTypes.Object : paramType;
                        var new_arg     = new Argument(new Cast(
                                                           new TypeExpression(parCastType, arg.Expr.Location),
                                                           arg.Expr, arg.Expr.Location), arg.ArgType);
                        new_arg.Resolve(ec);
                        args [i] = new_arg;
                    }
                }
                return(true);
            }

            return(false);
        }
コード例 #2
0
        public bool AsTryResolveDynamicArgs(ResolveContext ec, MemberSpec memberSpec)
        {
            AParametersCollection parameters = null;
            int fixedArgsLen = 0;

            if (memberSpec is MethodSpec)
            {
                MethodSpec methodSpec = memberSpec as MethodSpec;
                parameters   = methodSpec.Parameters;
                fixedArgsLen = parameters.FixedParameters.Length;
                if (methodSpec.IsExtensionMethod)
                {
                    fixedArgsLen--;
                }
            }
            else if (memberSpec is IndexerSpec)
            {
                IndexerSpec indexerSpec = memberSpec as IndexerSpec;
                parameters   = indexerSpec.Parameters;
                fixedArgsLen = parameters.FixedParameters.Length;
            }

            if (parameters == null)
            {
                return(false);
            }

            if (fixedArgsLen < args.Count)
            {
                // too many arguments
                return(false);
            }

            for (var i = 0; i < args.Count; i++)
            {
                var arg       = args [i];
                var paramType = parameters.Types [i];
                if (arg.Expr.Type == ec.BuiltinTypes.Dynamic)
                {
                    var parCastType = paramType.BuiltinType == BuiltinTypeSpec.Type.Dynamic ? ec.BuiltinTypes.Object : paramType;
                    var new_arg     = new Argument(new Cast(
                                                       new TypeExpression(parCastType, arg.Expr.Location),
                                                       arg.Expr, arg.Expr.Location), arg.ArgType);
                    new_arg.Resolve(ec);
                    args [i] = new_arg;
                }
            }
            return(true);
        }
コード例 #3
0
ファイル: pending.cs プロジェクト: vinaypotluri/mono
        /// <summary>
        ///   This function tells whether one of our base classes implements
        ///   the given method (which turns out, it is valid to have an interface
        ///   implementation in a base
        /// </summary>
        bool BaseImplements(TypeSpec iface_type, MethodSpec mi, out MethodSpec base_method)
        {
            base_method = null;
            bool     base_can_implement = true;
            TypeSpec lookup_type;

            //
            // Special handling for properties/indexers which cannot have accessors
            // implementing an interface found in different types (e.g. current and base)
            //
            if (mi.IsAccessor && container.Interfaces != null)
            {
                bool new_implementation = false;
                foreach (var iface in container.Interfaces)
                {
                    if (TypeSpecComparer.IsEqual(iface, iface_type))
                    {
                        new_implementation = true;
                        break;
                    }
                }

                if (new_implementation)
                {
                    MemberFilter filter;
                    if (mi.Parameters.Count > 1)
                    {
                        var indexer_params = mi.Name [0] == 'g' ? mi.Parameters : IndexerSpec.CreateParametersFromSetter(mi, mi.Parameters.Count - 1);
                        filter = new MemberFilter(MemberCache.IndexerNameAlias, 0, MemberKind.Indexer, indexer_params, null);
                    }
                    else
                    {
                        var pname = mi.Name.Substring(4);
                        filter = MemberFilter.Property(pname, null);
                    }

                    var prop = MemberCache.FindMember(container.CurrentType, filter, BindingRestriction.DeclaredOnly | BindingRestriction.InstanceOnly);
                    if (prop != null && (prop.Modifiers & Modifiers.NEW) != 0)
                    {
                        base_can_implement = false;
                    }
                }
            }

            if (base_can_implement)
            {
                lookup_type = container.BaseType;

                if (lookup_type.ImplementsInterface(iface_type, false))
                {
                    return(true);
                }
            }
            else
            {
                lookup_type = container.CurrentType;
            }

            //
            // Setup filter with no return type to give better error message
            // about mismatch at return type when the check bellow rejects them
            //
            var        parameters  = mi.Parameters;
            MethodSpec close_match = null;

            while (true)
            {
                var candidates = MemberCache.FindMembers(lookup_type, mi.Name, !base_can_implement);
                if (candidates == null)
                {
                    base_method = close_match;
                    return(false);
                }

                MethodSpec similar_candidate = null;
                foreach (var candidate in candidates)
                {
                    if (candidate.Kind != MemberKind.Method)
                    {
                        continue;
                    }

                    if (candidate.Arity != mi.Arity)
                    {
                        continue;
                    }

                    var candidate_param = ((MethodSpec)candidate).Parameters;
                    if (!TypeSpecComparer.Override.IsEqual(parameters.Types, candidate_param.Types))
                    {
                        continue;
                    }

                    bool modifiers_match = true;
                    for (int i = 0; i < parameters.Count; ++i)
                    {
                        //
                        // First check exact ref/out match
                        //
                        if ((parameters.FixedParameters[i].ModFlags & Parameter.Modifier.RefOutMask) == (candidate_param.FixedParameters[i].ModFlags & Parameter.Modifier.RefOutMask))
                        {
                            continue;
                        }

                        modifiers_match = false;

                        //
                        // Different in ref/out only
                        //
                        if ((parameters.FixedParameters[i].ModFlags & Parameter.Modifier.RefOutMask) != (candidate_param.FixedParameters[i].ModFlags & Parameter.Modifier.RefOutMask))
                        {
                            if (similar_candidate == null)
                            {
                                if (!candidate.IsPublic)
                                {
                                    break;
                                }

                                if (!TypeSpecComparer.Override.IsEqual(mi.ReturnType, ((MethodSpec)candidate).ReturnType))
                                {
                                    break;
                                }

                                // It's used for ref/out ambiguity overload check
                                similar_candidate = (MethodSpec)candidate;
                            }

                            continue;
                        }

                        similar_candidate = null;
                        break;
                    }

                    if (!modifiers_match)
                    {
                        continue;
                    }

                    //
                    // From this point the candidate is used for detailed error reporting
                    // because it's very close match to what we are looking for
                    //
                    var m = (MethodSpec)candidate;

                    if (!m.IsPublic)
                    {
                        if (close_match == null)
                        {
                            close_match = m;
                        }

                        continue;
                    }

                    if (!TypeSpecComparer.Override.IsEqual(mi.ReturnType, m.ReturnType))
                    {
                        if (close_match == null)
                        {
                            close_match = m;
                        }

                        continue;
                    }

                    base_method = m;

                    if (mi.IsGeneric && !Method.CheckImplementingMethodConstraints(container, m, mi))
                    {
                        return(true);
                    }
                }

                if (base_method != null)
                {
                    if (similar_candidate != null)
                    {
                        Report.SymbolRelatedToPreviousError(similar_candidate);
                        Report.SymbolRelatedToPreviousError(mi);
                        Report.SymbolRelatedToPreviousError(container);
                        Report.Warning(1956, 1, ((MemberCore)base_method.MemberDefinition).Location,
                                       "The interface method `{0}' implementation is ambiguous between following methods: `{1}' and `{2}' in type `{3}'",
                                       mi.GetSignatureForError(), base_method.GetSignatureForError(), similar_candidate.GetSignatureForError(), container.GetSignatureForError());
                    }

                    break;
                }

                if (!base_can_implement)
                {
                    return(false);
                }

                lookup_type = candidates[0].DeclaringType.BaseType;
                if (lookup_type == null)
                {
                    base_method = close_match;
                    return(false);
                }
            }

            if (!base_method.IsVirtual)
            {
#if STATIC
                var base_builder = base_method.GetMetaInfo() as MethodBuilder;
                if (base_builder != null)
                {
                    //
                    // We can avoid creating a proxy if base_method can be marked 'final virtual'. This can
                    // be done for all methods from compiled assembly
                    //
                    base_builder.__SetAttributes(base_builder.Attributes | MethodAttributes.Virtual | MethodAttributes.Final | MethodAttributes.NewSlot);
                    return(true);
                }
#endif
                DefineProxy(iface_type, base_method, mi);
            }

            return(true);
        }