예제 #1
0
            public void NoLineMatchesFromNoLines()
            {
                var chunks = new DiffChunk[0];
                var lines  = new DiffLine[0];

                var line = DiffUtilities.Match(chunks, lines);

                Assert.Null(line);
            }
예제 #2
0
        IPullRequestSessionManager CreateSessionManager(
            string commitSha            = "COMMIT",
            string relativePath         = RelativePath,
            IPullRequestSession session = null,
            PullRequestTextBufferInfo textBufferInfo = null)
        {
            var thread = CreateThread(10, "Existing comment");

            var diff = new DiffChunk
            {
                DiffLine      = 10,
                OldLineNumber = 1,
                NewLineNumber = 1,
            };

            for (var i = 0; i < 10; ++i)
            {
                diff.Lines.Add(new DiffLine
                {
                    NewLineNumber  = i,
                    DiffLineNumber = i + 10,
                    Type           = i < 5 ? DiffChangeType.Delete : DiffChangeType.Add,
                });
            }

            var file = Substitute.For <IPullRequestSessionFile>();

            file.CommitSha.Returns(commitSha);
            file.Diff.Returns(new[] { diff });
            file.InlineCommentThreads.Returns(new[] { thread });
            file.LinesChanged.Returns(new Subject <IReadOnlyList <Tuple <int, DiffSide> > >());

            session = session ?? CreateSession();

            if (textBufferInfo != null)
            {
                session.GetFile(textBufferInfo.RelativePath, textBufferInfo.CommitSha).Returns(file);
            }

            var result = Substitute.For <IPullRequestSessionManager>();

            result.CurrentSession.Returns(session);
            result.GetLiveFile(relativePath, Arg.Any <ITextView>(), Arg.Any <ITextBuffer>()).Returns(file);
            result.GetRelativePath(Arg.Any <ITextBuffer>()).Returns(relativePath);
            result.GetTextBufferInfo(Arg.Any <ITextBuffer>()).Returns(textBufferInfo);

            return(result);
        }
예제 #3
0
            static IPullRequestSessionFile CreateSessionFile()
            {
                var diffChunk = new DiffChunk
                {
                    Lines =
                    {
                        // Line numbers here are 1-based. There is an add diff entry on line 11
                        // and a delete entry on line 13.
                        new DiffLine {
                            Type = DiffChangeType.Add, NewLineNumber = 11 + 1
                        },
                        new DiffLine {
                            Type = DiffChangeType.Delete, OldLineNumber = 13 + 1
                        },
                    }
                };
                var diff = new List <DiffChunk> {
                    diffChunk
                };

                var rhsThread = Substitute.For <IInlineCommentThreadModel>();

                rhsThread.DiffLineType.Returns(DiffChangeType.Add);
                rhsThread.LineNumber.Returns(10);

                var lhsThread = Substitute.For <IInlineCommentThreadModel>();

                lhsThread.DiffLineType.Returns(DiffChangeType.Delete);
                lhsThread.LineNumber.Returns(12);

                // We have a comment to display on the right-hand-side of the diff view on line
                // 11 and a comment to display on line 13 on the left-hand-side.
                var threads = new List <IInlineCommentThreadModel> {
                    rhsThread, lhsThread
                };

                var file = Substitute.For <IPullRequestSessionFile>();

                file.Diff.Returns(diff);
                file.InlineCommentThreads.Returns(threads);
                file.LinesChanged.Returns(new Subject <IReadOnlyList <Tuple <int, DiffSide> > >());

                return(file);
            }
예제 #4
0
        IPullRequestSessionManager CreateSessionManager(string commitSha = "COMMIT")
        {
            var thread = CreateThread(10, "Existing comment");

            var diff = new DiffChunk
            {
                DiffLine      = 10,
                OldLineNumber = 1,
                NewLineNumber = 1,
            };

            for (var i = 0; i < 10; ++i)
            {
                diff.Lines.Add(new DiffLine
                {
                    NewLineNumber  = i,
                    DiffLineNumber = i + 10,
                    Type           = i < 5 ? DiffChangeType.Delete : DiffChangeType.Add,
                });
            }

            var file = Substitute.For <IPullRequestSessionFile>();

            file.CommitSha.Returns(commitSha);
            file.Diff.Returns(new[] { diff });
            file.InlineCommentThreads.Returns(new[] { thread });
            file.LinesChanged.Returns(new Subject <IReadOnlyList <Tuple <int, DiffSide> > >());

            var session = Substitute.For <IPullRequestSession>();

            session.LocalRepository.CloneUrl.Returns(new UriString("https://foo.bar"));

            var result = Substitute.For <IPullRequestSessionManager>();

            result.CurrentSession.Returns(session);
            result.GetLiveFile(RelativePath, Arg.Any <ITextView>(), Arg.Any <ITextBuffer>()).Returns(file);
            result.GetRelativePath(Arg.Any <ITextBuffer>()).Returns(RelativePath);

            return(result);
        }
