/* * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.intellij.openapi.diff.impl.incrementalMerge; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.diff.impl.highlighting.FragmentSide; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.ex.DocumentEx; import com.intellij.openapi.util.TextRange; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; public abstract class TwoSideChange<T extends TwoSideChange.SideChange> extends ChangeSide implements DiffRangeMarker.RangeInvalidListener { @NotNull protected final MergeList myMergeList; @NotNull protected DiffRangeMarker myBaseRangeMarker; protected T myLeftChange; protected T myRightChange; @NotNull protected final ChangeHighlighterHolder myCommonHighlighterHolder; protected TwoSideChange(@NotNull TextRange baseRange, @NotNull MergeList mergeList, @NotNull ChangeHighlighterHolder highlighterHolder) { myBaseRangeMarker = new DiffRangeMarker((DocumentEx)mergeList.getBaseDocument(), baseRange, this); myMergeList = mergeList; myCommonHighlighterHolder = highlighterHolder; } @NotNull public ChangeHighlighterHolder getHighlighterHolder() { return myCommonHighlighterHolder; } @NotNull public DiffRangeMarker getRange() { return myBaseRangeMarker; } @Nullable public Change getLeftChange() { return myLeftChange; } @Nullable public Change getRightChange() { return myRightChange; } public void setRange(@NotNull DiffRangeMarker range) { myBaseRangeMarker = range; } @Nullable T getOtherChange(@NotNull T change) { if (change == myLeftChange) { return myRightChange; } else if (change == myRightChange) { return myLeftChange; } else { throw new IllegalStateException("Unexpected change: " + change); } } public void removeOtherChange(@NotNull T change) { if (change == myLeftChange) { myRightChange = null; } else if (change == myRightChange) { myLeftChange = null; } else { throw new IllegalStateException("Unexpected change: " + change); } } public void conflictRemoved() { removeHighlighters(myLeftChange); removeHighlighters(myRightChange); myCommonHighlighterHolder.removeHighlighters(); myMergeList.removeChanges(myLeftChange, myRightChange); myBaseRangeMarker.removeListener(this); } private static <T extends SideChange> void removeHighlighters(@Nullable T change) { if (change != null) { change.getOriginalSide().getHighlighterHolder().removeHighlighters(); } } @NotNull public Document getOriginalDocument(FragmentSide mergeSide) { return myMergeList.getChanges(mergeSide).getDocument(MergeList.BRANCH_SIDE); } public void onRangeInvalidated() { conflictRemoved(); } @NotNull public MergeList getMergeList() { return myMergeList; } protected static abstract class SideChange<V extends TwoSideChange> extends Change implements DiffRangeMarker.RangeInvalidListener { protected V myTwoSideChange; @NotNull protected final ChangeList myChangeList; protected SimpleChangeSide myOriginalSide; @NotNull protected ChangeType myType; protected SideChange(@NotNull V twoSideChange, @NotNull ChangeList changeList, @NotNull ChangeType type, @NotNull FragmentSide mergeSide, @NotNull TextRange versionRange) { myTwoSideChange = twoSideChange; myChangeList = changeList; myOriginalSide = new SimpleChangeSide(mergeSide, new DiffRangeMarker((DocumentEx)twoSideChange.getOriginalDocument(mergeSide), versionRange, this)); myType = type; } @NotNull public ChangeType getType() { return myType; } public SimpleChangeSide getOriginalSide() { return myOriginalSide; } protected void markApplied() { myType = ChangeType.deriveApplied(myType); myChangeList.apply(this); myOriginalSide.getHighlighterHolder().updateHighlighter(myOriginalSide, myType); myOriginalSide.getHighlighterHolder().setActions(AnAction.EMPTY_ARRAY); // display, what one side of the conflict was resolved to myTwoSideChange.getHighlighterHolder().updateHighlighter(myTwoSideChange, myType); } public ChangeList getChangeList() { return myTwoSideChange.getMergeList().getChanges(myOriginalSide.getFragmentSide()); } @Override protected void changeSide(ChangeSide sideToChange, DiffRangeMarker newRange) { myTwoSideChange.setRange(newRange); } @NotNull @Override public ChangeSide getChangeSide(@NotNull FragmentSide side) { return isBranch(side) ? myOriginalSide : myTwoSideChange; } protected static boolean isBranch(@NotNull FragmentSide side) { return MergeList.BRANCH_SIDE == side; } protected void removeFromList() { myTwoSideChange.conflictRemoved(); myTwoSideChange = null; } public boolean isValid() { return myTwoSideChange != null; } public void onRemovedFromList() { myOriginalSide.getRange().removeListener(this); myTwoSideChange = null; myOriginalSide = null; } public void onRangeInvalidated() { removeFromList(); } } }