Exemplo n.º 1
0
        public async Task <JObject> GetValueFromObject(JToken objRet, CancellationToken token)
        {
            if (objRet["value"]?["className"]?.Value <string>() == "System.Exception")
            {
                if (DotnetObjectId.TryParse(objRet?["value"]?["objectId"]?.Value <string>(), out DotnetObjectId objectId))
                {
                    var exceptionObject = await context.SdbAgent.GetObjectValues(objectId.Value, GetObjectCommandOptions.WithProperties | GetObjectCommandOptions.OwnProperties, token);

                    var exceptionObjectMessage = exceptionObject.FirstOrDefault(attr => attr["name"].Value <string>().Equals("_message"));
                    exceptionObjectMessage["value"]["value"] = objRet["value"]?["className"]?.Value <string>() + ": " + exceptionObjectMessage["value"]?["value"]?.Value <string>();
                    return(exceptionObjectMessage["value"]?.Value <JObject>());
                }
                return(objRet["value"]?.Value <JObject>());
            }

            if (objRet["value"]?.Value <JObject>() != null)
            {
                return(objRet["value"]?.Value <JObject>());
            }
            if (objRet["get"]?.Value <JObject>() != null)
            {
                if (DotnetObjectId.TryParse(objRet?["get"]?["objectIdValue"]?.Value <string>(), out DotnetObjectId objectId))
                {
                    using var commandParamsWriter = new MonoBinaryWriter();
                    commandParamsWriter.WriteObj(objectId, context.SdbAgent);
                    var ret = await context.SdbAgent.InvokeMethod(commandParamsWriter.GetParameterBuffer(), objRet["get"]["methodId"].Value <int>(), objRet["name"].Value <string>(), token);

                    return(await GetValueFromObject(ret, token));
                }
            }
            return(null);
        }
Exemplo n.º 2
0
        public async Task <JObject> GetValueFromObject(JToken objRet, CancellationToken token)
        {
            if (objRet["value"]?["className"]?.Value <string>() == "System.Exception")
            {
                if (DotnetObjectId.TryParse(objRet?["value"]?["objectId"]?.Value <string>(), out DotnetObjectId objectId))
                {
                    var exceptionObject = await proxy.SdbHelper.GetObjectValues(sessionId, int.Parse(objectId.Value), true, false, false, true, token);

                    var exceptionObjectMessage = exceptionObject.FirstOrDefault(attr => attr["name"].Value <string>().Equals("_message"));
                    exceptionObjectMessage["value"]["value"] = objRet["value"]?["className"]?.Value <string>() + ": " + exceptionObjectMessage["value"]?["value"]?.Value <string>();
                    return(exceptionObjectMessage["value"]?.Value <JObject>());
                }
                return(objRet["value"]?.Value <JObject>());
            }

            if (objRet["value"]?.Value <JObject>() != null)
            {
                return(objRet["value"]?.Value <JObject>());
            }
            if (objRet["get"]?.Value <JObject>() != null)
            {
                if (DotnetObjectId.TryParse(objRet?["get"]?["objectIdValue"]?.Value <string>(), out DotnetObjectId objectId))
                {
                    var commandParams       = new MemoryStream();
                    var commandParamsWriter = new MonoBinaryWriter(commandParams);
                    commandParamsWriter.WriteObj(objectId, proxy.SdbHelper);
                    var ret = await proxy.SdbHelper.InvokeMethod(sessionId, commandParams.ToArray(), objRet["get"]["methodId"].Value <int>(), objRet["name"].Value <string>(), token);

                    return(await GetValueFromObject(ret, token));
                }
            }
            return(null);
        }