예제 #5
0
        /// <summary>
        /// Get a list of the operations that would make a terminal window look like this snapshot
        /// if you assume that beforehand it looked like the older snapshot you pass in.
        /// </summary>
        /// <param name="older">the older snapshot of a screen to diff from</param>
        /// <returns>the string that if output in order, will give you the desired changes</returns>
        public string DiffFrom(IScreenSnapShot older)
        {
            StringBuilder output = new StringBuilder();
            
            int verticalScroll = TopRow - older.TopRow;
            int trackCursorColumn = older.CursorColumn; // track the movements that will occur as the outputs happen.
            int trackCursorRow = older.CursorRow; // track the movements that will occur as the outputs happen.

            // First, output the command to make the terminal scroll to match:
            if (verticalScroll > 0) // scrolling text up (eyeballs panning down)
                output.Append(new String((char)UnicodeCommand.SCROLLSCREENUPONE, verticalScroll)); // A run of scrollup chars
            else if (verticalScroll < 0) // scrolling text down (eyeballs panning up)
                output.Append(new String((char)UnicodeCommand.SCROLLSCREENDOWNONE, -verticalScroll)); // A run of scrolldown chars

            // Check each row:
            for (int newRowNum = 0 ; newRowNum < RowCount ; ++newRowNum)
            {
                // Account for the diff due to the scrolling:
                int oldRowNum = newRowNum + verticalScroll;

                IScreenBufferLine newRow = Buffer[newRowNum];
                bool oldRowExists = (oldRowNum >= 0 && oldRowNum < older.Buffer.Count);
                IScreenBufferLine olderRow = oldRowExists ? older.Buffer[oldRowNum] : new ScreenBufferLine(0);
                
                // if new row is an empty dummy, then pad it out so it gets properly diffed against the old row:
                if (newRow.Length == 0)
                    newRow = new ScreenBufferLine(olderRow.Length);
                // If the old row is a dummy pad or if the new row is newer than the old row, then it needs checking for diffs:
                if (olderRow.Length == 0 || newRow.LastChangeTick > olderRow.LastChangeTick)
                {
                    List<DiffChunk> diffs = new List<DiffChunk>();
                    
                    for (int newCol = 0 ; newCol < newRow.Length ; ++newCol)
                    {
                        // Check if they differ, but in a way that treats ' ' and 0x00 as identical, and treats a shorter
                        // old row as if it has been padded with spaces:
                        bool oldRowTooShort = newCol >= olderRow.Length;
                        char newChar = (newRow[newCol] == '\0' ? ' ' : newRow[newCol]);
                        char oldChar = (oldRowTooShort ? ' ' : (olderRow[newCol] == '\0' ? ' ' : olderRow[newCol]));
                        if (newChar != oldChar)
                        {
                            // Start a new diff chunk if there isn't one yet, or the diff is a long enough distance from the existing one:
                            if (diffs.Count == 0 || diffs[diffs.Count-1].EndCol < newCol - JOIN_DIFF_DIST)
                            {
                                DiffChunk newChunk = new DiffChunk
                                {
                                    StartCol = newCol, 
                                    EndCol = newCol
                                };
                                diffs.Add(newChunk);
                            }
                            else // stretch the existing diff chunk to here.
                            {
                                diffs[diffs.Count-1].EndCol = newCol;
                            }
                        }
                    }
                    
                    string newRowText = newRow.ToString();

                    foreach (DiffChunk diff in diffs)
                    {
                        /* comment-out -----------------
                        // If we're lucky enough that the current cursor happens to be right where we need it to
                        // be, some of these are more efficient.  Else it does TELEPORTCURSOR's:
                        
                        // Just one char removed to the left of current cursor pos - do a backspace instead of the ugly work:
                        if (trackCursorRow == newRowNum && (diff.EndCol == trackCursorColumn - 1 && diff.StartCol == diff.EndCol))
                        {
                            output.Append(String.Format("{0}{1}{2}", (char)0x08, newRowText.Substring(diff.StartCol,1), (char)0x08));
                            trackCursorColumn = diff.EndCol;
                            trackCursorRow = newRowNum;
                        }
                        else
                        {
                        --------------------------- */
                            // If the change starts right where the cursor happens to be (i.e. when typing, one char
                            // at current cursor position will typically be the only diff from one update to the next),
                            // then don't bother moving the cursor first, else move it to the new pos:
                            string moveString;
                            if (trackCursorRow == newRowNum && diff.StartCol == trackCursorColumn)
                                moveString = "";
                            else
                                moveString = String.Format("{0}{1}{2}",
                                                           (char)UnicodeCommand.TELEPORTCURSOR,
                                                           (char)diff.StartCol,
                                                           (char)newRowNum);
                            
                            // content = the bit of string to print at this location, with nulls made into spaces so the 
                            // telnet terminal will print correctly.
                            string content = newRowText.Substring(diff.StartCol, diff.EndCol - diff.StartCol + 1).Replace('\0',' ');

                            output.Append(String.Format("{0}{1}", moveString, content));
 
                            trackCursorColumn = diff.EndCol+1;
                            trackCursorRow = newRowNum;
                        /* comment-out -----------------
                        }
                        --------------------------- */
                    }
                    
                }
                    
            }
                    
            // Now set the cursor back to the right spot one more time, unless it's already there:
            if (trackCursorRow != CursorRow || trackCursorColumn != CursorColumn)
            {
                output.Append(String.Format("{0}{1}{2}",
                                            (char)UnicodeCommand.TELEPORTCURSOR,
                                            (char)CursorColumn,
                                            (char)CursorRow));
            }
            return output.ToString();
        }
