Esempio n. 1
0
 //CONFORMING
 private static void ValidateElementInitAddMethodInfo(MethodInfo addMethod) {
     ValidateMethodInfo(addMethod);
     ParameterInfo[] pis = addMethod.GetParametersCached();
     if (pis.Length == 0) {
         throw Error.ElementInitializerMethodWithZeroArgs();
     }
     if (!addMethod.Name.Equals("Add", StringComparison.OrdinalIgnoreCase)) {
         throw Error.ElementInitializerMethodNotAdd();
     }
     if (addMethod.IsStatic) {
         throw Error.ElementInitializerMethodStatic();
     }
     foreach (ParameterInfo pi in pis) {
         if (pi.ParameterType.IsByRef) {
             throw Error.ElementInitializerMethodNoRefOutParam(pi.Name, addMethod.Name);
         }
     }
 }
Esempio n. 2
0
        private static void VerifyOpTrueFalse(ExpressionType nodeType, Type left, MethodInfo opTrue)
        {
            ParameterInfo[] pmsOpTrue = opTrue.GetParametersCached();
            if (pmsOpTrue.Length != 1)
                throw Error.IncorrectNumberOfMethodCallArguments(opTrue);

            if (!ParameterIsAssignable(pmsOpTrue[0], left))
            {
                if (!(TypeUtils.IsNullableType(left) && ParameterIsAssignable(pmsOpTrue[0], TypeUtils.GetNonNullableType(left))))
                    throw Error.OperandTypesDoNotMatchParameters(nodeType, opTrue.Name);
            }
        }
Esempio n. 3
0
 private static void ValidateUserDefinedConditionalLogicOperator(ExpressionType nodeType, Type left, Type right, MethodInfo method)
 {
     ValidateOperator(method, nameof(method));
     ParameterInfo[] pms = method.GetParametersCached();
     if (pms.Length != 2)
         throw Error.IncorrectNumberOfMethodCallArguments(method);
     if (!ParameterIsAssignable(pms[0], left))
     {
         if (!(TypeUtils.IsNullableType(left) && ParameterIsAssignable(pms[0], TypeUtils.GetNonNullableType(left))))
             throw Error.OperandTypesDoNotMatchParameters(nodeType, method.Name);
     }
     if (!ParameterIsAssignable(pms[1], right))
     {
         if (!(TypeUtils.IsNullableType(right) && ParameterIsAssignable(pms[1], TypeUtils.GetNonNullableType(right))))
             throw Error.OperandTypesDoNotMatchParameters(nodeType, method.Name);
     }
     if (pms[0].ParameterType != pms[1].ParameterType)
     {
         throw Error.UserDefinedOpMustHaveConsistentTypes(nodeType, method.Name);
     }
     if (method.ReturnType != pms[0].ParameterType)
     {
         throw Error.UserDefinedOpMustHaveConsistentTypes(nodeType, method.Name);
     }
     if (IsValidLiftedConditionalLogicalOperator(left, right, pms))
     {
         left = TypeUtils.GetNonNullableType(left);
         right = TypeUtils.GetNonNullableType(left);
     }
     MethodInfo opTrue = TypeUtils.GetBooleanOperator(method.DeclaringType, "op_True");
     MethodInfo opFalse = TypeUtils.GetBooleanOperator(method.DeclaringType, "op_False");
     if (opTrue == null || opTrue.ReturnType != typeof(bool) ||
         opFalse == null || opFalse.ReturnType != typeof(bool))
     {
         throw Error.LogicalOperatorMustHaveBooleanOperators(nodeType, method.Name);
     }
     VerifyOpTrueFalse(nodeType, left, opFalse);
     VerifyOpTrueFalse(nodeType, left, opTrue);
 }
Esempio n. 4
0
 private static BinaryExpression GetMethodBasedBinaryOperator(ExpressionType binaryType, Expression left, Expression right, MethodInfo method, bool liftToNull)
 {
     System.Diagnostics.Debug.Assert(method != null);
     ValidateOperator(method, nameof(method));
     ParameterInfo[] pms = method.GetParametersCached();
     if (pms.Length != 2)
         throw Error.IncorrectNumberOfMethodCallArguments(method);
     if (ParameterIsAssignable(pms[0], left.Type) && ParameterIsAssignable(pms[1], right.Type))
     {
         ValidateParamswithOperandsOrThrow(pms[0].ParameterType, left.Type, binaryType, method.Name);
         ValidateParamswithOperandsOrThrow(pms[1].ParameterType, right.Type, binaryType, method.Name);
         return new MethodBinaryExpression(binaryType, left, right, method.ReturnType, method);
     }
     // check for lifted call
     if (TypeUtils.IsNullableType(left.Type) && TypeUtils.IsNullableType(right.Type) &&
         ParameterIsAssignable(pms[0], TypeUtils.GetNonNullableType(left.Type)) &&
         ParameterIsAssignable(pms[1], TypeUtils.GetNonNullableType(right.Type)) &&
         method.ReturnType.GetTypeInfo().IsValueType && !TypeUtils.IsNullableType(method.ReturnType))
     {
         if (method.ReturnType != typeof(bool) || liftToNull)
         {
             return new MethodBinaryExpression(binaryType, left, right, TypeUtils.GetNullableType(method.ReturnType), method);
         }
         else
         {
             return new MethodBinaryExpression(binaryType, left, right, typeof(bool), method);
         }
     }
     throw Error.OperandTypesDoNotMatchParameters(binaryType, method.Name);
 }
 private static bool MethodHasByRefParameter(MethodInfo mi)
 {
     foreach (var pi in mi.GetParametersCached())
     {
         if (pi.IsByRefParameter())
         {
             return true;
         }
     }
     return false;
 }
