public TypeConversion(float quality, bool isNatural, MemberDescription implicitConversion = null, MemberDescription explicitConversion = null)
 {
     this.Quality   = quality;
     this.IsNatural = isNatural;
     this.Implicit  = implicitConversion;
     this.Explicit  = explicitConversion;
 }
        public TypeConversion Expand(MemberDescription implicitConversion, MemberDescription explicitConversion)
        {
            implicitConversion = implicitConversion ?? this.Implicit;
            explicitConversion = explicitConversion ?? this.Explicit;

            if (implicitConversion == this.Implicit && explicitConversion == this.Explicit)
            {
                return(this);
            }

            var newQuality = Math.Max(this.Quality, this.Implicit != null ? QUALITY_IMPLICIT_CONVERSION : QUALITY_EXPLICIT_CONVERSION);

            return(new TypeConversion(newQuality, this.IsNatural, implicitConversion, explicitConversion));
        }
        private MemberDescription[] GetOperators(List <MethodInfo> methods, MemberDescription[] methodsDescriptions, string operatorName, int?compareParameterIndex = null)
        {
            if (methods == null)
            {
                throw new ArgumentNullException("methods");
            }
            if (methodsDescriptions == null)
            {
                throw new ArgumentNullException("methodsDescriptions");
            }
            if (operatorName == null)
            {
                throw new ArgumentNullException("operatorName");
            }

            var operators = default(List <MemberDescription>);

            for (var i = 0; i < methods.Count; i++)
            {
                var method = methods[i];
                if (method.Name != operatorName)
                {
                    continue;
                }

                if (methodsDescriptions[i] == null)
                {
                    methodsDescriptions[i] = new MemberDescription(this, method);
                }

                var methodDescription = methodsDescriptions[i];
                if (compareParameterIndex.HasValue && methodDescription.GetParameterType(compareParameterIndex.Value) != this.type)
                {
                    continue;
                }

                if (operators == null)
                {
                    operators = new List <MemberDescription>();
                }
                operators.Add(new MemberDescription(this, method));
            }

            return(operators != null?operators.ToArray() : EmptyMembers);
        }
Exemplo n.º 4
0
        private static bool TryMakeGenericMethod(ref MemberDescription methodDescription, Type[] typeArguments)
        {
            if (methodDescription == null)
            {
                throw new ArgumentNullException("methodDescription");
            }

            try
            {
                if (typeArguments != null)
                {
                    methodDescription = methodDescription.MakeGenericMethod(typeArguments);
                }

                Debug.Assert(methodDescription != null, "methodDescription != null");

                return(true);
            }
            catch
            {
                return(false);
            }
        }
