private string GetVariableValueString(UnderlyingVariableValuePair variableValuePair)
        {
            // Determine how to format our value string.
            switch (variableValuePair.Variable.GenericType)
            {
            case VarGenericType.Array:
                return($"{variableValuePair.Variable.BaseType} (size: {((object[])variableValuePair.Value).Length})");

            case VarGenericType.ByteArrayDynamic:
                return($"{variableValuePair.Variable.BaseType} (size: {((Memory<byte>)variableValuePair.Value).Length})");

            case VarGenericType.ByteArrayFixed:
                return(variableValuePair.Variable.BaseType);

            case VarGenericType.Mapping:
                return("<unsupported>");

            case VarGenericType.String:
                return($"\"{variableValuePair.Value}\"");

            case VarGenericType.Struct:
                return(variableValuePair.Variable.BaseType);

            default:
                // As a fallback, try to turn the object into a string.
                return(variableValuePair.Value?.ToString() ?? "null");
            }
        }
Example #2
0
        protected override void HandleVariablesRequestAsync(IRequestResponder <VariablesArguments, VariablesResponse> responder)
        {
            // Obtain relevant variable resolving information.
            int  threadId              = 0;
            int  traceIndex            = 0;
            bool isLocalVariableScope  = false;
            bool isStateVariableScope  = false;
            bool isParentVariableScope = false;
            UnderlyingVariableValuePair parentVariableValuePair = new UnderlyingVariableValuePair(null, null);

            // Try to obtain the variable reference as a local variable scope.
            isLocalVariableScope = ReferenceContainer.ResolveLocalVariable(responder.Arguments.VariablesReference, out threadId, out traceIndex);
            if (!isLocalVariableScope)
            {
                // Try to obtain the variable reference as a state variable scope.
                isStateVariableScope = ReferenceContainer.ResolveStateVariable(responder.Arguments.VariablesReference, out threadId, out traceIndex);
                if (!isStateVariableScope)
                {
                    // Try to obtain the variable reference as a sub-variable scope.
                    isParentVariableScope = ReferenceContainer.ResolveParentVariable(responder.Arguments.VariablesReference, out threadId, out parentVariableValuePair);
                }
            }

            // Using our thread id, obtain our thread state
            ThreadStates.TryGetValue(threadId, out var threadState);

            // Verify the thread state is valid
            if (threadState == null)
            {
                responder.SetResponse(new VariablesResponse());
                return;
            }

            // Obtain the trace index for this scope.
            List <Variable> variableList = new List <Variable>();

            try
            {
                ResolveVariables(
                    variableList,
                    responder.Arguments.VariablesReference,
                    isLocalVariableScope,
                    isStateVariableScope,
                    isParentVariableScope,
                    traceIndex,
                    parentVariableValuePair,
                    threadState);
            }
            catch (Exception ex)
            {
                LogException(ex, threadState);
            }

            // Respond with our variable list.
            responder.SetResponse(new VariablesResponse(variableList));
        }
        protected override void HandleVariablesRequestAsync(IRequestResponder <VariablesArguments, VariablesResponse> responder)
        {
            // Obtain relevant variable resolving information.
            int  threadId              = 0;
            int  traceIndex            = 0;
            bool isLocalVariableScope  = false;
            bool isStateVariableScope  = false;
            bool isParentVariableScope = false;
            UnderlyingVariableValuePair parentVariableValuePair = new UnderlyingVariableValuePair(null, null);

            // Try to obtain the variable reference as a local variable scope.
            isLocalVariableScope = ReferenceContainer.ResolveLocalVariable(responder.Arguments.VariablesReference, out threadId, out traceIndex);
            if (!isLocalVariableScope)
            {
                // Try to obtain the variable reference as a state variable scope.
                isStateVariableScope = ReferenceContainer.ResolveStateVariable(responder.Arguments.VariablesReference, out threadId, out traceIndex);
                if (!isStateVariableScope)
                {
                    // Try to obtain the variable reference as a sub-variable scope.
                    isParentVariableScope = ReferenceContainer.ResolveParentVariable(responder.Arguments.VariablesReference, out threadId, out parentVariableValuePair);
                }
            }

            // Using our thread id, obtain our thread state
            ThreadStates.TryGetValue(threadId, out var threadState);

            // Verify the thread state is valid
            if (threadState == null)
            {
                responder.SetResponse(new VariablesResponse());
                return;
            }

            // Obtain the trace index for this scope.
            List <Variable> variableList = new List <Variable>();

            // Obtain our local variables at this point in execution
            VariableValuePair[] variablePairs = Array.Empty <VariableValuePair>();
            if (isLocalVariableScope)
            {
                variablePairs = threadState.ExecutionTraceAnalysis.GetLocalVariables(traceIndex);
            }
            else if (isStateVariableScope)
            {
                variablePairs = threadState.ExecutionTraceAnalysis.GetStateVariables(traceIndex);
            }
            else if (isParentVariableScope)
            {
                // We're loading sub-variables for a variable.
                switch (parentVariableValuePair.Variable.GenericType)
                {
                case VarGenericType.Struct:
                {
                    // Cast our to an enumerable type.
                    variablePairs = ((IEnumerable <VariableValuePair>)parentVariableValuePair.Value).ToArray();
                    break;
                }

                case VarGenericType.Array:
                {
                    // Cast our variable
                    var arrayVariable = ((VarArray)parentVariableValuePair.Variable);

                    // Cast to an object array.
                    var arrayValue = (object[])parentVariableValuePair.Value;

                    // Loop for each element
                    for (int i = 0; i < arrayValue.Length; i++)
                    {
                        // Create an underlying variable value pair for this element
                        var underlyingVariableValuePair = new UnderlyingVariableValuePair(arrayVariable.ElementObject, arrayValue[i]);

                        // Check if this is a nested variable type
                        bool nestedType = IsNestedVariableType(arrayVariable.ElementObject.GenericType);
                        int  variablePairReferenceId = 0;
                        if (nestedType)
                        {
                            // Create a new reference id for this variable if it's a nested type.
                            variablePairReferenceId = ReferenceContainer.GetUniqueId();

                            // Link our reference for any nested types.
                            ReferenceContainer.LinkSubVariableReference(responder.Arguments.VariablesReference, variablePairReferenceId, threadId, underlyingVariableValuePair);
                        }

                        // Obtain the value string for this variable and add it to our list.
                        string variableValueString = GetVariableValueString(underlyingVariableValuePair);
                        variableList.Add(new Variable($"[{i}]", variableValueString, variablePairReferenceId));
                    }


                    break;
                }

                case VarGenericType.ByteArrayDynamic:
                case VarGenericType.ByteArrayFixed:
                {
                    // Cast our to an enumerable type.
                    var bytes = (Memory <byte>)parentVariableValuePair.Value;
                    for (int i = 0; i < bytes.Length; i++)
                    {
                        variableList.Add(new Variable($"[{i}]", bytes.Span[i].ToString(CultureInfo.InvariantCulture), 0));
                    }

                    break;
                }
                }
            }

            // Loop for each local variables
            foreach (VariableValuePair variablePair in variablePairs)
            {
                // Create an underlying variable value pair for this pair.
                var underlyingVariableValuePair = new UnderlyingVariableValuePair(variablePair);

                // Check if this is a nested variable type
                bool nestedType = IsNestedVariableType(variablePair.Variable.GenericType);
                int  variablePairReferenceId = 0;
                if (nestedType)
                {
                    // Create a new reference id for this variable if it's a nested type.
                    variablePairReferenceId = ReferenceContainer.GetUniqueId();

                    // Link our reference for any nested types.
                    ReferenceContainer.LinkSubVariableReference(responder.Arguments.VariablesReference, variablePairReferenceId, threadId, underlyingVariableValuePair);
                }

                // Obtain the value string for this variable and add it to our list.
                string variableValueString = GetVariableValueString(underlyingVariableValuePair);
                variableList.Add(new Variable(variablePair.Variable.Name, variableValueString, variablePairReferenceId));
            }

            // Respond with our variable list.
            responder.SetResponse(new VariablesResponse(variableList));
        }