Esempio n. 6
0
        /// <summary>
        /// Creates a <see cref="SwitchExpression"/>.
        /// </summary>
        /// <param name="type">The result type of the switch.</param>
        /// <param name="switchValue">The value to be tested against each case.</param>
        /// <param name="defaultBody">The result of the switch if no cases are matched.</param>
        /// <param name="comparison">The equality comparison method to use.</param>
        /// <param name="cases">The valid cases for this switch.</param>
        /// <returns>The created <see cref="SwitchExpression"/>.</returns>
        public static SwitchExpression Switch(Type type, Expression switchValue, Expression defaultBody, MethodInfo comparison, IEnumerable<SwitchCase> cases)
        {
            RequiresCanRead(switchValue, nameof(switchValue));
            if (switchValue.Type == typeof(void)) throw Error.ArgumentCannotBeOfTypeVoid(nameof(switchValue));

            ReadOnlyCollection<SwitchCase> caseList = cases.ToReadOnly();
            ContractUtils.RequiresNotNullItems(caseList, nameof(cases));

            // Type of the result. Either provided, or it is type of the branches.
            Type resultType;
            if (type != null)
                resultType = type;
            else if (caseList.Count != 0)
                resultType = caseList[0].Body.Type;
            else if (defaultBody != null)
                resultType = defaultBody.Type;
            else
                resultType = typeof(void);
            bool customType = type != null;

            if (comparison != null)
            {
                ParameterInfo[] pms = comparison.GetParametersCached();
                if (pms.Length != 2)
                {
                    throw Error.IncorrectNumberOfMethodCallArguments(comparison, nameof(comparison));
                }
                // Validate that the switch value's type matches the comparison method's
                // left hand side parameter type.
                ParameterInfo leftParam = pms[0];
                bool liftedCall = false;
                if (!ParameterIsAssignable(leftParam, switchValue.Type))
                {
                    liftedCall = ParameterIsAssignable(leftParam, switchValue.Type.GetNonNullableType());
                    if (!liftedCall)
                    {
                        throw Error.SwitchValueTypeDoesNotMatchComparisonMethodParameter(switchValue.Type, leftParam.ParameterType);
                    }
                }

                ParameterInfo rightParam = pms[1];
                foreach (SwitchCase c in caseList)
                {
                    ContractUtils.RequiresNotNull(c, nameof(cases));
                    ValidateSwitchCaseType(c.Body, customType, resultType, nameof(cases));
                    for (int i = 0; i < c.TestValues.Count; i++)
                    {
                        // When a comparison method is provided, test values can have different type but have to
                        // be reference assignable to the right hand side parameter of the method.
                        Type rightOperandType = c.TestValues[i].Type;
                        if (liftedCall)
                        {
                            if (!rightOperandType.IsNullableType())
                            {
                                throw Error.TestValueTypeDoesNotMatchComparisonMethodParameter(rightOperandType, rightParam.ParameterType);
                            }
                            rightOperandType = rightOperandType.GetNonNullableType();
                        }
                        if (!ParameterIsAssignable(rightParam, rightOperandType))
                        {
                            throw Error.TestValueTypeDoesNotMatchComparisonMethodParameter(rightOperandType, rightParam.ParameterType);
                        }
                    }
                }

                // if we have a non-boolean user-defined equals, we don't want it.
                if (comparison.ReturnType != typeof(bool))
                {
                    throw Error.EqualityMustReturnBoolean(comparison, nameof(comparison));
                }
            }
            else if (caseList.Count != 0)
            {
                // When comparison method is not present, all the test values must have
                // the same type. Use the first test value's type as the baseline.
                Expression firstTestValue = caseList[0].TestValues[0];
                foreach (SwitchCase c in caseList)
                {
                    ContractUtils.RequiresNotNull(c, nameof(cases));
                    ValidateSwitchCaseType(c.Body, customType, resultType, nameof(cases));
                    // When no comparison method is provided, require all test values to have the same type.
                    for (int i = 0; i < c.TestValues.Count; i++)
                    {
                        if (!TypeUtils.AreEquivalent(firstTestValue.Type, c.TestValues[i].Type))
                        {
                            throw Error.AllTestValuesMustHaveSameType(nameof(cases));
                        }
                    }
                }

                // Now we need to validate that switchValue.Type and testValueType
                // make sense in an Equal node. Fortunately, Equal throws a
                // reasonable error, so just call it.
                BinaryExpression equal = Equal(switchValue, firstTestValue, false, comparison);

                // Get the comparison function from equals node.
                comparison = equal.Method;
            }

            if (defaultBody == null)
            {
                if (resultType != typeof(void)) throw Error.DefaultBodyMustBeSupplied(nameof(defaultBody));
            }
            else
            {
                ValidateSwitchCaseType(defaultBody, customType, resultType, nameof(defaultBody));
            }

            return new SwitchExpression(resultType, switchValue, defaultBody, comparison, caseList);
        }
Esempio n. 7
0
 private static UnaryExpression GetMethodBasedCoercionOperator(ExpressionType unaryType, Expression operand, Type convertToType, MethodInfo method)
 {
     System.Diagnostics.Debug.Assert(method != null);
     ValidateOperator(method);
     ParameterInfo[] pms = method.GetParametersCached();
     if (pms.Length != 1)
     {
         throw Error.IncorrectNumberOfMethodCallArguments(method);
     }
     if (ParameterIsAssignable(pms[0], operand.Type) && TypeUtils.AreEquivalent(method.ReturnType, convertToType))
     {
         return new UnaryExpression(unaryType, operand, method.ReturnType, method);
     }
     // check for lifted call
     if ((TypeUtils.IsNullableType(operand.Type) || TypeUtils.IsNullableType(convertToType)) &&
         ParameterIsAssignable(pms[0], TypeUtils.GetNonNullableType(operand.Type)) &&
         TypeUtils.AreEquivalent(method.ReturnType, TypeUtils.GetNonNullableType(convertToType)))
     {
         return new UnaryExpression(unaryType, operand, convertToType, method);
     }
     throw Error.OperandTypesDoNotMatchParameters(unaryType, method.Name);
 }
Esempio n. 8
0
        private static UnaryExpression GetMethodBasedUnaryOperator(ExpressionType unaryType, Expression operand, MethodInfo method)
        {
            System.Diagnostics.Debug.Assert(method != null);
            ValidateOperator(method);
            ParameterInfo[] pms = method.GetParametersCached();
            if (pms.Length != 1)
                throw Error.IncorrectNumberOfMethodCallArguments(method);
            if (ParameterIsAssignable(pms[0], operand.Type))
            {
                ValidateParamswithOperandsOrThrow(pms[0].ParameterType, operand.Type, unaryType, method.Name);
                return new UnaryExpression(unaryType, operand, method.ReturnType, method);
            }
            // check for lifted call
            if (TypeUtils.IsNullableType(operand.Type) &&
                ParameterIsAssignable(pms[0], TypeUtils.GetNonNullableType(operand.Type)) &&
                method.ReturnType.GetTypeInfo().IsValueType && !TypeUtils.IsNullableType(method.ReturnType))
            {
                return new UnaryExpression(unaryType, operand, TypeUtils.GetNullableType(method.ReturnType), method);
            }

            throw Error.OperandTypesDoNotMatchParameters(unaryType, method.Name);
        }
        private static void ValidateGetAwaiterMethod(Type operandType, MethodInfo getAwaiterMethod)
        {
            ValidateMethodInfo(getAwaiterMethod);

            // NB: We don't check whether the name of the method is GetAwaiter, just like we don't check the name of
            //     operator op_* methods in Binary and Unary node factories in LINQ. We could tighten this, but there
            //     is no harm in letting an advanced used specify another method that obeys to the awaiter pattern
            //     other than the predescribed method name. The C# compiler will always specify the MethodInfo in the
            //     emitted factory call.

            var getAwaiterParams = getAwaiterMethod.GetParametersCached();

            if (getAwaiterMethod.IsStatic)
            {
                if (getAwaiterParams.Length != 1)
                {
                    throw Error.GetAwaiterShouldTakeZeroParameters();
                }

                var firstParam = getAwaiterParams[0];
                if (!TypeUtils.AreReferenceAssignable(firstParam.ParameterType, operandType))
                {
                    throw LinqError.ExpressionTypeDoesNotMatchParameter(operandType, firstParam.ParameterType);
                }
            }
            else
            {
                if (getAwaiterParams.Length != 0)
                {
                    throw Error.GetAwaiterShouldTakeZeroParameters();
                }

                if (getAwaiterMethod.IsGenericMethod)
                {
                    throw Error.GetAwaiterShouldNotBeGeneric();
                }
            }

            var returnType = getAwaiterMethod.ReturnType;

            if (returnType == typeof(void) || returnType.IsByRef || returnType.IsPointer)
            {
                throw Error.GetAwaiterShouldReturnAwaiterType();
            }
        }
        public static IndexCSharpExpression Index(Expression instance, MethodInfo indexer, IEnumerable<Expression> arguments)
        {
            ContractUtils.RequiresNotNull(indexer, nameof(indexer));

            var property = GetProperty(indexer);
            return IndexCore(instance, property, indexer, indexer.GetParametersCached(), arguments);
        }
Esempio n. 11
0
 public static CallInstruction Create(MethodInfo info)
 {
     return Create(info, info.GetParametersCached());
 }