Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Valenta2007-09-14 15:17:55 +0000
committerMichael Valenta2007-09-14 15:17:55 +0000
commit32ea1739b098b6fa956bf65a903cf24030bfd6bf (patch)
treec0e021314c3eaf39a873bd6225dad99093dd6ea0
parent0a0d6b97aebeb53b69784ccd5a593cf7a0c2fcd7 (diff)
downloadeclipse.platform.team-branch_20070914_ExtractDocumentDiff.tar.gz
eclipse.platform.team-branch_20070914_ExtractDocumentDiff.tar.xz
eclipse.platform.team-branch_20070914_ExtractDocumentDiff.zip
Compare Exploratory Workbranch_20070914_ExtractDocumentDiff
-rw-r--r--bundles/org.eclipse.compare/compare/org/eclipse/compare/contentmergeviewer/TextMergeViewer.java1610
-rw-r--r--bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/merge/DocumentMerger.java1338
-rw-r--r--bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/contentmergeviewer/TextMergeViewer.java1610
-rw-r--r--bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/merge/DocumentMerger.java1338
4 files changed, 3296 insertions, 2600 deletions
diff --git a/bundles/org.eclipse.compare/compare/org/eclipse/compare/contentmergeviewer/TextMergeViewer.java b/bundles/org.eclipse.compare/compare/org/eclipse/compare/contentmergeviewer/TextMergeViewer.java
index 9cb18d1f9..659dee757 100644
--- a/bundles/org.eclipse.compare/compare/org/eclipse/compare/contentmergeviewer/TextMergeViewer.java
+++ b/bundles/org.eclipse.compare/compare/org/eclipse/compare/contentmergeviewer/TextMergeViewer.java
@@ -19,12 +19,14 @@ package org.eclipse.compare.contentmergeviewer;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.util.*;
-import java.util.List;
import org.eclipse.compare.*;
import org.eclipse.compare.internal.*;
+import org.eclipse.compare.internal.merge.DocumentMerger;
+import org.eclipse.compare.internal.merge.DocumentMerger.Diff;
+import org.eclipse.compare.internal.merge.DocumentMerger.IDocumentMergerInput;
import org.eclipse.compare.patch.IHunk;
-import org.eclipse.compare.rangedifferencer.*;
+import org.eclipse.compare.rangedifferencer.RangeDifference;
import org.eclipse.compare.structuremergeviewer.*;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.*;
@@ -32,7 +34,6 @@ import org.eclipse.core.runtime.Assert;
import org.eclipse.jface.action.*;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.MessageDialog;
-import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.resource.ColorRegistry;
import org.eclipse.jface.resource.JFaceResources;
@@ -54,7 +55,6 @@ import org.eclipse.swt.graphics.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.ui.*;
import org.eclipse.ui.actions.ActionFactory;
-import org.eclipse.ui.progress.IProgressService;
import org.eclipse.ui.texteditor.*;
import com.ibm.icu.text.MessageFormat;
@@ -161,13 +161,9 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
private static final int BIRDS_EYE_VIEW_INSET= 2;
/** */
private static final int RESOLVE_SIZE= 5;
- /** if true copying conflicts from one side to other concatenates both sides */
- private static final boolean APPEND_CONFLICT= true;
/** line width of change borders */
private static final int LW= 1;
- /** Selects between smartTokenDiff and mergingTokenDiff */
- private static final boolean USE_MERGING_TOKEN_DIFF= false;
// determines whether a change between left and right is considered incoming or outgoing
private boolean fLeftIsLocal;
@@ -202,13 +198,6 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
private IPreferenceStore fPreferenceStore;
private IPropertyChangeListener fPreferenceChangeListener;
- /** All diffs for calculating scrolling position (includes line ranges without changes) */
- private ArrayList fAllDiffs;
- /** Subset of above: just real differences. */
- private ArrayList fChangeDiffs;
- /** The current diff */
- private Diff fCurrentDiff;
-
private HashMap fNewAncestorRanges= new HashMap();
private HashMap fNewLeftRanges= new HashMap();
private HashMap fNewRightRanges= new HashMap();
@@ -291,6 +280,9 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
private TextEditorPropertyAction toggleLineNumbersAction;
private IFindReplaceTarget fFindReplaceTarget;
private ChangePropertyAction fIgnoreWhitespace;
+ private DocumentMerger fMerger;
+ /** The current diff */
+ private Diff fCurrentDiff;
private final class InternalOutlineViewerCreator extends OutlineViewerCreator implements ISelectionChangedListener {
public Viewer findStructureViewer(Viewer oldViewer,
@@ -340,16 +332,16 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
}
private Diff findDiff(Position p, boolean left) {
- for (Iterator iterator = fAllDiffs.iterator(); iterator.hasNext();) {
+ for (Iterator iterator = fMerger.rangesIterator(); iterator.hasNext();) {
Diff diff = (Diff) iterator.next();
Position diffPos;
if (left) {
- diffPos = diff.fLeftPos;
+ diffPos = diff.getPosition(LEFT_CONTRIBUTOR);
} else {
- diffPos = diff.fRightPos;
+ diffPos = diff.getPosition(RIGHT_CONTRIBUTOR);
}
// If the element falls within a diff, highlight that diff
- if (diffPos.offset + diffPos.length >= p.offset && diff.fDirection != RangeDifference.NOCHANGE)
+ if (diffPos.offset + diffPos.length >= p.offset && diff.getKind() != RangeDifference.NOCHANGE)
return diff;
// Otherwise, highlight the first diff after the elements position
if (diffPos.offset >= p.offset)
@@ -1028,276 +1020,36 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
}
}
- /*
- * A Diff represents synchronized character ranges in two or three Documents.
- * The MergeTextViewer uses Diffs to find differences in line and token ranges.
- */
- /* package */ class Diff {
- /** character range in ancestor document */
- Position fAncestorPos;
- /** character range in left document */
- Position fLeftPos;
- /** character range in right document */
- Position fRightPos;
- /** if this is a TokenDiff fParent points to the enclosing LineDiff */
- Diff fParent;
- /** if Diff has been resolved */
- boolean fResolved;
- int fDirection;
- boolean fIsToken= false;
- /** child token diffs */
- ArrayList fDiffs;
- boolean fIsWhitespace= false;
+ private class ChangeHighlighter implements ITextPresentationListener {
- /*
- * Create Diff from two ranges and an optional parent diff.
- */
- Diff(Diff parent, int dir, IDocument ancestorDoc, Position aRange, int ancestorStart, int ancestorEnd,
- IDocument leftDoc, Position lRange, int leftStart, int leftEnd,
- IDocument rightDoc, Position rRange, int rightStart, int rightEnd) {
- fParent= parent != null ? parent : this;
- fDirection= dir;
-
- fLeftPos= createPosition(leftDoc, lRange, leftStart, leftEnd);
- fRightPos= createPosition(rightDoc, rRange, rightStart, rightEnd);
- if (ancestorDoc != null)
- fAncestorPos= createPosition(ancestorDoc, aRange, ancestorStart, ancestorEnd);
- }
-
- Position getPosition(char type) {
- switch (type) {
- case ANCESTOR_CONTRIBUTOR:
- return fAncestorPos;
- case LEFT_CONTRIBUTOR:
- return fLeftPos;
- case RIGHT_CONTRIBUTOR:
- return fRightPos;
- }
- return null;
- }
-
- boolean isInRange(char type, int pos) {
- Position p= getPosition(type);
- return (pos >= p.offset) && (pos < (p.offset+p.length));
- }
-
- String changeType() {
- boolean leftEmpty= fLeftPos.length == 0;
- boolean rightEmpty= fRightPos.length == 0;
-
- if (fDirection == RangeDifference.LEFT) {
- if (!leftEmpty && rightEmpty)
- return CompareMessages.TextMergeViewer_changeType_addition;
- if (leftEmpty && !rightEmpty)
- return CompareMessages.TextMergeViewer_changeType_deletion;
- } else {
- if (leftEmpty && !rightEmpty)
- return CompareMessages.TextMergeViewer_changeType_addition;
- if (!leftEmpty && rightEmpty)
- return CompareMessages.TextMergeViewer_changeType_deletion;
- }
- return CompareMessages.TextMergeViewer_changeType_change;
- }
-
- Image getImage() {
- int code= Differencer.CHANGE;
- switch (fDirection) {
- case RangeDifference.RIGHT:
- code+= Differencer.LEFT;
- break;
- case RangeDifference.LEFT:
- code+= Differencer.RIGHT;
- break;
- case RangeDifference.ANCESTOR:
- case RangeDifference.CONFLICT:
- code+= Differencer.CONFLICTING;
- break;
- }
- if (code != 0)
- return getCompareConfiguration().getImage(code);
- return null;
- }
-
- Position createPosition(IDocument doc, Position range, int start, int end) {
- try {
- int l= end-start;
- if (range != null) {
- int dl= range.length;
- if (l > dl)
- l= dl;
- } else {
- int dl= doc.getLength();
- if (start+l > dl)
- l= dl-start;
- }
-
- Position p= null;
- try {
- p= new Position(start, l);
- } catch (RuntimeException ex) {
- p= new Position(0, 0);
- }
-
- try {
- doc.addPosition(DIFF_RANGE_CATEGORY, p);
- } catch (BadPositionCategoryException ex) {
- // silently ignored
- }
- return p;
- } catch (BadLocationException ee) {
- // silently ignored
- }
- return null;
- }
+ private final MergeSourceViewer viewer;
- void add(Diff d) {
- if (fDiffs == null)
- fDiffs= new ArrayList();
- fDiffs.add(d);
- }
-
- boolean isDeleted() {
- if (fAncestorPos != null && fAncestorPos.isDeleted())
- return true;
- return fLeftPos.isDeleted() || fRightPos.isDeleted();
- }
-
- void setResolved(boolean r) {
- fResolved= r;
- if (r)
- fDiffs= null;
+ public ChangeHighlighter(MergeSourceViewer viewer) {
+ this.viewer = viewer;
}
- boolean isResolved() {
- if (!fResolved && fDiffs != null) {
- Iterator e= fDiffs.iterator();
- while (e.hasNext()) {
- Diff d= (Diff) e.next();
- if (!d.isResolved())
- return false;
- }
- return true;
- }
- return fResolved;
- }
-
-// private boolean isIncoming() {
-// switch (fDirection) {
-// case RangeDifference.RIGHT:
-// if (fLeftIsLocal)
-// return true;
-// break;
-// case RangeDifference.LEFT:
-// if (!fLeftIsLocal)
-// return true;
-// break;
-// }
-// return false;
-// }
-
- private boolean isIncomingOrConflicting() {
- switch (fDirection) {
- case RangeDifference.RIGHT:
- if (fLeftIsLocal)
- return true;
- break;
- case RangeDifference.LEFT:
- if (!fLeftIsLocal)
- return true;
- break;
- case RangeDifference.CONFLICT:
- return true;
- }
- return false;
- }
-
-// private boolean isUnresolvedIncoming() {
-// if (fResolved)
-// return false;
-// return isIncoming();
-// }
-
- private boolean isUnresolvedIncomingOrConflicting() {
- if (fResolved)
- return false;
- return isIncomingOrConflicting();
- }
-
- Position getPosition(MergeSourceViewer w) {
- if (w == fLeft)
- return fLeftPos;
- if (w == fRight)
- return fRightPos;
- if (w == fAncestor)
- return fAncestorPos;
- return null;
- }
-
- /*
- * Returns true if given character range overlaps with this Diff.
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.text.ITextPresentationListener#applyTextPresentation(org.eclipse.jface.text.TextPresentation)
*/
- boolean overlaps(MergeSourceViewer w, int start, int end) {
- Position h= getPosition(w);
- if (h != null) {
- int ds= h.getOffset();
- int de= ds + h.getLength();
- if ((start < de) && (end >= ds))
- return true;
- }
- return false;
- }
-
- int getMaxDiffHeight() {
- Point region= new Point(0, 0);
- int h= fLeft.getLineRange(fLeftPos, region).y;
- if (isThreeWay())
- h= Math.max(h, fAncestor.getLineRange(fAncestorPos, region).y);
- return Math.max(h, fRight.getLineRange(fRightPos, region).y);
- }
-
- int getAncestorHeight() {
- Point region= new Point(0, 0);
- return fAncestor.getLineRange(fAncestorPos, region).y;
- }
-
- int getLeftHeight() {
- Point region= new Point(0, 0);
- return fLeft.getLineRange(fLeftPos, region).y;
- }
-
- int getRightHeight() {
- Point region= new Point(0, 0);
- return fRight.getLineRange(fRightPos, region).y;
- }
-
- public Diff[] getChangeDiffs(MergeSourceViewer viewer, IRegion region) {
- if (fDiffs != null && intersectsRegion(viewer, region)) {
- List result = new ArrayList();
- for (Iterator iterator = fDiffs.iterator(); iterator.hasNext();) {
- Diff diff = (Diff) iterator.next();
- if (diff.intersectsRegion(viewer, region)) {
- result.add(diff);
- }
- }
- return (Diff[]) result.toArray(new Diff[result.size()]);
+ public void applyTextPresentation(TextPresentation textPresentation) {
+ if (!fHighlightTokenChanges)
+ return;
+ IRegion region= textPresentation.getExtent();
+ Diff[] changeDiffs = fMerger.getChangeDiffs(getLeg(viewer), region);
+ for (int i = 0; i < changeDiffs.length; i++) {
+ Diff diff = changeDiffs[i];
+ StyleRange range = getStyleRange(diff, region);
+ if (range != null)
+ textPresentation.mergeStyleRange(range);
}
- return new Diff[0];
- }
-
- private boolean intersectsRegion(MergeSourceViewer viewer,
- IRegion region) {
- Position p = getPosition(viewer);
- if (p != null)
- return p.overlapsWith(region.getOffset(), region.getLength());
- return false;
}
- public StyleRange getStyleRange(MergeSourceViewer viewer, IRegion region) {
+ private StyleRange getStyleRange(Diff diff, IRegion region) {
//Color cText = getColor(null, getTextColor());
- Color cTextFill = getColor(null, getTextFillColor());
+ Color cTextFill = getColor(null, getTextFillColor(diff));
if (cTextFill == null)
return null;
- Position p = getPosition(viewer);
+ Position p = diff.getPosition(getLeg(viewer));
int start = p.getOffset();
int length = p.getLength();
// Don't start before the region
@@ -1316,9 +1068,9 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
return new StyleRange(start, length, null, cTextFill);
}
- private RGB getTextFillColor() {
+ private RGB getTextFillColor(Diff diff) {
if (isThreeWay() && !isIgnoreAncestor()) {
- switch (fDirection) {
+ switch (diff.getKind()) {
case RangeDifference.RIGHT:
if (fLeftIsLocal)
return INCOMING_TEXT_FILL;
@@ -1336,54 +1088,6 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
}
return OUTGOING_TEXT_FILL;
}
-
- public boolean hasChildren() {
- return fDiffs != null && !fDiffs.isEmpty();
- }
- }
-
- private class ChangeHighlighter implements ITextPresentationListener {
-
- private final MergeSourceViewer viewer;
-
- public ChangeHighlighter(MergeSourceViewer viewer) {
- this.viewer = viewer;
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.jface.text.ITextPresentationListener#applyTextPresentation(org.eclipse.jface.text.TextPresentation)
- */
- public void applyTextPresentation(TextPresentation textPresentation) {
- if (!fHighlightTokenChanges)
- return;
- IRegion region= textPresentation.getExtent();
- Diff[] changeDiffs = getChangeDiffs(region);
- for (int i = 0; i < changeDiffs.length; i++) {
- Diff diff = changeDiffs[i];
- StyleRange range = getStyleRange(diff, region);
- if (range != null)
- textPresentation.mergeStyleRange(range);
- }
- }
-
- private StyleRange getStyleRange(Diff diff, IRegion region) {
- return diff.getStyleRange(viewer, region);
- }
-
- private Diff[] getChangeDiffs(IRegion region) {
- if (fChangeDiffs == null)
- return new Diff[0];
- List intersectingDiffs = new ArrayList();
- for (Iterator iterator = fChangeDiffs.iterator(); iterator.hasNext();) {
- Diff diff = (Diff) iterator.next();
- Diff[] changeDiffs = diff.getChangeDiffs(viewer, region);
- for (int i = 0; i < changeDiffs.length; i++) {
- Diff changeDiff = changeDiffs[i];
- intersectingDiffs.add(changeDiff);
- }
- }
- return (Diff[]) intersectingDiffs.toArray(new Diff[intersectingDiffs.size()]);
- }
}
@@ -1438,6 +1142,58 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
public TextMergeViewer(Composite parent, int style, CompareConfiguration configuration) {
super(style, ResourceBundle.getBundle(BUNDLE_NAME), configuration);
+ fMerger = new DocumentMerger(new IDocumentMergerInput() {
+ public ITokenComparator createTokenComparator(String line) {
+ return TextMergeViewer.this.createTokenComparator(line);
+ }
+ public CompareConfiguration getCompareConfiguration() {
+ return TextMergeViewer.this.getCompareConfiguration();
+ }
+ public IDocument getDocument(char contributor) {
+ switch (contributor) {
+ case LEFT_CONTRIBUTOR:
+ return fLeft.getDocument();
+ case RIGHT_CONTRIBUTOR:
+ return fRight.getDocument();
+ case ANCESTOR_CONTRIBUTOR:
+ return fAncestor.getDocument();
+ }
+ return null;
+ }
+ public int getHunkStart() {
+ return TextMergeViewer.this.getHunkStart();
+ }
+ public Position getRegion(char contributor) {
+ switch (contributor) {
+ case LEFT_CONTRIBUTOR:
+ return fLeft.getRegion();
+ case RIGHT_CONTRIBUTOR:
+ return fRight.getRegion();
+ case ANCESTOR_CONTRIBUTOR:
+ return fAncestor.getRegion();
+ }
+ return null;
+ }
+ public boolean isHunkOnLeft() {
+ ITypedElement left = ((ICompareInput)getInput()).getRight();
+ return left != null && Utilities.getAdapter(left, IHunk.class) != null;
+ }
+ public boolean isIgnoreAncestor() {
+ return TextMergeViewer.this.isIgnoreAncestor();
+ }
+ public boolean isPatchHunk() {
+ return TextMergeViewer.this.isPatchHunk();
+ }
+
+ public boolean isShowPseudoConflicts() {
+ return fShowPseudoConflicts;
+ }
+ public boolean isThreeWay() {
+ return TextMergeViewer.this.isThreeWay();
+ }
+
+ });
+
int inheritedStyle= parent.getStyle();
if ((inheritedStyle & SWT.LEFT_TO_RIGHT) != 0)
fInheritedDirection= SWT.LEFT_TO_RIGHT;
@@ -1952,7 +1708,7 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
public void mouseMove(MouseEvent e) {
Cursor cursor= null;
Diff diff= handlemouseInBirdsEyeView(fBirdsEyeCanvas, e.y);
- if (diff != null && diff.fDirection != RangeDifference.NOCHANGE)
+ if (diff != null && diff.getKind() != RangeDifference.NOCHANGE)
cursor= fBirdsEyeCursor;
if (fLastCursor != cursor) {
fBirdsEyeCanvas.setCursor(cursor);
@@ -1993,7 +1749,7 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
}
private void setCurrentDiff2(Diff diff, boolean reveal) {
- if (diff != null && diff.fDirection != RangeDifference.NOCHANGE) {
+ if (diff != null && diff.getKind() != RangeDifference.NOCHANGE) {
//fCurrentDiff= null;
setCurrentDiff(diff, reveal);
}
@@ -2007,20 +1763,20 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
if (! fHighlightRanges)
return null;
- if (fChangeDiffs != null) {
+ if (fMerger.hasChanges()) {
int shift= tp.getVerticalScrollOffset() + (2-LW);
Point region= new Point(0, 0);
- Iterator e= fChangeDiffs.iterator();
- while (e.hasNext()) {
- Diff diff= (Diff) e.next();
+ char leg = getLeg(tp);
+ for (Iterator iterator = fMerger.changesIterator(); iterator.hasNext();) {
+ Diff diff = (Diff) iterator.next();
if (diff.isDeleted())
continue;
if (fShowCurrentOnly2 && !isCurrentDiff(diff))
continue;
- tp.getLineRange(diff.getPosition(tp), region);
+ tp.getLineRange(diff.getPosition(leg), region);
int y= (region.x * lineHeight) + shift;
int h= region.y * lineHeight;
@@ -2050,26 +1806,25 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
if (! fHighlightRanges)
return null;
- if (fChangeDiffs != null) {
+ if (fMerger.hasChanges()) {
int lshift= fLeft.getVerticalScrollOffset();
int rshift= fRight.getVerticalScrollOffset();
Point region= new Point(0, 0);
- Iterator e= fChangeDiffs.iterator();
- while (e.hasNext()) {
- Diff diff= (Diff) e.next();
+ for (Iterator iterator = fMerger.changesIterator(); iterator.hasNext();) {
+ Diff diff = (Diff) iterator.next();
if (diff.isDeleted())
continue;
if (fShowCurrentOnly2 && !isCurrentDiff(diff))
continue;
- fLeft.getLineRange(diff.fLeftPos, region);
+ fLeft.getLineRange(diff.getPosition(LEFT_CONTRIBUTOR), region);
int ly= (region.x * lineHeight) + lshift;
int lh= region.y * lineHeight;
- fRight.getLineRange(diff.fRightPos, region);
+ fRight.getLineRange(diff.getPosition(RIGHT_CONTRIBUTOR), region);
int ry= (region.x * lineHeight) + rshift;
int rh= region.y * lineHeight;
@@ -2096,35 +1851,7 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
}
private Diff handlemouseInBirdsEyeView(Canvas canvas, int my) {
- int yy, hh;
-
- Point size= canvas.getSize();
-
- int virtualHeight= fSynchronizedScrolling ? getVirtualHeight() : getRightHeight();
- if (virtualHeight < getViewportHeight())
- return null;
-
- int y= 0;
- if (fAllDiffs != null) {
- Iterator e= fAllDiffs.iterator();
- for (int i= 0; e.hasNext(); i++) {
- Diff diff= (Diff) e.next();
- int h= fSynchronizedScrolling ? diff.getMaxDiffHeight()
- : diff.getRightHeight();
- if (useChange(diff.fDirection) && !diff.fIsWhitespace) {
-
- yy= (y*size.y)/virtualHeight;
- hh= (h*size.y)/virtualHeight;
- if (hh < 3)
- hh= 3;
-
- if (my >= yy && my < yy+hh)
- return diff;
- }
- y+= h;
- }
- }
- return null;
+ return fMerger.findDiff(getViewportHeight(), fSynchronizedScrolling, canvas.getSize(), my);
}
private void paintBirdsEyeView(Canvas canvas, GC gc) {
@@ -2135,54 +1862,50 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
Point size= canvas.getSize();
- int virtualHeight= fSynchronizedScrolling ? getVirtualHeight() : getRightHeight();
+ int virtualHeight= fSynchronizedScrolling ? fMerger.getVirtualHeight() : fMerger.getRightHeight();
if (virtualHeight < getViewportHeight())
return;
Display display= canvas.getDisplay();
int y= 0;
- if (fAllDiffs != null) {
- Iterator e= fAllDiffs.iterator();
- for (int i= 0; e.hasNext(); i++) {
- Diff diff= (Diff) e.next();
- int h= fSynchronizedScrolling ? diff.getMaxDiffHeight()
- : diff.getRightHeight();
-
- if (useChange(diff.fDirection) && !diff.fIsWhitespace) {
-
- yy= (y*size.y)/virtualHeight;
- hh= (h*size.y)/virtualHeight;
- if (hh < 3)
- hh= 3;
-
- c= getColor(display, getFillColor(diff));
- if (c != null) {
- gc.setBackground(c);
- gc.fillRectangle(BIRDS_EYE_VIEW_INSET, yy, size.x-(2*BIRDS_EYE_VIEW_INSET),hh);
- }
- c= getColor(display, getStrokeColor(diff));
- if (c != null) {
- gc.setForeground(c);
- r.x= BIRDS_EYE_VIEW_INSET;
- r.y= yy;
- r.width= size.x-(2*BIRDS_EYE_VIEW_INSET)-1;
- r.height= hh;
- if (diff == fCurrentDiff ||
- (fCurrentDiff != null && diff == fCurrentDiff.fParent)) {
- gc.setLineWidth(2);
- r.x++;
- r.y++;
- r.width--;
- r.height--;
- } else {
- gc.setLineWidth(0 /* 1 */);
- }
- gc.drawRectangle(r);
+ for (Iterator iterator = fMerger.rangesIterator(); iterator.hasNext();) {
+ Diff diff = (Diff) iterator.next();
+ int h= fSynchronizedScrolling ? diff.getMaxDiffHeight()
+ : diff.getRightHeight();
+
+ if (fMerger.useChange(diff)) {
+
+ yy= (y*size.y)/virtualHeight;
+ hh= (h*size.y)/virtualHeight;
+ if (hh < 3)
+ hh= 3;
+
+ c= getColor(display, getFillColor(diff));
+ if (c != null) {
+ gc.setBackground(c);
+ gc.fillRectangle(BIRDS_EYE_VIEW_INSET, yy, size.x-(2*BIRDS_EYE_VIEW_INSET),hh);
+ }
+ c= getColor(display, getStrokeColor(diff));
+ if (c != null) {
+ gc.setForeground(c);
+ r.x= BIRDS_EYE_VIEW_INSET;
+ r.y= yy;
+ r.width= size.x-(2*BIRDS_EYE_VIEW_INSET)-1;
+ r.height= hh;
+ if (isCurrentDiff(diff)) {
+ gc.setLineWidth(2);
+ r.x++;
+ r.y++;
+ r.width--;
+ r.height--;
+ } else {
+ gc.setLineWidth(0 /* 1 */);
}
+ gc.drawRectangle(r);
}
-
- y+= h;
}
+
+ y+= h;
}
}
@@ -2257,7 +1980,7 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
setCurrentDiff(fButtonDiff, false);
copy(fCurrentDiff,
fCenterButton.getText().equals(COPY_LEFT_TO_RIGHT_INDICATOR),
- fCurrentDiff.fDirection != RangeDifference.CONFLICT);
+ fCurrentDiff.getKind() != RangeDifference.CONFLICT);
}
}
}
@@ -2651,9 +2374,9 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
Diff selectDiff= null;
if (FIX_47640) {
if (leftRange != null)
- selectDiff= findDiff(LEFT_CONTRIBUTOR, leftRange);
+ selectDiff= fMerger.findDiff(LEFT_CONTRIBUTOR, leftRange);
else if (rightRange != null)
- selectDiff= findDiff(RIGHT_CONTRIBUTOR, rightRange);
+ selectDiff= fMerger.findDiff(RIGHT_CONTRIBUTOR, rightRange);
}
if (selectDiff != null)
setCurrentDiff(selectDiff, true);
@@ -2673,37 +2396,12 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
return new ContributorInfo(this, element, leg);
}
- private Diff findDiff(char c, Position range) {
-
- MergeSourceViewer v;
- int start= range.getOffset();
- int end= start + range.getLength();
- if (c == LEFT_CONTRIBUTOR)
- v= fLeft;
- else if (c == RIGHT_CONTRIBUTOR)
- v= fRight;
- else
- return null;
-
- if (fChangeDiffs != null) {
- Iterator iter= fChangeDiffs.iterator();
- while (iter.hasNext()) {
- Diff diff= (Diff) iter.next();
- if (diff.isDeleted() || diff.fDirection == RangeDifference.NOCHANGE)
- continue;
- if (diff.overlaps(v, start, end))
- return diff;
- }
- }
- return null;
- }
-
private void updateDiffBackground(Diff diff) {
if (! fHighlightRanges)
return;
- if (diff == null || diff.fIsToken)
+ if (diff == null || diff.isToken())
return;
if (fShowCurrentOnly && !isCurrentDiff(diff))
@@ -2714,36 +2412,25 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
return;
if (isThreeWay())
- fAncestor.setLineBackground(diff.fAncestorPos, c);
- fLeft.setLineBackground(diff.fLeftPos, c);
- fRight.setLineBackground(diff.fRightPos, c);
+ fAncestor.setLineBackground(diff.getPosition(ANCESTOR_CONTRIBUTOR), c);
+ fLeft.setLineBackground(diff.getPosition(LEFT_CONTRIBUTOR), c);
+ fRight.setLineBackground(diff.getPosition(RIGHT_CONTRIBUTOR), c);
}
private void updateAllDiffBackgrounds(Display display) {
- if (fChangeDiffs != null) {
+ if (fMerger.hasChanges()) {
boolean threeWay= isThreeWay();
- Iterator iter= fChangeDiffs.iterator();
- while (iter.hasNext()) {
- Diff diff= (Diff) iter.next();
+ for (Iterator iterator = fMerger.changesIterator(); iterator.hasNext();) {
+ Diff diff = (Diff) iterator.next();
Color c= getColor(display, getFillColor(diff));
if (threeWay)
- fAncestor.setLineBackground(diff.fAncestorPos, c);
- fLeft.setLineBackground(diff.fLeftPos, c);
- fRight.setLineBackground(diff.fRightPos, c);
+ fAncestor.setLineBackground(diff.getPosition(ANCESTOR_CONTRIBUTOR), c);
+ fLeft.setLineBackground(diff.getPosition(LEFT_CONTRIBUTOR), c);
+ fRight.setLineBackground(diff.getPosition(RIGHT_CONTRIBUTOR), c);
}
}
}
- boolean isCurrentDiff(Diff diff) {
- if (diff == null)
- return false;
- if (diff == fCurrentDiff)
- return true;
- if (fCurrentDiff != null && fCurrentDiff.fParent == diff)
- return true;
- return false;
- }
-
/*
* Called whenever one of the documents changes.
* Sets the dirty state of this viewer and updates the lines.
@@ -2810,22 +2497,7 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
IDocumentRange dr= (IDocumentRange) other;
Position p= dr.getRange();
Diff diff= findDiff(otherType, p.offset);
- if (diff != null) {
- switch (type) {
- case ANCESTOR_CONTRIBUTOR:
- if (diff.fAncestorPos != null)
- return diff.fAncestorPos.offset;
- break;
- case LEFT_CONTRIBUTOR:
- if (diff.fLeftPos != null)
- return diff.fLeftPos.offset;
- break;
- case RIGHT_CONTRIBUTOR:
- if (diff.fRightPos != null)
- return diff.fRightPos.offset;
- break;
- }
- }
+ return fMerger.findInsertionPoint(diff, type);
}
return 0;
}
@@ -3059,224 +2731,53 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
}
//---- the differencing
-
- private static int maxWork(IRangeComparator a, IRangeComparator l, IRangeComparator r) {
- int ln= l.getRangeCount();
- int rn= r.getRangeCount();
- if (a != null) {
- int an= a.getRangeCount();
- return (2 * Math.max(an, ln)) + (2 * Math.max(an, rn));
- }
- return 2 * Math.max(ln, rn);
- }
/**
* Perform a two level 2- or 3-way diff.
* The first level is based on line comparison, the second level on token comparison.
*/
private void doDiff() {
-
- ArrayList newAllDiffs = new ArrayList();
- fChangeDiffs= new ArrayList();
- fCurrentDiff= null;
-
- IDocument aDoc= null;
IDocument lDoc= fLeft.getDocument();
IDocument rDoc= fRight.getDocument();
if (lDoc == null || rDoc == null)
return;
-
- Position aRegion= null;
- Position lRegion= fLeft.getRegion();
- Position rRegion= fRight.getRegion();
-
- boolean threeWay= isThreeWay();
-
- if (threeWay && !isIgnoreAncestor()) {
- aDoc= fAncestor.getDocument();
- aRegion= fAncestor.getRegion();
- }
-
- resetPositions(lDoc);
- resetPositions(rDoc);
- resetPositions(aDoc);
-
fAncestor.resetLineBackground();
fLeft.resetLineBackground();
fRight.resetLineBackground();
- boolean ignoreWhiteSpace= Utilities.getBoolean(getCompareConfiguration(), CompareConfiguration.IGNORE_WHITESPACE, false);
-
- DocLineComparator sright= new DocLineComparator(rDoc, toRegion(rRegion), ignoreWhiteSpace);
- DocLineComparator sleft= new DocLineComparator(lDoc, toRegion(lRegion), ignoreWhiteSpace);
- DocLineComparator sancestor= null;
- boolean isRight = true;
- if (aDoc != null) {
- sancestor= new DocLineComparator(aDoc, toRegion(aRegion), ignoreWhiteSpace);
- if (isPatchHunk()) {
- ITypedElement right = ((ICompareInput)getInput()).getRight();
- isRight = right != null && Utilities.getAdapter(right, IHunk.class) != null;
- if (isRight) {
- sleft= new DocLineComparator(aDoc, toRegion(aRegion), ignoreWhiteSpace);
- } else {
- sright= new DocLineComparator(aDoc, toRegion(aRegion), ignoreWhiteSpace);
- }
- }
- }
-
- if (!fSubDoc && rRegion != null && lRegion != null) {
- // we have to add a diff for the ignored lines
-
- int astart= 0;
- int as= 0;
- if (aRegion != null) {
- astart= aRegion.getOffset();
- as= Math.max(0, astart-1);
- }
- int ys= Math.max(0, lRegion.getOffset()-1);
- int ms= Math.max(0, rRegion.getOffset()-1);
-
- if (as > 0 || ys > 0 || ms > 0) {
- Diff diff= new Diff(null, RangeDifference.NOCHANGE,
- aDoc, aRegion, 0, astart,
- lDoc, lRegion, 0, lRegion.getOffset(),
- rDoc, rRegion, 0, rRegion.getOffset());
- newAllDiffs.add(diff);
- }
- }
-
- final ResourceBundle bundle= getResourceBundle();
-
- final Object[] result= new Object[1];
- final DocLineComparator sa= sancestor, sl= sleft, sr= sright;
- IRunnableWithProgress runnable= new IRunnableWithProgress() {
- public void run(IProgressMonitor monitor) throws InterruptedException, InvocationTargetException {
- String progressTitle= Utilities.getString(bundle, "compareProgressTask.title"); //$NON-NLS-1$
- monitor.beginTask(progressTitle, maxWork(sa, sl, sr));
- try {
- result[0]= RangeDifferencer.findRanges(monitor, sa, sl, sr);
- } catch (OutOfMemoryError ex) {
- System.gc();
- throw new InvocationTargetException(ex);
- }
- if (monitor.isCanceled()) { // canceled
- throw new InterruptedException();
- }
- monitor.done();
- }
- };
-
- RangeDifference[] e= null;
+ fCurrentDiff= null;
try {
- getCompareConfiguration().getContainer().run(true, true, runnable);
- e= (RangeDifference[]) result[0];
- } catch (InvocationTargetException ex) {
- String title= Utilities.getString(bundle, "tooComplexError.title"); //$NON-NLS-1$
- String format= Utilities.getString(bundle, "tooComplexError.format"); //$NON-NLS-1$
+ fMerger.doDiff();
+ } catch (CoreException e) {
+ CompareUIPlugin.log(e.getStatus());
+ String title= Utilities.getString(getResourceBundle(), "tooComplexError.title"); //$NON-NLS-1$
+ String format= Utilities.getString(getResourceBundle(), "tooComplexError.format"); //$NON-NLS-1$
String msg= MessageFormat.format(format, new Object[] { Integer.toString(PlatformUI.getWorkbench().getProgressService().getLongOperationTime()/1000) } );
MessageDialog.openError(fComposite.getShell(), title, msg);
- e= null;
- } catch (InterruptedException ex) {
- //
}
-
- if (e == null) {
- // we create a NOCHANGE range for the whole document
- Diff diff= new Diff(null, RangeDifference.NOCHANGE,
- aDoc, aRegion, 0, aDoc != null ? aDoc.getLength() : 0,
- lDoc, lRegion, 0, lDoc.getLength(),
- rDoc, rRegion, 0, rDoc.getLength());
-
- newAllDiffs.add(diff);
- } else {
- for (int i= 0; i < e.length; i++) {
- String a= null, s= null, d= null;
- RangeDifference es= e[i];
-
- int kind= es.kind();
-
- int ancestorStart= 0;
- int ancestorEnd= 0;
- if (sancestor != null) {
- ancestorStart= sancestor.getTokenStart(es.ancestorStart());
- ancestorEnd= getTokenEnd2(sancestor, es.ancestorStart(), es.ancestorLength());
- }
-
- int leftStart= sleft.getTokenStart(es.leftStart());
- int leftEnd= getTokenEnd2(sleft, es.leftStart(), es.leftLength());
-
- int rightStart= sright.getTokenStart(es.rightStart());
- int rightEnd= getTokenEnd2(sright, es.rightStart(), es.rightLength());
-
- if (isPatchHunk()) {
- if (isRight)
- leftStart = leftEnd = getHunkStart();
- else
- rightStart = rightEnd = getHunkStart();
- }
-
- Diff diff= new Diff(null, kind,
- aDoc, aRegion, ancestorStart, ancestorEnd,
- lDoc, lRegion, leftStart, leftEnd,
- rDoc, rRegion, rightStart, rightEnd);
-
- newAllDiffs.add(diff); // remember all range diffs for scrolling
-
- if (ignoreWhiteSpace && !isPatchHunk()) {
- if (sancestor != null)
- a= extract2(aDoc, sancestor, es.ancestorStart(), es.ancestorLength());
- s= extract2(lDoc, sleft, es.leftStart(), es.leftLength());
- d= extract2(rDoc, sright, es.rightStart(), es.rightLength());
-
- if ((a == null || a.trim().length() == 0) && s.trim().length() == 0 && d.trim().length() == 0) {
- diff.fIsWhitespace= true;
- continue;
- }
- }
- if (useChange(kind)) {
- fChangeDiffs.add(diff); // here we remember only the real diffs
- updateDiffBackground(diff);
-
- // Only do the token diff for non-hunks
- if (!isPatchHunk()) {
- if (s == null)
- s= extract2(lDoc, sleft, es.leftStart(), es.leftLength());
- if (d == null)
- d= extract2(rDoc, sright, es.rightStart(), es.rightLength());
-
- if (s.length() > 0 && d.length() > 0) {
- if (a == null && sancestor != null)
- a= extract2(aDoc, sancestor, es.ancestorStart(), es.ancestorLength());
- if (USE_MERGING_TOKEN_DIFF)
- mergingTokenDiff(diff, aDoc, a, rDoc, d, lDoc, s);
- else
- simpleTokenDiff(diff, aDoc, a, rDoc, d, lDoc, s);
- }
- }
- }
+ if (fMerger.hasChanges()) {
+ for (Iterator iterator = fMerger.changesIterator(); iterator.hasNext();) {
+ Diff diff = (Diff) iterator.next();
+ updateDiffBackground(diff);
}
}
-
- if (!fSubDoc && rRegion != null && lRegion != null) {
- // we have to add a diff for the ignored lines
-
- int aEnd= 0;
- int aLen= 0;
- if (aRegion != null && aDoc != null) {
- aEnd= aRegion.getOffset()+aRegion.getLength();
- aLen= aDoc.getLength();
- }
- Diff diff= new Diff(null, RangeDifference.NOCHANGE,
- aDoc, aRegion, aEnd, aLen,
- lDoc, lRegion, lRegion.getOffset()+lRegion.getLength(), lDoc.getLength(),
- rDoc, rRegion, rRegion.getOffset()+rRegion.getLength(), rDoc.getLength());
- newAllDiffs.add(diff);
- }
- fAllDiffs = newAllDiffs;
invalidateTextPresentation();
}
+ private Diff findDiff(char type, int pos) {
+ try {
+ return fMerger.findDiff(type, pos);
+ } catch (CoreException e) {
+ CompareUIPlugin.log(e.getStatus());
+ String title= Utilities.getString(getResourceBundle(), "tooComplexError.title"); //$NON-NLS-1$
+ String format= Utilities.getString(getResourceBundle(), "tooComplexError.format"); //$NON-NLS-1$
+ String msg= MessageFormat.format(format, new Object[] { Integer.toString(PlatformUI.getWorkbench().getProgressService().getLongOperationTime()/1000) } );
+ MessageDialog.openError(fComposite.getShell(), title, msg);
+ return null;
+ }
+ }
+
private void resetPositions(IDocument doc) {
if (doc == null)
return;
@@ -3287,314 +2788,6 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
}
doc.addPositionCategory(DIFF_RANGE_CATEGORY);
}
-
- private Diff findDiff(char type, int pos) {
-
- IDocument aDoc= null;
- IDocument lDoc= fLeft.getDocument();
- IDocument rDoc= fRight.getDocument();
- if (lDoc == null || rDoc == null)
- return null;
-
- Position aRegion= null;
- Position lRegion= null;
- Position rRegion= null;
-
- boolean threeWay= isThreeWay();
-
- if (threeWay && !isIgnoreAncestor())
- aDoc= fAncestor.getDocument();
-
- boolean ignoreWhiteSpace= Utilities.getBoolean(getCompareConfiguration(), CompareConfiguration.IGNORE_WHITESPACE, false);
-
- DocLineComparator sright= new DocLineComparator(rDoc, toRegion(rRegion), ignoreWhiteSpace);
- DocLineComparator sleft= new DocLineComparator(lDoc, toRegion(lRegion), ignoreWhiteSpace);
- DocLineComparator sancestor= null;
- if (aDoc != null)
- sancestor= new DocLineComparator(aDoc, toRegion(aRegion), ignoreWhiteSpace);
-
- final ResourceBundle bundle= getResourceBundle();
-
- final Object[] result= new Object[1];
- final DocLineComparator sa= sancestor, sl= sleft, sr= sright;
- IRunnableWithProgress runnable= new IRunnableWithProgress() {
- public void run(IProgressMonitor monitor) throws InterruptedException, InvocationTargetException {
- String progressTitle= Utilities.getString(bundle, "compareProgressTask.title"); //$NON-NLS-1$
- monitor.beginTask(progressTitle, maxWork(sa, sl, sr));
- try {
- result[0]= RangeDifferencer.findRanges(monitor, sa, sl, sr);
- } catch (OutOfMemoryError ex) {
- System.gc();
- throw new InvocationTargetException(ex);
- }
- if (monitor.isCanceled()) { // canceled
- throw new InterruptedException();
- }
- monitor.done();
- }
- };
- IProgressService progressService= PlatformUI.getWorkbench().getProgressService();
-
- RangeDifference[] e= null;
- try {
- progressService.run(true, true, runnable);
- e= (RangeDifference[]) result[0];
- } catch (InvocationTargetException ex) {
- String title= Utilities.getString(bundle, "tooComplexError.title"); //$NON-NLS-1$
- String format= Utilities.getString(bundle, "tooComplexError.format"); //$NON-NLS-1$
- String msg= MessageFormat.format(format, new Object[] { Integer.toString(progressService.getLongOperationTime()/1000) } );
- MessageDialog.openError(fComposite.getShell(), title, msg);
- e= null;
- } catch (InterruptedException ex) {
- //
- }
-
- if (e != null) {
- for (int i= 0; i < e.length; i++) {
- RangeDifference es= e[i];
-
- int kind= es.kind();
-
- int ancestorStart= 0;
- int ancestorEnd= 0;
- if (sancestor != null) {
- ancestorStart= sancestor.getTokenStart(es.ancestorStart());
- ancestorEnd= getTokenEnd2(sancestor, es.ancestorStart(), es.ancestorLength());
- }
-
- int leftStart= sleft.getTokenStart(es.leftStart());
- int leftEnd= getTokenEnd2(sleft, es.leftStart(), es.leftLength());
-
- int rightStart= sright.getTokenStart(es.rightStart());
- int rightEnd= getTokenEnd2(sright, es.rightStart(), es.rightLength());
-
- Diff diff= new Diff(null, kind,
- aDoc, aRegion, ancestorStart, ancestorEnd,
- lDoc, lRegion, leftStart, leftEnd,
- rDoc, rRegion, rightStart, rightEnd);
-
- if (diff.isInRange(type, pos))
- return diff;
- }
- }
-
- return null;
- }
-
- /*
- * Returns true if kind of change should be shown.
- */
- private boolean useChange(int kind) {
- if (kind == RangeDifference.NOCHANGE)
- return false;
- if (kind == RangeDifference.ANCESTOR)
- return fShowPseudoConflicts;
- return true;
- }
-
- private int getTokenEnd(ITokenComparator tc, int start, int count) {
- if (count <= 0)
- return tc.getTokenStart(start);
- int index= start + count - 1;
- return tc.getTokenStart(index) + tc.getTokenLength(index);
- }
-
- private static int getTokenEnd2(ITokenComparator tc, int start, int length) {
- return tc.getTokenStart(start + length);
- }
-
- /*
- * Returns the content of lines in the specified range as a String.
- * This includes the line separators.
- *
- * @param doc the document from which to extract the characters
- * @param start index of first line
- * @param length number of lines
- * @return the contents of the specified line range as a String
- */
- private String extract2(IDocument doc, ITokenComparator tc, int start, int length) {
- int count= tc.getRangeCount();
- if (length > 0 && count > 0) {
-
-//
-// int startPos= tc.getTokenStart(start);
-// int endPos= startPos;
-//
-// if (length > 1)
-// endPos= tc.getTokenStart(start + (length-1));
-// endPos+= tc.getTokenLength(start + (length-1));
-//
-
- int startPos= tc.getTokenStart(start);
- int endPos;
-
- if (length == 1) {
- endPos= startPos + tc.getTokenLength(start);
- } else {
- endPos= tc.getTokenStart(start + length);
- }
-
- try {
- return doc.get(startPos, endPos - startPos);
- } catch (BadLocationException e) {
- // silently ignored
- }
-
- }
- return ""; //$NON-NLS-1$
- }
-
- /*
- * Performs a token based 3-way diff on the character range specified by the given baseDiff.
- */
- private void simpleTokenDiff(final Diff baseDiff,
- IDocument ancestorDoc, String a,
- IDocument rightDoc, String d,
- IDocument leftDoc, String s) {
-
- int ancestorStart= 0;
- ITokenComparator sa= null;
- if (ancestorDoc != null) {
- ancestorStart= baseDiff.fAncestorPos.getOffset();
- sa= createTokenComparator(a);
- }
-
- int rightStart= baseDiff.fRightPos.getOffset();
- ITokenComparator sm= createTokenComparator(d);
-
- int leftStart= baseDiff.fLeftPos.getOffset();
- ITokenComparator sy= createTokenComparator(s);
-
- RangeDifference[] e= RangeDifferencer.findRanges(sa, sy, sm);
- for (int i= 0; i < e.length; i++) {
- RangeDifference es= e[i];
- int kind= es.kind();
- if (kind != RangeDifference.NOCHANGE) {
-
- int ancestorStart2= ancestorStart;
- int ancestorEnd2= ancestorStart;
- if (ancestorDoc != null) {
- ancestorStart2 += sa.getTokenStart(es.ancestorStart());
- ancestorEnd2 += getTokenEnd(sa, es.ancestorStart(), es.ancestorLength());
- }
-
- int leftStart2= leftStart + sy.getTokenStart(es.leftStart());
- int leftEnd2= leftStart + getTokenEnd(sy, es.leftStart(), es.leftLength());
-
- int rightStart2= rightStart + sm.getTokenStart(es.rightStart());
- int rightEnd2= rightStart + getTokenEnd(sm, es.rightStart(), es.rightLength());
-
- Diff diff= new Diff(baseDiff, kind,
- ancestorDoc, null, ancestorStart2, ancestorEnd2,
- leftDoc, null, leftStart2, leftEnd2,
- rightDoc, null, rightStart2, rightEnd2);
-
- // ensure that token diff is smaller than basediff
- int leftS= baseDiff.fLeftPos.offset;
- int leftE= baseDiff.fLeftPos.offset+baseDiff.fLeftPos.length;
- int rightS= baseDiff.fRightPos.offset;
- int rightE= baseDiff.fRightPos.offset+baseDiff.fRightPos.length;
- if (leftS != leftStart2 || leftE != leftEnd2 ||
- rightS != rightStart2 || rightE != rightEnd2) {
- diff.fIsToken= true;
- // add to base Diff
- baseDiff.add(diff);
- }
- }
- }
- }
-
- /*
- * Performs a "smart" token based 3-way diff on the character range specified by the given baseDiff.
- * It is "smart" because it tries to minimize the number of token diffs by merging them.
- */
- private void mergingTokenDiff(Diff baseDiff,
- IDocument ancestorDoc, String a,
- IDocument rightDoc, String d,
- IDocument leftDoc, String s) {
- ITokenComparator sa= null;
- int ancestorStart= 0;
- if (ancestorDoc != null) {
- sa= createTokenComparator(a);
- ancestorStart= baseDiff.fAncestorPos.getOffset();
- }
-
- int rightStart= baseDiff.fRightPos.getOffset();
- ITokenComparator sm= createTokenComparator(d);
-
- int leftStart= baseDiff.fLeftPos.getOffset();
- ITokenComparator sy= createTokenComparator(s);
-
- RangeDifference[] r= RangeDifferencer.findRanges(sa, sy, sm);
- for (int i= 0; i < r.length; i++) {
- RangeDifference es= r[i];
- // determine range of diffs in one line
- int start= i;
- int leftLine= -1;
- int rightLine= -1;
- try {
- leftLine= leftDoc.getLineOfOffset(leftStart+sy.getTokenStart(es.leftStart()));
- rightLine= rightDoc.getLineOfOffset(rightStart+sm.getTokenStart(es.rightStart()));
- } catch (BadLocationException e) {
- // silently ignored
- }
- i++;
- for (; i < r.length; i++) {
- es= r[i];
- try {
- if (leftLine != leftDoc.getLineOfOffset(leftStart+sy.getTokenStart(es.leftStart())))
- break;
- if (rightLine != rightDoc.getLineOfOffset(rightStart+sm.getTokenStart(es.rightStart())))
- break;
- } catch (BadLocationException e) {
- // silently ignored
- }
- }
- int end= i;
-
- // find first diff from left
- RangeDifference first= null;
- for (int ii= start; ii < end; ii++) {
- es= r[ii];
- if (useChange(es.kind())) {
- first= es;
- break;
- }
- }
-
- // find first diff from mine
- RangeDifference last= null;
- for (int ii= end-1; ii >= start; ii--) {
- es= r[ii];
- if (useChange(es.kind())) {
- last= es;
- break;
- }
- }
-
- if (first != null && last != null) {
-
- int ancestorStart2= 0;
- int ancestorEnd2= 0;
- if (ancestorDoc != null) {
- ancestorStart2= ancestorStart+sa.getTokenStart(first.ancestorStart());
- ancestorEnd2= ancestorStart+getTokenEnd(sa, last.ancestorStart(), last.ancestorLength());
- }
-
- int leftStart2= leftStart+sy.getTokenStart(first.leftStart());
- int leftEnd2= leftStart+getTokenEnd(sy, last.leftStart(), last.leftLength());
-
- int rightStart2= rightStart+sm.getTokenStart(first.rightStart());
- int rightEnd2= rightStart+getTokenEnd(sm, last.rightStart(), last.rightLength());
- Diff diff= new Diff(baseDiff, first.kind(),
- ancestorDoc, null, ancestorStart2, ancestorEnd2,
- leftDoc, null, leftStart2, leftEnd2,
- rightDoc, null, rightStart2, rightEnd2);
- diff.fIsToken= true;
- baseDiff.add(diff);
- }
- }
- }
//---- update UI stuff
@@ -3629,16 +2822,8 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
if (fCopyDiffRightToLeftItem != null)
((Action)fCopyDiffRightToLeftItem.getAction()).setEnabled(rightToLeft);
- boolean enableNavigation= false;
- if (fCurrentDiff == null && fChangeDiffs != null && fChangeDiffs.size() > 0)
- enableNavigation= true;
- else if (fChangeDiffs != null && fChangeDiffs.size() > 1)
- enableNavigation= true;
- else if (fCurrentDiff != null && fCurrentDiff.fDiffs != null)
- enableNavigation= true;
- else if (fCurrentDiff != null && fCurrentDiff.fIsToken)
- enableNavigation= true;
-
+ boolean enableNavigation= isNavigationPossible();
+
if (fNextDiff != null) {
IAction a= fNextDiff.getAction();
a.setEnabled(enableNavigation || hasNextElement(true));
@@ -3667,14 +2852,14 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
int unresolvedIncoming= 0;
int unresolvedConflicting= 0;
- if (fChangeDiffs != null) {
- Iterator e= fChangeDiffs.iterator();
- while (e.hasNext()) {
- Diff d= (Diff) e.next();
+ if (fMerger.hasChanges()) {
+ for (Iterator iterator = fMerger.changesIterator(); iterator
+ .hasNext();) {
+ Diff d = (Diff) iterator.next();
if (d.isIncomingOrConflicting() /* && useChange(d.fDirection) && !d.fIsWhitespace */) {
incomingOrConflicting++;
- if (!d.fResolved) {
- if (d.fDirection == RangeDifference.CONFLICT) {
+ if (!d.isResolved()) {
+ if (d.getKind() == RangeDifference.CONFLICT) {
unresolvedConflicting++;
break; // we can stop here because a conflict has the maximum priority
}
@@ -3709,16 +2894,16 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
diffDescription= CompareMessages.TextMergeViewer_diffDescription_noDiff_format;
} else {
- if (diff.fIsToken) // we don't show special info for token diffs
- diff= diff.fParent;
+ if (diff.isToken()) // we don't show special info for token diffs
+ diff= diff.getParent();
String format= CompareMessages.TextMergeViewer_diffDescription_diff_format;
diffDescription= MessageFormat.format(format,
new String[] {
getDiffType(diff), // 0: diff type
getDiffNumber(diff), // 1: diff number
- getDiffRange(fLeft, diff.fLeftPos), // 2: left start line
- getDiffRange(fRight, diff.fRightPos) // 3: left end line
+ getDiffRange(fLeft, diff.getPosition(LEFT_CONTRIBUTOR)), // 2: left start line
+ getDiffRange(fRight, diff.getPosition(RIGHT_CONTRIBUTOR)) // 3: left end line
}
);
}
@@ -3741,7 +2926,7 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
private String getDiffType(Diff diff) {
String s= ""; //$NON-NLS-1$
- switch(diff.fDirection) {
+ switch(diff.getKind()) {
case RangeDifference.LEFT:
s= CompareMessages.TextMergeViewer_direction_outgoing;
break;
@@ -3759,10 +2944,9 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
private String getDiffNumber(Diff diff) {
// find the diff's number
int diffNumber= 0;
- if (fChangeDiffs != null) {
- Iterator e= fChangeDiffs.iterator();
- while (e.hasNext()) {
- Diff d= (Diff) e.next();
+ if (fMerger.hasChanges()) {
+ for (Iterator iterator = fMerger.changesIterator(); iterator.hasNext();) {
+ Diff d = (Diff) iterator.next();
diffNumber++;
if (d == diff)
break;
@@ -4036,9 +3220,9 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
Diff firstDiff= null;
if (first)
- firstDiff= findNext(fRight, fChangeDiffs, -1, -1, false);
+ firstDiff= findNext(fRight, -1, -1, false);
else
- firstDiff= findPrev(fRight, fChangeDiffs, 9999999, 9999999, false);
+ firstDiff= findPrev(fRight, 9999999, 9999999, false);
setCurrentDiff(firstDiff, true);
}
@@ -4189,26 +3373,25 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
boolean showResolveUI= showResolveUI();
- if (fChangeDiffs != null) {
+ if (fMerger.hasChanges()) {
int lshift= fLeft.getVerticalScrollOffset();
int rshift= fRight.getVerticalScrollOffset();
Point region= new Point(0, 0);
- Iterator e= fChangeDiffs.iterator();
- while (e.hasNext()) {
- Diff diff= (Diff) e.next();
+ for (Iterator iterator = fMerger.changesIterator(); iterator.hasNext();) {
+ Diff diff = (Diff) iterator.next();
if (diff.isDeleted())
continue;
if (fShowCurrentOnly2 && !isCurrentDiff(diff))
continue;
- fLeft.getLineRange(diff.fLeftPos, region);
+ fLeft.getLineRange(diff.getPosition(LEFT_CONTRIBUTOR), region);
int ly= (region.x * lineHeightLeft) + lshift;
int lh= region.y * lineHeightLeft;
- fRight.getLineRange(diff.fRightPos, region);
+ fRight.getLineRange(diff.getPosition(RIGHT_CONTRIBUTOR), region);
int ry= (region.x * lineHeightRight) + rshift;
int rh= region.y * lineHeightRight;
@@ -4336,20 +3519,20 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
if (! fHighlightRanges)
return;
- if (fChangeDiffs != null) {
+ if (fMerger.hasChanges()) {
int shift= tp.getVerticalScrollOffset() + (2-LW);
Point region= new Point(0, 0);
- Iterator e= fChangeDiffs.iterator();
- while (e.hasNext()) {
- Diff diff= (Diff) e.next();
+ char leg = getLeg(tp);
+ for (Iterator iterator = fMerger.changesIterator(); iterator.hasNext();) {
+ Diff diff = (Diff) iterator.next();
if (diff.isDeleted())
continue;
if (fShowCurrentOnly2 && !isCurrentDiff(diff))
continue;
- tp.getLineRange(diff.getPosition(tp), region);
+ tp.getLineRange(diff.getPosition(leg), region);
int y= (region.x * lineHeight) + shift;
int h= region.y * lineHeight;
@@ -4378,7 +3561,7 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
if (! fHighlightRanges)
return;
- if (fChangeDiffs == null)
+ if (!fMerger.hasChanges())
return;
Control canvas= (Control) event.widget;
@@ -4395,17 +3578,17 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
shift+= fTopInset;
Point range= new Point(0, 0);
-
- Iterator e= fChangeDiffs.iterator();
- while (e.hasNext()) {
- Diff diff= (Diff) e.next();
+
+ char leg = getLeg(tp);
+ for (Iterator iterator = fMerger.changesIterator(); iterator.hasNext();) {
+ Diff diff = (Diff) iterator.next();
if (diff.isDeleted())
continue;
if (fShowCurrentOnly && !isCurrentDiff(diff))
continue;
- tp.getLineRange(diff.getPosition(tp), range);
+ tp.getLineRange(diff.getPosition(leg), range);
int y= (range.x * lineHeight) + shift;
int h= range.y * lineHeight;
@@ -4421,10 +3604,10 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
}
private RGB getFillColor(Diff diff) {
- boolean selected= fCurrentDiff != null && fCurrentDiff.fParent == diff;
+ boolean selected= fCurrentDiff != null && fCurrentDiff.getParent() == diff;
RGB selected_fill= getBackground(null);
if (isThreeWay() && !isIgnoreAncestor()) {
- switch (diff.fDirection) {
+ switch (diff.getKind()) {
case RangeDifference.RIGHT:
if (fLeftIsLocal)
return selected ? selected_fill : INCOMING_FILL;
@@ -4444,10 +3627,10 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
}
private RGB getStrokeColor(Diff diff) {
- boolean selected= fCurrentDiff != null && fCurrentDiff.fParent == diff;
+ boolean selected= fCurrentDiff != null && fCurrentDiff.getParent() == diff;
if (isThreeWay() && !isIgnoreAncestor()) {
- switch (diff.fDirection) {
+ switch (diff.getKind()) {
case RangeDifference.RIGHT:
if (fLeftIsLocal)
return selected ? SELECTED_INCOMING : INCOMING;
@@ -4501,12 +3684,13 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
if (part == null)
return null;
Point s = part.getSelectedRange();
+ char leg = getLeg(part);
for (;;) {
diff = null;
diff = internalGetNextDiff(down, deep, part, s);
- if (diff != null && diff.fDirection == RangeDifference.ANCESTOR
+ if (diff != null && diff.getKind() == RangeDifference.ANCESTOR
&& !isAncestorVisible()) {
- Position position = diff.getPosition(part);
+ Position position = diff.getPosition(leg);
s = new Point(position.getOffset(), position.getLength());
diff= null;
continue;
@@ -4517,10 +3701,10 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
}
private Diff internalGetNextDiff(boolean down, boolean deep, MergeSourceViewer part, Point s) {
- if (fChangeDiffs != null) {
+ if (fMerger.hasChanges()) {
if (down)
- return findNext(part, fChangeDiffs, s.x, s.x+s.y, deep);
- return findPrev(part, fChangeDiffs, s.x, s.x+s.y, deep);
+ return findNext(part, s.x, s.x+s.y, deep);
+ return findPrev(part, s.x, s.x+s.y, deep);
}
return null;
}
@@ -4533,12 +3717,7 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
}
private Diff getWrappedDiff(Diff diff, boolean down) {
- if (fChangeDiffs != null && fChangeDiffs.size() > 0) {
- if (down)
- return (Diff) fChangeDiffs.get(0);
- return (Diff) fChangeDiffs.get(fChangeDiffs.size()-1);
- }
- return null;
+ return fMerger.getWrappedDiff(diff, down);
}
/*
@@ -4558,7 +3737,7 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
}
if (diff != null)
setCurrentDiff(diff, true, deep);
- if (diff != null && diff.fDirection == RangeDifference.ANCESTOR
+ if (diff != null && diff.getKind() == RangeDifference.ANCESTOR
&& !isAncestorVisible())
continue;
break;
@@ -4662,83 +3841,16 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
* is returned.
*/
private Diff findDiff(MergeSourceViewer tp, int rangeStart, int rangeEnd) {
- if (fChangeDiffs != null) {
- Iterator e= fChangeDiffs.iterator();
- while (e.hasNext()) {
- Diff diff= (Diff) e.next();
- if (diff.overlaps(tp, rangeStart, rangeEnd))
- return diff;
- }
- }
- return null;
+ char contributor = getLeg(tp);
+ return fMerger.findDiff(contributor, rangeStart, rangeEnd);
}
- private static Diff findNext(MergeSourceViewer tp, List v, int start, int end, boolean deep) {
- for (int i= 0; i < v.size(); i++) {
- Diff diff= (Diff) v.get(i);
- Position p= diff.getPosition(tp);
- if (p != null) {
- int startOffset= p.getOffset();
- if (end < startOffset) // <=
- return diff;
- if (deep && diff.fDiffs != null) {
- Diff d= null;
- int endOffset= startOffset + p.getLength();
- if (start == startOffset && (end == endOffset || end == endOffset-1)) {
- d= findNext(tp, diff.fDiffs, start-1, start-1, deep);
- } else if (end < endOffset) {
- d= findNext(tp, diff.fDiffs, start, end, deep);
- }
- if (d != null)
- return d;
- }
- }
- }
- return null;
+ private Diff findNext(MergeSourceViewer tp, int start, int end, boolean deep) {
+ return fMerger.findNext(getLeg(tp), start, end, deep);
}
- private static Diff findPrev(MergeSourceViewer tp, List v, int start, int end, boolean deep) {
- for (int i= v.size()-1; i >= 0; i--) {
- Diff diff= (Diff) v.get(i);
- Position p= diff.getPosition(tp);
- if (p != null) {
- int startOffset= p.getOffset();
- int endOffset= startOffset + p.getLength();
- if (start > endOffset) {
- if (deep && diff.fDiffs != null) {
- // If we are going deep, find the last change in the diff
- return findPrev(tp, diff.fDiffs, end, end, deep);
- }
- return diff;
- }
- if (deep && diff.fDiffs != null) {
- Diff d= null;
- if (start == startOffset && end == endOffset) {
- // A whole diff is selected so we'll fall through
- // and go the the last change in the previous diff
- } else if (start >= startOffset) {
- // If we are at or before the first diff, select the
- // entire diff so next and previous are symmetrical
- if (isFirstDiff(tp, startOffset, diff.fDiffs)) {
- return diff;
- }
- d= findPrev(tp, diff.fDiffs, start, end, deep);
- }
- if (d != null)
- return d;
- }
- }
- }
- return null;
- }
-
- private static boolean isFirstDiff(MergeSourceViewer tp, int startOffset,
- ArrayList diffs) {
- if (diffs.isEmpty())
- return false;
- Diff diff = (Diff)diffs.get(0);
- Position p= diff.getPosition(tp);
- return (p.getOffset() >= startOffset);
+ private Diff findPrev(MergeSourceViewer tp, int start, int end, boolean deep) {
+ return fMerger.findPrev(getLeg(tp), start, end, deep);
}
/*
@@ -4770,27 +3882,27 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
// before we set fCurrentDiff we change the selection
// so that the paint code uses the old background colors
// otherwise selection isn't drawn correctly
- if (d.fIsToken || !fHighlightTokenChanges || deep || !d.hasChildren()) {
+ if (d.isToken() || !fHighlightTokenChanges || deep || !d.hasChildren()) {
if (isThreeWay() && !isIgnoreAncestor())
- fAncestor.setSelection(d.fAncestorPos);
- fLeft.setSelection(d.fLeftPos);
- fRight.setSelection(d.fRightPos);
+ fAncestor.setSelection(d.getPosition(ANCESTOR_CONTRIBUTOR));
+ fLeft.setSelection(d.getPosition(LEFT_CONTRIBUTOR));
+ fRight.setSelection(d.getPosition(RIGHT_CONTRIBUTOR));
} else {
if (isThreeWay() && !isIgnoreAncestor())
- fAncestor.setSelection(new Position(d.fAncestorPos.offset, 0));
- fLeft.setSelection(new Position(d.fLeftPos.offset, 0));
- fRight.setSelection(new Position(d.fRightPos.offset, 0));
+ fAncestor.setSelection(new Position(d.getPosition(ANCESTOR_CONTRIBUTOR).offset, 0));
+ fLeft.setSelection(new Position(d.getPosition(LEFT_CONTRIBUTOR).offset, 0));
+ fRight.setSelection(new Position(d.getPosition(RIGHT_CONTRIBUTOR).offset, 0));
}
// now switch diffs
fCurrentDiff= d;
- revealDiff(d, d.fIsToken);
+ revealDiff(d, d.isToken());
} else {
fCurrentDiff= d;
}
- Diff d1= oldDiff != null ? oldDiff.fParent : null;
- Diff d2= fCurrentDiff != null ? fCurrentDiff.fParent : null;
+ Diff d1= oldDiff != null ? oldDiff.getParent() : null;
+ Diff d2= fCurrentDiff != null ? fCurrentDiff.getParent() : null;
if (d1 != d2) {
updateDiffBackground(d1);
updateDiffBackground(d2);
@@ -4813,11 +3925,11 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
if (smart) {
Point region= new Point(0, 0);
// find the starting line of the diff in all text widgets
- int ls= fLeft.getLineRange(d.fLeftPos, region).x;
- int rs= fRight.getLineRange(d.fRightPos, region).x;
+ int ls= fLeft.getLineRange(d.getPosition(LEFT_CONTRIBUTOR), region).x;
+ int rs= fRight.getLineRange(d.getPosition(RIGHT_CONTRIBUTOR), region).x;
if (isThreeWay() && !isIgnoreAncestor()) {
- int as= fAncestor.getLineRange(d.fAncestorPos, region).x;
+ int as= fAncestor.getLineRange(d.getPosition(ANCESTOR_CONTRIBUTOR), region).x;
if (as >= fAncestor.getTopIndex() && as <= fAncestor.getBottomIndex())
ancestorIsVisible= true;
}
@@ -4835,33 +3947,31 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
MergeSourceViewer allButThis= null;
if (leftIsVisible) {
- avpos= lvpos= rvpos= realToVirtualPosition(fLeft, fLeft.getTopIndex());
+ avpos= lvpos= rvpos= realToVirtualPosition(LEFT_CONTRIBUTOR, fLeft.getTopIndex());
allButThis= fLeft;
} else if (rightIsVisible) {
- avpos= lvpos= rvpos= realToVirtualPosition(fRight, fRight.getTopIndex());
+ avpos= lvpos= rvpos= realToVirtualPosition(RIGHT_CONTRIBUTOR, fRight.getTopIndex());
allButThis= fRight;
} else if (ancestorIsVisible) {
- avpos= lvpos= rvpos= realToVirtualPosition(fAncestor, fAncestor.getTopIndex());
+ avpos= lvpos= rvpos= realToVirtualPosition(ANCESTOR_CONTRIBUTOR, fAncestor.getTopIndex());
allButThis= fAncestor;
} else {
- if (fAllDiffs != null) {
- int vpos= 0;
- Iterator e= fAllDiffs.iterator();
- for (int i= 0; e.hasNext(); i++) {
- Diff diff= (Diff) e.next();
- if (diff == d)
- break;
- if (fSynchronizedScrolling) {
- vpos+= diff.getMaxDiffHeight();
- } else {
- avpos+= diff.getAncestorHeight();
- lvpos+= diff.getLeftHeight();
- rvpos+= diff.getRightHeight();
- }
+ int vpos= 0;
+ for (Iterator iterator = fMerger.rangesIterator(); iterator
+ .hasNext();) {
+ Diff diff = (Diff) iterator.next();
+ if (diff == d)
+ break;
+ if (fSynchronizedScrolling) {
+ vpos+= diff.getMaxDiffHeight();
+ } else {
+ avpos+= diff.getAncestorHeight();
+ lvpos+= diff.getLeftHeight();
+ rvpos+= diff.getRightHeight();
}
- if (fSynchronizedScrolling)
- avpos= lvpos= rvpos= vpos;
}
+ if (fSynchronizedScrolling)
+ avpos= lvpos= rvpos= vpos;
int delta= fRight.getViewportLines()/4;
avpos-= delta;
if (avpos < 0)
@@ -4881,11 +3991,11 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
}
// horizontal scrolling
- if (d.fIsToken) {
+ if (d.isToken()) {
// we only scroll horizontally for token diffs
- reveal(fAncestor, d.fAncestorPos);
- reveal(fLeft, d.fLeftPos);
- reveal(fRight, d.fRightPos);
+ reveal(fAncestor, d.getPosition(ANCESTOR_CONTRIBUTOR));
+ reveal(fLeft, d.getPosition(LEFT_CONTRIBUTOR));
+ reveal(fRight, d.getPosition(RIGHT_CONTRIBUTOR));
} else {
// in all other cases we reset the horizontal offset
hscroll(fAncestor);
@@ -4916,14 +4026,13 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
//--------------------------------------------------------------------------------
void copyAllUnresolved(boolean leftToRight) {
- if (fChangeDiffs != null && isThreeWay() && !isIgnoreAncestor()) {
+ if (fMerger.hasChanges() && isThreeWay() && !isIgnoreAncestor()) {
IRewriteTarget target= leftToRight ? fRight.getRewriteTarget() : fLeft.getRewriteTarget();
boolean compoundChangeStarted= false;
- Iterator e= fChangeDiffs.iterator();
try {
- while (e.hasNext()) {
- Diff diff= (Diff) e.next();
- switch (diff.fDirection) {
+ for (Iterator iterator = fMerger.changesIterator(); iterator.hasNext();) {
+ Diff diff = (Diff) iterator.next();
+ switch (diff.getKind()) {
case RangeDifference.LEFT:
if (leftToRight) {
if (!compoundChangeStarted) {
@@ -5029,66 +4138,15 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
if (diff != null && !diff.isResolved()) {
if (!validateChange(!leftToRight))
return false;
- Position fromPos= null;
- Position toPos= null;
- IDocument fromDoc= null;
- IDocument toDoc= null;
-
if (leftToRight) {
fRight.setEnabled(true);
- fromPos= diff.fLeftPos;
- toPos= diff.fRightPos;
- fromDoc= fLeft.getDocument();
- toDoc= fRight.getDocument();
} else {
fLeft.setEnabled(true);
- fromPos= diff.fRightPos;
- toPos= diff.fLeftPos;
- fromDoc= fRight.getDocument();
- toDoc= fLeft.getDocument();
- }
-
- if (fromDoc != null) {
-
- int fromStart= fromPos.getOffset();
- int fromLen= fromPos.getLength();
-
- int toStart= toPos.getOffset();
- int toLen= toPos.getLength();
-
- try {
- String s= null;
-
- switch (diff.fDirection) {
- case RangeDifference.RIGHT:
- case RangeDifference.LEFT:
- s= fromDoc.get(fromStart, fromLen);
- break;
- case RangeDifference.ANCESTOR:
- break;
- case RangeDifference.CONFLICT:
- if (APPEND_CONFLICT) {
- s= toDoc.get(toStart, toLen);
- s+= fromDoc.get(fromStart, fromLen);
- } else
- s= fromDoc.get(fromStart, fromLen);
- break;
- }
- if (s != null) {
- toDoc.replace(toStart, toLen, s);
- toPos.setOffset(toStart);
- toPos.setLength(s.length());
- }
-
- } catch (BadLocationException e) {
- // silently ignored
- }
}
-
- diff.setResolved(true);
- updateResolveStatus();
-
- return true;
+ boolean result = fMerger.copy(diff, leftToRight);
+ if (result)
+ updateResolveStatus();
+ return result;
}
return false;
}
@@ -5104,36 +4162,6 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
}
//---- scrolling
-
- /*
- * Calculates virtual height (in lines) of views by adding the maximum of corresponding diffs.
- */
- private int getVirtualHeight() {
- int h= 1;
- if (fAllDiffs != null) {
- Iterator e= fAllDiffs.iterator();
- for (int i= 0; e.hasNext(); i++) {
- Diff diff= (Diff) e.next();
- h+= diff.getMaxDiffHeight();
- }
- }
- return h;
- }
-
- /*
- * Calculates height (in lines) of right view by adding the height of the right diffs.
- */
- private int getRightHeight() {
- int h= 1;
- if (fAllDiffs != null) {
- Iterator e= fAllDiffs.iterator();
- for (int i= 0; e.hasNext(); i++) {
- Diff diff= (Diff) e.next();
- h+= diff.getRightHeight();
- }
- }
- return h;
- }
/*
* The height of the TextEditors in lines.
@@ -5160,35 +4188,10 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
/*
* Returns the virtual position for the given view position.
*/
- private int realToVirtualPosition(MergeSourceViewer w, int vpos) {
-
- if (! fSynchronizedScrolling || fAllDiffs == null)
+ private int realToVirtualPosition(char contributor, int vpos) {
+ if (! fSynchronizedScrolling)
return vpos;
-
- int viewPos= 0; // real view position
- int virtualPos= 0; // virtual position
- Point region= new Point(0, 0);
-
- Iterator e= fAllDiffs.iterator();
- while (e.hasNext()) {
- Diff diff= (Diff) e.next();
- Position pos= diff.getPosition(w);
- w.getLineRange(pos, region);
- int realHeight= region.y;
- int virtualHeight= diff.getMaxDiffHeight();
- if (vpos <= viewPos + realHeight) { // OK, found!
- vpos-= viewPos; // make relative to this slot
- // now scale position within this slot to virtual slot
- if (realHeight <= 0)
- vpos= 0;
- else
- vpos= (vpos*virtualHeight)/realHeight;
- return virtualPos+vpos;
- }
- viewPos+= realHeight;
- virtualPos+= virtualHeight;
- }
- return virtualPos;
+ return fMerger.realToVirtualPosition(contributor, vpos);
}
private void scrollVertical(int avpos, int lvpos, int rvpos, MergeSourceViewer allBut) {
@@ -5196,7 +4199,7 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
int s= 0;
if (fSynchronizedScrolling) {
- s= getVirtualHeight() - rvpos;
+ s= fMerger.getVirtualHeight() - rvpos;
int height= fRight.getViewportLines()/4;
if (s < 0)
s= 0;
@@ -5208,21 +4211,21 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
if (isThreeWay() && allBut != fAncestor) {
if (fSynchronizedScrolling || allBut == null) {
- int y= virtualToRealPosition(fAncestor, avpos+s)-s;
+ int y= virtualToRealPosition(ANCESTOR_CONTRIBUTOR, avpos+s)-s;
fAncestor.vscroll(y);
}
}
if (allBut != fLeft) {
if (fSynchronizedScrolling || allBut == null) {
- int y= virtualToRealPosition(fLeft, lvpos+s)-s;
+ int y= virtualToRealPosition(LEFT_CONTRIBUTOR, lvpos+s)-s;
fLeft.vscroll(y);
}
}
if (allBut != fRight) {
if (fSynchronizedScrolling || allBut == null) {
- int y= virtualToRealPosition(fRight, rvpos+s)-s;
+ int y= virtualToRealPosition(RIGHT_CONTRIBUTOR, rvpos+s)-s;
fRight.vscroll(y);
}
}
@@ -5254,12 +4257,12 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
int ix= w.getTopIndex();
int ix2= w.getDocumentRegionOffset();
- int viewPosition= realToVirtualPosition(w, ix-ix2);
+ int viewPosition= realToVirtualPosition(getLeg(w), ix-ix2);
scrollVertical(viewPosition, viewPosition, viewPosition, w); // scroll all but the given views
if (fVScrollBar != null) {
- int value= Math.max(0, Math.min(viewPosition, getVirtualHeight() - getViewportHeight()));
+ int value= Math.max(0, Math.min(viewPosition, fMerger.getVirtualHeight() - getViewportHeight()));
fVScrollBar.setSelection(value);
//refreshBirdEyeView();
}
@@ -5270,7 +4273,7 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
private void updateVScrollBar() {
if (Utilities.okToUse(fVScrollBar) && fSynchronizedScrolling) {
- int virtualHeight= getVirtualHeight();
+ int virtualHeight= fMerger.getVirtualHeight();
int viewPortHeight= getViewportHeight();
int pageIncrement= viewPortHeight-1;
int thumb= (viewPortHeight > virtualHeight) ? virtualHeight : viewPortHeight;
@@ -5284,34 +4287,10 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
/*
* maps given virtual position into a real view position of this view.
*/
- private int virtualToRealPosition(MergeSourceViewer part, int v) {
-
- if (! fSynchronizedScrolling || fAllDiffs == null)
+ private int virtualToRealPosition(char contributor, int v) {
+ if (! fSynchronizedScrolling)
return v;
-
- int virtualPos= 0;
- int viewPos= 0;
- Point region= new Point(0, 0);
-
- Iterator e= fAllDiffs.iterator();
- while (e.hasNext()) {
- Diff diff= (Diff) e.next();
- Position pos= diff.getPosition(part);
- int viewHeight= part.getLineRange(pos, region).y;
- int virtualHeight= diff.getMaxDiffHeight();
- if (v < (virtualPos + virtualHeight)) {
- v-= virtualPos; // make relative to this slot
- if (viewHeight <= 0) {
- v= 0;
- } else {
- v= (int) (v * ((double)viewHeight/virtualHeight));
- }
- return viewPos+v;
- }
- virtualPos+= virtualHeight;
- viewPos+= viewHeight;
- }
- return viewPos;
+ return fMerger.virtualToRealPosition(contributor, v);
}
/* (non-Javadoc)
@@ -5453,8 +4432,7 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
private void resetDiffs() {
// clear stuff
fCurrentDiff= null;
- fChangeDiffs= null;
- fAllDiffs= null;
+ fMerger.reset();
resetPositions(fLeft.getDocument());
resetPositions(fRight.getDocument());
resetPositions(fAncestor.getDocument());
@@ -5492,4 +4470,36 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
fFindReplaceTarget= new FindReplaceTarget();
return fFindReplaceTarget;
}
+
+ /* package */ char getLeg(MergeSourceViewer w) {
+ if (w == fLeft)
+ return LEFT_CONTRIBUTOR;
+ if (w == fRight)
+ return RIGHT_CONTRIBUTOR;
+ if (w == fAncestor)
+ return ANCESTOR_CONTRIBUTOR;
+ return ANCESTOR_CONTRIBUTOR;
+ }
+
+ public boolean isCurrentDiff(Diff diff) {
+ if (diff == null)
+ return false;
+ if (diff == fCurrentDiff)
+ return true;
+ if (fCurrentDiff != null && fCurrentDiff.getParent() == diff)
+ return true;
+ return false;
+ }
+
+ public boolean isNavigationPossible() {
+ if (fCurrentDiff == null && fMerger.hasChanges())
+ return true;
+ else if (fMerger.changesCount() > 1)
+ return true;
+ else if (fCurrentDiff != null && fCurrentDiff.hasChildren())
+ return true;
+ else if (fCurrentDiff != null && fCurrentDiff.isToken())
+ return true;
+ return false;
+ }
}
diff --git a/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/merge/DocumentMerger.java b/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/merge/DocumentMerger.java
new file mode 100644
index 000000000..64290904a
--- /dev/null
+++ b/bundles/org.eclipse.compare/compare/org/eclipse/compare/internal/merge/DocumentMerger.java
@@ -0,0 +1,1338 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.compare.internal.merge;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.*;
+
+import org.eclipse.compare.CompareConfiguration;
+import org.eclipse.compare.contentmergeviewer.ITokenComparator;
+import org.eclipse.compare.internal.*;
+import org.eclipse.compare.rangedifferencer.*;
+import org.eclipse.compare.structuremergeviewer.Differencer;
+import org.eclipse.core.runtime.*;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.text.*;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.progress.IProgressService;
+
+/**
+ * A document merger manages the differences between two documents
+ * for either a 2-way or 3-way comparison.
+ * <p>
+ * This class should not have any UI dependencies.
+ */
+public class DocumentMerger {
+
+ private static final String DIFF_RANGE_CATEGORY = CompareUIPlugin.PLUGIN_ID + ".DIFF_RANGE_CATEGORY"; //$NON-NLS-1$
+
+ /** Selects between smartTokenDiff and mergingTokenDiff */
+ private static final boolean USE_MERGING_TOKEN_DIFF= false;
+
+ /** if true copying conflicts from one side to other concatenates both sides */
+ private static final boolean APPEND_CONFLICT= true;
+
+ /** All diffs for calculating scrolling position (includes line ranges without changes) */
+ private ArrayList fAllDiffs;
+ /** Subset of above: just real differences. */
+ private ArrayList fChangeDiffs;
+
+ private final boolean fLeftIsLocal;
+
+ private IDocumentMergerInput fInput;
+
+ public interface IDocumentMergerInput {
+
+ IDocument getDocument(char contributor);
+
+ Position getRegion(char contributor);
+
+ boolean isIgnoreAncestor();
+
+ boolean isThreeWay();
+
+ CompareConfiguration getCompareConfiguration();
+
+ ITokenComparator createTokenComparator(String s);
+
+ boolean isHunkOnLeft();
+
+ int getHunkStart();
+
+ boolean isPatchHunk();
+
+ boolean isShowPseudoConflicts();
+
+ }
+
+ public class Diff {
+ /** character range in ancestor document */
+ Position fAncestorPos;
+ /** character range in left document */
+ Position fLeftPos;
+ /** character range in right document */
+ Position fRightPos;
+ /** if this is a TokenDiff fParent points to the enclosing LineDiff */
+ Diff fParent;
+ /** if Diff has been resolved */
+ boolean fResolved;
+ int fDirection;
+ boolean fIsToken= false;
+ /** child token diffs */
+ ArrayList fDiffs;
+ boolean fIsWhitespace= false;
+
+ /*
+ * Create Diff from two ranges and an optional parent diff.
+ */
+ Diff(Diff parent, int dir, IDocument ancestorDoc, Position aRange, int ancestorStart, int ancestorEnd,
+ IDocument leftDoc, Position lRange, int leftStart, int leftEnd,
+ IDocument rightDoc, Position rRange, int rightStart, int rightEnd) {
+ fParent= parent != null ? parent : this;
+ fDirection= dir;
+
+ fLeftPos= createPosition(leftDoc, lRange, leftStart, leftEnd);
+ fRightPos= createPosition(rightDoc, rRange, rightStart, rightEnd);
+ if (ancestorDoc != null)
+ fAncestorPos= createPosition(ancestorDoc, aRange, ancestorStart, ancestorEnd);
+ }
+
+ public Position getPosition(char type) {
+ switch (type) {
+ case MergeViewerContentProvider.ANCESTOR_CONTRIBUTOR:
+ return fAncestorPos;
+ case MergeViewerContentProvider.LEFT_CONTRIBUTOR:
+ return fLeftPos;
+ case MergeViewerContentProvider.RIGHT_CONTRIBUTOR:
+ return fRightPos;
+ }
+ return null;
+ }
+
+ boolean isInRange(char type, int pos) {
+ Position p= getPosition(type);
+ return (pos >= p.offset) && (pos < (p.offset+p.length));
+ }
+
+ public String changeType() {
+ boolean leftEmpty= fLeftPos.length == 0;
+ boolean rightEmpty= fRightPos.length == 0;
+
+ if (fDirection == RangeDifference.LEFT) {
+ if (!leftEmpty && rightEmpty)
+ return CompareMessages.TextMergeViewer_changeType_addition;
+ if (leftEmpty && !rightEmpty)
+ return CompareMessages.TextMergeViewer_changeType_deletion;
+ } else {
+ if (leftEmpty && !rightEmpty)
+ return CompareMessages.TextMergeViewer_changeType_addition;
+ if (!leftEmpty && rightEmpty)
+ return CompareMessages.TextMergeViewer_changeType_deletion;
+ }
+ return CompareMessages.TextMergeViewer_changeType_change;
+ }
+
+ public Image getImage() {
+ int code= Differencer.CHANGE;
+ switch (fDirection) {
+ case RangeDifference.RIGHT:
+ code+= Differencer.LEFT;
+ break;
+ case RangeDifference.LEFT:
+ code+= Differencer.RIGHT;
+ break;
+ case RangeDifference.ANCESTOR:
+ case RangeDifference.CONFLICT:
+ code+= Differencer.CONFLICTING;
+ break;
+ }
+ if (code != 0)
+ return getCompareConfiguration().getImage(code);
+ return null;
+ }
+
+ Position createPosition(IDocument doc, Position range, int start, int end) {
+ try {
+ int l= end-start;
+ if (range != null) {
+ int dl= range.length;
+ if (l > dl)
+ l= dl;
+ } else {
+ int dl= doc.getLength();
+ if (start+l > dl)
+ l= dl-start;
+ }
+
+ Position p= null;
+ try {
+ p= new Position(start, l);
+ } catch (RuntimeException ex) {
+ p= new Position(0, 0);
+ }
+
+ try {
+ doc.addPosition(DIFF_RANGE_CATEGORY, p);
+ } catch (BadPositionCategoryException ex) {
+ // silently ignored
+ }
+ return p;
+ } catch (BadLocationException ee) {
+ // silently ignored
+ }
+ return null;
+ }
+
+ void add(Diff d) {
+ if (fDiffs == null)
+ fDiffs= new ArrayList();
+ fDiffs.add(d);
+ }
+
+ public boolean isDeleted() {
+ if (fAncestorPos != null && fAncestorPos.isDeleted())
+ return true;
+ return fLeftPos.isDeleted() || fRightPos.isDeleted();
+ }
+
+ void setResolved(boolean r) {
+ fResolved= r;
+ if (r)
+ fDiffs= null;
+ }
+
+ public boolean isResolved() {
+ if (!fResolved && fDiffs != null) {
+ Iterator e= fDiffs.iterator();
+ while (e.hasNext()) {
+ Diff d= (Diff) e.next();
+ if (!d.isResolved())
+ return false;
+ }
+ return true;
+ }
+ return fResolved;
+ }
+
+// private boolean isIncoming() {
+// switch (fDirection) {
+// case RangeDifference.RIGHT:
+// if (fLeftIsLocal)
+// return true;
+// break;
+// case RangeDifference.LEFT:
+// if (!fLeftIsLocal)
+// return true;
+// break;
+// }
+// return false;
+// }
+
+ public boolean isIncomingOrConflicting() {
+ switch (fDirection) {
+ case RangeDifference.RIGHT:
+ if (fLeftIsLocal)
+ return true;
+ break;
+ case RangeDifference.LEFT:
+ if (!fLeftIsLocal)
+ return true;
+ break;
+ case RangeDifference.CONFLICT:
+ return true;
+ }
+ return false;
+ }
+
+// private boolean isUnresolvedIncoming() {
+// if (fResolved)
+// return false;
+// return isIncoming();
+// }
+
+ public boolean isUnresolvedIncomingOrConflicting() {
+ if (fResolved)
+ return false;
+ return isIncomingOrConflicting();
+ }
+
+ Position getPosition(int contributor) {
+ if (contributor == MergeViewerContentProvider.LEFT_CONTRIBUTOR)
+ return fLeftPos;
+ if (contributor == MergeViewerContentProvider.RIGHT_CONTRIBUTOR)
+ return fRightPos;
+ if (contributor == MergeViewerContentProvider.ANCESTOR_CONTRIBUTOR)
+ return fAncestorPos;
+ return null;
+ }
+
+ /*
+ * Returns true if given character range overlaps with this Diff.
+ */
+ public boolean overlaps(int contributor, int start, int end) {
+ Position h= getPosition(contributor);
+ if (h != null) {
+ int ds= h.getOffset();
+ int de= ds + h.getLength();
+ if ((start < de) && (end >= ds))
+ return true;
+ }
+ return false;
+ }
+
+ public int getMaxDiffHeight() {
+ Point region= new Point(0, 0);
+ int h= getLineRange(getDocument(MergeViewerContentProvider.LEFT_CONTRIBUTOR), fLeftPos, region).y;
+ if (isThreeWay())
+ h= Math.max(h, getLineRange(getDocument(MergeViewerContentProvider.ANCESTOR_CONTRIBUTOR), fAncestorPos, region).y);
+ return Math.max(h, getLineRange(getDocument(MergeViewerContentProvider.RIGHT_CONTRIBUTOR), fRightPos, region).y);
+ }
+
+ public int getAncestorHeight() {
+ Point region= new Point(0, 0);
+ return getLineRange(getDocument(MergeViewerContentProvider.ANCESTOR_CONTRIBUTOR), fAncestorPos, region).y;
+ }
+
+ public int getLeftHeight() {
+ Point region= new Point(0, 0);
+ return getLineRange(getDocument(MergeViewerContentProvider.LEFT_CONTRIBUTOR), fLeftPos, region).y;
+ }
+
+ public int getRightHeight() {
+ Point region= new Point(0, 0);
+ return getLineRange(getDocument(MergeViewerContentProvider.RIGHT_CONTRIBUTOR), fRightPos, region).y;
+ }
+
+ public Diff[] getChangeDiffs(int contributor, IRegion region) {
+ if (fDiffs != null && intersectsRegion(contributor, region)) {
+ List result = new ArrayList();
+ for (Iterator iterator = fDiffs.iterator(); iterator.hasNext();) {
+ Diff diff = (Diff) iterator.next();
+ if (diff.intersectsRegion(contributor, region)) {
+ result.add(diff);
+ }
+ }
+ return (Diff[]) result.toArray(new Diff[result.size()]);
+ }
+ return new Diff[0];
+ }
+
+ private boolean intersectsRegion(int contributor, IRegion region) {
+ Position p = getPosition(contributor);
+ if (p != null)
+ return p.overlapsWith(region.getOffset(), region.getLength());
+ return false;
+ }
+
+ public boolean hasChildren() {
+ return fDiffs != null && !fDiffs.isEmpty();
+ }
+
+ public int getKind() {
+ return fDirection;
+ }
+
+ public boolean isToken() {
+ return fIsToken;
+ }
+
+ public Diff getParent() {
+ return fParent;
+ }
+
+ public Iterator childIterator() {
+ if (fDiffs == null)
+ return new ArrayList().iterator();
+ return fDiffs.iterator();
+ }
+ }
+
+ public DocumentMerger(IDocumentMergerInput input) {
+ this.fInput = input;
+ fLeftIsLocal= Utilities.getBoolean(getCompareConfiguration(), "LEFT_IS_LOCAL", false); //$NON-NLS-1$
+ }
+
+ /**
+ * Perform a two level 2- or 3-way diff.
+ * The first level is based on line comparison, the second level on token comparison.
+ * @throws CoreException
+ */
+ public void doDiff() throws CoreException {
+
+ fChangeDiffs= new ArrayList();
+ IDocument lDoc = getDocument(MergeViewerContentProvider.LEFT_CONTRIBUTOR);
+ IDocument rDoc = getDocument(MergeViewerContentProvider.RIGHT_CONTRIBUTOR);
+
+ if (lDoc == null || rDoc == null)
+ return;
+
+ Position lRegion= getRegion(MergeViewerContentProvider.LEFT_CONTRIBUTOR);
+ Position rRegion= getRegion(MergeViewerContentProvider.RIGHT_CONTRIBUTOR);
+
+ IDocument aDoc = null;
+ Position aRegion= null;
+ if (isThreeWay() && !isIgnoreAncestor()) {
+ aDoc= getDocument(MergeViewerContentProvider.ANCESTOR_CONTRIBUTOR);
+ aRegion= getRegion(MergeViewerContentProvider.ANCESTOR_CONTRIBUTOR);
+ }
+
+ resetPositions(lDoc);
+ resetPositions(rDoc);
+ resetPositions(aDoc);
+
+ boolean ignoreWhiteSpace= isIgnoreWhitespace();
+
+ DocLineComparator sright= new DocLineComparator(rDoc, toRegion(rRegion), ignoreWhiteSpace);
+ DocLineComparator sleft= new DocLineComparator(lDoc, toRegion(lRegion), ignoreWhiteSpace);
+ DocLineComparator sancestor= null;
+ if (aDoc != null) {
+ sancestor= new DocLineComparator(aDoc, toRegion(aRegion), ignoreWhiteSpace);
+ if (isPatchHunk()) {
+ if (isHunkOnLeft()) {
+ sright= new DocLineComparator(aDoc, toRegion(aRegion), ignoreWhiteSpace);
+ } else {
+ sleft= new DocLineComparator(aDoc, toRegion(aRegion), ignoreWhiteSpace);
+ }
+ }
+ }
+
+ final Object[] result= new Object[1];
+ final DocLineComparator sa= sancestor, sl= sleft, sr= sright;
+ IRunnableWithProgress runnable= new IRunnableWithProgress() {
+ public void run(IProgressMonitor monitor) throws InterruptedException, InvocationTargetException {
+ monitor.beginTask("Computing Differences...", maxWork(sa, sl, sr));
+ try {
+ result[0]= RangeDifferencer.findRanges(monitor, sa, sl, sr);
+ } catch (OutOfMemoryError ex) {
+ System.gc();
+ throw new InvocationTargetException(ex);
+ }
+ if (monitor.isCanceled()) { // canceled
+ throw new InterruptedException();
+ }
+ monitor.done();
+ }
+ };
+
+ RangeDifference[] e= null;
+ try {
+ getCompareConfiguration().getContainer().run(true, true, runnable);
+ e= (RangeDifference[]) result[0];
+ } catch (InvocationTargetException ex) {
+ // we create a NOCHANGE range for the whole document
+ Diff diff= new Diff(null, RangeDifference.NOCHANGE,
+ aDoc, aRegion, 0, aDoc != null ? aDoc.getLength() : 0,
+ lDoc, lRegion, 0, lDoc.getLength(),
+ rDoc, rRegion, 0, rDoc.getLength());
+
+ fAllDiffs = new ArrayList();
+ fAllDiffs.add(diff);
+ throw new CoreException(new Status(IStatus.ERROR, CompareUIPlugin.PLUGIN_ID, 0, "Too many differences found", ex.getTargetException()));
+ } catch (InterruptedException ex) {
+ //
+ }
+
+ ArrayList newAllDiffs = new ArrayList();
+ for (int i= 0; i < e.length; i++) {
+ RangeDifference es= e[i];
+
+ int ancestorStart= 0;
+ int ancestorEnd= 0;
+ if (sancestor != null) {
+ ancestorStart= sancestor.getTokenStart(es.ancestorStart());
+ ancestorEnd= getTokenEnd2(sancestor, es.ancestorStart(), es.ancestorLength());
+ }
+
+ int leftStart= sleft.getTokenStart(es.leftStart());
+ int leftEnd= getTokenEnd2(sleft, es.leftStart(), es.leftLength());
+
+ int rightStart= sright.getTokenStart(es.rightStart());
+ int rightEnd= getTokenEnd2(sright, es.rightStart(), es.rightLength());
+
+ if (isPatchHunk()) {
+ if (isHunkOnLeft()) {
+ rightStart = rightEnd = getHunkStart();
+ } else {
+ leftStart = leftEnd = getHunkStart();
+ }
+ }
+
+ Diff diff= new Diff(null, es.kind(),
+ aDoc, aRegion, ancestorStart, ancestorEnd,
+ lDoc, lRegion, leftStart, leftEnd,
+ rDoc, rRegion, rightStart, rightEnd);
+
+ newAllDiffs.add(diff); // remember all range diffs for scrolling
+
+ if (isPatchHunk()) {
+ if (useChange(diff)) {
+ recordChangeDiff(diff);
+ }
+ } else {
+ if (ignoreWhiteSpace || useChange(es.kind())) {
+
+ // Extract the string for each contributor.
+ String a= null;
+ if (sancestor != null)
+ a= extract2(aDoc, sancestor, es.ancestorStart(), es.ancestorLength());
+ String s= extract2(lDoc, sleft, es.leftStart(), es.leftLength());
+ String d= extract2(rDoc, sright, es.rightStart(), es.rightLength());
+
+ // Indicate whether all contributors are whitespace
+ if (ignoreWhiteSpace
+ && (a == null || a.trim().length() == 0)
+ && s.trim().length() == 0
+ && d.trim().length() == 0) {
+ diff.fIsWhitespace= true;
+ }
+
+ // If the diff is of interest, record it and generate the token diffs
+ if (useChange(diff)) {
+ recordChangeDiff(diff);
+ if (s.length() > 0 && d.length() > 0) {
+ if (a == null && sancestor != null)
+ a= extract2(aDoc, sancestor, es.ancestorStart(), es.ancestorLength());
+ if (USE_MERGING_TOKEN_DIFF)
+ mergingTokenDiff(diff, aDoc, a, rDoc, d, lDoc, s);
+ else
+ simpleTokenDiff(diff, aDoc, a, rDoc, d, lDoc, s);
+ }
+ }
+ }
+ }
+ }
+ fAllDiffs = newAllDiffs;
+ }
+
+ public Diff findDiff(char type, int pos) throws CoreException {
+
+ IDocument aDoc= null;
+ IDocument lDoc= getDocument(MergeViewerContentProvider.LEFT_CONTRIBUTOR);
+ IDocument rDoc= getDocument(MergeViewerContentProvider.RIGHT_CONTRIBUTOR);
+ if (lDoc == null || rDoc == null)
+ return null;
+
+ Position aRegion= null;
+ Position lRegion= null;
+ Position rRegion= null;
+
+ boolean threeWay= isThreeWay();
+
+ if (threeWay && !isIgnoreAncestor())
+ aDoc= getDocument(MergeViewerContentProvider.ANCESTOR_CONTRIBUTOR);
+
+ boolean ignoreWhiteSpace= isIgnoreWhitespace();
+
+ DocLineComparator sright= new DocLineComparator(rDoc, toRegion(rRegion), ignoreWhiteSpace);
+ DocLineComparator sleft= new DocLineComparator(lDoc, toRegion(lRegion), ignoreWhiteSpace);
+ DocLineComparator sancestor= null;
+ if (aDoc != null)
+ sancestor= new DocLineComparator(aDoc, toRegion(aRegion), ignoreWhiteSpace);
+
+ final Object[] result= new Object[1];
+ final DocLineComparator sa= sancestor, sl= sleft, sr= sright;
+ IRunnableWithProgress runnable= new IRunnableWithProgress() {
+ public void run(IProgressMonitor monitor) throws InterruptedException, InvocationTargetException {
+ monitor.beginTask("Finding Differences...", maxWork(sa, sl, sr));
+ try {
+ result[0]= RangeDifferencer.findRanges(monitor, sa, sl, sr);
+ } catch (OutOfMemoryError ex) {
+ System.gc();
+ throw new InvocationTargetException(ex);
+ }
+ if (monitor.isCanceled()) { // canceled
+ throw new InterruptedException();
+ }
+ monitor.done();
+ }
+ };
+ IProgressService progressService= PlatformUI.getWorkbench().getProgressService();
+
+ RangeDifference[] e= null;
+ try {
+ progressService.run(true, true, runnable);
+ e= (RangeDifference[]) result[0];
+ } catch (InvocationTargetException ex) {
+ throw new CoreException(new Status(IStatus.ERROR, CompareUIPlugin.PLUGIN_ID, 0, "Too many differences found", ex.getTargetException()));
+ } catch (InterruptedException ex) {
+ //
+ }
+
+ if (e != null) {
+ for (int i= 0; i < e.length; i++) {
+ RangeDifference es= e[i];
+
+ int kind= es.kind();
+
+ int ancestorStart= 0;
+ int ancestorEnd= 0;
+ if (sancestor != null) {
+ ancestorStart= sancestor.getTokenStart(es.ancestorStart());
+ ancestorEnd= getTokenEnd2(sancestor, es.ancestorStart(), es.ancestorLength());
+ }
+
+ int leftStart= sleft.getTokenStart(es.leftStart());
+ int leftEnd= getTokenEnd2(sleft, es.leftStart(), es.leftLength());
+
+ int rightStart= sright.getTokenStart(es.rightStart());
+ int rightEnd= getTokenEnd2(sright, es.rightStart(), es.rightLength());
+
+ Diff diff= new Diff(null, kind,
+ aDoc, aRegion, ancestorStart, ancestorEnd,
+ lDoc, lRegion, leftStart, leftEnd,
+ rDoc, rRegion, rightStart, rightEnd);
+
+ if (diff.isInRange(type, pos))
+ return diff;
+ }
+ }
+
+ return null;
+ }
+
+ private void recordChangeDiff(Diff diff) {
+ fChangeDiffs.add(diff); // here we remember only the real diffs
+ }
+
+ private boolean isHunkOnLeft() {
+ return fInput.isHunkOnLeft();
+ }
+
+ private int getHunkStart() {
+ return fInput.getHunkStart();
+ }
+
+ private boolean isPatchHunk() {
+ return fInput.isPatchHunk();
+ }
+
+ private boolean isIgnoreWhitespace() {
+ return Utilities.getBoolean(getCompareConfiguration(), CompareConfiguration.IGNORE_WHITESPACE, false);
+ }
+
+ private IDocument getDocument(char contributor) {
+ return fInput.getDocument(contributor);
+ }
+
+ private Position getRegion(char contributor) {
+ return fInput.getRegion(contributor);
+ }
+
+ public boolean isIgnoreAncestor() {
+ return fInput.isIgnoreAncestor();
+ }
+
+ public boolean isThreeWay() {
+ return fInput.isThreeWay();
+ }
+
+ /**
+ * Return the compare configuration associated with this merger.
+ * @return the compare configuration associated with this merger
+ */
+ public CompareConfiguration getCompareConfiguration() {
+ return fInput.getCompareConfiguration();
+ }
+
+ /*
+ * Returns true if kind of change should be shown.
+ */
+ public boolean useChange(Diff diff) {
+ if (diff.fIsWhitespace)
+ return false;
+ int kind = diff.getKind();
+ return useChange(kind);
+ }
+
+ private boolean useChange(int kind) {
+ if (kind == RangeDifference.NOCHANGE)
+ return false;
+ if (kind == RangeDifference.ANCESTOR)
+ return fInput.isShowPseudoConflicts();
+ return true;
+ }
+
+ private int getTokenEnd(ITokenComparator tc, int start, int count) {
+ if (count <= 0)
+ return tc.getTokenStart(start);
+ int index= start + count - 1;
+ return tc.getTokenStart(index) + tc.getTokenLength(index);
+ }
+
+ private static int getTokenEnd2(ITokenComparator tc, int start, int length) {
+ return tc.getTokenStart(start + length);
+ }
+
+ /**
+ * Returns the content of lines in the specified range as a String.
+ * This includes the line separators.
+ *
+ * @param doc the document from which to extract the characters
+ * @param start index of first line
+ * @param length number of lines
+ * @return the contents of the specified line range as a String
+ */
+ private String extract2(IDocument doc, ITokenComparator tc, int start, int length) {
+ int count= tc.getRangeCount();
+ if (length > 0 && count > 0) {
+
+//
+// int startPos= tc.getTokenStart(start);
+// int endPos= startPos;
+//
+// if (length > 1)
+// endPos= tc.getTokenStart(start + (length-1));
+// endPos+= tc.getTokenLength(start + (length-1));
+//
+
+ int startPos= tc.getTokenStart(start);
+ int endPos;
+
+ if (length == 1) {
+ endPos= startPos + tc.getTokenLength(start);
+ } else {
+ endPos= tc.getTokenStart(start + length);
+ }
+
+ try {
+ return doc.get(startPos, endPos - startPos);
+ } catch (BadLocationException e) {
+ // silently ignored
+ }
+
+ }
+ return ""; //$NON-NLS-1$
+ }
+
+ private static IRegion toRegion(Position position) {
+ if (position != null)
+ return new Region(position.getOffset(), position.getLength());
+ return null;
+ }
+
+ /*
+ * Performs a "smart" token based 3-way diff on the character range specified by the given baseDiff.
+ * It is "smart" because it tries to minimize the number of token diffs by merging them.
+ */
+ private void mergingTokenDiff(Diff baseDiff,
+ IDocument ancestorDoc, String a,
+ IDocument rightDoc, String d,
+ IDocument leftDoc, String s) {
+ ITokenComparator sa= null;
+ int ancestorStart= 0;
+ if (ancestorDoc != null) {
+ sa= createTokenComparator(a);
+ ancestorStart= baseDiff.fAncestorPos.getOffset();
+ }
+
+ int rightStart= baseDiff.fRightPos.getOffset();
+ ITokenComparator sm= createTokenComparator(d);
+
+ int leftStart= baseDiff.fLeftPos.getOffset();
+ ITokenComparator sy= createTokenComparator(s);
+
+ RangeDifference[] r= RangeDifferencer.findRanges(sa, sy, sm);
+ for (int i= 0; i < r.length; i++) {
+ RangeDifference es= r[i];
+ // determine range of diffs in one line
+ int start= i;
+ int leftLine= -1;
+ int rightLine= -1;
+ try {
+ leftLine= leftDoc.getLineOfOffset(leftStart+sy.getTokenStart(es.leftStart()));
+ rightLine= rightDoc.getLineOfOffset(rightStart+sm.getTokenStart(es.rightStart()));
+ } catch (BadLocationException e) {
+ // silently ignored
+ }
+ i++;
+ for (; i < r.length; i++) {
+ es= r[i];
+ try {
+ if (leftLine != leftDoc.getLineOfOffset(leftStart+sy.getTokenStart(es.leftStart())))
+ break;
+ if (rightLine != rightDoc.getLineOfOffset(rightStart+sm.getTokenStart(es.rightStart())))
+ break;
+ } catch (BadLocationException e) {
+ // silently ignored
+ }
+ }
+ int end= i;
+
+ // find first diff from left
+ RangeDifference first= null;
+ for (int ii= start; ii < end; ii++) {
+ es= r[ii];
+ if (useChange(es.kind())) {
+ first= es;
+ break;
+ }
+ }
+
+ // find first diff from mine
+ RangeDifference last= null;
+ for (int ii= end-1; ii >= start; ii--) {
+ es= r[ii];
+ if (useChange(es.kind())) {
+ last= es;
+ break;
+ }
+ }
+
+ if (first != null && last != null) {
+
+ int ancestorStart2= 0;
+ int ancestorEnd2= 0;
+ if (ancestorDoc != null) {
+ ancestorStart2= ancestorStart+sa.getTokenStart(first.ancestorStart());
+ ancestorEnd2= ancestorStart+getTokenEnd(sa, last.ancestorStart(), last.ancestorLength());
+ }
+
+ int leftStart2= leftStart+sy.getTokenStart(first.leftStart());
+ int leftEnd2= leftStart+getTokenEnd(sy, last.leftStart(), last.leftLength());
+
+ int rightStart2= rightStart+sm.getTokenStart(first.rightStart());
+ int rightEnd2= rightStart+getTokenEnd(sm, last.rightStart(), last.rightLength());
+ Diff diff= new Diff(baseDiff, first.kind(),
+ ancestorDoc, null, ancestorStart2, ancestorEnd2,
+ leftDoc, null, leftStart2, leftEnd2,
+ rightDoc, null, rightStart2, rightEnd2);
+ diff.fIsToken= true;
+ baseDiff.add(diff);
+ }
+ }
+ }
+
+ /*
+ * Performs a token based 3-way diff on the character range specified by the given baseDiff.
+ */
+ private void simpleTokenDiff(final Diff baseDiff,
+ IDocument ancestorDoc, String a,
+ IDocument rightDoc, String d,
+ IDocument leftDoc, String s) {
+
+ int ancestorStart= 0;
+ ITokenComparator sa= null;
+ if (ancestorDoc != null) {
+ ancestorStart= baseDiff.fAncestorPos.getOffset();
+ sa= createTokenComparator(a);
+ }
+
+ int rightStart= baseDiff.fRightPos.getOffset();
+ ITokenComparator sm= createTokenComparator(d);
+
+ int leftStart= baseDiff.fLeftPos.getOffset();
+ ITokenComparator sy= createTokenComparator(s);
+
+ RangeDifference[] e= RangeDifferencer.findRanges(sa, sy, sm);
+ for (int i= 0; i < e.length; i++) {
+ RangeDifference es= e[i];
+ int kind= es.kind();
+ if (kind != RangeDifference.NOCHANGE) {
+
+ int ancestorStart2= ancestorStart;
+ int ancestorEnd2= ancestorStart;
+ if (ancestorDoc != null) {
+ ancestorStart2 += sa.getTokenStart(es.ancestorStart());
+ ancestorEnd2 += getTokenEnd(sa, es.ancestorStart(), es.ancestorLength());
+ }
+
+ int leftStart2= leftStart + sy.getTokenStart(es.leftStart());
+ int leftEnd2= leftStart + getTokenEnd(sy, es.leftStart(), es.leftLength());
+
+ int rightStart2= rightStart + sm.getTokenStart(es.rightStart());
+ int rightEnd2= rightStart + getTokenEnd(sm, es.rightStart(), es.rightLength());
+
+ Diff diff= new Diff(baseDiff, kind,
+ ancestorDoc, null, ancestorStart2, ancestorEnd2,
+ leftDoc, null, leftStart2, leftEnd2,
+ rightDoc, null, rightStart2, rightEnd2);
+
+ // ensure that token diff is smaller than basediff
+ int leftS= baseDiff.fLeftPos.offset;
+ int leftE= baseDiff.fLeftPos.offset+baseDiff.fLeftPos.length;
+ int rightS= baseDiff.fRightPos.offset;
+ int rightE= baseDiff.fRightPos.offset+baseDiff.fRightPos.length;
+ if (leftS != leftStart2 || leftE != leftEnd2 ||
+ rightS != rightStart2 || rightE != rightEnd2) {
+ diff.fIsToken= true;
+ // add to base Diff
+ baseDiff.add(diff);
+ }
+ }
+ }
+ }
+
+ private ITokenComparator createTokenComparator(String s) {
+ return fInput.createTokenComparator(s);
+ }
+
+ private static int maxWork(IRangeComparator a, IRangeComparator l, IRangeComparator r) {
+ int ln= l.getRangeCount();
+ int rn= r.getRangeCount();
+ if (a != null) {
+ int an= a.getRangeCount();
+ return (2 * Math.max(an, ln)) + (2 * Math.max(an, rn));
+ }
+ return 2 * Math.max(ln, rn);
+ }
+
+ private void resetPositions(IDocument doc) {
+ if (doc == null)
+ return;
+ try {
+ doc.removePositionCategory(DIFF_RANGE_CATEGORY);
+ } catch (BadPositionCategoryException e) {
+ // Ignore
+ }
+ doc.addPositionCategory(DIFF_RANGE_CATEGORY);
+ }
+
+ /*
+ * Returns the start line and the number of lines which correspond to the given position.
+ * Starting line number is 0 based.
+ */
+ protected Point getLineRange(IDocument doc, Position p, Point region) {
+
+ if (p == null || doc == null) {
+ region.x= 0;
+ region.y= 0;
+ return region;
+ }
+
+ int start= p.getOffset();
+ int length= p.getLength();
+
+ int startLine= 0;
+ try {
+ startLine= doc.getLineOfOffset(start);
+ } catch (BadLocationException e) {
+ // silently ignored
+ }
+
+ int lineCount= 0;
+
+ if (length == 0) {
+// // if range length is 0 and if range starts a new line
+// try {
+// if (start == doc.getLineStartOffset(startLine)) {
+// lines--;
+// }
+// } catch (BadLocationException e) {
+// lines--;
+// }
+
+ } else {
+ int endLine= 0;
+ try {
+ endLine= doc.getLineOfOffset(start + length - 1); // why -1?
+ } catch (BadLocationException e) {
+ // silently ignored
+ }
+ lineCount= endLine-startLine+1;
+ }
+
+ region.x= startLine;
+ region.y= lineCount;
+ return region;
+ }
+
+ public Diff findDiff(Position p, boolean left) {
+ for (Iterator iterator = fAllDiffs.iterator(); iterator.hasNext();) {
+ Diff diff = (Diff) iterator.next();
+ Position diffPos;
+ if (left) {
+ diffPos = diff.fLeftPos;
+ } else {
+ diffPos = diff.fRightPos;
+ }
+ // If the element falls within a diff, highlight that diff
+ if (diffPos.offset + diffPos.length >= p.offset && diff.fDirection != RangeDifference.NOCHANGE)
+ return diff;
+ // Otherwise, highlight the first diff after the elements position
+ if (diffPos.offset >= p.offset)
+ return diff;
+ }
+ return null;
+ }
+
+ public void reset() {
+ fChangeDiffs= null;
+ fAllDiffs= null;
+ }
+
+ /**
+ * Returns the virtual position for the given view position.
+ * @param contributor
+ * @param vpos
+ * @return the virtual position for the given view position
+ */
+ public int realToVirtualPosition(char contributor, int vpos) {
+
+ if (fAllDiffs == null)
+ return vpos;
+
+ int viewPos= 0; // real view position
+ int virtualPos= 0; // virtual position
+ Point region= new Point(0, 0);
+
+ Iterator e= fAllDiffs.iterator();
+ while (e.hasNext()) {
+ Diff diff= (Diff) e.next();
+ Position pos= diff.getPosition(contributor);
+ getLineRange(getDocument(contributor),pos, region);
+ int realHeight= region.y;
+ int virtualHeight= diff.getMaxDiffHeight();
+ if (vpos <= viewPos + realHeight) { // OK, found!
+ vpos-= viewPos; // make relative to this slot
+ // now scale position within this slot to virtual slot
+ if (realHeight <= 0)
+ vpos= 0;
+ else
+ vpos= (vpos*virtualHeight)/realHeight;
+ return virtualPos+vpos;
+ }
+ viewPos+= realHeight;
+ virtualPos+= virtualHeight;
+ }
+ return virtualPos;
+ }
+
+ /**
+ * maps given virtual position into a real view position of this view.
+ * @param contributor
+ * @param v
+ * @return the real view position
+ */
+ public int virtualToRealPosition(char contributor, int v) {
+
+ if (fAllDiffs == null)
+ return v;
+
+ int virtualPos= 0;
+ int viewPos= 0;
+ Point region= new Point(0, 0);
+
+ Iterator e= fAllDiffs.iterator();
+ while (e.hasNext()) {
+ Diff diff= (Diff) e.next();
+ Position pos= diff.getPosition(contributor);
+ int viewHeight= getLineRange(getDocument(contributor), pos, region).y;
+ int virtualHeight= diff.getMaxDiffHeight();
+ if (v < (virtualPos + virtualHeight)) {
+ v-= virtualPos; // make relative to this slot
+ if (viewHeight <= 0) {
+ v= 0;
+ } else {
+ v= (int) (v * ((double)viewHeight/virtualHeight));
+ }
+ return viewPos+v;
+ }
+ virtualPos+= virtualHeight;
+ viewPos+= viewHeight;
+ }
+ return viewPos;
+ }
+
+ /*
+ * Calculates virtual height (in lines) of views by adding the maximum of corresponding diffs.
+ */
+ public int getVirtualHeight() {
+ int h= 1;
+ if (fAllDiffs != null) {
+ Iterator e= fAllDiffs.iterator();
+ for (int i= 0; e.hasNext(); i++) {
+ Diff diff= (Diff) e.next();
+ h+= diff.getMaxDiffHeight();
+ }
+ }
+ return h;
+ }
+
+ /*
+ * Calculates height (in lines) of right view by adding the height of the right diffs.
+ */
+ public int getRightHeight() {
+ int h= 1;
+ if (fAllDiffs != null) {
+ Iterator e= fAllDiffs.iterator();
+ for (int i= 0; e.hasNext(); i++) {
+ Diff diff= (Diff) e.next();
+ h+= diff.getRightHeight();
+ }
+ }
+ return h;
+ }
+
+ public int findInsertionPoint(Diff diff, char type) {
+ if (diff != null) {
+ switch (type) {
+ case MergeViewerContentProvider.ANCESTOR_CONTRIBUTOR:
+ if (diff.fAncestorPos != null)
+ return diff.fAncestorPos.offset;
+ break;
+ case MergeViewerContentProvider.LEFT_CONTRIBUTOR:
+ if (diff.fLeftPos != null)
+ return diff.fLeftPos.offset;
+ break;
+ case MergeViewerContentProvider.RIGHT_CONTRIBUTOR:
+ if (diff.fRightPos != null)
+ return diff.fRightPos.offset;
+ break;
+ }
+ }
+ return 0;
+ }
+
+ public Diff[] getChangeDiffs(char contributor, IRegion region) {
+ if (fChangeDiffs == null)
+ return new Diff[0];
+ List intersectingDiffs = new ArrayList();
+ for (Iterator iterator = fChangeDiffs.iterator(); iterator.hasNext();) {
+ Diff diff = (Diff) iterator.next();
+ Diff[] changeDiffs = diff.getChangeDiffs(contributor, region);
+ for (int i = 0; i < changeDiffs.length; i++) {
+ Diff changeDiff = changeDiffs[i];
+ intersectingDiffs.add(changeDiff);
+ }
+ }
+ return (Diff[]) intersectingDiffs.toArray(new Diff[intersectingDiffs.size()]);
+ }
+
+ public Diff findDiff(int viewportHeight, boolean synchronizedScrolling, Point size, int my) {
+ int virtualHeight= synchronizedScrolling ? getVirtualHeight() : getRightHeight();
+ if (virtualHeight < viewportHeight)
+ return null;
+
+ int yy, hh;
+ int y= 0;
+ if (fAllDiffs != null) {
+ Iterator e= fAllDiffs.iterator();
+ for (int i= 0; e.hasNext(); i++) {
+ Diff diff= (Diff) e.next();
+ int h= synchronizedScrolling ? diff.getMaxDiffHeight()
+ : diff.getRightHeight();
+ if (useChange(diff.getKind()) && !diff.fIsWhitespace) {
+
+ yy= (y*size.y)/virtualHeight;
+ hh= (h*size.y)/virtualHeight;
+ if (hh < 3)
+ hh= 3;
+
+ if (my >= yy && my < yy+hh)
+ return diff;
+ }
+ y+= h;
+ }
+ }
+ return null;
+ }
+
+ public boolean hasChanges() {
+ return fChangeDiffs != null && !fChangeDiffs.isEmpty();
+ }
+
+ public Iterator changesIterator() {
+ if (fChangeDiffs == null)
+ return new ArrayList().iterator();
+ return fChangeDiffs.iterator();
+ }
+
+ public Iterator rangesIterator() {
+ if (fAllDiffs == null)
+ return new ArrayList().iterator();
+ return fAllDiffs.iterator();
+ }
+
+ public boolean isFirstChildDiff(char contributor, int startOffset,
+ Diff diff) {
+ if (!diff.hasChildren())
+ return false;
+ Diff d = (Diff)diff.fDiffs.get(0);
+ Position p= d.getPosition(contributor);
+ return (p.getOffset() >= startOffset);
+ }
+
+ public Diff getWrappedDiff(Diff diff, boolean down) {
+ if (fChangeDiffs != null && fChangeDiffs.size() > 0) {
+ if (down)
+ return (Diff) fChangeDiffs.get(0);
+ return (Diff) fChangeDiffs.get(fChangeDiffs.size()-1);
+ }
+ return null;
+ }
+
+ /*
+ * Copy the contents of the given diff from one side to the other but
+ * doesn't reveal anything.
+ * Returns true if copy was successful.
+ */
+ public boolean copy(Diff diff, boolean leftToRight) {
+
+ if (diff != null && !diff.isResolved()) {
+ Position fromPos= null;
+ Position toPos= null;
+ IDocument fromDoc= null;
+ IDocument toDoc= null;
+
+ if (leftToRight) {
+ fromPos= diff.getPosition(MergeViewerContentProvider.LEFT_CONTRIBUTOR);
+ toPos= diff.getPosition(MergeViewerContentProvider.RIGHT_CONTRIBUTOR);
+ fromDoc= getDocument(MergeViewerContentProvider.LEFT_CONTRIBUTOR);
+ toDoc= getDocument(MergeViewerContentProvider.RIGHT_CONTRIBUTOR);
+ } else {
+ fromPos= diff.getPosition(MergeViewerContentProvider.RIGHT_CONTRIBUTOR);
+ toPos= diff.getPosition(MergeViewerContentProvider.LEFT_CONTRIBUTOR);
+ fromDoc= getDocument(MergeViewerContentProvider.RIGHT_CONTRIBUTOR);
+ toDoc= getDocument(MergeViewerContentProvider.LEFT_CONTRIBUTOR);
+ }
+
+ if (fromDoc != null) {
+
+ int fromStart= fromPos.getOffset();
+ int fromLen= fromPos.getLength();
+
+ int toStart= toPos.getOffset();
+ int toLen= toPos.getLength();
+
+ try {
+ String s= null;
+
+ switch (diff.getKind()) {
+ case RangeDifference.RIGHT:
+ case RangeDifference.LEFT:
+ s= fromDoc.get(fromStart, fromLen);
+ break;
+ case RangeDifference.ANCESTOR:
+ break;
+ case RangeDifference.CONFLICT:
+ if (APPEND_CONFLICT) {
+ s= toDoc.get(toStart, toLen);
+ s+= fromDoc.get(fromStart, fromLen);
+ } else
+ s= fromDoc.get(fromStart, fromLen);
+ break;
+ }
+ if (s != null) {
+ toDoc.replace(toStart, toLen, s);
+ toPos.setOffset(toStart);
+ toPos.setLength(s.length());
+ }
+
+ } catch (BadLocationException e) {
+ // silently ignored
+ }
+ }
+
+ diff.setResolved(true);
+ return true;
+ }
+ return false;
+ }
+
+ public int changesCount() {
+ if (fChangeDiffs == null)
+ return 0;
+ return fChangeDiffs.size();
+ }
+
+ public Diff findDiff(char contributor, int rangeStart, int rangeEnd) {
+ if (hasChanges()) {
+ for (Iterator iterator = changesIterator(); iterator.hasNext();) {
+ Diff diff = (Diff) iterator.next();
+ if (diff.isDeleted() || diff.getKind() == RangeDifference.NOCHANGE)
+ continue;
+ if (diff.overlaps(contributor, rangeStart, rangeEnd))
+ return diff;
+ }
+ }
+ return null;
+ }
+
+ public Diff findDiff(char contributor, Position range) {
+ int start= range.getOffset();
+ int end= start + range.getLength();
+ return findDiff(contributor, start, end);
+ }
+
+ public Diff findNext(char contributor, int start, int end, boolean deep) {
+ return findNext(contributor, fChangeDiffs, start, end, deep);
+ }
+
+ private Diff findNext(char contributor, List v, int start, int end, boolean deep) {
+ if (v == null)
+ return null;
+ for (int i= 0; i < v.size(); i++) {
+ Diff diff= (Diff) v.get(i);
+ Position p= diff.getPosition(contributor);
+ if (p != null) {
+ int startOffset= p.getOffset();
+ if (end < startOffset) // <=
+ return diff;
+ if (deep && diff.hasChildren()) {
+ Diff d= null;
+ int endOffset= startOffset + p.getLength();
+ if (start == startOffset && (end == endOffset || end == endOffset-1)) {
+ d= findNext(contributor, diff.fDiffs, start-1, start-1, deep);
+ } else if (end < endOffset) {
+ d= findNext(contributor, diff.fDiffs, start, end, deep);
+ }
+ if (d != null)
+ return d;
+ }
+ }
+ }
+ return null;
+ }
+
+ public Diff findPrev(char contributor, int start, int end, boolean deep) {
+ return findPrev(contributor, fChangeDiffs, start, end, deep);
+ }
+
+ private Diff findPrev(char contributor, List v, int start, int end, boolean deep) {
+ if (v == null)
+ return null;
+ for (int i= v.size()-1; i >= 0; i--) {
+ Diff diff= (Diff) v.get(i);
+ Position p= diff.getPosition(contributor);
+ if (p != null) {
+ int startOffset= p.getOffset();
+ int endOffset= startOffset + p.getLength();
+ if (start > endOffset) {
+ if (deep && diff.hasChildren()) {
+ // If we are going deep, find the last change in the diff
+ return findPrev(contributor, diff.fDiffs, end, end, deep);
+ }
+ return diff;
+ }
+ if (deep && diff.hasChildren()) {
+ Diff d= null;
+ if (start == startOffset && end == endOffset) {
+ // A whole diff is selected so we'll fall through
+ // and go the the last change in the previous diff
+ } else if (start >= startOffset) {
+ // If we are at or before the first diff, select the
+ // entire diff so next and previous are symmetrical
+ if (isFirstChildDiff(contributor, startOffset, diff)) {
+ return diff;
+ }
+ d= findPrev(contributor, diff.fDiffs, start, end, deep);
+ }
+ if (d != null)
+ return d;
+ }
+ }
+ }
+ return null;
+ }
+
+}
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/contentmergeviewer/TextMergeViewer.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/contentmergeviewer/TextMergeViewer.java
index 9cb18d1f9..659dee757 100644
--- a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/contentmergeviewer/TextMergeViewer.java
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/contentmergeviewer/TextMergeViewer.java
@@ -19,12 +19,14 @@ package org.eclipse.compare.contentmergeviewer;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.util.*;
-import java.util.List;
import org.eclipse.compare.*;
import org.eclipse.compare.internal.*;
+import org.eclipse.compare.internal.merge.DocumentMerger;
+import org.eclipse.compare.internal.merge.DocumentMerger.Diff;
+import org.eclipse.compare.internal.merge.DocumentMerger.IDocumentMergerInput;
import org.eclipse.compare.patch.IHunk;
-import org.eclipse.compare.rangedifferencer.*;
+import org.eclipse.compare.rangedifferencer.RangeDifference;
import org.eclipse.compare.structuremergeviewer.*;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.*;
@@ -32,7 +34,6 @@ import org.eclipse.core.runtime.Assert;
import org.eclipse.jface.action.*;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.MessageDialog;
-import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.resource.ColorRegistry;
import org.eclipse.jface.resource.JFaceResources;
@@ -54,7 +55,6 @@ import org.eclipse.swt.graphics.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.ui.*;
import org.eclipse.ui.actions.ActionFactory;
-import org.eclipse.ui.progress.IProgressService;
import org.eclipse.ui.texteditor.*;
import com.ibm.icu.text.MessageFormat;
@@ -161,13 +161,9 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
private static final int BIRDS_EYE_VIEW_INSET= 2;
/** */
private static final int RESOLVE_SIZE= 5;
- /** if true copying conflicts from one side to other concatenates both sides */
- private static final boolean APPEND_CONFLICT= true;
/** line width of change borders */
private static final int LW= 1;
- /** Selects between smartTokenDiff and mergingTokenDiff */
- private static final boolean USE_MERGING_TOKEN_DIFF= false;
// determines whether a change between left and right is considered incoming or outgoing
private boolean fLeftIsLocal;
@@ -202,13 +198,6 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
private IPreferenceStore fPreferenceStore;
private IPropertyChangeListener fPreferenceChangeListener;
- /** All diffs for calculating scrolling position (includes line ranges without changes) */
- private ArrayList fAllDiffs;
- /** Subset of above: just real differences. */
- private ArrayList fChangeDiffs;
- /** The current diff */
- private Diff fCurrentDiff;
-
private HashMap fNewAncestorRanges= new HashMap();
private HashMap fNewLeftRanges= new HashMap();
private HashMap fNewRightRanges= new HashMap();
@@ -291,6 +280,9 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
private TextEditorPropertyAction toggleLineNumbersAction;
private IFindReplaceTarget fFindReplaceTarget;
private ChangePropertyAction fIgnoreWhitespace;
+ private DocumentMerger fMerger;
+ /** The current diff */
+ private Diff fCurrentDiff;
private final class InternalOutlineViewerCreator extends OutlineViewerCreator implements ISelectionChangedListener {
public Viewer findStructureViewer(Viewer oldViewer,
@@ -340,16 +332,16 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
}
private Diff findDiff(Position p, boolean left) {
- for (Iterator iterator = fAllDiffs.iterator(); iterator.hasNext();) {
+ for (Iterator iterator = fMerger.rangesIterator(); iterator.hasNext();) {
Diff diff = (Diff) iterator.next();
Position diffPos;
if (left) {
- diffPos = diff.fLeftPos;
+ diffPos = diff.getPosition(LEFT_CONTRIBUTOR);
} else {
- diffPos = diff.fRightPos;
+ diffPos = diff.getPosition(RIGHT_CONTRIBUTOR);
}
// If the element falls within a diff, highlight that diff
- if (diffPos.offset + diffPos.length >= p.offset && diff.fDirection != RangeDifference.NOCHANGE)
+ if (diffPos.offset + diffPos.length >= p.offset && diff.getKind() != RangeDifference.NOCHANGE)
return diff;
// Otherwise, highlight the first diff after the elements position
if (diffPos.offset >= p.offset)
@@ -1028,276 +1020,36 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
}
}
- /*
- * A Diff represents synchronized character ranges in two or three Documents.
- * The MergeTextViewer uses Diffs to find differences in line and token ranges.
- */
- /* package */ class Diff {
- /** character range in ancestor document */
- Position fAncestorPos;
- /** character range in left document */
- Position fLeftPos;
- /** character range in right document */
- Position fRightPos;
- /** if this is a TokenDiff fParent points to the enclosing LineDiff */
- Diff fParent;
- /** if Diff has been resolved */
- boolean fResolved;
- int fDirection;
- boolean fIsToken= false;
- /** child token diffs */
- ArrayList fDiffs;
- boolean fIsWhitespace= false;
+ private class ChangeHighlighter implements ITextPresentationListener {
- /*
- * Create Diff from two ranges and an optional parent diff.
- */
- Diff(Diff parent, int dir, IDocument ancestorDoc, Position aRange, int ancestorStart, int ancestorEnd,
- IDocument leftDoc, Position lRange, int leftStart, int leftEnd,
- IDocument rightDoc, Position rRange, int rightStart, int rightEnd) {
- fParent= parent != null ? parent : this;
- fDirection= dir;
-
- fLeftPos= createPosition(leftDoc, lRange, leftStart, leftEnd);
- fRightPos= createPosition(rightDoc, rRange, rightStart, rightEnd);
- if (ancestorDoc != null)
- fAncestorPos= createPosition(ancestorDoc, aRange, ancestorStart, ancestorEnd);
- }
-
- Position getPosition(char type) {
- switch (type) {
- case ANCESTOR_CONTRIBUTOR:
- return fAncestorPos;
- case LEFT_CONTRIBUTOR:
- return fLeftPos;
- case RIGHT_CONTRIBUTOR:
- return fRightPos;
- }
- return null;
- }
-
- boolean isInRange(char type, int pos) {
- Position p= getPosition(type);
- return (pos >= p.offset) && (pos < (p.offset+p.length));
- }
-
- String changeType() {
- boolean leftEmpty= fLeftPos.length == 0;
- boolean rightEmpty= fRightPos.length == 0;
-
- if (fDirection == RangeDifference.LEFT) {
- if (!leftEmpty && rightEmpty)
- return CompareMessages.TextMergeViewer_changeType_addition;
- if (leftEmpty && !rightEmpty)
- return CompareMessages.TextMergeViewer_changeType_deletion;
- } else {
- if (leftEmpty && !rightEmpty)
- return CompareMessages.TextMergeViewer_changeType_addition;
- if (!leftEmpty && rightEmpty)
- return CompareMessages.TextMergeViewer_changeType_deletion;
- }
- return CompareMessages.TextMergeViewer_changeType_change;
- }
-
- Image getImage() {
- int code= Differencer.CHANGE;
- switch (fDirection) {
- case RangeDifference.RIGHT:
- code+= Differencer.LEFT;
- break;
- case RangeDifference.LEFT:
- code+= Differencer.RIGHT;
- break;
- case RangeDifference.ANCESTOR:
- case RangeDifference.CONFLICT:
- code+= Differencer.CONFLICTING;
- break;
- }
- if (code != 0)
- return getCompareConfiguration().getImage(code);
- return null;
- }
-
- Position createPosition(IDocument doc, Position range, int start, int end) {
- try {
- int l= end-start;
- if (range != null) {
- int dl= range.length;
- if (l > dl)
- l= dl;
- } else {
- int dl= doc.getLength();
- if (start+l > dl)
- l= dl-start;
- }
-
- Position p= null;
- try {
- p= new Position(start, l);
- } catch (RuntimeException ex) {
- p= new Position(0, 0);
- }
-
- try {
- doc.addPosition(DIFF_RANGE_CATEGORY, p);
- } catch (BadPositionCategoryException ex) {
- // silently ignored
- }
- return p;
- } catch (BadLocationException ee) {
- // silently ignored
- }
- return null;
- }
+ private final MergeSourceViewer viewer;
- void add(Diff d) {
- if (fDiffs == null)
- fDiffs= new ArrayList();
- fDiffs.add(d);
- }
-
- boolean isDeleted() {
- if (fAncestorPos != null && fAncestorPos.isDeleted())
- return true;
- return fLeftPos.isDeleted() || fRightPos.isDeleted();
- }
-
- void setResolved(boolean r) {
- fResolved= r;
- if (r)
- fDiffs= null;
+ public ChangeHighlighter(MergeSourceViewer viewer) {
+ this.viewer = viewer;
}
- boolean isResolved() {
- if (!fResolved && fDiffs != null) {
- Iterator e= fDiffs.iterator();
- while (e.hasNext()) {
- Diff d= (Diff) e.next();
- if (!d.isResolved())
- return false;
- }
- return true;
- }
- return fResolved;
- }
-
-// private boolean isIncoming() {
-// switch (fDirection) {
-// case RangeDifference.RIGHT:
-// if (fLeftIsLocal)
-// return true;
-// break;
-// case RangeDifference.LEFT:
-// if (!fLeftIsLocal)
-// return true;
-// break;
-// }
-// return false;
-// }
-
- private boolean isIncomingOrConflicting() {
- switch (fDirection) {
- case RangeDifference.RIGHT:
- if (fLeftIsLocal)
- return true;
- break;
- case RangeDifference.LEFT:
- if (!fLeftIsLocal)
- return true;
- break;
- case RangeDifference.CONFLICT:
- return true;
- }
- return false;
- }
-
-// private boolean isUnresolvedIncoming() {
-// if (fResolved)
-// return false;
-// return isIncoming();
-// }
-
- private boolean isUnresolvedIncomingOrConflicting() {
- if (fResolved)
- return false;
- return isIncomingOrConflicting();
- }
-
- Position getPosition(MergeSourceViewer w) {
- if (w == fLeft)
- return fLeftPos;
- if (w == fRight)
- return fRightPos;
- if (w == fAncestor)
- return fAncestorPos;
- return null;
- }
-
- /*
- * Returns true if given character range overlaps with this Diff.
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.text.ITextPresentationListener#applyTextPresentation(org.eclipse.jface.text.TextPresentation)
*/
- boolean overlaps(MergeSourceViewer w, int start, int end) {
- Position h= getPosition(w);
- if (h != null) {
- int ds= h.getOffset();
- int de= ds + h.getLength();
- if ((start < de) && (end >= ds))
- return true;
- }
- return false;
- }
-
- int getMaxDiffHeight() {
- Point region= new Point(0, 0);
- int h= fLeft.getLineRange(fLeftPos, region).y;
- if (isThreeWay())
- h= Math.max(h, fAncestor.getLineRange(fAncestorPos, region).y);
- return Math.max(h, fRight.getLineRange(fRightPos, region).y);
- }
-
- int getAncestorHeight() {
- Point region= new Point(0, 0);
- return fAncestor.getLineRange(fAncestorPos, region).y;
- }
-
- int getLeftHeight() {
- Point region= new Point(0, 0);
- return fLeft.getLineRange(fLeftPos, region).y;
- }
-
- int getRightHeight() {
- Point region= new Point(0, 0);
- return fRight.getLineRange(fRightPos, region).y;
- }
-
- public Diff[] getChangeDiffs(MergeSourceViewer viewer, IRegion region) {
- if (fDiffs != null && intersectsRegion(viewer, region)) {
- List result = new ArrayList();
- for (Iterator iterator = fDiffs.iterator(); iterator.hasNext();) {
- Diff diff = (Diff) iterator.next();
- if (diff.intersectsRegion(viewer, region)) {
- result.add(diff);
- }
- }
- return (Diff[]) result.toArray(new Diff[result.size()]);
+ public void applyTextPresentation(TextPresentation textPresentation) {
+ if (!fHighlightTokenChanges)
+ return;
+ IRegion region= textPresentation.getExtent();
+ Diff[] changeDiffs = fMerger.getChangeDiffs(getLeg(viewer), region);
+ for (int i = 0; i < changeDiffs.length; i++) {
+ Diff diff = changeDiffs[i];
+ StyleRange range = getStyleRange(diff, region);
+ if (range != null)
+ textPresentation.mergeStyleRange(range);
}
- return new Diff[0];
- }
-
- private boolean intersectsRegion(MergeSourceViewer viewer,
- IRegion region) {
- Position p = getPosition(viewer);
- if (p != null)
- return p.overlapsWith(region.getOffset(), region.getLength());
- return false;
}
- public StyleRange getStyleRange(MergeSourceViewer viewer, IRegion region) {
+ private StyleRange getStyleRange(Diff diff, IRegion region) {
//Color cText = getColor(null, getTextColor());
- Color cTextFill = getColor(null, getTextFillColor());
+ Color cTextFill = getColor(null, getTextFillColor(diff));
if (cTextFill == null)
return null;
- Position p = getPosition(viewer);
+ Position p = diff.getPosition(getLeg(viewer));
int start = p.getOffset();
int length = p.getLength();
// Don't start before the region
@@ -1316,9 +1068,9 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
return new StyleRange(start, length, null, cTextFill);
}
- private RGB getTextFillColor() {
+ private RGB getTextFillColor(Diff diff) {
if (isThreeWay() && !isIgnoreAncestor()) {
- switch (fDirection) {
+ switch (diff.getKind()) {
case RangeDifference.RIGHT:
if (fLeftIsLocal)
return INCOMING_TEXT_FILL;
@@ -1336,54 +1088,6 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
}
return OUTGOING_TEXT_FILL;
}
-
- public boolean hasChildren() {
- return fDiffs != null && !fDiffs.isEmpty();
- }
- }
-
- private class ChangeHighlighter implements ITextPresentationListener {
-
- private final MergeSourceViewer viewer;
-
- public ChangeHighlighter(MergeSourceViewer viewer) {
- this.viewer = viewer;
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.jface.text.ITextPresentationListener#applyTextPresentation(org.eclipse.jface.text.TextPresentation)
- */
- public void applyTextPresentation(TextPresentation textPresentation) {
- if (!fHighlightTokenChanges)
- return;
- IRegion region= textPresentation.getExtent();
- Diff[] changeDiffs = getChangeDiffs(region);
- for (int i = 0; i < changeDiffs.length; i++) {
- Diff diff = changeDiffs[i];
- StyleRange range = getStyleRange(diff, region);
- if (range != null)
- textPresentation.mergeStyleRange(range);
- }
- }
-
- private StyleRange getStyleRange(Diff diff, IRegion region) {
- return diff.getStyleRange(viewer, region);
- }
-
- private Diff[] getChangeDiffs(IRegion region) {
- if (fChangeDiffs == null)
- return new Diff[0];
- List intersectingDiffs = new ArrayList();
- for (Iterator iterator = fChangeDiffs.iterator(); iterator.hasNext();) {
- Diff diff = (Diff) iterator.next();
- Diff[] changeDiffs = diff.getChangeDiffs(viewer, region);
- for (int i = 0; i < changeDiffs.length; i++) {
- Diff changeDiff = changeDiffs[i];
- intersectingDiffs.add(changeDiff);
- }
- }
- return (Diff[]) intersectingDiffs.toArray(new Diff[intersectingDiffs.size()]);
- }
}
@@ -1438,6 +1142,58 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
public TextMergeViewer(Composite parent, int style, CompareConfiguration configuration) {
super(style, ResourceBundle.getBundle(BUNDLE_NAME), configuration);
+ fMerger = new DocumentMerger(new IDocumentMergerInput() {
+ public ITokenComparator createTokenComparator(String line) {
+ return TextMergeViewer.this.createTokenComparator(line);
+ }
+ public CompareConfiguration getCompareConfiguration() {
+ return TextMergeViewer.this.getCompareConfiguration();
+ }
+ public IDocument getDocument(char contributor) {
+ switch (contributor) {
+ case LEFT_CONTRIBUTOR:
+ return fLeft.getDocument();
+ case RIGHT_CONTRIBUTOR:
+ return fRight.getDocument();
+ case ANCESTOR_CONTRIBUTOR:
+ return fAncestor.getDocument();
+ }
+ return null;
+ }
+ public int getHunkStart() {
+ return TextMergeViewer.this.getHunkStart();
+ }
+ public Position getRegion(char contributor) {
+ switch (contributor) {
+ case LEFT_CONTRIBUTOR:
+ return fLeft.getRegion();
+ case RIGHT_CONTRIBUTOR:
+ return fRight.getRegion();
+ case ANCESTOR_CONTRIBUTOR:
+ return fAncestor.getRegion();
+ }
+ return null;
+ }
+ public boolean isHunkOnLeft() {
+ ITypedElement left = ((ICompareInput)getInput()).getRight();
+ return left != null && Utilities.getAdapter(left, IHunk.class) != null;
+ }
+ public boolean isIgnoreAncestor() {
+ return TextMergeViewer.this.isIgnoreAncestor();
+ }
+ public boolean isPatchHunk() {
+ return TextMergeViewer.this.isPatchHunk();
+ }
+
+ public boolean isShowPseudoConflicts() {
+ return fShowPseudoConflicts;
+ }
+ public boolean isThreeWay() {
+ return TextMergeViewer.this.isThreeWay();
+ }
+
+ });
+
int inheritedStyle= parent.getStyle();
if ((inheritedStyle & SWT.LEFT_TO_RIGHT) != 0)
fInheritedDirection= SWT.LEFT_TO_RIGHT;
@@ -1952,7 +1708,7 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
public void mouseMove(MouseEvent e) {
Cursor cursor= null;
Diff diff= handlemouseInBirdsEyeView(fBirdsEyeCanvas, e.y);
- if (diff != null && diff.fDirection != RangeDifference.NOCHANGE)
+ if (diff != null && diff.getKind() != RangeDifference.NOCHANGE)
cursor= fBirdsEyeCursor;
if (fLastCursor != cursor) {
fBirdsEyeCanvas.setCursor(cursor);
@@ -1993,7 +1749,7 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
}
private void setCurrentDiff2(Diff diff, boolean reveal) {
- if (diff != null && diff.fDirection != RangeDifference.NOCHANGE) {
+ if (diff != null && diff.getKind() != RangeDifference.NOCHANGE) {
//fCurrentDiff= null;
setCurrentDiff(diff, reveal);
}
@@ -2007,20 +1763,20 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
if (! fHighlightRanges)
return null;
- if (fChangeDiffs != null) {
+ if (fMerger.hasChanges()) {
int shift= tp.getVerticalScrollOffset() + (2-LW);
Point region= new Point(0, 0);
- Iterator e= fChangeDiffs.iterator();
- while (e.hasNext()) {
- Diff diff= (Diff) e.next();
+ char leg = getLeg(tp);
+ for (Iterator iterator = fMerger.changesIterator(); iterator.hasNext();) {
+ Diff diff = (Diff) iterator.next();
if (diff.isDeleted())
continue;
if (fShowCurrentOnly2 && !isCurrentDiff(diff))
continue;
- tp.getLineRange(diff.getPosition(tp), region);
+ tp.getLineRange(diff.getPosition(leg), region);
int y= (region.x * lineHeight) + shift;
int h= region.y * lineHeight;
@@ -2050,26 +1806,25 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
if (! fHighlightRanges)
return null;
- if (fChangeDiffs != null) {
+ if (fMerger.hasChanges()) {
int lshift= fLeft.getVerticalScrollOffset();
int rshift= fRight.getVerticalScrollOffset();
Point region= new Point(0, 0);
- Iterator e= fChangeDiffs.iterator();
- while (e.hasNext()) {
- Diff diff= (Diff) e.next();
+ for (Iterator iterator = fMerger.changesIterator(); iterator.hasNext();) {
+ Diff diff = (Diff) iterator.next();
if (diff.isDeleted())
continue;
if (fShowCurrentOnly2 && !isCurrentDiff(diff))
continue;
- fLeft.getLineRange(diff.fLeftPos, region);
+ fLeft.getLineRange(diff.getPosition(LEFT_CONTRIBUTOR), region);
int ly= (region.x * lineHeight) + lshift;
int lh= region.y * lineHeight;
- fRight.getLineRange(diff.fRightPos, region);
+ fRight.getLineRange(diff.getPosition(RIGHT_CONTRIBUTOR), region);
int ry= (region.x * lineHeight) + rshift;
int rh= region.y * lineHeight;
@@ -2096,35 +1851,7 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
}
private Diff handlemouseInBirdsEyeView(Canvas canvas, int my) {
- int yy, hh;
-
- Point size= canvas.getSize();
-
- int virtualHeight= fSynchronizedScrolling ? getVirtualHeight() : getRightHeight();
- if (virtualHeight < getViewportHeight())
- return null;
-
- int y= 0;
- if (fAllDiffs != null) {
- Iterator e= fAllDiffs.iterator();
- for (int i= 0; e.hasNext(); i++) {
- Diff diff= (Diff) e.next();
- int h= fSynchronizedScrolling ? diff.getMaxDiffHeight()
- : diff.getRightHeight();
- if (useChange(diff.fDirection) && !diff.fIsWhitespace) {
-
- yy= (y*size.y)/virtualHeight;
- hh= (h*size.y)/virtualHeight;
- if (hh < 3)
- hh= 3;
-
- if (my >= yy && my < yy+hh)
- return diff;
- }
- y+= h;
- }
- }
- return null;
+ return fMerger.findDiff(getViewportHeight(), fSynchronizedScrolling, canvas.getSize(), my);
}
private void paintBirdsEyeView(Canvas canvas, GC gc) {
@@ -2135,54 +1862,50 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
Point size= canvas.getSize();
- int virtualHeight= fSynchronizedScrolling ? getVirtualHeight() : getRightHeight();
+ int virtualHeight= fSynchronizedScrolling ? fMerger.getVirtualHeight() : fMerger.getRightHeight();
if (virtualHeight < getViewportHeight())
return;
Display display= canvas.getDisplay();
int y= 0;
- if (fAllDiffs != null) {
- Iterator e= fAllDiffs.iterator();
- for (int i= 0; e.hasNext(); i++) {
- Diff diff= (Diff) e.next();
- int h= fSynchronizedScrolling ? diff.getMaxDiffHeight()
- : diff.getRightHeight();
-
- if (useChange(diff.fDirection) && !diff.fIsWhitespace) {
-
- yy= (y*size.y)/virtualHeight;
- hh= (h*size.y)/virtualHeight;
- if (hh < 3)
- hh= 3;
-
- c= getColor(display, getFillColor(diff));
- if (c != null) {
- gc.setBackground(c);
- gc.fillRectangle(BIRDS_EYE_VIEW_INSET, yy, size.x-(2*BIRDS_EYE_VIEW_INSET),hh);
- }
- c= getColor(display, getStrokeColor(diff));
- if (c != null) {
- gc.setForeground(c);
- r.x= BIRDS_EYE_VIEW_INSET;
- r.y= yy;
- r.width= size.x-(2*BIRDS_EYE_VIEW_INSET)-1;
- r.height= hh;
- if (diff == fCurrentDiff ||
- (fCurrentDiff != null && diff == fCurrentDiff.fParent)) {
- gc.setLineWidth(2);
- r.x++;
- r.y++;
- r.width--;
- r.height--;
- } else {
- gc.setLineWidth(0 /* 1 */);
- }
- gc.drawRectangle(r);
+ for (Iterator iterator = fMerger.rangesIterator(); iterator.hasNext();) {
+ Diff diff = (Diff) iterator.next();
+ int h= fSynchronizedScrolling ? diff.getMaxDiffHeight()
+ : diff.getRightHeight();
+
+ if (fMerger.useChange(diff)) {
+
+ yy= (y*size.y)/virtualHeight;
+ hh= (h*size.y)/virtualHeight;
+ if (hh < 3)
+ hh= 3;
+
+ c= getColor(display, getFillColor(diff));
+ if (c != null) {
+ gc.setBackground(c);
+ gc.fillRectangle(BIRDS_EYE_VIEW_INSET, yy, size.x-(2*BIRDS_EYE_VIEW_INSET),hh);
+ }
+ c= getColor(display, getStrokeColor(diff));
+ if (c != null) {
+ gc.setForeground(c);
+ r.x= BIRDS_EYE_VIEW_INSET;
+ r.y= yy;
+ r.width= size.x-(2*BIRDS_EYE_VIEW_INSET)-1;
+ r.height= hh;
+ if (isCurrentDiff(diff)) {
+ gc.setLineWidth(2);
+ r.x++;
+ r.y++;
+ r.width--;
+ r.height--;
+ } else {
+ gc.setLineWidth(0 /* 1 */);
}
+ gc.drawRectangle(r);
}
-
- y+= h;
}
+
+ y+= h;
}
}
@@ -2257,7 +1980,7 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
setCurrentDiff(fButtonDiff, false);
copy(fCurrentDiff,
fCenterButton.getText().equals(COPY_LEFT_TO_RIGHT_INDICATOR),
- fCurrentDiff.fDirection != RangeDifference.CONFLICT);
+ fCurrentDiff.getKind() != RangeDifference.CONFLICT);
}
}
}
@@ -2651,9 +2374,9 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
Diff selectDiff= null;
if (FIX_47640) {
if (leftRange != null)
- selectDiff= findDiff(LEFT_CONTRIBUTOR, leftRange);
+ selectDiff= fMerger.findDiff(LEFT_CONTRIBUTOR, leftRange);
else if (rightRange != null)
- selectDiff= findDiff(RIGHT_CONTRIBUTOR, rightRange);
+ selectDiff= fMerger.findDiff(RIGHT_CONTRIBUTOR, rightRange);
}
if (selectDiff != null)
setCurrentDiff(selectDiff, true);
@@ -2673,37 +2396,12 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
return new ContributorInfo(this, element, leg);
}
- private Diff findDiff(char c, Position range) {
-
- MergeSourceViewer v;
- int start= range.getOffset();
- int end= start + range.getLength();
- if (c == LEFT_CONTRIBUTOR)
- v= fLeft;
- else if (c == RIGHT_CONTRIBUTOR)
- v= fRight;
- else
- return null;
-
- if (fChangeDiffs != null) {
- Iterator iter= fChangeDiffs.iterator();
- while (iter.hasNext()) {
- Diff diff= (Diff) iter.next();
- if (diff.isDeleted() || diff.fDirection == RangeDifference.NOCHANGE)
- continue;
- if (diff.overlaps(v, start, end))
- return diff;
- }
- }
- return null;
- }
-
private void updateDiffBackground(Diff diff) {
if (! fHighlightRanges)
return;
- if (diff == null || diff.fIsToken)
+ if (diff == null || diff.isToken())
return;
if (fShowCurrentOnly && !isCurrentDiff(diff))
@@ -2714,36 +2412,25 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
return;
if (isThreeWay())
- fAncestor.setLineBackground(diff.fAncestorPos, c);
- fLeft.setLineBackground(diff.fLeftPos, c);
- fRight.setLineBackground(diff.fRightPos, c);
+ fAncestor.setLineBackground(diff.getPosition(ANCESTOR_CONTRIBUTOR), c);
+ fLeft.setLineBackground(diff.getPosition(LEFT_CONTRIBUTOR), c);
+ fRight.setLineBackground(diff.getPosition(RIGHT_CONTRIBUTOR), c);
}
private void updateAllDiffBackgrounds(Display display) {
- if (fChangeDiffs != null) {
+ if (fMerger.hasChanges()) {
boolean threeWay= isThreeWay();
- Iterator iter= fChangeDiffs.iterator();
- while (iter.hasNext()) {
- Diff diff= (Diff) iter.next();
+ for (Iterator iterator = fMerger.changesIterator(); iterator.hasNext();) {
+ Diff diff = (Diff) iterator.next();
Color c= getColor(display, getFillColor(diff));
if (threeWay)
- fAncestor.setLineBackground(diff.fAncestorPos, c);
- fLeft.setLineBackground(diff.fLeftPos, c);
- fRight.setLineBackground(diff.fRightPos, c);
+ fAncestor.setLineBackground(diff.getPosition(ANCESTOR_CONTRIBUTOR), c);
+ fLeft.setLineBackground(diff.getPosition(LEFT_CONTRIBUTOR), c);
+ fRight.setLineBackground(diff.getPosition(RIGHT_CONTRIBUTOR), c);
}
}
}
- boolean isCurrentDiff(Diff diff) {
- if (diff == null)
- return false;
- if (diff == fCurrentDiff)
- return true;
- if (fCurrentDiff != null && fCurrentDiff.fParent == diff)
- return true;
- return false;
- }
-
/*
* Called whenever one of the documents changes.
* Sets the dirty state of this viewer and updates the lines.
@@ -2810,22 +2497,7 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
IDocumentRange dr= (IDocumentRange) other;
Position p= dr.getRange();
Diff diff= findDiff(otherType, p.offset);
- if (diff != null) {
- switch (type) {
- case ANCESTOR_CONTRIBUTOR:
- if (diff.fAncestorPos != null)
- return diff.fAncestorPos.offset;
- break;
- case LEFT_CONTRIBUTOR:
- if (diff.fLeftPos != null)
- return diff.fLeftPos.offset;
- break;
- case RIGHT_CONTRIBUTOR:
- if (diff.fRightPos != null)
- return diff.fRightPos.offset;
- break;
- }
- }
+ return fMerger.findInsertionPoint(diff, type);
}
return 0;
}
@@ -3059,224 +2731,53 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
}
//---- the differencing
-
- private static int maxWork(IRangeComparator a, IRangeComparator l, IRangeComparator r) {
- int ln= l.getRangeCount();
- int rn= r.getRangeCount();
- if (a != null) {
- int an= a.getRangeCount();
- return (2 * Math.max(an, ln)) + (2 * Math.max(an, rn));
- }
- return 2 * Math.max(ln, rn);
- }
/**
* Perform a two level 2- or 3-way diff.
* The first level is based on line comparison, the second level on token comparison.
*/
private void doDiff() {
-
- ArrayList newAllDiffs = new ArrayList();
- fChangeDiffs= new ArrayList();
- fCurrentDiff= null;
-
- IDocument aDoc= null;
IDocument lDoc= fLeft.getDocument();
IDocument rDoc= fRight.getDocument();
if (lDoc == null || rDoc == null)
return;
-
- Position aRegion= null;
- Position lRegion= fLeft.getRegion();
- Position rRegion= fRight.getRegion();
-
- boolean threeWay= isThreeWay();
-
- if (threeWay && !isIgnoreAncestor()) {
- aDoc= fAncestor.getDocument();
- aRegion= fAncestor.getRegion();
- }
-
- resetPositions(lDoc);
- resetPositions(rDoc);
- resetPositions(aDoc);
-
fAncestor.resetLineBackground();
fLeft.resetLineBackground();
fRight.resetLineBackground();
- boolean ignoreWhiteSpace= Utilities.getBoolean(getCompareConfiguration(), CompareConfiguration.IGNORE_WHITESPACE, false);
-
- DocLineComparator sright= new DocLineComparator(rDoc, toRegion(rRegion), ignoreWhiteSpace);
- DocLineComparator sleft= new DocLineComparator(lDoc, toRegion(lRegion), ignoreWhiteSpace);
- DocLineComparator sancestor= null;
- boolean isRight = true;
- if (aDoc != null) {
- sancestor= new DocLineComparator(aDoc, toRegion(aRegion), ignoreWhiteSpace);
- if (isPatchHunk()) {
- ITypedElement right = ((ICompareInput)getInput()).getRight();
- isRight = right != null && Utilities.getAdapter(right, IHunk.class) != null;
- if (isRight) {
- sleft= new DocLineComparator(aDoc, toRegion(aRegion), ignoreWhiteSpace);
- } else {
- sright= new DocLineComparator(aDoc, toRegion(aRegion), ignoreWhiteSpace);
- }
- }
- }
-
- if (!fSubDoc && rRegion != null && lRegion != null) {
- // we have to add a diff for the ignored lines
-
- int astart= 0;
- int as= 0;
- if (aRegion != null) {
- astart= aRegion.getOffset();
- as= Math.max(0, astart-1);
- }
- int ys= Math.max(0, lRegion.getOffset()-1);
- int ms= Math.max(0, rRegion.getOffset()-1);
-
- if (as > 0 || ys > 0 || ms > 0) {
- Diff diff= new Diff(null, RangeDifference.NOCHANGE,
- aDoc, aRegion, 0, astart,
- lDoc, lRegion, 0, lRegion.getOffset(),
- rDoc, rRegion, 0, rRegion.getOffset());
- newAllDiffs.add(diff);
- }
- }
-
- final ResourceBundle bundle= getResourceBundle();
-
- final Object[] result= new Object[1];
- final DocLineComparator sa= sancestor, sl= sleft, sr= sright;
- IRunnableWithProgress runnable= new IRunnableWithProgress() {
- public void run(IProgressMonitor monitor) throws InterruptedException, InvocationTargetException {
- String progressTitle= Utilities.getString(bundle, "compareProgressTask.title"); //$NON-NLS-1$
- monitor.beginTask(progressTitle, maxWork(sa, sl, sr));
- try {
- result[0]= RangeDifferencer.findRanges(monitor, sa, sl, sr);
- } catch (OutOfMemoryError ex) {
- System.gc();
- throw new InvocationTargetException(ex);
- }
- if (monitor.isCanceled()) { // canceled
- throw new InterruptedException();
- }
- monitor.done();
- }
- };
-
- RangeDifference[] e= null;
+ fCurrentDiff= null;
try {
- getCompareConfiguration().getContainer().run(true, true, runnable);
- e= (RangeDifference[]) result[0];
- } catch (InvocationTargetException ex) {
- String title= Utilities.getString(bundle, "tooComplexError.title"); //$NON-NLS-1$
- String format= Utilities.getString(bundle, "tooComplexError.format"); //$NON-NLS-1$
+ fMerger.doDiff();
+ } catch (CoreException e) {
+ CompareUIPlugin.log(e.getStatus());
+ String title= Utilities.getString(getResourceBundle(), "tooComplexError.title"); //$NON-NLS-1$
+ String format= Utilities.getString(getResourceBundle(), "tooComplexError.format"); //$NON-NLS-1$
String msg= MessageFormat.format(format, new Object[] { Integer.toString(PlatformUI.getWorkbench().getProgressService().getLongOperationTime()/1000) } );
MessageDialog.openError(fComposite.getShell(), title, msg);
- e= null;
- } catch (InterruptedException ex) {
- //
}
-
- if (e == null) {
- // we create a NOCHANGE range for the whole document
- Diff diff= new Diff(null, RangeDifference.NOCHANGE,
- aDoc, aRegion, 0, aDoc != null ? aDoc.getLength() : 0,
- lDoc, lRegion, 0, lDoc.getLength(),
- rDoc, rRegion, 0, rDoc.getLength());
-
- newAllDiffs.add(diff);
- } else {
- for (int i= 0; i < e.length; i++) {
- String a= null, s= null, d= null;
- RangeDifference es= e[i];
-
- int kind= es.kind();
-
- int ancestorStart= 0;
- int ancestorEnd= 0;
- if (sancestor != null) {
- ancestorStart= sancestor.getTokenStart(es.ancestorStart());
- ancestorEnd= getTokenEnd2(sancestor, es.ancestorStart(), es.ancestorLength());
- }
-
- int leftStart= sleft.getTokenStart(es.leftStart());
- int leftEnd= getTokenEnd2(sleft, es.leftStart(), es.leftLength());
-
- int rightStart= sright.getTokenStart(es.rightStart());
- int rightEnd= getTokenEnd2(sright, es.rightStart(), es.rightLength());
-
- if (isPatchHunk()) {
- if (isRight)
- leftStart = leftEnd = getHunkStart();
- else
- rightStart = rightEnd = getHunkStart();
- }
-
- Diff diff= new Diff(null, kind,
- aDoc, aRegion, ancestorStart, ancestorEnd,
- lDoc, lRegion, leftStart, leftEnd,
- rDoc, rRegion, rightStart, rightEnd);
-
- newAllDiffs.add(diff); // remember all range diffs for scrolling
-
- if (ignoreWhiteSpace && !isPatchHunk()) {
- if (sancestor != null)
- a= extract2(aDoc, sancestor, es.ancestorStart(), es.ancestorLength());
- s= extract2(lDoc, sleft, es.leftStart(), es.leftLength());
- d= extract2(rDoc, sright, es.rightStart(), es.rightLength());
-
- if ((a == null || a.trim().length() == 0) && s.trim().length() == 0 && d.trim().length() == 0) {
- diff.fIsWhitespace= true;
- continue;
- }
- }
- if (useChange(kind)) {
- fChangeDiffs.add(diff); // here we remember only the real diffs
- updateDiffBackground(diff);
-
- // Only do the token diff for non-hunks
- if (!isPatchHunk()) {
- if (s == null)
- s= extract2(lDoc, sleft, es.leftStart(), es.leftLength());
- if (d == null)
- d= extract2(rDoc, sright, es.rightStart(), es.rightLength());
-
- if (s.length() > 0 && d.length() > 0) {
- if (a == null && sancestor != null)
- a= extract2(aDoc, sancestor, es.ancestorStart(), es.ancestorLength());
- if (USE_MERGING_TOKEN_DIFF)
- mergingTokenDiff(diff, aDoc, a, rDoc, d, lDoc, s);
- else
- simpleTokenDiff(diff, aDoc, a, rDoc, d, lDoc, s);
- }
- }
- }
+ if (fMerger.hasChanges()) {
+ for (Iterator iterator = fMerger.changesIterator(); iterator.hasNext();) {
+ Diff diff = (Diff) iterator.next();
+ updateDiffBackground(diff);
}
}
-
- if (!fSubDoc && rRegion != null && lRegion != null) {
- // we have to add a diff for the ignored lines
-
- int aEnd= 0;
- int aLen= 0;
- if (aRegion != null && aDoc != null) {
- aEnd= aRegion.getOffset()+aRegion.getLength();
- aLen= aDoc.getLength();
- }
- Diff diff= new Diff(null, RangeDifference.NOCHANGE,
- aDoc, aRegion, aEnd, aLen,
- lDoc, lRegion, lRegion.getOffset()+lRegion.getLength(), lDoc.getLength(),
- rDoc, rRegion, rRegion.getOffset()+rRegion.getLength(), rDoc.getLength());
- newAllDiffs.add(diff);
- }
- fAllDiffs = newAllDiffs;
invalidateTextPresentation();
}
+ private Diff findDiff(char type, int pos) {
+ try {
+ return fMerger.findDiff(type, pos);
+ } catch (CoreException e) {
+ CompareUIPlugin.log(e.getStatus());
+ String title= Utilities.getString(getResourceBundle(), "tooComplexError.title"); //$NON-NLS-1$
+ String format= Utilities.getString(getResourceBundle(), "tooComplexError.format"); //$NON-NLS-1$
+ String msg= MessageFormat.format(format, new Object[] { Integer.toString(PlatformUI.getWorkbench().getProgressService().getLongOperationTime()/1000) } );
+ MessageDialog.openError(fComposite.getShell(), title, msg);
+ return null;
+ }
+ }
+
private void resetPositions(IDocument doc) {
if (doc == null)
return;
@@ -3287,314 +2788,6 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
}
doc.addPositionCategory(DIFF_RANGE_CATEGORY);
}
-
- private Diff findDiff(char type, int pos) {
-
- IDocument aDoc= null;
- IDocument lDoc= fLeft.getDocument();
- IDocument rDoc= fRight.getDocument();
- if (lDoc == null || rDoc == null)
- return null;
-
- Position aRegion= null;
- Position lRegion= null;
- Position rRegion= null;
-
- boolean threeWay= isThreeWay();
-
- if (threeWay && !isIgnoreAncestor())
- aDoc= fAncestor.getDocument();
-
- boolean ignoreWhiteSpace= Utilities.getBoolean(getCompareConfiguration(), CompareConfiguration.IGNORE_WHITESPACE, false);
-
- DocLineComparator sright= new DocLineComparator(rDoc, toRegion(rRegion), ignoreWhiteSpace);
- DocLineComparator sleft= new DocLineComparator(lDoc, toRegion(lRegion), ignoreWhiteSpace);
- DocLineComparator sancestor= null;
- if (aDoc != null)
- sancestor= new DocLineComparator(aDoc, toRegion(aRegion), ignoreWhiteSpace);
-
- final ResourceBundle bundle= getResourceBundle();
-
- final Object[] result= new Object[1];
- final DocLineComparator sa= sancestor, sl= sleft, sr= sright;
- IRunnableWithProgress runnable= new IRunnableWithProgress() {
- public void run(IProgressMonitor monitor) throws InterruptedException, InvocationTargetException {
- String progressTitle= Utilities.getString(bundle, "compareProgressTask.title"); //$NON-NLS-1$
- monitor.beginTask(progressTitle, maxWork(sa, sl, sr));
- try {
- result[0]= RangeDifferencer.findRanges(monitor, sa, sl, sr);
- } catch (OutOfMemoryError ex) {
- System.gc();
- throw new InvocationTargetException(ex);
- }
- if (monitor.isCanceled()) { // canceled
- throw new InterruptedException();
- }
- monitor.done();
- }
- };
- IProgressService progressService= PlatformUI.getWorkbench().getProgressService();
-
- RangeDifference[] e= null;
- try {
- progressService.run(true, true, runnable);
- e= (RangeDifference[]) result[0];
- } catch (InvocationTargetException ex) {
- String title= Utilities.getString(bundle, "tooComplexError.title"); //$NON-NLS-1$
- String format= Utilities.getString(bundle, "tooComplexError.format"); //$NON-NLS-1$
- String msg= MessageFormat.format(format, new Object[] { Integer.toString(progressService.getLongOperationTime()/1000) } );
- MessageDialog.openError(fComposite.getShell(), title, msg);
- e= null;
- } catch (InterruptedException ex) {
- //
- }
-
- if (e != null) {
- for (int i= 0; i < e.length; i++) {
- RangeDifference es= e[i];
-
- int kind= es.kind();
-
- int ancestorStart= 0;
- int ancestorEnd= 0;
- if (sancestor != null) {
- ancestorStart= sancestor.getTokenStart(es.ancestorStart());
- ancestorEnd= getTokenEnd2(sancestor, es.ancestorStart(), es.ancestorLength());
- }
-
- int leftStart= sleft.getTokenStart(es.leftStart());
- int leftEnd= getTokenEnd2(sleft, es.leftStart(), es.leftLength());
-
- int rightStart= sright.getTokenStart(es.rightStart());
- int rightEnd= getTokenEnd2(sright, es.rightStart(), es.rightLength());
-
- Diff diff= new Diff(null, kind,
- aDoc, aRegion, ancestorStart, ancestorEnd,
- lDoc, lRegion, leftStart, leftEnd,
- rDoc, rRegion, rightStart, rightEnd);
-
- if (diff.isInRange(type, pos))
- return diff;
- }
- }
-
- return null;
- }
-
- /*
- * Returns true if kind of change should be shown.
- */
- private boolean useChange(int kind) {
- if (kind == RangeDifference.NOCHANGE)
- return false;
- if (kind == RangeDifference.ANCESTOR)
- return fShowPseudoConflicts;
- return true;
- }
-
- private int getTokenEnd(ITokenComparator tc, int start, int count) {
- if (count <= 0)
- return tc.getTokenStart(start);
- int index= start + count - 1;
- return tc.getTokenStart(index) + tc.getTokenLength(index);
- }
-
- private static int getTokenEnd2(ITokenComparator tc, int start, int length) {
- return tc.getTokenStart(start + length);
- }
-
- /*
- * Returns the content of lines in the specified range as a String.
- * This includes the line separators.
- *
- * @param doc the document from which to extract the characters
- * @param start index of first line
- * @param length number of lines
- * @return the contents of the specified line range as a String
- */
- private String extract2(IDocument doc, ITokenComparator tc, int start, int length) {
- int count= tc.getRangeCount();
- if (length > 0 && count > 0) {
-
-//
-// int startPos= tc.getTokenStart(start);
-// int endPos= startPos;
-//
-// if (length > 1)
-// endPos= tc.getTokenStart(start + (length-1));
-// endPos+= tc.getTokenLength(start + (length-1));
-//
-
- int startPos= tc.getTokenStart(start);
- int endPos;
-
- if (length == 1) {
- endPos= startPos + tc.getTokenLength(start);
- } else {
- endPos= tc.getTokenStart(start + length);
- }
-
- try {
- return doc.get(startPos, endPos - startPos);
- } catch (BadLocationException e) {
- // silently ignored
- }
-
- }
- return ""; //$NON-NLS-1$
- }
-
- /*
- * Performs a token based 3-way diff on the character range specified by the given baseDiff.
- */
- private void simpleTokenDiff(final Diff baseDiff,
- IDocument ancestorDoc, String a,
- IDocument rightDoc, String d,
- IDocument leftDoc, String s) {
-
- int ancestorStart= 0;
- ITokenComparator sa= null;
- if (ancestorDoc != null) {
- ancestorStart= baseDiff.fAncestorPos.getOffset();
- sa= createTokenComparator(a);
- }
-
- int rightStart= baseDiff.fRightPos.getOffset();
- ITokenComparator sm= createTokenComparator(d);
-
- int leftStart= baseDiff.fLeftPos.getOffset();
- ITokenComparator sy= createTokenComparator(s);
-
- RangeDifference[] e= RangeDifferencer.findRanges(sa, sy, sm);
- for (int i= 0; i < e.length; i++) {
- RangeDifference es= e[i];
- int kind= es.kind();
- if (kind != RangeDifference.NOCHANGE) {
-
- int ancestorStart2= ancestorStart;
- int ancestorEnd2= ancestorStart;
- if (ancestorDoc != null) {
- ancestorStart2 += sa.getTokenStart(es.ancestorStart());
- ancestorEnd2 += getTokenEnd(sa, es.ancestorStart(), es.ancestorLength());
- }
-
- int leftStart2= leftStart + sy.getTokenStart(es.leftStart());
- int leftEnd2= leftStart + getTokenEnd(sy, es.leftStart(), es.leftLength());
-
- int rightStart2= rightStart + sm.getTokenStart(es.rightStart());
- int rightEnd2= rightStart + getTokenEnd(sm, es.rightStart(), es.rightLength());
-
- Diff diff= new Diff(baseDiff, kind,
- ancestorDoc, null, ancestorStart2, ancestorEnd2,
- leftDoc, null, leftStart2, leftEnd2,
- rightDoc, null, rightStart2, rightEnd2);
-
- // ensure that token diff is smaller than basediff
- int leftS= baseDiff.fLeftPos.offset;
- int leftE= baseDiff.fLeftPos.offset+baseDiff.fLeftPos.length;
- int rightS= baseDiff.fRightPos.offset;
- int rightE= baseDiff.fRightPos.offset+baseDiff.fRightPos.length;
- if (leftS != leftStart2 || leftE != leftEnd2 ||
- rightS != rightStart2 || rightE != rightEnd2) {
- diff.fIsToken= true;
- // add to base Diff
- baseDiff.add(diff);
- }
- }
- }
- }
-
- /*
- * Performs a "smart" token based 3-way diff on the character range specified by the given baseDiff.
- * It is "smart" because it tries to minimize the number of token diffs by merging them.
- */
- private void mergingTokenDiff(Diff baseDiff,
- IDocument ancestorDoc, String a,
- IDocument rightDoc, String d,
- IDocument leftDoc, String s) {
- ITokenComparator sa= null;
- int ancestorStart= 0;
- if (ancestorDoc != null) {
- sa= createTokenComparator(a);
- ancestorStart= baseDiff.fAncestorPos.getOffset();
- }
-
- int rightStart= baseDiff.fRightPos.getOffset();
- ITokenComparator sm= createTokenComparator(d);
-
- int leftStart= baseDiff.fLeftPos.getOffset();
- ITokenComparator sy= createTokenComparator(s);
-
- RangeDifference[] r= RangeDifferencer.findRanges(sa, sy, sm);
- for (int i= 0; i < r.length; i++) {
- RangeDifference es= r[i];
- // determine range of diffs in one line
- int start= i;
- int leftLine= -1;
- int rightLine= -1;
- try {
- leftLine= leftDoc.getLineOfOffset(leftStart+sy.getTokenStart(es.leftStart()));
- rightLine= rightDoc.getLineOfOffset(rightStart+sm.getTokenStart(es.rightStart()));
- } catch (BadLocationException e) {
- // silently ignored
- }
- i++;
- for (; i < r.length; i++) {
- es= r[i];
- try {
- if (leftLine != leftDoc.getLineOfOffset(leftStart+sy.getTokenStart(es.leftStart())))
- break;
- if (rightLine != rightDoc.getLineOfOffset(rightStart+sm.getTokenStart(es.rightStart())))
- break;
- } catch (BadLocationException e) {
- // silently ignored
- }
- }
- int end= i;
-
- // find first diff from left
- RangeDifference first= null;
- for (int ii= start; ii < end; ii++) {
- es= r[ii];
- if (useChange(es.kind())) {
- first= es;
- break;
- }
- }
-
- // find first diff from mine
- RangeDifference last= null;
- for (int ii= end-1; ii >= start; ii--) {
- es= r[ii];
- if (useChange(es.kind())) {
- last= es;
- break;
- }
- }
-
- if (first != null && last != null) {
-
- int ancestorStart2= 0;
- int ancestorEnd2= 0;
- if (ancestorDoc != null) {
- ancestorStart2= ancestorStart+sa.getTokenStart(first.ancestorStart());
- ancestorEnd2= ancestorStart+getTokenEnd(sa, last.ancestorStart(), last.ancestorLength());
- }
-
- int leftStart2= leftStart+sy.getTokenStart(first.leftStart());
- int leftEnd2= leftStart+getTokenEnd(sy, last.leftStart(), last.leftLength());
-
- int rightStart2= rightStart+sm.getTokenStart(first.rightStart());
- int rightEnd2= rightStart+getTokenEnd(sm, last.rightStart(), last.rightLength());
- Diff diff= new Diff(baseDiff, first.kind(),
- ancestorDoc, null, ancestorStart2, ancestorEnd2,
- leftDoc, null, leftStart2, leftEnd2,
- rightDoc, null, rightStart2, rightEnd2);
- diff.fIsToken= true;
- baseDiff.add(diff);
- }
- }
- }
//---- update UI stuff
@@ -3629,16 +2822,8 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
if (fCopyDiffRightToLeftItem != null)
((Action)fCopyDiffRightToLeftItem.getAction()).setEnabled(rightToLeft);
- boolean enableNavigation= false;
- if (fCurrentDiff == null && fChangeDiffs != null && fChangeDiffs.size() > 0)
- enableNavigation= true;
- else if (fChangeDiffs != null && fChangeDiffs.size() > 1)
- enableNavigation= true;
- else if (fCurrentDiff != null && fCurrentDiff.fDiffs != null)
- enableNavigation= true;
- else if (fCurrentDiff != null && fCurrentDiff.fIsToken)
- enableNavigation= true;
-
+ boolean enableNavigation= isNavigationPossible();
+
if (fNextDiff != null) {
IAction a= fNextDiff.getAction();
a.setEnabled(enableNavigation || hasNextElement(true));
@@ -3667,14 +2852,14 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
int unresolvedIncoming= 0;
int unresolvedConflicting= 0;
- if (fChangeDiffs != null) {
- Iterator e= fChangeDiffs.iterator();
- while (e.hasNext()) {
- Diff d= (Diff) e.next();
+ if (fMerger.hasChanges()) {
+ for (Iterator iterator = fMerger.changesIterator(); iterator
+ .hasNext();) {
+ Diff d = (Diff) iterator.next();
if (d.isIncomingOrConflicting() /* && useChange(d.fDirection) && !d.fIsWhitespace */) {
incomingOrConflicting++;
- if (!d.fResolved) {
- if (d.fDirection == RangeDifference.CONFLICT) {
+ if (!d.isResolved()) {
+ if (d.getKind() == RangeDifference.CONFLICT) {
unresolvedConflicting++;
break; // we can stop here because a conflict has the maximum priority
}
@@ -3709,16 +2894,16 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
diffDescription= CompareMessages.TextMergeViewer_diffDescription_noDiff_format;
} else {
- if (diff.fIsToken) // we don't show special info for token diffs
- diff= diff.fParent;
+ if (diff.isToken()) // we don't show special info for token diffs
+ diff= diff.getParent();
String format= CompareMessages.TextMergeViewer_diffDescription_diff_format;
diffDescription= MessageFormat.format(format,
new String[] {
getDiffType(diff), // 0: diff type
getDiffNumber(diff), // 1: diff number
- getDiffRange(fLeft, diff.fLeftPos), // 2: left start line
- getDiffRange(fRight, diff.fRightPos) // 3: left end line
+ getDiffRange(fLeft, diff.getPosition(LEFT_CONTRIBUTOR)), // 2: left start line
+ getDiffRange(fRight, diff.getPosition(RIGHT_CONTRIBUTOR)) // 3: left end line
}
);
}
@@ -3741,7 +2926,7 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
private String getDiffType(Diff diff) {
String s= ""; //$NON-NLS-1$
- switch(diff.fDirection) {
+ switch(diff.getKind()) {
case RangeDifference.LEFT:
s= CompareMessages.TextMergeViewer_direction_outgoing;
break;
@@ -3759,10 +2944,9 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
private String getDiffNumber(Diff diff) {
// find the diff's number
int diffNumber= 0;
- if (fChangeDiffs != null) {
- Iterator e= fChangeDiffs.iterator();
- while (e.hasNext()) {
- Diff d= (Diff) e.next();
+ if (fMerger.hasChanges()) {
+ for (Iterator iterator = fMerger.changesIterator(); iterator.hasNext();) {
+ Diff d = (Diff) iterator.next();
diffNumber++;
if (d == diff)
break;
@@ -4036,9 +3220,9 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
Diff firstDiff= null;
if (first)
- firstDiff= findNext(fRight, fChangeDiffs, -1, -1, false);
+ firstDiff= findNext(fRight, -1, -1, false);
else
- firstDiff= findPrev(fRight, fChangeDiffs, 9999999, 9999999, false);
+ firstDiff= findPrev(fRight, 9999999, 9999999, false);
setCurrentDiff(firstDiff, true);
}
@@ -4189,26 +3373,25 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
boolean showResolveUI= showResolveUI();
- if (fChangeDiffs != null) {
+ if (fMerger.hasChanges()) {
int lshift= fLeft.getVerticalScrollOffset();
int rshift= fRight.getVerticalScrollOffset();
Point region= new Point(0, 0);
- Iterator e= fChangeDiffs.iterator();
- while (e.hasNext()) {
- Diff diff= (Diff) e.next();
+ for (Iterator iterator = fMerger.changesIterator(); iterator.hasNext();) {
+ Diff diff = (Diff) iterator.next();
if (diff.isDeleted())
continue;
if (fShowCurrentOnly2 && !isCurrentDiff(diff))
continue;
- fLeft.getLineRange(diff.fLeftPos, region);
+ fLeft.getLineRange(diff.getPosition(LEFT_CONTRIBUTOR), region);
int ly= (region.x * lineHeightLeft) + lshift;
int lh= region.y * lineHeightLeft;
- fRight.getLineRange(diff.fRightPos, region);
+ fRight.getLineRange(diff.getPosition(RIGHT_CONTRIBUTOR), region);
int ry= (region.x * lineHeightRight) + rshift;
int rh= region.y * lineHeightRight;
@@ -4336,20 +3519,20 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
if (! fHighlightRanges)
return;
- if (fChangeDiffs != null) {
+ if (fMerger.hasChanges()) {
int shift= tp.getVerticalScrollOffset() + (2-LW);
Point region= new Point(0, 0);
- Iterator e= fChangeDiffs.iterator();
- while (e.hasNext()) {
- Diff diff= (Diff) e.next();
+ char leg = getLeg(tp);
+ for (Iterator iterator = fMerger.changesIterator(); iterator.hasNext();) {
+ Diff diff = (Diff) iterator.next();
if (diff.isDeleted())
continue;
if (fShowCurrentOnly2 && !isCurrentDiff(diff))
continue;
- tp.getLineRange(diff.getPosition(tp), region);
+ tp.getLineRange(diff.getPosition(leg), region);
int y= (region.x * lineHeight) + shift;
int h= region.y * lineHeight;
@@ -4378,7 +3561,7 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
if (! fHighlightRanges)
return;
- if (fChangeDiffs == null)
+ if (!fMerger.hasChanges())
return;
Control canvas= (Control) event.widget;
@@ -4395,17 +3578,17 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
shift+= fTopInset;
Point range= new Point(0, 0);
-
- Iterator e= fChangeDiffs.iterator();
- while (e.hasNext()) {
- Diff diff= (Diff) e.next();
+
+ char leg = getLeg(tp);
+ for (Iterator iterator = fMerger.changesIterator(); iterator.hasNext();) {
+ Diff diff = (Diff) iterator.next();
if (diff.isDeleted())
continue;
if (fShowCurrentOnly && !isCurrentDiff(diff))
continue;
- tp.getLineRange(diff.getPosition(tp), range);
+ tp.getLineRange(diff.getPosition(leg), range);
int y= (range.x * lineHeight) + shift;
int h= range.y * lineHeight;
@@ -4421,10 +3604,10 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
}
private RGB getFillColor(Diff diff) {
- boolean selected= fCurrentDiff != null && fCurrentDiff.fParent == diff;
+ boolean selected= fCurrentDiff != null && fCurrentDiff.getParent() == diff;
RGB selected_fill= getBackground(null);
if (isThreeWay() && !isIgnoreAncestor()) {
- switch (diff.fDirection) {
+ switch (diff.getKind()) {
case RangeDifference.RIGHT:
if (fLeftIsLocal)
return selected ? selected_fill : INCOMING_FILL;
@@ -4444,10 +3627,10 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
}
private RGB getStrokeColor(Diff diff) {
- boolean selected= fCurrentDiff != null && fCurrentDiff.fParent == diff;
+ boolean selected= fCurrentDiff != null && fCurrentDiff.getParent() == diff;
if (isThreeWay() && !isIgnoreAncestor()) {
- switch (diff.fDirection) {
+ switch (diff.getKind()) {
case RangeDifference.RIGHT:
if (fLeftIsLocal)
return selected ? SELECTED_INCOMING : INCOMING;
@@ -4501,12 +3684,13 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
if (part == null)
return null;
Point s = part.getSelectedRange();
+ char leg = getLeg(part);
for (;;) {
diff = null;
diff = internalGetNextDiff(down, deep, part, s);
- if (diff != null && diff.fDirection == RangeDifference.ANCESTOR
+ if (diff != null && diff.getKind() == RangeDifference.ANCESTOR
&& !isAncestorVisible()) {
- Position position = diff.getPosition(part);
+ Position position = diff.getPosition(leg);
s = new Point(position.getOffset(), position.getLength());
diff= null;
continue;
@@ -4517,10 +3701,10 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
}
private Diff internalGetNextDiff(boolean down, boolean deep, MergeSourceViewer part, Point s) {
- if (fChangeDiffs != null) {
+ if (fMerger.hasChanges()) {
if (down)
- return findNext(part, fChangeDiffs, s.x, s.x+s.y, deep);
- return findPrev(part, fChangeDiffs, s.x, s.x+s.y, deep);
+ return findNext(part, s.x, s.x+s.y, deep);
+ return findPrev(part, s.x, s.x+s.y, deep);
}
return null;
}
@@ -4533,12 +3717,7 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
}
private Diff getWrappedDiff(Diff diff, boolean down) {
- if (fChangeDiffs != null && fChangeDiffs.size() > 0) {
- if (down)
- return (Diff) fChangeDiffs.get(0);
- return (Diff) fChangeDiffs.get(fChangeDiffs.size()-1);
- }
- return null;
+ return fMerger.getWrappedDiff(diff, down);
}
/*
@@ -4558,7 +3737,7 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
}
if (diff != null)
setCurrentDiff(diff, true, deep);
- if (diff != null && diff.fDirection == RangeDifference.ANCESTOR
+ if (diff != null && diff.getKind() == RangeDifference.ANCESTOR
&& !isAncestorVisible())
continue;
break;
@@ -4662,83 +3841,16 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
* is returned.
*/
private Diff findDiff(MergeSourceViewer tp, int rangeStart, int rangeEnd) {
- if (fChangeDiffs != null) {
- Iterator e= fChangeDiffs.iterator();
- while (e.hasNext()) {
- Diff diff= (Diff) e.next();
- if (diff.overlaps(tp, rangeStart, rangeEnd))
- return diff;
- }
- }
- return null;
+ char contributor = getLeg(tp);
+ return fMerger.findDiff(contributor, rangeStart, rangeEnd);
}
- private static Diff findNext(MergeSourceViewer tp, List v, int start, int end, boolean deep) {
- for (int i= 0; i < v.size(); i++) {
- Diff diff= (Diff) v.get(i);
- Position p= diff.getPosition(tp);
- if (p != null) {
- int startOffset= p.getOffset();
- if (end < startOffset) // <=
- return diff;
- if (deep && diff.fDiffs != null) {
- Diff d= null;
- int endOffset= startOffset + p.getLength();
- if (start == startOffset && (end == endOffset || end == endOffset-1)) {
- d= findNext(tp, diff.fDiffs, start-1, start-1, deep);
- } else if (end < endOffset) {
- d= findNext(tp, diff.fDiffs, start, end, deep);
- }
- if (d != null)
- return d;
- }
- }
- }
- return null;
+ private Diff findNext(MergeSourceViewer tp, int start, int end, boolean deep) {
+ return fMerger.findNext(getLeg(tp), start, end, deep);
}
- private static Diff findPrev(MergeSourceViewer tp, List v, int start, int end, boolean deep) {
- for (int i= v.size()-1; i >= 0; i--) {
- Diff diff= (Diff) v.get(i);
- Position p= diff.getPosition(tp);
- if (p != null) {
- int startOffset= p.getOffset();
- int endOffset= startOffset + p.getLength();
- if (start > endOffset) {
- if (deep && diff.fDiffs != null) {
- // If we are going deep, find the last change in the diff
- return findPrev(tp, diff.fDiffs, end, end, deep);
- }
- return diff;
- }
- if (deep && diff.fDiffs != null) {
- Diff d= null;
- if (start == startOffset && end == endOffset) {
- // A whole diff is selected so we'll fall through
- // and go the the last change in the previous diff
- } else if (start >= startOffset) {
- // If we are at or before the first diff, select the
- // entire diff so next and previous are symmetrical
- if (isFirstDiff(tp, startOffset, diff.fDiffs)) {
- return diff;
- }
- d= findPrev(tp, diff.fDiffs, start, end, deep);
- }
- if (d != null)
- return d;
- }
- }
- }
- return null;
- }
-
- private static boolean isFirstDiff(MergeSourceViewer tp, int startOffset,
- ArrayList diffs) {
- if (diffs.isEmpty())
- return false;
- Diff diff = (Diff)diffs.get(0);
- Position p= diff.getPosition(tp);
- return (p.getOffset() >= startOffset);
+ private Diff findPrev(MergeSourceViewer tp, int start, int end, boolean deep) {
+ return fMerger.findPrev(getLeg(tp), start, end, deep);
}
/*
@@ -4770,27 +3882,27 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
// before we set fCurrentDiff we change the selection
// so that the paint code uses the old background colors
// otherwise selection isn't drawn correctly
- if (d.fIsToken || !fHighlightTokenChanges || deep || !d.hasChildren()) {
+ if (d.isToken() || !fHighlightTokenChanges || deep || !d.hasChildren()) {
if (isThreeWay() && !isIgnoreAncestor())
- fAncestor.setSelection(d.fAncestorPos);
- fLeft.setSelection(d.fLeftPos);
- fRight.setSelection(d.fRightPos);
+ fAncestor.setSelection(d.getPosition(ANCESTOR_CONTRIBUTOR));
+ fLeft.setSelection(d.getPosition(LEFT_CONTRIBUTOR));
+ fRight.setSelection(d.getPosition(RIGHT_CONTRIBUTOR));
} else {
if (isThreeWay() && !isIgnoreAncestor())
- fAncestor.setSelection(new Position(d.fAncestorPos.offset, 0));
- fLeft.setSelection(new Position(d.fLeftPos.offset, 0));
- fRight.setSelection(new Position(d.fRightPos.offset, 0));
+ fAncestor.setSelection(new Position(d.getPosition(ANCESTOR_CONTRIBUTOR).offset, 0));
+ fLeft.setSelection(new Position(d.getPosition(LEFT_CONTRIBUTOR).offset, 0));
+ fRight.setSelection(new Position(d.getPosition(RIGHT_CONTRIBUTOR).offset, 0));
}
// now switch diffs
fCurrentDiff= d;
- revealDiff(d, d.fIsToken);
+ revealDiff(d, d.isToken());
} else {
fCurrentDiff= d;
}
- Diff d1= oldDiff != null ? oldDiff.fParent : null;
- Diff d2= fCurrentDiff != null ? fCurrentDiff.fParent : null;
+ Diff d1= oldDiff != null ? oldDiff.getParent() : null;
+ Diff d2= fCurrentDiff != null ? fCurrentDiff.getParent() : null;
if (d1 != d2) {
updateDiffBackground(d1);
updateDiffBackground(d2);
@@ -4813,11 +3925,11 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
if (smart) {
Point region= new Point(0, 0);
// find the starting line of the diff in all text widgets
- int ls= fLeft.getLineRange(d.fLeftPos, region).x;
- int rs= fRight.getLineRange(d.fRightPos, region).x;
+ int ls= fLeft.getLineRange(d.getPosition(LEFT_CONTRIBUTOR), region).x;
+ int rs= fRight.getLineRange(d.getPosition(RIGHT_CONTRIBUTOR), region).x;
if (isThreeWay() && !isIgnoreAncestor()) {
- int as= fAncestor.getLineRange(d.fAncestorPos, region).x;
+ int as= fAncestor.getLineRange(d.getPosition(ANCESTOR_CONTRIBUTOR), region).x;
if (as >= fAncestor.getTopIndex() && as <= fAncestor.getBottomIndex())
ancestorIsVisible= true;
}
@@ -4835,33 +3947,31 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
MergeSourceViewer allButThis= null;
if (leftIsVisible) {
- avpos= lvpos= rvpos= realToVirtualPosition(fLeft, fLeft.getTopIndex());
+ avpos= lvpos= rvpos= realToVirtualPosition(LEFT_CONTRIBUTOR, fLeft.getTopIndex());
allButThis= fLeft;
} else if (rightIsVisible) {
- avpos= lvpos= rvpos= realToVirtualPosition(fRight, fRight.getTopIndex());
+ avpos= lvpos= rvpos= realToVirtualPosition(RIGHT_CONTRIBUTOR, fRight.getTopIndex());
allButThis= fRight;
} else if (ancestorIsVisible) {
- avpos= lvpos= rvpos= realToVirtualPosition(fAncestor, fAncestor.getTopIndex());
+ avpos= lvpos= rvpos= realToVirtualPosition(ANCESTOR_CONTRIBUTOR, fAncestor.getTopIndex());
allButThis= fAncestor;
} else {
- if (fAllDiffs != null) {
- int vpos= 0;
- Iterator e= fAllDiffs.iterator();
- for (int i= 0; e.hasNext(); i++) {
- Diff diff= (Diff) e.next();
- if (diff == d)
- break;
- if (fSynchronizedScrolling) {
- vpos+= diff.getMaxDiffHeight();
- } else {
- avpos+= diff.getAncestorHeight();
- lvpos+= diff.getLeftHeight();
- rvpos+= diff.getRightHeight();
- }
+ int vpos= 0;
+ for (Iterator iterator = fMerger.rangesIterator(); iterator
+ .hasNext();) {
+ Diff diff = (Diff) iterator.next();
+ if (diff == d)
+ break;
+ if (fSynchronizedScrolling) {
+ vpos+= diff.getMaxDiffHeight();
+ } else {
+ avpos+= diff.getAncestorHeight();
+ lvpos+= diff.getLeftHeight();
+ rvpos+= diff.getRightHeight();
}
- if (fSynchronizedScrolling)
- avpos= lvpos= rvpos= vpos;
}
+ if (fSynchronizedScrolling)
+ avpos= lvpos= rvpos= vpos;
int delta= fRight.getViewportLines()/4;
avpos-= delta;
if (avpos < 0)
@@ -4881,11 +3991,11 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
}
// horizontal scrolling
- if (d.fIsToken) {
+ if (d.isToken()) {
// we only scroll horizontally for token diffs
- reveal(fAncestor, d.fAncestorPos);
- reveal(fLeft, d.fLeftPos);
- reveal(fRight, d.fRightPos);
+ reveal(fAncestor, d.getPosition(ANCESTOR_CONTRIBUTOR));
+ reveal(fLeft, d.getPosition(LEFT_CONTRIBUTOR));
+ reveal(fRight, d.getPosition(RIGHT_CONTRIBUTOR));
} else {
// in all other cases we reset the horizontal offset
hscroll(fAncestor);
@@ -4916,14 +4026,13 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
//--------------------------------------------------------------------------------
void copyAllUnresolved(boolean leftToRight) {
- if (fChangeDiffs != null && isThreeWay() && !isIgnoreAncestor()) {
+ if (fMerger.hasChanges() && isThreeWay() && !isIgnoreAncestor()) {
IRewriteTarget target= leftToRight ? fRight.getRewriteTarget() : fLeft.getRewriteTarget();
boolean compoundChangeStarted= false;
- Iterator e= fChangeDiffs.iterator();
try {
- while (e.hasNext()) {
- Diff diff= (Diff) e.next();
- switch (diff.fDirection) {
+ for (Iterator iterator = fMerger.changesIterator(); iterator.hasNext();) {
+ Diff diff = (Diff) iterator.next();
+ switch (diff.getKind()) {
case RangeDifference.LEFT:
if (leftToRight) {
if (!compoundChangeStarted) {
@@ -5029,66 +4138,15 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
if (diff != null && !diff.isResolved()) {
if (!validateChange(!leftToRight))
return false;
- Position fromPos= null;
- Position toPos= null;
- IDocument fromDoc= null;
- IDocument toDoc= null;
-
if (leftToRight) {
fRight.setEnabled(true);
- fromPos= diff.fLeftPos;
- toPos= diff.fRightPos;
- fromDoc= fLeft.getDocument();
- toDoc= fRight.getDocument();
} else {
fLeft.setEnabled(true);
- fromPos= diff.fRightPos;
- toPos= diff.fLeftPos;
- fromDoc= fRight.getDocument();
- toDoc= fLeft.getDocument();
- }
-
- if (fromDoc != null) {
-
- int fromStart= fromPos.getOffset();
- int fromLen= fromPos.getLength();
-
- int toStart= toPos.getOffset();
- int toLen= toPos.getLength();
-
- try {
- String s= null;
-
- switch (diff.fDirection) {
- case RangeDifference.RIGHT:
- case RangeDifference.LEFT:
- s= fromDoc.get(fromStart, fromLen);
- break;
- case RangeDifference.ANCESTOR:
- break;
- case RangeDifference.CONFLICT:
- if (APPEND_CONFLICT) {
- s= toDoc.get(toStart, toLen);
- s+= fromDoc.get(fromStart, fromLen);
- } else
- s= fromDoc.get(fromStart, fromLen);
- break;
- }
- if (s != null) {
- toDoc.replace(toStart, toLen, s);
- toPos.setOffset(toStart);
- toPos.setLength(s.length());
- }
-
- } catch (BadLocationException e) {
- // silently ignored
- }
}
-
- diff.setResolved(true);
- updateResolveStatus();
-
- return true;
+ boolean result = fMerger.copy(diff, leftToRight);
+ if (result)
+ updateResolveStatus();
+ return result;
}
return false;
}
@@ -5104,36 +4162,6 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
}
//---- scrolling
-
- /*
- * Calculates virtual height (in lines) of views by adding the maximum of corresponding diffs.
- */
- private int getVirtualHeight() {
- int h= 1;
- if (fAllDiffs != null) {
- Iterator e= fAllDiffs.iterator();
- for (int i= 0; e.hasNext(); i++) {
- Diff diff= (Diff) e.next();
- h+= diff.getMaxDiffHeight();
- }
- }
- return h;
- }
-
- /*
- * Calculates height (in lines) of right view by adding the height of the right diffs.
- */
- private int getRightHeight() {
- int h= 1;
- if (fAllDiffs != null) {
- Iterator e= fAllDiffs.iterator();
- for (int i= 0; e.hasNext(); i++) {
- Diff diff= (Diff) e.next();
- h+= diff.getRightHeight();
- }
- }
- return h;
- }
/*
* The height of the TextEditors in lines.
@@ -5160,35 +4188,10 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
/*
* Returns the virtual position for the given view position.
*/
- private int realToVirtualPosition(MergeSourceViewer w, int vpos) {
-
- if (! fSynchronizedScrolling || fAllDiffs == null)
+ private int realToVirtualPosition(char contributor, int vpos) {
+ if (! fSynchronizedScrolling)
return vpos;
-
- int viewPos= 0; // real view position
- int virtualPos= 0; // virtual position
- Point region= new Point(0, 0);
-
- Iterator e= fAllDiffs.iterator();
- while (e.hasNext()) {
- Diff diff= (Diff) e.next();
- Position pos= diff.getPosition(w);
- w.getLineRange(pos, region);
- int realHeight= region.y;
- int virtualHeight= diff.getMaxDiffHeight();
- if (vpos <= viewPos + realHeight) { // OK, found!
- vpos-= viewPos; // make relative to this slot
- // now scale position within this slot to virtual slot
- if (realHeight <= 0)
- vpos= 0;
- else
- vpos= (vpos*virtualHeight)/realHeight;
- return virtualPos+vpos;
- }
- viewPos+= realHeight;
- virtualPos+= virtualHeight;
- }
- return virtualPos;
+ return fMerger.realToVirtualPosition(contributor, vpos);
}
private void scrollVertical(int avpos, int lvpos, int rvpos, MergeSourceViewer allBut) {
@@ -5196,7 +4199,7 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
int s= 0;
if (fSynchronizedScrolling) {
- s= getVirtualHeight() - rvpos;
+ s= fMerger.getVirtualHeight() - rvpos;
int height= fRight.getViewportLines()/4;
if (s < 0)
s= 0;
@@ -5208,21 +4211,21 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
if (isThreeWay() && allBut != fAncestor) {
if (fSynchronizedScrolling || allBut == null) {
- int y= virtualToRealPosition(fAncestor, avpos+s)-s;
+ int y= virtualToRealPosition(ANCESTOR_CONTRIBUTOR, avpos+s)-s;
fAncestor.vscroll(y);
}
}
if (allBut != fLeft) {
if (fSynchronizedScrolling || allBut == null) {
- int y= virtualToRealPosition(fLeft, lvpos+s)-s;
+ int y= virtualToRealPosition(LEFT_CONTRIBUTOR, lvpos+s)-s;
fLeft.vscroll(y);
}
}
if (allBut != fRight) {
if (fSynchronizedScrolling || allBut == null) {
- int y= virtualToRealPosition(fRight, rvpos+s)-s;
+ int y= virtualToRealPosition(RIGHT_CONTRIBUTOR, rvpos+s)-s;
fRight.vscroll(y);
}
}
@@ -5254,12 +4257,12 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
int ix= w.getTopIndex();
int ix2= w.getDocumentRegionOffset();
- int viewPosition= realToVirtualPosition(w, ix-ix2);
+ int viewPosition= realToVirtualPosition(getLeg(w), ix-ix2);
scrollVertical(viewPosition, viewPosition, viewPosition, w); // scroll all but the given views
if (fVScrollBar != null) {
- int value= Math.max(0, Math.min(viewPosition, getVirtualHeight() - getViewportHeight()));
+ int value= Math.max(0, Math.min(viewPosition, fMerger.getVirtualHeight() - getViewportHeight()));
fVScrollBar.setSelection(value);
//refreshBirdEyeView();
}
@@ -5270,7 +4273,7 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
private void updateVScrollBar() {
if (Utilities.okToUse(fVScrollBar) && fSynchronizedScrolling) {
- int virtualHeight= getVirtualHeight();
+ int virtualHeight= fMerger.getVirtualHeight();
int viewPortHeight= getViewportHeight();
int pageIncrement= viewPortHeight-1;
int thumb= (viewPortHeight > virtualHeight) ? virtualHeight : viewPortHeight;
@@ -5284,34 +4287,10 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
/*
* maps given virtual position into a real view position of this view.
*/
- private int virtualToRealPosition(MergeSourceViewer part, int v) {
-
- if (! fSynchronizedScrolling || fAllDiffs == null)
+ private int virtualToRealPosition(char contributor, int v) {
+ if (! fSynchronizedScrolling)
return v;
-
- int virtualPos= 0;
- int viewPos= 0;
- Point region= new Point(0, 0);
-
- Iterator e= fAllDiffs.iterator();
- while (e.hasNext()) {
- Diff diff= (Diff) e.next();
- Position pos= diff.getPosition(part);
- int viewHeight= part.getLineRange(pos, region).y;
- int virtualHeight= diff.getMaxDiffHeight();
- if (v < (virtualPos + virtualHeight)) {
- v-= virtualPos; // make relative to this slot
- if (viewHeight <= 0) {
- v= 0;
- } else {
- v= (int) (v * ((double)viewHeight/virtualHeight));
- }
- return viewPos+v;
- }
- virtualPos+= virtualHeight;
- viewPos+= viewHeight;
- }
- return viewPos;
+ return fMerger.virtualToRealPosition(contributor, v);
}
/* (non-Javadoc)
@@ -5453,8 +4432,7 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
private void resetDiffs() {
// clear stuff
fCurrentDiff= null;
- fChangeDiffs= null;
- fAllDiffs= null;
+ fMerger.reset();
resetPositions(fLeft.getDocument());
resetPositions(fRight.getDocument());
resetPositions(fAncestor.getDocument());
@@ -5492,4 +4470,36 @@ public class TextMergeViewer extends ContentMergeViewer implements IAdaptable {
fFindReplaceTarget= new FindReplaceTarget();
return fFindReplaceTarget;
}
+
+ /* package */ char getLeg(MergeSourceViewer w) {
+ if (w == fLeft)
+ return LEFT_CONTRIBUTOR;
+ if (w == fRight)
+ return RIGHT_CONTRIBUTOR;
+ if (w == fAncestor)
+ return ANCESTOR_CONTRIBUTOR;
+ return ANCESTOR_CONTRIBUTOR;
+ }
+
+ public boolean isCurrentDiff(Diff diff) {
+ if (diff == null)
+ return false;
+ if (diff == fCurrentDiff)
+ return true;
+ if (fCurrentDiff != null && fCurrentDiff.getParent() == diff)
+ return true;
+ return false;
+ }
+
+ public boolean isNavigationPossible() {
+ if (fCurrentDiff == null && fMerger.hasChanges())
+ return true;
+ else if (fMerger.changesCount() > 1)
+ return true;
+ else if (fCurrentDiff != null && fCurrentDiff.hasChildren())
+ return true;
+ else if (fCurrentDiff != null && fCurrentDiff.isToken())
+ return true;
+ return false;
+ }
}
diff --git a/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/merge/DocumentMerger.java b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/merge/DocumentMerger.java
new file mode 100644
index 000000000..64290904a
--- /dev/null
+++ b/bundles/org.eclipse.compare/plugins/org.eclipse.compare/compare/org/eclipse/compare/internal/merge/DocumentMerger.java
@@ -0,0 +1,1338 @@
+/*******************************************************************************
+ * Copyright (c) 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.compare.internal.merge;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.*;
+
+import org.eclipse.compare.CompareConfiguration;
+import org.eclipse.compare.contentmergeviewer.ITokenComparator;
+import org.eclipse.compare.internal.*;
+import org.eclipse.compare.rangedifferencer.*;
+import org.eclipse.compare.structuremergeviewer.Differencer;
+import org.eclipse.core.runtime.*;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.text.*;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.progress.IProgressService;
+
+/**
+ * A document merger manages the differences between two documents
+ * for either a 2-way or 3-way comparison.
+ * <p>
+ * This class should not have any UI dependencies.
+ */
+public class DocumentMerger {
+
+ private static final String DIFF_RANGE_CATEGORY = CompareUIPlugin.PLUGIN_ID + ".DIFF_RANGE_CATEGORY"; //$NON-NLS-1$
+
+ /** Selects between smartTokenDiff and mergingTokenDiff */
+ private static final boolean USE_MERGING_TOKEN_DIFF= false;
+
+ /** if true copying conflicts from one side to other concatenates both sides */
+ private static final boolean APPEND_CONFLICT= true;
+
+ /** All diffs for calculating scrolling position (includes line ranges without changes) */
+ private ArrayList fAllDiffs;
+ /** Subset of above: just real differences. */
+ private ArrayList fChangeDiffs;
+
+ private final boolean fLeftIsLocal;
+
+ private IDocumentMergerInput fInput;
+
+ public interface IDocumentMergerInput {
+
+ IDocument getDocument(char contributor);
+
+ Position getRegion(char contributor);
+
+ boolean isIgnoreAncestor();
+
+ boolean isThreeWay();
+
+ CompareConfiguration getCompareConfiguration();
+
+ ITokenComparator createTokenComparator(String s);
+
+ boolean isHunkOnLeft();
+
+ int getHunkStart();
+
+ boolean isPatchHunk();
+
+ boolean isShowPseudoConflicts();
+
+ }
+
+ public class Diff {
+ /** character range in ancestor document */
+ Position fAncestorPos;
+ /** character range in left document */
+ Position fLeftPos;
+ /** character range in right document */
+ Position fRightPos;
+ /** if this is a TokenDiff fParent points to the enclosing LineDiff */
+ Diff fParent;
+ /** if Diff has been resolved */
+ boolean fResolved;
+ int fDirection;
+ boolean fIsToken= false;
+ /** child token diffs */
+ ArrayList fDiffs;
+ boolean fIsWhitespace= false;
+
+ /*
+ * Create Diff from two ranges and an optional parent diff.
+ */
+ Diff(Diff parent, int dir, IDocument ancestorDoc, Position aRange, int ancestorStart, int ancestorEnd,
+ IDocument leftDoc, Position lRange, int leftStart, int leftEnd,
+ IDocument rightDoc, Position rRange, int rightStart, int rightEnd) {
+ fParent= parent != null ? parent : this;
+ fDirection= dir;
+
+ fLeftPos= createPosition(leftDoc, lRange, leftStart, leftEnd);
+ fRightPos= createPosition(rightDoc, rRange, rightStart, rightEnd);
+ if (ancestorDoc != null)
+ fAncestorPos= createPosition(ancestorDoc, aRange, ancestorStart, ancestorEnd);
+ }
+
+ public Position getPosition(char type) {
+ switch (type) {
+ case MergeViewerContentProvider.ANCESTOR_CONTRIBUTOR:
+ return fAncestorPos;
+ case MergeViewerContentProvider.LEFT_CONTRIBUTOR:
+ return fLeftPos;
+ case MergeViewerContentProvider.RIGHT_CONTRIBUTOR:
+ return fRightPos;
+ }
+ return null;
+ }
+
+ boolean isInRange(char type, int pos) {
+ Position p= getPosition(type);
+ return (pos >= p.offset) && (pos < (p.offset+p.length));
+ }
+
+ public String changeType() {
+ boolean leftEmpty= fLeftPos.length == 0;
+ boolean rightEmpty= fRightPos.length == 0;
+
+ if (fDirection == RangeDifference.LEFT) {
+ if (!leftEmpty && rightEmpty)
+ return CompareMessages.TextMergeViewer_changeType_addition;
+ if (leftEmpty && !rightEmpty)
+ return CompareMessages.TextMergeViewer_changeType_deletion;
+ } else {
+ if (leftEmpty && !rightEmpty)
+ return CompareMessages.TextMergeViewer_changeType_addition;
+ if (!leftEmpty && rightEmpty)
+ return CompareMessages.TextMergeViewer_changeType_deletion;
+ }
+ return CompareMessages.TextMergeViewer_changeType_change;
+ }
+
+ public Image getImage() {
+ int code= Differencer.CHANGE;
+ switch (fDirection) {
+ case RangeDifference.RIGHT:
+ code+= Differencer.LEFT;
+ break;
+ case RangeDifference.LEFT:
+ code+= Differencer.RIGHT;
+ break;
+ case RangeDifference.ANCESTOR:
+ case RangeDifference.CONFLICT:
+ code+= Differencer.CONFLICTING;
+ break;
+ }
+ if (code != 0)
+ return getCompareConfiguration().getImage(code);
+ return null;
+ }
+
+ Position createPosition(IDocument doc, Position range, int start, int end) {
+ try {
+ int l= end-start;
+ if (range != null) {
+ int dl= range.length;
+ if (l > dl)
+ l= dl;
+ } else {
+ int dl= doc.getLength();
+ if (start+l > dl)
+ l= dl-start;
+ }
+
+ Position p= null;
+ try {
+ p= new Position(start, l);
+ } catch (RuntimeException ex) {
+ p= new Position(0, 0);
+ }
+
+ try {
+ doc.addPosition(DIFF_RANGE_CATEGORY, p);
+ } catch (BadPositionCategoryException ex) {
+ // silently ignored
+ }
+ return p;
+ } catch (BadLocationException ee) {
+ // silently ignored
+ }
+ return null;
+ }
+
+ void add(Diff d) {
+ if (fDiffs == null)
+ fDiffs= new ArrayList();
+ fDiffs.add(d);
+ }
+
+ public boolean isDeleted() {
+ if (fAncestorPos != null && fAncestorPos.isDeleted())
+ return true;
+ return fLeftPos.isDeleted() || fRightPos.isDeleted();
+ }
+
+ void setResolved(boolean r) {
+ fResolved= r;
+ if (r)
+ fDiffs= null;
+ }
+
+ public boolean isResolved() {
+ if (!fResolved && fDiffs != null) {
+ Iterator e= fDiffs.iterator();
+ while (e.hasNext()) {
+ Diff d= (Diff) e.next();
+ if (!d.isResolved())
+ return false;
+ }
+ return true;
+ }
+ return fResolved;
+ }
+
+// private boolean isIncoming() {
+// switch (fDirection) {
+// case RangeDifference.RIGHT:
+// if (fLeftIsLocal)
+// return true;
+// break;
+// case RangeDifference.LEFT:
+// if (!fLeftIsLocal)
+// return true;
+// break;
+// }
+// return false;
+// }
+
+ public boolean isIncomingOrConflicting() {
+ switch (fDirection) {
+ case RangeDifference.RIGHT:
+ if (fLeftIsLocal)
+ return true;
+ break;
+ case RangeDifference.LEFT:
+ if (!fLeftIsLocal)
+ return true;
+ break;
+ case RangeDifference.CONFLICT:
+ return true;
+ }
+ return false;
+ }
+
+// private boolean isUnresolvedIncoming() {
+// if (fResolved)
+// return false;
+// return isIncoming();
+// }
+
+ public boolean isUnresolvedIncomingOrConflicting() {
+ if (fResolved)
+ return false;
+ return isIncomingOrConflicting();
+ }
+
+ Position getPosition(int contributor) {
+ if (contributor == MergeViewerContentProvider.LEFT_CONTRIBUTOR)
+ return fLeftPos;
+ if (contributor == MergeViewerContentProvider.RIGHT_CONTRIBUTOR)
+ return fRightPos;
+ if (contributor == MergeViewerContentProvider.ANCESTOR_CONTRIBUTOR)
+ return fAncestorPos;
+ return null;
+ }
+
+ /*
+ * Returns true if given character range overlaps with this Diff.
+ */
+ public boolean overlaps(int contributor, int start, int end) {
+ Position h= getPosition(contributor);
+ if (h != null) {
+ int ds= h.getOffset();
+ int de= ds + h.getLength();
+ if ((start < de) && (end >= ds))
+ return true;
+ }
+ return false;
+ }
+
+ public int getMaxDiffHeight() {
+ Point region= new Point(0, 0);
+ int h= getLineRange(getDocument(MergeViewerContentProvider.LEFT_CONTRIBUTOR), fLeftPos, region).y;
+ if (isThreeWay())
+ h= Math.max(h, getLineRange(getDocument(MergeViewerContentProvider.ANCESTOR_CONTRIBUTOR), fAncestorPos, region).y);
+ return Math.max(h, getLineRange(getDocument(MergeViewerContentProvider.RIGHT_CONTRIBUTOR), fRightPos, region).y);
+ }
+
+ public int getAncestorHeight() {
+ Point region= new Point(0, 0);
+ return getLineRange(getDocument(MergeViewerContentProvider.ANCESTOR_CONTRIBUTOR), fAncestorPos, region).y;
+ }
+
+ public int getLeftHeight() {
+ Point region= new Point(0, 0);
+ return getLineRange(getDocument(MergeViewerContentProvider.LEFT_CONTRIBUTOR), fLeftPos, region).y;
+ }
+
+ public int getRightHeight() {
+ Point region= new Point(0, 0);
+ return getLineRange(getDocument(MergeViewerContentProvider.RIGHT_CONTRIBUTOR), fRightPos, region).y;
+ }
+
+ public Diff[] getChangeDiffs(int contributor, IRegion region) {
+ if (fDiffs != null && intersectsRegion(contributor, region)) {
+ List result = new ArrayList();
+ for (Iterator iterator = fDiffs.iterator(); iterator.hasNext();) {
+ Diff diff = (Diff) iterator.next();
+ if (diff.intersectsRegion(contributor, region)) {
+ result.add(diff);
+ }
+ }
+ return (Diff[]) result.toArray(new Diff[result.size()]);
+ }
+ return new Diff[0];
+ }
+
+ private boolean intersectsRegion(int contributor, IRegion region) {
+ Position p = getPosition(contributor);
+ if (p != null)
+ return p.overlapsWith(region.getOffset(), region.getLength());
+ return false;
+ }
+
+ public boolean hasChildren() {
+ return fDiffs != null && !fDiffs.isEmpty();
+ }
+
+ public int getKind() {
+ return fDirection;
+ }
+
+ public boolean isToken() {
+ return fIsToken;
+ }
+
+ public Diff getParent() {
+ return fParent;
+ }
+
+ public Iterator childIterator() {
+ if (fDiffs == null)
+ return new ArrayList().iterator();
+ return fDiffs.iterator();
+ }
+ }
+
+ public DocumentMerger(IDocumentMergerInput input) {
+ this.fInput = input;
+ fLeftIsLocal= Utilities.getBoolean(getCompareConfiguration(), "LEFT_IS_LOCAL", false); //$NON-NLS-1$
+ }
+
+ /**
+ * Perform a two level 2- or 3-way diff.
+ * The first level is based on line comparison, the second level on token comparison.
+ * @throws CoreException
+ */
+ public void doDiff() throws CoreException {
+
+ fChangeDiffs= new ArrayList();
+ IDocument lDoc = getDocument(MergeViewerContentProvider.LEFT_CONTRIBUTOR);
+ IDocument rDoc = getDocument(MergeViewerContentProvider.RIGHT_CONTRIBUTOR);
+
+ if (lDoc == null || rDoc == null)
+ return;
+
+ Position lRegion= getRegion(MergeViewerContentProvider.LEFT_CONTRIBUTOR);
+ Position rRegion= getRegion(MergeViewerContentProvider.RIGHT_CONTRIBUTOR);
+
+ IDocument aDoc = null;
+ Position aRegion= null;
+ if (isThreeWay() && !isIgnoreAncestor()) {
+ aDoc= getDocument(MergeViewerContentProvider.ANCESTOR_CONTRIBUTOR);
+ aRegion= getRegion(MergeViewerContentProvider.ANCESTOR_CONTRIBUTOR);
+ }
+
+ resetPositions(lDoc);
+ resetPositions(rDoc);
+ resetPositions(aDoc);
+
+ boolean ignoreWhiteSpace= isIgnoreWhitespace();
+
+ DocLineComparator sright= new DocLineComparator(rDoc, toRegion(rRegion), ignoreWhiteSpace);
+ DocLineComparator sleft= new DocLineComparator(lDoc, toRegion(lRegion), ignoreWhiteSpace);
+ DocLineComparator sancestor= null;
+ if (aDoc != null) {
+ sancestor= new DocLineComparator(aDoc, toRegion(aRegion), ignoreWhiteSpace);
+ if (isPatchHunk()) {
+ if (isHunkOnLeft()) {
+ sright= new DocLineComparator(aDoc, toRegion(aRegion), ignoreWhiteSpace);
+ } else {
+ sleft= new DocLineComparator(aDoc, toRegion(aRegion), ignoreWhiteSpace);
+ }
+ }
+ }
+
+ final Object[] result= new Object[1];
+ final DocLineComparator sa= sancestor, sl= sleft, sr= sright;
+ IRunnableWithProgress runnable= new IRunnableWithProgress() {
+ public void run(IProgressMonitor monitor) throws InterruptedException, InvocationTargetException {
+ monitor.beginTask("Computing Differences...", maxWork(sa, sl, sr));
+ try {
+ result[0]= RangeDifferencer.findRanges(monitor, sa, sl, sr);
+ } catch (OutOfMemoryError ex) {
+ System.gc();
+ throw new InvocationTargetException(ex);
+ }
+ if (monitor.isCanceled()) { // canceled
+ throw new InterruptedException();
+ }
+ monitor.done();
+ }
+ };
+
+ RangeDifference[] e= null;
+ try {
+ getCompareConfiguration().getContainer().run(true, true, runnable);
+ e= (RangeDifference[]) result[0];
+ } catch (InvocationTargetException ex) {
+ // we create a NOCHANGE range for the whole document
+ Diff diff= new Diff(null, RangeDifference.NOCHANGE,
+ aDoc, aRegion, 0, aDoc != null ? aDoc.getLength() : 0,
+ lDoc, lRegion, 0, lDoc.getLength(),
+ rDoc, rRegion, 0, rDoc.getLength());
+
+ fAllDiffs = new ArrayList();
+ fAllDiffs.add(diff);
+ throw new CoreException(new Status(IStatus.ERROR, CompareUIPlugin.PLUGIN_ID, 0, "Too many differences found", ex.getTargetException()));
+ } catch (InterruptedException ex) {
+ //
+ }
+
+ ArrayList newAllDiffs = new ArrayList();
+ for (int i= 0; i < e.length; i++) {
+ RangeDifference es= e[i];
+
+ int ancestorStart= 0;
+ int ancestorEnd= 0;
+ if (sancestor != null) {
+ ancestorStart= sancestor.getTokenStart(es.ancestorStart());
+ ancestorEnd= getTokenEnd2(sancestor, es.ancestorStart(), es.ancestorLength());
+ }
+
+ int leftStart= sleft.getTokenStart(es.leftStart());
+ int leftEnd= getTokenEnd2(sleft, es.leftStart(), es.leftLength());
+
+ int rightStart= sright.getTokenStart(es.rightStart());
+ int rightEnd= getTokenEnd2(sright, es.rightStart(), es.rightLength());
+
+ if (isPatchHunk()) {
+ if (isHunkOnLeft()) {
+ rightStart = rightEnd = getHunkStart();
+ } else {
+ leftStart = leftEnd = getHunkStart();
+ }
+ }
+
+ Diff diff= new Diff(null, es.kind(),
+ aDoc, aRegion, ancestorStart, ancestorEnd,
+ lDoc, lRegion, leftStart, leftEnd,
+ rDoc, rRegion, rightStart, rightEnd);
+
+ newAllDiffs.add(diff); // remember all range diffs for scrolling
+
+ if (isPatchHunk()) {
+ if (useChange(diff)) {
+ recordChangeDiff(diff);
+ }
+ } else {
+ if (ignoreWhiteSpace || useChange(es.kind())) {
+
+ // Extract the string for each contributor.
+ String a= null;
+ if (sancestor != null)
+ a= extract2(aDoc, sancestor, es.ancestorStart(), es.ancestorLength());
+ String s= extract2(lDoc, sleft, es.leftStart(), es.leftLength());
+ String d= extract2(rDoc, sright, es.rightStart(), es.rightLength());
+
+ // Indicate whether all contributors are whitespace
+ if (ignoreWhiteSpace
+ && (a == null || a.trim().length() == 0)
+ && s.trim().length() == 0
+ && d.trim().length() == 0) {
+ diff.fIsWhitespace= true;
+ }
+
+ // If the diff is of interest, record it and generate the token diffs
+ if (useChange(diff)) {
+ recordChangeDiff(diff);
+ if (s.length() > 0 && d.length() > 0) {
+ if (a == null && sancestor != null)
+ a= extract2(aDoc, sancestor, es.ancestorStart(), es.ancestorLength());
+ if (USE_MERGING_TOKEN_DIFF)
+ mergingTokenDiff(diff, aDoc, a, rDoc, d, lDoc, s);
+ else
+ simpleTokenDiff(diff, aDoc, a, rDoc, d, lDoc, s);
+ }
+ }
+ }
+ }
+ }
+ fAllDiffs = newAllDiffs;
+ }
+
+ public Diff findDiff(char type, int pos) throws CoreException {
+
+ IDocument aDoc= null;
+ IDocument lDoc= getDocument(MergeViewerContentProvider.LEFT_CONTRIBUTOR);
+ IDocument rDoc= getDocument(MergeViewerContentProvider.RIGHT_CONTRIBUTOR);
+ if (lDoc == null || rDoc == null)
+ return null;
+
+ Position aRegion= null;
+ Position lRegion= null;
+ Position rRegion= null;
+
+ boolean threeWay= isThreeWay();
+
+ if (threeWay && !isIgnoreAncestor())
+ aDoc= getDocument(MergeViewerContentProvider.ANCESTOR_CONTRIBUTOR);
+
+ boolean ignoreWhiteSpace= isIgnoreWhitespace();
+
+ DocLineComparator sright= new DocLineComparator(rDoc, toRegion(rRegion), ignoreWhiteSpace);
+ DocLineComparator sleft= new DocLineComparator(lDoc, toRegion(lRegion), ignoreWhiteSpace);
+ DocLineComparator sancestor= null;
+ if (aDoc != null)
+ sancestor= new DocLineComparator(aDoc, toRegion(aRegion), ignoreWhiteSpace);
+
+ final Object[] result= new Object[1];
+ final DocLineComparator sa= sancestor, sl= sleft, sr= sright;
+ IRunnableWithProgress runnable= new IRunnableWithProgress() {
+ public void run(IProgressMonitor monitor) throws InterruptedException, InvocationTargetException {
+ monitor.beginTask("Finding Differences...", maxWork(sa, sl, sr));
+ try {
+ result[0]= RangeDifferencer.findRanges(monitor, sa, sl, sr);
+ } catch (OutOfMemoryError ex) {
+ System.gc();
+ throw new InvocationTargetException(ex);
+ }
+ if (monitor.isCanceled()) { // canceled
+ throw new InterruptedException();
+ }
+ monitor.done();
+ }
+ };
+ IProgressService progressService= PlatformUI.getWorkbench().getProgressService();
+
+ RangeDifference[] e= null;
+ try {
+ progressService.run(true, true, runnable);
+ e= (RangeDifference[]) result[0];
+ } catch (InvocationTargetException ex) {
+ throw new CoreException(new Status(IStatus.ERROR, CompareUIPlugin.PLUGIN_ID, 0, "Too many differences found", ex.getTargetException()));
+ } catch (InterruptedException ex) {
+ //
+ }
+
+ if (e != null) {
+ for (int i= 0; i < e.length; i++) {
+ RangeDifference es= e[i];
+
+ int kind= es.kind();
+
+ int ancestorStart= 0;
+ int ancestorEnd= 0;
+ if (sancestor != null) {
+ ancestorStart= sancestor.getTokenStart(es.ancestorStart());
+ ancestorEnd= getTokenEnd2(sancestor, es.ancestorStart(), es.ancestorLength());
+ }
+
+ int leftStart= sleft.getTokenStart(es.leftStart());
+ int leftEnd= getTokenEnd2(sleft, es.leftStart(), es.leftLength());
+
+ int rightStart= sright.getTokenStart(es.rightStart());
+ int rightEnd= getTokenEnd2(sright, es.rightStart(), es.rightLength());
+
+ Diff diff= new Diff(null, kind,
+ aDoc, aRegion, ancestorStart, ancestorEnd,
+ lDoc, lRegion, leftStart, leftEnd,
+ rDoc, rRegion, rightStart, rightEnd);
+
+ if (diff.isInRange(type, pos))
+ return diff;
+ }
+ }
+
+ return null;
+ }
+
+ private void recordChangeDiff(Diff diff) {
+ fChangeDiffs.add(diff); // here we remember only the real diffs
+ }
+
+ private boolean isHunkOnLeft() {
+ return fInput.isHunkOnLeft();
+ }
+
+ private int getHunkStart() {
+ return fInput.getHunkStart();
+ }
+
+ private boolean isPatchHunk() {
+ return fInput.isPatchHunk();
+ }
+
+ private boolean isIgnoreWhitespace() {
+ return Utilities.getBoolean(getCompareConfiguration(), CompareConfiguration.IGNORE_WHITESPACE, false);
+ }
+
+ private IDocument getDocument(char contributor) {
+ return fInput.getDocument(contributor);
+ }
+
+ private Position getRegion(char contributor) {
+ return fInput.getRegion(contributor);
+ }
+
+ public boolean isIgnoreAncestor() {
+ return fInput.isIgnoreAncestor();
+ }
+
+ public boolean isThreeWay() {
+ return fInput.isThreeWay();
+ }
+
+ /**
+ * Return the compare configuration associated with this merger.
+ * @return the compare configuration associated with this merger
+ */
+ public CompareConfiguration getCompareConfiguration() {
+ return fInput.getCompareConfiguration();
+ }
+
+ /*
+ * Returns true if kind of change should be shown.
+ */
+ public boolean useChange(Diff diff) {
+ if (diff.fIsWhitespace)
+ return false;
+ int kind = diff.getKind();
+ return useChange(kind);
+ }
+
+ private boolean useChange(int kind) {
+ if (kind == RangeDifference.NOCHANGE)
+ return false;
+ if (kind == RangeDifference.ANCESTOR)
+ return fInput.isShowPseudoConflicts();
+ return true;
+ }
+
+ private int getTokenEnd(ITokenComparator tc, int start, int count) {
+ if (count <= 0)
+ return tc.getTokenStart(start);
+ int index= start + count - 1;
+ return tc.getTokenStart(index) + tc.getTokenLength(index);
+ }
+
+ private static int getTokenEnd2(ITokenComparator tc, int start, int length) {
+ return tc.getTokenStart(start + length);
+ }
+
+ /**
+ * Returns the content of lines in the specified range as a String.
+ * This includes the line separators.
+ *
+ * @param doc the document from which to extract the characters
+ * @param start index of first line
+ * @param length number of lines
+ * @return the contents of the specified line range as a String
+ */
+ private String extract2(IDocument doc, ITokenComparator tc, int start, int length) {
+ int count= tc.getRangeCount();
+ if (length > 0 && count > 0) {
+
+//
+// int startPos= tc.getTokenStart(start);
+// int endPos= startPos;
+//
+// if (length > 1)
+// endPos= tc.getTokenStart(start + (length-1));
+// endPos+= tc.getTokenLength(start + (length-1));
+//
+
+ int startPos= tc.getTokenStart(start);
+ int endPos;
+
+ if (length == 1) {
+ endPos= startPos + tc.getTokenLength(start);
+ } else {
+ endPos= tc.getTokenStart(start + length);
+ }
+
+ try {
+ return doc.get(startPos, endPos - startPos);
+ } catch (BadLocationException e) {
+ // silently ignored
+ }
+
+ }
+ return ""; //$NON-NLS-1$
+ }
+
+ private static IRegion toRegion(Position position) {
+ if (position != null)
+ return new Region(position.getOffset(), position.getLength());
+ return null;
+ }
+
+ /*
+ * Performs a "smart" token based 3-way diff on the character range specified by the given baseDiff.
+ * It is "smart" because it tries to minimize the number of token diffs by merging them.
+ */
+ private void mergingTokenDiff(Diff baseDiff,
+ IDocument ancestorDoc, String a,
+ IDocument rightDoc, String d,
+ IDocument leftDoc, String s) {
+ ITokenComparator sa= null;
+ int ancestorStart= 0;
+ if (ancestorDoc != null) {
+ sa= createTokenComparator(a);
+ ancestorStart= baseDiff.fAncestorPos.getOffset();
+ }
+
+ int rightStart= baseDiff.fRightPos.getOffset();
+ ITokenComparator sm= createTokenComparator(d);
+
+ int leftStart= baseDiff.fLeftPos.getOffset();
+ ITokenComparator sy= createTokenComparator(s);
+
+ RangeDifference[] r= RangeDifferencer.findRanges(sa, sy, sm);
+ for (int i= 0; i < r.length; i++) {
+ RangeDifference es= r[i];
+ // determine range of diffs in one line
+ int start= i;
+ int leftLine= -1;
+ int rightLine= -1;
+ try {
+ leftLine= leftDoc.getLineOfOffset(leftStart+sy.getTokenStart(es.leftStart()));
+ rightLine= rightDoc.getLineOfOffset(rightStart+sm.getTokenStart(es.rightStart()));
+ } catch (BadLocationException e) {
+ // silently ignored
+ }
+ i++;
+ for (; i < r.length; i++) {
+ es= r[i];
+ try {
+ if (leftLine != leftDoc.getLineOfOffset(leftStart+sy.getTokenStart(es.leftStart())))
+ break;
+ if (rightLine != rightDoc.getLineOfOffset(rightStart+sm.getTokenStart(es.rightStart())))
+ break;
+ } catch (BadLocationException e) {
+ // silently ignored
+ }
+ }
+ int end= i;
+
+ // find first diff from left
+ RangeDifference first= null;
+ for (int ii= start; ii < end; ii++) {
+ es= r[ii];
+ if (useChange(es.kind())) {
+ first= es;
+ break;
+ }
+ }
+
+ // find first diff from mine
+ RangeDifference last= null;
+ for (int ii= end-1; ii >= start; ii--) {
+ es= r[ii];
+ if (useChange(es.kind())) {
+ last= es;
+ break;
+ }
+ }
+
+ if (first != null && last != null) {
+
+ int ancestorStart2= 0;
+ int ancestorEnd2= 0;
+ if (ancestorDoc != null) {
+ ancestorStart2= ancestorStart+sa.getTokenStart(first.ancestorStart());
+ ancestorEnd2= ancestorStart+getTokenEnd(sa, last.ancestorStart(), last.ancestorLength());
+ }
+
+ int leftStart2= leftStart+sy.getTokenStart(first.leftStart());
+ int leftEnd2= leftStart+getTokenEnd(sy, last.leftStart(), last.leftLength());
+
+ int rightStart2= rightStart+sm.getTokenStart(first.rightStart());
+ int rightEnd2= rightStart+getTokenEnd(sm, last.rightStart(), last.rightLength());
+ Diff diff= new Diff(baseDiff, first.kind(),
+ ancestorDoc, null, ancestorStart2, ancestorEnd2,
+ leftDoc, null, leftStart2, leftEnd2,
+ rightDoc, null, rightStart2, rightEnd2);
+ diff.fIsToken= true;
+ baseDiff.add(diff);
+ }
+ }
+ }
+
+ /*
+ * Performs a token based 3-way diff on the character range specified by the given baseDiff.
+ */
+ private void simpleTokenDiff(final Diff baseDiff,
+ IDocument ancestorDoc, String a,
+ IDocument rightDoc, String d,
+ IDocument leftDoc, String s) {
+
+ int ancestorStart= 0;
+ ITokenComparator sa= null;
+ if (ancestorDoc != null) {
+ ancestorStart= baseDiff.fAncestorPos.getOffset();
+ sa= createTokenComparator(a);
+ }
+
+ int rightStart= baseDiff.fRightPos.getOffset();
+ ITokenComparator sm= createTokenComparator(d);
+
+ int leftStart= baseDiff.fLeftPos.getOffset();
+ ITokenComparator sy= createTokenComparator(s);
+
+ RangeDifference[] e= RangeDifferencer.findRanges(sa, sy, sm);
+ for (int i= 0; i < e.length; i++) {
+ RangeDifference es= e[i];
+ int kind= es.kind();
+ if (kind != RangeDifference.NOCHANGE) {
+
+ int ancestorStart2= ancestorStart;
+ int ancestorEnd2= ancestorStart;
+ if (ancestorDoc != null) {
+ ancestorStart2 += sa.getTokenStart(es.ancestorStart());
+ ancestorEnd2 += getTokenEnd(sa, es.ancestorStart(), es.ancestorLength());
+ }
+
+ int leftStart2= leftStart + sy.getTokenStart(es.leftStart());
+ int leftEnd2= leftStart + getTokenEnd(sy, es.leftStart(), es.leftLength());
+
+ int rightStart2= rightStart + sm.getTokenStart(es.rightStart());
+ int rightEnd2= rightStart + getTokenEnd(sm, es.rightStart(), es.rightLength());
+
+ Diff diff= new Diff(baseDiff, kind,
+ ancestorDoc, null, ancestorStart2, ancestorEnd2,
+ leftDoc, null, leftStart2, leftEnd2,
+ rightDoc, null, rightStart2, rightEnd2);
+
+ // ensure that token diff is smaller than basediff
+ int leftS= baseDiff.fLeftPos.offset;
+ int leftE= baseDiff.fLeftPos.offset+baseDiff.fLeftPos.length;
+ int rightS= baseDiff.fRightPos.offset;
+ int rightE= baseDiff.fRightPos.offset+baseDiff.fRightPos.length;
+ if (leftS != leftStart2 || leftE != leftEnd2 ||
+ rightS != rightStart2 || rightE != rightEnd2) {
+ diff.fIsToken= true;
+ // add to base Diff
+ baseDiff.add(diff);
+ }
+ }
+ }
+ }
+
+ private ITokenComparator createTokenComparator(String s) {
+ return fInput.createTokenComparator(s);
+ }
+
+ private static int maxWork(IRangeComparator a, IRangeComparator l, IRangeComparator r) {
+ int ln= l.getRangeCount();
+ int rn= r.getRangeCount();
+ if (a != null) {
+ int an= a.getRangeCount();
+ return (2 * Math.max(an, ln)) + (2 * Math.max(an, rn));
+ }
+ return 2 * Math.max(ln, rn);
+ }
+
+ private void resetPositions(IDocument doc) {
+ if (doc == null)
+ return;
+ try {
+ doc.removePositionCategory(DIFF_RANGE_CATEGORY);
+ } catch (BadPositionCategoryException e) {
+ // Ignore
+ }
+ doc.addPositionCategory(DIFF_RANGE_CATEGORY);
+ }
+
+ /*
+ * Returns the start line and the number of lines which correspond to the given position.
+ * Starting line number is 0 based.
+ */
+ protected Point getLineRange(IDocument doc, Position p, Point region) {
+
+ if (p == null || doc == null) {
+ region.x= 0;
+ region.y= 0;
+ return region;
+ }
+
+ int start= p.getOffset();
+ int length= p.getLength();
+
+ int startLine= 0;
+ try {
+ startLine= doc.getLineOfOffset(start);
+ } catch (BadLocationException e) {
+ // silently ignored
+ }
+
+ int lineCount= 0;
+
+ if (length == 0) {
+// // if range length is 0 and if range starts a new line
+// try {
+// if (start == doc.getLineStartOffset(startLine)) {
+// lines--;
+// }
+// } catch (BadLocationException e) {
+// lines--;
+// }
+
+ } else {
+ int endLine= 0;
+ try {
+ endLine= doc.getLineOfOffset(start + length - 1); // why -1?
+ } catch (BadLocationException e) {
+ // silently ignored
+ }
+ lineCount= endLine-startLine+1;
+ }
+
+ region.x= startLine;
+ region.y= lineCount;
+ return region;
+ }
+
+ public Diff findDiff(Position p, boolean left) {
+ for (Iterator iterator = fAllDiffs.iterator(); iterator.hasNext();) {
+ Diff diff = (Diff) iterator.next();
+ Position diffPos;
+ if (left) {
+ diffPos = diff.fLeftPos;
+ } else {
+ diffPos = diff.fRightPos;
+ }
+ // If the element falls within a diff, highlight that diff
+ if (diffPos.offset + diffPos.length >= p.offset && diff.fDirection != RangeDifference.NOCHANGE)
+ return diff;
+ // Otherwise, highlight the first diff after the elements position
+ if (diffPos.offset >= p.offset)
+ return diff;
+ }
+ return null;
+ }
+
+ public void reset() {
+ fChangeDiffs= null;
+ fAllDiffs= null;
+ }
+
+ /**
+ * Returns the virtual position for the given view position.
+ * @param contributor
+ * @param vpos
+ * @return the virtual position for the given view position
+ */
+ public int realToVirtualPosition(char contributor, int vpos) {
+
+ if (fAllDiffs == null)
+ return vpos;
+
+ int viewPos= 0; // real view position
+ int virtualPos= 0; // virtual position
+ Point region= new Point(0, 0);
+
+ Iterator e= fAllDiffs.iterator();
+ while (e.hasNext()) {
+ Diff diff= (Diff) e.next();
+ Position pos= diff.getPosition(contributor);
+ getLineRange(getDocument(contributor),pos, region);
+ int realHeight= region.y;
+ int virtualHeight= diff.getMaxDiffHeight();
+ if (vpos <= viewPos + realHeight) { // OK, found!
+ vpos-= viewPos; // make relative to this slot
+ // now scale position within this slot to virtual slot
+ if (realHeight <= 0)
+ vpos= 0;
+ else
+ vpos= (vpos*virtualHeight)/realHeight;
+ return virtualPos+vpos;
+ }
+ viewPos+= realHeight;
+ virtualPos+= virtualHeight;
+ }
+ return virtualPos;
+ }
+
+ /**
+ * maps given virtual position into a real view position of this view.
+ * @param contributor
+ * @param v
+ * @return the real view position
+ */
+ public int virtualToRealPosition(char contributor, int v) {
+
+ if (fAllDiffs == null)
+ return v;
+
+ int virtualPos= 0;
+ int viewPos= 0;
+ Point region= new Point(0, 0);
+
+ Iterator e= fAllDiffs.iterator();
+ while (e.hasNext()) {
+ Diff diff= (Diff) e.next();
+ Position pos= diff.getPosition(contributor);
+ int viewHeight= getLineRange(getDocument(contributor), pos, region).y;
+ int virtualHeight= diff.getMaxDiffHeight();
+ if (v < (virtualPos + virtualHeight)) {
+ v-= virtualPos; // make relative to this slot
+ if (viewHeight <= 0) {
+ v= 0;
+ } else {
+ v= (int) (v * ((double)viewHeight/virtualHeight));
+ }
+ return viewPos+v;
+ }
+ virtualPos+= virtualHeight;
+ viewPos+= viewHeight;
+ }
+ return viewPos;
+ }
+
+ /*
+ * Calculates virtual height (in lines) of views by adding the maximum of corresponding diffs.
+ */
+ public int getVirtualHeight() {
+ int h= 1;
+ if (fAllDiffs != null) {
+ Iterator e= fAllDiffs.iterator();
+ for (int i= 0; e.hasNext(); i++) {
+ Diff diff= (Diff) e.next();
+ h+= diff.getMaxDiffHeight();
+ }
+ }
+ return h;
+ }
+
+ /*
+ * Calculates height (in lines) of right view by adding the height of the right diffs.
+ */
+ public int getRightHeight() {
+ int h= 1;
+ if (fAllDiffs != null) {
+ Iterator e= fAllDiffs.iterator();
+ for (int i= 0; e.hasNext(); i++) {
+ Diff diff= (Diff) e.next();
+ h+= diff.getRightHeight();
+ }
+ }
+ return h;
+ }
+
+ public int findInsertionPoint(Diff diff, char type) {
+ if (diff != null) {
+ switch (type) {
+ case MergeViewerContentProvider.ANCESTOR_CONTRIBUTOR:
+ if (diff.fAncestorPos != null)
+ return diff.fAncestorPos.offset;
+ break;
+ case MergeViewerContentProvider.LEFT_CONTRIBUTOR:
+ if (diff.fLeftPos != null)
+ return diff.fLeftPos.offset;
+ break;
+ case MergeViewerContentProvider.RIGHT_CONTRIBUTOR:
+ if (diff.fRightPos != null)
+ return diff.fRightPos.offset;
+ break;
+ }
+ }
+ return 0;
+ }
+
+ public Diff[] getChangeDiffs(char contributor, IRegion region) {
+ if (fChangeDiffs == null)
+ return new Diff[0];
+ List intersectingDiffs = new ArrayList();
+ for (Iterator iterator = fChangeDiffs.iterator(); iterator.hasNext();) {
+ Diff diff = (Diff) iterator.next();
+ Diff[] changeDiffs = diff.getChangeDiffs(contributor, region);
+ for (int i = 0; i < changeDiffs.length; i++) {
+ Diff changeDiff = changeDiffs[i];
+ intersectingDiffs.add(changeDiff);
+ }
+ }
+ return (Diff[]) intersectingDiffs.toArray(new Diff[intersectingDiffs.size()]);
+ }
+
+ public Diff findDiff(int viewportHeight, boolean synchronizedScrolling, Point size, int my) {
+ int virtualHeight= synchronizedScrolling ? getVirtualHeight() : getRightHeight();
+ if (virtualHeight < viewportHeight)
+ return null;
+
+ int yy, hh;
+ int y= 0;
+ if (fAllDiffs != null) {
+ Iterator e= fAllDiffs.iterator();
+ for (int i= 0; e.hasNext(); i++) {
+ Diff diff= (Diff) e.next();
+ int h= synchronizedScrolling ? diff.getMaxDiffHeight()
+ : diff.getRightHeight();
+ if (useChange(diff.getKind()) && !diff.fIsWhitespace) {
+
+ yy= (y*size.y)/virtualHeight;
+ hh= (h*size.y)/virtualHeight;
+ if (hh < 3)
+ hh= 3;
+
+ if (my >= yy && my < yy+hh)
+ return diff;
+ }
+ y+= h;
+ }
+ }
+ return null;
+ }
+
+ public boolean hasChanges() {
+ return fChangeDiffs != null && !fChangeDiffs.isEmpty();
+ }
+
+ public Iterator changesIterator() {
+ if (fChangeDiffs == null)
+ return new ArrayList().iterator();
+ return fChangeDiffs.iterator();
+ }
+
+ public Iterator rangesIterator() {
+ if (fAllDiffs == null)
+ return new ArrayList().iterator();
+ return fAllDiffs.iterator();
+ }
+
+ public boolean isFirstChildDiff(char contributor, int startOffset,
+ Diff diff) {
+ if (!diff.hasChildren())
+ return false;
+ Diff d = (Diff)diff.fDiffs.get(0);
+ Position p= d.getPosition(contributor);
+ return (p.getOffset() >= startOffset);
+ }
+
+ public Diff getWrappedDiff(Diff diff, boolean down) {
+ if (fChangeDiffs != null && fChangeDiffs.size() > 0) {
+ if (down)
+ return (Diff) fChangeDiffs.get(0);
+ return (Diff) fChangeDiffs.get(fChangeDiffs.size()-1);
+ }
+ return null;
+ }
+
+ /*
+ * Copy the contents of the given diff from one side to the other but
+ * doesn't reveal anything.
+ * Returns true if copy was successful.
+ */
+ public boolean copy(Diff diff, boolean leftToRight) {
+
+ if (diff != null && !diff.isResolved()) {
+ Position fromPos= null;
+ Position toPos= null;
+ IDocument fromDoc= null;
+ IDocument toDoc= null;
+
+ if (leftToRight) {
+ fromPos= diff.getPosition(MergeViewerContentProvider.LEFT_CONTRIBUTOR);
+ toPos= diff.getPosition(MergeViewerContentProvider.RIGHT_CONTRIBUTOR);
+ fromDoc= getDocument(MergeViewerContentProvider.LEFT_CONTRIBUTOR);
+ toDoc= getDocument(MergeViewerContentProvider.RIGHT_CONTRIBUTOR);
+ } else {
+ fromPos= diff.getPosition(MergeViewerContentProvider.RIGHT_CONTRIBUTOR);
+ toPos= diff.getPosition(MergeViewerContentProvider.LEFT_CONTRIBUTOR);
+ fromDoc= getDocument(MergeViewerContentProvider.RIGHT_CONTRIBUTOR);
+ toDoc= getDocument(MergeViewerContentProvider.LEFT_CONTRIBUTOR);
+ }
+
+ if (fromDoc != null) {
+
+ int fromStart= fromPos.getOffset();
+ int fromLen= fromPos.getLength();
+
+ int toStart= toPos.getOffset();
+ int toLen= toPos.getLength();
+
+ try {
+ String s= null;
+
+ switch (diff.getKind()) {
+ case RangeDifference.RIGHT:
+ case RangeDifference.LEFT:
+ s= fromDoc.get(fromStart, fromLen);
+ break;
+ case RangeDifference.ANCESTOR:
+ break;
+ case RangeDifference.CONFLICT:
+ if (APPEND_CONFLICT) {
+ s= toDoc.get(toStart, toLen);
+ s+= fromDoc.get(fromStart, fromLen);
+ } else
+ s= fromDoc.get(fromStart, fromLen);
+ break;
+ }
+ if (s != null) {
+ toDoc.replace(toStart, toLen, s);
+ toPos.setOffset(toStart);
+ toPos.setLength(s.length());
+ }
+
+ } catch (BadLocationException e) {
+ // silently ignored
+ }
+ }
+
+ diff.setResolved(true);
+ return true;
+ }
+ return false;
+ }
+
+ public int changesCount() {
+ if (fChangeDiffs == null)
+ return 0;
+ return fChangeDiffs.size();
+ }
+
+ public Diff findDiff(char contributor, int rangeStart, int rangeEnd) {
+ if (hasChanges()) {
+ for (Iterator iterator = changesIterator(); iterator.hasNext();) {
+ Diff diff = (Diff) iterator.next();
+ if (diff.isDeleted() || diff.getKind() == RangeDifference.NOCHANGE)
+ continue;
+ if (diff.overlaps(contributor, rangeStart, rangeEnd))
+ return diff;
+ }
+ }
+ return null;
+ }
+
+ public Diff findDiff(char contributor, Position range) {
+ int start= range.getOffset();
+ int end= start + range.getLength();
+ return findDiff(contributor, start, end);
+ }
+
+ public Diff findNext(char contributor, int start, int end, boolean deep) {
+ return findNext(contributor, fChangeDiffs, start, end, deep);
+ }
+
+ private Diff findNext(char contributor, List v, int start, int end, boolean deep) {
+ if (v == null)
+ return null;
+ for (int i= 0; i < v.size(); i++) {
+ Diff diff= (Diff) v.get(i);
+ Position p= diff.getPosition(contributor);
+ if (p != null) {
+ int startOffset= p.getOffset();
+ if (end < startOffset) // <=
+ return diff;
+ if (deep && diff.hasChildren()) {
+ Diff d= null;
+ int endOffset= startOffset + p.getLength();
+ if (start == startOffset && (end == endOffset || end == endOffset-1)) {
+ d= findNext(contributor, diff.fDiffs, start-1, start-1, deep);
+ } else if (end < endOffset) {
+ d= findNext(contributor, diff.fDiffs, start, end, deep);
+ }
+ if (d != null)
+ return d;
+ }
+ }
+ }
+ return null;
+ }
+
+ public Diff findPrev(char contributor, int start, int end, boolean deep) {
+ return findPrev(contributor, fChangeDiffs, start, end, deep);
+ }
+
+ private Diff findPrev(char contributor, List v, int start, int end, boolean deep) {
+ if (v == null)
+ return null;
+ for (int i= v.size()-1; i >= 0; i--) {
+ Diff diff= (Diff) v.get(i);
+ Position p= diff.getPosition(contributor);
+ if (p != null) {
+ int startOffset= p.getOffset();
+ int endOffset= startOffset + p.getLength();
+ if (start > endOffset) {
+ if (deep && diff.hasChildren()) {
+ // If we are going deep, find the last change in the diff
+ return findPrev(contributor, diff.fDiffs, end, end, deep);
+ }
+ return diff;
+ }
+ if (deep && diff.hasChildren()) {
+ Diff d= null;
+ if (start == startOffset && end == endOffset) {
+ // A whole diff is selected so we'll fall through
+ // and go the the last change in the previous diff
+ } else if (start >= startOffset) {
+ // If we are at or before the first diff, select the
+ // entire diff so next and previous are symmetrical
+ if (isFirstChildDiff(contributor, startOffset, diff)) {
+ return diff;
+ }
+ d= findPrev(contributor, diff.fDiffs, start, end, deep);
+ }
+ if (d != null)
+ return d;
+ }
+ }
+ }
+ return null;
+ }
+
+}

Back to the top