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