Exemplo n.º 5
0
        public bool TryResolveMember(object memberName, out MemberDescription member)
        {
            member = null;
            if (memberName is SyntaxTreeNode == false)
            {
                return(false);
            }

            var memberNode = (SyntaxTreeNode)memberName;
            var typeName   = memberNode.GetTypeName(throwOnError: false);
            var type       = default(Type);

            if (typeName == null || this.TryResolveType(typeName, out type) == false)
            {
                return(false);
            }

            var name    = memberNode.GetName(throwOnError: false);
            var nameRef = default(TypeReference);

            if (name == null || TryGetTypeReference(name, out nameRef) == false)
            {
                return(false);
            }

            var genericArguments = default(Type[]);

            if (nameRef.IsGenericType)
            {
                genericArguments = new Type[nameRef.TypeArguments.Count];
                for (var i = 0; i < genericArguments.Length; i++)
                {
                    var typeArgument = nameRef.TypeArguments[i];
                    if (this.TryResolveType(typeArgument, out genericArguments[i]) == false)
                    {
                        return(false);
                    }
                }
            }

            var typeDescription = TypeDescription.GetTypeDescription(type);
            var argumentNames   = memberNode.GetArgumentNames(throwOnError: false);
            var members         = nameRef.Name == ".ctor" ? typeDescription.Constructors : typeDescription.GetMembers(nameRef.Name);

            foreach (var declaredMember in members)
            {
                if ((declaredMember.IsMethod || declaredMember.IsConstructor) && argumentNames != null)
                {
                    var paramsCount = declaredMember.GetParametersCount();
                    if (paramsCount != argumentNames.Count)
                    {
                        continue;
                    }
                    else if (paramsCount > 0)
                    {
                        for (var i = 0; i < paramsCount; i++)
                        {
                            var parameter      = declaredMember.GetParameter(i);
                            var parameterIndex = Constants.GetIndexAsString(parameter.Position);

                            var argumentName = default(string);
                            if (argumentNames.TryGetValue(parameterIndex, out argumentName) == false)
                            {
                                break;
                            }

                            if (string.Equals(argumentName, parameter.Name, StringComparison.OrdinalIgnoreCase) == false &&
                                string.Equals(argumentName, parameterIndex, StringComparison.OrdinalIgnoreCase) == false)
                            {
                                break;
                            }

                            if (i == paramsCount - 1)
                            {
                                member = declaredMember;
                                return(TryMakeGenericMethod(ref member, genericArguments));
                            }
                        }
                    }
                    else
                    {
                        member = declaredMember;
                        return(TryMakeGenericMethod(ref member, genericArguments));
                    }
                }
                else if (nameRef.TypeArguments.Count == declaredMember.GenericArgumentsCount)
                {
                    member = declaredMember;
                    return(TryMakeGenericMethod(ref member, genericArguments));
                }
            }
            return(false);
        }
        public TypeDescription(Type type, TypeCache cache)
        {
            if (type == null)
            {
                throw new ArgumentNullException("type");
            }
            if (cache == null)
            {
                throw new ArgumentNullException("cache");
            }

            this.type     = type;
            this.hashCode = type.GetHashCode();
            this.Name     = NameUtils.RemoveGenericSuffix(NameUtils.WriteName(type)).ToString();

            cache.Add(type, this);

            var typeInfo       = type.GetTypeInfo();
            var underlyingType = default(Type);

            if (typeInfo.IsEnum)
            {
                underlyingType = Enum.GetUnderlyingType(type);
            }
            else if (typeInfo.IsValueType)
            {
                underlyingType = Nullable.GetUnderlyingType(type);
            }
            else if (typeInfo.IsArray)
            {
                underlyingType = typeInfo.GetElementType();
            }

            this.BaseType = typeInfo.BaseType != null?cache.GetOrCreateTypeDescription(typeInfo.BaseType) : null;

            this.UnderlyingType = underlyingType != null?cache.GetOrCreateTypeDescription(underlyingType) : null;

            this.BaseTypes        = GetBaseTypes(this, 0);
            this.Interfaces       = typeInfo.GetImplementedInterfaces().Select(cache.GetOrCreateTypeDescription).ToArray();
            this.GenericArguments = typeInfo.IsGenericType ? ArrayUtils.ConvertAll(typeInfo.GetGenericArguments(), cache.GetOrCreateTypeDescription) : EmptyTypes;

            this.IsInterface          = typeInfo.IsInterface;
            this.IsValueType          = typeInfo.IsValueType;
            this.IsNullable           = Nullable.GetUnderlyingType(type) != null;
            this.IsNumber             = NumberUtils.IsNumber(type);
            this.CanBeNull            = this.IsNullable || typeInfo.IsValueType == false;
            this.IsEnum               = typeInfo.IsEnum;
            this.IsVoid               = type == typeof(void);
            this.IsDelegate           = typeof(Delegate).GetTypeInfo().IsAssignableFrom(typeInfo) && type != typeof(Delegate) && type != typeof(MulticastDelegate);
            this.HasGenericParameters = typeInfo.ContainsGenericParameters;
            if (this.IsVoid)
            {
                this.DefaultExpression = Expression.Constant(null, typeof(object));
            }
            else
            {
                this.DefaultExpression = Expression.Constant(typeInfo.IsValueType && this.IsNullable == false ? Activator.CreateInstance(type) : null, type);
            }
            this.TypeCode = ReflectionUtils.GetTypeCode(type);

            this.MembersByName = this.GetMembersByName(ref this.Indexers);

            var methods             = typeInfo.GetAllMethods().Where(m => m.IsPublic && m.IsStatic).ToList();
            var methodsDescriptions = new MemberDescription[methods.Count];

            // ReSharper disable LocalizableElement
            this.ImplicitConvertTo   = this.GetOperators(methods, methodsDescriptions, "op_Implicit", 0);
            this.ImplicitConvertFrom = this.GetOperators(methods, methodsDescriptions, "op_Implicit", -1);
            this.ExplicitConvertTo   = this.GetOperators(methods, methodsDescriptions, "op_Explicit", 0);
            this.ExplicitConvertFrom = this.GetOperators(methods, methodsDescriptions, "op_Explicit", -1);
            this.Addition            = this.GetOperators(methods, methodsDescriptions, "op_Addition");
            this.Division            = this.GetOperators(methods, methodsDescriptions, "op_Division");
            this.Equality            = this.GetOperators(methods, methodsDescriptions, "op_Equality");
            this.GreaterThan         = this.GetOperators(methods, methodsDescriptions, "op_GreaterThan");
            this.GreaterThanOrEqual  = this.GetOperators(methods, methodsDescriptions, "op_GreaterThanOrEqual");
            this.Inequality          = this.GetOperators(methods, methodsDescriptions, "op_Inequality");
            this.LessThan            = this.GetOperators(methods, methodsDescriptions, "op_LessThan");
            this.LessThanOrEqual     = this.GetOperators(methods, methodsDescriptions, "op_LessThanOrEqual");
            this.Modulus             = this.GetOperators(methods, methodsDescriptions, "op_Modulus");
            this.Multiply            = this.GetOperators(methods, methodsDescriptions, "op_Multiply");
            this.Subtraction         = this.GetOperators(methods, methodsDescriptions, "op_Subtraction");
            this.UnaryNegation       = this.GetOperators(methods, methodsDescriptions, "op_UnaryNegation");
            this.UnaryPlus           = this.GetOperators(methods, methodsDescriptions, "op_UnaryPlus");
            this.BitwiseAnd          = this.GetOperators(methods, methodsDescriptions, "op_BitwiseAnd");
            this.BitwiseOr           = this.GetOperators(methods, methodsDescriptions, "op_BitwiseOr");
            // ReSharper restore LocalizableElement
            this.Conversions  = Combine(this.ImplicitConvertTo, this.ImplicitConvertFrom, this.ExplicitConvertTo, this.ExplicitConvertFrom);
            this.Constructors = type.GetTypeInfo().GetPublicInstanceConstructors().Select(ctr => new MemberDescription(this, ctr)).ToArray();

            Array.Sort(this.Conversions);
            Array.Sort(this.Constructors);

            if (this.IsNullable && this.UnderlyingType != null)
            {
                this.UnderlyingType.nullableType = this;
            }
        }
        private Dictionary <string, MemberDescription[]> GetMembersByName(ref MemberDescription[] indexers)
        {
            var declaredMembers  = GetDeclaredMembers(this.type);
            var memberSetsByName = new Dictionary <string, HashSet <MemberDescription> >((this.BaseType != null ? this.BaseType.MembersByName.Count : 0) + declaredMembers.Count);

            foreach (var member in declaredMembers)
            {
                var memberDescription = default(MemberDescription);
                var method            = member as MethodInfo;
                var field             = member as FieldInfo;
                var property          = member as PropertyInfo;
                if (property != null)
                {
                    memberDescription = new MemberDescription(this, property);
                    if (memberDescription.GetParametersCount() != 0)
                    {
                        Add(ref indexers, memberDescription);
                    }
                }
                else if (field != null)
                {
                    memberDescription = new MemberDescription(this, field);
                }
                else if (method != null && method.IsSpecialName == false)
                {
                    memberDescription = new MemberDescription(this, method);
                }

                if (memberDescription == null)
                {
                    continue;
                }

                var members = default(HashSet <MemberDescription>);
                if (memberSetsByName.TryGetValue(memberDescription.Name, out members) == false)
                {
                    memberSetsByName[memberDescription.Name] = members = new HashSet <MemberDescription>();
                }
                members.Add(memberDescription);
            }

            if (this.BaseType != null)
            {
                foreach (var kv in this.BaseType.MembersByName)
                {
                    var memberName = kv.Key;
                    var memberList = kv.Value;

                    var members = default(HashSet <MemberDescription>);
                    if (memberSetsByName.TryGetValue(memberName, out members) == false)
                    {
                        memberSetsByName[memberName] = members = new HashSet <MemberDescription>();
                    }

                    foreach (var member in memberList)
                    {
                        members.Add(member);
                    }
                }
            }

            var membersByName = new Dictionary <string, MemberDescription[]>(memberSetsByName.Count, StringComparer.Ordinal);

            foreach (var kv in memberSetsByName)
            {
                var membersArray = kv.Value.ToArray();
                Array.Sort(membersArray);
                membersByName.Add(kv.Key, membersArray);
            }
            return(membersByName);
        }