Mercurial > projects > dwt-addons
diff dwtx/jface/internal/text/revisions/ChangeRegion.d @ 129:eb30df5ca28b
Added JFace Text sources
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Sat, 23 Aug 2008 19:10:48 +0200 |
parents | |
children | c4fb132a086c |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwtx/jface/internal/text/revisions/ChangeRegion.d Sat Aug 23 19:10:48 2008 +0200 @@ -0,0 +1,168 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 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 + * Port to the D programming language: + * Frank Benoit <benoit@tionex.de> + *******************************************************************************/ +module dwtx.jface.internal.text.revisions.ChangeRegion; + +import dwt.dwthelper.utils; + +import java.util.LinkedList; +import java.util.List; +import java.util.ListIterator; + +import dwtx.core.runtime.Assert; +import dwtx.jface.text.revisions.Revision; +import dwtx.jface.text.source.ILineRange; +import dwtx.jface.text.source.LineRange; + +/** + * A change region describes a contiguous range of lines that was changed in the same revision of a + * document. Once it is adjusted to diff information, the originally contiguous range may be split + * into several ranges or even be empty. + * + * @since 3.2 + */ +public final class ChangeRegion { + private final Revision fRevision; + private final ILineRange fLines; + private final List fAdjusted= new LinkedList(); + + /** + * Creates a new change region for the given revision and line range. + * + * @param revision the revision of the new region + * @param lines the line range of the new region + * @throws IndexOutOfBoundsException if the line range is not well-formed + */ + public ChangeRegion(Revision revision, ILineRange lines) throws IndexOutOfBoundsException { + Assert.isLegal(revision !is null); + Assert.isLegal(lines !is null); + fLines= Range.copy(lines); + fRevision=revision; + clearDiff(); + } + + /** + * Returns the revision that this region belongs to. + * + * @return the revision that this region belongs to + */ + public Revision getRevision() { + return fRevision; + } + + /** + * Returns the original (before applying diff information) line range of this change region. + * + * @return the original (before applying diff information) line range of this change region + */ + public ILineRange getOriginalRange() { + return fLines; + } + + /** + * Returns the list of {@link ILineRange}s of this change region for which the revision + * information is still valid. + * + * @return the list of adjusted line ranges + */ + public List getAdjustedRanges() { + return fAdjusted; + } + + /** + * Returns the line coverage of the adjusted ranges, an empty range if the coverage is empty. + * + * @return the line coverage of the adjusted ranges + */ + public ILineRange getAdjustedCoverage() { + if (fAdjusted.isEmpty()) + return new LineRange(fLines.getStartLine(), 0); + + Range first= (Range) fAdjusted.get(0); + Range last= (Range) fAdjusted.get(fAdjusted.size() - 1); + + return Range.createAbsolute(first.start(), last.end()); + } + + /** + * Clears any adjusted ranges, restoring the original range. + */ + public void clearDiff() { + fAdjusted.clear(); + fAdjusted.add(Range.copy(fLines)); + } + + /** + * Adjusts this change region to a diff hunk. This will change the adjusted ranges. + * + * @param hunk the diff hunk to adjust to + */ + public void adjustTo(Hunk hunk) { + for (ListIterator it= fAdjusted.listIterator(); it.hasNext();) { + Range range= (Range) it.next(); + + // do we need a split? + int unchanged= getUnchanged(hunk, range.start()); + if (unchanged > 0) { + if (unchanged >= range.length()) + continue; + range= range.split(unchanged); + it.add(range); + it.previous(); it.next(); // needed so we can remove below + } + + int line= range.start(); + Assert.isTrue(hunk.line <= line); + + // by how much do we shrink? + int overlap= getOverlap(hunk, line); + if (overlap >= range.length()) { + it.remove(); + continue; + } + + // by how much do we move? + range.moveBy(hunk.delta + overlap); + range.resizeBy(-overlap); + } + + } + + private int getUnchanged(Hunk hunk, int line) { + return Math.max(0, hunk.line - line); + } + + /* + * Returns the number of lines after line that the hunk reports as changed. + */ + private int getOverlap(Hunk hunk, int line) { + + int deltaLine= hunk.line + hunk.changed; + if (hunk.delta >= 0) { + if (deltaLine <= line) + return 0; + return deltaLine - line; + } + + // hunk.delta < 0 + int hunkEnd= deltaLine - hunk.delta; + int cutCount= hunkEnd - line; + return Math.max(0, cutCount); + } + + /* + * @see java.lang.Object#toString() + */ + public String toString() { + return "ChangeRegion [" + fRevision.toString() + ", [" + fLines.getStartLine() + "+" + fLines.getNumberOfLines() + ")]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ + } +}