private bool TryProcessPredicatelessAny(MethodCallExpression methodCallExpression, ScriptParameterDictionary parameters, out string result) { var invokedMethod = methodCallExpression.Method; if (invokedMethod.IsGenericMethod) { invokedMethod = invokedMethod.GetGenericMethodDefinition(); } if (invokedMethod == AnyExtensionWithoutPredicate) { // Since extensins are static, we must pass the first method invocation argument as the expression, // not the methodCallExpression.Object (because that is null). var ownerExpressionString = _expressionProcessorPipeline.ProcessExpression(methodCallExpression.Arguments[0], parameters); if (IsInvokedOnDictionary(methodCallExpression)) { result = $"Object.keys({ownerExpressionString}).length > 0"; return(true); } result = $"{ownerExpressionString}.length > 0"; return(true); } result = default; return(false); }
public bool TryProcess(Expression expression, ScriptParameterDictionary parameters, out string result) { if (expression == null) { throw new ArgumentNullException(nameof(expression)); } if (parameters == null) { throw new ArgumentNullException(nameof(parameters)); } if (expression is ConditionalExpression conditionalExpression) { var test = _expressionProcessorPipeline.ProcessExpression(conditionalExpression.Test, parameters); var ifTrue = _expressionProcessorPipeline.ProcessExpression(conditionalExpression.IfTrue, parameters); var ifFalse = _expressionProcessorPipeline.ProcessExpression(conditionalExpression.IfFalse, parameters); result = $"({test} ? {ifTrue} : {ifFalse})"; return(true); } result = default; return(false); }
public bool TryProcess(MemberExpression memberExpression, ScriptParameterDictionary parameters, out string result) { if (memberExpression == null) { throw new ArgumentNullException(nameof(memberExpression)); } if (parameters == null) { throw new ArgumentNullException(nameof(parameters)); } // TODO: Tests if (memberExpression.Member is PropertyInfo propertyInfo) { if (IsDictionaryCountAccess(propertyInfo)) { // Dictionaries are mapped to object literals based on their keys when they are serialized to JSON, // so we can't use the .length as we would with a regular collection. But there are as many items // in a dictionary as there are keys, so we need find the number of keys to resolve the expression. var ownerExpressionString = _expressionProcessorPipeline.ProcessExpression(memberExpression.Expression, parameters); // TODO: Check whether RavenDB provides a magic property for Dictionary key collections. result = $"Object.keys({ownerExpressionString}).length"; return(true); } if (IsDictionaryKeysCollectionCountAccess(memberExpression, propertyInfo)) { // We need to navigate one level further up (i.e. doc.MyDictionary.Keys becomes doc.MyDictionary) // because dictionaries are mapped to object literals with the respective keys when they become // JSON, so the Keys segment becomes invalid. var parentMemberExpression = ((MemberExpression)memberExpression.Expression).Expression; var ownerExpressionString = _expressionProcessorPipeline.ProcessExpression(parentMemberExpression, parameters); // TODO: Check whether RavenDB provides a magic property for Dictionary key collections. result = $"Object.keys({ownerExpressionString}).length"; return(true); } if (IsDictionaryValuesCollectionCountAccess(memberExpression, propertyInfo)) { // We need to navigate one level further up (i.e. doc.MyDictionary.Values becomes doc.MyDictionary) // because dictionaries are mapped to object literals with the respective keys when they become // JSON, so the Values segment becomes invalid. var parentMemberExpression = ((MemberExpression)memberExpression.Expression).Expression; var ownerExpressionString = _expressionProcessorPipeline.ProcessExpression(parentMemberExpression, parameters); // TODO: Check whether RavenDB provides a magic property for Dictionary value collections. result = $"Object.values({ownerExpressionString}).length"; return(true); } } result = default; return(false); }
public bool TryProcess(MethodCallExpression methodCallExpression, ScriptParameterDictionary parameters, out string result) { if (methodCallExpression == null) { throw new ArgumentNullException(nameof(methodCallExpression)); } if (parameters == null) { throw new ArgumentNullException(nameof(parameters)); } if (!integralTypes.Contains(methodCallExpression.Method.DeclaringType)) { result = default; return(false); } if (methodCallExpression.Method.Name == ToStringMethodName) { var ownerExpressionString = _expressionProcessorPipeline.ProcessExpression(methodCallExpression.Object, parameters); result = $"{ownerExpressionString}.toString()"; return(true); } result = default; return(false); }
public bool TryProcess(Expression expression, ScriptParameterDictionary parameters, out string result) { if (expression == null) { throw new ArgumentNullException(nameof(expression)); } if (parameters == null) { throw new ArgumentNullException(nameof(parameters)); } var lambdaExpression = expression as LambdaExpression; if (lambdaExpression == null) { result = default; return(false); } var parameterList = string.Join(", ", lambdaExpression.Parameters.Select(p => p.Name)); var body = _expressionProcessorPipeline.ProcessExpression(lambdaExpression.Body, parameters); // TODO: Consider whether "return" is always correct (technically we can return void stuff in JS but what if result = $"function({parameterList}) {{ return {body}; }}"; return(true); }
public bool TryProcess(MemberExpression memberExpression, ScriptParameterDictionary parameters, out string result) { if (memberExpression == null) { throw new ArgumentNullException(nameof(memberExpression)); } if (parameters == null) { throw new ArgumentNullException(nameof(parameters)); } if (memberExpression.Member is PropertyInfo propertyInfo) { var memberOwnerType = propertyInfo.DeclaringType; if (memberOwnerType.IsGenericType) { memberOwnerType = memberOwnerType.GetGenericTypeDefinition(); } if (memberOwnerType == NullableType) { if (propertyInfo.Name == "HasValue") { var ownerExpressionString = _expressionProcessorPipeline.ProcessExpression(memberExpression.Expression, parameters); result = $"({ownerExpressionString} != null)"; return(true); } if (propertyInfo.Name == "Value") { var ownerExpressionString = _expressionProcessorPipeline.ProcessExpression(memberExpression.Expression, parameters); result = $"{ownerExpressionString}"; return(true); } } } result = default; return(false); }
public void BinaryOps_Integers_Assign() { var memberExpression = LambdaExpression(doc => doc.SomeInt).Body; var constantExpression = Expression.Constant(1); var expression = Expression.Assign(memberExpression, constantExpression); var parameters = new ScriptParameterDictionary(); var result = expressionProcessorPipeline.ProcessExpression(expression, parameters); Assert.AreEqual( "(doc.SomeInt = args.__param1)", result); Assert.AreEqual(1, parameters.Count); Assert.AreEqual(1, parameters["__param1"]); }
public string CreateScriptCondition <TDocument>(Expression <Func <TDocument, bool> > condition, ScriptParameterDictionary parameters) { if (condition == null) { throw new ArgumentNullException(nameof(condition)); } if (parameters == null) { throw new ArgumentNullException(nameof(parameters)); } var normalizedConditionBody = GetNormalizedConditionBody(condition); return(_expressionProcessorPipeline.ProcessExpression(normalizedConditionBody, parameters)); }
public bool TryProcess(MemberExpression memberExpression, ScriptParameterDictionary parameters, out string result) { if (memberExpression == null) { throw new ArgumentNullException(nameof(memberExpression)); } if (parameters == null) { throw new ArgumentNullException(nameof(parameters)); } var ownerExpressionString = _expressionProcessorPipeline.ProcessExpression(memberExpression.Expression, parameters); // TODO: Consider cases when the property is called differently in the document than in the object model. Check out // Raven.Client.Documents.Linq.LinqPathProvider, maybe that can solve it out-of-the-box. result = $"{ownerExpressionString}.{memberExpression.Member.Name}"; return(true); }
public string CreateScriptBody(PropertyUpdateDescriptor[] propertyUpdates, ScriptParameterDictionary parameters) { var assignmentScripts = new List <string>(propertyUpdates.Length); foreach (var propertyUpdate in propertyUpdates) { var transformedMemberSelector = GetNormalizedExpression(propertyUpdate.MemberSelector); var assignmentExpression = Expression.Assign( transformedMemberSelector, Expression.Constant(propertyUpdate.NewValue)); assignmentScripts.Add(_expressionProcessorPipeline.ProcessExpression(assignmentExpression, parameters)); } return(string.Join( "\n", assignmentScripts.Select(script => $"\t{script};"))); }
public bool TryProcess(MemberExpression memberExpression, ScriptParameterDictionary parameters, out string result) { if (memberExpression == null) { throw new ArgumentNullException(nameof(memberExpression)); } if (parameters == null) { throw new ArgumentNullException(nameof(parameters)); } if (memberExpression.Member is PropertyInfo propertyInfo && propertyInfo == NonStatic_Length) { var ownerExpressionString = _expressionProcessorPipeline.ProcessExpression(memberExpression.Expression, parameters); result = $"{ownerExpressionString}.length"; return(true); } result = default; return(false); }
public bool TryProcess(MemberExpression memberExpression, ScriptParameterDictionary parameters, out string result) { if (memberExpression == null) { throw new ArgumentNullException(nameof(memberExpression)); } if (parameters == null) { throw new ArgumentNullException(nameof(parameters)); } // TODO: Tests if (memberExpression.Member is PropertyInfo propertyInfo && IsSpeciallyTreatedCountPropertyAccess(propertyInfo)) { var ownerExpressionString = _expressionProcessorPipeline.ProcessExpression(memberExpression.Expression, parameters); result = $"{ownerExpressionString}.length"; return(true); } result = default; return(false); }
public bool TryProcess(Expression expression, ScriptParameterDictionary parameters, out string result) { if (expression == null) { throw new ArgumentNullException(nameof(expression)); } if (parameters == null) { throw new ArgumentNullException(nameof(parameters)); } var binaryExpression = expression as BinaryExpression; if (binaryExpression == null) { result = default; return(false); } var operation = binaryExpression.NodeType; var left = _expressionProcessorPipeline.ProcessExpression(binaryExpression.Left, parameters); var right = _expressionProcessorPipeline.ProcessExpression(binaryExpression.Right, parameters); switch (operation) { case ExpressionType.Add: case ExpressionType.AddChecked: result = $"({left} + {right})"; return(true); case ExpressionType.And: result = $"({left} & {right})"; return(true); case ExpressionType.AndAlso: result = $"({left} && {right})"; return(true); case ExpressionType.ArrayIndex: result = $"{left}[{right}]"; return(true); case ExpressionType.Coalesce: result = $"({left} != null ? {left} : {right})"; return(true); case ExpressionType.Divide: result = $"({left} / {right})"; return(true); case ExpressionType.Equal: result = $"({left} == {right})"; return(true); case ExpressionType.ExclusiveOr: result = $"({left} ^ {right})"; return(true); case ExpressionType.GreaterThan: result = $"({left} > {right})"; return(true); case ExpressionType.GreaterThanOrEqual: result = $"({left} >= {right})"; return(true); case ExpressionType.LessThan: result = $"({left} < {right})"; return(true); case ExpressionType.LessThanOrEqual: result = $"({left} <= {right})"; return(true); case ExpressionType.Modulo: result = $"({left} % {right})"; return(true); case ExpressionType.Multiply: case ExpressionType.MultiplyChecked: result = $"({left} * {right})"; return(true); case ExpressionType.NotEqual: result = $"({left} != {right})"; return(true); case ExpressionType.Or: result = $"({left} | {right})"; return(true); case ExpressionType.OrElse: result = $"({left} || {right})"; return(true); case ExpressionType.Subtract: case ExpressionType.SubtractChecked: result = $"({left} - {right})"; return(true); case ExpressionType.Assign: result = $"({left} = {right})"; return(true); case ExpressionType.Index: result = $"{left}[{right}]"; return(true); case ExpressionType.AddAssign: case ExpressionType.AddAssignChecked: result = $"({left} += {right})"; return(true); case ExpressionType.AndAssign: result = $"({left} &= {right})"; return(true); case ExpressionType.DivideAssign: result = $"({left} /= {right})"; return(true); case ExpressionType.ExclusiveOrAssign: result = $"({left} ^= {right})"; return(true); case ExpressionType.ModuloAssign: result = $"({left} %= {right})"; return(true); case ExpressionType.MultiplyAssign: case ExpressionType.MultiplyAssignChecked: result = $"({left} *= {right})"; return(true); case ExpressionType.OrAssign: result = $"({left} |= {right})"; return(true); case ExpressionType.SubtractAssign: case ExpressionType.SubtractAssignChecked: result = $"({left} -= {right})"; return(true); default: result = default; return(false); } }
public bool TryProcess(Expression expression, ScriptParameterDictionary parameters, out string result) { if (expression == null) { throw new ArgumentNullException(nameof(expression)); } if (parameters == null) { throw new ArgumentNullException(nameof(parameters)); } var unaryExpression = expression as UnaryExpression; if (unaryExpression == null) { result = default; return(false); } var operation = unaryExpression.NodeType; var operand = _expressionProcessorPipeline.ProcessExpression(unaryExpression.Operand, parameters); switch (operation) { case ExpressionType.ArrayLength: result = $"{operand}.length"; return(true); case ExpressionType.Convert: result = operand; return(true); case ExpressionType.Negate: result = $"-({operand})"; return(true); case ExpressionType.UnaryPlus: result = $"+({operand})"; return(true); case ExpressionType.Not: result = $"!({operand})"; return(true); case ExpressionType.Decrement: result = $"({operand} - 1)"; return(true); case ExpressionType.Increment: result = $"({operand} + 1)"; return(true); case ExpressionType.PreIncrementAssign: result = $"(++{operand})"; return(true); case ExpressionType.PreDecrementAssign: result = $"(--{operand})"; return(true); case ExpressionType.PostIncrementAssign: result = $"({operand}++)"; return(true); case ExpressionType.PostDecrementAssign: result = $"({operand}--)"; return(true); default: result = default; return(false); } }
private bool TryProcessStaticStringMethodInvocation(MethodCallExpression methodCallExpression, MethodInfo methodInfo, ScriptParameterDictionary parameters, out string result) { if (methodInfo == Static_IsNullOrEmpty) { var methodParameterExpression = methodCallExpression.Arguments[0]; var methodParameter = _expressionProcessorPipeline.ProcessExpression(methodParameterExpression, parameters); result = $"({methodParameter} == null || {methodParameter} == '')"; return(true); } else if (methodInfo == Static_IsNullOrWhiteSpace) { var methodParameterExpression = methodCallExpression.Arguments[0]; var methodParameter = _expressionProcessorPipeline.ProcessExpression(methodParameterExpression, parameters); result = $"({methodParameter} == null || {methodParameter}.trim() == '')"; return(true); } /* * else if (methodInfo == Static_Concat) * { * } * else if (methodInfo == Static_Join) * { * } */ result = null; return(false); }