下面列出了怎么用org.eclipse.jface.text.source.projection.ProjectionAnnotation的API类实例代码及写法,或者点击链接到github查看源代码。
/**
* Collapses all proofs.
*
* @param cursorOffset
*/
private void foldAllProofs()
{
Vector<Annotation> modifiedAnnotations = new Vector<Annotation>();
for (Iterator<TLAProofPosition> it = foldPositions.iterator(); it.hasNext();)
{
TLAProofPosition proofPosition = it.next();
if (!proofPosition.getAnnotation().isCollapsed())
{
// should fold every proof
// so that only theorem statements are shown
proofPosition.getAnnotation().markCollapsed();
modifiedAnnotations.add(proofPosition.getAnnotation());
}
}
editor.modifyProjectionAnnotations((Annotation[]) modifiedAnnotations
.toArray(new ProjectionAnnotation[modifiedAnnotations.size()]));
}
private void expandAllProofs()
{
Vector<Annotation> modifiedAnnotations = new Vector<Annotation>();
for (Iterator<TLAProofPosition> it = foldPositions.iterator(); it.hasNext();)
{
TLAProofPosition proofPosition = it.next();
if (proofPosition.getAnnotation().isCollapsed())
{
// should fold every proof
// so that only theorem statements are shown
proofPosition.getAnnotation().markExpanded();
modifiedAnnotations.add(proofPosition.getAnnotation());
}
}
editor.modifyProjectionAnnotations((Annotation[]) modifiedAnnotations
.toArray(new ProjectionAnnotation[modifiedAnnotations.size()]));
}
/**
* @return an annotation that should be added (or null if that entry already has an annotation
* added for it).
*/
private Tuple<ProjectionAnnotation, Position> getAnnotationToAdd(FoldingEntry node, int start, int end,
ProjectionAnnotationModel model, List<Annotation> existing) throws BadLocationException {
try {
IDocument document = editor.getDocumentProvider().getDocument(editor.getEditorInput());
int offset = document.getLineOffset(start);
int endOffset = offset;
try {
endOffset = document.getLineOffset(end);
} catch (Exception e) {
//sometimes when we are at the last line, the command above will not work very well
IRegion lineInformation = document.getLineInformation(end);
endOffset = lineInformation.getOffset() + lineInformation.getLength();
}
Position position = new Position(offset, endOffset - offset);
return getAnnotationToAdd(position, node, model, existing);
} catch (BadLocationException x) {
//this could happen
}
return null;
}
protected Annotation[] mergeFoldingRegions(Collection<FoldedPosition> foldedPositions,
ProjectionAnnotationModel projectionAnnotationModel) {
List<Annotation> deletions = new ArrayList<Annotation>();
for (Iterator<Annotation> iterator = projectionAnnotationModel.getAnnotationIterator(); iterator.hasNext();) {
Annotation annotation = iterator.next();
if (annotation instanceof ProjectionAnnotation) {
Position position = projectionAnnotationModel.getPosition(annotation);
if (!foldedPositions.remove(position)) {
deletions.add(annotation);
}
}
}
return deletions.toArray(new Annotation[deletions.size()]);
}
protected void updateFoldingRegions(boolean allowCollapse, ProjectionAnnotationModel model,
Collection<FoldedPosition> foldedPositions, Annotation[] deletions) {
Map<ProjectionAnnotation, Position> additionsMap = Maps.newHashMap();
for (FoldedPosition foldedPosition: foldedPositions) {
addProjectionAnnotation(allowCollapse, foldedPosition, additionsMap);
}
if (deletions.length != 0 || additionsMap.size() != 0) {
model.modifyAnnotations(deletions, additionsMap, new Annotation[] {});
}
}
public void run()
{
ITextEditor editor = getTextEditor();
ISelection selection = editor.getSelectionProvider().getSelection();
if (selection instanceof ITextSelection)
{
ITextSelection textSelection = (ITextSelection) selection;
if (textSelection.getLength() != 0)
{
IAnnotationModel model = getAnnotationModel(editor);
if (model != null)
{
int start = textSelection.getStartLine();
int end = textSelection.getEndLine();
try
{
IDocument document = editor.getDocumentProvider().getDocument(editor.getEditorInput());
int offset = document.getLineOffset(start);
int endOffset = document.getLineOffset(end + 1);
Position position = new Position(offset, endOffset - offset);
model.addAnnotation(new ProjectionAnnotation(), position);
} catch (BadLocationException x)
{
// ignore
}
}
}
}
}
/**
* Folds all proofs not containing the cursor.
*
* Note that this will fold every proof if the cursor
* is not in a proof.
*
* @param cursorOffset
*/
private void foldEverythingUnusable(int cursorOffset)
{
Vector<Annotation> modifiedAnnotations = new Vector<Annotation>();
for (Iterator<TLAProofPosition> it = foldPositions.iterator(); it.hasNext();)
{
TLAProofPosition proofPosition = it.next();
try
{
if (proofPosition.containsInProofOrStatement(cursorOffset, document))
{
if (proofPosition.getAnnotation().isCollapsed())
{
proofPosition.getAnnotation().markExpanded();
modifiedAnnotations.add(proofPosition.getAnnotation());
}
} else if (!proofPosition.getAnnotation().isCollapsed())
{
proofPosition.getAnnotation().markCollapsed();
modifiedAnnotations.add(proofPosition.getAnnotation());
}
} catch (BadLocationException e)
{
Activator.getDefault().logError("Error changing expansion state of proofs.", e);
}
}
editor.modifyProjectionAnnotations((Annotation[]) modifiedAnnotations
.toArray(new ProjectionAnnotation[modifiedAnnotations.size()]));
}
public void updateFoldingStructure(List<Position> positions) {
final Map<Annotation, Position> newAnnotations = new HashMap<Annotation, Position>();
for (Position position : positions) {
newAnnotations.put(new ProjectionAnnotation(), position);
}
annotationModel.modifyAnnotations(oldAnnotations, newAnnotations, null);
oldAnnotations = newAnnotations.keySet().toArray(new Annotation[0]);
}
GamaFoldingActionGroup(final ITextEditor editor, final ITextViewer viewer) {
super(editor, viewer);
if (!(viewer instanceof ProjectionViewer)) { return; }
this.pViewer = (ProjectionViewer) viewer;
collapseStrings = new FoldingAction() { // $NON-NLS-1$
// private final EClass type = GamlPackage.
@Override
public void run() {
final ProjectionAnnotationModel model = pViewer.getProjectionAnnotationModel();
final Iterator<?> iterator = model.getAnnotationIterator();
final List<Annotation> toCollapse = new ArrayList<>();
while (iterator.hasNext()) {
final Object next = iterator.next();
if (next instanceof ProjectionAnnotation) {
final ProjectionAnnotation pa = (ProjectionAnnotation) next;
final Position position = model.getPosition(pa);
if (position instanceof TypedFoldedPosition) {
if (((TypedFoldedPosition) position).getType().equals("__comment")) {
pa.markCollapsed();
toCollapse.add(pa);
}
}
}
}
model.modifyAnnotations(null, null, toCollapse.toArray(new Annotation[0]));
}
};
collapseStrings.setActionDefinitionId("org.xtext.example.folding.ui.folding.collapseStrings");
editor.setAction("FoldingCollapseStrings", collapseStrings); //$NON-NLS-1$
}
protected void calculatePositions(boolean initialReconcile, IProgressMonitor monitor, IParseRootNode ast)
{
if (monitor != null && monitor.isCanceled())
{
return;
}
// Folding...
try
{
Map<ProjectionAnnotation, Position> positions = folder.emitFoldingRegions(initialReconcile, monitor, ast);
synchronized (fPositionsLock)
{
fPositions = positions;
}
}
catch (BadLocationException e)
{
IdeLog.logError(CommonEditorPlugin.getDefault(), e);
}
// If we had all positions we shouldn't probably listen to cancel, but we may have exited emitFoldingRegions
// early because of cancel...
if (monitor != null && monitor.isCanceled() || !shouldUpdatePositions(folder))
{
return;
}
updatePositions();
}
/**
* Update the folding positions in the document
*/
protected void updatePositions()
{
AbstractThemeableEditor editor = fEditor;
if (editor != null)
{
HashMap<ProjectionAnnotation, Position> positions;
synchronized (fPositionsLock)
{
// Create a copy to pass to updateFoldingStructure, as it may take more time there.
positions = new HashMap<ProjectionAnnotation, Position>(fPositions);
}
editor.updateFoldingStructure(positions);
}
}
public Map<ProjectionAnnotation, Position> getPositions()
{
synchronized (fPositionsLock)
{
return new HashMap<ProjectionAnnotation, Position>(fPositions);
}
}
public void updateFoldingStructure(Map<ProjectionAnnotation, Position> annotations)
{
synchronized (lockUpdateFoldingStructure)
{
List<Annotation> deletions = new ArrayList<Annotation>();
Collection<Position> additions = annotations.values();
ProjectionAnnotationModel currentModel = getAnnotationModel();
if (currentModel == null)
{
return;
}
for (@SuppressWarnings("rawtypes")
Iterator iter = currentModel.getAnnotationIterator(); iter.hasNext();)
{
Object annotation = iter.next();
if (annotation instanceof ProjectionAnnotation)
{
Position position = currentModel.getPosition((Annotation) annotation);
if (additions.contains(position))
{
additions.remove(position);
}
else
{
deletions.add((Annotation) annotation);
}
}
}
if (annotations.size() != 0 || deletions.size() != 0)
{
currentModel.modifyAnnotations(deletions.toArray(new Annotation[deletions.size()]), annotations, null);
}
}
}
/**
* Given the ast, create the needed marks and set them in the passed model.
*/
private synchronized void addMarksToModel(SimpleNode root2, ProjectionAnnotationModel model) {
try {
if (model != null) {
ArrayList<Annotation> existing = new ArrayList<Annotation>();
//get the existing annotations
Iterator<Annotation> iter = model.getAnnotationIterator();
while (iter != null && iter.hasNext()) {
Annotation element = iter.next();
existing.add(element);
}
//now, remove the annotations not used and add the new ones needed
IDocument doc = editor.getDocument();
if (doc != null) { //this can happen if we change the input of the editor very quickly.
boolean foldInitial = initialFolding;
initialFolding = false;
List<FoldingEntry> marks = getMarks(doc, root2, foldInitial);
Map<ProjectionAnnotation, Position> annotationsToAdd;
if (marks.size() > OptimizationRelatedConstants.MAXIMUM_NUMBER_OF_CODE_FOLDING_MARKS) {
annotationsToAdd = new HashMap<ProjectionAnnotation, Position>();
} else {
annotationsToAdd = getAnnotationsToAdd(marks, model, existing);
}
model.replaceAnnotations(existing.toArray(new Annotation[existing.size()]), annotationsToAdd);
}
}
} catch (Exception e) {
Log.log(e);
}
}
/**
* We have to be careful not to remove existing annotations because if this happens, previous code folding is not correct.
*/
private Tuple<ProjectionAnnotation, Position> getAnnotationToAdd(Position position, FoldingEntry node,
ProjectionAnnotationModel model, List<Annotation> existing) {
for (Iterator<Annotation> iter = existing.iterator(); iter.hasNext();) {
Annotation element = iter.next();
Position existingPosition = model.getPosition(element);
if (existingPosition.equals(position)) {
//ok, do nothing to this annotation (neither remove nor add, as it already exists in the correct place).
existing.remove(element);
return null;
}
}
return new Tuple<ProjectionAnnotation, Position>(new PyProjectionAnnotation(node.getAstEntry(),
node.isCollapsed), position);
}
protected void addProjectionAnnotation(boolean allowCollapse, Position foldingRegion,
Map<ProjectionAnnotation, Position> additionsMap) {
boolean collapse = allowCollapse && (foldingRegion instanceof DefaultFoldedPosition) && ((DefaultFoldedPosition)foldingRegion).isInitiallyFolded();
ProjectionAnnotation projectionAnnotation = createProjectionAnnotation(collapse, foldingRegion);
additionsMap.put(projectionAnnotation, foldingRegion);
}
protected ProjectionAnnotation createProjectionAnnotation(boolean isCollapsed, Position foldedRegion) {
return new ProjectionAnnotation(isCollapsed);
}
/**
* Expands the proof of a statement and all sub proofs. Assumes
* all TLAProofPosition in foldPositions are sorted by ascending offset.
*/
private void expandCurrentSubtree(int offset)
{
List<Annotation> modifiedAnnotations = new ArrayList<Annotation>();
// find statement containing offset
TLAProofPosition found = null;
/*
* Iterate though folds until finding the first
* TLAProofPosition that contains the offset before
* its proof (i.e. in the step/theorem or in a line
* between the step/theorem and the proof). Expand the
* proof of this TLAProofPosition and continue iterating, expanding
* all proofs that are contained in the found TLAProofPosition.
*
* This requires that the proof positions be sorted in ascending
* order of offset.
*/
for (Iterator<TLAProofPosition> it = foldPositions.iterator(); it.hasNext();)
{
TLAProofPosition proofPosition = it.next();
try
{
if (found == null && proofPosition.containsBeforeProof(offset, document))
{
found = proofPosition;
if (found.getAnnotation().isCollapsed())
{
found.getAnnotation().markExpanded();
modifiedAnnotations.add(found.getAnnotation());
}
continue;
}
if (found != null && found.contains(proofPosition))
{
if (proofPosition.getAnnotation().isCollapsed())
{
proofPosition.getAnnotation().markExpanded();
modifiedAnnotations.add(proofPosition.getAnnotation());
}
}
} catch (BadLocationException e)
{
Activator.getDefault().logError("Error changing expansion state of proofs.", e);
}
}
editor.modifyProjectionAnnotations((Annotation[]) modifiedAnnotations
.toArray(new ProjectionAnnotation[modifiedAnnotations.size()]));
}
/**
* Hides the proof of a statement and all subproofs. Assumes
* all TLAProofPosition in foldPositions are sorted by ascending offset.
*/
private void hideCurrentSubtree(int offset)
{
List<Annotation> modifiedAnnotations = new ArrayList<Annotation>();
// find statement containing offset
TLAProofPosition found = null;
/*
* Iterate though folds until finding the first
* TLAProofPosition that contains the offset before
* its proof (i.e. in the step/theorem or in a line
* between the step/theorem and the proof). Collapse the
* proof of this TLAProofPosition and continue iterating, collapsing
* all proofs that are contained in the found TLAProofPosition.
*
* This requires that the proof positions be sorted in ascending
* order of offset.
*/
for (Iterator<TLAProofPosition> it = foldPositions.iterator(); it.hasNext();)
{
TLAProofPosition proofPosition = it.next();
try
{
if (found == null && proofPosition.containsBeforeProof(offset, document))
{
found = proofPosition;
if (!found.getAnnotation().isCollapsed())
{
found.getAnnotation().markCollapsed();
modifiedAnnotations.add(found.getAnnotation());
}
continue;
}
if (found != null && found.contains(proofPosition))
{
if (!proofPosition.getAnnotation().isCollapsed())
{
proofPosition.getAnnotation().markCollapsed();
modifiedAnnotations.add(proofPosition.getAnnotation());
}
}
} catch (BadLocationException e)
{
Activator.getDefault().logError("Error changing expansion state of proofs.", e);
}
}
editor.modifyProjectionAnnotations((Annotation[]) modifiedAnnotations
.toArray(new ProjectionAnnotation[modifiedAnnotations.size()]));
}
/**
* Shows the immediate descendants in the proof of a
* statement and hides the proofs of the immediate descendants.
* Assumes all TLAProofPosition in foldPositions are sorted by ascending offset.
*/
private void showImmediateDescendants(int offset)
{
List<Annotation> modifiedAnnotations = new ArrayList<Annotation>();
// find statement containing offset
TLAProofPosition found = null;
/*
* Iterate though folds until finding the first
* TLAProofPosition that contains the offset before
* its proof (i.e. in the step/theorem or in a line
* between the step/theorem and the proof). Expand proof
* of found statement and collapse the proofs of all
* TLAProofPositions inside.
*
* This requires that the proof positions be sorted in ascending
* order of offset.
*/
for (Iterator<TLAProofPosition> it = foldPositions.iterator(); it.hasNext();)
{
TLAProofPosition proofPosition = it.next();
try
{
if (found == null && proofPosition.containsBeforeProof(offset, document))
{
found = proofPosition;
if (found.getAnnotation().isCollapsed())
{
found.getAnnotation().markExpanded();
modifiedAnnotations.add(found.getAnnotation());
}
continue;
}
if (found != null && found.contains(proofPosition))
{
if (!proofPosition.getAnnotation().isCollapsed())
{
proofPosition.getAnnotation().markCollapsed();
modifiedAnnotations.add(proofPosition.getAnnotation());
}
}
} catch (BadLocationException e)
{
Activator.getDefault().logError("Error changing expansion state of proofs.", e);
}
}
editor.modifyProjectionAnnotations((Annotation[]) modifiedAnnotations
.toArray(new ProjectionAnnotation[modifiedAnnotations.size()]));
}
/**
* Constructor for the position.
*
* For the offset and length for the proof and statement, first obtain the {@link Location} from the syntax tree. For the proof, use
* the location returned by {@link ProofNode#getLocation()}, where the {@link ProofNode} is obtained by {@link TheoremNode#getProof()}.
*
* For initTheoremOffset, use the beginning of the location returned by {@link TheoremNode#getLocation()}.
*
* For the end of the statement, use the end of the location returned by {@link LevelNode#getLocation()}
* for the {@link LevelNode} returned by {@link TheoremNode#getTheorem()}.
*
* To convert from the 4-int {@link Location} to the offset and length, use {@link AdapterFactory#locationToRegion(IDocument, Location)} and
* then use the offset and length for the returned region.
*
* @param initProofOffset initial offset of the proof
* @param initProofLength initial length of the proof
* @param initTheoremOffset initial offset of the theorem or step
* for which this is a proof
* @param initLengthToEndOfStatement initial length from initTheoremOffset to the end of
* the statement of the theorem
* @param annotation {@link ProjectionAnnotation} that should be at this position
* @param document
*/
public TLAProofPosition(int initProofOffset, int initProofLength, int initTheoremOffset,
int initLengthToEndOfStatement, ProjectionAnnotation annotation, IDocument document)
{
/*
* This seems to be a bit of a hack, but I see
* no other way to do it correctly because of
* how eclipse expands folds. In particular, when eclipse
* is asked to expand a fold, it expands all lines between
* the start line and end line, including the start line but
* excluding the end line. It computes start
* and end lines for a fold with offset and length in the following way:
*
* start line: the greatest numbered line with
* first character offset <= offset of fold
*
* end line: the greatest numbered line with
* first character offset <= offset + length of fold
*
* In other words, it takes the offset of the fold and moves it back until it finds the start
* of a line and takes the offset+length of a fold and moves it back until it finds the
* start of a line. It then expands all lines in between and including the start line but excluding
* the end line. See ProjectionViewer.addMasterDocumentRange() to see the exact implementation.
*
* I think this is a silly way of doing things. The interface IProjectionPosition
* allows the position to compute what lines are collapsed using the method
* computeProjectionRegions but does not provide a way for the position to compute
* what lines are expanded. This asymmetry can result in lines being collapsed
* when a fold is collapsed but not re-expanded when the fold is expanded so that
* lines just disappear. This requires being careful about the offset and length
* of the position as well as what regions are collapsed.
*
* The method alignRegion is stolen from the code for Java editor folding. Read the method
* comments to see what it does. It should ensure that the entire proof is revealed
* when expanded.
*/
IRegion region = alignRegion(new Region(initTheoremOffset, initProofOffset + initProofLength
- initTheoremOffset), document);
offset = region.getOffset();
length = region.getLength();
positionOfStatement = new Position(initTheoremOffset, initLengthToEndOfStatement);
positionOfProof = new Position(initProofOffset, initProofLength);
this.annotation = annotation;
// add positions to document so that they are updated on document changes.
try
{
document.addPosition(positionOfProof);
document.addPosition(positionOfStatement);
} catch (BadLocationException e)
{
Activator.getDefault().logError("Error installing positions for proof fold at " + this, e);
}
}
public ProjectionAnnotation getAnnotation()
{
return annotation;
}
public Map<ProjectionAnnotation, Position> emitFoldingRegions(boolean initialReconcile, IProgressMonitor monitor,
IParseRootNode parseNode) throws BadLocationException
{
this.initialReconcile = initialReconcile;
fLines = new ArrayList<Integer>();
int lineCount = getDocument().getNumberOfLines();
if (lineCount <= 1) // Quick hack fix for minified files. We need at least two lines to have folding!
{
return Collections.emptyMap();
}
SubMonitor sub = null;
try
{
if (parseNode == null)
{
return Collections.emptyMap();
}
int length = parseNode.getChildCount();
if (parseNode instanceof IParseRootNode)
{
IParseRootNode prn = (IParseRootNode) parseNode;
IParseNode[] comments = prn.getCommentNodes();
if (comments != null && comments.length > 0)
{
length += comments.length;
}
}
sub = SubMonitor.convert(monitor, Messages.CommonReconcilingStrategy_FoldingTaskName, length);
SubMonitor subMonitor = sub.newChild(length);
Map<ProjectionAnnotation, Position> positions = getPositions(subMonitor, parseNode);
// In case the getPositions call canceled the monitor, we cancel the 'parent' monitor as well.
// This will cause the system to skip a foldings update (see CommonReconcilingStrategy#calculatePositions).
if (subMonitor.isCanceled())
{
monitor.setCanceled(true);
}
return positions;
}
finally
{
fLines = null;
if (sub != null)
{
sub.done();
}
}
}
/**
* Compute and return the folding positions. In case a folding update should be avoided, the given monitor should be
* canceled. The default implementation does not cancel the monitor, and in case it's needed, it should be handled
* by a subclass.
*
* @param monitor
* @param parseNode
* @return folding positions
*/
protected Map<ProjectionAnnotation, Position> getPositions(IProgressMonitor monitor, IParseNode parseNode)
{
Map<ProjectionAnnotation, Position> newPositions = new HashMap<ProjectionAnnotation, Position>();
IParseNode[] children = getChildren(parseNode);
SubMonitor sub = SubMonitor.convert(monitor, 2 * children.length);
for (IParseNode child : children)
{
if (sub.isCanceled())
{
return newPositions;
}
if (isFoldable(child))
{
int start = child.getStartingOffset();
boolean add = true;
int end = child.getEndingOffset() + 1;
try
{
int line = getDocument().getLineOfOffset(start);
// Don't bother adding multiple positions for the same starting line
if (fLines != null && fLines.contains(line))
{
add = false;
}
else
{
// Don't set up folding for stuff starting and ending on same line
int endLine = getDocument().getLineOfOffset(child.getEndingOffset());
if (endLine == line)
{
add = false;
}
else
{
// When we can, use the end of the end line as the end offset, so it looks nicer in the
// editor. Using getLineInformation excludes the line delimiter, so we use the methods that
// include it!
end = getDocument().getLineOffset(endLine) + getDocument().getLineLength(endLine);
if (fLines != null)
{
fLines.add(line);
}
}
}
}
catch (BadLocationException e)
{
// ignore
}
if (add)
{
end = Math.min(getDocument().getLength(), end);
if (start <= end)
{
newPositions.put(initialReconcile ? new ProjectionAnnotation(isCollapsed(child))
: new ProjectionAnnotation(), new Position(start, end - start));
}
else
{
IdeLog.logWarning(CommonEditorPlugin.getDefault(), MessageFormat.format(
"Was unable to add folding position. Start: {0}, end: {1}", start, end)); //$NON-NLS-1$
}
}
}
if (traverseInto(child))
{
// Recurse into AST!
newPositions.putAll(getPositions(sub.newChild(1), child));
}
sub.worked(1);
}
sub.done();
return newPositions;
}
public Map<ProjectionAnnotation, Position> emitFoldingRegions(boolean initialReconcile, IProgressMonitor monitor,
IParseRootNode ast) throws BadLocationException
{
int lineCount = fDocument.getNumberOfLines();
if (lineCount <= 1) // Quick hack fix for minified files. We need at least two lines to have folding!
{
return Collections.emptyMap();
}
Map<ProjectionAnnotation, Position> newPositions = new HashMap<ProjectionAnnotation, Position>(lineCount >> 2);
Map<Integer, Integer> starts = new HashMap<Integer, Integer>(3);
if (monitor != null)
{
monitor.beginTask(Messages.CommonReconcilingStrategy_FoldingTaskName, lineCount);
}
for (int currentLine = 0; currentLine < lineCount; currentLine++)
{
// Check for cancellation
if (monitor != null && monitor.isCanceled())
return newPositions;
IRegion lineRegion = fDocument.getLineInformation(currentLine);
int offset = lineRegion.getOffset();
String line = fDocument.get(offset, lineRegion.getLength());
// Use scope at beginning of line for start regexp
RubyRegexp startRegexp = getStartFoldRegexp(getScopeAtOffset(offset));
if (startRegexp == null)
{
if (monitor != null)
monitor.worked(1);
continue;
}
// Use scope at end of line for end regexp
RubyRegexp endRegexp = getEndFoldRegexp(getScopeAtOffset(offset + lineRegion.getLength()));
if (endRegexp == null)
{
if (monitor != null)
monitor.worked(1);
continue;
}
// Look for an open...
RubyString rLine = startRegexp.getRuntime().newString(line);
IRubyObject startMatcher = startRegexp.match_m(startRegexp.getRuntime().getCurrentContext(), rLine);
if (!startMatcher.isNil())
{
starts.put(findIndent(line), offset); // cheat and just give offset of line since line resolution is all
// that matters
}
// Don't look for an end if there's no open yet!
if (starts.size() > 0)
{
// check to see if we have an open folding region at this indent level...
int indent = findIndent(line);
// Subtract one if we're handling /* */ folding!
if (line.trim().startsWith("*")) //$NON-NLS-1$
{
indent--;
}
if (starts.containsKey(indent))
{
IRubyObject endMatcher = endRegexp.match_m(endRegexp.getRuntime().getCurrentContext(), rLine);
if (!endMatcher.isNil())
{
int startingOffset = starts.remove(indent);
int startLine = fDocument.getLineOfOffset(startingOffset);
if (startLine != currentLine)
{
int end = lineRegion.getOffset() + lineRegion.getLength() + 1; // cheat and just use end of
// line
if (end > fDocument.getLength())
{
end = fDocument.getLength();
}
int posLength = end - startingOffset;
if (posLength > 0)
{
Position position = new Position(startingOffset, posLength);
newPositions.put(new ProjectionAnnotation(), position);
}
}
}
}
}
if (monitor != null)
monitor.worked(1);
}
if (monitor != null)
{
monitor.done();
}
return newPositions;
}
public abstract Map<ProjectionAnnotation, Position> emitFoldingRegions(boolean initialReconcile,
IProgressMonitor monitor, IParseRootNode ast) throws BadLocationException;
/**
* Calls {@link ProjectionAnnotationModel#modifyAnnotations(Annotation[], Map, Annotation[])} with the
* arguments.
*
* Note that in the map additions, the keys should be instances of {@link ProjectionAnnotation} and the values
* should be instances of the corresponding {@link Position}.
*
* @param deletions
* @param additions
*/
public void modifyProjectionAnnotations(final Annotation[] deletions,
final Map<? extends ProjectionAnnotation, ? extends Position> additions) {
this.annotationModel.modifyAnnotations(deletions, additions, null);
}
public abstract void updateFoldingStructure(Map<ProjectionAnnotation, Position> positions);