Exemple #1
0
 private void WriteType(IReturnType rt)
 {
     if (rt == null)
     {
         _writer.Write(NullRTReferenceCode);
         return;
     }
     if (rt.IsDefaultReturnType)
     {
         string name = rt.FullyQualifiedName;
         if (name == "System.Void")
         {
             _writer.Write(VoidRTCode);
         }
         else
         {
             _writer.Write(_classIndices[new ClassNameTypeCountPair(rt)]);
         }
     }
     else if (rt.IsGenericReturnType)
     {
         GenericReturnType grt = rt.CastToGenericReturnType();
         if (grt.TypeParameter.Method != null)
         {
             _writer.Write(MethodGenericRTCode);
         }
         else
         {
             _writer.Write(TypeGenericRTCode);
         }
         _writer.Write(grt.TypeParameter.Index);
     }
     else if (rt.IsArrayReturnType)
     {
         _writer.Write(ArrayRTCode);
         _writer.Write(rt.CastToArrayReturnType().ArrayDimensions);
         WriteType(rt.CastToArrayReturnType().ArrayElementType);
     }
     else if (rt.IsConstructedReturnType)
     {
         ConstructedReturnType crt = rt.CastToConstructedReturnType();
         _writer.Write(ConstructedRTCode);
         WriteType(crt.UnboundType);
         _writer.Write((byte)crt.TypeArguments.Count);
         foreach (IReturnType typeArgument in crt.TypeArguments)
         {
             WriteType(typeArgument);
         }
     }
     else
     {
         _writer.Write(NullRTReferenceCode);
         LoggingService.Warn("Unknown return type: " + rt.ToString());
     }
 }
        /// <summary>
        /// Gets the common base type of a and b.
        /// </summary>
        public static IReturnType GetCommonType(IProjectContent projectContent, IReturnType a, IReturnType b)
        {
            if (projectContent == null)
            {
                throw new ArgumentNullException("projectContent");
            }
            if (a == null)
            {
                return(b);
            }
            if (b == null)
            {
                return(a);
            }
            if (ConversionExists(a, b))
            {
                return(b);
            }
            if (ConversionExists(b, a))
            {
                return(a);
            }
            IClass c = a.GetUnderlyingClass();

            if (c != null)
            {
                foreach (IClass baseClass in c.ClassInheritanceTree)
                {
                    IReturnType baseType = baseClass.DefaultReturnType;
                    if (baseClass.TypeParameters.Count > 0)
                    {
                        IReturnType[] typeArguments = new IReturnType[baseClass.TypeParameters.Count];
                        for (int i = 0; i < typeArguments.Length; i++)
                        {
                            typeArguments[i] = GetTypeParameterPassedToBaseClass(a, baseClass, i);
                        }
                        baseType = new ConstructedReturnType(baseType, typeArguments);
                    }
                    if (ConversionExists(b, baseType))
                    {
                        return(baseType);
                    }
                }
            }
            return(projectContent.SystemTypes.Object);
        }
