PageRenderTime 45ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/src/NUnit/UiException/CSharpParser/CSTokenCollection.cs

#
C# | 219 lines | 125 code | 35 blank | 59 comment | 6 complexity | f02aa335d837bec9d9d430c7e5ec6228 MD5 | raw file
Possible License(s): GPL-2.0
  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. namespace NUnit.UiException.CodeFormatters
  10. {
  11. /// <summary>
  12. /// (formerly named CSTokenCollection)
  13. ///
  14. /// Manages an ordered collection of ClassifiedToken present in one line of text.
  15. /// </summary>
  16. public class ClassifiedTokenCollection
  17. {
  18. /// <summary>
  19. /// Target location when building a ClassifiedToken instance on the fly.
  20. /// </summary>
  21. protected ClassifiedToken _token;
  22. /// <summary>
  23. /// Keeps tracks of the data source.
  24. /// </summary>
  25. protected FormattedCode.CodeInfo _info;
  26. /// <summary>
  27. /// Store the current line startingPosition.
  28. /// </summary>
  29. protected int _lineIndex;
  30. /// <summary>
  31. /// This class requires subclassing.
  32. /// </summary>
  33. protected ClassifiedTokenCollection()
  34. {
  35. _token = new InternalToken();
  36. }
  37. /// <summary>
  38. /// Gets the number of ClassifiedToken present in this line of text.
  39. /// </summary>
  40. public int Count
  41. {
  42. get
  43. {
  44. int count;
  45. if (_lineIndex + 1 < _info.LineArray.Count)
  46. {
  47. count = _info.LineArray[_lineIndex + 1] -
  48. _info.LineArray[_lineIndex];
  49. }
  50. else
  51. {
  52. count = _info.IndexArray.Count -
  53. _info.LineArray[_lineIndex];
  54. }
  55. return (count);
  56. }
  57. }
  58. /// <summary>
  59. /// Gets the ClassifiedToken instance at the specified startingPosition.
  60. /// Warning: this indexer always return the same instance.
  61. /// To keep data safe, it is strongly recommanded to make
  62. /// a deep copy of the returned ClassifiedToken.
  63. /// </summary>
  64. /// <param name="startingPosition">A zero based value in the range: [0 - Count[</param>
  65. /// <returns>The ClassifiedToken at this startingPosition.</returns>
  66. public ClassifiedToken this[int index]
  67. {
  68. get
  69. {
  70. InternalToken result;
  71. result = (InternalToken)_token;
  72. _populateToken(_lineIndex, index, result);
  73. return (result);
  74. }
  75. }
  76. /// <summary>
  77. /// Gets the part of the text at the given position.
  78. /// The returned string can be composed of one or severals words
  79. /// all with the same style.
  80. /// </summary>
  81. private void _populateToken(int lineIndex, int tokenIndex, InternalToken output)
  82. {
  83. int tagZero;
  84. int tagStart;
  85. int tagEnd;
  86. int strIndex_start;
  87. int strIndex_end;
  88. string res;
  89. ClassificationTag tag;
  90. //
  91. // Gets value of tagStart and tagEnd
  92. // from which string indexes can be extracted
  93. //
  94. tagZero = _info.LineArray[lineIndex];
  95. tagStart = tagZero + tokenIndex;
  96. tagEnd = tagStart + 1;
  97. strIndex_start = _info.IndexArray[tagStart];
  98. if (tagEnd < _info.IndexArray.Count)
  99. {
  100. strIndex_end = _info.IndexArray[tagEnd];
  101. res = _info.Text.Substring(strIndex_start, strIndex_end - strIndex_start);
  102. }
  103. else
  104. res = _info.Text.Substring(strIndex_start);
  105. //
  106. // Check the need to trimEnd() the resulting string.
  107. // We only want to trimEnd when current string is the
  108. // last part of the current line. Intermediary strings
  109. // must not be trimed end. At display time this would
  110. // lead to introduce bad shifting of text sequences.
  111. //
  112. if (res.EndsWith("\n"))
  113. res = res.TrimEnd();
  114. //
  115. // Convert the byte code into a ClassificationTag
  116. // for this string sequence
  117. //
  118. tag = _getTagFromByteValue(_info.TagArray[tagStart]);
  119. // and populate result
  120. output.Setup(res, tag);
  121. return;
  122. }
  123. /// <summary>
  124. /// Converts the given value into the matching ClassificationTag.
  125. /// </summary>
  126. private ClassificationTag _getTagFromByteValue(byte value)
  127. {
  128. switch (value)
  129. {
  130. case 0: return (ClassificationTag.Code);
  131. case 1: return (ClassificationTag.Keyword);
  132. case 2: return (ClassificationTag.Comment);
  133. case 3: return (ClassificationTag.String);
  134. default:
  135. UiExceptionHelper.CheckTrue(false, "should not reach this code", "value");
  136. break;
  137. }
  138. return (ClassificationTag.Code);
  139. }
  140. /// <summary>
  141. /// Return a string filled with the text present at the current line startingPosition.
  142. /// </summary>
  143. public string Text
  144. {
  145. get
  146. {
  147. int index_start;
  148. int index_start_ptr;
  149. int index_end;
  150. int index_end_ptr;
  151. string text;
  152. index_start_ptr = _info.LineArray[_lineIndex];
  153. index_start = _info.IndexArray[index_start_ptr];
  154. if (_lineIndex + 1 >= _info.LineArray.Count)
  155. index_end = _info.Text.Length;
  156. else
  157. {
  158. index_end_ptr = _info.LineArray[_lineIndex + 1];
  159. index_end = _info.IndexArray[index_end_ptr];
  160. }
  161. if (index_end - index_start < 0)
  162. throw new Exception(
  163. "ClassifiedTokenCollection: Text: error: calling substring with negative length");
  164. text = _info.Text.Substring(index_start, index_end - index_start);
  165. text = text.TrimEnd();
  166. return (text);
  167. }
  168. }
  169. #region InternalToken
  170. class InternalToken :
  171. ClassifiedToken
  172. {
  173. public InternalToken()
  174. {
  175. }
  176. public void Setup(string text, ClassificationTag tag)
  177. {
  178. _text = text;
  179. _tag = tag;
  180. }
  181. }
  182. #endregion
  183. }
  184. }