public void X(string input)
        {
            var map = new PositionToLine(input);

            var expectedLineNo = 0;

            for (int i = 0; i < input.Length; i++)
            {
                var lineNo = map.GetLineinPosition(i);
                Assert.That(lineNo, Is.EqualTo(expectedLineNo), $"Mismatch at position {i}");

                if (input[i] == '\n')
                {
                    expectedLineNo++;
                }
            }
        }
Esempio n. 2
0
        public static int Track(string commentVersion, string newVersion, int line)
        {
            var patches = MakeDiff(commentVersion, newVersion);

            if (!patches.Any() || string.IsNullOrEmpty(commentVersion))
            {
                return(line);
            }

            DiffUtils.UnrollContext(patches);

            foreach (var patch in patches)
            {
                FourWayDiff.ExpandPatchToFullLines(newVersion, patch);
            }

            patches = DiffUtils.MergeAdjacentPatches(patches);

            patches.Sort(new LambdaComparer <Patch, int>(x => x.Start1));

            var commentLines = LineList.SplitLines(commentVersion);

            var newVersionLinesMap = new PositionToLine(newVersion);
            var newVersionLines    = LineList.SplitLines(newVersion);

            var commentLineEntry = commentLines[line - 1];
            var commentLine      = commentLineEntry.Text;
            var commentPosition  = commentLineEntry.StartPosition;

            var patchContainingComment = patches.FirstOrDefault(x => x.Start1 <= commentPosition && commentPosition <= x.Start1 + x.Length1);

            if (patchContainingComment != null)
            {
                var patchNewText = DMP.DiffText2(patchContainingComment.Diffs);
                var commentLinePositionInPatch = patchNewText.IndexOf(commentLine);

                if (commentLinePositionInPatch >= 0)
                {
                    var newLine = newVersionLines.LineIndexInPosition(commentLinePositionInPatch + patchContainingComment.Start2);

                    if (newLine == null)
                    {
                        Logger.Error("LineIndexInPosition returned null!");
                    }

                    return((newLine ?? 0) + 1);
                }

                var commentLineTrimmed = commentLine.Trim();
                commentLinePositionInPatch = patchNewText.IndexOf(commentLineTrimmed); // try part-match without leading & trailing whitespaces

                if (commentLinePositionInPatch >= 0)
                {
                    var newLine = newVersionLines.LineIndexInPosition(commentLinePositionInPatch + patchContainingComment.Start2);
                    if (newLine == null)
                    {
                        Logger.Error("LineIndexInPosition returned null!");
                    }

                    return((newLine ?? 0) + 1);
                }

                // For some reason DMP Match algorithm does not work with pattern longer that some internal limit
                var prefixLength = patchContainingComment.Diffs.TakeWhile(x => x.Operation.IsEqual).Sum(x => x.Text.Length);

                var approximateMatchPosition = DMP.MatchMain(patchNewText.Substring(prefixLength), commentLineTrimmed.Substring(0, Math.Min(DMP.MatchMaxBits, commentLineTrimmed.Length)), 0);
                if (approximateMatchPosition > -1)
                {
                    var newLine = newVersionLines.LineIndexInPosition(approximateMatchPosition + prefixLength + patchContainingComment.Start2);
                    if (newLine == null)
                    {
                        Logger.Error("LineIndexInPosition returned null!");
                    }

                    return((newLine ?? 0) + 1);
                }
            }

            var lastPatchBeforeComment = patches.LastOrDefault(x => x.Start1 + x.Length1 <= commentPosition);

            if (lastPatchBeforeComment != null)
            {
                var patchEnd           = lastPatchBeforeComment.Start1 + lastPatchBeforeComment.Length1;
                var distance           = commentPosition - patchEnd;
                var newCommentPosition = lastPatchBeforeComment.Start2 + lastPatchBeforeComment.Length2 + distance;

                var newVersionLine = newVersionLines.LineIndexInPosition(newCommentPosition);

                if (newVersionLine.HasValue)
                {
                    return((int)newVersionLine + 1);
                }
            }

            if (line > newVersionLines.Count)
            {
                // trim comments to last line in new file
                line = newVersionLines.Count;
            }

            return(line);
        }