Exemple #3
0
 static void TryAddExtension(LanguageProperties language, ArrayList res, IMethodOrProperty ext, IReturnType resolvedType)
 {
     // accept only extension methods
     if (!ext.IsExtensionMethod)
     {
         return;
     }
     // don't add extension if method with that name already exists
     // but allow overloading extension methods
     foreach (IMember member in res)
     {
         IMethodOrProperty p = member as IMethodOrProperty;
         if (p != null && p.IsExtensionMethod)
         {
             continue;
         }
         if (language.NameComparer.Equals(member.Name, ext.Name))
         {
             return;
         }
     }
     // now add the extension method if it fits the type
     if (MemberLookupHelper.ConversionExists(resolvedType, ext.Parameters[0].ReturnType))
     {
         IMethod method = ext as IMethod;
         if (method != null && method.TypeParameters.Count > 0)
         {
             IReturnType[] typeArguments = new IReturnType[method.TypeParameters.Count];
             MemberLookupHelper.InferTypeArgument(method.Parameters[0].ReturnType, resolvedType, typeArguments);
             for (int i = 0; i < typeArguments.Length; i++)
             {
                 if (typeArguments[i] != null)
                 {
                     ext            = (IMethod)ext.Clone();
                     ext.ReturnType = ConstructedReturnType.TranslateType(ext.ReturnType, typeArguments, true);
                     for (int j = 0; j < ext.Parameters.Count; ++j)
                     {
                         ext.Parameters[j].ReturnType = ConstructedReturnType.TranslateType(ext.Parameters[j].ReturnType, typeArguments, true);
                     }
                     break;
                 }
             }
         }
         res.Add(ext);
     }
 }
 static IReturnType[][] ExpandParametersAndSubstitute(IList <IMethodOrProperty> list,
                                                      IReturnType[] arguments,
                                                      int maxScore, int[] ranking, bool[] needToExpand,
                                                      out IReturnType[][] inferredTypeParameters)
 {
     IReturnType[][] expandedParameters = new IReturnType[list.Count][];
     inferredTypeParameters = new IReturnType[list.Count][];
     for (int i = 0; i < ranking.Length; i++)
     {
         if (ranking[i] == maxScore)
         {
             IList <IParameter> parameters     = list[i].Parameters;
             IReturnType[]      typeParameters = (list[i] is IMethod) ? InferTypeArguments((IMethod)list[i], arguments) : null;
             inferredTypeParameters[i] = typeParameters;
             IReturnType paramsType = null;
             expandedParameters[i] = new IReturnType[arguments.Length];
             for (int j = 0; j < arguments.Length; j++)
             {
                 if (j < parameters.Count)
                 {
                     IParameter parameter = parameters[j];
                     if (parameter.IsParams && needToExpand[i])
                     {
                         if (parameter.ReturnType.IsArrayReturnType)
                         {
                             paramsType = parameter.ReturnType.CastToArrayReturnType().ArrayElementType;
                             paramsType = ConstructedReturnType.TranslateType(paramsType, typeParameters, true);
                         }
                         expandedParameters[i][j] = paramsType;
                     }
                     else
                     {
                         expandedParameters[i][j] = ConstructedReturnType.TranslateType(parameter.ReturnType, typeParameters, true);
                     }
                 }
                 else
                 {
                     expandedParameters[i][j] = paramsType;
                 }
             }
         }
     }
     return(expandedParameters);
 }
        /// <summary>
        /// Gets the type parameter that was passed to a certain base class.
        /// For example, when <paramref name="returnType"/> is Dictionary(of string, int)
        /// this method will return KeyValuePair(of string, int)
        /// </summary>
        public static IReturnType GetTypeParameterPassedToBaseClass(IReturnType parentType, IClass baseClass, int baseClassTypeParameterIndex)
        {
            if (!parentType.IsConstructedReturnType)
            {
                return(null);
            }
            ConstructedReturnType returnType = parentType.CastToConstructedReturnType();
            IClass c = returnType.GetUnderlyingClass();

            if (c == null)
            {
                return(null);
            }
            if (baseClass.CompareTo(c) == 0)
            {
                if (baseClassTypeParameterIndex >= returnType.TypeArguments.Count)
                {
                    return(null);
                }
                return(returnType.TypeArguments[baseClassTypeParameterIndex]);
            }
            foreach (IReturnType baseType in c.BaseTypes)
            {
                if (baseClass.CompareTo(baseType.GetUnderlyingClass()) == 0)
                {
                    if (!baseType.IsConstructedReturnType)
                    {
                        return(null);
                    }
                    ConstructedReturnType baseTypeCRT = baseType.CastToConstructedReturnType();
                    if (baseClassTypeParameterIndex >= baseTypeCRT.TypeArguments.Count)
                    {
                        return(null);
                    }
                    IReturnType result = baseTypeCRT.TypeArguments[baseClassTypeParameterIndex];
                    if (returnType.TypeArguments != null)
                    {
                        result = ConstructedReturnType.TranslateType(result, returnType.TypeArguments, false);
                    }
                    return(result);
                }
            }
            return(null);
        }
