Example #1
0
        public static IEnumerable <LineInfo> SplitLines(string text)
        {
            NewLineLocation nextLine;
            List <LineInfo> lines = new List <LineInfo>();

            int lastLineEnd = 0;

            while ((nextLine = NewLineLocation.FindNewLine(text, lastLineEnd)).EndIndex != lastLineEnd)
            {
                yield return(new LineInfo(
                                 lastLineEnd,
                                 nextLine.EndIndex - lastLineEnd - nextLine.Kind.GetSize(),
                                 lines.Count,
                                 nextLine.Kind
                                 ));

                lastLineEnd = nextLine.EndIndex;
            }

            if (lastLineEnd != text.Length)
            {
                yield return(new LineInfo(
                                 lastLineEnd,
                                 text.Length - lastLineEnd,
                                 lines.Count,
                                 NewLineKind.None
                                 ));
            }
        }
Example #2
0
        public static IEnumerable <LineInfo> SplitLines(string text, int firstLineNumber = 0)
        {
            NewLineLocation nextLine;
            var             lineNo = firstLineNumber;

            var lastLineEnd = 0;

            while ((nextLine = NewLineLocation.FindNewLine(text, lastLineEnd)).EndIndex != lastLineEnd)
            {
                yield return(new LineInfo(
                                 lastLineEnd,
                                 nextLine.EndIndex - lastLineEnd - nextLine.Kind.GetSize(),
                                 lineNo++,
                                 nextLine.Kind
                                 ));

                lastLineEnd = nextLine.EndIndex;
            }

            if (lastLineEnd != text.Length)
            {
                yield return(new LineInfo(
                                 lastLineEnd,
                                 text.Length - lastLineEnd,
                                 lineNo++,
                                 NewLineKind.None
                                 ));
            }
        }
Example #3
0
        private static IEnumerable<NewLineLocation> SplitLines(StringBuilder text) {
            NewLineLocation nextLine;

            // TODO: Avoid string allocation by operating directly on StringBuilder
            var str = text.ToString();

            int lastLineEnd = 0;
            while ((nextLine = NewLineLocation.FindNewLine(str, lastLineEnd)).EndIndex != lastLineEnd) {
                yield return nextLine;
                lastLineEnd = nextLine.EndIndex;
            }

            if (lastLineEnd != str.Length) {
                yield return nextLine;
            }
        }
