public static bool TryBind(SyntaxTreeNode node, BindingContext bindingContext, TypeDescription expectedType, out Expression boundExpression, out Exception bindingError) { if (node == null) { throw new ArgumentNullException("node"); } if (bindingContext == null) { throw new ArgumentNullException("bindingContext"); } if (expectedType == null) { throw new ArgumentNullException("expectedType"); } if (TryBindMethodCall(node, bindingContext, expectedType, out boundExpression, out bindingError)) { return(true); } var targetNode = node.GetExpression(throwOnError: true); var arguments = node.GetArguments(throwOnError: false); var target = default(Expression); if (AnyBinder.TryBind(targetNode, bindingContext, TypeDescription.ObjectType, out target, out bindingError) == false) { return(false); } Debug.Assert(target != null, "target != null"); var typeDescription = TypeDescription.GetTypeDescription(target.Type); if (typeDescription.IsDelegate == false) { bindingError = new ExpressionParserException(string.Format(Properties.Resources.EXCEPTION_BIND_UNABLETOINVOKENONDELEG, target.Type), node); return(false); } var methodDescription = typeDescription.GetMembers(Constants.DELEGATE_INVOKE_NAME).FirstOrDefault(m => m.IsMethod && !m.IsStatic); if (methodDescription == null) { throw new MissingMethodException(string.Format(Properties.Resources.EXCEPTION_BIND_MISSINGMETHOD, target.Type.FullName, Constants.DELEGATE_INVOKE_NAME)); } var expressionQuality = 0.0f; if (methodDescription.TryMakeCall(target, arguments, bindingContext, out boundExpression, out expressionQuality) == false) { bindingError = new ExpressionParserException(string.Format(Properties.Resources.EXCEPTION_BIND_UNABLETOBINDDELEG, target.Type, methodDescription), node); return(false); } return(true); }
public static bool TryBind(SyntaxTreeNode node, BindingContext bindingContext, TypeDescription expectedType, out Expression boundExpression, out Exception bindingError) { if (node == null) { throw new ArgumentNullException("node"); } if (bindingContext == null) { throw new ArgumentNullException("bindingContext"); } if (expectedType == null) { throw new ArgumentNullException("expectedType"); } boundExpression = null; bindingError = null; var newNode = node.GetNewExpression(throwOnError: true); var newExpression = default(Expression); if (AnyBinder.TryBind(newNode, bindingContext, TypeDescription.ObjectType, out newExpression, out bindingError) == false || newExpression is NewExpression == false) { if (bindingError == null) { bindingError = new ExpressionParserException(Properties.Resources.EXCEPTION_BIND_FAILEDTOBINDNEWEXPRESSION, node); } return(false); } var initializers = default(ElementInit[]); if (TryGetListInitializers(node, bindingContext, out initializers, out bindingError) == false) { if (bindingError == null) { bindingError = new ExpressionParserException(Properties.Resources.EXCEPTION_BIND_FAILEDTOBINDLISTINITIALIZERS, node); } return(false); } boundExpression = Expression.ListInit((NewExpression)newExpression, initializers); return(true); }
public static bool TryBind(SyntaxTreeNode node, BindingContext bindingContext, TypeDescription expectedType, out Expression boundExpression, out Exception bindingError) { if (node == null) { throw new ArgumentNullException("node"); } if (bindingContext == null) { throw new ArgumentNullException("bindingContext"); } if (expectedType == null) { throw new ArgumentNullException("expectedType"); } boundExpression = null; bindingError = null; var target = default(Expression); var targetNode = node.GetExpression(throwOnError: false); var propertyOrFieldName = node.GetPropertyOrFieldName(throwOnError: true); var useNullPropagation = node.GetUseNullPropagation(throwOnError: false); var targetType = default(Type); var isStatic = false; if (bindingContext.TryResolveType(targetNode, out targetType)) { target = null; isStatic = true; } else if (targetNode == null) { target = bindingContext.Global; targetType = target != null ? target.Type : null; isStatic = false; switch (propertyOrFieldName) { case Constants.VALUE_NULL_STRING: boundExpression = ExpressionUtils.NullConstant; return(true); case Constants.VALUE_TRUE_STRING: boundExpression = ExpressionUtils.TrueConstant; return(true); case Constants.VALUE_FALSE_STRING: boundExpression = ExpressionUtils.TrueConstant; return(false); default: if (bindingContext.TryGetParameter(propertyOrFieldName, out boundExpression)) { return(true); } break; } } else if (AnyBinder.TryBind(targetNode, bindingContext, TypeDescription.ObjectType, out target, out bindingError)) { Debug.Assert(target != null, "target != null"); targetType = target.Type; isStatic = false; } else { target = null; targetType = null; } if (target == null && targetType == null) { if (bindingError == null) { bindingError = new ExpressionParserException(string.Format(Properties.Resources.EXCEPTION_BIND_UNABLETORESOLVENAME, propertyOrFieldName), node); } return(false); } Debug.Assert(targetType != null, "type != null"); var targetTypeDescription = TypeDescription.GetTypeDescription(targetType); if (isStatic && targetTypeDescription.IsEnum) { var fieldMemberDescription = targetTypeDescription.GetMembers(propertyOrFieldName).FirstOrDefault(m => m.IsStatic); if (fieldMemberDescription == null) { bindingError = new ExpressionParserException(string.Format(Properties.Resources.EXCEPTION_BIND_UNABLETORESOLVEMEMBERONTYPE, propertyOrFieldName, targetType), node); return(false); } boundExpression = fieldMemberDescription.ConstantValueExpression; } else { foreach (var member in targetTypeDescription.GetMembers(propertyOrFieldName)) { if (member.IsStatic != isStatic || member.IsPropertyOrField == false) { continue; } if (member.TryMakeAccessor(target, out boundExpression)) { break; } } } if (boundExpression == null) { bindingError = new ExpressionParserException(string.Format(Properties.Resources.EXCEPTION_BIND_UNABLETORESOLVEMEMBERONTYPE, propertyOrFieldName, targetType), node); return(false); } if (useNullPropagation && isStatic) { bindingError = new ExpressionParserException(string.Format(Properties.Resources.EXCEPTION_BIND_UNABLETOAPPLYNULLCONDITIONALOPERATORONTYPEREF, targetType)); return(false); } if (useNullPropagation && targetTypeDescription.CanBeNull) { bindingContext.RegisterNullPropagationTarget(target); } return(true); }
public static bool TryBind(SyntaxTreeNode node, BindingContext bindingContext, TypeDescription expectedType, out Expression boundExpression, out Exception bindingError) { if (node == null) { throw new ArgumentNullException("node"); } if (bindingContext == null) { throw new ArgumentNullException("bindingContext"); } if (expectedType == null) { throw new ArgumentNullException("expectedType"); } boundExpression = null; bindingError = null; var target = default(Expression); var arguments = node.GetArguments(throwOnError: false); var methodName = node.GetMethodName(throwOnError: true); var useNullPropagation = node.GetUseNullPropagation(throwOnError: false); var methodMember = default(MemberDescription); if (bindingContext.TryResolveMember(methodName, out methodMember)) { if (methodMember.IsMethod == false) { bindingError = new ExpressionParserException(string.Format(Properties.Resources.EXCEPTION_BIND_CALLMEMBERISNOTMETHOD, methodMember.Name, methodMember.DeclaringType), node); return(false); } var targetNode = node.GetExpression(throwOnError: true); if (AnyBinder.TryBind(targetNode, bindingContext, TypeDescription.ObjectType, out target, out bindingError) == false) { return(false); } float methodQuality; if (methodMember.TryMakeCall(target, arguments, bindingContext, out boundExpression, out methodQuality) == false) { bindingError = new ExpressionParserException(string.Format(Properties.Resources.EXCEPTION_BIND_UNABLETOBINDMETHOD, methodMember.Name, target.Type, arguments.Count), node); return(false); } return(true); } var methodRef = default(TypeReference); if (BindingContext.TryGetMethodReference(methodName, out methodRef) == false) { bindingError = new ExpressionParserException(string.Format(Properties.Resources.EXCEPTION_BIND_UNABLETORESOLVENAME, methodName), node); return(false); } var targetType = default(Type); if (TryBindTarget(node, bindingContext, out target, out targetType, out bindingError) == false) { return(false); } var isStatic = target == null; var selectedMethodQuality = MemberDescription.QUALITY_INCOMPATIBLE; var hasGenericParameters = methodRef.IsGenericType; var genericArguments = default(Type[]); if (hasGenericParameters) { genericArguments = new Type[methodRef.TypeArguments.Count]; for (var i = 0; i < genericArguments.Length; i++) { var typeArgument = methodRef.TypeArguments[i]; if (bindingContext.TryResolveType(typeArgument, out genericArguments[i]) == false) { bindingError = new ExpressionParserException(string.Format(Properties.Resources.EXCEPTION_BIND_UNABLETORESOLVETYPE, typeArgument), node); return(false); } } } var targetTypeDescription = TypeDescription.GetTypeDescription(targetType); var foundMethod = default(MethodInfo); foreach (var memberDescription in targetTypeDescription.GetMembers(methodRef.Name)) { if (memberDescription.IsMethod == false) { continue; } var methodDescription = memberDescription; var method = (MethodInfo)memberDescription; foundMethod = foundMethod ?? method; if (method.IsStatic != isStatic || method.IsGenericMethod != hasGenericParameters) { continue; } if (hasGenericParameters && memberDescription.GenericArgumentsCount != methodRef.TypeArguments.Count) { continue; } if (hasGenericParameters) { try { methodDescription = methodDescription.MakeGenericMethod(genericArguments); method = methodDescription; } catch (ArgumentException exception) { bindingError = exception; continue; /* An element of typeArguments does not satisfy the constraints specified for the corresponding type parameter of the current generic method definition. */ } } var methodQuality = 0.0f; var methodCallExpression = default(Expression); if (methodDescription.TryMakeCall(target, arguments, bindingContext, out methodCallExpression, out methodQuality) == false) { continue; } if (float.IsNaN(methodQuality) || methodQuality <= selectedMethodQuality) { continue; } boundExpression = methodCallExpression; selectedMethodQuality = methodQuality; if (Math.Abs(methodQuality - MemberDescription.QUALITY_EXACT_MATCH) < float.Epsilon) { break; // best match } } if (bindingError != null) { return(false); } if (boundExpression == null) { if (foundMethod != null) { bindingError = new ExpressionParserException(string.Format(Properties.Resources.EXCEPTION_BIND_UNABLETOBINDMETHOD, methodRef.Name, targetType, arguments.Count), node); } else { bindingError = new ExpressionParserException(string.Format(Properties.Resources.EXCEPTION_BIND_UNABLETOBINDCALL, methodRef.Name, targetType, arguments.Count), node); } return(false); } if (useNullPropagation && target == null) { bindingError = new ExpressionParserException(string.Format(Properties.Resources.EXCEPTION_BIND_UNABLETOAPPLYNULLCONDITIONALOPERATORONTYPEREF, targetType)); return(false); } if (useNullPropagation && targetTypeDescription.CanBeNull) { bindingContext.RegisterNullPropagationTarget(target); } if (targetTypeDescription.IsAssignableFrom(typeof(Type)) && bindingContext.IsKnownType(typeof(Type)) == false && (bindingContext.IsKnownType(targetType) == false || methodRef.Name.Equals("InvokeMember", StringComparison.Ordinal))) { bindingError = new ExpressionParserException(string.Format(Properties.Resources.EXCEPTION_BIND_RESTRICTED_MEMBER_INVOCATION, methodName, targetType, typeof(ITypeResolver)), node); return(false); } return(true); }
public static bool TryBind(SyntaxTreeNode node, BindingContext bindingContext, TypeDescription expectedType, out Expression boundExpression, out Exception bindingError) { boundExpression = null; bindingError = null; var useNullPropagation = node.GetUseNullPropagation(throwOnError: false); var arguments = node.GetArguments(throwOnError: true); var targetNode = node.GetExpression(throwOnError: true); var target = default(Expression); if (AnyBinder.TryBind(targetNode, bindingContext, TypeDescription.ObjectType, out target, out bindingError) == false) { return(false); } Debug.Assert(target != null, "target != null"); var targetTypeDescription = TypeDescription.GetTypeDescription(target.Type); if (target.Type.IsArray) { var indexType = TypeDescription.Int32Type; var indexingExpressions = new Expression[arguments.Count]; for (var i = 0; i < indexingExpressions.Length; i++) { var argument = default(SyntaxTreeNode); if (arguments.TryGetValue(i, out argument) == false) { bindingError = new ExpressionParserException(string.Format(Resources.EXCEPTION_BIND_MISSINGMETHODPARAMETER, i), node); return(false); } if (AnyBinder.TryBindInNewScope(argument, bindingContext, indexType, out indexingExpressions[i], out bindingError) == false) { return(false); } Debug.Assert(indexingExpressions[i] != null, "indexingExpressions[i] != null"); } try { if (indexingExpressions.Length == 1) { boundExpression = Expression.ArrayIndex(target, indexingExpressions[0]); } else { boundExpression = Expression.ArrayIndex(target, indexingExpressions); } } catch (Exception exception) { bindingError = new ExpressionParserException(exception.Message, exception, node); return(false); } } else { var selectedIndexerQuality = MemberDescription.QUALITY_INCOMPATIBLE; foreach (var indexer in targetTypeDescription.Indexers) { var indexerQuality = MemberDescription.QUALITY_INCOMPATIBLE; var indexerCall = default(Expression); if (indexer.TryMakeCall(target, arguments, bindingContext, out indexerCall, out indexerQuality) == false) { continue; } if (indexerQuality <= selectedIndexerQuality) { continue; } boundExpression = indexerCall; selectedIndexerQuality = indexerQuality; } } if (boundExpression == null) { bindingError = new ExpressionParserException(string.Format(Resources.EXCEPTION_BIND_UNABLETOBINDINDEXER, target.Type), node); return(false); } if (useNullPropagation && targetTypeDescription.CanBeNull) { bindingContext.RegisterNullPropagationTarget(target); } return(true); }
public static bool TryBindMethodCall(SyntaxTreeNode node, BindingContext bindingContext, TypeDescription expectedType, out Expression boundExpression, out Exception bindingError) { if (node == null) { throw new ArgumentNullException("node"); } if (bindingContext == null) { throw new ArgumentNullException("bindingContext"); } if (expectedType == null) { throw new ArgumentNullException("expectedType"); } // bindingError could return null from this method bindingError = null; boundExpression = null; var methodNameNode = node.GetExpression(throwOnError: true); var methodNameNodeType = methodNameNode.GetExpressionType(throwOnError: true); if (methodNameNodeType != Constants.EXPRESSION_TYPE_PROPERTY_OR_FIELD && methodNameNodeType != Constants.EXPRESSION_TYPE_MEMBER_RESOLVE) { return(false); } var methodTargetNode = methodNameNode.GetExpression(throwOnError: false); var methodTarget = default(Expression); var type = default(Type); var typeReference = default(TypeReference); var isStatic = false; if (methodTargetNode == null && bindingContext.Global != null) { methodTarget = bindingContext.Global; type = methodTarget.Type; isStatic = false; } else if (methodTargetNode == null) { var methodName = methodNameNode.GetMemberName(throwOnError: false); bindingError = new ExpressionParserException(string.Format(Properties.Resources.EXCEPTION_BIND_UNABLETORESOLVENAME, methodName ?? "<unknown>"), node); return(false); } else if (BindingContext.TryGetTypeReference(methodTargetNode, out typeReference) && bindingContext.TryResolveType(typeReference, out type)) { isStatic = true; } else if (AnyBinder.TryBind(methodTargetNode, bindingContext, TypeDescription.ObjectType, out methodTarget, out bindingError)) { Debug.Assert(methodTarget != null, "methodTarget != null"); isStatic = false; type = methodTarget.Type; } else { if (typeReference != null && bindingError == null) { bindingError = new ExpressionParserException(string.Format(Properties.Resources.EXCEPTION_BIND_UNABLETORESOLVETYPE, typeReference), node); } return(false); } var methodRef = default(TypeReference); if (type == null || BindingContext.TryGetMethodReference(methodNameNode, out methodRef) == false) { return(false); } var typeDescription = TypeDescription.GetTypeDescription(type); foreach (var member in typeDescription.GetMembers(methodRef.Name)) { if (member.IsMethod == false || member.IsStatic != isStatic) { continue; } var callNode = new SyntaxTreeNode(new Dictionary <string, object> { { Constants.EXPRESSION_ATTRIBUTE, methodTarget ?? (object)type }, { Constants.ARGUMENTS_ATTRIBUTE, node.GetValueOrDefault(Constants.ARGUMENTS_ATTRIBUTE, default(object)) }, { Constants.METHOD_ATTRIBUTE, methodRef }, { Constants.USE_NULL_PROPAGATION_ATTRIBUTE, methodNameNode.GetValueOrDefault(Constants.USE_NULL_PROPAGATION_ATTRIBUTE, default(object)) }, { Constants.EXPRESSION_POSITION, methodNameNode.GetPosition(throwOnError: false) } }); return(CallBinder.TryBind(callNode, bindingContext, expectedType, out boundExpression, out bindingError)); } return(false); }