Example #4
0
        void ResolveVariables(
            List <Variable> variableList,
            int variablesReference,
            bool isLocalVariableScope,
            bool isStateVariableScope,
            bool isParentVariableScope,
            int traceIndex,
            UnderlyingVariableValuePair parentVariableValuePair,
            MeadowDebugAdapterThreadState threadState)
        {
            // Obtain our local variables at this point in execution
            VariableValuePair[] variablePairs = Array.Empty <VariableValuePair>();
            if (isLocalVariableScope)
            {
                variablePairs = threadState.ExecutionTraceAnalysis.GetLocalVariables(traceIndex, threadState.RpcClient);
            }
            else if (isStateVariableScope)
            {
                variablePairs = threadState.ExecutionTraceAnalysis.GetStateVariables(traceIndex, threadState.RpcClient);
            }
            else if (isParentVariableScope)
            {
                // We're loading sub-variables for a variable.
                switch (parentVariableValuePair.Variable.GenericType)
                {
                case VarGenericType.Struct:
                {
                    // Cast our to an enumerable type.
                    variablePairs = ((IEnumerable <VariableValuePair>)parentVariableValuePair.Value).ToArray();
                    break;
                }

                case VarGenericType.Array:
                {
                    // Cast our variable
                    var arrayVariable = ((VarArray)parentVariableValuePair.Variable);

                    // Cast to an object array.
                    var arrayValue = (object[])parentVariableValuePair.Value;

                    // Loop for each element
                    for (int i = 0; i < arrayValue.Length; i++)
                    {
                        // Create an underlying variable value pair for this element
                        var underlyingVariableValuePair = new UnderlyingVariableValuePair(arrayVariable.ElementObject, arrayValue[i]);

                        // Check if this is a nested variable type
                        bool nestedType = IsNestedVariableType(arrayVariable.ElementObject.GenericType);
                        int  variablePairReferenceId = 0;
                        if (nestedType)
                        {
                            // Create a new reference id for this variable if it's a nested type.
                            variablePairReferenceId = ReferenceContainer.GetUniqueId();

                            // Link our reference for any nested types.
                            ReferenceContainer.LinkSubVariableReference(variablesReference, variablePairReferenceId, threadState.ThreadId, underlyingVariableValuePair);
                        }

                        // Obtain the value string for this variable and add it to our list.
                        string variableValueString = GetVariableValueString(underlyingVariableValuePair);
                        variableList.Add(CreateVariable($"[{i}]", variableValueString, variablePairReferenceId, underlyingVariableValuePair.Variable.BaseType));
                    }


                    break;
                }

                case VarGenericType.ByteArrayDynamic:
                case VarGenericType.ByteArrayFixed:
                {
                    // Cast our to an enumerable type.
                    var bytes = (Memory <byte>)parentVariableValuePair.Value;
                    for (int i = 0; i < bytes.Length; i++)
                    {
                        variableList.Add(CreateVariable($"[{i}]", bytes.Span[i].ToString(CultureInfo.InvariantCulture), 0, "byte"));
                    }

                    break;
                }

                case VarGenericType.Mapping:
                {
                    // Obtain our mapping's key-value pairs.
                    var mappingKeyValuePairs = (MappingKeyValuePair[])parentVariableValuePair.Value;
                    variablePairs = new VariableValuePair[mappingKeyValuePairs.Length * 2];

                    // Loop for each key and value pair to add.
                    int variableIndex = 0;
                    for (int i = 0; i < mappingKeyValuePairs.Length; i++)
                    {
                        // Set our key and value in our variable value pair enumeration.
                        variablePairs[variableIndex++] = mappingKeyValuePairs[i].Key;
                        variablePairs[variableIndex++] = mappingKeyValuePairs[i].Value;
                    }

                    break;
                }
                }
            }

            // Loop for each local variables
            foreach (VariableValuePair variablePair in variablePairs)
            {
                // Create an underlying variable value pair for this pair.
                var underlyingVariableValuePair = new UnderlyingVariableValuePair(variablePair);

                // Check if this is a nested variable type
                bool nestedType = IsNestedVariableType(variablePair.Variable.GenericType);
                int  variablePairReferenceId = 0;
                if (nestedType)
                {
                    // Create a new reference id for this variable if it's a nested type.
                    variablePairReferenceId = ReferenceContainer.GetUniqueId();

                    // Link our reference for any nested types.
                    ReferenceContainer.LinkSubVariableReference(variablesReference, variablePairReferenceId, threadState.ThreadId, underlyingVariableValuePair);
                }

                // Obtain the value string for this variable and add it to our list.
                string variableValueString = GetVariableValueString(underlyingVariableValuePair);


                variableList.Add(CreateVariable(variablePair.Variable.Name, variableValueString, variablePairReferenceId, variablePair.Variable.BaseType));
            }
        }