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());
}
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());
}
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());
}
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);
}
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;
}
Aggregations