Exemplo n.º 3
0
        public async Task <JObject> GetValueFromObject(JToken objRet, CancellationToken token)
        {
            if (objRet["value"]?["className"]?.Value <string>() == "System.Exception")
            {
                if (DotnetObjectId.TryParse(objRet?["value"]?["objectId"]?.Value <string>(), out DotnetObjectId objectId))
                {
                    GetMembersResult exceptionObject = await MemberObjectsExplorer.GetTypeMemberValues(context.SdbAgent, objectId, GetObjectCommandOptions.WithProperties | GetObjectCommandOptions.OwnProperties, token);

                    var exceptionObjectMessage = exceptionObject.FirstOrDefault(attr => attr["name"].Value <string>().Equals("_message"));
                    exceptionObjectMessage["value"]["value"] = objRet["value"]?["className"]?.Value <string>() + ": " + exceptionObjectMessage["value"]?["value"]?.Value <string>();
                    return(exceptionObjectMessage["value"]?.Value <JObject>());
                }
                return(objRet["value"]?.Value <JObject>());
            }

            if (objRet["value"]?.Value <JObject>() != null)
            {
                return(objRet["value"]?.Value <JObject>());
            }

            if (objRet["get"]?.Value <JObject>() != null &&
                DotnetObjectId.TryParse(objRet?["get"]?["objectId"]?.Value <string>(), out DotnetObjectId getterObjectId))
            {
                var ret = await context.SdbAgent.InvokeMethod(getterObjectId, token);

                return(await GetValueFromObject(ret, token));
            }
            return(null);
        }
Exemplo n.º 4
0
        internal async Task <JToken> TryGetVariableValue(MessageId msg_id, int scope_id, string expression, bool only_search_on_this, CancellationToken token)
        {
            JToken thisValue = null;
            var    context   = GetContext(msg_id);

            if (context.CallStack == null)
            {
                return(null);
            }

            if (TryFindVariableValueInCache(context, expression, only_search_on_this, out JToken obj))
            {
                return(obj);
            }

            var scope     = context.CallStack.FirstOrDefault(s => s.Id == scope_id);
            var live_vars = scope.Method.GetLiveVarsAt(scope.Location.CliLocation.Offset);
            //get_this
            var res = await SendMonoCommand(msg_id, MonoCommands.GetScopeVariables(scope.Id, live_vars), token);

            var scope_values = res.Value?["result"]?["value"]?.Values <JObject>()?.ToArray();

            thisValue = scope_values?.FirstOrDefault(v => v["name"]?.Value <string>() == "this");

            if (!only_search_on_this)
            {
                if (thisValue != null && expression == "this")
                {
                    return(thisValue);
                }

                var value = scope_values.SingleOrDefault(sv => sv["name"]?.Value <string>() == expression);
                if (value != null)
                {
                    return(value);
                }
            }

            //search in scope
            if (thisValue != null)
            {
                if (!DotnetObjectId.TryParse(thisValue["value"]["objectId"], out var objectId))
                {
                    return(null);
                }

                res = await SendMonoCommand(msg_id, MonoCommands.GetDetails(objectId), token);

                scope_values = res.Value?["result"]?["value"]?.Values <JObject>().ToArray();
                var foundValue = scope_values.FirstOrDefault(v => v["name"].Value <string>() == expression);
                if (foundValue != null)
                {
                    foundValue["fromThis"] = true;
                    context.LocalsCache[foundValue["name"].Value <string>()] = foundValue;
                    return(foundValue);
                }
            }
            return(null);
        }
Exemplo n.º 5
0
            private static string ConvertJSToCSharpLocalVariableAssignment(string idName, JToken variable)
            {
                string typeRet;
                object valueRet;
                JToken value   = variable["value"];
                string type    = variable["type"].Value <string>();
                string subType = variable["subtype"]?.Value <string>();

                switch (type)
                {
                case "string":
                {
                    var str = value?.Value <string>();
                    str      = str.Replace("\"", "\\\"");
                    valueRet = $"\"{str}\"";
                    typeRet  = "string";
                    break;
                }

                case "symbol":
                {
                    valueRet = $"'{value?.Value<char>()}'";
                    typeRet  = "char";
                    break;
                }

                case "number":
                    //casting to double and back to string would loose precision; so casting straight to string
                    valueRet = value?.Value <string>();
                    typeRet  = "double";
                    break;

                case "boolean":
                    valueRet = value?.Value <string>().ToLowerInvariant();
                    typeRet  = "bool";
                    break;

                case "object":
                    if (variable["subtype"]?.Value <string>() == "null")
                    {
                        (valueRet, typeRet) = GetNullObject(variable["className"]?.Value <string>());
                    }
                    else
                    {
                        if (!DotnetObjectId.TryParse(variable["objectId"], out DotnetObjectId objectId))
                        {
                            throw new Exception($"Internal error: Cannot parse objectId for var {idName}, with value: {variable}");
                        }

                        switch (objectId?.Scheme)
                        {
                        case "valuetype" when variable["isEnum"]?.Value <bool>() == true:
                            typeRet  = variable["className"]?.Value <string>();
                            valueRet = $"({typeRet}) {value["value"].Value<double>()}";
                            break;
Exemplo n.º 6
0
        // Checks Locals, followed by `this`
        public async Task <JObject> Resolve(string varName, CancellationToken token)
        {
            //has method calls
            if (varName.Contains('('))
            {
                return(null);
            }

            string[] parts      = varName.Split(".");
            JObject  rootObject = null;

            if (scopeCache.MemberReferences.TryGetValue(varName, out JObject ret))
            {
                return(ret);
            }

            if (scopeCache.ObjectFields.TryGetValue(varName, out JObject valueRet))
            {
                return(await GetValueFromObject(valueRet, token));
            }

            foreach (string part in parts)
            {
                string partTrimmed = part.Trim();
                if (partTrimmed == "")
                {
                    return(null);
                }
                if (rootObject != null)
                {
                    if (rootObject?["subtype"]?.Value <string>() == "null")
                    {
                        return(null);
                    }
                    if (DotnetObjectId.TryParse(rootObject?["objectId"]?.Value <string>(), out DotnetObjectId objectId))
                    {
                        var rootResObj = await proxy.RuntimeGetPropertiesInternal(sessionId, objectId, null, token);

                        var objRet = rootResObj.FirstOrDefault(objPropAttr => objPropAttr["name"].Value <string>() == partTrimmed);
                        if (objRet == null)
                        {
                            return(null);
                        }

                        rootObject = await GetValueFromObject(objRet, token);
                    }
                    continue;
                }
                if (scopeCache.Locals.Count == 0 && !localsFetched)
                {
                    Result scope_res = await proxy.GetScopeProperties(sessionId, scopeId, token);

                    if (scope_res.IsErr)
                    {
                        throw new Exception($"BUG: Unable to get properties for scope: {scopeId}. {scope_res}");
                    }
                    localsFetched = true;
                }
                if (scopeCache.Locals.TryGetValue(partTrimmed, out JObject obj))
                {
                    rootObject = obj["value"]?.Value <JObject>();
                }
                else if (scopeCache.Locals.TryGetValue("this", out JObject objThis))
                {
                    if (partTrimmed == "this")
                    {
                        rootObject = objThis?["value"].Value <JObject>();
                    }
                    else if (DotnetObjectId.TryParse(objThis?["value"]?["objectId"]?.Value <string>(), out DotnetObjectId objectId))
                    {
                        var rootResObj = await proxy.RuntimeGetPropertiesInternal(sessionId, objectId, null, token);

                        var objRet = rootResObj.FirstOrDefault(objPropAttr => objPropAttr["name"].Value <string>() == partTrimmed);
                        if (objRet != null)
                        {
                            rootObject = await GetValueFromObject(objRet, token);
                        }
                        else
                        {
                            return(null);
                        }
                    }
                }
            }
            scopeCache.MemberReferences[varName] = rootObject;
            return(rootObject);
        }
Exemplo n.º 7
0
        public async Task <JObject> Resolve(InvocationExpressionSyntax method, Dictionary <string, JObject> memberAccessValues, CancellationToken token)
        {
            var methodName = "";

            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 typeId = await proxy.SdbHelper.GetTypeIdFromObject(sessionId, int.Parse(objectId.Value), true, token);

                    int methodId = await proxy.SdbHelper.GetMethodIdByName(sessionId, typeId[0], methodName, token);

                    if (methodId == 0)
                    {
                        var typeName = await proxy.SdbHelper.GetTypeName(sessionId, typeId[0], token);

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

                        return(await GetValueFromObject(retMethod, token));
                    }
                }
                return(null);
            }
            catch (Exception)
            {
                throw new Exception($"Unable to evaluate method '{methodName}'");
            }
        }
Exemplo n.º 8
0
        protected override async Task <bool> AcceptCommand(MessageId id, string method, JObject args, CancellationToken token)
        {
            // Inspector doesn't use the Target domain or sessions
            // so we try to init immediately
            if (hideWebDriver && id == SessionId.Null)
            {
                await DeleteWebDriver(id, token);
            }

            if (!contexts.TryGetValue(id, out var context))
            {
                return(false);
            }

            switch (method)
            {
            case "Target.attachToTarget":
                {
                    var resp = await SendCommand(id, method, args, token);
                    await DeleteWebDriver(new SessionId(resp.Value["sessionId"]?.ToString()), token);

                    break;
                }

            case "Debugger.enable":
                {
                    var resp = await SendCommand(id, method, args, token);

                    context.DebuggerId = resp.Value["debuggerId"]?.ToString();

                    if (await IsRuntimeAlreadyReadyAlready(id, token))
                    {
                        await RuntimeReady(id, token);
                    }

                    SendResponse(id, resp, token);
                    return(true);
                }

            case "Debugger.getScriptSource":
            {
                var script = args?["scriptId"]?.Value <string>();
                return(await OnGetScriptSource(id, script, token));
            }

            case "Runtime.compileScript":
            {
                var exp = args?["expression"]?.Value <string>();
                if (exp.StartsWith("//dotnet:", StringComparison.Ordinal))
                {
                    OnCompileDotnetScript(id, token);
                    return(true);
                }
                break;
            }

            case "Debugger.getPossibleBreakpoints":
            {
                var resp = await SendCommand(id, method, args, token);

                if (resp.IsOk && resp.Value["locations"].HasValues)
                {
                    SendResponse(id, resp, token);
                    return(true);
                }

                var start = SourceLocation.Parse(args?["start"] as JObject);
                //FIXME support variant where restrictToFunction=true and end is omitted
                var end = SourceLocation.Parse(args?["end"] as JObject);
                if (start != null && end != null && await GetPossibleBreakpoints(id, start, end, token))
                {
                    return(true);
                }

                SendResponse(id, resp, token);
                return(true);
            }

            case "Debugger.setBreakpoint":
            {
                break;
            }

            case "Debugger.setBreakpointByUrl":
            {
                var resp = await SendCommand(id, method, args, token);

                if (!resp.IsOk)
                {
                    SendResponse(id, resp, token);
                    return(true);
                }

                var bpid      = resp.Value["breakpointId"]?.ToString();
                var locations = resp.Value["locations"]?.Values <object>();
                var request   = BreakpointRequest.Parse(bpid, args);

                // is the store done loading?
                var loaded = context.Source.Task.IsCompleted;
                if (!loaded)
                {
                    // Send and empty response immediately if not
                    // and register the breakpoint for resolution
                    context.BreakpointRequests[bpid] = request;
                    SendResponse(id, resp, token);
                }

                if (await IsRuntimeAlreadyReadyAlready(id, token))
                {
                    var store = await RuntimeReady(id, token);

                    Log("verbose", $"BP req {args}");
                    await SetBreakpoint(id, store, request, !loaded, token);
                }

                if (loaded)
                {
                    // we were already loaded so we should send a response
                    // with the locations included and register the request
                    context.BreakpointRequests[bpid] = request;
                    var result = Result.OkFromObject(request.AsSetBreakpointByUrlResponse(locations));
                    SendResponse(id, result, token);
                }
                return(true);
            }

            case "Debugger.removeBreakpoint":
            {
                await RemoveBreakpoint(id, args, token);

                break;
            }

            case "Debugger.resume":
            {
                await OnResume(id, token);

                break;
            }

            case "Debugger.stepInto":
            {
                return(await Step(id, StepKind.Into, token));
            }

            case "Debugger.stepOut":
            {
                return(await Step(id, StepKind.Out, token));
            }

            case "Debugger.stepOver":
            {
                return(await Step(id, StepKind.Over, token));
            }

            case "Debugger.evaluateOnCallFrame":
            {
                if (!DotnetObjectId.TryParse(args?["callFrameId"], out var objectId))
                {
                    return(false);
                }

                switch (objectId.Scheme)
                {
                case "scope":
                    return(await OnEvaluateOnCallFrame(id,
                                                       int.Parse(objectId.Value),
                                                       args?["expression"]?.Value <string>(), token));

                default:
                    return(false);
                }
            }

            case "Runtime.getProperties":
            {
                if (!DotnetObjectId.TryParse(args?["objectId"], out var objectId))
                {
                    break;
                }

                var result = await RuntimeGetProperties(id, objectId, args, token);

                SendResponse(id, result, token);
                return(true);
            }

            case "Runtime.releaseObject":
            {
                if (!(DotnetObjectId.TryParse(args["objectId"], out var objectId) && objectId.Scheme == "cfo_res"))
                {
                    break;
                }

                await SendMonoCommand(id, MonoCommands.ReleaseObject(objectId), token);

                SendResponse(id, Result.OkFromObject(new { }), token);
                return(true);
            }

            case "Debugger.setPauseOnExceptions":
            {
                string state = args["state"].Value <string>();
                await SendMonoCommand(id, MonoCommands.SetPauseOnExceptions(state), token);

                // Pass this on to JS too
                return(false);
            }

            // Protocol extensions
            case "DotnetDebugger.addSymbolServerUrl":
            {
                string url = args["url"]?.Value <string>();
                if (!String.IsNullOrEmpty(url) && !urlSymbolServerList.Contains(url))
                {
                    urlSymbolServerList.Add(url);
                }
                SendResponse(id, Result.OkFromObject(new { }), token);
                return(true);
            }

            case "DotnetDebugger.getMethodLocation":
            {
                Console.WriteLine("set-breakpoint-by-method: " + id + " " + args);

                var store = await RuntimeReady(id, token);

                string aname      = args["assemblyName"]?.Value <string>();
                string typeName   = args["typeName"]?.Value <string>();
                string methodName = args["methodName"]?.Value <string>();
                if (aname == null || typeName == null || methodName == null)
                {
                    SendResponse(id, Result.Err("Invalid protocol message '" + args + "'."), token);
                    return(true);
                }

                // GetAssemblyByName seems to work on file names
                var assembly = store.GetAssemblyByName(aname);
                if (assembly == null)
                {
                    assembly = store.GetAssemblyByName(aname + ".exe");
                }
                if (assembly == null)
                {
                    assembly = store.GetAssemblyByName(aname + ".dll");
                }
                if (assembly == null)
                {
                    SendResponse(id, Result.Err("Assembly '" + aname + "' not found."), token);
                    return(true);
                }

                var type = assembly.GetTypeByName(typeName);
                if (type == null)
                {
                    SendResponse(id, Result.Err($"Type '{typeName}' not found."), token);
                    return(true);
                }

                var methodInfo = type.Methods.FirstOrDefault(m => m.Name == methodName);
                if (methodInfo == null)
                {
                    // Maybe this is an async method, in which case the debug info is attached
                    // to the async method implementation, in class named:
                    //      `{type_name}/<method_name>::MoveNext`
                    methodInfo = assembly.TypesByName.Values.SingleOrDefault(t => t.FullName.StartsWith($"{typeName}/<{methodName}>"))?
                                 .Methods.FirstOrDefault(mi => mi.Name == "MoveNext");
                }

                if (methodInfo == null)
                {
                    SendResponse(id, Result.Err($"Method '{typeName}:{methodName}' not found."), token);
                    return(true);
                }

                var src_url = methodInfo.Assembly.Sources.Single(sf => sf.SourceId == methodInfo.SourceId).Url;
                SendResponse(id, Result.OkFromObject(new
                    {
                        result = new { line = methodInfo.StartLocation.Line, column = methodInfo.StartLocation.Column, url = src_url }
                    }), token);

                return(true);
            }

            case "Runtime.callFunctionOn":
            {
                if (!DotnetObjectId.TryParse(args["objectId"], out var objectId))
                {
                    return(false);
                }

                if (objectId.Scheme == "scope")
                {
                    SendResponse(id,
                                 Result.Exception(new ArgumentException(
                                                      $"Runtime.callFunctionOn not supported with scope ({objectId}).")),
                                 token);
                    return(true);
                }

                var res = await SendMonoCommand(id, MonoCommands.CallFunctionOn(args), token);

                var res_value_type = res.Value?["result"]?["value"]?.Type;

                if (res.IsOk && res_value_type == JTokenType.Object || res_value_type == JTokenType.Object)
                {
                    res = Result.OkFromObject(new { result = res.Value["result"]["value"] });
                }

                SendResponse(id, res, token);
                return(true);
            }
            }

            return(false);
        }
Exemplo n.º 9
0
        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}'");
            }
        }
Exemplo n.º 10
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}'");
            }
        }