All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.jface.text.projection.ProjectionMapping Maven / Gradle / Ivy

Go to download

AspectJ tools most notably contains the AspectJ compiler (AJC). AJC applies aspects to Java classes during compilation, fully replacing Javac for plain Java classes and also compiling native AspectJ or annotation-based @AspectJ syntax. Furthermore, AJC can weave aspects into existing class files in a post-compile binary weaving step. This library is a superset of AspectJ weaver and hence also of AspectJ runtime.

There is a newer version: 1.9.22.1
Show newest version
/*******************************************************************************
 * Copyright (c) 2000, 2010 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.jface.text.projection;

import org.eclipse.core.runtime.Assert;

import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.BadPositionCategoryException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentInformationMapping;
import org.eclipse.jface.text.IDocumentInformationMappingExtension;
import org.eclipse.jface.text.IDocumentInformationMappingExtension2;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.Position;
import org.eclipse.jface.text.Region;


/**
 * Internal class. Do not use. Only public for testing purposes.
 * 

* Implementation of {@link org.eclipse.jface.text.IDocumentInformationMapping} * for the projection mapping between a master and a slave document. * * @since 3.0 * @noinstantiate This class is not intended to be instantiated by clients. * @noextend This class is not intended to be subclassed by clients. */ public class ProjectionMapping implements IDocumentInformationMapping , IDocumentInformationMappingExtension, IDocumentInformationMappingExtension2, IMinimalMapping { private static final int LEFT= -1; private static final int NONE= 0; private static final int RIGHT= +1; /** The master document */ private IDocument fMasterDocument; /** The position category used to manage the projection fragments inside the master document */ private String fFragmentsCategory; /** The projection document */ private IDocument fSlaveDocument; /** The position category to manage the projection segments inside the slave document. */ private String fSegmentsCategory; /** Cached segments */ private Position[] fCachedSegments; /** Cached fragments */ private Position[] fCachedFragments; /** * Creates a new mapping between the given parent document and the given projection document. * * @param masterDocument the master document * @param fragmentsCategory the position category of the parent document used to manage the projected regions * @param slaveDocument the slave document * @param segmentsCategory the position category of the projection document used to manage the fragments */ public ProjectionMapping(IDocument masterDocument, String fragmentsCategory, IDocument slaveDocument, String segmentsCategory) { fMasterDocument= masterDocument; fFragmentsCategory= fragmentsCategory; fSlaveDocument= slaveDocument; fSegmentsCategory= segmentsCategory; } /** * Notifies this projection mapping that there was a projection change. */ public void projectionChanged() { fCachedSegments= null; fCachedFragments= null; } private Position[] getSegments() { if (fCachedSegments == null) { try { fCachedSegments= fSlaveDocument.getPositions(fSegmentsCategory); } catch (BadPositionCategoryException e) { return new Position[0]; } } return fCachedSegments; } private Position[] getFragments() { if (fCachedFragments == null) { try { fCachedFragments= fMasterDocument.getPositions(fFragmentsCategory); } catch (BadPositionCategoryException e) { return new Position[0]; } } return fCachedFragments; } private int findSegmentIndex(int offset) throws BadLocationException { Position[] segments= getSegments(); if (segments.length == 0) { if (offset > 0) throw new BadLocationException(); return -1; } try { int index= fSlaveDocument.computeIndexInCategory(fSegmentsCategory, offset); if (index == segments.length && offset > exclusiveEnd(segments[index-1])) throw new BadLocationException(); if (index < segments.length && offset == segments[index].offset) return index; if (index > 0) index--; return index; } catch (BadPositionCategoryException e) { throw new IllegalStateException(); } } private Segment findSegment(int offset) throws BadLocationException { checkImageOffset(offset); int index= findSegmentIndex(offset); if (index == -1) { Segment s= new Segment(0, 0); Fragment f= new Fragment(0, 0); s.fragment= f; f.segment= s; return s; } Position[] segments= getSegments(); return (Segment) segments[index]; } /** * Computes the fragment index given an origin offset. Returns the index of * the fragment that contains offset, or -1 * if no fragment contains offset. *

* If extensionDirection is set to RIGHT or * LEFT, the next fragment in that direction is returned if * there is no fragment containing offset. Note that if * offset occurs before any fragment and * extensionDirection is LEFT, * -1 is also returned. The same applies for an offset after * the last fragment and extensionDirection set to * RIGHT. *

* * @param offset an origin offset * @param extensionDirection the direction in which to extend the search, or * NONE * @return the index of the fragment containing offset, or * -1 * @throws BadLocationException if the index is not valid on the master * document */ private int findFragmentIndex(int offset, int extensionDirection) throws BadLocationException { try { Position[] fragments= getFragments(); if (fragments.length == 0) return -1; int index= fMasterDocument.computeIndexInCategory(fFragmentsCategory, offset); if (index < fragments.length && offset == fragments[index].offset) return index; if (0 < index && index <= fragments.length && fragments[index - 1].includes(offset)) return index - 1; switch (extensionDirection) { case LEFT: return index - 1; case RIGHT: if (index < fragments.length) return index; } return -1; } catch (BadPositionCategoryException e) { throw new IllegalStateException(); } } private Fragment findFragment(int offset) throws BadLocationException { checkOriginOffset(offset); int index= findFragmentIndex(offset, NONE); Position[] fragments= getFragments(); if (index == -1) { if (fragments.length > 0) { Fragment last= (Fragment) fragments[fragments.length - 1]; if (exclusiveEnd(last) == offset) return last; } return null; } return (Fragment) fragments[index]; } /** * Returns the image region for originRegion. * * @param originRegion the region to get the image for * @param exact if true, the begin and end offsets of * originRegion must be projected, otherwise * null is returned. If false, the * begin and end range that is not visible is simply clipped. * @param takeClosestImage if false, null is * returned if originRegion is completely invisible. * If true, the zero-length region is returned that * "covers" the hidden origin region * @return the image region of originRegion * @throws BadLocationException if the region is not a valid origin region */ private IRegion toImageRegion(IRegion originRegion, boolean exact, boolean takeClosestImage) throws BadLocationException { if (originRegion.getLength() == 0 && !takeClosestImage) { int imageOffset= toImageOffset(originRegion.getOffset()); return imageOffset == -1 ? null : new Region(imageOffset, 0); } Fragment[] fragments= findFragments(originRegion, exact, takeClosestImage); if (fragments == null) { if (takeClosestImage) { // originRegion may before the first or after the last fragment Position[] allFragments= getFragments(); if (allFragments.length > 0) { // before the first if (exclusiveEnd(originRegion) <= allFragments[0].getOffset()) return new Region(0, 0); // after last Position last= allFragments[allFragments.length - 1]; if (originRegion.getOffset() >= exclusiveEnd(last)) return new Region(exclusiveEnd(((Fragment) last).segment), 0); } return new Region(0, 0); } return null; } int imageOffset, exclusiveImageEndOffset; // translate start offset int relative= originRegion.getOffset() - fragments[0].getOffset(); if (relative < 0) { Assert.isTrue(!exact); relative= 0; } imageOffset= fragments[0].segment.getOffset() + relative; // translate end offset relative= exclusiveEnd(originRegion) - fragments[1].getOffset(); if (relative > fragments[1].getLength()) { Assert.isTrue(!exact); relative= fragments[1].getLength(); } exclusiveImageEndOffset= fragments[1].segment.getOffset() + relative; return new Region(imageOffset, exclusiveImageEndOffset - imageOffset); } /** * Returns the two fragments containing the begin and end offsets of * originRegion. * * @param originRegion the region to get the fragments for * @param exact if true, only the fragments that contain the * begin and end offsets are returned; if false, the * first fragment after the begin offset and the last fragment before * the end offset are returned if the offsets are not projected * @param takeClosestImage if true, the method will return * fragments also if originRegion completely lies in * an unprojected region. * @return the two fragments containing the begin and end offset of * originRegion, or null if these do * not exist * @throws BadLocationException if the region is not a valid origin region */ private Fragment[] findFragments(IRegion originRegion, boolean exact, boolean takeClosestImage) throws BadLocationException { Position[] fragments= getFragments(); if (fragments.length == 0) return null; checkOriginRegion(originRegion); int startFragmentIdx= findFragmentIndex(originRegion.getOffset(), exact ? NONE : RIGHT); if (startFragmentIdx == -1) return null; int endFragmentIdx= findFragmentIndex(inclusiveEnd(originRegion), exact ? NONE : LEFT); if (!takeClosestImage && startFragmentIdx > endFragmentIdx || endFragmentIdx == -1) return null; Fragment[] result= {(Fragment) fragments[startFragmentIdx], (Fragment) fragments[endFragmentIdx]}; return result; } private IRegion createOriginStartRegion(Segment image, int offsetShift) { return new Region(image.fragment.getOffset() + offsetShift, image.fragment.getLength() - offsetShift); } private IRegion createOriginRegion(Segment image) { return new Region(image.fragment.getOffset(), image.fragment.getLength()); } private IRegion createOriginEndRegion(Segment image, int lengthReduction) { return new Region(image.fragment.getOffset(), image.fragment.getLength() - lengthReduction); } private IRegion createImageStartRegion(Fragment origin, int offsetShift) { int shift= offsetShift > 0 ? offsetShift : 0; return new Region(origin.segment.getOffset() + shift, origin.segment.getLength() - shift); } private IRegion createImageRegion(Fragment origin) { return new Region(origin.segment.getOffset(), origin.segment.getLength()); } private IRegion createImageEndRegion(Fragment origin, int lengthReduction) { int reduction= lengthReduction > 0 ? lengthReduction : 0; return new Region(origin.segment.getOffset(), origin.segment.getLength() - reduction); } private IRegion createOriginStartRegion(Fragment origin, int offsetShift) { int shift= offsetShift > 0 ? offsetShift : 0; return new Region(origin.getOffset() + shift, origin.getLength() - shift); } private IRegion createOriginRegion(Fragment origin) { return new Region(origin.getOffset(), origin.getLength()); } private IRegion createOriginEndRegion(Fragment origin, int lengthReduction) { int reduction= lengthReduction > 0 ? lengthReduction : 0; return new Region(origin.getOffset(), origin.getLength() - reduction); } private IRegion getIntersectingRegion(IRegion left, IRegion right) { int offset= Math.max(left.getOffset(), right.getOffset()); int exclusiveEndOffset= Math.min(exclusiveEnd(left), exclusiveEnd(right)); if (exclusiveEndOffset < offset) return null; return new Region(offset, exclusiveEndOffset - offset); } @Override public IRegion getCoverage() { Position[] fragments= getFragments(); if (fragments != null && fragments.length > 0) { Position first=fragments[0]; Position last= fragments[fragments.length -1]; return new Region(first.offset, exclusiveEnd(last) - first.offset); } return new Region(0, 0); } @Override public int toOriginOffset(int imageOffset) throws BadLocationException { Segment segment= findSegment(imageOffset); int relative= imageOffset - segment.offset; return segment.fragment.offset + relative; } @Override public IRegion toOriginRegion(IRegion imageRegion) throws BadLocationException { int imageOffset= imageRegion.getOffset(); int imageLength= imageRegion.getLength(); if (imageLength == 0) { if (imageOffset == 0) { Position[] fragments= getFragments(); if (fragments.length == 0 || (fragments.length == 1 && fragments[0].getOffset() == 0 && fragments[0].getLength() == 0)) return new Region(0, fMasterDocument.getLength()); } return new Region(toOriginOffset(imageOffset), 0); } int originOffset= toOriginOffset(imageOffset); int inclusiveImageEndOffset= imageOffset + imageLength -1; int inclusiveOriginEndOffset= toOriginOffset(inclusiveImageEndOffset); return new Region(originOffset, (inclusiveOriginEndOffset + 1) - originOffset); } @Override public IRegion toOriginLines(int imageLine) throws BadLocationException { IRegion imageRegion= fSlaveDocument.getLineInformation(imageLine); IRegion originRegion= toOriginRegion(imageRegion); int originStartLine= fMasterDocument.getLineOfOffset(originRegion.getOffset()); if (originRegion.getLength() == 0) return new Region(originStartLine, 1); int originEndLine= fMasterDocument.getLineOfOffset(inclusiveEnd(originRegion)); return new Region(originStartLine, (originEndLine + 1) - originStartLine); } @Override public int toOriginLine(int imageLine) throws BadLocationException { IRegion lines= toOriginLines(imageLine); return (lines.getLength() > 1 ? -1 : lines.getOffset()); } @Override public int toImageOffset(int originOffset) throws BadLocationException { Fragment fragment= findFragment(originOffset); if (fragment != null) { int relative= originOffset - fragment.offset; return fragment.segment.offset + relative; } return -1; } @Override public IRegion toExactImageRegion(IRegion originRegion) throws BadLocationException { return toImageRegion(originRegion, true, false); } @Override public IRegion toImageRegion(IRegion originRegion) throws BadLocationException { return toImageRegion(originRegion, false, false); } @Override public IRegion toClosestImageRegion(IRegion originRegion) throws BadLocationException { return toImageRegion(originRegion, false, true); } @Override public int toImageLine(int originLine) throws BadLocationException { IRegion originRegion= fMasterDocument.getLineInformation(originLine); IRegion imageRegion= toImageRegion(originRegion); if (imageRegion == null) { int imageOffset= toImageOffset(originRegion.getOffset()); if (imageOffset > -1) imageRegion= new Region(imageOffset, 0); else return -1; } int startLine= fSlaveDocument.getLineOfOffset(imageRegion.getOffset()); if (imageRegion.getLength() == 0) return startLine; int endLine= fSlaveDocument.getLineOfOffset(imageRegion.getOffset() + imageRegion.getLength()); if (endLine != startLine) throw new IllegalStateException("startLine (" + startLine + ") does not match endLine (" + endLine + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ return startLine; } @Override public int toClosestImageLine(int originLine) throws BadLocationException { try { int imageLine= toImageLine(originLine); if (imageLine > -1) return imageLine; Position[] fragments= getFragments(); if (fragments.length == 0) return -1; IRegion originLineRegion= fMasterDocument.getLineInformation(originLine); int index= fMasterDocument.computeIndexInCategory(fFragmentsCategory, originLineRegion.getOffset()); if (0 < index && index < fragments.length) { Fragment left= (Fragment) fragments[index - 1]; int leftDistance= originLineRegion.getOffset() - (exclusiveEnd(left)); Fragment right= (Fragment) fragments[index]; int rightDistance= right.getOffset() - (exclusiveEnd(originLineRegion)); if (leftDistance <= rightDistance) originLine= fMasterDocument.getLineOfOffset(left.getOffset() + Math.max(left.getLength() - 1, 0)); else originLine= fMasterDocument.getLineOfOffset(right.getOffset()); } else if (index == 0) { Fragment right= (Fragment) fragments[index]; originLine= fMasterDocument.getLineOfOffset(right.getOffset()); } else if (index == fragments.length) { Fragment left= (Fragment) fragments[index - 1]; originLine= fMasterDocument.getLineOfOffset(exclusiveEnd(left)); } return toImageLine(originLine); } catch (BadPositionCategoryException x) { } return -1; } @Override public IRegion[] toExactOriginRegions(IRegion imageRegion) throws BadLocationException { if (imageRegion.getLength() == 0) return new IRegion[] { new Region(toOriginOffset(imageRegion.getOffset()), 0) }; int endOffset= exclusiveEnd(imageRegion); Position[] segments= getSegments(); int firstIndex= findSegmentIndex(imageRegion.getOffset()); int lastIndex= findSegmentIndex(endOffset - 1); int resultLength= lastIndex - firstIndex + 1; IRegion[] result= new IRegion[resultLength]; // first result[0]= createOriginStartRegion((Segment) segments[firstIndex], imageRegion.getOffset() - segments[firstIndex].getOffset()); // middles for (int i= 1; i < resultLength - 1; i++) result[i]= createOriginRegion((Segment) segments[firstIndex + i]); // last Segment last= (Segment) segments[lastIndex]; int segmentEndOffset= exclusiveEnd(last); IRegion lastRegion= createOriginEndRegion(last, segmentEndOffset - endOffset); if (resultLength > 1) { // first != last result[resultLength - 1]= lastRegion; } else { // merge first and last IRegion intersection= getIntersectingRegion(result[0], lastRegion); if (intersection == null) result= new IRegion[0]; else result[0]= intersection; } return result; } @Override public int getImageLength() { Position[] segments= getSegments(); int length= 0; for (Position segment : segments) { length += segment.length; } return length; } @Override public IRegion[] toExactImageRegions(IRegion originRegion) throws BadLocationException { int offset= originRegion.getOffset(); if (originRegion.getLength() == 0) { int imageOffset= toImageOffset(offset); return imageOffset > -1 ? new IRegion[] { new Region(imageOffset, 0) } : null; } int endOffset= exclusiveEnd(originRegion); Position[] fragments= getFragments(); int firstIndex= findFragmentIndex(offset, RIGHT); int lastIndex= findFragmentIndex(endOffset - 1, LEFT); if (firstIndex == -1 || firstIndex > lastIndex) return null; int resultLength= lastIndex - firstIndex + 1; IRegion[] result= new IRegion[resultLength]; // first result[0]= createImageStartRegion((Fragment) fragments[firstIndex], offset - fragments[firstIndex].getOffset()); // middles for (int i= 1; i < resultLength - 1; i++) result[i]= createImageRegion((Fragment) fragments[firstIndex + i]); // last Fragment last= (Fragment) fragments[lastIndex]; int fragmentEndOffset= exclusiveEnd(last); IRegion lastRegion= createImageEndRegion(last, fragmentEndOffset - endOffset); if (resultLength > 1) { // first != last result[resultLength - 1]= lastRegion; } else { // merge first and last IRegion intersection= getIntersectingRegion(result[0], lastRegion); if (intersection == null) return null; result[0]= intersection; } return result; } @Override public IRegion[] getExactCoverage(IRegion originRegion) throws BadLocationException { int originOffset= originRegion.getOffset(); int originLength= originRegion.getLength(); if (originLength == 0) { int imageOffset= toImageOffset(originOffset); return imageOffset > -1 ? new IRegion[] { new Region(originOffset, 0) } : null; } int endOffset= originOffset + originLength; Position[] fragments= getFragments(); int firstIndex= findFragmentIndex(originOffset, RIGHT); int lastIndex= findFragmentIndex(endOffset - 1, LEFT); if (firstIndex == -1 || firstIndex > lastIndex) return null; int resultLength= lastIndex - firstIndex + 1; IRegion[] result= new IRegion[resultLength]; // first result[0]= createOriginStartRegion((Fragment) fragments[firstIndex], originOffset - fragments[firstIndex].getOffset()); // middles for (int i= 1; i < resultLength - 1; i++) result[i]= createOriginRegion((Fragment) fragments[firstIndex + i]); // last Fragment last= (Fragment) fragments[lastIndex]; int fragmentEndOffset= exclusiveEnd(last); IRegion lastRegion= createOriginEndRegion(last, fragmentEndOffset - endOffset); if (resultLength > 1) { // first != last result[resultLength - 1]= lastRegion; } else { // merge first and last IRegion intersection= getIntersectingRegion(result[0], lastRegion); if (intersection == null) return null; result[0]= intersection; } return result; } private final void checkOriginRegion(IRegion originRegion) throws BadLocationException { int offset= originRegion.getOffset(); int endOffset= inclusiveEnd(originRegion); int max= fMasterDocument.getLength(); if (offset < 0 || offset > max || endOffset < 0 || endOffset > max) throw new BadLocationException(); } private final void checkOriginOffset(int originOffset) throws BadLocationException { if (originOffset < 0 || originOffset > fMasterDocument.getLength()) throw new BadLocationException(); } private final void checkImageOffset(int imageOffset) throws BadLocationException { if (imageOffset < 0 || imageOffset > getImageLength()) throw new BadLocationException(); } private final int exclusiveEnd(Position position) { return position.offset + position.length; } private final int exclusiveEnd(IRegion region) { return region.getOffset() + region.getLength(); } private final int inclusiveEnd(IRegion region) { int length= region.getLength(); if (length == 0) return region.getOffset(); return region.getOffset() + length - 1; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy