Ejemplo n.º 1
0
        private Patch ApplyExactAt(int loc, WorkingPatch patch)
        {
            if (!patch.ContextLines.SequenceEqual(lines.GetRange(loc, patch.length1)))
            {
                throw new Exception("Patch engine failure");
            }
            if (!CanApplySafelyAt(loc, patch))
            {
                throw new Exception("Patch affects another patch");
            }


            lines.RemoveRange(loc, patch.length1);
            lines.InsertRange(loc, patch.PatchedLines);

            //update the lineModeText
            if (lmText != null)
            {
                lmText = lmText.Remove(loc) + patch.lmPatched + lmText.Substring(loc + patch.length1);
            }

            //update the wordModeLines
            if (wmLines != null)
            {
                wmLines.RemoveRange(loc, patch.length1);
                wmLines.InsertRange(loc, patch.wmPatched);
            }

            int   patchedDelta = patches.Where(p => p.KeepoutRange2?.end <= loc).Sum(p => p.AppliedDelta.Value);
            Patch appliedPatch = patch;

            if (appliedPatch.start2 != loc || appliedPatch.start1 != loc - patchedDelta)
            {
                appliedPatch = new Patch(patch)                   //create a new patch with different applied position if necessary
                {
                    start1 = loc - patchedDelta,
                    start2 = loc
                }
            }
            ;


            // update the applied location for patches following this one in the file, but preceding it in the patch list
            // can only happen if fuzzy matching causes a patch to move before one of the previously applied patches
            if (loc < ModifiedRange.end)
            {
                foreach (var p in patches.Where(p => p.KeepoutRange2?.start > loc))
                {
                    p.result.appliedPatch.start2 += appliedPatch.length2 - appliedPatch.length1;
                }
            }
            else
            {
                lastAppliedPatch = appliedPatch;
            }

            searchOffset = appliedPatch.start2 - patch.start2;
            return(appliedPatch);
        }
Ejemplo n.º 2
0
        private bool ApplyOffset(WorkingPatch patch)
        {
            if (lmText == null)
            {
                LinesToChars();
            }

            if (patch.length1 > lines.Count)
            {
                return(false);
            }

            int loc = patch.start2 + searchOffset;

            if (loc < 0)
            {
                loc = 0;
            }
            else if (loc >= lines.Count)
            {
                loc = lines.Count - 1;
            }

            int forward = lmText.IndexOf(patch.lmContext, loc, StringComparison.Ordinal);
            int reverse = lmText.LastIndexOf(patch.lmContext, Math.Min(loc + patch.lmContext.Length, lines.Count - 1), StringComparison.Ordinal);

            if (!CanApplySafelyAt(forward, patch))
            {
                forward = -1;
            }
            if (!CanApplySafelyAt(reverse, patch))
            {
                reverse = -1;
            }

            if (forward < 0 && reverse < 0)
            {
                return(false);
            }

            int found = reverse < 0 || forward >= 0 && (forward - loc) < (loc - reverse) ? forward : reverse;

            patch.Succeed(Mode.OFFSET, ApplyExactAt(found, patch));
            patch.AddOffsetResult(found - loc, lines.Count);

            return(true);
        }
Ejemplo n.º 3
0
        private bool ApplyExact(WorkingPatch patch)
        {
            int loc = patch.start2 + searchOffset;

            if (loc + patch.length1 > lines.Count)
            {
                return(false);
            }

            if (!patch.ContextLines.SequenceEqual(lines.GetRange(loc, patch.length1)))
            {
                return(false);
            }

            patch.Succeed(Mode.EXACT, ApplyExactAt(loc, patch));
            return(true);
        }
Ejemplo n.º 4
0
        private Patch ApplyExactAt(int loc, WorkingPatch patch)
        {
            if (!patch.ContextLines.SequenceEqual(textLines.GetRange(loc, patch.length1)))
            {
                throw new Exception("Patch engine failure");
            }

            textLines.RemoveRange(loc, patch.length1);
            textLines.InsertRange(loc, patch.PatchedLines);

            //update the lineModeText
            if (lmText != null)
            {
                lmText = lmText.Remove(loc) + patch.lmPatched + lmText.Substring(loc + patch.length1);
            }

            //update the wordModeLines
            if (wmLines != null)
            {
                wmLines.RemoveRange(loc, patch.length1);
                wmLines.InsertRange(loc, patch.wmPatched);
            }

            Patch applied = patch;

            if (applied.start2 != loc || applied.start1 != loc - patchedDelta)
            {
                applied = new Patch(patch)                   //create a new patch with different applied position if necessary
                {
                    start1 = loc - patchedDelta,
                    start2 = loc
                }
            }
            ;

            //update the patchedDelta and searchOffset
            searchOffset    = loc - patch.start2;
            patchedDelta   += patch.length2 - patch.length1;
            lastPatchedLine = loc + patch.length2;

            return(applied);
        }
