Search in sources :

Example 21 with Range

use of com.intellij.diff.util.Range in project intellij-community by JetBrains.

the class ByChar method matchAdjustmentSpacesIW.

/*
   * Given DiffIterable on non-whitespace characters, convert it into DiffIterable on original texts.
   *
   * matched characters: matched non-space characters + all adjustment whitespaces
   */
@NotNull
private static DiffIterable matchAdjustmentSpacesIW(@NotNull CharOffsets chars1, @NotNull CharOffsets chars2, @NotNull CharSequence text1, @NotNull CharSequence text2, @NotNull FairDiffIterable changes) {
    final List<Range> ranges = new ArrayList<>();
    for (Range ch : changes.iterateChanges()) {
        int startOffset1;
        int endOffset1;
        if (ch.start1 == ch.end1) {
            startOffset1 = endOffset1 = expandForwardW(chars1, chars2, text1, text2, ch, true);
        } else {
            startOffset1 = chars1.offsets[ch.start1];
            endOffset1 = chars1.offsets[ch.end1 - 1] + 1;
        }
        int startOffset2;
        int endOffset2;
        if (ch.start2 == ch.end2) {
            startOffset2 = endOffset2 = expandForwardW(chars1, chars2, text1, text2, ch, false);
        } else {
            startOffset2 = chars2.offsets[ch.start2];
            endOffset2 = chars2.offsets[ch.end2 - 1] + 1;
        }
        ranges.add(new Range(startOffset1, endOffset1, startOffset2, endOffset2));
    }
    return create(ranges, text1.length(), text2.length());
}
Also used : TIntArrayList(gnu.trove.TIntArrayList) ArrayList(java.util.ArrayList) Range(com.intellij.diff.util.Range) NotNull(org.jetbrains.annotations.NotNull)

Example 22 with Range

use of com.intellij.diff.util.Range in project intellij-community by JetBrains.

the class ByChar method transfer.

//
// Impl
//
@NotNull
private static FairDiffIterable transfer(@NotNull final CharOffsets chars1, @NotNull final CharOffsets chars2, @NotNull final CharSequence text1, @NotNull final CharSequence text2, @NotNull final FairDiffIterable changes, @NotNull final ProgressIndicator indicator) {
    ChangeBuilder builder = new ChangeBuilder(text1.length(), text2.length());
    for (Range range : changes.iterateUnchanged()) {
        int count = range.end1 - range.start1;
        for (int i = 0; i < count; i++) {
            int offset1 = chars1.offsets[range.start1 + i];
            int offset2 = chars2.offsets[range.start2 + i];
            builder.markEqual(offset1, offset2);
        }
    }
    return fair(builder.finish());
}
Also used : Range(com.intellij.diff.util.Range) NotNull(org.jetbrains.annotations.NotNull)

Example 23 with Range

use of com.intellij.diff.util.Range in project intellij-community by JetBrains.

the class ByLine method correctChangesSecondStep.

