public async Task <JObject> Resolve(InvocationExpressionSyntax method, Dictionary <string, JObject> memberAccessValues, CancellationToken token)
        {
            var methodName   = "";
            int isTryingLinq = 0;

            try
            {
                JObject rootObject = null;
                var     expr       = method.Expression;
                if (expr is MemberAccessExpressionSyntax)
                {
                    var memberAccessExpressionSyntax = expr as MemberAccessExpressionSyntax;
                    rootObject = await Resolve(memberAccessExpressionSyntax.Expression.ToString(), token);

                    methodName = memberAccessExpressionSyntax.Name.ToString();
                }
                else if (expr is IdentifierNameSyntax)
                {
                    if (scopeCache.ObjectFields.TryGetValue("this", out JObject valueRet))
                    {
                        rootObject = await GetValueFromObject(valueRet, token);

                        methodName = expr.ToString();
                    }
                }

                if (rootObject != null)
                {
                    DotnetObjectId.TryParse(rootObject?["objectId"]?.Value <string>(), out DotnetObjectId objectId);
                    var typeIds = await sdbHelper.GetTypeIdFromObject(sessionId, int.Parse(objectId.Value), true, token);

                    int methodId = await sdbHelper.GetMethodIdByName(sessionId, typeIds[0], methodName, token);

                    var className = await sdbHelper.GetTypeNameOriginal(sessionId, typeIds[0], token);

                    if (methodId == 0) //try to search on System.Linq.Enumerable
                    {
                        if (linqTypeId == -1)
                        {
                            linqTypeId = await sdbHelper.GetTypeByName(sessionId, "System.Linq.Enumerable", token);
                        }
                        methodId = await sdbHelper.GetMethodIdByName(sessionId, linqTypeId, methodName, token);

                        if (methodId != 0)
                        {
                            foreach (var typeId in typeIds)
                            {
                                var genericTypeArgs = await sdbHelper.GetTypeParamsOrArgsForGenericType(sessionId, typeId, token);

                                if (genericTypeArgs.Count > 0)
                                {
                                    isTryingLinq = 1;
                                    methodId     = await sdbHelper.MakeGenericMethod(sessionId, methodId, genericTypeArgs, token);

                                    break;
                                }
                            }
                        }
                    }
                    if (methodId == 0)
                    {
                        var typeName = await sdbHelper.GetTypeName(sessionId, typeIds[0], token);

                        throw new Exception($"Method '{methodName}' not found in type '{typeName}'");
                    }
                    var commandParamsObj       = new MemoryStream();
                    var commandParamsObjWriter = new MonoBinaryWriter(commandParamsObj);
                    if (isTryingLinq == 0)
                    {
                        commandParamsObjWriter.WriteObj(objectId, sdbHelper);
                    }
                    if (method.ArgumentList != null)
                    {
                        commandParamsObjWriter.Write((int)method.ArgumentList.Arguments.Count + isTryingLinq);
                        if (isTryingLinq == 1)
                        {
                            commandParamsObjWriter.WriteObj(objectId, sdbHelper);
                        }
                        foreach (var arg in method.ArgumentList.Arguments)
                        {
                            if (arg.Expression is LiteralExpressionSyntax)
                            {
                                if (!await commandParamsObjWriter.WriteConst(sessionId, arg.Expression as LiteralExpressionSyntax, sdbHelper, token))
                                {
                                    return(null);
                                }
                            }
                            if (arg.Expression is IdentifierNameSyntax)
                            {
                                var argParm = arg.Expression as IdentifierNameSyntax;
                                if (!await commandParamsObjWriter.WriteJsonValue(sessionId, memberAccessValues[argParm.Identifier.Text], sdbHelper, token))
                                {
                                    return(null);
                                }
                            }
                        }
                        var retMethod = await sdbHelper.InvokeMethod(sessionId, commandParamsObj.ToArray(), methodId, "methodRet", token);

                        return(await GetValueFromObject(retMethod, token));
                    }
                }
                return(null);
            }
            catch (Exception)
            {
                throw new Exception($"Unable to evaluate method '{methodName}'");
            }
        }
