PageRenderTime 19ms CodeModel.GetById 12ms app.highlight 5ms RepoModel.GetById 1ms app.codeStats 0ms

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