Beispiel #1
0
        public ElisionBuffer(IProjectionEditResolver resolver,
                             IContentType contentType,
                             ITextBuffer sourceBuffer,
                             NormalizedSpanCollection exposedSpans,
                             ElisionBufferOptions options,
                             ITextDifferencingService textDifferencingService,
                             GuardedOperations guardedOperations)
            : base(resolver, contentType, textDifferencingService, guardedOperations)
        {
            Debug.Assert(sourceBuffer != null);
            this.sourceBuffer   = sourceBuffer;
            this.sourceSnapshot = sourceBuffer.CurrentSnapshot;

            BaseBuffer baseSourceBuffer = (BaseBuffer)sourceBuffer;

            this.eventHook = new WeakEventHook(this, baseSourceBuffer);

            this.group = baseSourceBuffer.group;
            this.group.AddMember(this);

            this.content = new ElisionMap(this.sourceSnapshot, exposedSpans);

            StringRebuilder newBuilder = StringRebuilder.Empty;

            for (int i = 0; (i < exposedSpans.Count); ++i)
            {
                newBuilder = newBuilder.Append(BufferFactoryService.StringRebuilderFromSnapshotAndSpan(this.sourceSnapshot, exposedSpans[i]));
            }
            this.builder = newBuilder;

            this.elisionOptions = options;
            this.currentVersion.SetLength(content.Length);
            this.currentElisionSnapshot = new ElisionSnapshot(this, this.sourceSnapshot, base.currentVersion, this.builder, this.content, (options & ElisionBufferOptions.FillInMappingMode) != 0);
            this.currentSnapshot        = this.currentElisionSnapshot;
        }
Beispiel #2
0
 public ElisionSnapshot(ElisionBuffer elisionBuffer,
                        ITextSnapshot sourceSnapshot,
                        ITextVersion2 version,
                        StringRebuilder builder,
                        ElisionMap content,
                        bool fillInMappingMode)
     : base(version, builder)
 {
     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);
     }
 }
Beispiel #3
0
        public ElisionMap IncorporateChanges(INormalizedTextChangeCollection sourceChanges,
                                             FrugalList <TextChange> projectedChanges,
                                             ITextSnapshot beforeSourceSnapshot,
                                             ITextSnapshot sourceSnapshot,
                                             ITextSnapshot beforeElisionSnapshot)
        {
            ElisionMapNode newRoot = this.root;
            int            accumulatedProjectedDelta = 0;

            foreach (ITextChange sourceChange in sourceChanges)
            {
                int             accumulatedDelete = 0;
                int             incrementalAccumulatedProjectedDelta = 0;
                StringRebuilder newText = TextChange.NewStringRebuilder(sourceChange);

                newRoot = newRoot.IncorporateChange(beforeSourceSnapshot: beforeSourceSnapshot,
                                                    afterSourceSnapshot: sourceSnapshot,
                                                    beforeElisionSnapshot: beforeElisionSnapshot,
                                                    sourceInsertionPosition: sourceChange.NewLength > 0 ? sourceChange.NewPosition : (int?)null,
                                                    newText: newText,
                                                    sourceDeletionSpan: new Span(sourceChange.NewPosition, sourceChange.OldLength),
                                                    absoluteSourceOldPosition: sourceChange.OldPosition,
                                                    absoluteSourceNewPosition: sourceChange.NewPosition,
                                                    projectedPrefixSize: 0,
                                                    projectedChanges: projectedChanges,
                                                    incomingAccumulatedDelta: accumulatedProjectedDelta,
                                                    outgoingAccumulatedDelta: ref incrementalAccumulatedProjectedDelta,
                                                    accumulatedDelete: ref accumulatedDelete);
                accumulatedProjectedDelta += incrementalAccumulatedProjectedDelta;
            }
            if (newRoot.TotalSourceSize != sourceSnapshot.Length)
            {
                Debug.Fail(String.Format(System.Globalization.CultureInfo.InvariantCulture,
                                         "Change incorporation length inconsistency. Elision:{0} Source:{1}", newRoot.TotalSourceSize, sourceSnapshot.Length));
                throw new InvalidOperationException(Strings.InvalidLengthCalculation);
            }
            if (newRoot.TotalSourceLineBreakCount + 1 != sourceSnapshot.LineCount)
            {
                Debug.Fail(String.Format(System.Globalization.CultureInfo.InvariantCulture,
                                         "Change incorporation line count inconsistency. Elision:{0} Source:{1}", newRoot.TotalSourceLineBreakCount + 1, sourceSnapshot.LineCount));
                throw new InvalidOperationException(Strings.InvalidLineCountCalculation);
            }
            return(new ElisionMap(newRoot, this.spanCount));
        }