@NotNull
private static FairDiffIterable correctChangesSecondStep(@NotNull final List<Line> lines1, @NotNull final List<Line> lines2, @NotNull final FairDiffIterable changes) {
    /*
     * We want to fix invalid matching here:
     *
     * .{        ..{
     * ..{   vs  ...{
     * ...{
     *
     * first step will return matching (0,2)-(0,2). And we should adjust it to (1,3)-(0,2)
     *
     *
     * From the other hand, we don't want to reduce number of IW-matched lines.
     *
     * .{         ...{
     * ..{    vs  ..{
     * ...{       .{
     *
     * first step will return (0,3)-(0,3) and 'correcting' it to (0,1)-(2,3) is wrong (and it will break ByWord highlighting).
     *
     *
     * Idea:
     * 1. lines are matched at first step and equal -> match them
     * 2. lines are not matched at first step -> do not match them
     * 3. lines are matched at first step and not equal ->
     *   a. find all IW-equal lines in the same unmatched block
     *   b. find a maximum matching between them, maximising amount of equal pairs in it
     *   c. match equal lines using result of the previous step
     */
    final ExpandChangeBuilder builder = new ExpandChangeBuilder(lines1, lines2);
    new Object() {

        private CharSequence sample = null;

        private int last1 = 0;

        private int last2 = 0;

        public void run() {
            for (Range range : changes.iterateUnchanged()) {
                int count = range.end1 - range.start1;
                for (int i = 0; i < count; i++) {
                    int index1 = range.start1 + i;
                    int index2 = range.start2 + i;
                    Line line1 = lines1.get(index1);
                    Line line2 = lines2.get(index2);
                    if (!StringUtil.equalsIgnoreWhitespaces(sample, line1.getContent())) {
                        if (line1.equals(line2)) {
                            flush(index1, index2);
                            builder.markEqual(index1, index2);
                        } else {
                            flush(index1, index2);
                            sample = line1.getContent();
                        }
                    }
                }
            }
            flush(changes.getLength1(), changes.getLength2());
        }

        private void flush(int line1, int line2) {
            if (sample == null)
                return;
            int start1 = Math.max(last1, builder.getIndex1());
            int start2 = Math.max(last2, builder.getIndex2());
            TIntArrayList subLines1 = new TIntArrayList();
            TIntArrayList subLines2 = new TIntArrayList();
            for (int i = start1; i < line1; i++) {
                if (StringUtil.equalsIgnoreWhitespaces(sample, lines1.get(i).getContent())) {
                    subLines1.add(i);
                    last1 = i + 1;
                }
            }
            for (int i = start2; i < line2; i++) {
                if (StringUtil.equalsIgnoreWhitespaces(sample, lines2.get(i).getContent())) {
                    subLines2.add(i);
                    last2 = i + 1;
                }
            }
            assert subLines1.size() > 0 && subLines2.size() > 0;
            alignExactMatching(subLines1, subLines2);
            sample = null;
        }

        private void alignExactMatching(TIntArrayList subLines1, TIntArrayList subLines2) {
            int n = Math.max(subLines1.size(), subLines2.size());
            boolean skipAligning = // we use brute-force algorithm (C_n_k). This will limit search space by ~250 cases.
            n > 10 || // nothing to do
            subLines1.size() == subLines2.size();
            if (skipAligning) {
                int count = Math.min(subLines1.size(), subLines2.size());
                for (int i = 0; i < count; i++) {
                    int index1 = subLines1.get(i);
                    int index2 = subLines2.get(i);
                    if (lines1.get(index1).equals(lines2.get(index2))) {
                        builder.markEqual(index1, index2);
                    }
                }
                return;
            }
            if (subLines1.size() < subLines2.size()) {
                int[] matching = getBestMatchingAlignment(subLines1, subLines2, lines1, lines2);
                for (int i = 0; i < subLines1.size(); i++) {
                    int index1 = subLines1.get(i);
                    int index2 = subLines2.get(matching[i]);
                    if (lines1.get(index1).equals(lines2.get(index2))) {
                        builder.markEqual(index1, index2);
                    }
                }
            } else {
                int[] matching = getBestMatchingAlignment(subLines2, subLines1, lines2, lines1);
                for (int i = 0; i < subLines2.size(); i++) {
                    int index1 = subLines1.get(matching[i]);
                    int index2 = subLines2.get(i);
                    if (lines1.get(index1).equals(lines2.get(index2))) {
                        builder.markEqual(index1, index2);
                    }
                }
            }
        }
    }.run();
    return fair(builder.finish());
}
Also used : MergeRange(com.intellij.diff.util.MergeRange) Range(com.intellij.diff.util.Range) TIntArrayList(gnu.trove.TIntArrayList) NotNull(org.jetbrains.annotations.NotNull)

Example 24 with Range

use of com.intellij.diff.util.Range in project intellij-community by JetBrains.

the class ByWord method splitIterable2Side.

@NotNull
private static Couple<List<Range>> splitIterable2Side(@NotNull FairDiffIterable changes, int offset) {
    final List<Range> ranges1 = new ArrayList<>();
    final List<Range> ranges2 = new ArrayList<>();
    for (Range ch : changes.iterateUnchanged()) {
        if (ch.end2 <= offset) {
            ranges1.add(new Range(ch.start1, ch.end1, ch.start2, ch.end2));
        } else if (ch.start2 >= offset) {
            ranges2.add(new Range(ch.start1, ch.end1, ch.start2 - offset, ch.end2 - offset));
        } else {
            int len2 = offset - ch.start2;
            ranges1.add(new Range(ch.start1, ch.start1 + len2, ch.start2, offset));
            ranges2.add(new Range(ch.start1 + len2, ch.end1, 0, ch.end2 - offset));
        }
    }
    return Couple.of(ranges1, ranges2);
}
Also used : ArrayList(java.util.ArrayList) MergeRange(com.intellij.diff.util.MergeRange) Range(com.intellij.diff.util.Range) NotNull(org.jetbrains.annotations.NotNull)