Example #2
0
        public async Task <JObject> Resolve(ElementAccessExpressionSyntax elementAccess, Dictionary <string, JObject> memberAccessValues, JObject indexObject, CancellationToken token)
        {
            try
            {
                JObject rootObject = null;
                string  elementAccessStrExpression = elementAccess.Expression.ToString();
                rootObject = await Resolve(elementAccessStrExpression, token);

                if (rootObject == null)
                {
                    rootObject  = indexObject;
                    indexObject = null;
                }
                if (rootObject != null)
                {
                    string elementIdxStr;
                    int    elementIdx = 0;
                    // x[1] or x[a] or x[a.b]
                    if (indexObject == null)
                    {
                        if (elementAccess.ArgumentList != null)
                        {
                            var commandParamsObj       = new MemoryStream();
                            var commandParamsObjWriter = new MonoBinaryWriter(commandParamsObj);
                            foreach (var arg in elementAccess.ArgumentList.Arguments)
                            {
                                // e.g. x[1]
                                if (arg.Expression is LiteralExpressionSyntax)
                                {
                                    var argParm = arg.Expression as LiteralExpressionSyntax;
                                    elementIdxStr = argParm.ToString();
                                    int.TryParse(elementIdxStr, out elementIdx);
                                }

                                // e.g. x[a] or x[a.b]
                                if (arg.Expression is IdentifierNameSyntax)
                                {
                                    var argParm = arg.Expression as IdentifierNameSyntax;

                                    // x[a.b]
                                    memberAccessValues.TryGetValue(argParm.Identifier.Text, out indexObject);

                                    // x[a]
                                    if (indexObject == null)
                                    {
                                        indexObject = await Resolve(argParm.Identifier.Text, token);
                                    }
                                    elementIdxStr = indexObject["value"].ToString();
                                    int.TryParse(elementIdxStr, out elementIdx);
                                }
                            }
                        }
                    }
                    // e.g. x[a[0]], x[a[b[1]]] etc.
                    else
                    {
                        elementIdxStr = indexObject["value"].ToString();
                        int.TryParse(elementIdxStr, out elementIdx);
                    }
                    if (elementIdx >= 0)
                    {
                        DotnetObjectId.TryParse(rootObject?["objectId"]?.Value <string>(), out DotnetObjectId objectId);
                        switch (objectId.Scheme)
                        {
                        case "array":
                            rootObject["value"] = await sdbHelper.GetArrayValues(sessionId, int.Parse(objectId.Value), token);

                            return((JObject)rootObject["value"][elementIdx]["value"]);

                        case "object":
                            var typeIds = await sdbHelper.GetTypeIdFromObject(sessionId, int.Parse(objectId.Value), true, token);

                            int methodId = await sdbHelper.GetMethodIdByName(sessionId, typeIds[0], "ToArray", token);

                            var commandParamsObj       = new MemoryStream();
                            var commandParamsObjWriter = new MonoBinaryWriter(commandParamsObj);
                            commandParamsObjWriter.WriteObj(objectId, sdbHelper);
                            var toArrayRetMethod = await sdbHelper.InvokeMethod(sessionId, commandParamsObj.ToArray(), methodId, elementAccess.Expression.ToString(), token);

                            rootObject = await GetValueFromObject(toArrayRetMethod, token);

                            DotnetObjectId.TryParse(rootObject?["objectId"]?.Value <string>(), out DotnetObjectId arrayObjectId);
                            rootObject["value"] = await sdbHelper.GetArrayValues(sessionId, int.Parse(arrayObjectId.Value), token);

                            return((JObject)rootObject["value"][elementIdx]["value"]);

                        default:
                            throw new InvalidOperationException($"Cannot apply indexing with [] to an expression of type '{objectId.Scheme}'");
                        }
                    }
                }
                return(null);
            }
            catch (Exception ex)
            {
                var e = ex;
                throw new Exception($"Unable to evaluate method '{elementAccess}'");
            }
        }