internal static AP.ChangeInfo[] GetChanges(PythonTextBufferInfo buffer, ITextVersion curVersion) { var changes = new List <AP.ChangeInfo>(); if (curVersion.Changes != null) { foreach (var change in curVersion.Changes) { var oldPos = buffer.LocationTracker.GetSourceLocation(change.OldPosition, curVersion.VersionNumber); var oldEnd = buffer.LocationTracker.GetSourceLocation(change.OldEnd, curVersion.VersionNumber); changes.Add(new AP.ChangeInfo { startLine = oldPos.Line, startColumn = oldPos.Column, endLine = oldEnd.Line, endColumn = oldEnd.Column, newText = change.NewText, #if DEBUG _startIndex = change.OldPosition, _endIndex = change.OldEnd #endif }); } } #if DEBUG Debug.WriteLine("Getting changes for version {0}", curVersion.VersionNumber); foreach (var c in changes) { Debug.WriteLine($" - ({c.startLine}, {c.startColumn})-({c.endLine}, {c.endColumn}): \"{c.newText}\""); } #endif return(changes.ToArray()); }
public Span GetSpan(ITextVersion version) { return(Span.FromBounds( _start.GetPosition(version), _end.GetPosition(version) )); }
public TextSnapshot(ITextBuffer textBuffer, ITextVersion version, StringRebuilder content) : base(version) { System.Diagnostics.Debug.Assert(version.Length == content.Length); this.textBuffer = textBuffer; this.content = content; }
protected override int TrackPosition(ITextVersion targetVersion) { // Compute the new position on the requested snapshot. // // This method can be called simultaneously from multiple threads, and must be fast. // // We are relying on the atomicity of pointer copies (this.cachedPosition might change after we've // fetched it but we will always get a self-consistent VersionPosition). This ensures we // have proper behavior when called from multiple threads--multiple threads may all track and update the // cached value if called at inconvenient times, but they will return consistent results. // ForwardFidelity points do not support tracking backward, so consistency is not guaranteed in that case. VersionPosition cached = this.cachedPosition; int targetPosition; if (targetVersion == cached.Version) { targetPosition = cached.Position; } else if (targetVersion.VersionNumber > cached.Version.VersionNumber) { // Roll the cached version forward to the requested version. targetPosition = Tracking.TrackPositionForwardInTime(this.trackingMode, cached.Position, cached.Version, targetVersion); // Cache new cached version. this.cachedPosition = new VersionPosition(targetVersion, targetPosition); } else { // Roll backwards from the cached version. targetPosition = Tracking.TrackPositionBackwardInTime(this.trackingMode, cached.Position, cached.Version, targetVersion); } return(targetPosition); }
//Check to see if, when translating position to snapshot, the character after position was deleted. private static bool CharacterDeleted(SnapshotPoint position, ITextSnapshot snapshot) { int currentPosition = position.Position; ITextVersion version = position.Snapshot.Version; while (version.VersionNumber != snapshot.Version.VersionNumber) { foreach (ITextChange change in version.Changes) { if (change.NewPosition > currentPosition) { break; } else { if (change.NewPosition + change.OldLength > currentPosition) { //Line break (or the first character of it) was deleted. return(true); } else { //Change occurs entirely before currentPosition so adjust. currentPosition += change.Delta; } } } version = version.Next; } return(false); }
internal void DocumentClosed(ITextSnapshot savedSnapshot) { Assumes.NotNull(_originalVersion); if ((savedSnapshot != null) && (savedSnapshot.Version.VersionNumber > _originalVersion.VersionNumber)) { // The document was saved and we want to line/column indices in the saved snapshot (& not the current snapshot) var savedSpan = new SnapshotSpan(savedSnapshot, Tracking.TrackSpanForwardInTime(_trackingMode, _originalSpan, _originalVersion, savedSnapshot.Version)); PersistentSpan.SnapshotPointToLineIndex(savedSpan.Start, out _startLine, out _startIndex); PersistentSpan.SnapshotPointToLineIndex(savedSpan.End, out _endLine, out _endIndex); } else { // The document was never saved (or was saved before we created) so continue to use the old line/column indices. // Since those are set when either the span is created (against an open document) or when the document is reopened, // they don't need to be changed. } //We set this to false when the document is closed because we have an accurate line/index and that is more stable //than a simple offset. _useLineIndex = true; _originalSpan = default(Span); _originalVersion = null; _span = null; }
public async Task <ImmutableArray <NavigationBarItem> > GetItemsAsync( Document document, ITextVersion textVersion, CancellationToken cancellationToken) { var items = await _service.GetItemsAsync(document, cancellationToken).ConfigureAwait(false); return(ConvertItems(items, textVersion)); }
internal HighFidelityTrackingPoint(ITextVersion version, int position, PointTrackingMode trackingMode, TrackingFidelityMode fidelity) : base(version, position, trackingMode) { if (fidelity != TrackingFidelityMode.UndoRedo && fidelity != TrackingFidelityMode.Backward) { throw new ArgumentOutOfRangeException(nameof(fidelity)); } List <VersionNumberPosition> initialHistory = null; if (fidelity == TrackingFidelityMode.UndoRedo && version.VersionNumber > 0) { // The system may perform undo operations that reach prior to the initial version; if any of // those transitions are noninvertible, then redoing back to the initial version will give the // wrong answer. Thus we save the state of the point for the initial version, unless the // initial version happens to be version zero (in which case we could not undo past it). initialHistory = new List <VersionNumberPosition>(); if (version.VersionNumber != version.ReiteratedVersionNumber) { Debug.Assert(version.ReiteratedVersionNumber < version.VersionNumber); // If the current version and reiterated version differ, also remember the position // using the reiterated version number, since when undoing back to this point it // will be the key that is used. initialHistory.Add(new VersionNumberPosition(version.ReiteratedVersionNumber, position)); } initialHistory.Add(new VersionNumberPosition(version.VersionNumber, position)); } this.cachedPosition = new VersionPositionHistory(version, position, initialHistory); this.fidelity = fidelity; }
private static AP.ChangeInfo[] GetChanges(ITextVersion curVersion) { Debug.WriteLine("Changes for version {0}", curVersion.VersionNumber); var changes = new List <AP.ChangeInfo>(); if (curVersion.Changes != null) { AP.ChangeInfo prev = null; foreach (var change in curVersion.Changes) { Debug.WriteLine("Changes for version {0} {1} {2}", change.OldPosition, change.OldLength, change.NewText); if (prev != null && !string.IsNullOrEmpty(prev.newText) && change.OldLength == 0 && prev.length == 0 && prev.start + prev.newText.Length == change.OldPosition) { // we can merge the two changes together prev.newText += change.NewText; continue; } prev = new AP.ChangeInfo() { start = change.OldPosition, length = change.OldLength, newText = change.NewText }; changes.Add(prev); } } return(changes.ToArray()); }
private int ExecOnAll( ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut) { var result = 0; var pguidCmdGroupLocal = pguidCmdGroup; this.SelectionSwapExec( (tempSelections, targetSelections) => { // Begin the edit. this.dte.UndoContext.Open("Multi-point edit"); foreach (var selection in tempSelections) { selection.SetSelection(this.textView); this.expectedEditVersion = this.textView.TextSnapshot.Version; result = this.nextTarget.Exec(ref pguidCmdGroupLocal, nCmdID, nCmdexecopt, pvaIn, pvaOut); // Add the selection into the list again - we do this so that we have // clean selection details in the list and can handle any merging targetSelections.InsertExpectEnd(Utils.GetCurrentSelections(this.textView)); } // End the edit this.dte.UndoContext.Close(); }); pguidCmdGroup = pguidCmdGroupLocal; return(result); }
public BufferInfo(ITextBuffer buffer, int id) { Buffer = buffer; Id = id; _analysisVersion = buffer.CurrentSnapshot.Version; LastParsedVersion = _analysisVersion.VersionNumber - 1; }
private static IEnumerable <ITextVersion> GetVersions(ITextVersion from, ITextVersion to) { for (var v = from; v != null && v != to; v = v.Next) { yield return(v); } }
public Span GetSpan(ITextVersion version) { return Span.FromBounds( _start.GetPosition(version), _end.GetPosition(version) ); }
/// <summary> /// Constructs a TextBufferChangeUndoPrimitive. /// </summary> /// <param name="undoHistory"> /// The ITextUndoHistory this change will be added to. /// </param> /// <param name="textVersion"> /// The <see cref="ITextVersion" /> representing this change. /// This is actually the version associated with the snapshot prior to the change. /// </param> /// <exception cref="ArgumentNullException"><paramref name="undoHistory"/> is null.</exception> /// <exception cref="ArgumentNullException"><paramref name="textVersion"/> is null.</exception> public TextBufferChangeUndoPrimitive(ITextUndoHistory undoHistory, ITextVersion textVersion) { // Verify input parameters if (undoHistory == null) { throw new ArgumentNullException("undoHistory"); } if (textVersion == null) { throw new ArgumentNullException("textVersion"); } _textChanges = textVersion.Changes; _beforeVersion = textVersion.ReiteratedVersionNumber; _afterVersion = textVersion.Next.VersionNumber; Debug.Assert(textVersion.Next.VersionNumber == textVersion.Next.ReiteratedVersionNumber, "Creating a TextBufferChangeUndoPrimitive for a change that has previously been undone? This is probably wrong."); _undoHistory = undoHistory; TextBuffer = textVersion.TextBuffer; AttachedToNewBuffer = false; _canUndo = true; #if DEBUG // for debug sanity checks _bufferLengthAfterChange = textVersion.Next.Length; #endif }
public ElisionSnapshot(ElisionBuffer elisionBuffer, ITextSnapshot sourceSnapshot, ITextVersion version, ElisionMap content, bool fillInMappingMode) : base(version) { this.elisionBuffer = elisionBuffer; this.sourceSnapshot = sourceSnapshot; // The SourceSnapshots property is used heavily, so cache a handy copy. this.sourceSnapshots = new ReadOnlyCollection <ITextSnapshot>(new FrugalList <ITextSnapshot>() { sourceSnapshot }); this.totalLength = content.Length; this.content = content; this.totalLineCount = content.LineCount; this.fillInMappingMode = fillInMappingMode; Debug.Assert(this.totalLength == version.Length, string.Format(System.Globalization.CultureInfo.CurrentCulture, "Elision Snapshot Inconsistency. Content: {0}, Previous + delta: {1}", this.totalLength, version.Length)); if (this.totalLength != version.Length) { throw new InvalidOperationException(Strings.InvalidLengthCalculation); } }
public MultilineCommentToken(IClassificationType type, ITrackingSpan span, ITextVersion version) : base(TokenType.MultilineComment) { classificationType = type; trackingSpan = span; textVersion = version; }
public MouseLeftDownInfo(VirtualSnapshotSpan span, Point point, int clicks, ITextVersion version) { Span = span; Point = point; Clicks = clicks; Version = version; }
private void Initialize(TextBuffer buffer, ITextVersion bufferVersion, Int32 position, TrackingMode trackingMode) { _version = bufferVersion; _textBuffer = buffer; _position = position; _trackingMode = trackingMode; }
public async Task <bool> TryNavigateToItemAsync( Document document, NavigationBarItem item, ITextView view, ITextVersion textVersion, CancellationToken cancellationToken) { // The logic here was ported from FSharp's implementation. The main reason was to avoid shimming INotificationService. var navigationSpan = item.TryGetNavigationSpan(textVersion); if (navigationSpan != null) { var span = navigationSpan.Value; var workspace = document.Project.Solution.Workspace; var navigationService = workspace.Services.GetRequiredService <IFSharpDocumentNavigationService>(); await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); if (navigationService.CanNavigateToPosition(workspace, document.Id, span.Start, virtualSpace: 0, cancellationToken)) { navigationService.TryNavigateToPosition(workspace, document.Id, span.Start, virtualSpace: 0, options: null, cancellationToken); } else { var notificationService = workspace.Services.GetRequiredService <INotificationService>(); notificationService.SendNotification(EditorFeaturesResources.The_definition_of_the_object_is_hidden, severity: NotificationSeverity.Error); } } return(true); }
public Model(ITextVersion textVersion, QuickInfoItem item, bool trackMouse) { Contract.ThrowIfNull(item); this.TextVersion = textVersion; this.Item = item; this.TrackMouse = trackMouse; }
public TextVersionMock CreateNextVersion(TextChangeMock change) { _change = change; var nextVersion = new TextVersionMock(TextBuffer, VersionNumber + 1, Length + _change.Delta); Next = nextVersion; return(nextVersion); }
private void UpdateVersion(ITextSnapshot snapshot) { ITextVersion v = snapshot.Version; VersionText = "V " + v.VersionNumber.ToString(); ReiteratedText = "R " + v.ReiteratedVersionNumber.ToString(); this.prevVersion = v; }
public TextVersionMock CreateNextVersion(TextChangeMock change) { _change = change; TextVersionMock nextVersion = new TextVersionMock(TextBuffer, VersionNumber + 1, Length + _change.Delta); Next = nextVersion; return nextVersion; }
/// <summary> /// Initializes a new instance of the <see cref="ClassificationSpan"/> class. /// </summary> /// <exception cref="ArgumentNullException"><para><paramref name="classification"/> is <see langword="null"/>.</para></exception> public ClassificationSpan(TextBuffer buffer, ITextVersion version, Int32 start, Int32 length, String classification) : base(buffer, version, start, length) { if (classification == null) { throw new ArgumentNullException("classification"); } _classification = classification; }
public void CheckCompilationVersion() { ITextVersion textVersion = this.TextBuffer?.CurrentSnapshot?.Version; if (this.backgroundVersion == null || this.backgroundVersion != textVersion) { Interlocked.Exchange(ref this.backgroundVersion, textVersion); this.Compile(); } }
public void Dispose() { if (this.SpanSet != null) { this.SpanSet.Delete(this); this.SpanSet = null; _originalVersion = null; _span = null; } }
public TextSpan?TryGetNavigationSpan(ITextVersion textVersion) { if (this.NavigationSpan == null) { return(null); } return(this.TextVersion !.CreateTrackingSpan(this.NavigationSpan.Value.ToSpan(), SpanTrackingMode.EdgeExclusive) .GetSpan(textVersion).ToTextSpan()); }
public VersionSpanHistory(ITextVersion version, Span span, List <VersionNumberPosition> noninvertibleStartHistory, List <VersionNumberPosition> noninvertibleEndHistory) { this.version = version; this.span = span; this.noninvertibleStartHistory = noninvertibleStartHistory; this.noninvertibleEndHistory = noninvertibleEndHistory; }
protected async Task NavigateToSymbolItemAsync( Document document, NavigationBarItem item, SymbolItem symbolItem, ITextVersion textVersion, CancellationToken cancellationToken) { var workspace = document.Project.Solution.Workspace; var(documentId, position, virtualSpace) = await GetNavigationLocationAsync( document, item, symbolItem, textVersion, cancellationToken).ConfigureAwait(false); await NavigateToPositionAsync(workspace, documentId, position, virtualSpace, cancellationToken).ConfigureAwait(false); }
protected override int TrackPosition(ITextVersion targetVersion) { // Compute the new position on the requested snapshot. // This object caches the most recently requested version and the position in that version. // // We are relying on the atomicity of pointer copies (this.cachedPosition might change after we've // fetched it below but we will always get a self-consistent VersionPosition). This ensures we // have proper behavior when called from multiple threads (multiple threads may all track and update the // cached value if called at inconvenient times, but they will return consistent results). // // In most cases, one can track backwards from the cached version to a previously computed // version and get the same result, but this is not always the case: in particular, when the // position lies in a deleted region, simulating reinsertion of that region will not cause // the previous value of the position to be recovered. Such transitions are called noninvertible. // This class explicitly tracks the positions of the point for versions for which the subsequent // transition is noninvertible; this allows the value to be computed properly when tracking backwards // or in undo/redo situations. VersionPositionHistory cached = this.cachedPosition; // must fetch just once if (targetVersion == cached.Version) { // easy! return(cached.Position); } List <VersionNumberPosition> noninvertibleHistory = cached.NoninvertibleHistory; int targetPosition; if (targetVersion.VersionNumber > cached.Version.VersionNumber) { // Roll the cached version forward to the requested version. targetPosition = TrackPositionForwardInTime (this.trackingMode, this.fidelity, ref noninvertibleHistory, cached.Position, cached.Version, targetVersion); // Cache new position this.cachedPosition = new VersionPositionHistory(targetVersion, targetPosition, noninvertibleHistory); } else { // roll backwards from the cached version targetPosition = TrackPositionBackwardInTime (this.trackingMode, this.fidelity == TrackingFidelityMode.Backward ? noninvertibleHistory : null, cached.Position, cached.Version, targetVersion); } return(targetPosition); }
private SnapshotPoint GetPoint(ITextVersion version) { if (version.TextBuffer != _snapshot.TextBuffer) { Debug.Fail("Mismatched buffers"); throw new ArgumentException("Mismatched text buffers"); } var newPos = _position; var current = _snapshot.Version; var target = version; var toSnapshot = ((MockTextVersion)target)._snapshot; if (current.VersionNumber > target.VersionNumber) { // Apply the changes in reverse var changesStack = new Stack<INormalizedTextChangeCollection>(); for (var v = target; v.VersionNumber < current.VersionNumber; v = v.Next) { changesStack.Push(v.Changes); } while (changesStack.Count > 0) { foreach (var change in changesStack.Pop()) { if (change.Delta > 0 && change.NewPosition <= newPos && change.NewPosition - change.Delta > newPos) { // point was deleted newPos = change.NewPosition; } else if (change.NewPosition == newPos) { if (_mode == PointTrackingMode.Positive) { newPos -= change.Delta; } } else if (change.NewPosition < newPos) { newPos -= change.Delta; } } } } else if (current.VersionNumber < target.VersionNumber) { // Apply the changes normally for (var v = current; v.VersionNumber < target.VersionNumber; v = v.Next) { foreach (var change in v.Changes) { if (change.Delta < 0 && change.OldPosition <= newPos && change.OldPosition - change.Delta > newPos) { // point was deleted newPos = change.OldPosition; } else if (change.OldPosition == newPos) { if (_mode == PointTrackingMode.Positive) { newPos += change.Delta; } } else if(change.OldPosition < newPos) { newPos += change.Delta; } } } } Debug.Assert(newPos >= 0, string.Format("new point '{0}' should be zero or greater", newPos)); Debug.Assert(newPos <= toSnapshot.Length, string.Format("new point '{0}' should be {1} or less", newPos, toSnapshot.Length)); return new SnapshotPoint(toSnapshot, newPos); }
// Returns spans corresponding to the changes that occurred between startVersion and endVersion public static bool GetChangedExtent(this ITextVersion oldVersion, ITextVersion newVersion, out Span?oldSpan, out Span?newSpan) { oldSpan = null; newSpan = null; if (oldVersion.VersionNumber > newVersion.VersionNumber) { // They've asked for information about an earlier snapshot, not supported Debug.Assert(false); return(false); } int newEnd = Int32.MinValue; int position = Int32.MaxValue; int deltaLen = 0; while (oldVersion != newVersion) { INormalizedTextChangeCollection changes = oldVersion.Changes; if (changes.Count > 0) { ITextChange firstChange = changes[0]; ITextChange lastChange = changes[changes.Count - 1]; int changeDeltaLen = lastChange.NewEnd - lastChange.OldEnd; deltaLen += changeDeltaLen; position = Math.Min(position, firstChange.NewPosition); if (newEnd < lastChange.OldEnd) { newEnd = lastChange.NewEnd; } else { newEnd += changeDeltaLen; } } oldVersion = oldVersion.Next; } if (newEnd < position) { // There weren't any changes between the versions, return a null TextChangeExtent return(false); } int oldEnd = newEnd - deltaLen; oldSpan = Span.FromBounds(position, oldEnd); newSpan = Span.FromBounds(position, newEnd); return(true); }
public TrackingPoint(ITextVersion textVersion, int position, PointTrackingMode trackingMode, TrackingFidelityMode trackingFidelity) { if (textVersion == null) throw new ArgumentNullException(nameof(textVersion)); if ((uint)position > (uint)textVersion.Length) throw new ArgumentOutOfRangeException(nameof(position)); TextBuffer = textVersion.TextBuffer; TrackingMode = trackingMode; TrackingFidelity = trackingFidelity; this.textVersion = textVersion; this.position = position; }
public Model( ITextVersion textVersion, QuickInfoItem item, IQuickInfoProvider provider, bool trackMouse) { this.TextVersion = textVersion; this.Item = item; this.Provider = provider; this.TrackMouse = trackMouse; }
public TrackingSpan(ITextVersion textVersion, Span span, SpanTrackingMode trackingMode, TrackingFidelityMode trackingFidelity) { if (textVersion == null) throw new ArgumentNullException(nameof(textVersion)); if ((uint)span.End > (uint)textVersion.Length) throw new ArgumentOutOfRangeException(nameof(span)); TextBuffer = textVersion.TextBuffer; TrackingFidelity = trackingFidelity; TrackingMode = trackingMode; this.textVersion = textVersion; this.span = span; }
private SnapshotPoint GetPoint(ITextVersion version) { var current = _snapshot.Version; var target = version; if (current.VersionNumber == target.VersionNumber) { return new SnapshotPoint(_snapshot, _position); } else if (current.VersionNumber > target.VersionNumber) { // Apply the changes in reverse var changesStack = new Stack<INormalizedTextChangeCollection>(); for (var v = target; v.VersionNumber < current.VersionNumber; v = v.Next) { changesStack.Push(v.Changes); } var newPos = _position; while (changesStack.Count > 0) { foreach (var change in changesStack.Pop()) { if (change.Delta > 0 && change.NewPosition <= newPos && change.NewPosition - change.Delta > newPos) { // point was deleted newPos = change.NewPosition; } else if (change.NewPosition == newPos) { if (_mode == PointTrackingMode.Positive) { newPos -= change.Delta; } } else if (change.NewPosition < newPos) { newPos -= change.Delta; } } } return new SnapshotPoint(((MockTextVersion)target)._snapshot, newPos); } else { // Apply the changes normally var newPos = _position; for (var v = current; v.VersionNumber < target.VersionNumber; v = v.Next) { foreach (var change in v.Changes) { if (change.Delta < 0 && change.OldPosition <= newPos && change.OldPosition - change.Delta > newPos) { // point was deleted newPos = change.OldPosition; } else if (change.OldPosition == newPos) { if (_mode == PointTrackingMode.Positive) { newPos += change.Delta; } } else if(change.OldPosition < newPos) { newPos += change.Delta; } } } return new SnapshotPoint(((MockTextVersion)target)._snapshot, newPos); } }
public Model( ITextVersion textVersion, QuickInfoItem item, IQuickInfoProvider provider, bool trackMouse) { Contract.ThrowIfNull(item); this.TextVersion = textVersion; this.Item = item; this.Provider = provider; this.TrackMouse = trackMouse; }
public TextSnapshot(ITextSource textSource, IContentType contentType, TextBuffer textBuffer, ITextVersion textVersion) { if (textSource == null) throw new ArgumentNullException(nameof(textSource)); if (contentType == null) throw new ArgumentNullException(nameof(contentType)); if (textBuffer == null) throw new ArgumentNullException(nameof(textBuffer)); if (textVersion == null) throw new ArgumentNullException(nameof(textVersion)); this.textSource = textSource; ContentType = contentType; TextBuffer = textBuffer; Version = textVersion; }
/// <summary> /// Creates a new location tracker which can track spans and positions through time. /// /// The tracker will translate positions from the specified version to the current /// snapshot in VS. Requests can be made to track either forwards or backwards. /// </summary> public LocationTracker(ITextVersion lastAnalysisVersion, ITextBuffer buffer, int fromVersion) { // We always hold onto the last version that we've successfully analyzed, as that's // the last event the out of proc analyzer will send us. Once we've received // that event all future information should come from at least that version. This // prevents us from holding onto every version in the world. Debug.Assert(fromVersion >= lastAnalysisVersion.VersionNumber); while (lastAnalysisVersion.VersionNumber != fromVersion) { lastAnalysisVersion = lastAnalysisVersion.Next; } _fromVersion = lastAnalysisVersion; _buffer = buffer; }
/// <summary> /// May return <code>null</code> if span is outside range of document. /// </summary> private ITrackingSpan CreateTrackingSpan(ITextVersion version, int position, int length) { // Check range of span is ok (we don't know what happen to the files // on disk, so we have to be safe) if ((0 <= position) && (position + length <= version.Length)) { // See http://blogs.msdn.com/b/noahric/archive/2009/06/06/editor-perf-markers-vs-tracking-spans.aspx // Never grows the tracking span. const SpanTrackingMode mode = SpanTrackingMode.EdgeExclusive; var span = version.CreateTrackingSpan( new Span(position, length), mode, TrackingFidelityMode.Forward); return span; } else { return null; } }
public int GetPosition(ITextVersion version) { if (version == null) throw new ArgumentNullException(nameof(version)); if (version == textVersion) return position; if (version.TextBuffer != textVersion.TextBuffer) throw new ArgumentException(); // Rewrite the values since it's common to just move in one direction. This can lose // information: if we move forward and then backward, we might get another position. position = version.VersionNumber > textVersion.VersionNumber ? Tracking.TrackPositionForwardInTime(TrackingMode, position, textVersion, version) : Tracking.TrackPositionBackwardInTime(TrackingMode, position, textVersion, version); textVersion = version; return position; }
public Span GetSpan(ITextVersion version) { var start = _start.GetPosition(version); var end = _end.GetPosition(version); if (start > end) { // start has positive tracking, end has negative, everything has been deleted // and our spans have become inverted. return new Span( start, 0 ); } return Span.FromBounds( _start.GetPosition(version), _end.GetPosition(version) ); }
public Span GetSpan(ITextVersion version) { var current = _snapshot.Version; var target = version; if (current.VersionNumber == target.VersionNumber) { return new Span(_start, _length); } else if (current.VersionNumber > target.VersionNumber) { // Apply the changes in reverse var changesStack = new Stack<INormalizedTextChangeCollection>(); for (var v = target; v.VersionNumber < current.VersionNumber; v = v.Next) { changesStack.Push(v.Changes); } var newStart = _start; var newLength = _length; while (changesStack.Count > 0) { foreach (var change in changesStack.Pop()) { if (change.NewPosition <= newStart) { newStart -= change.Delta; } else if (change.NewPosition <= newStart + newLength) { newLength -= change.Delta; } } } return new Span(newStart, newLength); } else { // Apply the changes normally var newStart = _start; var newLength = _length; for (var v = current; v.VersionNumber < target.VersionNumber; v = v.Next) { foreach (var change in v.Changes) { if (change.OldPosition < newStart) { newStart += change.Delta; } else if (change.OldPosition < newStart + newLength) { newLength += change.Delta; } } } return new Span(newStart, newLength); } }
/// <summary> /// Initializes a new instance of the <see cref="VersionedTextSpan"/> class. /// </summary> /// <exception cref="ArgumentNullException"> /// <para><paramref name="buffer"/> is <see langword="null"/>.</para> /// -or- /// <para><paramref name="span"/> is <see langword="null"/>.</para> /// -or- /// <para><paramref name="version"/> is <see langword="null"/>.</para> /// </exception> public VersionedTextSpan(TextBuffer buffer, ITextVersion version, Span span) { if (buffer == null) { throw new ArgumentNullException("buffer"); } if (version == null) { throw new ArgumentNullException("version"); } if (span == null) { throw new ArgumentNullException("span"); } this.Construct(buffer, buffer.Version, span.Start, span.Length, SpanTrackingMode.EdgeExclusive); }
/// <summary> /// Creates a new location tracker which can track spans and positions through time. /// /// The tracker will translate positions from the specified version to the current /// snapshot in VS. Requests can be made to track either forwards or backwards. /// </summary> public LocationTracker(ITextVersion lastAnalysisVersion, ITextBuffer buffer, int fromVersion) { // We always hold onto the last version that we've successfully analyzed, as that's // the last event the out of proc analyzer will send us. Once we've received // that event all future information should come from at least that version. This // prevents us from holding onto every version in the world. if (fromVersion >= lastAnalysisVersion.VersionNumber) { while (lastAnalysisVersion.Next != null && lastAnalysisVersion.VersionNumber != fromVersion) { lastAnalysisVersion = lastAnalysisVersion.Next; } } else { // Warn the developer, but we should be able to continue with // the ITextVersion that was provided. Debug.Fail("fromVersion {0} was less than lastAnalysisVersion {1}".FormatInvariant(fromVersion, lastAnalysisVersion.VersionNumber)); } _fromVersion = lastAnalysisVersion; _buffer = buffer; }
public bool TryAdvanceVersion(ITextVersion newVersion) { var v = Version; while (v != newVersion) { var changes = v.Changes; if (changes == null) break; if (changes.Count == 1 && changes[0].OldPosition == 0 && changes[0].OldLength == v.Length) return false; v = v.Next; } Version = newVersion; return true; }
public Span GetSpan(ITextVersion version) { throw new NotImplementedException(); }
private static IEnumerable<IEnumerable<TextChangeRange>> GetMultipleVersionTextChanges(ITextVersion oldVersion, ITextVersion newVersion, bool forward) { for (var version = oldVersion; version != newVersion; version = version.Next) { yield return version.Changes.Select(forward ? s_forwardTextChangeRange : s_backwardTextChangeRange); } }
/// <summary> /// </summary> /// <exception cref="ArgumentNullException"> /// <para> /// <paramref name="targetVersion"/> is <see langword="null"/>. /// </para> /// -or- /// <para> /// The specified <paramref name="version"/> does not belong to the specified <paramref name="buffer"/>. /// </para> /// </exception> public Span Span(ITextVersion targetVersion) { if (targetVersion == null) { throw new ArgumentNullException("targetVersion"); } if (!_buffer.VersionBelongsToBuffer(targetVersion)) { throw new ArgumentException("The specified TextVersion does not belong to the specified TextBuffer"); } ITextVersion next = _version; Int32 num = TextBuffer.CompareVersions(next, targetVersion); Int32 position = _start; Int32 num3 = _start + _length; if (num < 0) { while (next != targetVersion) { if (_trackingMode == SpanTrackingMode.EdgeExclusive) { position = TextSpan.UpdatePositiveTrackingPoint(next.Change, position); num3 = TextSpan.UpdateNegativeTrackingPoint(next.Change, num3); } else { position = TextSpan.UpdateNegativeTrackingPoint(next.Change, position); num3 = TextSpan.UpdatePositiveTrackingPoint(next.Change, num3); } next = next.Next; } } else if (num > 0) { Stack<TextChange> stack = new Stack<TextChange>(1); for (ITextVersion version2 = targetVersion; version2 != next; version2 = version2.Next) { stack.Push(version2.Change); } while (stack.Count > 0) { TextChange change = stack.Pop(); if (_trackingMode == SpanTrackingMode.EdgeExclusive) { if (change.Position <= position) { position -= change.Delta; } if (change.Position < num3) { num3 -= change.Delta; } } else { if (change.Position < position) { position -= change.Delta; } if (change.Position <= num3) { num3 -= change.Delta; } } } } if (num3 < position) { num3 = position; } return new Span(position, num3 - position); }
/// <summary> /// Initializes a new instance of the <see cref="VersionedTextSpan"/> class. /// </summary> /// <exception cref="ArgumentNullException"> /// <para><paramref name="buffer"/> is <see langword="null"/>.</para> /// -or- /// <para><paramref name="version"/> is <see langword="null"/>.</para> /// </exception> public VersionedTextSpan(TextBuffer buffer, ITextVersion version, Int32 start, Int32 length) { if (buffer == null) { throw new ArgumentNullException("buffer"); } if (version == null) { throw new ArgumentNullException("version"); } this.Construct(buffer, version, start, length, SpanTrackingMode.EdgeExclusive); }
public int GetPosition(ITextVersion version) { return _position; }
private TextChangeRange GetChangeRanges(ITextVersion oldVersion, ITextVersion newVersion, bool forward) { TextChangeRange? range = null; var iterator = GetMultipleVersionTextChanges(oldVersion, newVersion, forward); foreach (var changes in forward ? iterator : iterator.Reverse()) { range = range.Accumulate(changes); } Contract.Requires(range.HasValue); return range.Value; }
public Span GetSpan(ITextVersion version) { return _span; }
// Returns spans corresponding to the changes that occurred between startVersion and endVersion public static bool GetChangedExtent(this ITextVersion oldVersion, ITextVersion newVersion, out Span? oldSpan, out Span? newSpan) { oldSpan = null; newSpan = null; if (oldVersion.VersionNumber > newVersion.VersionNumber) { // They've asked for information about an earlier snapshot, not supported Debug.Assert(false); return false; } int newEnd = Int32.MinValue; int position = Int32.MaxValue; int deltaLen = 0; while (oldVersion != newVersion) { INormalizedTextChangeCollection changes = oldVersion.Changes; if (changes.Count > 0) { ITextChange firstChange = changes[0]; ITextChange lastChange = changes[changes.Count - 1]; int changeDeltaLen = lastChange.NewEnd - lastChange.OldEnd; deltaLen += changeDeltaLen; position = Math.Min(position, firstChange.NewPosition); if (newEnd < lastChange.OldEnd) { newEnd = lastChange.NewEnd; } else { newEnd += changeDeltaLen; } } oldVersion = oldVersion.Next; } if (newEnd < position) { // There weren't any changes between the versions, return a null TextChangeExtent return false; } int oldEnd = newEnd - deltaLen; oldSpan = Span.FromBounds(position, oldEnd); newSpan = Span.FromBounds(position, newEnd); return true; }
/// <summary> /// Initializes a new instance of the <see cref="VersionedTextSpan"/> class. /// </summary> /// <exception cref="ArgumentNullException"> /// <para><paramref name="buffer"/> is <see langword="null"/>.</para> /// -or- /// <para><paramref name="version"/> is <see langword="null"/>.</para> /// </exception> /// <exception cref="ArgumentException"> /// <para>The specified <paramref name="version"/> does not belong to the specified <paramref name="buffer"/>.</para> /// </exception> public VersionedTextSpan(TextBuffer buffer, ITextVersion version, Int32 start, Int32 length, SpanTrackingMode trackingMode) { if (buffer == null) { throw new ArgumentNullException("buffer"); } if (version == null) { throw new ArgumentNullException("version"); } if (!buffer.VersionBelongsToBuffer(version)) { throw new ArgumentException("The specified TextVersion does not belong to the specified TextBuffer."); } this.Construct(buffer, version, start, length, trackingMode); }
public Span GetSpan(ITextVersion version) { return new Span(_start, _length); }
Span ITrackingSpan.GetSpan(ITextVersion version) { throw new System.NotImplementedException(); }
private void Construct(TextBuffer buffer, ITextVersion version, Int32 start, Int32 length, SpanTrackingMode trackingMode) { Int32 lengthOfVersion = buffer.GetLengthOfVersion(version); if ((start < 0) || (start > lengthOfVersion)) { throw new ArgumentOutOfRangeException("start"); } if ((length < 0) || ((start + length) > lengthOfVersion)) { throw new ArgumentOutOfRangeException("length"); } _buffer = buffer; _version = version; _start = start; _length = length; _trackingMode = trackingMode; }