예제 #6
0
        static IPullRequestSessionFile CreateSessionFile(bool withComments = true, bool withAnnotations = false)
        {
            var diffChunk = new DiffChunk
            {
                Lines =
                {
                    // Line numbers here are 1-based. There is an add diff entry on lines 11 and 21
                    // and a delete entry on line 13.
                    new DiffLine {
                        Type = DiffChangeType.Add, NewLineNumber = 11 + 1
                    },
                    new DiffLine {
                        Type = DiffChangeType.Delete, OldLineNumber = 13 + 1
                    },
                    new DiffLine {
                        Type = DiffChangeType.Add, NewLineNumber = 21 + 1
                    },
                }
            };
            var diff = new List <DiffChunk> {
                diffChunk
            };

            var file = Substitute.For <IPullRequestSessionFile>();

            file.Diff.Returns(diff);

            if (withComments)
            {
                var rhsThread = Substitute.For <IInlineCommentThreadModel>();
                rhsThread.DiffLineType.Returns(DiffChangeType.Add);
                rhsThread.LineNumber.Returns(10);

                var lhsThread = Substitute.For <IInlineCommentThreadModel>();
                lhsThread.DiffLineType.Returns(DiffChangeType.Delete);
                lhsThread.LineNumber.Returns(12);

                // We have a comment to display on the right-hand-side of the diff view on line
                // 11 and a comment to display on line 13 on the left-hand-side.
                var threads = new List <IInlineCommentThreadModel> {
                    rhsThread, lhsThread
                };

                file.InlineCommentThreads.Returns(threads);
            }

            if (withAnnotations)
            {
                var annotation1 = new InlineAnnotationModel(new CheckSuiteModel(), new CheckRunModel(), new CheckRunAnnotationModel()
                {
                    EndLine = 11
                });

                var annotation2 = new InlineAnnotationModel(new CheckSuiteModel(), new CheckRunModel(), new CheckRunAnnotationModel()
                {
                    EndLine = 21
                });

                var annotation3 = new InlineAnnotationModel(new CheckSuiteModel(), new CheckRunModel(), new CheckRunAnnotationModel()
                {
                    EndLine = 21
                });

                var annotations = new List <InlineAnnotationModel> {
                    annotation1, annotation2, annotation3
                };

                file.InlineAnnotations.Returns(annotations);
            }

            file.LinesChanged.Returns(new Subject <IReadOnlyList <Tuple <int, DiffSide> > >());

            return(file);
        }
