Пример #1
0
        private void DoUpdate()
        {
            // It would be good to do all of this work on a background thread but we can't:
            //      _classifier.GetClassificationSpans() should only be called on the UI thread because some classifiers assume they are called from the UI thread.
            //      Raising the TagsChanged event from the taggers needs to happen on the UI thread (because some consumers might assume it is being raised on the UI thread).
            //
            // Updating the snapshot for the factory and calling the sink can happen on any thread but those operations are so fast that there is no point.
            if (!_isDisposed)
            {
                if (_buffer.Equals(_textview.TextBuffer))
                {
                    ErrorSnapShot           oldErrors = this._factory.CurrentSnapshot;
                    ErrorSnapShot           newErrors = new ErrorSnapShot(this._filePath, oldErrors.VersionNumber + 1);
                    List <ErrorInformation> newSpanErrors;
                    // Go through the existing errors. If they are on the line we are currently parsing then
                    // copy them to oldLineErrors, otherwise they go to the new errors.

                    newSpanErrors = this.GetErrorInformation(_buffer.CurrentSnapshot.GetText());
                    if (!newSpanErrors.Equals(_spanErrors))
                    {
                        _spanErrors.Clear();
                        _spanErrors.AddRange(newSpanErrors);
                        foreach (ErrorInformation spanError in _spanErrors)
                        {
                            if (spanError.Length >= 0)
                            {
                                SnapshotSpan newSpan  = new SnapshotSpan(_buffer.CurrentSnapshot, spanError.StartIndex, spanError.Length);
                                ErrorSpan    oldError = oldErrors.Errors.Find((e) => e.Span == newSpan);

                                if (oldError != null)
                                {
                                    // There was a error at the same span as the old one so we should be able to just reuse it.
                                    oldError.NextIndex = newErrors.Errors.Count;
                                    newErrors.Errors.Add(ErrorSpan.Clone(oldError));    // Don't clone the old error yet
                                }
                                else
                                {
                                    newErrors.Errors.Add(new ErrorSpan(newSpan, spanError.ErrorMessage, spanError.ErrorCode));
                                }
                            }
                        }
                        this.UpdateErrors(newErrors);
                    }
                    else
                    {
                        foreach (var error in oldErrors.Errors)
                        {
                            error.NextIndex = -1;
                        }
                    }
                }
            }
            _isUpdating = false;
        }
Пример #2
0
        /// <summary>
        /// Quickly parses the entire text of the file and returns a span for each multi-line comment
        /// (because these cannot be determined from a snapshot without any context).
        /// </summary>
        /// <param name="snapshot">The text snapshot</param>
        /// <returns>A sequence of Spans (possibly empty) with one span for each multi-line comment in the file.</returns>
        private IEnumerable <Span> GetMultiLineComments(ITextSnapshot snapshot)
        {
            // use cache
            IList <Span> multiLineComments;

            _commentCache.TryGetValue(snapshot, out multiLineComments);
            if (multiLineComments != null)
            {
                return(multiLineComments);
            }

            multiLineComments = new List <Span>();

            string text = snapshot.GetText();

            int commentStart;
            int commentEnd = 0 - MultiLineCommentDelimiter.Length;

            do
            {
                commentStart = text.IndexOf(
                    MultiLineCommentDelimiter, commentEnd + MultiLineCommentDelimiter.Length, StringComparison.Ordinal);

                if (commentStart < 0)
                {
                    continue;
                }

                commentEnd = text.IndexOf(
                    MultiLineCommentDelimiter, commentStart + MultiLineCommentDelimiter.Length, StringComparison.Ordinal);

                if (commentEnd < 0)
                {
                    commentEnd = text.Length; // if there's no end then run to end of file
                }
                else
                {
                    commentEnd += MultiLineCommentDelimiter.Length;
                }

                multiLineComments.Add(Span.FromBounds(commentStart, commentEnd));

                Debug.Assert(
                    commentStart < commentEnd,
                    "Comment must have some width and the start and end must be the correct way around");
            } while (commentStart > -1 && commentEnd > -1 && commentEnd < text.Length);

            // Remove the cached version if there is one
            if (_commentCache.Count > 0)
            {
                //// ReSharper disable RedundantAssignment
                ITextBuffer buffer = snapshot.TextBuffer;
                //// ReSharper restore RedundantAssignment

                Debug.Assert(_commentCache.Count == 1, "There should be one item in the cache");
                Debug.Assert(buffer.Equals(_commentCache.Single().Key.TextBuffer), "The key should be the same");

                _commentCache.Clear();
            }

            // add to cache so we don't have to calculate it again for this snapshot
            _commentCache[snapshot] = multiLineComments;

            return(multiLineComments);
        }