X-Git-Url: http://secure.phpeclipse.com
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/folding/DefaultJavaFoldingStructureProvider.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/folding/DefaultJavaFoldingStructureProvider.java
deleted file mode 100644
index 0739690..0000000
--- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/folding/DefaultJavaFoldingStructureProvider.java
+++ /dev/null
@@ -1,1061 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2000, 2003 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Common Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/cpl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package net.sourceforge.phpdt.internal.ui.text.folding;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-
-import net.sourceforge.phpdt.core.ElementChangedEvent;
-import net.sourceforge.phpdt.core.ICompilationUnit;
-import net.sourceforge.phpdt.core.IElementChangedListener;
-import net.sourceforge.phpdt.core.IJavaElement;
-import net.sourceforge.phpdt.core.IJavaElementDelta;
-import net.sourceforge.phpdt.core.IMember;
-import net.sourceforge.phpdt.core.IParent;
-import net.sourceforge.phpdt.core.ISourceRange;
-import net.sourceforge.phpdt.core.ISourceReference;
-import net.sourceforge.phpdt.core.IType;
-import net.sourceforge.phpdt.core.JavaCore;
-import net.sourceforge.phpdt.core.JavaModelException;
-import net.sourceforge.phpdt.core.ToolFactory;
-import net.sourceforge.phpdt.core.compiler.IScanner;
-import net.sourceforge.phpdt.core.compiler.ITerminalSymbols;
-import net.sourceforge.phpdt.core.compiler.InvalidInputException;
-import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
-import net.sourceforge.phpdt.internal.ui.text.DocumentCharacterIterator;
-import net.sourceforge.phpdt.ui.IWorkingCopyManager;
-import net.sourceforge.phpdt.ui.PreferenceConstants;
-import net.sourceforge.phpdt.ui.text.folding.IJavaFoldingStructureProvider;
-import net.sourceforge.phpeclipse.PHPeclipsePlugin;
-import net.sourceforge.phpeclipse.phpeditor.PHPEditor;
-import net.sourceforge.phpeclipse.phpeditor.PHPUnitEditor;
-
-import org.eclipse.jface.preference.IPreferenceStore;
-import org.eclipse.jface.text.Assert;
-import org.eclipse.jface.text.BadLocationException;
-import org.eclipse.jface.text.IDocument;
-import org.eclipse.jface.text.IRegion;
-import org.eclipse.jface.text.Position;
-import org.eclipse.jface.text.Region;
-import org.eclipse.jface.text.source.Annotation;
-import org.eclipse.jface.text.source.IAnnotationModel;
-import org.eclipse.jface.text.source.projection.IProjectionListener;
-import org.eclipse.jface.text.source.projection.IProjectionPosition;
-import org.eclipse.jface.text.source.projection.ProjectionAnnotation;
-import org.eclipse.jface.text.source.projection.ProjectionAnnotationModel;
-import org.eclipse.jface.text.source.projection.ProjectionViewer;
-import org.eclipse.ui.texteditor.IDocumentProvider;
-import org.eclipse.ui.texteditor.ITextEditor;
-
-/**
- * Updates the projection model of a class file or compilation unit.
- *
- * @since 3.0
- */
-public class DefaultJavaFoldingStructureProvider implements
- IProjectionListener, IJavaFoldingStructureProvider {
-
- private static class JavaProjectionAnnotation extends ProjectionAnnotation {
-
- private IJavaElement fJavaElement;
-
- private boolean fIsComment;
-
- public JavaProjectionAnnotation(IJavaElement element,
- boolean isCollapsed, boolean isComment) {
- super(isCollapsed);
- fJavaElement = element;
- fIsComment = isComment;
- }
-
- public IJavaElement getElement() {
- return fJavaElement;
- }
-
- public void setElement(IJavaElement element) {
- fJavaElement = element;
- }
-
- public boolean isComment() {
- return fIsComment;
- }
-
- public void setIsComment(boolean isComment) {
- fIsComment = isComment;
- }
-
- /*
- * @see java.lang.Object#toString()
- */
- public String toString() {
- return "JavaProjectionAnnotation:\n" + //$NON-NLS-1$
- "\telement: \t" + fJavaElement.toString() + "\n" + //$NON-NLS-1$ //$NON-NLS-2$
- "\tcollapsed: \t" + isCollapsed() + "\n" + //$NON-NLS-1$ //$NON-NLS-2$
- "\tcomment: \t" + fIsComment + "\n"; //$NON-NLS-1$ //$NON-NLS-2$
- }
- }
-
- private static final class Tuple {
- JavaProjectionAnnotation annotation;
-
- Position position;
-
- Tuple(JavaProjectionAnnotation annotation, Position position) {
- this.annotation = annotation;
- this.position = position;
- }
- }
-
- private class ElementChangedListener implements IElementChangedListener {
-
- /*
- * @see org.eclipse.jdt.core.IElementChangedListener#elementChanged(org.eclipse.jdt.core.ElementChangedEvent)
- */
- public void elementChanged(ElementChangedEvent e) {
- IJavaElementDelta delta = findElement(fInput, e.getDelta());
- if (delta != null)
- processDelta(delta);
- }
-
- private IJavaElementDelta findElement(IJavaElement target,
- IJavaElementDelta delta) {
-
- if (delta == null || target == null)
- return null;
-
- IJavaElement element = delta.getElement();
-
- if (element.getElementType() > IJavaElement.CLASS_FILE)
- return null;
-
- if (target.equals(element))
- return delta;
-
- IJavaElementDelta[] children = delta.getAffectedChildren();
-
- for (int i = 0; i < children.length; i++) {
- IJavaElementDelta d = findElement(target, children[i]);
- if (d != null)
- return d;
- }
-
- return null;
- }
- }
-
- /**
- * Projection position that will return two foldable regions: one folding
- * away the region from after the '/**' to the beginning of the content, the
- * other from after the first content line until after the comment.
- *
- * @since 3.1
- */
- private static final class CommentPosition extends Position implements
- IProjectionPosition {
- CommentPosition(int offset, int length) {
- super(offset, length);
- }
-
- /*
- * @see org.eclipse.jface.text.source.projection.IProjectionPosition#computeFoldingRegions(org.eclipse.jface.text.IDocument)
- */
- public IRegion[] computeProjectionRegions(IDocument document)
- throws BadLocationException {
- DocumentCharacterIterator sequence = new DocumentCharacterIterator(
- document, offset, offset + length);
- int prefixEnd = 0;
- int contentStart = findFirstContent(sequence, prefixEnd);
-
- int firstLine = document.getLineOfOffset(offset + prefixEnd);
- int captionLine = document.getLineOfOffset(offset + contentStart);
- int lastLine = document.getLineOfOffset(offset + length);
-
- Assert.isTrue(firstLine <= captionLine,
- "first folded line is greater than the caption line"); //$NON-NLS-1$
- Assert.isTrue(captionLine <= lastLine,
- "caption line is greater than the last folded line"); //$NON-NLS-1$
-
- IRegion preRegion;
- if (firstLine < captionLine) {
- // preRegion= new Region(offset + prefixEnd, contentStart -
- // prefixEnd);
- int preOffset = document.getLineOffset(firstLine);
- IRegion preEndLineInfo = document
- .getLineInformation(captionLine);
- int preEnd = preEndLineInfo.getOffset();
- preRegion = new Region(preOffset, preEnd - preOffset);
- } else {
- preRegion = null;
- }
-
- if (captionLine < lastLine) {
- int postOffset = document.getLineOffset(captionLine + 1);
- IRegion postRegion = new Region(postOffset, offset + length
- - postOffset);
-
- if (preRegion == null)
- return new IRegion[] { postRegion };
-
- return new IRegion[] { preRegion, postRegion };
- }
-
- if (preRegion != null)
- return new IRegion[] { preRegion };
-
- return null;
- }
-
- /**
- * Finds the offset of the first identifier part within
- * content
. Returns 0 if none is found.
- *
- * @param content
- * the content to search
- * @return the first index of a unicode identifier part, or zero if none
- * can be found
- */
- private int findFirstContent(final CharSequence content, int prefixEnd) {
- int lenght = content.length();
- for (int i = prefixEnd; i < lenght; i++) {
- if (Character.isUnicodeIdentifierPart(content.charAt(i)))
- return i;
- }
- return 0;
- }
-
- // /**
- // * Finds the offset of the first identifier part within
- // content
.
- // * Returns 0 if none is found.
- // *
- // * @param content the content to search
- // * @return the first index of a unicode identifier part, or zero if
- // none
- // can
- // * be found
- // */
- // private int findPrefixEnd(final CharSequence content) {
- // // return the index after the leading '/*' or '/**'
- // int len= content.length();
- // int i= 0;
- // while (i < len && isWhiteSpace(content.charAt(i)))
- // i++;
- // if (len >= i + 2 && content.charAt(i) == '/' && content.charAt(i + 1)
- // ==
- // '*')
- // if (len >= i + 3 && content.charAt(i + 2) == '*')
- // return i + 3;
- // else
- // return i + 2;
- // else
- // return i;
- // }
- //
- // private boolean isWhiteSpace(char c) {
- // return c == ' ' || c == '\t';
- // }
-
- /*
- * @see org.eclipse.jface.text.source.projection.IProjectionPosition#computeCaptionOffset(org.eclipse.jface.text.IDocument)
- */
- public int computeCaptionOffset(IDocument document) {
- // return 0;
- DocumentCharacterIterator sequence = new DocumentCharacterIterator(
- document, offset, offset + length);
- return findFirstContent(sequence, 0);
- }
- }
-
- /**
- * Projection position that will return two foldable regions: one folding
- * away the lines before the one containing the simple name of the java
- * element, one folding away any lines after the caption.
- *
- * @since 3.1
- */
- private static final class JavaElementPosition extends Position implements
- IProjectionPosition {
-
- private IMember fMember;
-
- public JavaElementPosition(int offset, int length, IMember member) {
- super(offset, length);
- Assert.isNotNull(member);
- fMember = member;
- }
-
- public void setMember(IMember member) {
- Assert.isNotNull(member);
- fMember = member;
- }
-
- /*
- * @see org.eclipse.jface.text.source.projection.IProjectionPosition#computeFoldingRegions(org.eclipse.jface.text.IDocument)
- */
- public IRegion[] computeProjectionRegions(IDocument document)
- throws BadLocationException {
- int nameStart = offset;
- try {
- /*
- * The member's name range may not be correct. However,
- * reconciling would trigger another element delta which would
- * lead to reentrant situations. Therefore, we optimistically
- * assume that the name range is correct, but double check the
- * received lines below.
- */
- ISourceRange nameRange = fMember.getNameRange();
- if (nameRange != null)
- nameStart = nameRange.getOffset();
-
- } catch (JavaModelException e) {
- // ignore and use default
- }
-
- int firstLine = document.getLineOfOffset(offset);
- int captionLine = document.getLineOfOffset(nameStart);
- int lastLine = document.getLineOfOffset(offset + length);
-
- /*
- * see comment above - adjust the caption line to be inside the
- * entire folded region, and rely on later element deltas to correct
- * the name range.
- */
- if (captionLine < firstLine)
- captionLine = firstLine;
- if (captionLine > lastLine)
- captionLine = lastLine;
-
- IRegion preRegion;
- if (firstLine < captionLine) {
- int preOffset = document.getLineOffset(firstLine);
- IRegion preEndLineInfo = document
- .getLineInformation(captionLine);
- int preEnd = preEndLineInfo.getOffset();
- preRegion = new Region(preOffset, preEnd - preOffset);
- } else {
- preRegion = null;
- }
-
- if (captionLine < lastLine) {
- int postOffset = document.getLineOffset(captionLine + 1);
- IRegion postRegion = new Region(postOffset, offset + length
- - postOffset);
-
- if (preRegion == null)
- return new IRegion[] { postRegion };
-
- return new IRegion[] { preRegion, postRegion };
- }
-
- if (preRegion != null)
- return new IRegion[] { preRegion };
-
- return null;
- }
-
- /*
- * @see org.eclipse.jface.text.source.projection.IProjectionPosition#computeCaptionOffset(org.eclipse.jface.text.IDocument)
- */
- public int computeCaptionOffset(IDocument document)
- throws BadLocationException {
- int nameStart = offset;
- try {
- // need a reconcile here?
- ISourceRange nameRange = fMember.getNameRange();
- if (nameRange != null)
- nameStart = nameRange.getOffset();
- } catch (JavaModelException e) {
- // ignore and use default
- }
-
- return nameStart - offset;
- }
-
- }
-
- private IDocument fCachedDocument;
-
- private ProjectionAnnotationModel fCachedModel;
-
- private ITextEditor fEditor;
-
- private ProjectionViewer fViewer;
-
- private IJavaElement fInput;
-
- private IElementChangedListener fElementListener;
-
- private boolean fAllowCollapsing = false;
-
- private boolean fCollapseJavadoc = false;
-
- // private boolean fCollapseImportContainer = true;
-
- private boolean fCollapseInnerTypes = true;
-
- private boolean fCollapseMethods = false;
-
- private boolean fCollapseHeaderComments = true;
-
- /* caches for header comment extraction. */
- private IType fFirstType;
-
- private boolean fHasHeaderComment;
-
- public DefaultJavaFoldingStructureProvider() {
- }
-
- public void install(ITextEditor editor, ProjectionViewer viewer) {
- if (editor instanceof PHPEditor) {
- fEditor = editor;
- fViewer = viewer;
- fViewer.addProjectionListener(this);
- }
- }
-
- public void uninstall() {
- if (isInstalled()) {
- projectionDisabled();
- fViewer.removeProjectionListener(this);
- fViewer = null;
- fEditor = null;
- }
- }
-
- protected boolean isInstalled() {
- return fEditor != null;
- }
-
- /*
- * @see org.eclipse.jface.text.source.projection.IProjectionListener#projectionEnabled()
- */
- public void projectionEnabled() {
- // http://home.ott.oti.com/teams/wswb/anon/out/vms/index.html
- // projectionEnabled messages are not always paired with
- // projectionDisabled
- // i.e. multiple enabled messages may be sent out.
- // we have to make sure that we disable first when getting an enable
- // message.
- projectionDisabled();
-
- if (fEditor instanceof PHPEditor) {
- initialize();
- fElementListener = new ElementChangedListener();
- JavaCore.addElementChangedListener(fElementListener);
- }
- }
-
- /*
- * @see org.eclipse.jface.text.source.projection.IProjectionListener#projectionDisabled()
- */
- public void projectionDisabled() {
- fCachedDocument = null;
- if (fElementListener != null) {
- JavaCore.removeElementChangedListener(fElementListener);
- fElementListener = null;
- }
- }
-
- public void initialize() {
-
- if (!isInstalled())
- return;
-
- initializePreferences();
-
- try {
-
- IDocumentProvider provider = fEditor.getDocumentProvider();
- fCachedDocument = provider.getDocument(fEditor.getEditorInput());
- fAllowCollapsing = true;
-
- fFirstType = null;
- fHasHeaderComment = false;
-
- if (fEditor instanceof PHPUnitEditor) {
- IWorkingCopyManager manager = PHPeclipsePlugin.getDefault()
- .getWorkingCopyManager();
- fInput = manager.getWorkingCopy(fEditor.getEditorInput());
- }
- // else if (fEditor instanceof ClassFileEditor) {
- // IClassFileEditorInput editorInput= (IClassFileEditorInput)
- // fEditor.getEditorInput();
- // fInput= editorInput.getClassFile();
- // }
-
- if (fInput != null) {
- ProjectionAnnotationModel model = (ProjectionAnnotationModel) fEditor
- .getAdapter(ProjectionAnnotationModel.class);
- if (model != null) {
- fCachedModel = model;
- if (fInput instanceof ICompilationUnit) {
- ICompilationUnit unit = (ICompilationUnit) fInput;
- synchronized (unit) {
- try {
- // unit.reconcile(ICompilationUnit.NO_AST,
- // false, null, null);
- unit.reconcile();
- } catch (JavaModelException x) {
- }
- }
- }
-
- Map additions = computeAdditions((IParent) fInput);
- /*
- * Minimize the events being sent out - as this happens in
- * the UI thread merge everything into one call.
- */
- List removals = new LinkedList();
- Iterator existing = model.getAnnotationIterator();
- while (existing.hasNext())
- removals.add(existing.next());
- model.replaceAnnotations((Annotation[]) removals
- .toArray(new Annotation[removals.size()]),
- additions);
- }
- }
-
- } finally {
- fCachedDocument = null;
- fCachedModel = null;
- fAllowCollapsing = false;
-
- fFirstType = null;
- fHasHeaderComment = false;
- }
- }
-
- private void initializePreferences() {
- IPreferenceStore store = PHPeclipsePlugin.getDefault()
- .getPreferenceStore();
- fCollapseInnerTypes = store
- .getBoolean(PreferenceConstants.EDITOR_FOLDING_INNERTYPES);
- // fCollapseImportContainer =
- // store.getBoolean(PreferenceConstants.EDITOR_FOLDING_IMPORTS);
- fCollapseJavadoc = store
- .getBoolean(PreferenceConstants.EDITOR_FOLDING_JAVADOC);
- fCollapseMethods = store
- .getBoolean(PreferenceConstants.EDITOR_FOLDING_METHODS);
- fCollapseHeaderComments = store
- .getBoolean(PreferenceConstants.EDITOR_FOLDING_HEADERS);
- }
-
- private Map computeAdditions(IParent parent) {
- Map map = new LinkedHashMap(); // use a linked map to maintain ordering
- // of
- // comments
- try {
- computeAdditions(parent.getChildren(), map);
- } catch (JavaModelException x) {
- }
- return map;
- }
-
- private void computeAdditions(IJavaElement[] elements, Map map)
- throws JavaModelException {
- for (int i = 0; i < elements.length; i++) {
- IJavaElement element = elements[i];
-
- computeAdditions(element, map);
-
- if (element instanceof IParent) {
- IParent parent = (IParent) element;
- computeAdditions(parent.getChildren(), map);
- }
- }
- }
-
- private void computeAdditions(IJavaElement element, Map map) {
-
- boolean createProjection = false;
-
- boolean collapse = false;
- switch (element.getElementType()) {
-
- // case IJavaElement.IMPORT_CONTAINER:
- // collapse = fAllowCollapsing && fCollapseImportContainer;
- // createProjection = true;
- // break;
- case IJavaElement.TYPE:
- collapse = fAllowCollapsing;
- if (isInnerType((IType) element)) {
- collapse = collapse && fCollapseInnerTypes;
- } else {
- collapse = false; // don't allow the most outer type to be
- // folded, may be changed in future versions
- }
- createProjection = true;
- break;
- case IJavaElement.METHOD:
- collapse = fAllowCollapsing && fCollapseMethods;
- createProjection = true;
- break;
- }
-
- if (createProjection) {
- IRegion[] regions = computeProjectionRanges(element);
- if (regions != null) {
- // comments
- for (int i = 0; i < regions.length - 1; i++) {
- Position position = createProjectionPosition(regions[i],
- null);
- boolean commentCollapse;
- if (position != null) {
- if (i == 0 && (regions.length > 2 || fHasHeaderComment)
- && element == fFirstType) {
- commentCollapse = fAllowCollapsing
- && fCollapseHeaderComments;
- } else {
- commentCollapse = fAllowCollapsing
- && fCollapseJavadoc;
- }
- map.put(new JavaProjectionAnnotation(element,
- commentCollapse, true), position);
- }
- }
- // code
- Position position = createProjectionPosition(
- regions[regions.length - 1], element);
- if (position != null)
- map.put(new JavaProjectionAnnotation(element, collapse,
- false), position);
- }
- }
- }
-
- private boolean isInnerType(IType type) {
-
- try {
- return type.isMember();
- } catch (JavaModelException x) {
- IJavaElement parent = type.getParent();
- if (parent != null) {
- int parentType = parent.getElementType();
- return (parentType != IJavaElement.COMPILATION_UNIT && parentType != IJavaElement.CLASS_FILE);
- }
- }
-
- return false;
- }
-
- /**
- * Computes the projection ranges for a given IJavaElement
.
- * More than one range may be returned if the element has a leading comment
- * which gets folded separately. If there are no foldable regions,
- * null
is returned.
- *
- * @param element
- * the java element that can be folded
- * @return the regions to be folded, or null
if there are
- * none
- */
- private IRegion[] computeProjectionRanges(IJavaElement element) {
-
- try {
- if (element instanceof ISourceReference) {
- ISourceReference reference = (ISourceReference) element;
- ISourceRange range = reference.getSourceRange();
-
- String contents = reference.getSource();
- if (contents == null)
- return null;
-
- List regions = new ArrayList();
- // now add all comments first to the regions list
- if (fFirstType == null && element instanceof IType) {
- fFirstType = (IType) element;
- IRegion headerComment = computeHeaderComment(fFirstType);
- if (headerComment != null) {
- regions.add(headerComment);
- fHasHeaderComment = true;
- }
- }
-
- final int shift = range.getOffset();
- int start = shift;
- if (element instanceof IType) {
- Scanner scanner = ToolFactory.createScanner(true, false,
- false, false);
- scanner.setSource(contents.toCharArray());
- scanner.setPHPMode(true);
-
- int token = scanner.getNextToken();
- while (token != ITerminalSymbols.TokenNameEOF) {
-
- token = scanner.getNextToken();
- start = shift + scanner.getCurrentTokenStartPosition();
-
- switch (token) {
- case ITerminalSymbols.TokenNameCOMMENT_PHPDOC:
- case ITerminalSymbols.TokenNameCOMMENT_BLOCK: {
- int end = shift
- + scanner.getCurrentTokenEndPosition() + 1;
- regions.add(new Region(start, end - start));
- }
- case ITerminalSymbols.TokenNameCOMMENT_LINE:
- continue;
- }
- }
- }
- // at the end add the element region
- regions.add(new Region(range.getOffset(), range.getLength()));
-
- if (regions.size() > 0) {
- IRegion[] result = new IRegion[regions.size()];
- regions.toArray(result);
- return result;
- }
-
- }
- } catch (JavaModelException e) {
- } catch (InvalidInputException e) {
- }
-
- return null;
- }
-
- private IRegion computeHeaderComment(IType type) throws JavaModelException {
- if (fCachedDocument == null)
- return null;
-
- // search at most up to the first type
- ISourceRange range = type.getSourceRange();
- if (range == null)
- return null;
- int start = 0;
- int end = range.getOffset();
-
- if (fInput instanceof ISourceReference) {
- String content;
- try {
- content = fCachedDocument.get(start, end - start);
- } catch (BadLocationException e) {
- return null; // ignore header comment in that case
- }
-
- /*
- * code adapted from CommentFormattingStrategy: scan the header
- * content up to the first type. Once a comment is found, accumulate
- * any additional comments up to the stop condition. The stop
- * condition is reaching a package declaration, import container, or
- * the end of the input.
- */
- IScanner scanner = ToolFactory.createScanner(true, false, false,
- false);
- scanner.setSource(content.toCharArray());
-
- int headerStart = -1;
- int headerEnd = -1;
- try {
- boolean foundComment = false;
- int terminal = scanner.getNextToken();
- while (terminal != ITerminalSymbols.TokenNameEOF
- && !(terminal == ITerminalSymbols.TokenNameclass
- || terminal == ITerminalSymbols.TokenNameinterface || foundComment)) {
-
- if (terminal == ITerminalSymbols.TokenNameCOMMENT_PHPDOC
- || terminal == ITerminalSymbols.TokenNameCOMMENT_BLOCK
- || terminal == ITerminalSymbols.TokenNameCOMMENT_LINE) {
- if (!foundComment)
- headerStart = scanner
- .getCurrentTokenStartPosition();
- headerEnd = scanner.getCurrentTokenEndPosition();
- foundComment = true;
- }
- terminal = scanner.getNextToken();
- }
-
- } catch (InvalidInputException ex) {
- return null;
- }
-
- if (headerEnd != -1) {
- return new Region(headerStart, headerEnd - headerStart);
- }
- }
- return null;
- }
-
- private Position createProjectionPosition(IRegion region,
- IJavaElement element) {
-
- if (fCachedDocument == null)
- return null;
-
- try {
-
- int start = fCachedDocument.getLineOfOffset(region.getOffset());
- int end = fCachedDocument.getLineOfOffset(region.getOffset()
- + region.getLength());
- if (start != end) {
- int offset = fCachedDocument.getLineOffset(start);
- int endOffset;
- if (fCachedDocument.getNumberOfLines() > end + 1)
- endOffset = fCachedDocument.getLineOffset(end + 1);
- else if (end > start)
- endOffset = fCachedDocument.getLineOffset(end)
- + fCachedDocument.getLineLength(end);
- else
- return null;
- if (element instanceof IMember)
- return new JavaElementPosition(offset, endOffset - offset,
- (IMember) element);
- else
- return new CommentPosition(offset, endOffset - offset);
- }
-
- } catch (BadLocationException x) {
- }
-
- return null;
- }
-
- protected void processDelta(IJavaElementDelta delta) {
-
- if (!isInstalled())
- return;
-
- if ((delta.getFlags() & (IJavaElementDelta.F_CONTENT | IJavaElementDelta.F_CHILDREN)) == 0)
- return;
-
- ProjectionAnnotationModel model = (ProjectionAnnotationModel) fEditor
- .getAdapter(ProjectionAnnotationModel.class);
- if (model == null)
- return;
-
- try {
-
- IDocumentProvider provider = fEditor.getDocumentProvider();
- fCachedDocument = provider.getDocument(fEditor.getEditorInput());
- fCachedModel = model;
- fAllowCollapsing = false;
-
- fFirstType = null;
- fHasHeaderComment = false;
-
- Map additions = new HashMap();
- List deletions = new ArrayList();
- List updates = new ArrayList();
-
- Map updated = computeAdditions((IParent) fInput);
- Map previous = createAnnotationMap(model);
-
- Iterator e = updated.keySet().iterator();
- while (e.hasNext()) {
- JavaProjectionAnnotation newAnnotation = (JavaProjectionAnnotation) e
- .next();
-//+
- Position newPosition = (Position) updated.get(newAnnotation);
- additions.put(newAnnotation, newPosition);
-//-
-// IJavaElement element = newAnnotation.getElement();
-// Position newPosition = (Position) updated.get(newAnnotation);
-//
-// List annotations = (List) previous.get(element);
-// if (annotations == null) {
-//
-// additions.put(newAnnotation, newPosition);
-//
-// } else {
-// Iterator x = annotations.iterator();
-// boolean matched = false;
-// while (x.hasNext()) {
-// Tuple tuple = (Tuple) x.next();
-// JavaProjectionAnnotation existingAnnotation = tuple.annotation;
-// Position existingPosition = tuple.position;
-// if (newAnnotation.isComment() == existingAnnotation
-// .isComment()) {
-// if (existingPosition != null
-// && (!newPosition.equals(existingPosition))) {
-// existingPosition.setOffset(newPosition
-// .getOffset());
-// existingPosition.setLength(newPosition
-// .getLength());
-// updates.add(existingAnnotation);
-// }
-// matched = true;
-// x.remove();
-// break;
-// }
-// }
-// if (!matched)
-// additions.put(newAnnotation, newPosition);
-//
-// if (annotations.isEmpty())
-// previous.remove(element);
-// }
-//-
- }
-
- e = previous.values().iterator();
- while (e.hasNext()) {
- List list = (List) e.next();
- int size = list.size();
- for (int i = 0; i < size; i++)
- deletions.add(((Tuple) list.get(i)).annotation);
- }
-
- match(deletions, additions, updates);
-
- Annotation[] removals = new Annotation[deletions.size()];
- deletions.toArray(removals);
- Annotation[] changes = new Annotation[updates.size()];
- updates.toArray(changes);
- model.modifyAnnotations(removals, additions, changes);
-
- } finally {
- fCachedDocument = null;
- fAllowCollapsing = true;
- fCachedModel = null;
-
- fFirstType = null;
- fHasHeaderComment = false;
- }
- }
-
- /**
- * Matches deleted annotations to changed or added ones. A deleted
- * annotation/position tuple that has a matching addition / change is
- * updated and marked as changed. The matching tuple is not added (for
- * additions) or marked as deletion instead (for changes). The result is
- * that more annotations are changed and fewer get deleted/re-added.
- */
- private void match(List deletions, Map additions, List changes) {
- if (deletions.isEmpty() || (additions.isEmpty() && changes.isEmpty()))
- return;
-
- List newDeletions = new ArrayList();
- List newChanges = new ArrayList();
-
- Iterator deletionIterator = deletions.iterator();
- while (deletionIterator.hasNext()) {
- JavaProjectionAnnotation deleted = (JavaProjectionAnnotation) deletionIterator
- .next();
- Position deletedPosition = fCachedModel.getPosition(deleted);
- if (deletedPosition == null)
- continue;
-
- Tuple deletedTuple = new Tuple(deleted, deletedPosition);
-
- Tuple match = findMatch(deletedTuple, changes, null);
- boolean addToDeletions = true;
- if (match == null) {
- match = findMatch(deletedTuple, additions.keySet(), additions);
- addToDeletions = false;
- }
-
- if (match != null) {
- IJavaElement element = match.annotation.getElement();
- deleted.setElement(element);
- deletedPosition.setLength(match.position.getLength());
- if (deletedPosition instanceof JavaElementPosition
- && element instanceof IMember) {
- JavaElementPosition jep = (JavaElementPosition) deletedPosition;
- jep.setMember((IMember) element);
- }
-
- deletionIterator.remove();
- newChanges.add(deleted);
-
- if (addToDeletions)
- newDeletions.add(match.annotation);
- }
- }
-
- deletions.addAll(newDeletions);
- changes.addAll(newChanges);
- }
-
- /**
- * Finds a match for tuple
in a collection of annotations.
- * The positions for the JavaProjectionAnnotation
instances
- * in annotations
can be found in the passed
- * positionMap
or fCachedModel
if
- * positionMap
is null
.
- *
- * A tuple is said to match another if their annotations have the same - * comment flag and their position offsets are equal. - *
- *
- * If a match is found, the annotation gets removed from
- * annotations
.
- *
JavaProjectionAnnotation
- * @param positionMap
- * a Map<Annotation, Position>
or
- * null
- * @return a matching tuple or null
for no match
- */
- private Tuple findMatch(Tuple tuple, Collection annotations, Map positionMap) {
- Iterator it = annotations.iterator();
- while (it.hasNext()) {
- JavaProjectionAnnotation annotation = (JavaProjectionAnnotation) it
- .next();
- if (tuple.annotation.isComment() == annotation.isComment()) {
- Position position = positionMap == null ? fCachedModel
- .getPosition(annotation) : (Position) positionMap
- .get(annotation);
- if (position == null)
- continue;
-
- if (tuple.position.getOffset() == position.getOffset()) {
- it.remove();
- return new Tuple(annotation, position);
- }
- }
- }
-
- return null;
- }
-
- private Map createAnnotationMap(IAnnotationModel model) {
- Map map = new HashMap();
- Iterator e = model.getAnnotationIterator();
- while (e.hasNext()) {
- Object annotation = e.next();
- if (annotation instanceof JavaProjectionAnnotation) {
- JavaProjectionAnnotation java = (JavaProjectionAnnotation) annotation;
- Position position = model.getPosition(java);
- Assert.isNotNull(position);
- List list = (List) map.get(java.getElement());
- if (list == null) {
- list = new ArrayList(2);
- map.put(java.getElement(), list);
- }
- list.add(new Tuple(java, position));
- }
- }
-
- Comparator comparator = new Comparator() {
- public int compare(Object o1, Object o2) {
- return ((Tuple) o1).position.getOffset()
- - ((Tuple) o2).position.getOffset();
- }
- };
- for (Iterator it = map.values().iterator(); it.hasNext();) {
- List list = (List) it.next();
- Collections.sort(list, comparator);
- }
- return map;
- }
-}
\ No newline at end of file