mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
merge: do not re-check if conflict can be resolved every time
* store this information in MergeConflictType
This commit is contained in:
@@ -781,25 +781,6 @@ public class TextMergeViewer implements MergeTool.MergeViewer {
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private CharSequence tryResolveConflictedChangeUsingInnerDifferences(@NotNull TextMergeChange change) {
|
||||
if (!change.isConflict()) return null;
|
||||
if (change.isResolved(Side.LEFT) || change.isResolved(Side.RIGHT)) return null;
|
||||
|
||||
MergeLineFragment changeFragment = change.getFragment();
|
||||
if (changeFragment.getStartLine(ThreeSide.LEFT) == changeFragment.getEndLine(ThreeSide.LEFT)) return null;
|
||||
if (changeFragment.getStartLine(ThreeSide.BASE) == changeFragment.getEndLine(ThreeSide.BASE)) return null;
|
||||
if (changeFragment.getStartLine(ThreeSide.RIGHT) == changeFragment.getEndLine(ThreeSide.RIGHT)) return null;
|
||||
|
||||
if (isChangeRangeModified(change)) return null;
|
||||
|
||||
List<CharSequence> texts = ThreeSide.map(side -> {
|
||||
return DiffUtil.getLinesContent(getEditor(side).getDocument(), change.getStartLine(side), change.getEndLine(side));
|
||||
});
|
||||
|
||||
return ComparisonMergeUtil.tryResolveConflict(texts.get(0), texts.get(1), texts.get(2));
|
||||
}
|
||||
|
||||
private boolean isChangeRangeModified(@NotNull TextMergeChange change) {
|
||||
MergeLineFragment changeFragment = change.getFragment();
|
||||
int baseStartLine = changeFragment.getStartLine(ThreeSide.BASE);
|
||||
@@ -817,12 +798,24 @@ public class TextMergeViewer implements MergeTool.MergeViewer {
|
||||
}
|
||||
|
||||
public boolean canResolveConflictedChange(@NotNull TextMergeChange change) {
|
||||
return tryResolveConflictedChangeUsingInnerDifferences(change) != null;
|
||||
return change.isConflict() &&
|
||||
change.getType().canBeResolved() &&
|
||||
!change.isResolved(Side.LEFT) && !change.isResolved(Side.RIGHT) &&
|
||||
!isChangeRangeModified(change);
|
||||
}
|
||||
|
||||
public void resolveConflictedChange(@NotNull TextMergeChange change) {
|
||||
CharSequence newContent = tryResolveConflictedChangeUsingInnerDifferences(change);
|
||||
if (newContent == null) return;
|
||||
if (!canResolveConflictedChange(change)) return;
|
||||
|
||||
List<CharSequence> texts = ThreeSide.map(side -> {
|
||||
return DiffUtil.getLinesContent(getEditor(side).getDocument(), change.getStartLine(side), change.getEndLine(side));
|
||||
});
|
||||
|
||||
CharSequence newContent = ComparisonMergeUtil.tryResolveConflict(texts.get(0), texts.get(1), texts.get(2));
|
||||
if (newContent == null) {
|
||||
LOG.warn(String.format("Can't resolve conflicting change:\n'%s'\n'%s'\n'%s'\n", texts.get(0), texts.get(1), texts.get(2)));
|
||||
return;
|
||||
}
|
||||
|
||||
String[] newContentLines = LineTokenizer.tokenize(newContent, false);
|
||||
myModel.replaceChange(change.getIndex(), Arrays.asList(newContentLines));
|
||||
@@ -878,19 +871,16 @@ public class TextMergeViewer implements MergeTool.MergeViewer {
|
||||
//
|
||||
|
||||
private boolean hasNonConflictedChanges(@NotNull ThreeSide side) {
|
||||
if (ContainerUtil.exists(getAllChanges(), change -> !change.isResolved() &&
|
||||
!change.isConflict() &&
|
||||
change.isChange(side))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (side == ThreeSide.BASE) {
|
||||
if (ContainerUtil.exists(getAllChanges(), change -> canResolveConflictedChange(change))) {
|
||||
return true;
|
||||
return ContainerUtil.exists(getAllChanges(), change -> {
|
||||
if (change.isConflict()) {
|
||||
return side == ThreeSide.BASE &&
|
||||
canResolveConflictedChange(change);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
else {
|
||||
return !change.isResolved() &&
|
||||
change.isChange(side);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void applyNonConflictedChanges(@NotNull ThreeSide side) {
|
||||
@@ -1163,9 +1153,12 @@ public class TextMergeViewer implements MergeTool.MergeViewer {
|
||||
|
||||
@Override
|
||||
protected boolean isEnabled(@NotNull TextMergeChange change) {
|
||||
if (change.isResolved()) return false;
|
||||
if (change.isConflict()) return canResolveConflictedChange(change);
|
||||
return true;
|
||||
if (change.isConflict()) {
|
||||
return canResolveConflictedChange(change);
|
||||
}
|
||||
else {
|
||||
return !change.isResolved();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -20,10 +20,7 @@ import com.intellij.diff.DiffContext;
|
||||
import com.intellij.diff.DiffDialogHints;
|
||||
import com.intellij.diff.DiffTool;
|
||||
import com.intellij.diff.SuppressiveDiffTool;
|
||||
import com.intellij.diff.comparison.ByWord;
|
||||
import com.intellij.diff.comparison.ComparisonManager;
|
||||
import com.intellij.diff.comparison.ComparisonPolicy;
|
||||
import com.intellij.diff.comparison.ComparisonUtil;
|
||||
import com.intellij.diff.comparison.*;
|
||||
import com.intellij.diff.contents.DiffContent;
|
||||
import com.intellij.diff.contents.DiffPsiFileSupport;
|
||||
import com.intellij.diff.contents.DocumentContent;
|
||||
@@ -1027,7 +1024,8 @@ public class DiffUtil {
|
||||
|
||||
@NotNull
|
||||
public static MergeConflictType getMergeType(@NotNull Condition<ThreeSide> emptiness,
|
||||
@NotNull Equality<ThreeSide> equality) {
|
||||
@NotNull Equality<ThreeSide> equality,
|
||||
@NotNull BooleanGetter conflictResolver) {
|
||||
boolean isLeftEmpty = emptiness.value(ThreeSide.LEFT);
|
||||
boolean isBaseEmpty = emptiness.value(ThreeSide.BASE);
|
||||
boolean isRightEmpty = emptiness.value(ThreeSide.RIGHT);
|
||||
@@ -1042,12 +1040,17 @@ public class DiffUtil {
|
||||
}
|
||||
else { // =-=
|
||||
boolean equalModifications = equality.equals(ThreeSide.LEFT, ThreeSide.RIGHT);
|
||||
return new MergeConflictType(equalModifications ? TextDiffType.INSERTED : TextDiffType.CONFLICT);
|
||||
if (equalModifications) {
|
||||
return new MergeConflictType(TextDiffType.INSERTED, true, true);
|
||||
}
|
||||
else {
|
||||
return new MergeConflictType(TextDiffType.CONFLICT, true, true, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (isLeftEmpty && isRightEmpty) { // -=-
|
||||
return new MergeConflictType(TextDiffType.DELETED);
|
||||
return new MergeConflictType(TextDiffType.DELETED, true, true);
|
||||
}
|
||||
else { // -==, ==-, ===
|
||||
boolean unchangedLeft = equality.equals(ThreeSide.BASE, ThreeSide.LEFT);
|
||||
@@ -1058,7 +1061,13 @@ public class DiffUtil {
|
||||
if (unchangedRight) return new MergeConflictType(isLeftEmpty ? TextDiffType.DELETED : TextDiffType.MODIFIED, true, false);
|
||||
|
||||
boolean equalModifications = equality.equals(ThreeSide.LEFT, ThreeSide.RIGHT);
|
||||
return new MergeConflictType(equalModifications ? TextDiffType.MODIFIED : TextDiffType.CONFLICT);
|
||||
if (equalModifications) {
|
||||
return new MergeConflictType(TextDiffType.MODIFIED, true, true);
|
||||
}
|
||||
else {
|
||||
boolean canBeResolved = !isLeftEmpty && !isRightEmpty && conflictResolver.get();
|
||||
return new MergeConflictType(TextDiffType.CONFLICT, true, true, canBeResolved);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1069,7 +1078,17 @@ public class DiffUtil {
|
||||
@NotNull List<LineOffsets> lineOffsets,
|
||||
@NotNull ComparisonPolicy policy) {
|
||||
return getMergeType((side) -> isLineMergeIntervalEmpty(fragment, side),
|
||||
(side1, side2) -> compareLineMergeContents(fragment, sequences, lineOffsets, policy, side1, side2));
|
||||
(side1, side2) -> compareLineMergeContents(fragment, sequences, lineOffsets, policy, side1, side2),
|
||||
() -> canResolveLineConflict(fragment, sequences, lineOffsets));
|
||||
}
|
||||
|
||||
private static boolean canResolveLineConflict(@NotNull MergeLineFragment fragment,
|
||||
@NotNull List<? extends CharSequence> sequences,
|
||||
@NotNull List<LineOffsets> lineOffsets) {
|
||||
List<? extends CharSequence> contents = ThreeSide.map(side -> {
|
||||
return getLinesContent(side.select(sequences), side.select(lineOffsets), fragment.getStartLine(side), fragment.getEndLine(side));
|
||||
});
|
||||
return ComparisonMergeUtil.tryResolveConflict(contents.get(0), contents.get(1), contents.get(2)) != null;
|
||||
}
|
||||
|
||||
private static boolean compareLineMergeContents(@NotNull MergeLineFragment fragment,
|
||||
@@ -1111,7 +1130,8 @@ public class DiffUtil {
|
||||
@NotNull List<? extends CharSequence> texts,
|
||||
@NotNull ComparisonPolicy policy) {
|
||||
return getMergeType((side) -> isWordMergeIntervalEmpty(fragment, side),
|
||||
(side1, side2) -> compareWordMergeContents(fragment, texts, policy, side1, side2));
|
||||
(side1, side2) -> compareWordMergeContents(fragment, texts, policy, side1, side2),
|
||||
BooleanGetter.FALSE);
|
||||
}
|
||||
|
||||
private static boolean compareWordMergeContents(@NotNull MergeWordFragment fragment,
|
||||
|
||||
@@ -21,15 +21,17 @@ public class MergeConflictType {
|
||||
@NotNull private final TextDiffType myType;
|
||||
private final boolean myLeftChange;
|
||||
private final boolean myRightChange;
|
||||
|
||||
public MergeConflictType(@NotNull TextDiffType type) {
|
||||
this(type, true, true);
|
||||
}
|
||||
private final boolean myCanBeResolved;
|
||||
|
||||
public MergeConflictType(@NotNull TextDiffType type, boolean leftChange, boolean rightChange) {
|
||||
this(type, leftChange, rightChange, true);
|
||||
}
|
||||
|
||||
public MergeConflictType(@NotNull TextDiffType type, boolean leftChange, boolean rightChange, boolean canBeResolved) {
|
||||
myType = type;
|
||||
myLeftChange = leftChange;
|
||||
myRightChange = rightChange;
|
||||
myCanBeResolved = canBeResolved;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -37,6 +39,10 @@ public class MergeConflictType {
|
||||
return myType;
|
||||
}
|
||||
|
||||
public boolean canBeResolved() {
|
||||
return myCanBeResolved;
|
||||
}
|
||||
|
||||
public boolean isChange(@NotNull Side side) {
|
||||
return side.isLeft() ? myLeftChange : myRightChange;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user