Example #4
0
        internal NewLineLocation[] GetLineLocations(int version)
        {
            var ver = _snapshots.Peek().Version;

            NewLineLocation[] initial;

            lock (_lineCache) {
                // Precalculated for this version
                if (_lineCache.TryGetValue(version, out initial))
                {
                    return(initial);
                }

                // We simply can't provide these lines any more
                if (ver.VersionNumber > version)
                {
                    throw new NotSupportedException($"version {version} is no longer in memory");
                }

                int fromVersion = version;
                // Get the last available set of newlines
                while (--fromVersion >= ver.VersionNumber)
                {
                    if (_lineCache.TryGetValue(fromVersion, out initial))
                    {
                        break;
                    }
                }

                // Create the initial set if it wasn't cached
                if (initial == null)
                {
                    fromVersion             = ver.VersionNumber;
                    _lineCache[fromVersion] = initial = LinesToLineEnds(_snapshots.Peek().Lines).ToArray();
                }

                while (ver.Next != null && ver.VersionNumber < fromVersion)
                {
                    ver = ver.Next;
                }

#if DEBUG
                var appliedVersions = new List <ITextVersion>();
#endif
                List <NewLineLocation> asLengths = null;
                while (ver.Changes != null && ver.VersionNumber < version)
                {
#if DEBUG
                    appliedVersions.Add(ver);
#endif
                    if (asLengths == null)
                    {
                        asLengths = LineEndsToLineLengths(initial).ToList();
                    }

                    // Apply the changes from this version to the line lengths
                    foreach (var c in ver.Changes.Reverse())
                    {
                        var oldLoc = NewLineLocation.IndexToLocation(initial, c.OldPosition);
                        int lineNo = oldLoc.Line - 1;
                        while (asLengths.Count <= lineNo)
                        {
                            asLengths.Add(new NewLineLocation(0, NewLineKind.None));
                        }

                        if (c.OldLength > 0)
                        {
                            var line = asLengths[lineNo];
                            // Deletion may span lines, so combine them until we can delete
                            int cutAtCol = oldLoc.Column - 1;
                            for (int toRemove = c.OldLength; lineNo < asLengths.Count; lineNo += 1)
                            {
                                line = asLengths[lineNo];
                                int lineLen = line.EndIndex - cutAtCol;
                                cutAtCol = 0;
                                if (line.Kind == NewLineKind.CarriageReturnLineFeed && toRemove == lineLen - 1)
                                {
                                    // Special case of deleting just the '\r' from a '\r\n' ending
                                    asLengths[lineNo] = new NewLineLocation(line.EndIndex - toRemove, NewLineKind.LineFeed);
                                    break;
                                }
                                else if (toRemove < lineLen)
                                {
                                    asLengths[lineNo] = new NewLineLocation(line.EndIndex - toRemove, line.Kind);
                                    break;
                                }
                                else
                                {
                                    asLengths[lineNo] = new NewLineLocation(line.EndIndex - lineLen, NewLineKind.None);
                                    toRemove         -= lineLen;
                                    if (toRemove <= 0)
                                    {
                                        break;
                                    }
                                }
                            }
                        }
                        lineNo = oldLoc.Line - 1;
                        if (!string.IsNullOrEmpty(c.NewText))
                        {
                            var             line = asLengths[lineNo];
                            NewLineLocation addedLine = new NewLineLocation(0, NewLineKind.None);
                            int             lastLineEnd = 0, cutAtCol = oldLoc.Column - 1;
                            if (cutAtCol > line.EndIndex - line.Kind.GetSize() && lineNo + 1 < asLengths.Count)
                            {
                                cutAtCol = 0;
                                lineNo  += 1;
                                line     = asLengths[lineNo];
                            }
                            while ((addedLine = NewLineLocation.FindNewLine(c.NewText, lastLineEnd)).Kind != NewLineKind.None)
                            {
                                if (cutAtCol > 0)
                                {
                                    asLengths[lineNo] = new NewLineLocation(line.EndIndex - cutAtCol, line.Kind);
                                    lastLineEnd      -= cutAtCol;
                                    cutAtCol          = 0;
                                }
                                line = new NewLineLocation(addedLine.EndIndex - lastLineEnd, addedLine.Kind);
                                asLengths.Insert(lineNo++, line);
                                lastLineEnd = addedLine.EndIndex;
                            }
                            if (addedLine.EndIndex > lastLineEnd)
                            {
                                if (lineNo < asLengths.Count)
                                {
                                    line = asLengths[lineNo];
                                    asLengths[lineNo] = line = new NewLineLocation(line.EndIndex + addedLine.EndIndex - lastLineEnd, line.Kind);
                                }
                                else
                                {
                                    asLengths.Add(new NewLineLocation(addedLine.EndIndex - lastLineEnd, NewLineKind.None));
                                }
                            }
                        }
                    }

                    initial = LineLengthsToLineEnds(asLengths).ToArray();
                    if (asLengths.Count != initial.Length)
                    {
                        asLengths = null;
                    }
                    _lineCache[ver.VersionNumber + 1] = initial;

#if DEBUG
                    if (System.Diagnostics.Debugger.IsAttached && initial.Length > 0 && ver.Next != null && initial.Last().EndIndex != ver.Next.Length)
                    {
                        // Line calculations were wrong
                        // Asserts do not work properly here, so we just break if the debugger is attached
                        System.Diagnostics.Debugger.Break();
                    }
#endif

                    ver = ver.Next;
                }

                return(initial);
            }
        }