private void OnBufferChange(object sender, TextContentChangedEventArgs e) { _currentSnapshot = e.After; // Translate all errors to the new snapshot (and remove anything that is a dirty region since we will need to check that again). var oldErrors = this._factory.CurrentSnapshot; var newErrors = new ErrorSnapShot(this._filePath, oldErrors.VersionNumber + 1); // Copy all of the old errors to the new errors unless the error was affected by the text change foreach (var error in oldErrors.Errors) { Debug.Assert(error.NextIndex == -1); ErrorSpan newError = ErrorSpan.CloneAndTranslateTo(error, e.After); if (newError != null) { Debug.Assert(newError.Span.Length == error.Span.Length); error.NextIndex = newErrors.Errors.Count; newErrors.Errors.Add(newError); } } this.UpdateErrors(newErrors); this.KickUpdate(); }
public static ErrorSpan CloneAndTranslateTo(ErrorSpan error, ITextSnapshot newSnapshot) { var newSpan = error.Span.TranslateTo(newSnapshot, SpanTrackingMode.EdgeExclusive); // We want to only translate the error if the length of the error span did not change (if it did change, it would imply that // there was some text edit inside the error and, therefore, that the error is no longer valid). return((newSpan.Length == error.Span.Length) ? new ErrorSpan(newSpan, error.ErrorMessage, error.ErrorCode) : null); }
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; }
private __VSERRORCATEGORY CheckErrorType(ErrorSpan errorSpan) { if (errorSpan.ErrorCode.StartsWith("WA")) { return(__VSERRORCATEGORY.EC_WARNING); } else if (errorSpan.ErrorCode.StartsWith("IF")) { return(__VSERRORCATEGORY.EC_MESSAGE); } else if (errorSpan.ErrorCode.StartsWith("ER")) { return(__VSERRORCATEGORY.EC_ERROR); } else { return(__VSERRORCATEGORY.EC_MESSAGE); } }
public static ErrorSpan Clone(ErrorSpan error) { return(new ErrorSpan(error.Span, error.ErrorMessage, error.ErrorCode)); }