private IEnumerable <IVisualizerCommand> getAvailableVisualizerCommands() { if (!evaluated) { EvaluateExpression(); } if (this.expressionType == null) { // no visualizers if EvaluateExpression failed yield break; } if (this.valueIsNull) { // no visualizers if evaluated value is null yield break; } /*if (this.expressionType.IsPrimitive || this.expressionType.IsSystemDotObject() || this.expressionType.IsEnum()) { * // no visualizers for primitive types * yield break; * }*/ foreach (var descriptor in VisualizerDescriptors.GetAllDescriptors()) { if (descriptor.IsVisualizerAvailable(this.expressionType)) { yield return(descriptor.CreateVisualizerCommand(this.Expression)); } } }
/// <summary> Get the value of the node and update the UI text fields. </summary> /// <remarks> This should be only called once so the Value is not cached. </remarks> void GetValueAndUpdateUI() { try { Stopwatch watch = new Stopwatch(); watch.Start(); // Do not keep permanent reference Value val = this.getValue(); if (val == null) { Value = string.Empty; Type = string.Empty; GetChildren = null; VisualizerCommands = null; return; } // Note that the child collections are lazy-evaluated if (val.IsNull) { this.GetChildren = null; } else if (val.Type.IsPrimitiveType() || val.Type.IsKnownType(KnownTypeCode.String)) // Must be before IsClass { this.GetChildren = null; } else if (val.Type.Kind == TypeKind.Array) // Must be before IsClass { var dimBase = val.ArrayBaseIndicies; // Eval now var dimSize = val.ArrayDimensions; // Eval now if (val.ArrayLength > 0) { this.GetChildren = () => GetArrayChildren(dimBase, dimSize); } } else if (val.Type.Kind == TypeKind.Class || val.Type.Kind == TypeKind.Struct) { if (val.Type.IsKnownType(typeof(List <>))) { if ((int)val.GetFieldValue("_size").PrimitiveValue > 0) { this.GetChildren = () => GetIListChildren(this.GetValue); } } else { this.GetChildren = () => GetObjectChildren(val.Type); } } else if (val.Type.Kind == TypeKind.Pointer) { if (val.Dereference() != null) { this.GetChildren = () => new[] { new ValueNode(ClassBrowserIconService.LocalVariable, "*" + this.Name, () => GetValue().Dereference()) }; } } // Do last since it may expire the object if (val.IsNull) { fullValue = "null"; } else if (val.Type.IsInteger()) { var i = val.PrimitiveValue; if (DebuggingOptions.Instance.ShowIntegersAs == ShowIntegersAs.Decimal) { fullValue = i.ToString(); } else { string hex = string.Format("0x{0:X4}", i); if (hex.Length > 6) { hex = string.Format("0x{0:X8}", i); } if (hex.Length > 10) { hex = string.Format("0x{0:X16}", i); } if (DebuggingOptions.Instance.ShowIntegersAs == ShowIntegersAs.Hexadecimal) { fullValue = hex; } else { fullValue = string.Format("{0} ({1})", i, hex); } } } else if (val.Type.Kind == TypeKind.Pointer) { fullValue = String.Format("0x{0:X}", val.PointerAddress); } else if (val.Type.IsKnownType(KnownTypeCode.String)) { fullValue = '"' + val.InvokeToString(WindowsDebugger.EvalThread).Replace("\n", "\\n").Replace("\t", "\\t").Replace("\r", "\\r").Replace("\0", "\\0").Replace("\b", "\\b").Replace("\a", "\\a").Replace("\f", "\\f").Replace("\v", "\\v").Replace("\"", "\\\"") + '"'; } else if (val.Type.IsKnownType(KnownTypeCode.Char)) { fullValue = "'" + val.InvokeToString(WindowsDebugger.EvalThread).Replace("\n", "\\n").Replace("\t", "\\t").Replace("\r", "\\r").Replace("\0", "\\0").Replace("\b", "\\b").Replace("\a", "\\a").Replace("\f", "\\f").Replace("\v", "\\v").Replace("\"", "\\\"") + "'"; } else if ((val.Type.Kind == TypeKind.Class || val.Type.Kind == TypeKind.Struct)) { fullValue = val.FormatByDebuggerDisplayAttribute(WindowsDebugger.EvalThread); if (fullValue == null) { fullValue = val.InvokeToString(WindowsDebugger.EvalThread); } } else if (val.Type.Kind == TypeKind.Enum) { var primitiveValue = val.PrimitiveValue; var builder = new TypeSystemAstBuilder(); builder.AlwaysUseShortTypeNames = true; AstNode node = builder.ConvertConstantValue(val.Type, primitiveValue); fullValue = node + "=" + primitiveValue; } else { fullValue = val.AsString(); } this.error = null; this.Value = (fullValue.Length > 256) ? fullValue.Substring(0, 256) + "..." : fullValue; this.Type = val.Type.Name; if (!val.IsNull) { this.VisualizerCommands = VisualizerDescriptors.GetAllDescriptors() .Where(descriptor => descriptor.IsVisualizerAvailable(val.Type)) .Select(descriptor => descriptor.CreateVisualizerCommand(this.Name, this.GetValue)) .ToList(); } LoggingService.InfoFormatted("Evaluated node '{0}' in {1} ms", this.Name, watch.ElapsedMilliseconds); } catch (GetValueException e) { error = e; this.Value = e.Message; this.Type = string.Empty; this.GetChildren = null; this.VisualizerCommands = null; } finally { if (error == null) { ContextMenuAddInTreeEntry = "/AddIns/Debugger/Tooltips/ContextMenu/ValueNode"; } else { ContextMenuAddInTreeEntry = "/AddIns/Debugger/Tooltips/ContextMenu/ErrorNode"; } } }