mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-10-01 06:51:17 +07:00
IDEA-204040 diff: support changelists and excluded changes in unified viewer - introduce tool for local changelists
GitOrigin-RevId: cd1ae2d5dbaaf3b8642d2b6cc3f57af6f73331c3
This commit is contained in:
committed by
intellij-monorepo-bot
parent
02880c9336
commit
013744871f
@@ -30,15 +30,29 @@ public class UnifiedDiffChange {
|
||||
@NotNull private final LineRange myInsertedRange;
|
||||
@NotNull private final LineFragment myLineFragment;
|
||||
|
||||
private final boolean myIsExcluded;
|
||||
private final boolean myIsSkipped;
|
||||
|
||||
public UnifiedDiffChange(int blockStart,
|
||||
int insertedStart,
|
||||
int blockEnd,
|
||||
@NotNull LineFragment lineFragment) {
|
||||
this(blockStart, insertedStart, blockEnd, lineFragment, false, false);
|
||||
}
|
||||
|
||||
public UnifiedDiffChange(int blockStart,
|
||||
int insertedStart,
|
||||
int blockEnd,
|
||||
@NotNull LineFragment lineFragment,
|
||||
boolean isExcluded,
|
||||
boolean isSkipped) {
|
||||
myLine1 = blockStart;
|
||||
myLine2 = blockEnd;
|
||||
myDeletedRange = new LineRange(blockStart, insertedStart);
|
||||
myInsertedRange = new LineRange(insertedStart, blockEnd);
|
||||
myLineFragment = lineFragment;
|
||||
myIsExcluded = isExcluded;
|
||||
myIsSkipped = isSkipped;
|
||||
}
|
||||
|
||||
public int getLine1() {
|
||||
@@ -67,6 +81,14 @@ public class UnifiedDiffChange {
|
||||
return myInsertedRange;
|
||||
}
|
||||
|
||||
public boolean isExcluded() {
|
||||
return myIsExcluded;
|
||||
}
|
||||
|
||||
public boolean isSkipped() {
|
||||
return myIsSkipped;
|
||||
}
|
||||
|
||||
public void processChange(int oldLine1, int oldLine2, int shift) {
|
||||
UpdatedLineRange newRange = DiffUtil.updateRangeOnModification(myLine1, myLine2, oldLine1, oldLine2, shift);
|
||||
myLine1 = newRange.startLine;
|
||||
|
||||
@@ -54,6 +54,8 @@ public class UnifiedDiffChangeUi {
|
||||
}
|
||||
|
||||
private void doInstallActionHighlighters() {
|
||||
if (myChange.isSkipped()) return;
|
||||
|
||||
boolean leftEditable = myViewer.isEditable(Side.LEFT, false);
|
||||
boolean rightEditable = myViewer.isEditable(Side.RIGHT, false);
|
||||
|
||||
@@ -70,6 +72,8 @@ public class UnifiedDiffChangeUi {
|
||||
myHighlighters.addAll(DiffDrawUtil.createUnifiedChunkHighlighters(myEditor,
|
||||
myChange.getDeletedRange(),
|
||||
myChange.getInsertedRange(),
|
||||
myChange.isExcluded(),
|
||||
myChange.isSkipped(),
|
||||
myChange.getLineFragment().getInnerFragments()));
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,6 @@ import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ReadAction;
|
||||
import com.intellij.openapi.command.undo.UndoManager;
|
||||
import com.intellij.openapi.diff.DiffBundle;
|
||||
import com.intellij.openapi.diff.LineTokenizer;
|
||||
import com.intellij.openapi.editor.*;
|
||||
import com.intellij.openapi.editor.actionSystem.EditorActionManager;
|
||||
@@ -45,7 +44,6 @@ import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.pom.Navigatable;
|
||||
import com.intellij.util.ThreeState;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import gnu.trove.TIntFunction;
|
||||
import org.jetbrains.annotations.*;
|
||||
@@ -67,7 +65,7 @@ public class UnifiedDiffViewer extends ListenerDiffViewerBase {
|
||||
@NotNull private final MyInitialScrollHelper myInitialScrollHelper = new MyInitialScrollHelper();
|
||||
@NotNull private final MyFoldingModel myFoldingModel;
|
||||
|
||||
@NotNull private final TwosideTextDiffProvider.NoIgnore myTextDiffProvider;
|
||||
@NotNull protected final TwosideTextDiffProvider.NoIgnore myTextDiffProvider;
|
||||
|
||||
@NotNull protected Side myMasterSide = Side.RIGHT;
|
||||
|
||||
@@ -253,15 +251,20 @@ public class UnifiedDiffViewer extends ListenerDiffViewerBase {
|
||||
}
|
||||
catch (Throwable e) {
|
||||
LOG.error(e);
|
||||
return () -> {
|
||||
clearDiffPresentation();
|
||||
myPanel.setErrorContent();
|
||||
};
|
||||
return applyErrorNotification();
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Runnable computeDifferences(@NotNull ProgressIndicator indicator) {
|
||||
protected Runnable applyErrorNotification() {
|
||||
return () -> {
|
||||
clearDiffPresentation();
|
||||
myPanel.setErrorContent();
|
||||
};
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected Runnable computeDifferences(@NotNull ProgressIndicator indicator) {
|
||||
final Document document1 = getContent1().getDocument();
|
||||
final Document document2 = getContent2().getDocument();
|
||||
|
||||
@@ -320,9 +323,9 @@ public class UnifiedDiffViewer extends ListenerDiffViewerBase {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Runnable apply(@NotNull UnifiedFragmentBuilder builder,
|
||||
@NotNull CharSequence[] texts,
|
||||
@NotNull ProgressIndicator indicator) {
|
||||
protected Runnable apply(@NotNull UnifiedFragmentBuilder builder,
|
||||
@NotNull CharSequence[] texts,
|
||||
@NotNull ProgressIndicator indicator) {
|
||||
final DocumentContent content1 = getContent1();
|
||||
final DocumentContent content2 = getContent2();
|
||||
|
||||
@@ -823,7 +826,7 @@ public class UnifiedDiffViewer extends ListenerDiffViewerBase {
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected JComponent getStatusPanel() {
|
||||
protected StatusPanel getStatusPanel() {
|
||||
return myStatusPanel;
|
||||
}
|
||||
|
||||
@@ -1026,13 +1029,12 @@ public class UnifiedDiffViewer extends ListenerDiffViewerBase {
|
||||
@Override
|
||||
protected String getMessage() {
|
||||
ChangedBlockData blockData = myModel.getData();
|
||||
|
||||
if (blockData == null) return null;
|
||||
int changesCount = blockData.getDiffChanges().size();
|
||||
if (changesCount == 0 && myModel.isContentsEqual() == ThreeState.NO) {
|
||||
return DiffBundle.message("diff.all.differences.ignored.text");
|
||||
}
|
||||
return DiffBundle.message("diff.count.differences.status.text", changesCount);
|
||||
|
||||
List<UnifiedDiffChange> allChanges = blockData.getDiffChanges();
|
||||
return DiffUtil.getStatusText(allChanges.size(),
|
||||
ContainerUtil.count(allChanges, it -> it.isExcluded()),
|
||||
myModel.isContentsEqual());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1104,7 +1106,8 @@ public class UnifiedDiffViewer extends ListenerDiffViewerBase {
|
||||
List<UnifiedDiffChange> changes = myModel.getDiffChanges();
|
||||
if (changes == null) return false;
|
||||
|
||||
UnifiedDiffChange targetChange = scrollToChangePolicy.select(changes);
|
||||
UnifiedDiffChange targetChange = scrollToChangePolicy.select(ContainerUtil.filter(changes, it -> !it.isSkipped()));
|
||||
if (targetChange == null) targetChange = scrollToChangePolicy.select(changes);
|
||||
if (targetChange == null) return false;
|
||||
|
||||
DiffUtil.scrollEditor(myEditor, targetChange.getLine1(), false);
|
||||
|
||||
+22
-18
@@ -25,8 +25,8 @@ import org.jetbrains.annotations.NotNull;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
class UnifiedFragmentBuilder {
|
||||
@NotNull private final List<? extends LineFragment> myFragments;
|
||||
public class UnifiedFragmentBuilder {
|
||||
@NotNull protected final List<? extends LineFragment> myFragments;
|
||||
@NotNull private final Document myDocument1;
|
||||
@NotNull private final Document myDocument2;
|
||||
@NotNull private final Side myMasterSide;
|
||||
@@ -38,7 +38,7 @@ class UnifiedFragmentBuilder {
|
||||
@NotNull private final LineNumberConvertor.Builder myConvertor2 = new LineNumberConvertor.Builder();
|
||||
@NotNull private final List<LineRange> myChangedLines = new ArrayList<>();
|
||||
|
||||
UnifiedFragmentBuilder(@NotNull List<? extends LineFragment> fragments,
|
||||
public UnifiedFragmentBuilder(@NotNull List<? extends LineFragment> fragments,
|
||||
@NotNull Document document1,
|
||||
@NotNull Document document2,
|
||||
@NotNull Side masterSide) {
|
||||
@@ -63,9 +63,10 @@ class UnifiedFragmentBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
for (LineFragment fragment : myFragments) {
|
||||
for (int i = 0; i < myFragments.size(); i++) {
|
||||
LineFragment fragment = myFragments.get(i);
|
||||
processEquals(fragment.getStartLine1() - 1, fragment.getStartLine2() - 1);
|
||||
processChanged(fragment);
|
||||
processChanged(fragment, i);
|
||||
}
|
||||
processEquals(getLineCount(myDocument1) - 1, getLineCount(myDocument2) - 1);
|
||||
|
||||
@@ -79,8 +80,7 @@ class UnifiedFragmentBuilder {
|
||||
appendTextMaster(startLine1, startLine2, endLine1, endLine2);
|
||||
}
|
||||
|
||||
@SuppressWarnings("UnnecessaryLocalVariable")
|
||||
private void processChanged(@NotNull LineFragment fragment) {
|
||||
private void processChanged(@NotNull LineFragment fragment, int fragmentIndex) {
|
||||
int startLine1 = fragment.getStartLine1();
|
||||
int endLine1 = fragment.getEndLine1() - 1;
|
||||
int lines1 = endLine1 - startLine1;
|
||||
@@ -95,7 +95,7 @@ class UnifiedFragmentBuilder {
|
||||
if (lines1 >= 0) {
|
||||
int startOffset1 = myDocument1.getLineStartOffset(startLine1);
|
||||
int endOffset1 = myDocument1.getLineEndOffset(endLine1);
|
||||
appendTextSide(Side.LEFT, startOffset1, endOffset1, lines1, lines2, startLine1, -1);
|
||||
appendText(Side.LEFT, startOffset1, endOffset1, lines1, lines2, startLine1, -1);
|
||||
}
|
||||
|
||||
int linesBetween = totalLines;
|
||||
@@ -103,17 +103,29 @@ class UnifiedFragmentBuilder {
|
||||
if (lines2 >= 0) {
|
||||
int startOffset2 = myDocument2.getLineStartOffset(startLine2);
|
||||
int endOffset2 = myDocument2.getLineEndOffset(endLine2);
|
||||
appendTextSide(Side.RIGHT, startOffset2, endOffset2, lines2, lines2, -1, startLine2);
|
||||
appendText(Side.RIGHT, startOffset2, endOffset2, lines2, lines2, -1, startLine2);
|
||||
}
|
||||
|
||||
linesAfter = totalLines;
|
||||
|
||||
myChanges.add(new UnifiedDiffChange(linesBefore, linesBetween, linesAfter, fragment));
|
||||
UnifiedDiffChange change = createDiffChange(linesBefore, linesBetween, linesAfter, fragmentIndex);
|
||||
myChanges.add(change);
|
||||
if (!change.isSkipped()) {
|
||||
myChangedLines.add(new LineRange(linesBefore, linesAfter));
|
||||
}
|
||||
|
||||
lastProcessedLine1 = endLine1;
|
||||
lastProcessedLine2 = endLine2;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected UnifiedDiffChange createDiffChange(int blockStart,
|
||||
int insertedStart,
|
||||
int blockEnd,
|
||||
int fragmentIndex) {
|
||||
return new UnifiedDiffChange(blockStart, insertedStart, blockEnd, myFragments.get(fragmentIndex));
|
||||
}
|
||||
|
||||
private void appendTextMaster(int startLine1, int startLine2, int endLine1, int endLine2) {
|
||||
// The slave-side line matching might be incomplete for non-fair line fragments (@see FairDiffIterable)
|
||||
// If it ever became an issue, it could be fixed by explicit fair by-line comparing of "equal" regions
|
||||
@@ -128,14 +140,6 @@ class UnifiedFragmentBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
private void appendTextSide(@NotNull Side side, int offset1, int offset2, int lines1, int lines2, int startLine1, int startLine2) {
|
||||
int linesBefore = totalLines;
|
||||
appendText(side, offset1, offset2, lines1, lines2, startLine1, startLine2);
|
||||
int linesAfter = totalLines;
|
||||
|
||||
if (linesBefore != linesAfter) myChangedLines.add(new LineRange(linesBefore, linesAfter));
|
||||
}
|
||||
|
||||
private void appendText(@NotNull Side side, int offset1, int offset2, int lines1, int lines2, int startLine1, int startLine2) {
|
||||
int lines = side.select(lines1, lines2);
|
||||
boolean notEmpty = lines >= 0;
|
||||
|
||||
@@ -299,21 +299,31 @@ public class DiffDrawUtil {
|
||||
@NotNull LineRange deleted,
|
||||
@NotNull LineRange inserted,
|
||||
@Nullable List<? extends DiffFragment> innerFragments) {
|
||||
return createUnifiedChunkHighlighters(editor, deleted, inserted, false, false, innerFragments);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static List<RangeHighlighter> createUnifiedChunkHighlighters(@NotNull Editor editor,
|
||||
@NotNull LineRange deleted,
|
||||
@NotNull LineRange inserted,
|
||||
boolean excluded,
|
||||
boolean skipped,
|
||||
@Nullable List<? extends DiffFragment> innerFragments) {
|
||||
boolean ignored = innerFragments != null;
|
||||
|
||||
List<RangeHighlighter> list = new ArrayList<>();
|
||||
if (!inserted.isEmpty() && !deleted.isEmpty()) {
|
||||
list.addAll(createHighlighter(editor, deleted.start, deleted.end, TextDiffType.DELETED, ignored));
|
||||
list.addAll(createHighlighter(editor, inserted.start, inserted.end, TextDiffType.INSERTED, ignored));
|
||||
list.addAll(createHighlighter(editor, deleted.start, deleted.end, TextDiffType.DELETED, ignored, skipped, excluded));
|
||||
list.addAll(createHighlighter(editor, inserted.start, inserted.end, TextDiffType.INSERTED, ignored, skipped, excluded));
|
||||
}
|
||||
else if (!inserted.isEmpty()) {
|
||||
list.addAll(createHighlighter(editor, inserted.start, inserted.end, TextDiffType.INSERTED, ignored));
|
||||
list.addAll(createHighlighter(editor, inserted.start, inserted.end, TextDiffType.INSERTED, ignored, skipped, excluded));
|
||||
}
|
||||
else if (!deleted.isEmpty()) {
|
||||
list.addAll(createHighlighter(editor, deleted.start, deleted.end, TextDiffType.DELETED, ignored));
|
||||
list.addAll(createHighlighter(editor, deleted.start, deleted.end, TextDiffType.DELETED, ignored, skipped, excluded));
|
||||
}
|
||||
|
||||
if (innerFragments != null) {
|
||||
if (innerFragments != null && !skipped) {
|
||||
int deletedStartOffset = editor.getDocument().getLineStartOffset(deleted.start);
|
||||
int insertedStartOffset = editor.getDocument().getLineStartOffset(inserted.start);
|
||||
|
||||
@@ -331,6 +341,16 @@ public class DiffDrawUtil {
|
||||
return list;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static List<RangeHighlighter> createHighlighter(@NotNull Editor editor, int startLine, int endLine, @NotNull TextDiffType type,
|
||||
boolean ignored, boolean excludedInEditor, boolean excludedInGutter) {
|
||||
return new LineHighlighterBuilder(editor, startLine, endLine, type)
|
||||
.withIgnored(ignored)
|
||||
.withExcludedInEditor(excludedInEditor)
|
||||
.withExcludedInGutter(excludedInGutter)
|
||||
.done();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static List<RangeHighlighter> createHighlighter(@NotNull Editor editor, int startLine, int endLine, @NotNull TextDiffType type,
|
||||
boolean ignored) {
|
||||
|
||||
@@ -45,7 +45,8 @@
|
||||
<diff.merge.MergeTool implementation="com.intellij.openapi.vcs.changes.patch.tool.ApplyPatchMergeTool"/>
|
||||
<diff.DiffTool implementation="com.intellij.openapi.vcs.changes.patch.tool.ApplyPatchDiffTool"/>
|
||||
<diff.DiffTool implementation="com.intellij.openapi.vcs.changes.patch.tool.PatchDiffTool"/>
|
||||
<diff.impl.DiffToolSubstitutor implementation="com.intellij.openapi.vcs.changes.actions.diff.lst.LocalChangeListDiffTool"/>
|
||||
<diff.impl.DiffToolSubstitutor implementation="com.intellij.openapi.vcs.changes.actions.diff.lst.LocalChangeListDiffTool$Simple"/>
|
||||
<diff.impl.DiffToolSubstitutor implementation="com.intellij.openapi.vcs.changes.actions.diff.lst.LocalChangeListDiffTool$Unified"/>
|
||||
|
||||
<diff.actions.ShowDiffAction.ExtensionProvider implementation="com.intellij.openapi.vcs.changes.shelf.DiffShelvedChangesActionProvider"/>
|
||||
<diff.actions.ShowDiffAction.ExtensionProvider implementation="com.intellij.openapi.vcs.update.ShowUpdatedDiffActionProvider"/>
|
||||
|
||||
+48
-22
@@ -6,40 +6,66 @@ import com.intellij.diff.DiffTool;
|
||||
import com.intellij.diff.FrameDiffTool;
|
||||
import com.intellij.diff.impl.DiffToolSubstitutor;
|
||||
import com.intellij.diff.requests.DiffRequest;
|
||||
import com.intellij.diff.tools.fragmented.UnifiedDiffTool;
|
||||
import com.intellij.diff.tools.simple.SimpleDiffTool;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.vcs.ex.PartialLocalLineStatusTracker;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class LocalChangeListDiffTool implements FrameDiffTool, DiffToolSubstitutor {
|
||||
public class LocalChangeListDiffTool {
|
||||
public static final Key<Boolean> ALLOW_EXCLUDE_FROM_COMMIT = Key.create("Diff.LocalChangeListDiffTool.ALLOW_EXCLUDE_FROM_COMMIT");
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public DiffViewer createComponent(@NotNull DiffContext context, @NotNull DiffRequest request) {
|
||||
LocalChangeListDiffRequest localRequest = (LocalChangeListDiffRequest)request;
|
||||
return new SimpleLocalChangeListDiffViewer(context, localRequest);
|
||||
public static class Simple extends Base {
|
||||
public Simple() {
|
||||
super(SimpleDiffTool.INSTANCE);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public DiffViewer createComponent(@NotNull DiffContext context, @NotNull DiffRequest request) {
|
||||
return new SimpleLocalChangeListDiffViewer(context, (LocalChangeListDiffRequest)request);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canShow(@NotNull DiffContext context, @NotNull DiffRequest request) {
|
||||
if (!(request instanceof LocalChangeListDiffRequest)) return false;
|
||||
LocalChangeListDiffRequest localRequest = (LocalChangeListDiffRequest)request;
|
||||
return localRequest.getLineStatusTracker() instanceof PartialLocalLineStatusTracker;
|
||||
public static class Unified extends Base {
|
||||
public Unified() {
|
||||
super(UnifiedDiffTool.INSTANCE);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public DiffViewer createComponent(@NotNull DiffContext context, @NotNull DiffRequest request) {
|
||||
return new UnifiedLocalChangeListDiffViewer(context, (LocalChangeListDiffRequest)request);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getName() {
|
||||
return SimpleDiffTool.INSTANCE.getName();
|
||||
}
|
||||
private static abstract class Base implements FrameDiffTool, DiffToolSubstitutor {
|
||||
@NotNull private final FrameDiffTool myReplacement;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public DiffTool getReplacement(@NotNull DiffTool tool, @NotNull DiffContext context, @NotNull DiffRequest request) {
|
||||
if (tool != SimpleDiffTool.INSTANCE) return null;
|
||||
if (!canShow(context, request)) return null;
|
||||
return this;
|
||||
protected Base(@NotNull FrameDiffTool replacement) {
|
||||
myReplacement = replacement;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canShow(@NotNull DiffContext context, @NotNull DiffRequest request) {
|
||||
if (!(request instanceof LocalChangeListDiffRequest)) return false;
|
||||
LocalChangeListDiffRequest localRequest = (LocalChangeListDiffRequest)request;
|
||||
return localRequest.getLineStatusTracker() instanceof PartialLocalLineStatusTracker;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getName() {
|
||||
return myReplacement.getName();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public DiffTool getReplacement(@NotNull DiffTool tool, @NotNull DiffContext context, @NotNull DiffRequest request) {
|
||||
if (tool != myReplacement) return null;
|
||||
if (!canShow(context, request)) return null;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+47
-2
@@ -2,6 +2,7 @@
|
||||
package com.intellij.openapi.vcs.changes.actions.diff.lst
|
||||
|
||||
import com.intellij.diff.fragments.LineFragment
|
||||
import com.intellij.diff.tools.util.base.DiffViewerBase
|
||||
import com.intellij.diff.tools.util.text.TwosideTextDiffProvider
|
||||
import com.intellij.diff.util.Range
|
||||
import com.intellij.openapi.application.runReadAction
|
||||
@@ -12,6 +13,7 @@ import com.intellij.openapi.vcs.ex.LineStatusTracker
|
||||
import com.intellij.openapi.vcs.ex.LocalRange
|
||||
import com.intellij.openapi.vcs.ex.PartialLocalLineStatusTracker
|
||||
import com.intellij.openapi.vcs.ex.SimpleLocalLineStatusTracker
|
||||
import com.intellij.openapi.vcs.impl.LineStatusTrackerManager
|
||||
|
||||
object LocalTrackerDiffUtil {
|
||||
@JvmStatic
|
||||
@@ -72,13 +74,14 @@ object LocalTrackerDiffUtil {
|
||||
|
||||
val ranges = diffData.ranges
|
||||
val isContentsEqual = ranges.isEmpty()
|
||||
val texts = arrayOf(diffData.vcsText, diffData.localText)
|
||||
|
||||
if (!StringUtil.equals(diffData.vcsText, diffData.trackerVcsText)) {
|
||||
return handler.error() // DiffRequest is out of date
|
||||
}
|
||||
|
||||
if (textDiffProvider.isHighlightingDisabled) {
|
||||
return handler.done(isContentsEqual, emptyList(), emptyList())
|
||||
return handler.done(isContentsEqual, texts, emptyList(), emptyList())
|
||||
}
|
||||
|
||||
|
||||
@@ -99,11 +102,12 @@ object LocalTrackerDiffUtil {
|
||||
repeat(rangeFragments.size) { fragmentsData.add(fragmentData) }
|
||||
}
|
||||
|
||||
return handler.done(isContentsEqual, fragments, fragmentsData)
|
||||
return handler.done(isContentsEqual, texts, fragments, fragmentsData)
|
||||
}
|
||||
|
||||
interface LocalTrackerDiffHandler {
|
||||
fun done(isContentsEqual: Boolean,
|
||||
texts: Array<CharSequence>,
|
||||
fragments: List<LineFragment>,
|
||||
fragmentsData: List<LineFragmentData>): Runnable
|
||||
|
||||
@@ -130,4 +134,45 @@ object LocalTrackerDiffUtil {
|
||||
val localText: CharSequence,
|
||||
val vcsText: CharSequence,
|
||||
val trackerVcsText: CharSequence)
|
||||
|
||||
|
||||
@JvmStatic
|
||||
fun installTrackerListener(viewer: DiffViewerBase, localRequest: LocalChangeListDiffRequest) {
|
||||
val trackerListener = MyTrackerListener(viewer)
|
||||
val lstmListener = MyLineStatusTrackerManagerListener(viewer, localRequest, trackerListener)
|
||||
|
||||
LineStatusTrackerManager.getInstanceImpl(localRequest.project).addTrackerListener(lstmListener, viewer)
|
||||
|
||||
val tracker = localRequest.lineStatusTracker as? PartialLocalLineStatusTracker
|
||||
if (tracker != null) tracker.addListener(trackerListener, viewer)
|
||||
}
|
||||
|
||||
private class MyTrackerListener(private val viewer: DiffViewerBase)
|
||||
: PartialLocalLineStatusTracker.ListenerAdapter() {
|
||||
|
||||
override fun onBecomingValid(tracker: PartialLocalLineStatusTracker) {
|
||||
viewer.scheduleRediff()
|
||||
}
|
||||
|
||||
override fun onChangeListMarkerChange(tracker: PartialLocalLineStatusTracker) {
|
||||
viewer.scheduleRediff()
|
||||
}
|
||||
|
||||
override fun onExcludedFromCommitChange(tracker: PartialLocalLineStatusTracker) {
|
||||
viewer.scheduleRediff()
|
||||
}
|
||||
}
|
||||
|
||||
private class MyLineStatusTrackerManagerListener(private val viewer: DiffViewerBase,
|
||||
private val localRequest: LocalChangeListDiffRequest,
|
||||
private val trackerListener: PartialLocalLineStatusTracker.Listener)
|
||||
: LineStatusTrackerManager.ListenerAdapter() {
|
||||
|
||||
override fun onTrackerAdded(tracker: LineStatusTracker<*>) {
|
||||
if (tracker is PartialLocalLineStatusTracker && tracker.virtualFile == localRequest.virtualFile) {
|
||||
tracker.addListener(trackerListener, viewer)
|
||||
viewer.scheduleRediff()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+7
-44
@@ -29,8 +29,10 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vcs.changes.ChangeListManager;
|
||||
import com.intellij.openapi.vcs.changes.LocalChangeList;
|
||||
import com.intellij.openapi.vcs.ex.*;
|
||||
import com.intellij.openapi.vcs.impl.LineStatusTrackerManager;
|
||||
import com.intellij.openapi.vcs.ex.ExclusionState;
|
||||
import com.intellij.openapi.vcs.ex.LocalRange;
|
||||
import com.intellij.openapi.vcs.ex.MoveChangesLineStatusAction;
|
||||
import com.intellij.openapi.vcs.ex.PartialLocalLineStatusTracker;
|
||||
import com.intellij.ui.InplaceButton;
|
||||
import com.intellij.ui.scale.JBUIScale;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
@@ -63,15 +65,9 @@ public class SimpleLocalChangeListDiffViewer extends SimpleDiffViewer {
|
||||
myChangelistId = localRequest.getChangelistId();
|
||||
myChangelistName = localRequest.getChangelistName();
|
||||
|
||||
MyTrackerListener trackerListener = new MyTrackerListener();
|
||||
MyLineStatusTrackerManagerListener lstmListener = new MyLineStatusTrackerManagerListener(trackerListener);
|
||||
myAllowExcludeChangesFromCommit = DiffUtil.isUserDataFlagSet(LocalChangeListDiffTool.ALLOW_EXCLUDE_FROM_COMMIT, context);
|
||||
|
||||
LineStatusTrackerManager.getInstanceImpl(getProject()).addTrackerListener(lstmListener, this);
|
||||
|
||||
PartialLocalLineStatusTracker tracker = getPartialTracker();
|
||||
if (tracker != null) tracker.addListener(trackerListener, this);
|
||||
|
||||
myAllowExcludeChangesFromCommit = Boolean.TRUE.equals(context.getUserData(LocalChangeListDiffTool.ALLOW_EXCLUDE_FROM_COMMIT));
|
||||
LocalTrackerDiffUtil.installTrackerListener(this, myLocalRequest);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -146,6 +142,7 @@ public class SimpleLocalChangeListDiffViewer extends SimpleDiffViewer {
|
||||
@NotNull
|
||||
@Override
|
||||
public Runnable done(boolean isContentsEqual,
|
||||
@NotNull CharSequence[] texts,
|
||||
@NotNull List<? extends LineFragment> fragments,
|
||||
@NotNull List<LocalTrackerDiffUtil.LineFragmentData> fragmentsData) {
|
||||
List<SimpleDiffChange> changes = new ArrayList<>();
|
||||
@@ -289,40 +286,6 @@ public class SimpleLocalChangeListDiffViewer extends SimpleDiffViewer {
|
||||
}
|
||||
|
||||
|
||||
private class MyTrackerListener extends PartialLocalLineStatusTracker.ListenerAdapter {
|
||||
@Override
|
||||
public void onBecomingValid(@NotNull PartialLocalLineStatusTracker tracker) {
|
||||
scheduleRediff();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChangeListMarkerChange(@NotNull PartialLocalLineStatusTracker tracker) {
|
||||
scheduleRediff();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onExcludedFromCommitChange(@NotNull PartialLocalLineStatusTracker tracker) {
|
||||
scheduleRediff();
|
||||
}
|
||||
}
|
||||
|
||||
private class MyLineStatusTrackerManagerListener extends LineStatusTrackerManager.ListenerAdapter {
|
||||
@NotNull private final PartialLocalLineStatusTracker.Listener myListener;
|
||||
|
||||
MyLineStatusTrackerManagerListener(@NotNull PartialLocalLineStatusTracker.Listener trackerListener) {
|
||||
myListener = trackerListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTrackerAdded(@NotNull LineStatusTracker<?> tracker) {
|
||||
if (tracker instanceof PartialLocalLineStatusTracker &&
|
||||
tracker.getVirtualFile().equals(myLocalRequest.getVirtualFile())) {
|
||||
((PartialLocalLineStatusTracker)tracker).addListener(myListener, SimpleLocalChangeListDiffViewer.this);
|
||||
scheduleRediff();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class MoveSelectedChangesToAnotherChangelistAction extends MySelectedChangesActionBase {
|
||||
MoveSelectedChangesToAnotherChangelistAction() {
|
||||
super(false);
|
||||
|
||||
+135
@@ -0,0 +1,135 @@
|
||||
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.openapi.vcs.changes.actions.diff.lst;
|
||||
|
||||
import com.intellij.diff.DiffContext;
|
||||
import com.intellij.diff.fragments.LineFragment;
|
||||
import com.intellij.diff.tools.fragmented.UnifiedDiffChange;
|
||||
import com.intellij.diff.tools.fragmented.UnifiedDiffViewer;
|
||||
import com.intellij.diff.tools.fragmented.UnifiedFragmentBuilder;
|
||||
import com.intellij.diff.util.DiffUtil;
|
||||
import com.intellij.openapi.application.ReadAction;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class UnifiedLocalChangeListDiffViewer extends UnifiedDiffViewer {
|
||||
@NotNull private final LocalChangeListDiffRequest myLocalRequest;
|
||||
|
||||
private final boolean myAllowExcludeChangesFromCommit;
|
||||
|
||||
public UnifiedLocalChangeListDiffViewer(@NotNull DiffContext context,
|
||||
@NotNull LocalChangeListDiffRequest localRequest) {
|
||||
super(context, localRequest.getRequest());
|
||||
myLocalRequest = localRequest;
|
||||
|
||||
myAllowExcludeChangesFromCommit = DiffUtil.isUserDataFlagSet(LocalChangeListDiffTool.ALLOW_EXCLUDE_FROM_COMMIT, context);
|
||||
|
||||
LocalTrackerDiffUtil.installTrackerListener(this, myLocalRequest);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Runnable superComputeDifferences(@NotNull ProgressIndicator indicator) {
|
||||
return super.computeDifferences(indicator);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected Runnable computeDifferences(@NotNull ProgressIndicator indicator) {
|
||||
Document document1 = getContent1().getDocument();
|
||||
Document document2 = getContent2().getDocument();
|
||||
|
||||
return LocalTrackerDiffUtil.computeDifferences(
|
||||
myLocalRequest.getLineStatusTracker(),
|
||||
document1,
|
||||
document2,
|
||||
myLocalRequest.getChangelistId(),
|
||||
myTextDiffProvider,
|
||||
indicator,
|
||||
new MyLocalTrackerDiffHandler(document1, document2, indicator));
|
||||
}
|
||||
|
||||
private class MyLocalTrackerDiffHandler implements LocalTrackerDiffUtil.LocalTrackerDiffHandler {
|
||||
@NotNull private final Document myDocument1;
|
||||
@NotNull private final Document myDocument2;
|
||||
@NotNull private final ProgressIndicator myIndicator;
|
||||
|
||||
private MyLocalTrackerDiffHandler(@NotNull Document document1,
|
||||
@NotNull Document document2,
|
||||
@NotNull ProgressIndicator indicator) {
|
||||
myDocument1 = document1;
|
||||
myDocument2 = document2;
|
||||
myIndicator = indicator;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Runnable done(boolean isContentsEqual,
|
||||
@NotNull CharSequence[] texts,
|
||||
@NotNull List<? extends LineFragment> fragments,
|
||||
@NotNull List<LocalTrackerDiffUtil.LineFragmentData> fragmentsData) {
|
||||
UnifiedFragmentBuilder builder = ReadAction.compute(() -> {
|
||||
myIndicator.checkCanceled();
|
||||
return new MyUnifiedFragmentBuilder(fragments, fragmentsData, myDocument1, myDocument2).exec();
|
||||
});
|
||||
|
||||
return apply(builder, texts, myIndicator);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Runnable retryLater() {
|
||||
scheduleRediff();
|
||||
throw new ProcessCanceledException();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Runnable fallback() {
|
||||
return superComputeDifferences(myIndicator);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Runnable fallbackWithProgress() {
|
||||
Runnable callback = superComputeDifferences(myIndicator);
|
||||
return () -> {
|
||||
callback.run();
|
||||
getStatusPanel().setBusy(true);
|
||||
};
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Runnable error() {
|
||||
return applyErrorNotification();
|
||||
}
|
||||
}
|
||||
|
||||
private class MyUnifiedFragmentBuilder extends UnifiedFragmentBuilder {
|
||||
@NotNull private final List<LocalTrackerDiffUtil.LineFragmentData> myFragmentsData;
|
||||
|
||||
MyUnifiedFragmentBuilder(@NotNull List<? extends LineFragment> fragments,
|
||||
@NotNull List<LocalTrackerDiffUtil.LineFragmentData> fragmentsData,
|
||||
@NotNull Document document1,
|
||||
@NotNull Document document2) {
|
||||
super(fragments, document1, document2, myMasterSide);
|
||||
myFragmentsData = fragmentsData;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected UnifiedDiffChange createDiffChange(int blockStart,
|
||||
int insertedStart,
|
||||
int blockEnd,
|
||||
int fragmentIndex) {
|
||||
LineFragment fragment = myFragments.get(fragmentIndex);
|
||||
LocalTrackerDiffUtil.LineFragmentData data = myFragmentsData.get(fragmentIndex);
|
||||
boolean isSkipped = data.isSkipped();
|
||||
boolean isExcluded = data.isExcluded(myAllowExcludeChangesFromCommit);
|
||||
return new UnifiedDiffChange(blockStart, insertedStart, blockEnd, fragment, isExcluded, isSkipped);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user