/Debugger/ILSpy.Debugger/Models/TreeModel/ArrayRangeNode.cs

http://github.com/icsharpcode/ILSpy · C# · 121 lines · 102 code · 13 blank · 6 comment · 18 complexity · a4274658dd5039cab39f9de63966df60 MD5 · raw file

  1. // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
  2. // This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Text;
  6. using Debugger;
  7. using ICSharpCode.NRefactory.Ast;
  8. using ICSharpCode.NRefactory.CSharp;
  9. namespace ICSharpCode.ILSpy.Debugger.Models.TreeModel
  10. {
  11. internal static partial class Utils
  12. {
  13. public static IEnumerable<TreeNode> LazyGetChildNodesOfArray(Expression expression, ArrayDimensions dimensions)
  14. {
  15. if (dimensions.TotalElementCount == 0)
  16. return new TreeNode[] { new TreeNode(null, "(empty)", null, null, null) };
  17. return new ArrayRangeNode(expression, dimensions, dimensions).ChildNodes;
  18. }
  19. }
  20. /// <summary> This is a partent node for all elements within a given bounds </summary>
  21. internal class ArrayRangeNode: TreeNode
  22. {
  23. const int MaxElementCount = 100;
  24. Expression arrayTarget;
  25. ArrayDimensions bounds;
  26. ArrayDimensions originalBounds;
  27. public ArrayRangeNode(Expression arrayTarget, ArrayDimensions bounds, ArrayDimensions originalBounds)
  28. {
  29. this.arrayTarget = arrayTarget;
  30. this.bounds = bounds;
  31. this.originalBounds = originalBounds;
  32. this.Name = GetName();
  33. this.ChildNodes = LazyGetChildren();
  34. }
  35. string GetName()
  36. {
  37. StringBuilder name = new StringBuilder();
  38. bool isFirst = true;
  39. name.Append("[");
  40. for(int i = 0; i < bounds.Count; i++) {
  41. if (!isFirst) name.Append(", ");
  42. isFirst = false;
  43. ArrayDimension dim = bounds[i];
  44. ArrayDimension originalDim = originalBounds[i];
  45. if (dim.Count == 0) {
  46. throw new DebuggerException("Empty dimension");
  47. } else if (dim.Count == 1) {
  48. name.Append(dim.LowerBound.ToString());
  49. } else if (dim.Equals(originalDim)) {
  50. name.Append("*");
  51. } else {
  52. name.Append(dim.LowerBound);
  53. name.Append("..");
  54. name.Append(dim.UpperBound);
  55. }
  56. }
  57. name.Append("]");
  58. return name.ToString();
  59. }
  60. static string GetName(int[] indices)
  61. {
  62. StringBuilder sb = new StringBuilder(indices.Length * 4);
  63. sb.Append("[");
  64. bool isFirst = true;
  65. foreach(int index in indices) {
  66. if (!isFirst) sb.Append(", ");
  67. sb.Append(index.ToString());
  68. isFirst = false;
  69. }
  70. sb.Append("]");
  71. return sb.ToString();
  72. }
  73. IEnumerable<TreeNode> LazyGetChildren()
  74. {
  75. // The whole array is small - just add all elements as childs
  76. if (bounds.TotalElementCount <= MaxElementCount) {
  77. foreach(int[] indices in bounds.Indices) {
  78. string imageName;
  79. var image = ExpressionNode.GetImageForArrayIndexer(out imageName);
  80. var expression = new ExpressionNode(image, GetName(indices), arrayTarget.AppendIndexer(indices));
  81. expression.ImageName = imageName;
  82. yield return expression;
  83. }
  84. yield break;
  85. }
  86. // Find a dimension of size at least 2
  87. int splitDimensionIndex = bounds.Count - 1;
  88. for(int i = 0; i < bounds.Count; i++) {
  89. if (bounds[i].Count > 1) {
  90. splitDimensionIndex = i;
  91. break;
  92. }
  93. }
  94. ArrayDimension splitDim = bounds[splitDimensionIndex];
  95. // Split the dimension
  96. int elementsPerSegment = 1;
  97. while (splitDim.Count > elementsPerSegment * MaxElementCount) {
  98. elementsPerSegment *= MaxElementCount;
  99. }
  100. for(int i = splitDim.LowerBound; i <= splitDim.UpperBound; i += elementsPerSegment) {
  101. List<ArrayDimension> newDims = new List<ArrayDimension>(bounds);
  102. newDims[splitDimensionIndex] = new ArrayDimension(i, Math.Min(i + elementsPerSegment - 1, splitDim.UpperBound));
  103. yield return new ArrayRangeNode(arrayTarget, new ArrayDimensions(newDims), originalBounds);
  104. }
  105. yield break;
  106. }
  107. }
  108. }