Exemple #6
0
 public static IReturnType TranslateType(IReturnType input, IList <IReturnType> typeParameters, bool convertForMethod)
 {
     if (typeParameters == null || typeParameters.Count == 0)
     {
         return(input);                // nothing to do when there are no type parameters specified
     }
     if (input.IsGenericReturnType)
     {
         GenericReturnType rt = input.CastToGenericReturnType();
         if (convertForMethod ? (rt.TypeParameter.Method != null) : (rt.TypeParameter.Method == null))
         {
             if (rt.TypeParameter.Index < typeParameters.Count)
             {
                 IReturnType newType = typeParameters[rt.TypeParameter.Index];
                 if (newType != null)
                 {
                     return(newType);
                 }
             }
         }
     }
     else if (input.IsArrayReturnType)
     {
         ArrayReturnType arInput = input.CastToArrayReturnType();
         IReturnType     e       = arInput.ArrayElementType;
         IReturnType     t       = TranslateType(e, typeParameters, convertForMethod);
         if (e != t && t != null)
         {
             return(new ArrayReturnType(arInput.ProjectContent, t, arInput.ArrayDimensions));
         }
     }
     else if (input.IsConstructedReturnType)
     {
         ConstructedReturnType cinput = input.CastToConstructedReturnType();
         List <IReturnType>    para   = new List <IReturnType>(cinput.TypeArguments.Count);
         foreach (IReturnType argument in cinput.TypeArguments)
         {
             para.Add(TranslateType(argument, typeParameters, convertForMethod));
         }
         return(new ConstructedReturnType(cinput.UnboundType, para));
     }
     return(input);
 }
 static void ApplyInferredTypeParameters(IList <IMethod> list, IReturnType[][] inferredTypeParameters)
 {
     if (inferredTypeParameters == null)
     {
         return;
     }
     for (int i = 0; i < list.Count; i++)
     {
         IReturnType[] inferred = inferredTypeParameters[i];
         if (inferred != null && inferred.Length > 0)
         {
             IMethod m = (IMethod)list[i].Clone();
             m.ReturnType = ConstructedReturnType.TranslateType(m.ReturnType, inferred, true);
             for (int j = 0; j < m.Parameters.Count; ++j)
             {
                 m.Parameters[j].ReturnType = ConstructedReturnType.TranslateType(m.Parameters[j].ReturnType, inferred, true);
             }
             list[i] = m;
         }
     }
 }
        /// <summary>
        /// Assigns a ranking score to each method in the <paramref name="list"/>.
        /// </summary>
        /// <param name="list">Link with the methods to check.<br/>
        /// <b>Generic methods in the input type are replaced by methods with have the types substituted!</b>
        /// </param>
        /// <param name="typeParameters">List with the type parameters passed to the method.
        /// Can be null (=no type parameters)</param>
        /// <param name="arguments">The types of the arguments passed to the method.
        /// A null return type means any argument type is allowed.</param>
        /// <param name="allowAdditionalArguments">Specifies whether the method can have
        /// more parameters than specified here. Useful for method insight scenarios.</param>
        /// <param name="acceptableMatch">Out parameter that is true when the best ranked
        /// method is acceptable for a method call (no invalid casts)</param>
        /// <returns>Integer array. Each value in the array </returns>
        public static int[] RankOverloads(IList <IMethod> list,
                                          IReturnType[] typeParameters,
                                          IReturnType[] arguments,
                                          bool allowAdditionalArguments,
                                          out bool acceptableMatch)
        {
            acceptableMatch = false;
            if (list.Count == 0)
            {
                return new int[] {}
            }
            ;

            List <IMethodOrProperty> l2 = new List <IMethodOrProperty>(list.Count);

            IReturnType[][] inferredTypeParameters;
            // See ECMA-334, § 14.3

            // If type parameters are specified, remove all methods from the list that do not
            // use the specified number of parameters.
            if (typeParameters != null && typeParameters.Length > 0)
            {
                for (int i = 0; i < list.Count; i++)
                {
                    IMethod m = list[i];
                    if (m.TypeParameters.Count == typeParameters.Length)
                    {
                        m            = (IMethod)m.Clone();
                        m.ReturnType = ConstructedReturnType.TranslateType(m.ReturnType, typeParameters, true);
                        for (int j = 0; j < m.Parameters.Count; ++j)
                        {
                            m.Parameters[j].ReturnType = ConstructedReturnType.TranslateType(m.Parameters[j].ReturnType, typeParameters, true);
                        }
                        list[i] = m;
                        l2.Add(m);
                    }
                }

                int[] innerRanking = RankOverloads(l2, arguments, allowAdditionalArguments, out acceptableMatch, out inferredTypeParameters);

                int[] ranking    = new int[list.Count];
                int   innerIndex = 0;
                for (int i = 0; i < ranking.Length; i++)
                {
                    if (list[i].TypeParameters.Count == typeParameters.Length)
                    {
                        ranking[i] = innerRanking[innerIndex++];
                    }
                    else
                    {
                        ranking[i] = 0;
                    }
                }
                return(ranking);
            }
            else
            {
                // Note that when there are no type parameters, methods having type parameters
                // are not removed, since the type inference process might be able to infer the
                // type arguments.
                foreach (IMethod m in list)
                {
                    l2.Add(m);
                }

                int[] ranking = RankOverloads(l2, arguments, allowAdditionalArguments, out acceptableMatch, out inferredTypeParameters);
                ApplyInferredTypeParameters(list, inferredTypeParameters);
                return(ranking);
            }
        }