private static void EnsureTokensAreValidInner(IEnumerable <FilterExpressionToken> tokens, ref int numberOfCalls)
        {
            numberOfCalls++;

            if (numberOfCalls > 10 * 1000)
            {
                throw new InternalJsonPathwayException(
                          "Number of calls to EnsureTokensAreValidInner exceeded max expected number of 10000, possible stack overflow or infinite loop.");
            }

            foreach (FilterExpressionToken t in tokens)
            {
                if (t is PrimitiveExpressionToken)
                {
                    throw new UnexpectedTokenException(t);
                }

                if (t is MethodCallExpressionToken tc)
                {
                    EnsureTokensAreValidInner(tc.Arguments, ref numberOfCalls);

                    MethodCallExpressionToken calleeMethod = tc.CalledOnExpression as MethodCallExpressionToken;
                    while (calleeMethod != null)
                    {
                        EnsureTokensAreValidInner(calleeMethod.Arguments, ref numberOfCalls);
                        calleeMethod = calleeMethod.CalledOnExpression as MethodCallExpressionToken;
                    }
                }
            }
        }
        private static void EnsureMethodArgumentsAreValid(MethodCallExpressionToken mct, ref int callCount)
        {
            callCount++;

            if (callCount > 10 * 1000)
            {
                throw new InternalJsonPathwayException(
                          "Number of calls to EnsureTokensAreValidInner exceeded max expected number of 10000, possible stack overflow or infinite loop.");
            }

            if (mct.CalledOnExpression is MethodCallExpressionToken inner1)
            {
                EnsureMethodArgumentsAreValid(inner1, ref callCount);
            }

            foreach (FilterExpressionToken arg in mct.Arguments)
            {
                if (arg is MethodCallExpressionToken inner2)
                {
                    EnsureMethodArgumentsAreValid(inner2, ref callCount);
                }
            }

            FilterExpressionToken prim = mct.Arguments.FirstOrDefault(x => x is PrimitiveExpressionToken);

            if (prim != null)
            {
                throw new UnexpectedTokenException((prim as PrimitiveExpressionToken).Token);
            }
        }
        private static List <FilterExpressionToken> ReplaceMethodCallsOnArrayAccess(List <FilterExpressionToken> tokens)
        {
            List <ArrayAccessExpressionToken> arrayTokens = tokens.Where(x => x is ArrayAccessExpressionToken).Cast <ArrayAccessExpressionToken>().ToList();
            List <FilterExpressionToken>      ret         = tokens.ToList();

            foreach (ArrayAccessExpressionToken at in arrayTokens)
            {
                int arrayIndex = ret.IndexOf(at);
                int dotIndex   = arrayIndex + 1;

                if (dotIndex < ret.Count - 4 && ret[dotIndex] is PrimitiveExpressionToken petDot && petDot.Token.IsSymbolToken('.'))
                {
                    int methodNameIndex = dotIndex + 1;

                    if (ret[methodNameIndex] is PrimitiveExpressionToken petMethodName && petMethodName.Token.IsPropertyToken())
                    {
                        PropertyToken propToken = petMethodName.Token.CastToPropertyToken();
                        if (propToken.Escaped)
                        {
                            throw new UnexpectedTokenException(propToken, "Expected method call on array element");
                        }
                        string methodName = propToken.StringValue;

                        int openGroupIndex = methodNameIndex + 1;

                        if (openGroupIndex < ret.Count && ret[openGroupIndex] is OpenGroupToken ogt)
                        {
                            FilterExpressionToken closed = ret.FirstOrDefault(x => x is CloseGroupToken cgt && cgt.GroupId == ogt.GroupId);

                            if (closed == null)
                            {
                                throw new ParsingException("Failed to find ) for ( at " + ogt.StartIndex);
                            }

                            List <FilterExpressionToken> args = new List <FilterExpressionToken>();

                            int startIndex = ret.IndexOf(ogt);
                            int endIndex   = ret.IndexOf(closed);

                            for (int i = startIndex + 1; i < endIndex; i++)
                            {
                                args.Add(ret[i]);
                            }

                            args = FormatAndValidateMethodArgumentTokens(args);

                            ret[arrayIndex] = new MethodCallExpressionToken(at, methodName, args.ToArray());

                            for (int i = arrayIndex + 1; i <= endIndex; i++)
                            {
                                ret[i] = null;
                            }
                        }
                    }
                }
            }

            return(ret.Where(x => x != null).ToList());
        }
        private static List <FilterExpressionToken> ReplaceMethodCallsOnMethodsInner(List <FilterExpressionToken> tokens, ref int callCount, out int replacedCount)
        {
            callCount++;
            replacedCount = 0;

            if (callCount > 10 * 1000)
            {
                throw new InternalJsonPathwayException(
                          "Number of calls to ReplaceMethodCallsOnMethodsInner exceeded max expected number of 10000, possible stack overflow or infinite loop.");
            }

            List <FilterExpressionToken> ret = tokens.ToList();

            foreach (MethodCallExpressionToken mc in tokens.Where(x => x is MethodCallExpressionToken))
            {
                int index = ret.IndexOf(mc);

                if (index < ret.Count - 4 && ret[index + 1] is PrimitiveExpressionToken pet1 && pet1.Token.IsSymbolToken('.') &&
                    ret[index + 2] is PrimitiveExpressionToken pet2 && pet2.Token.IsPropertyToken() &&
                    ret[index + 3] is OpenGroupToken)
                {
                    OpenGroupToken        open  = ret[index + 3] as OpenGroupToken;
                    FilterExpressionToken close = ret.Single(x => x is CloseGroupToken cgt && cgt.GroupId == open.GroupId);

                    string methodName = (ret[index + 2] as PrimitiveExpressionToken).Token.CastToPropertyToken().StringValue;

                    List <FilterExpressionToken> args = new List <FilterExpressionToken>();

                    int closeIndex = ret.IndexOf(close);
                    for (int i = index + 4; i < closeIndex; i++)
                    {
                        args.Add(ret[i]);
                    }
                    args = FormatAndValidateMethodArgumentTokens(args);

                    ret[index] = new MethodCallExpressionToken(mc, methodName, args.ToArray());

                    for (int i = index + 1; i <= closeIndex; i++)
                    {
                        ret[i] = null;
                    }

                    replacedCount++;
                }
            }

            return(ret.Where(x => x != null).ToList());
        }
        private static List <FilterExpressionToken> ReplaceMethodCallsOnProps(List <FilterExpressionToken> tokens)
        {
            List <PropertyExpressionToken> propTokens = tokens.Where(x => x is PropertyExpressionToken).Cast <PropertyExpressionToken>().ToList();
            List <FilterExpressionToken>   ret        = tokens.ToList();

            foreach (PropertyExpressionToken pt in propTokens)
            {
                int nextIndex = ret.IndexOf(pt) + 1;
                if (nextIndex < ret.Count && ret[nextIndex] is OpenGroupToken)
                {
                    OpenGroupToken  open  = ret[nextIndex] as OpenGroupToken;
                    CloseGroupToken close = ret.First(x => x is CloseGroupToken cgt && cgt.GroupId == open.GroupId) as CloseGroupToken;

                    int openIndex  = ret.IndexOf(open);
                    int closeIndex = ret.IndexOf(close);

                    List <FilterExpressionToken> args = new List <FilterExpressionToken>();
                    for (int i = openIndex + 1; i < closeIndex; i++)
                    {
                        args.Add(ret[i]);
                    }
                    args = FormatAndValidateMethodArgumentTokens(args);

                    string methodName;
                    PropertyExpressionToken allButLast = pt.AllButLast(out methodName);
                    int ptIndex = ret.IndexOf(pt);

                    ret[ptIndex] = new MethodCallExpressionToken(allButLast, methodName, args.ToArray());

                    List <FilterExpressionToken> toRemove = new List <FilterExpressionToken>();

                    for (int i = ptIndex + 1; i <= closeIndex; i++)
                    {
                        ret[i] = null;
                    }
                }
            }

            return(ret.Where(x => x != null).ToList());
        }
예제 #6
0
        public MethodCallFilterSubExpression(MethodCallExpressionToken token)
        {
            if (token == null)
            {
                throw new ArgumentNullException(nameof(token));
            }

            CalledOnExpression = FilterParser.Parse(new List <FilterExpressionToken> {
                token.CalledOnExpression
            });
            MethodName = token.MethodName;

            List <FilterSubExpression> args = new List <FilterSubExpression>();

            foreach (FilterExpressionToken a in token.Arguments)
            {
                args.Add(FilterParser.Parse(new List <FilterExpressionToken> {
                    a
                }));
            }

            Arguments = args;
        }
        private static List <FilterExpressionToken> ReplaceMethodCallsOnConstants(List <FilterExpressionToken> tokens)
        {
            List <FilterExpressionToken> ret = tokens.ToList();

            foreach (ConstantBaseExpressionToken ct in tokens.Where(x => x is ConstantBaseExpressionToken))
            {
                int index = ret.IndexOf(ct);

                if (index < ret.Count - 4 && ret[index + 1] is PrimitiveExpressionToken pet1 && pet1.Token.IsSymbolToken('.') &&
                    ret[index + 2] is PrimitiveExpressionToken pet2 && pet2.Token.IsPropertyToken() &&
                    ret[index + 3] is OpenGroupToken)
                {
                    OpenGroupToken        open  = ret[index + 3] as OpenGroupToken;
                    FilterExpressionToken close = ret.Single(x => x is CloseGroupToken cgt && cgt.GroupId == open.GroupId);

                    string methodName = (ret[index + 2] as PrimitiveExpressionToken).Token.CastToPropertyToken().StringValue;

                    List <FilterExpressionToken> args = new List <FilterExpressionToken>();

                    int closeIndex = ret.IndexOf(close);
                    for (int i = index + 4; i < closeIndex; i++)
                    {
                        args.Add(ret[i]);
                    }
                    args = FormatAndValidateMethodArgumentTokens(args);

                    ret[index] = new MethodCallExpressionToken(ct, methodName, args.ToArray());

                    for (int i = index + 1; i <= closeIndex; i++)
                    {
                        ret[i] = null;
                    }
                }
            }

            return(ret.Where(x => x != null).ToList());
        }