Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,8 @@ private CompareMessages() {
public static String UnifiedDiff_openTwoWayCompare_tooltip;
public static String UnifiedDiff_cannotEditFile_title;
public static String UnifiedDiff_cannotEditFile_message;
public static String UnifiedDiff_expandUnchangedLine;
public static String UnifiedDiff_expandUnchangedLines;

static {
NLS.initializeMessages(BUNDLE_NAME, CompareMessages.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,3 +163,5 @@ UnifiedDiff_revert=Revert
UnifiedDiff_openTwoWayCompare_tooltip=Open in 2-way Compare Editor
UnifiedDiff_cannotEditFile_title=Cannot edit file
UnifiedDiff_cannotEditFile_message=Cannot edit file {0}: {1}
UnifiedDiff_expandUnchangedLine=Expand 1 unchanged line
UnifiedDiff_expandUnchangedLines=Expand {0} unchanged lines
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,10 @@ Collection<T> getAll() {

public static final int NO_DIFFERENCE = 10000;

// Number of unchanged context lines kept around each change when the unified
// diff collapses unchanged regions.
private static final int UNIFIED_DIFF_CONTEXT_LINES = 3;

/**
* The plugin singleton.
*/
Expand Down Expand Up @@ -627,6 +631,7 @@ private boolean openUnifiedDiffInEditor(final CompareEditorInput input, final IW
: null)
.ignoreWhiteSpace(Utilities.getBoolean(input.getCompareConfiguration(),
CompareConfiguration.IGNORE_WHITESPACE, false))
.foldUnchanged(UNIFIED_DIFF_CONTEXT_LINES)
.open();
return status.isOK();
}
Expand Down Expand Up @@ -654,6 +659,7 @@ private boolean openUnifiedDiffInEditor(final CompareEditorInput input, final IW
: null)
.ignoreWhiteSpace(Utilities.getBoolean(input.getCompareConfiguration(),
CompareConfiguration.IGNORE_WHITESPACE, false))
.foldUnchanged(UNIFIED_DIFF_CONTEXT_LINES)
.open();
return status.isOK();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ public static final class Builder {
private List<Action> additionalActions;
private TokenComparatorFactory tokenComparatorFactory;
private IgnoreWhitespaceContributorFactory ignoreWhitespaceContributorFactory;
private int foldContextLines = -1;

private Builder(ITextEditor editor, String source, UnifiedDiffMode mode) {
this.editor = Objects.requireNonNull(editor, "Editor cannot be null"); //$NON-NLS-1$
Expand Down Expand Up @@ -89,9 +90,19 @@ public Builder ignoreWhiteSpace(boolean value) {
return this;
}

/**
* Collapses unchanged regions between diffs, keeping the given number of
* context lines (at least one) around each change. A negative value disables
* folding.
*/
public Builder foldUnchanged(int contextLines) {
this.foldContextLines = contextLines;
return this;
}

public IStatus open() {
return UnifiedDiffManager.open(editor, source, mode, additionalActions, tokenComparatorFactory,
ignoreWhitespaceContributorFactory, ignoreWhiteSpace);
ignoreWhitespaceContributorFactory, ignoreWhiteSpace, foldContextLines);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;

import org.eclipse.compare.internal.CompareMessages;
import org.eclipse.compare.unifieddiff.UnifiedDiffMode;
import org.eclipse.compare.unifieddiff.internal.UnifiedDiffManager.UnifiedDiff;
import org.eclipse.core.runtime.IProgressMonitor;
Expand All @@ -49,6 +50,7 @@
import org.eclipse.jface.text.source.SourceViewer;
import org.eclipse.jface.text.source.inlined.LineFooterAnnotation;
import org.eclipse.jface.text.source.inlined.LineHeaderAnnotation;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.custom.StyledText;
Expand Down Expand Up @@ -156,6 +158,9 @@ public CompletableFuture<List<? extends ICodeMining>> provideCodeMinings(ITextVi
}
}
if (existingMinings.size() > 0) {
// the expander minings are recreated instead of reused so that they
// reflect the current expansion state of the folds
createFoldRegionCodeMinings(viewer, existingMinings);
return CompletableFuture.completedFuture(existingMinings);
}
}
Expand All @@ -164,9 +169,13 @@ public CompletableFuture<List<? extends ICodeMining>> provideCodeMinings(ITextVi
// take an immutable snapshot so the async iteration cannot observe
// concurrent modifications when accept/hide actions mutate the live list
List<UnifiedDiff> diffsSnapshot = List.copyOf(diffs);
// created on the calling thread because it reads the projection annotation model
List<ICodeMining> foldMinings = new ArrayList<>();
createFoldRegionCodeMinings(viewer, foldMinings);
return CompletableFuture.supplyAsync(() -> {
List<ICodeMining> minings = new ArrayList<>();
createLineHeaderCodeMinings(diffsSnapshot, minings, viewer, tabWidth);
minings.addAll(foldMinings);
return minings;
});
}
Expand Down Expand Up @@ -274,6 +283,53 @@ private void createLineHeaderCodeMinings(List<UnifiedDiff> diffs, List<ICodeMini
}
}

/**
* Creates one clickable expander mining per collapsed unchanged-region fold,
* shown as e.g. "Expand 42 unchanged lines" above the fold's caption line.
*/
private void createFoldRegionCodeMinings(ITextViewer viewer, List<ICodeMining> minings) {
IDocument doc = viewer.getDocument();
if (doc == null) {
return;
}
Map<Annotation, Position> folds = UnifiedDiffManager.getCollapsedFoldRegions(viewer);
for (Map.Entry<Annotation, Position> fold : folds.entrySet()) {
Position position = fold.getValue();
try {
int firstLine = doc.getLineOfOffset(position.getOffset());
int lastLine = position.getLength() > 0
? doc.getLineOfOffset(position.getOffset() + position.getLength() - 1)
: firstLine;
// the first line of the region stays visible as the fold's caption
int hiddenLines = lastLine - firstLine;
if (hiddenLines <= 0) {
continue;
}
minings.add(new FoldedRegionCodeMining(new Position(position.getOffset(), 1), this, viewer,
fold.getKey(), hiddenLines));
} catch (BadLocationException e) {
error(e);
}
}
}

static class FoldedRegionCodeMining extends LineHeaderCodeMining {

private final String expandLabel;

public FoldedRegionCodeMining(Position position, ICodeMiningProvider provider, ITextViewer viewer,
Annotation foldAnnotation, int hiddenLines) throws BadLocationException {
super(position, provider, e -> UnifiedDiffManager.expandFoldRegion(viewer, foldAnnotation));
this.expandLabel = hiddenLines == 1 ? CompareMessages.UnifiedDiff_expandUnchangedLine
: NLS.bind(CompareMessages.UnifiedDiff_expandUnchangedLines, Integer.valueOf(hiddenLines));
}

@Override
public String getLabel() {
return this.expandLabel;
}
}

static class UnifiedDiffFooterCodeMining extends DocumentFooterCodeMining {
private final String unifiedDiffLabel;
private final Color deletionBackgroundColor;
Expand Down
Loading
Loading