Пример #1
0
        /// <summary>
        /// This method scans the given SnapshotSpan for potential matches for this classification.
        /// </summary>
        /// <param name="span">The span currently being classified.</param>
        /// <returns>A list of ClassificationSpans that represent spans identified to be of this classification.</returns>
        public IList<ClassificationSpan> GetClassificationSpans(SnapshotSpan span)
        {
            // TODO this is an inefficient call to GetMultiLineComments each time!
            var multiLineComments = GetMultiLineComments(span);

            var compiler = new Compiler();
            compiler.Options.Add("number", "float");

            // Use Cobra's own tokenizer
            var tokCobra = new VisualCobraTokenizer
                               {
                                   TypeProvider = compiler,
                                   WillReturnComments = true,
                                   WillReturnDirectives = true
                               };

            Node.SetCompiler(compiler);
            tokCobra.StartSource(span.GetText());
            
            var classifications = GetClassificationsFromCobraTokenizer(span, tokCobra);

            // Add classification spans for indent errors
            classifications.AddRange(GetIndentErrorSpans(span));

            var removeMe = new List<ClassificationSpan>();
            var e = classifications.GetEnumerator();
            while (e.MoveNext())
            {
                if (e.Current != null)
                {
                    removeMe.AddRange(from comment in multiLineComments
// ReSharper disable PossibleNullReferenceException
                                      where comment.Contains(e.Current.Span)
// ReSharper restore PossibleNullReferenceException
                                      select e.Current);
                }
            }

            foreach (var remove in removeMe)
            {
                classifications.Remove(remove);
            }

            // Add all comment spans
            // TODO Many of these will be out of bounds, so they should perhaps be trimmed down first
            classifications.AddRange(multiLineComments.Select(comment => new ClassificationSpan(new SnapshotSpan(span.Snapshot, comment), _cobraCommentClassificationType)));

            return classifications;
        }
Пример #2
0
 /// <summary>
 /// Gets the classifications from <see cref="VisualCobraTokenizer"/>.
 /// </summary>
 /// <param name="span">The span to get classifications from.</param>
 /// <param name="tokCobra">The tokenizer to use.</param>
 /// <returns>A list of <see cref="ClassificationSpan"/> objects representing the classifications
 /// in <paramref name="span"/>.</returns>
 private static List<ClassificationSpan> GetClassificationsFromCobraTokenizer(SnapshotSpan span, VisualCobraTokenizer tokCobra)
 {
     // Tried parallelising, but I'm not sure it's safe in combination with "previous".
     var classifications = new List<ClassificationSpan>();
     IToken previous = null;
     foreach (var tok in tokCobra.AllTokens())
     {
         if (tok.IsKeyword)
         {
             var tokenSpan = new SnapshotSpan(span.Snapshot, new Span(span.Start.Position + tok.CharNum - 1, tok.Length)); // +1
             var cs = new ClassificationSpan(tokenSpan, _cobraKeywordClassificationType);
             classifications.Add(cs);
         }
         else
         {
             switch (tok.Which)
             {
                 case "STRING_SINGLE":
                 case "STRING_DOUBLE":
                 case "CHAR":
                 case "CHAR_LIT_SINGLE":
                     AddSpanToClassifications(span, classifications, tok, tok.Length, _cobraStringClassificationType);
                     break;
                 case "ID": // Note "CLASS" is the class keyword, not "a class"
                     if (IsClass(tok))
                     {
                         AddSpanToClassifications(span, classifications, tok, tok.Length, _cobraClassClassificationType);
                     }
                     break;
                 case "QUESTION":
                     {
                         if (IsClass(previous))
                         {
                             // add another char to cover the ? on the end of a nillable class
                             AddSpanToClassifications(span, classifications, tok, 1, _cobraClassClassificationType);
                         }
                         break;
                     }
                 case "COMMENT":
                     AddSpanToClassifications(span, classifications, tok, tok.Length, _cobraCommentClassificationType);
                     break;
             }
             previous = tok;
         }
     }
     return classifications;
 }