예제 #7
0
        /// <summary>
        /// Get a list of the operations that would make a terminal window look like this snapshot
        /// if you assume that beforehand it looked like the older snapshot you pass in.
        /// </summary>
        /// <param name="older">the older snapshot of a screen to diff from</param>
        /// <returns>the string that if output in order, will give you the desired changes</returns>
        public string DiffFrom(IScreenSnapShot older)
        {
            StringBuilder output = new StringBuilder();

            int verticalScroll    = TopRow - older.TopRow;
            int trackCursorColumn = older.CursorColumn; // track the movements that will occur as the outputs happen.
            int trackCursorRow    = older.CursorRow;    // track the movements that will occur as the outputs happen.

            // First, output the command to make the terminal scroll to match:
            if (verticalScroll > 0)                                                                   // scrolling text up (eyeballs panning down)
            {
                output.Append(new String((char)UnicodeCommand.SCROLLSCREENUPONE, verticalScroll));    // A run of scrollup chars
            }
            else if (verticalScroll < 0)                                                              // scrolling text down (eyeballs panning up)
            {
                output.Append(new String((char)UnicodeCommand.SCROLLSCREENDOWNONE, -verticalScroll)); // A run of scrolldown chars
            }
            // Check each row:
            for (int newRowNum = 0; newRowNum < RowCount; ++newRowNum)
            {
                // Account for the diff due to the scrolling:
                int oldRowNum = newRowNum + verticalScroll;

                IScreenBufferLine newRow   = Buffer[newRowNum];
                bool oldRowExists          = (oldRowNum >= 0 && oldRowNum < older.Buffer.Count);
                IScreenBufferLine olderRow = oldRowExists ? older.Buffer[oldRowNum] : new ScreenBufferLine(0);

                // if new row is an empty dummy, then pad it out so it gets properly diffed against the old row:
                if (newRow.Length == 0)
                {
                    newRow = new ScreenBufferLine(olderRow.Length);
                }
                // If the old row is a dummy pad or if the new row is newer than the old row, then it needs checking for diffs:
                if (olderRow.Length == 0 || newRow.LastChangeTick > olderRow.LastChangeTick)
                {
                    List <DiffChunk> diffs = new List <DiffChunk>();

                    for (int newCol = 0; newCol < newRow.Length; ++newCol)
                    {
                        // Check if they differ, but in a way that treats ' ' and 0x00 as identical, and treats a shorter
                        // old row as if it has been padded with spaces:
                        bool oldRowTooShort = newCol >= olderRow.Length;
                        char newChar        = (newRow[newCol] == '\0' ? ' ' : newRow[newCol]);
                        char oldChar        = (oldRowTooShort ? ' ' : (olderRow[newCol] == '\0' ? ' ' : olderRow[newCol]));
                        if (newChar != oldChar)
                        {
                            // Start a new diff chunk if there isn't one yet, or the diff is a long enough distance from the existing one:
                            if (diffs.Count == 0 || diffs[diffs.Count - 1].EndCol < newCol - JOIN_DIFF_DIST)
                            {
                                DiffChunk newChunk = new DiffChunk
                                {
                                    StartCol = newCol,
                                    EndCol   = newCol
                                };
                                diffs.Add(newChunk);
                            }
                            else // stretch the existing diff chunk to here.
                            {
                                diffs[diffs.Count - 1].EndCol = newCol;
                            }
                        }
                    }

                    string newRowText = newRow.ToString();

                    foreach (DiffChunk diff in diffs)
                    {
                        /* comment-out -----------------
                         * // If we're lucky enough that the current cursor happens to be right where we need it to
                         * // be, some of these are more efficient.  Else it does TELEPORTCURSOR's:
                         *
                         * // Just one char removed to the left of current cursor pos - do a backspace instead of the ugly work:
                         * if (trackCursorRow == newRowNum && (diff.EndCol == trackCursorColumn - 1 && diff.StartCol == diff.EndCol))
                         * {
                         *  output.Append(String.Format("{0}{1}{2}", (char)0x08, newRowText.Substring(diff.StartCol,1), (char)0x08));
                         *  trackCursorColumn = diff.EndCol;
                         *  trackCursorRow = newRowNum;
                         * }
                         * else
                         * {
                         * --------------------------- */
                        // If the change starts right where the cursor happens to be (i.e. when typing, one char
                        // at current cursor position will typically be the only diff from one update to the next),
                        // then don't bother moving the cursor first, else move it to the new pos:
                        string moveString;
                        if (trackCursorRow == newRowNum && diff.StartCol == trackCursorColumn)
                        {
                            moveString = "";
                        }
                        else
                        {
                            moveString = String.Format("{0}{1}{2}",
                                                       (char)UnicodeCommand.TELEPORTCURSOR,
                                                       (char)diff.StartCol,
                                                       (char)newRowNum);
                        }

                        // content = the bit of string to print at this location, with nulls made into spaces so the
                        // telnet terminal will print correctly.
                        string content = newRowText.Substring(diff.StartCol, diff.EndCol - diff.StartCol + 1).Replace('\0', ' ');

                        output.Append(String.Format("{0}{1}", moveString, content));

                        trackCursorColumn = diff.EndCol + 1;
                        trackCursorRow    = newRowNum;

                        /* comment-out -----------------
                         * }
                         * --------------------------- */
                    }
                }
            }

            // Now set the cursor back to the right spot one more time, unless it's already there:
            if (trackCursorRow != CursorRow || trackCursorColumn != CursorColumn)
            {
                output.Append(String.Format("{0}{1}{2}",
                                            (char)UnicodeCommand.TELEPORTCURSOR,
                                            (char)CursorColumn,
                                            (char)CursorRow));
            }
            return(output.ToString());
        }