public ObjectValue CreateElementValue (ArrayElementGroup grp, ObjectPath path, int[] indices) { if (array != null) { CorValRef elem = (CorValRef) GetElement (indices); return ctx.Adapter.CreateObjectValue (ctx, grp, path, elem, ObjectValueFlags.ArrayElement); } else return ObjectValue.CreateUnknown ("?"); }
public virtual ObjectValue[] GetObjectValueChildren (EvaluationContext ctx, IObjectSource objectSource, object type, object obj, int firstItemIndex, int count, bool dereferenceProxy) { if (obj is EvaluationResult) return new ObjectValue[0]; if (IsArray (ctx, obj)) { ArrayElementGroup agroup = new ArrayElementGroup (ctx, CreateArrayAdaptor (ctx, obj)); return agroup.GetChildren (ctx.Options); } if (IsPrimitive (ctx, obj)) return new ObjectValue[0]; bool showRawView = false; // If there is a proxy, it has to show the members of the proxy object proxy = obj; if (dereferenceProxy) { proxy = GetProxyObject (ctx, obj); if (proxy != obj) { type = GetValueType (ctx, proxy); showRawView = true; } } TypeDisplayData tdata = GetTypeDisplayData (ctx, type); bool groupPrivateMembers = ctx.Options.GroupPrivateMembers && (ctx.Options.GroupUserPrivateMembers || IsExternalType (ctx, type)); List<ObjectValue> values = new List<ObjectValue> (); BindingFlags flattenFlag = ctx.Options.FlattenHierarchy ? (BindingFlags)0 : BindingFlags.DeclaredOnly; BindingFlags nonNonPublicFlag = groupPrivateMembers || showRawView ? (BindingFlags)0 : BindingFlags.NonPublic; BindingFlags staticFlag = ctx.Options.GroupStaticMembers ? (BindingFlags)0 : BindingFlags.Static; BindingFlags access = BindingFlags.Public | BindingFlags.Instance | flattenFlag | nonNonPublicFlag | staticFlag; // Load all members to a list before creating the object values, // to avoid problems with objects being invalidated due to evaluations in the target, List<ValueReference> list = new List<ValueReference> (); list.AddRange (GetMembersSorted (ctx, objectSource, type, proxy, access)); var names = new ObjectValueNameTracker (ctx); object tdataType = type; foreach (ValueReference val in list) { try { object decType = val.DeclaringType; if (decType != null && decType != tdataType) { tdataType = decType; tdata = GetTypeDisplayData (ctx, decType); } DebuggerBrowsableState state = tdata.GetMemberBrowsableState (val.Name); if (state == DebuggerBrowsableState.Never) continue; if (state == DebuggerBrowsableState.RootHidden && dereferenceProxy) { object ob = val.Value; if (ob != null) { values.Clear (); values.AddRange (GetObjectValueChildren (ctx, val, ob, -1, -1)); showRawView = true; break; } } else { ObjectValue oval = val.CreateObjectValue (true); names.Disambiguate (val, oval); values.Add (oval); } } catch (Exception ex) { ctx.WriteDebuggerError (ex); values.Add (ObjectValue.CreateError (null, new ObjectPath (val.Name), GetDisplayTypeName (GetTypeName (ctx, val.Type)), ex.Message, val.Flags)); } } if (showRawView) { values.Add (RawViewSource.CreateRawView (ctx, objectSource, obj)); } else { if (IsArray (ctx, proxy)) { ICollectionAdaptor col = CreateArrayAdaptor (ctx, proxy); ArrayElementGroup agroup = new ArrayElementGroup (ctx, col); ObjectValue val = ObjectValue.CreateObject (null, new ObjectPath ("Raw View"), "", "", ObjectValueFlags.ReadOnly, values.ToArray ()); values = new List<ObjectValue> (); values.Add (val); values.AddRange (agroup.GetChildren (ctx.Options)); } else { if (ctx.Options.GroupStaticMembers && HasMembers (ctx, type, proxy, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | flattenFlag)) { access = BindingFlags.Static | BindingFlags.Public | flattenFlag | nonNonPublicFlag; values.Add (FilteredMembersSource.CreateStaticsNode (ctx, objectSource, type, proxy, access)); } if (groupPrivateMembers && HasMembers (ctx, type, proxy, BindingFlags.Instance | BindingFlags.NonPublic | flattenFlag | staticFlag)) values.Add (FilteredMembersSource.CreateNonPublicsNode (ctx, objectSource, type, proxy, BindingFlags.Instance | BindingFlags.NonPublic | flattenFlag | staticFlag)); if (!ctx.Options.FlattenHierarchy) { object baseType = GetBaseType (ctx, type, false); if (baseType != null) values.Insert (0, BaseTypeViewSource.CreateBaseTypeView (ctx, objectSource, baseType, proxy)); } } } return values.ToArray (); }
public virtual ObjectValue[] GetObjectValueChildren(EvaluationContext ctx, IObjectSource objectSource, object type, object obj, int firstItemIndex, int count, bool dereferenceProxy) { if (IsArray(ctx, obj)) { ArrayElementGroup agroup = new ArrayElementGroup(ctx, CreateArrayAdaptor(ctx, obj)); return(agroup.GetChildren(ctx.Options)); } if (IsPrimitive(ctx, obj)) { return(new ObjectValue[0]); } bool showRawView = false; // If there is a proxy, it has to show the members of the proxy object proxy = obj; if (dereferenceProxy) { proxy = GetProxyObject(ctx, obj); if (proxy != obj) { type = GetValueType(ctx, proxy); showRawView = true; } } TypeDisplayData tdata = GetTypeDisplayData(ctx, type); bool groupPrivateMembers = ctx.Options.GroupPrivateMembers && (ctx.Options.GroupUserPrivateMembers || IsExternalType(ctx, type)); List <ObjectValue> values = new List <ObjectValue> (); BindingFlags flattenFlag = ctx.Options.FlattenHierarchy ? (BindingFlags)0 : BindingFlags.DeclaredOnly; BindingFlags nonNonPublicFlag = groupPrivateMembers || showRawView ? (BindingFlags)0 : BindingFlags.NonPublic; BindingFlags staticFlag = ctx.Options.GroupStaticMembers ? (BindingFlags)0 : BindingFlags.Static; BindingFlags access = BindingFlags.Public | BindingFlags.Instance | flattenFlag | nonNonPublicFlag | staticFlag; // Load all members to a list before creating the object values, // to avoid problems with objects being invalidated due to evaluations in the target, List <ValueReference> list = new List <ValueReference> (); list.AddRange(GetMembersSorted(ctx, objectSource, type, proxy, access)); object tdataType = type; foreach (ValueReference val in list) { try { object decType = val.DeclaringType; if (decType != null && decType != tdataType) { tdataType = decType; tdata = GetTypeDisplayData(ctx, decType); } DebuggerBrowsableState state = tdata.GetMemberBrowsableState(val.Name); if (state == DebuggerBrowsableState.Never) { continue; } if (state == DebuggerBrowsableState.RootHidden && dereferenceProxy) { object ob = val.Value; if (ob != null) { values.Clear(); values.AddRange(GetObjectValueChildren(ctx, val, ob, -1, -1)); showRawView = true; break; } } else { ObjectValue oval = val.CreateObjectValue(true); values.Add(oval); } } catch (Exception ex) { ctx.WriteDebuggerError(ex); values.Add(ObjectValue.CreateError(null, new ObjectPath(val.Name), GetDisplayTypeName(GetTypeName(ctx, val.Type)), ex.Message, val.Flags)); } } if (showRawView) { values.Add(RawViewSource.CreateRawView(ctx, objectSource, obj)); } else { if (IsArray(ctx, proxy)) { ICollectionAdaptor col = CreateArrayAdaptor(ctx, proxy); ArrayElementGroup agroup = new ArrayElementGroup(ctx, col); ObjectValue val = ObjectValue.CreateObject(null, new ObjectPath("Raw View"), "", "", ObjectValueFlags.ReadOnly, values.ToArray()); values = new List <ObjectValue> (); values.Add(val); values.AddRange(agroup.GetChildren(ctx.Options)); } else { if (ctx.Options.GroupStaticMembers && HasMembers(ctx, type, proxy, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | flattenFlag)) { access = BindingFlags.Static | BindingFlags.Public | flattenFlag | nonNonPublicFlag; values.Add(FilteredMembersSource.CreateStaticsNode(ctx, objectSource, type, proxy, access)); } if (groupPrivateMembers && HasMembers(ctx, type, proxy, BindingFlags.Instance | BindingFlags.NonPublic | flattenFlag | staticFlag)) { values.Add(FilteredMembersSource.CreateNonPublicsNode(ctx, objectSource, type, proxy, BindingFlags.Instance | BindingFlags.NonPublic | flattenFlag | staticFlag)); } if (!ctx.Options.FlattenHierarchy) { object baseType = GetBaseType(ctx, type, false); if (baseType != null) { values.Insert(0, BaseTypeViewSource.CreateBaseTypeView(ctx, objectSource, baseType, proxy)); } } } } return(values.ToArray()); }
public ArrayObjectSource(ICollectionAdaptor source, int[] index) { this.source = source; this.path = ArrayElementGroup.IndicesToString(index); }
public ObjectValue[] GetChildren(ObjectPath path, int firstItemIndex, int count, EvaluationOptions options) { EvaluationContext cctx = ctx.WithOptions(options); if (path.Length > 1) { // Looking for children of an array element int[] idx = StringToIndices(path [1]); object obj = array.GetElement(idx); return(cctx.Adapter.GetObjectValueChildren(cctx, new ArrayObjectSource(array, path[1]), obj, firstItemIndex, count)); } int lowerBound; int upperBound; bool isLastDimension; if (dimensions.Length > 1) { int rank = baseIndices.Length; lowerBound = array.GetLowerBounds() [rank]; upperBound = lowerBound + dimensions [rank] - 1; isLastDimension = rank == dimensions.Length - 1; } else { lowerBound = array.GetLowerBounds() [0]; upperBound = lowerBound + dimensions [0] - 1; isLastDimension = true; } int len; int initalIndex; if (!IsRange) { initalIndex = lowerBound; len = upperBound + 1 - lowerBound; } else { initalIndex = firstIndex; len = lastIndex - firstIndex + 1; } if (firstItemIndex == -1) { firstItemIndex = 0; count = len; } // Make sure the group doesn't have too many elements. If so, divide int div = 1; while (len / div > MaxChildCount) { div *= 10; } if (div == 1 && isLastDimension) { // Return array elements ObjectValue[] values = new ObjectValue [count]; ObjectPath newPath = new ObjectPath("this"); int[] curIndex = new int [baseIndices.Length + 1]; Array.Copy(baseIndices, curIndex, baseIndices.Length); string curIndexStr = IndicesToString(baseIndices); if (baseIndices.Length > 0) { curIndexStr += ","; } curIndex [curIndex.Length - 1] = initalIndex + firstItemIndex; var elems = array.GetElements(curIndex, System.Math.Min(values.Length, upperBound - lowerBound + 1)); for (int n = 0; n < values.Length; n++) { int index = n + initalIndex + firstItemIndex; string sidx = curIndexStr + index; ObjectValue val; string ename = "[" + sidx.Replace(",", ", ") + "]"; if (index > upperBound) { val = ObjectValue.CreateUnknown(sidx); } else { curIndex [curIndex.Length - 1] = index; val = cctx.Adapter.CreateObjectValue(cctx, this, newPath.Append(sidx), elems.GetValue(n), ObjectValueFlags.ArrayElement); if (elems.GetValue(n) != null && !cctx.Adapter.IsNull(cctx, elems.GetValue(n))) { TypeDisplayData tdata = cctx.Adapter.GetTypeDisplayData(cctx, cctx.Adapter.GetValueType(cctx, elems.GetValue(n))); if (!string.IsNullOrEmpty(tdata.NameDisplayString)) { try { ename = cctx.Adapter.EvaluateDisplayString(cctx, elems.GetValue(n), tdata.NameDisplayString); } catch (MissingMemberException) { // missing property or otherwise malformed DebuggerDisplay string } } } } val.Name = ename; values [n] = val; } return(values); } if (!isLastDimension && div == 1) { // Return an array element group for each index var list = new List <ObjectValue> (); for (int i = 0; i < count; i++) { int index = i + initalIndex + firstItemIndex; ObjectValue val; // This array must be created at every call to avoid sharing // changes with all array groups int[] curIndex = new int [baseIndices.Length + 1]; Array.Copy(baseIndices, curIndex, baseIndices.Length); curIndex [curIndex.Length - 1] = index; if (index > upperBound) { val = ObjectValue.CreateUnknown(""); } else { ArrayElementGroup grp = new ArrayElementGroup(cctx, array, curIndex); val = grp.CreateObjectValue(); } list.Add(val); } return(list.ToArray()); } else { // Too many elements. Split the array. // Don't make divisions of 10 elements, min is 100 if (div == 10) { div = 100; } // Create the child groups int i = initalIndex + firstItemIndex; len += i; var list = new List <ObjectValue> (); while (i < len) { int end = i + div - 1; if (end >= len) { end = len - 1; } ArrayElementGroup grp = new ArrayElementGroup(cctx, array, baseIndices, i, end); list.Add(grp.CreateObjectValue()); i += div; } return(list.ToArray()); } }
public ObjectValue[] GetChildren (ObjectPath path, int firstItemIndex, int count, EvaluationOptions options) { EvaluationContext cctx = ctx.WithOptions (options); if (path.Length > 1) { // Looking for children of an array element int[] idx = StringToIndices (path [1]); object obj = array.GetElement (idx); return cctx.Adapter.GetObjectValueChildren (cctx, new ArrayObjectSource (array, path[1]), obj, firstItemIndex, count); } int lowerBound; int upperBound; bool isLastDimension; if (bounds.Length > 1) { int rank = baseIndices.Length; lowerBound = 0; upperBound = bounds [rank] - 1; isLastDimension = rank == bounds.Length - 1; } else { lowerBound = 0; upperBound = bounds [0] - 1; isLastDimension = true; } int len; int initalIndex; if (!IsRange) { initalIndex = lowerBound; len = upperBound + 1; } else { initalIndex = firstIndex; len = lastIndex - firstIndex + 1; } if (firstItemIndex == -1) { firstItemIndex = 0; count = len; } // Make sure the group doesn't have too many elements. If so, divide int div = 1; while (len / div > MaxChildCount) div *= 10; if (div == 1 && isLastDimension) { // Return array elements ObjectValue[] values = new ObjectValue [count]; ObjectPath newPath = new ObjectPath ("this"); int[] curIndex = new int [baseIndices.Length + 1]; Array.Copy (baseIndices, curIndex, baseIndices.Length); string curIndexStr = IndicesToString (baseIndices); if (baseIndices.Length > 0) curIndexStr += ","; for (int n=0; n < values.Length; n++) { int index = n + initalIndex + firstItemIndex; string sidx = curIndexStr + index.ToString (); ObjectValue val; string ename = "[" + sidx.Replace (",",", ") + "]"; if (index > upperBound) val = ObjectValue.CreateUnknown (sidx); else { curIndex [curIndex.Length - 1] = index; object elem = array.GetElement (curIndex); val = cctx.Adapter.CreateObjectValue (cctx, this, newPath.Append (sidx), elem, ObjectValueFlags.ArrayElement); if (elem != null && !cctx.Adapter.IsNull (cctx, elem)) { TypeDisplayData tdata = cctx.Adapter.GetTypeDisplayData (cctx, cctx.Adapter.GetValueType (cctx, elem)); if (!string.IsNullOrEmpty (tdata.NameDisplayString)) ename = cctx.Adapter.EvaluateDisplayString (cctx, elem, tdata.NameDisplayString); } } val.Name = ename; values [n] = val; } return values; } else if (!isLastDimension && div == 1) { // Return an array element group for each index List<ObjectValue> list = new List<ObjectValue> (); for (int i=0; i<count; i++) { int index = i + initalIndex + firstItemIndex; ObjectValue val; // This array must be created at every call to avoid sharing // changes with all array groups int[] curIndex = new int [baseIndices.Length + 1]; Array.Copy (baseIndices, curIndex, baseIndices.Length); curIndex [curIndex.Length - 1] = index; if (index > upperBound) val = ObjectValue.CreateUnknown (""); else { ArrayElementGroup grp = new ArrayElementGroup (cctx, array, curIndex); val = grp.CreateObjectValue (); } list.Add (val); } return list.ToArray (); } else { // Too many elements. Split the array. // Don't make divisions of 10 elements, min is 100 if (div == 10) div = 100; // Create the child groups int i = initalIndex + firstItemIndex; len += i; List<ObjectValue> list = new List<ObjectValue> (); while (i < len) { int end = i + div - 1; if (end > len) end = len - 1; ArrayElementGroup grp = new ArrayElementGroup (cctx, array, baseIndices, i, end); list.Add (grp.CreateObjectValue ()); i += div; } return list.ToArray (); } }