private void ExpandClassInspectionData(InspectionData selectedData) { // Expansion for a class and class properties ProtoCore.Lang.Obj stackValue = GetStackValue(selectedData.Name); Dictionary<string, ProtoCore.Lang.Obj> classProperties = GetClassProperties(stackValue); if (null != classProperties) { ObservableCollection<InspectionData> oldDerivations = selectedData.Derivations; selectedData.ClearDerivations(); int index = 0; foreach (KeyValuePair<string, ProtoCore.Lang.Obj> property in classProperties) { InspectionData inspectionData = CreateInspectionData(property.Value, property.Key); if (null != inspectionData) { selectedData.AddDerivation(inspectionData); if (null != oldDerivations && (index < oldDerivations.Count)) inspectionData.IsExpanded = oldDerivations[index].IsExpanded; } index = index + 1; } } }
private void CreateDataRecursive(InspectionData inspectionData, ProtoCore.Lang.Obj stackValue) { if (null == stackValue || null == stackValue.Payload) { inspectionData.Type = string.Empty; inspectionData.Value = string.Empty; if (!string.IsNullOrEmpty(inspectionData.DisplayText)) inspectionData.Value = "null"; inspectionData.ClearDerivations(); return; } inspectionData.OpType = stackValue.DsasmValue.optype; switch (stackValue.DsasmValue.optype) { case ProtoCore.DSASM.AddressType.ArrayPointer: // Array type { inspectionData.Type = "array"; inspectionData.Value = "array"; if (false == inspectionData.IsExpanded) { // If we are looking at an array, then make sure it // at least have an empty child data (so that HasItems // property returns "true"). This child data can later // be replaced by the actual value upon expansion. if (false == inspectionData.HasItems) { string parentExpression = inspectionData.Expression; inspectionData.AddDerivation(parentExpression, 0); } } else { List<ProtoCore.Lang.Obj> arrayElements = GetArrayStackValues(stackValue); int elementCount = ((null == arrayElements) ? 0 : arrayElements.Count); inspectionData.Type = string.Format("array[{0}]", elementCount); inspectionData.Value = inspectionData.Type; if (inspectionData.Derivations != null) ShrinkDerivations(inspectionData, elementCount); int elementsToDisplay = elementCount; if (inspectionData.ExpansionLimit > 0) { elementsToDisplay = inspectionData.ExpansionLimit; if (elementsToDisplay > elementCount) elementsToDisplay = elementCount; } string parentExpression = inspectionData.Expression; for (int index = 0; index < elementsToDisplay; ++index) { InspectionData childData = inspectionData.GetDrivationAtIndex(index); if (null == childData) childData = inspectionData.AddDerivation(parentExpression, index); CreateDataRecursive(childData, arrayElements[index]); } } break; } case ProtoCore.DSASM.AddressType.Pointer: // Class type { if (inspectionData.Expression.Equals("this") && (Int64)stackValue.Payload == -1) { inspectionData.Type = "Invalid"; inspectionData.Value = "null"; break; } inspectionData.Type = GetStackValueType(stackValue); inspectionData.Value = GetStackValueData(stackValue); if (false == inspectionData.IsExpanded) { // If we are looking at a class, then make sure it // at least have an empty child data (so that HasItems // property returns "true"). This child data can later // be replaced by the actual value upon expansion. if (false == inspectionData.HasItems) inspectionData.AddDerivation(string.Empty, -1); } else { // Expansion for a class and class properties Dictionary<string, ProtoCore.Lang.Obj> properties = GetClassProperties(stackValue); if (null == properties || (properties.Count <= 0)) return; if (inspectionData.Derivations != null) ShrinkDerivations(inspectionData, properties.Count); int index = 0; foreach (KeyValuePair<string, ProtoCore.Lang.Obj> property in properties) { InspectionData childData = inspectionData.GetDrivationAtIndex(index); if (null == childData) childData = inspectionData.AddDerivation(property.Key, -1); // The first child data that was created before this class gets // expanded may not have the appropriate expression to begin with, // so set it here... childData.Expression = property.Key; if (null != property.Value) CreateDataRecursive(childData, property.Value); else { // This may be an external property, try evaluating it for value. string qualifiedName = childData.GetQualifiedName(); ProtoCore.Lang.Obj childStackValue = GetStackValue(qualifiedName); CreateDataRecursive(childData, childStackValue); } index = index + 1; } } break; } case ProtoCore.DSASM.AddressType.String: case ProtoCore.DSASM.AddressType.Char: { inspectionData.Type = GetStackValueType(stackValue); inspectionData.Value = GetStackValueData(stackValue); inspectionData.ClearDerivations(); break; } default: // This applies to all other primitive types. { inspectionData.Type = GetStackValueType(stackValue); inspectionData.Value = GetStackValuePayload(stackValue); inspectionData.ClearDerivations(); break; } } }
/// <summary> /// Method to create an inspection data out of a sent variable by talking /// to the Virtual machine. The watch window adds the variable with a dummy layer under the expansion. /// The dummy level prevents the Virtual Machine being called too many times, /// and should never be shown to the user. /// Eg: Variable name: 'a' /// In watch window: /// Name |Value|Type /// 'a' /// - 'This' 'is' 'dummy' /// </summary> /// <param name="inspectionObj"> Obj type retrieved from Virtual Machine for given variable </param> /// <param name="variableName"> Name of the variable to be made into InspectionData </param> /// <returns> InspectionData object of the Variable </returns> private InspectionData CreateInspectionData(ProtoCore.Lang.Obj inspectionObj, string variableName) { string stackValueType = GetStackValueType(inspectionObj); InspectionData inspectedScope = null; if (stackValueType == "int" || stackValueType == "double" || stackValueType == "null" || stackValueType == "bool") { string n = variableName; string v = (inspectionObj.Payload == null) ? ("null") : (inspectionObj.Payload.ToString()); string t = stackValueType; inspectedScope = new InspectionData(n, v, t); } else if (stackValueType == "array") { string n = variableName; string t = stackValueType; List<ProtoCore.Lang.Obj> arrayElements = GetArrayStackValues(inspectionObj); int arrayIndex = 0; foreach (ProtoCore.Lang.Obj element in arrayElements) { string arrayName = variableName + "[" + arrayIndex + "]"; arrayIndex++; } string v = stackValueType + "[" + arrayElements.Count + "]"; inspectedScope = new InspectionData(n, v, t); if (arrayElements.Count > 0) { // By adding "this is dummy" into the watch window we aim to prevent overworking the // Virtual Machine and expand only if necessary. Obviously, the user should NEVER see this // so that will be a defect, if ever. This also notifies the XAML binding to show the [+] // next to the watch variable. inspectedScope.AddDerivation(new InspectionData(n, v, t)); } } else { Dictionary<string, ProtoCore.Lang.Obj> classProperties = GetClassProperties(inspectionObj); if (null != classProperties) { foreach (KeyValuePair<string, ProtoCore.Lang.Obj> property in classProperties) { string propName = property.Key; } string n = variableName; string v = stackValueType; string t = stackValueType; inspectedScope = new InspectionData(n, v, t); if (classProperties.Count > 0) inspectedScope.AddDerivation(new InspectionData(n, v, t)); } } return inspectedScope; }
//Recursive system to run through all branches of variable inspected public InspectionData MakeInspectionData(ProtoCore.Lang.Obj inspectionObj, string variableName, int limit = 100) { string stackValueType = GetStackValueType(inspectionObj); InspectionData inspectedScope = null; if (stackValueType == "int" || stackValueType == "double" || stackValueType == "null" || stackValueType == "bool") { string n = variableName; string v = (inspectionObj.Payload == null) ? ("null") : (inspectionObj.Payload.ToString()); string t = stackValueType; inspectedScope = new InspectionData(n, v, t); } else if (stackValueType == "array") { string n = variableName; string t = stackValueType; List<ProtoCore.Lang.Obj> arrayElements = GetArrayStackValues(inspectionObj); int arrayIndex = 0; string v = stackValueType + "[" + arrayElements.Count + "]"; inspectedScope = new InspectionData(n, v, t); foreach (ProtoCore.Lang.Obj element in arrayElements) { string arrayName = variableName + "[" + arrayIndex + "]"; inspectedScope.AddDerivation(MakeInspectionData(element, arrayName)); arrayIndex++; } } else { Dictionary<string, ProtoCore.Lang.Obj> classProperties = GetClassProperties(inspectionObj); if (null != classProperties) { string n = variableName; string v = stackValueType; string t = stackValueType; inspectedScope = new InspectionData(n, v, t); foreach (KeyValuePair<string, ProtoCore.Lang.Obj> property in classProperties) { string propName = property.Key; inspectedScope.AddDerivation(MakeInspectionData(property.Value, propName)); } } } return inspectedScope; }