Example 25 with Range

use of com.intellij.diff.util.Range in project intellij-community by JetBrains.

the class TextPatchBuilder method createHunk.

@NotNull
private static PatchHunk createHunk(@NotNull List<Range> hunkFragments, @NotNull List<String> beforeLines, @NotNull List<String> afterLines, boolean beforeNoNewlineAtEOF, boolean afterNoNewlineAtEOF) {
    Range first = hunkFragments.get(0);
    Range last = hunkFragments.get(hunkFragments.size() - 1);
    int contextStart1 = Math.max(first.start1 - CONTEXT_LINES, 0);
    int contextStart2 = Math.max(first.start2 - CONTEXT_LINES, 0);
    int contextEnd1 = Math.min(last.end1 + CONTEXT_LINES, beforeLines.size());
    int contextEnd2 = Math.min(last.end2 + CONTEXT_LINES, afterLines.size());
    PatchHunk hunk = new PatchHunk(contextStart1, contextEnd1, contextStart2, contextEnd2);
    int lastLine1 = contextStart1;
    int lastLine2 = contextStart2;
    for (Range fragment : hunkFragments) {
        int start1 = fragment.start1;
        int start2 = fragment.start2;
        int end1 = fragment.end1;
        int end2 = fragment.end2;
        assert start1 - lastLine1 == start2 - lastLine2;
        for (int i = lastLine1; i < start1; i++) {
            addLineToHunk(hunk, beforeLines, PatchLine.Type.CONTEXT, i, beforeNoNewlineAtEOF);
        }
        for (int i = start1; i < end1; i++) {
            addLineToHunk(hunk, beforeLines, PatchLine.Type.REMOVE, i, beforeNoNewlineAtEOF);
        }
        for (int i = start2; i < end2; i++) {
            addLineToHunk(hunk, afterLines, PatchLine.Type.ADD, i, afterNoNewlineAtEOF);
        }
        lastLine1 = end1;
        lastLine2 = end2;
    }
    assert contextEnd1 - lastLine1 == contextEnd2 - lastLine2;
    for (int i = lastLine1; i < contextEnd1; i++) {
        addLineToHunk(hunk, beforeLines, PatchLine.Type.CONTEXT, i, beforeNoNewlineAtEOF);
    }
    return hunk;
}
Also used : Range(com.intellij.diff.util.Range) NotNull(org.jetbrains.annotations.NotNull)

Aggregations

Range (com.intellij.diff.util.Range)26 NotNull (org.jetbrains.annotations.NotNull)21 MergeRange (com.intellij.diff.util.MergeRange)8 ArrayList (java.util.ArrayList)7 TextRange (com.intellij.openapi.util.TextRange)5 FairDiffIterable (com.intellij.diff.comparison.iterables.FairDiffIterable)3 Iterator (java.util.Iterator)3 DiffTooBigException (com.intellij.diff.comparison.DiffTooBigException)2 DiffIterable (com.intellij.diff.comparison.iterables.DiffIterable)2 DiffIterableUtil (com.intellij.diff.comparison.iterables.DiffIterableUtil)2 DiffUtil (com.intellij.diff.util.DiffUtil)2 IntPair (com.intellij.diff.util.IntPair)2 TIntArrayList (gnu.trove.TIntArrayList)2 Nullable (org.jetbrains.annotations.Nullable)2 WordBlock (com.intellij.diff.comparison.LineFragmentSplitter.WordBlock)1 DiffIterableUtil.fair (com.intellij.diff.comparison.iterables.DiffIterableUtil.fair)1 com.intellij.diff.fragments (com.intellij.diff.fragments)1 DiffFragment (com.intellij.diff.fragments.DiffFragment)1 Side (com.intellij.diff.util.Side)1 Logger (com.intellij.openapi.diagnostic.Logger)1