Ejemplo n.º 5
0
        private bool ApplyFuzzy(WorkingPatch patch)
        {
            if (wmLines == null)
            {
                WordsToChars();
            }

            int loc = patch.start2 + searchOffset;

            if (loc + patch.length1 > wmLines.Count)            //initialise search at end of file if loc is past file length
            {
                loc = wmLines.Count - patch.length1;
            }

            (int[] match, float matchQuality) = FindMatch(loc, patch.wmContext);
            if (match == null)
            {
                return(false);
            }

            var fuzzyPatch = new WorkingPatch(AdjustPatchToMatchedLines(patch, match, lines));

            if (wmLines != null)
            {
                fuzzyPatch.WordsToChars(charRep);
            }
            if (lmText != null)
            {
                fuzzyPatch.LinesToChars(charRep);
            }

            int at = match.First(i => i >= 0);             //if the patch needs lines trimmed off it, the early match entries will be negative

            patch.Succeed(Mode.FUZZY, ApplyExactAt(at, fuzzyPatch));
            patch.AddOffsetResult(fuzzyPatch.start2 - loc, lines.Count);
            patch.AddFuzzyResult(matchQuality);
            return(true);
        }
Ejemplo n.º 6
0
        private bool ApplyFuzzy(WorkingPatch patch)
        {
            if (wmLines == null)
            {
                WordsToChars();
            }

            int loc = patch.start2 + searchOffset;

            if (loc + patch.length1 > wmLines.Count)            //initialise search at end of file if loc is past file length
            {
                loc = wmLines.Count - patch.length1;
            }

            int[] match = FindMatch(loc, patch.wmContext, out float matchQuality);
            if (match == null)
            {
                return(false);
            }

            //replace the patch with a copy
            var fuzzyPatch = new WorkingPatch(patch);
            var diffs      = fuzzyPatch.diffs;        //for convenience

            //keep operations, but replace lines with lines in source text
            //unmatched patch lines (-1) are deleted
            //unmatched target lines (increasing offset) are added to the patch
            for (int i = 0, j = 0, ploc = -1; i < patch.length1; i++)
            {
                int mloc = match[i];

                //insert extra target lines into patch
                if (mloc >= 0 && ploc >= 0 && mloc - ploc > 1)
                {
                    //delete an unmatched target line if the surrounding diffs are also DELETE, otherwise use it as context
                    var op = diffs[j - 1].op == Operation.DELETE && diffs[j].op == Operation.DELETE ?
                             Operation.DELETE : Operation.EQUAL;

                    for (int l = ploc + 1; l < mloc; l++)
                    {
                        diffs.Insert(j++, new Diff(op, textLines[l]));
                    }
                }
                ploc = mloc;

                //keep insert lines the same
                while (diffs[j].op == Operation.INSERT)
                {
                    j++;
                }

                if (mloc < 0)                 //unmatched context line
                {
                    diffs.RemoveAt(j);
                }
                else                 //update context to match target file (may be the same, doesn't matter)
                {
                    diffs[j++].text = textLines[mloc];
                }
            }

            //finish our new patch
            fuzzyPatch.RecalculateLength();
            if (wmLines != null)
            {
                fuzzyPatch.WordsToChars(charRep);
            }
            if (lmText != null)
            {
                fuzzyPatch.LinesToChars(charRep);
            }

            int at = match.First(i => i >= 0);             //if the patch needs lines trimmed off it, the early match entries will be negative

            patch.Succeed(Mode.FUZZY, ApplyExactAt(at, fuzzyPatch));
            patch.AddOffsetResult(fuzzyPatch.start2 - loc, textLines.Count);
            patch.AddFuzzyResult(matchQuality);
            return(true);
        }