Skip to content
Open
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 @@ -844,7 +844,7 @@ private Action createOpenTwoWayCompareAction(final CompareEditorInput input, fin
Action openTwoWayCompare = new Action(null, image) {
@Override
public void run() {
new HideAllDiffsRunnable(textEditor).run();
new HideAllDiffsRunnable(textEditor, false).run();
if (input.canRunAsJob()) {
openEditorInBackground(input, page, editor, activate);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ public static final class Builder {
private char editorContributor = MergeViewerContentProvider.LEFT_CONTRIBUTOR;
private char sourceContributor = MergeViewerContentProvider.RIGHT_CONTRIBUTOR;
private int foldContextLines = -1;
private UnifiedDiffEventListener eventListener;
private final Map<ToolbarAction, String> toolbarActionTexts = new EnumMap<>(ToolbarAction.class);
private final Map<ToolbarAction, ImageDescriptor> toolbarActionImages = new EnumMap<>(ToolbarAction.class);

Expand Down Expand Up @@ -176,6 +177,18 @@ public Builder toolbarActionImage(ToolbarAction action, ImageDescriptor image) {
return this;
}

/**
* Sets the listener notified when a diff hunk is resolved. The listener
* is invoked on the UI thread once for each hunk that the user resolves.
*
* @param listener the listener, or <code>null</code> to receive no events
* @return this builder
*/
public Builder eventListener(UnifiedDiffEventListener listener) {
this.eventListener = listener;
return this;
}

/**
* Collapses unchanged regions between diffs, keeping the given number of
* context lines (at least one) around each change. A negative value disables
Expand All @@ -194,7 +207,7 @@ public IStatus open() {
return UnifiedDiffManager.open(editor, source, mode, additionalActions, tokenComparatorFactory,
ignoreWhitespaceContributorFactory, compareFilters, editorContributor, sourceContributor,
ignoreWhiteSpace, foldContextLines,
new ToolbarActionPresentations(toolbarActionTexts, toolbarActionImages));
new ToolbarActionPresentations(toolbarActionTexts, toolbarActionImages), eventListener);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*******************************************************************************
* Copyright (c) 2026 SAP
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* SAP - initial implementation
*******************************************************************************/
package org.eclipse.compare.unifieddiff;

import java.util.Objects;

/**
* Describes a unified-diff hunk that was resolved by the user.
* <p>
* The range and line identify the hunk in the editor document at the time it is
* resolved. The editor and compared-source code are the unmodified snippets
* used when the unified diff was created.
*/
public final class UnifiedDiffEvent {

/** How the hunk was resolved. */
public enum Resolution {
/** The compared/new hunk was selected. */
ACCEPTED,
/** The original/current hunk was retained. */
REJECTED,
/** The user manually removed or replaced the complete displayed hunk. */
MANUALLY_DELETED
}

private final Resolution resolution;
private final int line;
private final int offset;
private final int length;
private final String editorCode;
private final String comparedSourceCode;

public UnifiedDiffEvent(Resolution resolution, int line, int offset, int length, String editorCode,
String comparedSourceCode) {
this.resolution = Objects.requireNonNull(resolution);
this.line = line;
this.offset = offset;
this.length = length;
this.editorCode = Objects.requireNonNull(editorCode);
this.comparedSourceCode = Objects.requireNonNull(comparedSourceCode);
}

/** Returns whether the hunk was accepted, rejected, or manually deleted. */
public Resolution getResolution() {
return resolution;
}

/** Returns the one-based line at which the hunk starts. */
public int getLine() {
return line;
}

/** Returns the offset of the hunk in the editor document. */
public int getOffset() {
return offset;
}

/** Returns the length of the hunk in the editor document. */
public int getLength() {
return length;
}

/** Returns the code in the editor document when the diff was created. */
public String getEditorCode() {
return editorCode;
}

/** Returns the code in the source compared with the editor document. */
public String getComparedSourceCode() {
return comparedSourceCode;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*******************************************************************************
* Copyright (c) 2026 SAP
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* SAP - initial implementation
*******************************************************************************/
package org.eclipse.compare.unifieddiff;

/**
* Receives a notification when a unified-diff hunk is resolved.
*/
@FunctionalInterface
public interface UnifiedDiffEventListener {

/**
* Invoked on the UI thread when a unified-diff hunk is resolved.
*
* @param event the resolved hunk
*/
void unifiedDiffResolved(UnifiedDiffEvent event);
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

import org.eclipse.compare.internal.CompareMessages;
import org.eclipse.compare.internal.CompareUIPlugin;
import org.eclipse.compare.unifieddiff.UnifiedDiffEvent;
import org.eclipse.compare.unifieddiff.internal.UnifiedDiffManager.UnifiedDiff;
import org.eclipse.compare.unifieddiff.internal.UnifiedDiffManager.UnifiedDiffAnnotation;
import org.eclipse.jface.resource.ImageDescriptor;
Expand Down Expand Up @@ -69,6 +70,7 @@ public void run() {
}
List<Position> positions = new ArrayList<>();
List<String> replaceStrings = new ArrayList<>();
List<UnifiedDiffManager.ResolvedDiff> resolvedDiffs = new ArrayList<>();
for (UnifiedDiff diff : diffs1) {
List<Annotation> annos = getAllAnnotationsForUnifiedDiff(model, diff);
int unifiedDiffAdditionCount = 0;
Expand All @@ -79,6 +81,7 @@ public void run() {
throw new IllegalStateException("Multiple UnifiedDiffAnnotation for one UnifiedDiff found"); //$NON-NLS-1$
}
Position pos = model.getPosition(lanno);
resolvedDiffs.add(UnifiedDiffManager.prepareEvent(diff, UnifiedDiffEvent.Resolution.ACCEPTED, pos));
positions.add(pos);
replaceStrings.add(diff.rightStr);
}
Expand All @@ -96,15 +99,19 @@ public void run() {
// we have to insert with delay because otherwise the line header code minings
// cannot be deleted
runAfterRepaintFinished(tw, () -> {
List<UnifiedDiffManager.ResolvedDiff> completed = new ArrayList<>();
for (int i = positions.size() - 1; i >= 0; i--) {
Position pos = positions.get(i);
String replaceStr = replaceStrings.get(i);
try {
tv.getDocument().replace(pos.offset, pos.length, replaceStr);
completed.add(resolvedDiffs.get(i));
} catch (BadLocationException e) {
UnifiedDiffManager.cancelEvent(resolvedDiffs.get(i));
UnifiedDiffManager.error(e);
}
}
UnifiedDiffManager.fireEvents(completed);
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,13 @@
import static org.eclipse.compare.unifieddiff.internal.UnifiedDiffManager.getAllAnnotationsForUnifiedDiff;
import static org.eclipse.compare.unifieddiff.internal.UnifiedDiffManager.removeAnnotationModelListener;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.compare.internal.CompareMessages;
import org.eclipse.compare.internal.CompareUIPlugin;
import org.eclipse.compare.unifieddiff.UnifiedDiffEvent;
import org.eclipse.compare.unifieddiff.UnifiedDiffMode;
import org.eclipse.compare.unifieddiff.internal.UnifiedDiffManager.UnifiedDiff;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.text.ITextViewer;
Expand All @@ -36,15 +39,26 @@ public class HideAllDiffsRunnable implements Runnable {

private IAnnotationModel model;
private ITextViewer tv;
private final boolean notifyEvents;

public HideAllDiffsRunnable(ITextViewer tv, IAnnotationModel model) {
this(tv, model, true);
}

public HideAllDiffsRunnable(ITextViewer tv, IAnnotationModel model, boolean notifyEvents) {
this.tv = tv;
this.model = model;
this.notifyEvents = notifyEvents;
}

public HideAllDiffsRunnable(ITextEditor textEditor) {
this(textEditor, true);
}

public HideAllDiffsRunnable(ITextEditor textEditor, boolean notifyEvents) {
this.tv = textEditor.getAdapter(ITextViewer.class);
this.model = UnifiedDiffManager.annotationModelOf(textEditor);
this.notifyEvents = notifyEvents;
}

public String getLabel() {
Expand All @@ -69,9 +83,15 @@ public void run() {
if (diffs1 == null) {
return;
}
List<UnifiedDiffManager.ResolvedDiff> resolvedDiffs = new ArrayList<>();
for (UnifiedDiff diff : diffs1) {
List<Annotation> annos = getAllAnnotationsForUnifiedDiff(model, diff);
for (var lanno : annos) {
if (notifyEvents && lanno instanceof UnifiedDiffManager.UnifiedDiffAnnotation) {
UnifiedDiffEvent.Resolution resolution = diff.mode.equals(UnifiedDiffMode.REPLACE_MODE)
? UnifiedDiffEvent.Resolution.ACCEPTED : UnifiedDiffEvent.Resolution.REJECTED;
resolvedDiffs.add(UnifiedDiffManager.prepareEvent(diff, resolution, model.getPosition(lanno)));
}
// markDeleted must be called before removing it from the model so that the vertical indent of line header mining is properly reset
lanno.markDeleted(true);
model.removeAnnotation(lanno);
Expand All @@ -82,5 +102,6 @@ public void run() {
ext.updateCodeMinings();
}
disposeUnifiedDiff(tv, model, tv.getTextWidget());
UnifiedDiffManager.fireEvents(resolvedDiffs);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@
import static org.eclipse.compare.unifieddiff.internal.UnifiedDiffManager.get;
import static org.eclipse.compare.unifieddiff.internal.UnifiedDiffManager.getAllAnnotationsForUnifiedDiff;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.compare.internal.CompareMessages;
import org.eclipse.compare.unifieddiff.UnifiedDiffEvent;
import org.eclipse.compare.unifieddiff.internal.UnifiedDiffManager.UnifiedDiff;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.source.Annotation;
Expand All @@ -45,9 +47,14 @@ public void run() {
if (diffs1 == null) {
return;
}
List<UnifiedDiffManager.ResolvedDiff> resolvedDiffs = new ArrayList<>();
for (UnifiedDiff diff : diffs1) {
List<Annotation> annos = getAllAnnotationsForUnifiedDiff(model, diff);
for (var lanno : annos) {
if (lanno instanceof UnifiedDiffManager.UnifiedDiffAnnotation) {
resolvedDiffs.add(UnifiedDiffManager.prepareEvent(diff, UnifiedDiffEvent.Resolution.ACCEPTED,
model.getPosition(lanno)));
}
model.removeAnnotation(lanno);
}
}
Expand All @@ -56,5 +63,6 @@ public void run() {
ext.updateCodeMinings();
}
disposeUnifiedDiff(tv, model, tv.getTextWidget());
UnifiedDiffManager.fireEvents(resolvedDiffs);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import java.util.List;

import org.eclipse.compare.internal.CompareMessages;
import org.eclipse.compare.unifieddiff.UnifiedDiffEvent;
import org.eclipse.compare.unifieddiff.internal.UnifiedDiffManager.UnifiedDiff;
import org.eclipse.compare.unifieddiff.internal.UnifiedDiffManager.UnifiedDiffAnnotation;
import org.eclipse.jface.text.BadLocationException;
Expand Down Expand Up @@ -57,6 +58,7 @@ public void run() {
}
List<Position> positions = new ArrayList<>();
List<String> replaceStrings = new ArrayList<>();
List<UnifiedDiffManager.ResolvedDiff> resolvedDiffs = new ArrayList<>();
for (UnifiedDiff diff : diffs1) {
List<Annotation> annos = getAllAnnotationsForUnifiedDiff(model, diff);
int unifiedDiffAdditionCount = 0;
Expand All @@ -67,6 +69,7 @@ public void run() {
throw new IllegalStateException("Multiple UnifiedDiffAnnotation for one UnifiedDiff found"); //$NON-NLS-1$
}
Position pos = model.getPosition(lanno);
resolvedDiffs.add(UnifiedDiffManager.prepareEvent(diff, UnifiedDiffEvent.Resolution.REJECTED, pos));
positions.add(pos);
replaceStrings.add(diff.leftStr);
}
Expand All @@ -84,15 +87,19 @@ public void run() {
// we have to insert with delay because otherwise the line header code minings
// cannot be deleted
runAfterRepaintFinished(tw, () -> {
List<UnifiedDiffManager.ResolvedDiff> completed = new ArrayList<>();
for (int i = positions.size() - 1; i >= 0; i--) {
Position pos = positions.get(i);
String replaceStr = replaceStrings.get(i);
try {
tv.getDocument().replace(pos.offset, pos.length, replaceStr);
completed.add(resolvedDiffs.get(i));
} catch (BadLocationException e) {
UnifiedDiffManager.cancelEvent(resolvedDiffs.get(i));
error(e);
}
}
UnifiedDiffManager.fireEvents(completed);
});
}
}
Loading
Loading