PageRenderTime 45ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/NUnit-2.5.7.10213/src/GuiException/UiException/CSharpParser/CSCode.cs

http://github.com/shouldly/shouldly
C# | 354 lines | 199 code | 57 blank | 98 comment | 30 complexity | dce3099ce201328aebfbc595bbaa89dc MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause
  1. // ****************************************************************
  2. // This is free software licensed under the NUnit license. You may
  3. // obtain a copy of the license at http://nunit.org
  4. // ****************************************************************
  5. using System;
  6. using System.Collections.Generic;
  7. using System.Text;
  8. using System.Collections;
  9. using NUnit.UiException.CodeFormatters;
  10. namespace NUnit.UiException.CodeFormatters
  11. {
  12. /// <summary>
  13. /// (Formerly named CSCode)
  14. ///
  15. /// Implements ITextManager and adds new behaviors to provide support for basic
  16. /// syntax coloring.
  17. /// </summary>
  18. public class FormattedCode :
  19. ITextManager
  20. {
  21. /// <summary>
  22. /// Keeps tracks of the text and the data used by the syntax coloring feature.
  23. /// </summary>
  24. protected CodeInfo _codeInfo;
  25. /// <summary>
  26. /// Stores the character count of the longest line in this text.
  27. /// </summary>
  28. private int _maxLength;
  29. /// <summary>
  30. /// Builds a new instance of FormattedCode.
  31. /// </summary>
  32. public FormattedCode()
  33. {
  34. _codeInfo = NewCodeInfo();
  35. _maxLength = 0;
  36. return;
  37. }
  38. public FormattedCode(string csharpText, int[] strIndexes, byte[] tagValues, int[] lineIndexes)
  39. {
  40. UiExceptionHelper.CheckNotNull(csharpText, "csharpText");
  41. UiExceptionHelper.CheckNotNull(strIndexes, "strIndexes");
  42. UiExceptionHelper.CheckNotNull(tagValues, "tagValues");
  43. UiExceptionHelper.CheckNotNull(lineIndexes, "lineIndexes");
  44. _codeInfo = new CodeInfo();
  45. _codeInfo.Text = csharpText;
  46. _codeInfo.IndexArray = new List<int>();
  47. foreach (int index in strIndexes)
  48. _codeInfo.IndexArray.Add(index);
  49. _codeInfo.TagArray = new List<byte>();
  50. foreach (byte tag in tagValues)
  51. _codeInfo.TagArray.Add(tag);
  52. _codeInfo.LineArray = new List<int>();
  53. foreach (int line in lineIndexes)
  54. _codeInfo.LineArray.Add(line);
  55. return;
  56. }
  57. public static FormattedCode Empty
  58. {
  59. get { return (new FormattedCode()); }
  60. }
  61. public CodeInfo CopyInfo()
  62. {
  63. FormattedCode copy;
  64. copy = new FormattedCode(_codeInfo.Text,
  65. _codeInfo.IndexArray.ToArray(),
  66. _codeInfo.TagArray.ToArray(),
  67. _codeInfo.LineArray.ToArray());
  68. return (copy._codeInfo);
  69. }
  70. /// <summary>
  71. /// Builds a new instance of CodeInfo.
  72. /// </summary>
  73. public static CodeInfo NewCodeInfo()
  74. {
  75. CodeInfo res;
  76. res = new CodeInfo();
  77. res.Text = "";
  78. res.IndexArray = new List<int>();
  79. res.LineArray = new List<int>();
  80. res.TagArray = new List<byte>();
  81. return (res);
  82. }
  83. /// <summary>
  84. /// Gets the text currently managed by this object.
  85. /// </summary>
  86. public string Text
  87. {
  88. get { return (_codeInfo.Text); }
  89. }
  90. /// <summary>
  91. /// Gets the line count in the text currently
  92. /// managed by this object.
  93. /// </summary>
  94. public int LineCount
  95. {
  96. get { return (_codeInfo.LineArray.Count); }
  97. }
  98. /// <summary>
  99. /// Gets the character count of the longest line
  100. /// in this text.
  101. /// </summary>
  102. public int MaxLength
  103. {
  104. get
  105. {
  106. int i;
  107. if (_maxLength == 0)
  108. for (i = 0; i < LineCount; ++i)
  109. _maxLength = Math.Max(_maxLength, this[i].Text.TrimEnd().Length);
  110. return (_maxLength);
  111. }
  112. }
  113. /// <summary>
  114. /// Gives access to the collection of ClassifiedToken at the specified lineIndex.
  115. /// </summary>
  116. /// <param name="lineIndex">A zero based startingPosition.</param>
  117. /// <returns>The ClassifiedTokenCollection instance at this startingPosition.</returns>
  118. public ClassifiedTokenCollection this[int lineIndex]
  119. {
  120. get { return (new InternalCSTokenCollection(_codeInfo, lineIndex)); }
  121. }
  122. /// <summary>
  123. /// Gets the text at the specified line.
  124. /// </summary>
  125. /// <param name="lineIndex">A zero based startingPosition.</param>
  126. /// <returns>The text at the specified line startingPosition.</returns>
  127. public string GetTextAt(int lineIndex)
  128. {
  129. return (this[lineIndex].Text);
  130. }
  131. /// <summary>
  132. /// An utility method that check data consistency. The operation
  133. /// raises an exception if an error is found.
  134. /// </summary>
  135. public static void CheckData(FormattedCode data)
  136. {
  137. List<int> lines;
  138. int line;
  139. int bound;
  140. int i;
  141. UiExceptionHelper.CheckNotNull(data, "data");
  142. UiExceptionHelper.CheckTrue(
  143. data._codeInfo.IndexArray.Count == data._codeInfo.TagArray.Count,
  144. "IndexArray.Count and TagArray.Count must match.",
  145. "data");
  146. bound = data._codeInfo.IndexArray.Count;
  147. lines = data._codeInfo.LineArray;
  148. for (i = 0; i < lines.Count; ++i)
  149. {
  150. line = lines[i];
  151. UiExceptionHelper.CheckTrue(
  152. line >= 0 && line < bound,
  153. "Bad LineArray value at index " + i + ", value was: " + line + ", expected to be in: [0-" + bound + "[.",
  154. "data");
  155. if (i == 0)
  156. continue;
  157. UiExceptionHelper.CheckTrue(
  158. lines[i] > lines[i - 1],
  159. "Bad LineArray[" + i + "], value was: " + line + ", expected to be > than LineArray[" + (i - 1) + "]=" + lines[i - 1] + ".",
  160. "data");
  161. }
  162. return;
  163. }
  164. public override bool Equals(object obj)
  165. {
  166. FormattedCode arg;
  167. int i;
  168. if (obj == null ||
  169. !(obj is FormattedCode))
  170. return (false);
  171. arg = obj as FormattedCode;
  172. if (arg._codeInfo.Text != _codeInfo.Text ||
  173. arg._codeInfo.IndexArray.Count != _codeInfo.IndexArray.Count ||
  174. arg._codeInfo.TagArray.Count != _codeInfo.TagArray.Count ||
  175. arg._codeInfo.LineArray.Count != _codeInfo.LineArray.Count)
  176. return (false);
  177. for (i = 0; i < arg._codeInfo.IndexArray.Count; ++i)
  178. if (arg._codeInfo.IndexArray[i] != _codeInfo.IndexArray[i])
  179. return (false);
  180. for (i = 0; i < arg._codeInfo.TagArray.Count; ++i)
  181. if (arg._codeInfo.TagArray[i] != _codeInfo.TagArray[i])
  182. return (false);
  183. for (i = 0; i < arg._codeInfo.LineArray.Count; ++i)
  184. if (arg._codeInfo.LineArray[i] != _codeInfo.LineArray[i])
  185. return (false);
  186. return (true);
  187. }
  188. public override int GetHashCode()
  189. {
  190. return base.GetHashCode();
  191. }
  192. public override string ToString()
  193. {
  194. string res;
  195. string index_array;
  196. string tag_array;
  197. string line_array;
  198. int i;
  199. index_array = "";
  200. for (i = 0; i < _codeInfo.IndexArray.Count; ++i)
  201. {
  202. if (i > 0)
  203. index_array += ", ";
  204. index_array += "" + _codeInfo.IndexArray[i];
  205. }
  206. tag_array = "";
  207. for (i = 0; i < _codeInfo.TagArray.Count; ++i)
  208. {
  209. if (i > 0)
  210. tag_array += ", ";
  211. tag_array += "" + _codeInfo.TagArray[i];
  212. }
  213. line_array = "";
  214. for (i = 0; i < _codeInfo.LineArray.Count; ++i)
  215. {
  216. if (i > 0)
  217. line_array += ", ";
  218. line_array += "" + _codeInfo.LineArray[i];
  219. }
  220. res = String.Format(
  221. "FormattedCode: [(text=[{0}], len={1}), (startingPosition=[{2}]), (tag=[{3}]), (line=[{4}])]",
  222. _codeInfo.Text, _codeInfo.Text.Length,
  223. index_array, tag_array, line_array);
  224. return (res);
  225. }
  226. /// <summary>
  227. /// A naive attempt to modelize a structure of data that manages the text to be
  228. /// displayed and extra data to make basic syntax coloring at rendering time,
  229. /// while keeping a low memory footprint.
  230. ///
  231. /// At rendering time, CodeInfo is used to make a link between the text to be drawn
  232. /// and the brush color to be used during the process. So it is possible to distinguishes
  233. /// code, comments, keywords and strings.
  234. /// Currently, CodeInfo is used to split the text into a collection of couple of data,
  235. /// where each couple is composed of:
  236. /// - a string of characters
  237. /// - a value (called tag) that classifies this string from 0 to 3.
  238. /// Where 0 corresponds to 'Code', 1 to 'Keyword' and so on.
  239. /// These couples are named 'ClassifiedToken'. At rendering time, the process can link each
  240. /// of these values to a particular System.Drawing.Brush instance and display text
  241. /// differently.
  242. ///
  243. /// However, keeping track of all these couples at any time could have a significative
  244. /// impact on memory especially for big files. Therefore, instead of storing all theses couples,
  245. /// CodeInfo stores just primitive information that allow to build ClassifiedToken instances on the fly.
  246. /// </summary>
  247. public class CodeInfo
  248. {
  249. /// <summary>
  250. /// Holds the entire text as a simple string.
  251. /// </summary>
  252. public string Text;
  253. /// <summary>
  254. /// Array of character indexes that refers to
  255. /// the field "Text". Each value in this array
  256. /// must be interpreted as the starting index position
  257. /// in the string into Text.
  258. /// </summary>
  259. public List<int> IndexArray;
  260. /// <summary>
  261. /// Array of ClassificationTag values held as a
  262. /// byte array. There is a one-to-one correspondance
  263. /// with 'IndexArray'. i.e.: TagArray[0] refers to the
  264. /// ClassificationTag value for string sequence at
  265. /// IndexArray[0]. TagArray[1] refers value to IndexArray[1] and
  266. /// so on... Hence, the following condition:
  267. /// - IndexArray.Count == TagArray.Count must be verified.
  268. /// </summary>
  269. public List<byte> TagArray;
  270. /// <summary>
  271. /// This index_array is used to easily locate the start of each
  272. /// line of text, for instance: startingPosition[0] refers to line startingPosition 0,
  273. /// startingPosition[1] refers to line startingPosition 1 and so on...
  274. /// However, there is a small indirection in that this index_array
  275. /// doesn't directly hold string indexes but refers to the startingPosition
  276. /// of the item to be used in 'IndexArray'.
  277. /// Therefore, LineArray[0] gives access to the startingPosition of the
  278. /// IndexArray's item to be used to get the corresponding character
  279. /// position. Hence, line 0 starts at: IndexArray[LineArray[0]]
  280. /// line 1: IndexArray[LineArray[1]] and so on...
  281. /// </summary>
  282. public List<int> LineArray;
  283. }
  284. #region InternalCSTokenCollection
  285. class InternalCSTokenCollection :
  286. ClassifiedTokenCollection
  287. {
  288. public InternalCSTokenCollection(CodeInfo info, int lineIndex)
  289. {
  290. _info = info;
  291. _lineIndex = lineIndex;
  292. return;
  293. }
  294. }
  295. #endregion
  296. }
  297. }