merge: simplify - move non-conflict resolution logic into one method

This commit is contained in:
Aleksey Pivovarov
2017-03-06 16:51:22 +03:00
parent 533b211368
commit 21b1c57e51
4 changed files with 59 additions and 76 deletions
@@ -324,20 +324,20 @@ public class TextMergeChange extends ThreesideDiffChangeBase {
@Nullable
private GutterIconRenderer createResolveRenderer() {
if (!myViewer.canResolveConflictedChange(this)) return null;
if (!this.isConflict() || !myViewer.canApplyNonConflictedChange(this, ThreeSide.BASE)) return null;
return createIconRenderer(DiffBundle.message("merge.dialog.resolve.change.action.name"), AllIcons.Diff.MagicResolve, false, () -> {
myViewer.executeMergeCommand("Resolve conflict", Collections.singletonList(this), () -> {
myViewer.resolveConflictedChange(this);
myViewer.applyNonConflictedChange(this, ThreeSide.BASE);
});
});
}
@Nullable
private GutterIconRenderer createIconRenderer(@NotNull final String text,
@NotNull final Icon icon,
boolean ctrlClickVisible,
@NotNull final Runnable perform) {
@NotNull
private static GutterIconRenderer createIconRenderer(@NotNull final String text,
@NotNull final Icon icon,
boolean ctrlClickVisible,
@NotNull final Runnable perform) {
final String tooltipText = DiffUtil.createTooltipText(text, ctrlClickVisible ? CTRL_CLICK_TO_RESOLVE : null);
return new DiffGutterRenderer(icon, tooltipText) {
@Override
@@ -781,47 +781,6 @@ public class TextMergeViewer implements MergeTool.MergeViewer {
}
}
private boolean isChangeRangeModified(@NotNull TextMergeChange change) {
MergeLineFragment changeFragment = change.getFragment();
int baseStartLine = changeFragment.getStartLine(ThreeSide.BASE);
int baseEndLine = changeFragment.getEndLine(ThreeSide.BASE);
DiffContent baseDiffContent = ThreeSide.BASE.select(myMergeRequest.getContents());
Document baseDocument = ((DocumentContent)baseDiffContent).getDocument();
int resultStartLine = change.getStartLine();
int resultEndLine = change.getEndLine();
Document resultDocument = getEditor().getDocument();
CharSequence baseContent = DiffUtil.getLinesContent(baseDocument, baseStartLine, baseEndLine);
CharSequence resultContent = DiffUtil.getLinesContent(resultDocument, resultStartLine, resultEndLine);
return !StringUtil.equals(baseContent, resultContent);
}
public boolean canResolveConflictedChange(@NotNull TextMergeChange change) {
return change.isConflict() &&
change.getType().canBeResolved() &&
!change.isResolved(Side.LEFT) && !change.isResolved(Side.RIGHT) &&
!isChangeRangeModified(change);
}
public void resolveConflictedChange(@NotNull TextMergeChange change) {
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));
markChangeResolved(change);
}
private class MyMergeModel extends MergeModelBase<TextMergeChange.State> {
public MyMergeModel(@Nullable Project project, @NotNull Document document) {
super(project, document);
@@ -871,17 +830,7 @@ public class TextMergeViewer implements MergeTool.MergeViewer {
//
private boolean hasNonConflictedChanges(@NotNull ThreeSide side) {
return ContainerUtil.exists(getAllChanges(), change -> {
if (change.isConflict()) {
return side == ThreeSide.BASE &&
canResolveConflictedChange(change);
}
else {
return !change.isResolved() &&
change.isChange(side) &&
!isChangeRangeModified(change);
}
});
return ContainerUtil.exists(getAllChanges(), change -> canApplyNonConflictedChange(change, side));
}
private void applyNonConflictedChanges(@NotNull ThreeSide side) {
@@ -896,15 +845,55 @@ public class TextMergeViewer implements MergeTool.MergeViewer {
if (firstUnresolved != null) doScrollToChange(firstUnresolved, true);
}
private void applyNonConflictedChange(@NotNull TextMergeChange change, @NotNull ThreeSide side) {
public boolean canApplyNonConflictedChange(@NotNull TextMergeChange change, @NotNull ThreeSide side) {
if (change.isConflict()) {
if (side != ThreeSide.BASE) return;
resolveConflictedChange(change);
return side == ThreeSide.BASE &&
change.getType().canBeResolved() &&
!change.isResolved(Side.LEFT) && !change.isResolved(Side.RIGHT) &&
!isChangeRangeModified(change);
}
else {
return !change.isResolved() &&
change.isChange(side) &&
!isChangeRangeModified(change);
}
}
private boolean isChangeRangeModified(@NotNull TextMergeChange change) {
MergeLineFragment changeFragment = change.getFragment();
int baseStartLine = changeFragment.getStartLine(ThreeSide.BASE);
int baseEndLine = changeFragment.getEndLine(ThreeSide.BASE);
DiffContent baseDiffContent = ThreeSide.BASE.select(myMergeRequest.getContents());
Document baseDocument = ((DocumentContent)baseDiffContent).getDocument();
int resultStartLine = change.getStartLine();
int resultEndLine = change.getEndLine();
Document resultDocument = getEditor().getDocument();
CharSequence baseContent = DiffUtil.getLinesContent(baseDocument, baseStartLine, baseEndLine);
CharSequence resultContent = DiffUtil.getLinesContent(resultDocument, resultStartLine, resultEndLine);
return !StringUtil.equals(baseContent, resultContent);
}
public void applyNonConflictedChange(@NotNull TextMergeChange change, @NotNull ThreeSide side) {
if (!canApplyNonConflictedChange(change, side)) return;
if (change.isConflict()) {
List<CharSequence> texts = ThreeSide.map(it -> {
return DiffUtil.getLinesContent(getEditor(it).getDocument(), change.getStartLine(it), change.getEndLine(it));
});
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));
markChangeResolved(change);
}
else {
if (change.isResolved(side)) return;
if (!change.isChange(side)) return;
if (isChangeRangeModified(change)) return;
Side masterSide = side.select(Side.LEFT,
change.isChange(Side.LEFT) ? Side.LEFT : Side.RIGHT,
Side.RIGHT);
@@ -1155,13 +1144,7 @@ public class TextMergeViewer implements MergeTool.MergeViewer {
@Override
protected boolean isEnabled(@NotNull TextMergeChange change) {
if (change.isConflict()) {
return canResolveConflictedChange(change);
}
else {
return !change.isResolved() &&
!isChangeRangeModified(change);
}
return canApplyNonConflictedChange(change, ThreeSide.BASE);
}
@Override
@@ -82,7 +82,7 @@ class MergeAutoTest : MergeTestBase() {
val index = RNG.nextInt(changes.size)
val change = changes[index]
command(change) { viewer.resolveConflictedChange(change) }
command(change) { viewer.applyNonConflictedChange(change, ThreeSide.BASE) }
}
private fun TestBuilder.doModifyText(): Unit {
@@ -164,14 +164,14 @@ abstract class MergeTestBase : DiffTestCase() {
fun Int.resolve() {
val change = change(this)
command(change) {
assertTrue(viewer.canResolveConflictedChange(change))
viewer.resolveConflictedChange(change)
assertTrue(change.isConflict && viewer.canApplyNonConflictedChange(change, ThreeSide.BASE))
viewer.applyNonConflictedChange(change, ThreeSide.BASE)
}
}
fun Int.canResolveConflict(): Boolean {
val change = change(this)
return viewer.canResolveConflictedChange(change)
return viewer.canApplyNonConflictedChange(change, ThreeSide.BASE)
}
//