Beispiel #4
0
        public ProjectionSnapshot(ProjectionBuffer projectionBuffer, ITextVersion2 version, StringRebuilder content, IList <SnapshotSpan> sourceSpans)
            : base(version, content)
        {
            this.projectionBuffer = projectionBuffer;
            this.sourceSpans      = new ReadOnlyCollection <SnapshotSpan>(sourceSpans);

            this.cumulativeLengths         = new int[sourceSpans.Count + 1];
            this.cumulativeLineBreakCounts = new int[sourceSpans.Count + 1];

            this.sourceSnapshotMap = new Dictionary <ITextSnapshot, List <InvertedSource> >();
            for (int s = 0; s < sourceSpans.Count; ++s)
            {
                SnapshotSpan sourceSpan = sourceSpans[s];
                this.totalLength += sourceSpan.Length;

                this.cumulativeLengths[s + 1] = this.cumulativeLengths[s] + sourceSpan.Length;

                // Most source spans won't change when generating a new projection snapshot,
                // which means we should be able to reuse the line break count from the previous
                // projection snapshot.

                int lineBreakCount = sourceSpan.Snapshot.GetLineNumberFromPosition(sourceSpan.End) - sourceSpan.Snapshot.GetLineNumberFromPosition(sourceSpan.Start);

                // todo: incorrect when span ends with \r and following begins with \n
                this.totalLineCount += lineBreakCount;

                this.cumulativeLineBreakCounts[s + 1] = this.cumulativeLineBreakCounts[s] + lineBreakCount;

                ITextSnapshot         snapshot = sourceSpan.Snapshot;
                List <InvertedSource> invertedSources;
                if (!this.sourceSnapshotMap.TryGetValue(snapshot, out invertedSources))
                {
                    invertedSources = new List <InvertedSource>();
                    this.sourceSnapshotMap.Add(snapshot, invertedSources);
                }
                invertedSources.Add(new InvertedSource(sourceSpan.Span, this.cumulativeLengths[s]));
            }

            // The SourceSnapshots property is heavily used, so calculate it once
            this.sourceSnapshots = new ReadOnlyCollection <ITextSnapshot>(new List <ITextSnapshot>(this.sourceSnapshotMap.Keys));

            // sort the per-buffer source span lists by position in source snapshot
            foreach (var v in this.sourceSnapshotMap.Values)
            {
                // sort by starting position. Spans can't overlap, but we do need null spans at a particular position
                // to precede non-null spans at that position, so if starting positions are equal, compare the ends.
                v.Sort((left, right) => (left.sourceSpan.Start == right.sourceSpan.Start
                                            ? left.sourceSpan.End - right.sourceSpan.End
                                            : left.sourceSpan.Start - right.sourceSpan.Start));
            }

            if (BufferGroup.Tracing)
            {
                Debug.WriteLine(LocalToString());
            }
            if (this.totalLength != version.Length)
            {
                Debug.Fail(string.Format(System.Globalization.CultureInfo.CurrentCulture,
                                         "Projection Snapshot Inconsistency. Sum of spans: {0}, Previous + delta: {1}", this.totalLength, version.Length));
                throw new InvalidOperationException(Strings.InvalidLengthCalculation);
            }
            OverlapCheck();
        }
Beispiel #5
0
 protected BaseProjectionSnapshot(ITextVersion2 version, StringRebuilder builder)
     : base(version, builder)
 {
 }