Code folding for PHPdoc at start of PHP file
authoraxelcl <axelcl>
Tue, 27 Sep 2005 20:32:14 +0000 (20:32 +0000)
committeraxelcl <axelcl>
Tue, 27 Sep 2005 20:32:14 +0000 (20:32 +0000)
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/DocumentCharacterIterator.java
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/text/folding/DefaultJavaFoldingStructureProvider.java
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/ui/PreferenceConstants.java

index 1aabb54..ea30c7a 100644 (file)
@@ -1,10 +1,10 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2004 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
+ * Copyright (c) 2000, 2005 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/cpl-v10.html
- * 
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
@@ -18,8 +18,15 @@ import org.eclipse.jface.text.IDocument;
 
 
 /**
- * An <code>IDocument</code> based implementation of <code>CharacterIterator</code>.
- * 
+ * An <code>IDocument</code> based implementation of
+ * <code>CharacterIterator</code> and <code>CharSequence</code>. Note that
+ * the supplied document is not copied; if the document is modified during the
+ * lifetime of a <code>DocumentCharacterIterator</code>, the methods
+ * returning document content may not always return the same values. Also, if
+ * accessing the document fails with a {@link BadLocationException}, any of
+ * <code>CharacterIterator</code> methods as well as <code>charAt</code>may
+ * return {@link CharacterIterator#DONE}.
+ *
  * @since 3.0
  */
 public class DocumentCharacterIterator implements CharacterIterator, CharSequence {
@@ -28,48 +35,49 @@ public class DocumentCharacterIterator implements CharacterIterator, CharSequenc
        private final IDocument fDocument;
        private final int fFirst;
        private final int fLast;
-       
+
        private void invariant() {
                Assert.isTrue(fIndex >= fFirst);
                Assert.isTrue(fIndex <= fLast);
        }
-       
+
        /**
-        * Creates an iterator for the entire sequence.
-        * 
-        * @param sequence the sequence backing this iterator
+        * Creates an iterator for the entire document.
+        *
+        * @param document the document backing this iterator
         */
-       public DocumentCharacterIterator(IDocument sequence) {
-               this(sequence, 0);
+       public DocumentCharacterIterator(IDocument document) {
+               this(document, 0);
        }
-       
+
        /**
-        * Creates an iterator.
-        * 
-        * @param sequence the sequence backing this iterator
+        * Creates an iterator, starting at offset <code>first</code>.
+        *
+        * @param document the document backing this iterator
         * @param first the first character to consider
         * @throws IllegalArgumentException if the indices are out of bounds
         */
-       public DocumentCharacterIterator(IDocument sequence, int first) throws IllegalArgumentException {
-               this(sequence, first, sequence.getLength());
+       public DocumentCharacterIterator(IDocument document, int first) throws IllegalArgumentException {
+               this(document, first, document.getLength());
        }
 
        /**
-        * Creates an iterator.
-        * 
-        * @param sequence the sequence backing this iterator
+        * Creates an iterator for the document contents from <code>first</code>
+        * (inclusive) to <code>last</code> (exclusive).
+        *
+        * @param document the document backing this iterator
         * @param first the first character to consider
         * @param last the last character index to consider
         * @throws IllegalArgumentException if the indices are out of bounds
         */
-       public DocumentCharacterIterator(IDocument sequence, int first, int last) throws IllegalArgumentException {
-               if (sequence == null)
+       public DocumentCharacterIterator(IDocument document, int first, int last) throws IllegalArgumentException {
+               if (document == null)
                        throw new NullPointerException();
                if (first < 0 || first > last)
                        throw new IllegalArgumentException();
-               if (last > sequence.getLength())
+               if (last > document.getLength())
                        throw new IllegalArgumentException();
-               fDocument= sequence;
+               fDocument= document;
                fFirst= first;
                fLast= last;
                fIndex= first;
@@ -132,7 +140,7 @@ public class DocumentCharacterIterator implements CharacterIterator, CharSequenc
                        fIndex= position;
                else
                        throw new IllegalArgumentException();
-               
+
                invariant();
                return current();
        }
@@ -176,25 +184,39 @@ public class DocumentCharacterIterator implements CharacterIterator, CharSequenc
                return getEndIndex() - getBeginIndex();
        }
 
-       /*
-        * @see java.lang.CharSequence#charAt(int)
+       /**
+        * {@inheritDoc}
+        * <p>
+        * Note that, if the document is modified concurrently, this method may
+        * return {@link CharacterIterator#DONE} if a {@link BadLocationException}
+        * was thrown when accessing the backing document.
+        * </p>
+        *
+        * @param index {@inheritDoc}
+        * @return {@inheritDoc}
         */
        public char charAt(int index) {
-               if (index >= getBeginIndex() && index <= getEndIndex())
+               if (index >= 0 && index < length())
                        try {
-                               return fDocument.getChar(index);
+                               return fDocument.getChar(getBeginIndex() + index);
                        } catch (BadLocationException e) {
                                // ignore and return DONE
                                return DONE;
                        }
                else
-                       throw new IllegalArgumentException();
+                       throw new IndexOutOfBoundsException();
        }
 
        /*
         * @see java.lang.CharSequence#subSequence(int, int)
         */
        public CharSequence subSequence(int start, int end) {
-               return new DocumentCharacterIterator(fDocument, getBeginIndex() + start, getBeginIndex() + start + end);
+               if (start < 0)
+                       throw new IndexOutOfBoundsException();
+               if (end < start)
+                       throw new IndexOutOfBoundsException();
+               if (end > length())
+                       throw new IndexOutOfBoundsException();
+               return new DocumentCharacterIterator(fDocument, getBeginIndex() + start, getBeginIndex() + end);
        }
 }
index 4d81074..a15d39c 100644 (file)
@@ -1,25 +1,32 @@
 /*******************************************************************************
  * Copyright (c) 2000, 2003 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials 
+ * 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;
@@ -30,6 +37,7 @@ 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.ui.text.DocumentCharacterIterator;
 import net.sourceforge.phpdt.ui.IWorkingCopyManager;
 import net.sourceforge.phpdt.ui.PreferenceConstants;
 import net.sourceforge.phpdt.ui.text.folding.IJavaFoldingStructureProvider;
@@ -38,6 +46,7 @@ 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;
@@ -46,193 +55,477 @@ 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;
+                       fJavaElement = element;
+                       fIsComment = isComment;
                }
-               
+
                public IJavaElement getElement() {
                        return fJavaElement;
                }
-               
+
                public void setElement(IJavaElement element) {
-                       fJavaElement= element;
+                       fJavaElement = element;
                }
-               
+
                public boolean isComment() {
                        return fIsComment;
                }
-               
+
                public void setIsComment(boolean isComment) {
-                       fIsComment= 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 net.sourceforge.phpdt.core.IElementChangedListener#elementChanged(net.sourceforge.phpdt.core.ElementChangedEvent)
+                * @see org.eclipse.jdt.core.IElementChangedListener#elementChanged(org.eclipse.jdt.core.ElementChangedEvent)
                 */
                public void elementChanged(ElementChangedEvent e) {
-                       IJavaElementDelta delta= findElement(fInput, e.getDelta());
+                       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();
-                       
+
+                       IJavaElement element = delta.getElement();
+
                        if (element.getElementType() > IJavaElement.CLASS_FILE)
                                return null;
-                       
+
                        if (target.equals(element))
-                               return delta;                           
-                       
-                       IJavaElementDelta[] children= delta.getAffectedChildren();
-                       if (children == null || children.length == 0)
-                               return null;
-                               
-                       for (int i= 0; i < children.length; i++) {
-                               IJavaElementDelta d= findElement(target, children[i]);
+                               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 <code>content</code>.
+                * 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
+               // <code>content</code>.
+               // * 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 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;
+                       fEditor = editor;
+                       fViewer = viewer;
                        fViewer.addProjectionListener(this);
                }
        }
-       
+
        public void uninstall() {
                if (isInstalled()) {
                        projectionDisabled();
                        fViewer.removeProjectionListener(this);
-                       fViewer= null;
-                       fEditor= null;
+                       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();
+                       fElementListener = new ElementChangedListener();
                        JavaCore.addElementChangedListener(fElementListener);
                }
        }
-       
+
        /*
         * @see org.eclipse.jface.text.source.projection.IProjectionListener#projectionDisabled()
         */
        public void projectionDisabled() {
-               fCachedDocument= null;
+               fCachedDocument = null;
                if (fElementListener != null) {
                        JavaCore.removeElementChangedListener(fElementListener);
-                       fElementListener= null;
+                       fElementListener = null;
                }
        }
-               
+
        public void initialize() {
-               
+
                if (!isInstalled())
                        return;
-               
+
                initializePreferences();
-               
+
                try {
-                       
-                       IDocumentProvider provider= fEditor.getDocumentProvider();
-                       fCachedDocument= provider.getDocument(fEditor.getEditorInput());
-                       fAllowCollapsing= true;
-                       
+
+                       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();
-//                     }
-                       
+                               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);
+                               ProjectionAnnotationModel model = (ProjectionAnnotationModel) fEditor.getAdapter(ProjectionAnnotationModel.class);
                                if (model != null) {
-                                       Map additions= computeAdditions((IParent) fInput);
-                                       model.removeAllAnnotations();
-                                       model.replaceAnnotations(null, additions);
+                                       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;
-                       fAllowCollapsing= false;
+                       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);
+               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 HashMap();
+               Map map = new LinkedHashMap(); // use a linked map to maintain ordering of
+                                                                                                                                               // comments
                try {
                        computeAdditions(parent.getChildren(), map);
                } catch (JavaModelException x) {
@@ -241,50 +534,57 @@ public class DefaultJavaFoldingStructureProvider implements IProjectionListener,
        }
 
        private void computeAdditions(IJavaElement[] elements, Map map) throws JavaModelException {
-               for (int i= 0; i < elements.length; i++) {
-                       IJavaElement element= elements[i];
-                       
+               for (int i = 0; i < elements.length; i++) {
+                       IJavaElement element = elements[i];
+
                        computeAdditions(element, map);
-                       
+
                        if (element instanceof IParent) {
-                               IParent parent= (IParent) element;
+                               IParent parent = (IParent) element;
                                computeAdditions(parent.getChildren(), map);
                        }
                }
        }
 
        private void computeAdditions(IJavaElement element, Map map) {
-               
-               boolean createProjection= false;
-               
-               boolean collapse= false;
+
+               boolean createProjection = false;
+
+               boolean collapse = false;
                switch (element.getElementType()) {
-                       
-                       case IJavaElement.IMPORT_CONTAINER:
-                               collapse= fAllowCollapsing && fCollapseImportContainer;
-                               createProjection= true;
-                               break;
-                       case IJavaElement.TYPE:
-                               collapse= fAllowCollapsing && fCollapseInnerTypes && isInnerType((IType) element);
-                               createProjection= true;
-                               break;
-                       case IJavaElement.METHOD:
-                               collapse= fAllowCollapsing && fCollapseMethods;
-                               createProjection= true;
-                               break;
-               }
-               
+
+//             case IJavaElement.IMPORT_CONTAINER:
+//                     collapse = fAllowCollapsing && fCollapseImportContainer;
+//                     createProjection = true;
+//                     break;
+               case IJavaElement.TYPE:
+                       collapse = fAllowCollapsing && fCollapseInnerTypes && isInnerType((IType) element);
+                       createProjection = true;
+                       break;
+               case IJavaElement.METHOD:
+                       collapse = fAllowCollapsing && fCollapseMethods;
+                       createProjection = true;
+                       break;
+               }
+
                if (createProjection) {
-                       IRegion[] regions= computeProjectionRanges(element);
+                       IRegion[] regions = computeProjectionRanges(element);
                        if (regions != null) {
                                // comments
-                               for (int i= 0; i < regions.length - 1; i++) {
-                                       Position position= createProjectionPosition(regions[i]);
-                                       if (position != null)
-                                               map.put(new JavaProjectionAnnotation(element, fAllowCollapsing && fCollapseJavadoc, true), position);
+                               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]);
+                               Position position = createProjectionPosition(regions[regions.length - 1], element);
                                if (position != null)
                                        map.put(new JavaProjectionAnnotation(element, collapse, false), position);
                        }
@@ -292,58 +592,77 @@ public class DefaultJavaFoldingStructureProvider implements IProjectionListener,
        }
 
        private boolean isInnerType(IType type) {
-               
+
                try {
                        return type.isMember();
                } catch (JavaModelException x) {
-                       IJavaElement parent= type.getParent();
+                       IJavaElement parent = type.getParent();
                        if (parent != null) {
-                               int parentType= parent.getElementType();
+                               int parentType = parent.getElementType();
                                return (parentType != IJavaElement.COMPILATION_UNIT && parentType != IJavaElement.CLASS_FILE);
                        }
                }
-               
-               return false;           
+
+               return false;
        }
 
+       /**
+        * Computes the projection ranges for a given <code>IJavaElement</code>.
+        * More than one range may be returned if the element has a leading comment
+        * which gets folded separately. If there are no foldable regions,
+        * <code>null</code> is returned.
+        *
+        * @param element
+        *          the java element that can be folded
+        * @return the regions to be folded, or <code>null</code> 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();
+                               ISourceReference reference = (ISourceReference) element;
+                               ISourceRange range = reference.getSourceRange();
+
+                               String contents = reference.getSource();
                                if (contents == null)
                                        return null;
-                               
-                               IScanner scanner= ToolFactory.createScanner(true/*tokenizeComments*/, false, false, true /* phpMode */ );
+
+                               List regions = new ArrayList();
+                               if (fFirstType == null && element instanceof IType) {
+                                       fFirstType = (IType) element;
+                                       IRegion headerComment = computeHeaderComment(fFirstType);
+                                       if (headerComment != null) {
+                                               regions.add(headerComment);
+                                               fHasHeaderComment = true;
+                                       }
+                               }
+
+                               IScanner scanner = ToolFactory.createScanner(true, false, false, false);
                                scanner.setSource(contents.toCharArray());
-                               
-                               List regions= new ArrayList();
-                               int shift= range.getOffset();
-                               int start= shift;
+                               final int shift = range.getOffset();
+                               int start = shift;
                                while (true) {
-                                       
-                                       int token= scanner.getNextToken();
-                                       start= shift + scanner.getCurrentTokenStartPosition();
-                                       
+
+                                       int token = scanner.getNextToken();
+                                       start = shift + scanner.getCurrentTokenStartPosition();
+
                                        switch (token) {
-                                               case ITerminalSymbols.TokenNameCOMMENT_PHPDOC: //  COMMENT_JAVADOC:
-                                               case ITerminalSymbols.TokenNameCOMMENT_BLOCK: {
-                                                       int end= shift + scanner.getCurrentTokenEndPosition() + 1;
-                                                       regions.add(new Region(start, end - start));
-                                               }
-                                               case ITerminalSymbols.TokenNameCOMMENT_LINE:
-                                                       continue;
+                                       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;
                                        }
-                                       
+
                                        break;
                                }
-                               
-                               regions.add(new Region(start, range.getOffset() + range.getLength() - start));
-                               
+
+                               regions.add(new Region(start, shift + range.getLength() - start));
+
                                if (regions.size() > 0) {
-                                       IRegion[] result= new IRegion[regions.size()];
+                                       IRegion[] result = new IRegion[regions.size()];
                                        regions.toArray(result);
                                        return result;
                                }
@@ -351,188 +670,310 @@ public class DefaultJavaFoldingStructureProvider implements IProjectionListener,
                } catch (JavaModelException e) {
                } catch (InvalidInputException e) {
                }
-               
+
                return null;
        }
-       
-       private Position createProjectionPosition(IRegion region) {
-               
+
+       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());
+
+                       int start = fCachedDocument.getLineOfOffset(region.getOffset());
+                       int end = fCachedDocument.getLineOfOffset(region.getOffset() + region.getLength());
                        if (start != end) {
-                               int offset= fCachedDocument.getLineOffset(start);
-                               int endOffset= fCachedDocument.getLineOffset(end + 1);
-                               return new Position(offset, endOffset - offset);
+                               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;
-               
-               ProjectionAnnotationModel model= (ProjectionAnnotationModel) fEditor.getAdapter(ProjectionAnnotationModel.class);
+
+               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());
-                       fAllowCollapsing= 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();
+
+                       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 annotation= (JavaProjectionAnnotation) e.next();
-                               IJavaElement element= annotation.getElement();
-                               Position position= (Position) updated.get(annotation);
-                               
-                               List annotations= (List) previous.get(element);
+                               JavaProjectionAnnotation newAnnotation = (JavaProjectionAnnotation) e.next();
+                               IJavaElement element = newAnnotation.getElement();
+                               Position newPosition = (Position) updated.get(newAnnotation);
+
+                               List annotations = (List) previous.get(element);
                                if (annotations == null) {
-                                       
-                                       additions.put(annotation, position);
-                                       
+
+                                       additions.put(newAnnotation, newPosition);
+
                                } else {
-                                       
-                                       Iterator x= annotations.iterator();
+                                       Iterator x = annotations.iterator();
+                                       boolean matched = false;
                                        while (x.hasNext()) {
-                                               JavaProjectionAnnotation a= (JavaProjectionAnnotation) x.next();
-                                               if (annotation.isComment() == a.isComment()) {
-                                                       Position p= model.getPosition(a);
-                                                       if (p != null && !position.equals(p)) {
-                                                               p.setOffset(position.getOffset());
-                                                               p.setLength(position.getLength());
-                                                               updates.add(a);
+                                               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();
+
+                       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(list.get(i));
+                               List list = (List) e.next();
+                               int size = list.size();
+                               for (int i = 0; i < size; i++)
+                                       deletions.add(((Tuple) list.get(i)).annotation);
                        }
-                       
-                       match(model, deletions, additions, updates);
-                       
-                       Annotation[] removals= new Annotation[deletions.size()];
+
+                       match(deletions, additions, updates);
+
+                       Annotation[] removals = new Annotation[deletions.size()];
                        deletions.toArray(removals);
-                       Annotation[] changes= new Annotation[updates.size()];
+                       Annotation[] changes = new Annotation[updates.size()];
                        updates.toArray(changes);
                        model.modifyAnnotations(removals, additions, changes);
-                       
+
                } finally {
-                       fCachedDocument= null;
-                       fAllowCollapsing= true;
+                       fCachedDocument = null;
+                       fAllowCollapsing = true;
+                       fCachedModel = null;
+
+                       fFirstType = null;
+                       fHasHeaderComment = false;
                }
        }
-       
-       private void match(ProjectionAnnotationModel model, List deletions, Map additions, List changes) {
+
+       /**
+        * 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();
-               outer: while (deletionIterator.hasNext()) {
-                       JavaProjectionAnnotation deleted= (JavaProjectionAnnotation) deletionIterator.next();
-                       Position deletedPosition= model.getPosition(deleted);
+
+               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;
-                       
-                       Iterator changesIterator= changes.iterator();
-                       while (changesIterator.hasNext()) {
-                               JavaProjectionAnnotation changed= (JavaProjectionAnnotation) changesIterator.next();
-                               if (deleted.isComment() == changed.isComment()) {
-                                       Position changedPosition= model.getPosition(changed);
-                                       if (changedPosition == null)
-                                               continue;
-                                       
-                                       if (deletedPosition.getOffset() == changedPosition.getOffset()) {
-                                               
-                                               deletedPosition.setLength(changedPosition.getLength());
-                                               deleted.setElement(changed.getElement());
-                                               
-                                               deletionIterator.remove();
-                                               newChanges.add(deleted);
-                                               
-                                               changesIterator.remove();
-                                               newDeletions.add(changed);
-                                               
-                                               continue outer;
-                                       }
-                               }
+
+                       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;
                        }
-                       
-                       Iterator additionsIterator= additions.keySet().iterator();
-                       while (additionsIterator.hasNext()) {
-                               JavaProjectionAnnotation added= (JavaProjectionAnnotation) additionsIterator.next();
-                               if (deleted.isComment() == added.isComment()) {
-                                       Position addedPosition= (Position) additions.get(added);
-                                       
-                                       if (deletedPosition.getOffset() == addedPosition.getOffset()) {
-                                               
-                                               deletedPosition.setLength(addedPosition.getLength());
-                                               deleted.setElement(added.getElement());
-                                               
-                                               deletionIterator.remove();
-                                               newChanges.add(deleted);
-                                               
-                                               additionsIterator.remove();
-                                               
-                                               break;
-                                       }
+
+                       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 <code>tuple</code> in a collection of annotations. The
+        * positions for the <code>JavaProjectionAnnotation</code> instances in
+        * <code>annotations</code> can be found in the passed
+        * <code>positionMap</code> or <code>fCachedModel</code> if
+        * <code>positionMap</code> is <code>null</code>.
+        * <p>
+        * A tuple is said to match another if their annotations have the same comment
+        * flag and their position offsets are equal.
+        * </p>
+        * <p>
+        * If a match is found, the annotation gets removed from
+        * <code>annotations</code>.
+        * </p>
+        *
+        * @param tuple
+        *          the tuple for which we want to find a match
+        * @param annotations
+        *          collection of <code>JavaProjectionAnnotation</code>
+        * @param positionMap
+        *          a <code>Map&lt;Annotation, Position&gt;</code> or
+        *          <code>null</code>
+        * @return a matching tuple or <code>null</code> 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();
+               Map map = new HashMap();
+               Iterator e = model.getAnnotationIterator();
                while (e.hasNext()) {
-                       Object annotation= e.next();
+                       Object annotation = e.next();
                        if (annotation instanceof JavaProjectionAnnotation) {
-                               JavaProjectionAnnotation java= (JavaProjectionAnnotation) annotation;
-                               List list= (List) map.get(java.getElement());
+                               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);
+                                       list = new ArrayList(2);
                                        map.put(java.getElement(), list);
                                }
-                               list.add(java);
+                               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
index 220c27c..9aa8ef0 100644 (file)
@@ -1,10 +1,10 @@
 /*******************************************************************************
  * Copyright (c) 2002 International Business Machines Corp. and others.
- * All rights reserved. This program and the accompanying materials 
- * are made available under the terms of the Common Public License v1.0 
+ * 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-v05.html
- * 
+ *
  * Contributors:
  *     IBM Corporation - initial API and implementation
  ******************************************************************************/
@@ -32,7 +32,7 @@ import org.eclipse.ui.texteditor.AbstractTextEditor;
 /**
  * Preference constants used in the JDT-UI preference store. Clients should only read the JDT-UI preference store using these
  * values. Clients are not allowed to modify the preference store programmatically.
- * 
+ *
  * @since 2.0
  */
 public class PreferenceConstants {
@@ -70,7 +70,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @see #APPEARANCE_PKG_NAME_PATTERN_FOR_PKG_VIEW
    */
   public static final String APPEARANCE_COMPRESS_PACKAGE_NAMES = "net.sourceforge.phpdt.ui.compresspackagenames"; //$NON-NLS-1$
@@ -80,7 +80,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>: if <code>true</code> empty inner packages are folded.
    * </p>
-   * 
+   *
    * @since 2.1
    */
   public static final String APPEARANCE_FOLD_PACKAGES_IN_PACKAGE_EXPLORER = "net.sourceforge.phpdt.ui.flatPackagesInPackageExplorer"; //$NON-NLS-1$
@@ -101,7 +101,7 @@ public class PreferenceConstants {
    * <li><b>SF </b>: Static Fields</li>
    * </ul>
    * </p>
-   * 
+   *
    * @since 2.1
    */
   public static final String APPEARANCE_MEMBER_SORT_ORDER = "outlinesortoption"; //$NON-NLS-1$
@@ -119,7 +119,7 @@ public class PreferenceConstants {
    * <li><b>D </b>: Default</li>
    * </ul>
    * </p>
-   * 
+   *
    * @since 3.0
    */
   public static final String APPEARANCE_VISIBILITY_SORT_ORDER = "net.sourceforge.phpdt.ui.visibility.order"; //$NON-NLS-1$
@@ -129,7 +129,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 3.0
    */
   public static final String APPEARANCE_ENABLE_VISIBILITY_SORT_ORDER = "net.sourceforge.phpdt.ui.enable.visibility.order"; //$NON-NLS-1$
@@ -147,7 +147,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>String</code>: comma separated list of prefixed
    * </p>
-   * 
+   *
    * @see #CODEGEN_USE_GETTERSETTER_PREFIX
    */
   public static final String CODEGEN_GETTERSETTER_PREFIX = "net.sourceforge.phpdt.ui.gettersetter.prefix.list"; //$NON-NLS-1$
@@ -165,7 +165,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>String</code>: comma separated list of suffixes
    * </p>
-   * 
+   *
    * @see #CODEGEN_USE_GETTERSETTER_SUFFIX
    */
   public static final String CODEGEN_GETTERSETTER_SUFFIX = "net.sourceforge.phpdt.ui.gettersetter.suffix.list"; //$NON-NLS-1$
@@ -188,8 +188,8 @@ public class PreferenceConstants {
         * @since 3.0
         */
        public static final String CODEGEN_IS_FOR_GETTERS= "org.eclipse.jdt.ui.gettersetter.use.is"; //$NON-NLS-1$
-       
-       
+
+
        /**
         * A named preference that defines the preferred variable names for exceptions in
         * catch clauses.
@@ -197,15 +197,15 @@ public class PreferenceConstants {
         * Value is of type <code>String</code>.
         * </p>
         * @since 3.0
-        */     
+        */
        public static final String CODEGEN_EXCEPTION_VAR_NAME= "org.eclipse.jdt.ui.exception.name"; //$NON-NLS-1$
-       
+
   /**
    * A named preference that controls if comment stubs will be added automatically to newly created types and methods.
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 2.1
    */
   public static final String CODEGEN_ADD_COMMENTS = "net.sourceforge.phpdt.ui.phpdoc"; //$NON-NLS-1$
@@ -215,7 +215,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @deprecated Use CODEGEN_ADD_COMMENTS instead (Name is more precise).
    */
   //  public static final String CODEGEN__JAVADOC_STUBS = CODEGEN_ADD_COMMENTS; //$NON-NLS-1$
@@ -289,7 +289,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 2.1
    */
   public static final String LINK_BROWSING_VIEW_TO_EDITOR = "net.sourceforge.phpdt.ui.browsing.linktoeditor"; //$NON-NLS-1$
@@ -309,7 +309,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>String</code>.
    * </p>
-   * 
+   *
    * @see #SRCBIN_FOLDERS_IN_NEWPROJ
    */
   public static final String SRCBIN_SRCNAME = "net.sourceforge.phpdt.ui.wizards.srcBinFoldersSrcName"; //$NON-NLS-1$
@@ -320,7 +320,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>String</code>.
    * </p>
-   * 
+   *
    * @see #SRCBIN_FOLDERS_IN_NEWPROJ
    */
   public static final String SRCBIN_BINNAME = "net.sourceforge.phpdt.ui.wizards.srcBinFoldersBinName"; //$NON-NLS-1$
@@ -337,7 +337,7 @@ public class PreferenceConstants {
    * decodeJRELibraryClasspathEntries(String)</code> to decode the
    * description and the array of classpath entries from an encoded string.
    * </p>
-   * 
+   *
    * @see #NEWPROJECT_JRELIBRARY_INDEX
    * @see #encodeJRELibrary(String, IClasspathEntry[])
    * @see #decodeJRELibraryDescription(String)
@@ -350,7 +350,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Int</code>: an index into the list of possible JRE libraries.
    * </p>
-   * 
+   *
    * @see #NEWPROJECT_JRELIBRARY_LIST
    */
   public static final String NEWPROJECT_JRELIBRARY_INDEX = "net.sourceforge.phpdt.ui.wizards.jre.index"; //$NON-NLS-1$
@@ -363,7 +363,7 @@ public class PreferenceConstants {
    * OPEN_TYPE_HIERARCHY_IN_PERSPECTIVE</code> or <code>
    * OPEN_TYPE_HIERARCHY_IN_VIEW_PART</code>.
    * </p>
-   * 
+   *
    * @see #OPEN_TYPE_HIERARCHY_IN_PERSPECTIVE
    * @see #OPEN_TYPE_HIERARCHY_IN_VIEW_PART
    */
@@ -371,14 +371,14 @@ public class PreferenceConstants {
 
   /**
    * A string value used by the named preference <code>OPEN_TYPE_HIERARCHY</code>.
-   * 
+   *
    * @see #OPEN_TYPE_HIERARCHY
    */
   public static final String OPEN_TYPE_HIERARCHY_IN_PERSPECTIVE = "perspective"; //$NON-NLS-1$
 
   /**
    * A string value used by the named preference <code>OPEN_TYPE_HIERARCHY</code>.
-   * 
+   *
    * @see #OPEN_TYPE_HIERARCHY
    */
   public static final String OPEN_TYPE_HIERARCHY_IN_VIEW_PART = "viewPart"; //$NON-NLS-1$
@@ -390,7 +390,7 @@ public class PreferenceConstants {
    * DOUBLE_CLICK_GOES_INTO</code> or <code>
    * DOUBLE_CLICK_EXPANDS</code>.
    * </p>
-   * 
+   *
    * @see #DOUBLE_CLICK_EXPANDS
    * @see #DOUBLE_CLICK_GOES_INTO
    */
@@ -398,14 +398,14 @@ public class PreferenceConstants {
 
   /**
    * A string value used by the named preference <code>DOUBLE_CLICK</code>.
-   * 
+   *
    * @see #DOUBLE_CLICK
    */
   public static final String DOUBLE_CLICK_GOES_INTO = "packageview.gointo"; //$NON-NLS-1$
 
   /**
    * A string value used by the named preference <code>DOUBLE_CLICK</code>.
-   * 
+   *
    * @see #DOUBLE_CLICK
    */
   public static final String DOUBLE_CLICK_EXPANDS = "packageview.doubleclick.expands"; //$NON-NLS-1$
@@ -418,7 +418,7 @@ public class PreferenceConstants {
    * UPDATE_ON_SAVE</code> or <code>
    * UPDATE_WHILE_EDITING</code>.
    * </p>
-   * 
+   *
    * @see #UPDATE_ON_SAVE
    * @see #UPDATE_WHILE_EDITING
    */
@@ -426,14 +426,14 @@ public class PreferenceConstants {
 
   /**
    * A string value used by the named preference <code>UPDATE_JAVA_VIEWS</code>
-   * 
+   *
    * @see #UPDATE_JAVA_VIEWS
    */
   public static final String UPDATE_ON_SAVE = "JavaUI.update.onSave"; //$NON-NLS-1$
 
   /**
    * A string value used by the named preference <code>UPDATE_JAVA_VIEWS</code>
-   * 
+   *
    * @see #UPDATE_JAVA_VIEWS
    */
   public static final String UPDATE_WHILE_EDITING = "JavaUI.update.whileEditing"; //$NON-NLS-1$
@@ -448,7 +448,7 @@ public class PreferenceConstants {
 
   /**
    * A named preference that defines whether hint to make hover sticky should be shown.
-   * 
+   *
    * @see JavaUI
    * @since 3.0
    */
@@ -456,7 +456,7 @@ public class PreferenceConstants {
 
   /**
    * A named preference that defines the key for the hover modifiers.
-   * 
+   *
    * @see JavaUI
    * @since 2.1
    */
@@ -464,21 +464,21 @@ public class PreferenceConstants {
 
   /**
    * The id of the best match hover contributed for extension point <code>javaEditorTextHovers</code>.
-   * 
+   *
    * @since 2.1
    */
   public static String ID_BESTMATCH_HOVER = "net.sourceforge.phpdt.ui.BestMatchHover"; //$NON-NLS-1$
 
   /**
    * The id of the source code hover contributed for extension point <code>javaEditorTextHovers</code>.
-   * 
+   *
    * @since 2.1
    */
   public static String ID_SOURCE_HOVER = "net.sourceforge.phpdt.ui.JavaSourceHover"; //$NON-NLS-1$
 
   /**
    * The id of the problem hover contributed for extension point <code>javaEditorTextHovers</code>.
-   * 
+   *
    * @since 2.1
    */
   public static String ID_PROBLEM_HOVER = "net.sourceforge.phpdt.ui.ProblemHover"; //$NON-NLS-1$
@@ -496,7 +496,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>String</code>. A RGB color value encoded as a string using class <code>PreferenceConverter</code>
    * </p>
-   * 
+   *
    * @see org.eclipse.jface.resource.StringConverter
    * @see org.eclipse.jface.preference.PreferenceConverter
    */
@@ -515,7 +515,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>String</code>. A RGB color value encoded as a string using class <code>PreferenceConverter</code>
    * </p>
-   * 
+   *
    * @see org.eclipse.jface.resource.StringConverter
    * @see org.eclipse.jface.preference.PreferenceConverter
    */
@@ -534,7 +534,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>String</code>. A RGB color value encoded as a string using class <code>PreferenceConverter</code>
    * </p>
-   * 
+   *
    * @see org.eclipse.jface.resource.StringConverter
    * @see org.eclipse.jface.preference.PreferenceConverter
    */
@@ -550,7 +550,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>String</code>. A RGB color value encoded as a string using class <code>PreferenceConverter</code>
    * </p>
-   * 
+   *
    * @see org.eclipse.jface.resource.StringConverter
    * @see org.eclipse.jface.preference.PreferenceConverter
    */
@@ -581,7 +581,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 2.1
    */
   public final static String EDITOR_SYNC_OUTLINE_ON_CURSOR_MOVE = "JavaEditor.SyncOutlineOnCursorMove"; //$NON-NLS-1$
@@ -606,7 +606,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>String</code>. A RGB color value encoded as a string using class <code>PreferenceConverter</code>
    * </p>
-   * 
+   *
    * @see #EDITOR_PROBLEM_INDICATION
    * @see org.eclipse.jface.resource.StringConverter
    * @see org.eclipse.jface.preference.PreferenceConverter
@@ -625,7 +625,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>String</code>. A RGB color value encoded as a string using class <code>PreferenceConverter</code>
    * </p>
-   * 
+   *
    * @see #EDITOR_WARNING_INDICATION
    * @see org.eclipse.jface.resource.StringConverter
    * @see org.eclipse.jface.preference.PreferenceConverter
@@ -644,7 +644,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>String</code>. A RGB color value encoded as a string using class <code>PreferenceConverter</code>
    * </p>
-   * 
+   *
    * @see #EDITOR_TASK_INDICATION
    * @see org.eclipse.jface.resource.StringConverter
    * @see org.eclipse.jface.preference.PreferenceConverter
@@ -656,7 +656,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 2.1
    */
   public final static String EDITOR_BOOKMARK_INDICATION = "bookmarkIndication"; //$NON-NLS-1$
@@ -666,7 +666,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>String</code>. A RGB color value encoded as a string using class <code>PreferenceConverter</code>
    * </p>
-   * 
+   *
    * @see #EDITOR_BOOKMARK_INDICATION
    * @see org.eclipse.jface.resource.StringConverter
    * @see org.eclipse.jface.preference.PreferenceConverter
@@ -679,7 +679,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 2.1
    */
   public final static String EDITOR_SEARCH_RESULT_INDICATION = "searchResultIndication"; //$NON-NLS-1$
@@ -689,7 +689,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>String</code>. A RGB color value encoded as a string using class <code>PreferenceConverter</code>
    * </p>
-   * 
+   *
    * @see #EDITOR_SEARCH_RESULT_INDICATION
    * @see org.eclipse.jface.resource.StringConverter
    * @see org.eclipse.jface.preference.PreferenceConverter
@@ -702,7 +702,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 2.1
    */
   public final static String EDITOR_UNKNOWN_INDICATION = "othersIndication"; //$NON-NLS-1$
@@ -712,7 +712,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>String</code>. A RGB color value encoded as a string using class <code>PreferenceConverter</code>
    * </p>
-   * 
+   *
    * @see #EDITOR_UNKNOWN_INDICATION
    * @see org.eclipse.jface.resource.StringConverter
    * @see org.eclipse.jface.preference.PreferenceConverter
@@ -725,7 +725,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 2.1
    */
   public final static String EDITOR_ERROR_INDICATION_IN_OVERVIEW_RULER = "errorIndicationInOverviewRuler"; //$NON-NLS-1$
@@ -735,7 +735,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 2.1
    */
   public final static String EDITOR_WARNING_INDICATION_IN_OVERVIEW_RULER = "warningIndicationInOverviewRuler"; //$NON-NLS-1$
@@ -745,7 +745,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 2.1
    */
   public final static String EDITOR_TASK_INDICATION_IN_OVERVIEW_RULER = "taskIndicationInOverviewRuler"; //$NON-NLS-1$
@@ -755,7 +755,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 2.1
    */
   public final static String EDITOR_BOOKMARK_INDICATION_IN_OVERVIEW_RULER = "bookmarkIndicationInOverviewRuler"; //$NON-NLS-1$
@@ -765,7 +765,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 2.1
    */
   public final static String EDITOR_SEARCH_RESULT_INDICATION_IN_OVERVIEW_RULER = "searchResultIndicationInOverviewRuler"; //$NON-NLS-1$
@@ -775,7 +775,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 2.1
    */
   public final static String EDITOR_UNKNOWN_INDICATION_IN_OVERVIEW_RULER = "othersIndicationInOverviewRuler"; //$NON-NLS-1$
@@ -801,7 +801,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 2.1
    */
   public final static String EDITOR_CLOSE_BRACKETS_PHP = "closeBracketsPHP"; //$NON-NLS-1$
@@ -811,7 +811,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 2.1
    */
   public final static String EDITOR_WRAP_WORDS = "wrapWords"; //$NON-NLS-1$
@@ -821,7 +821,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 2.1
    */
   public final static String EDITOR_WRAP_STRINGS_DQ = "wrapStringsDQ"; //$NON-NLS-1$
@@ -831,7 +831,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 3.0
    */
   public final static String EDITOR_ESCAPE_STRINGS_DQ = "escapeStringsDQ"; //$NON-NLS-1$
@@ -841,7 +841,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 2.1
    */
   public final static String EDITOR_WRAP_STRINGS_SQ = "wrapStringsDQ"; //$NON-NLS-1$
@@ -851,7 +851,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 3.0
    */
   public final static String EDITOR_ESCAPE_STRINGS_SQ = "escapeStringsSQ"; //$NON-NLS-1$
@@ -861,7 +861,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 3.0
    */
   public final static String CODEASSIST_PREFIX_COMPLETION = "content_assist_prefix_completion"; //$NON-NLS-1$
@@ -871,7 +871,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 2.1
    */
   public final static String EDITOR_CLOSE_BRACES = "closeBraces"; //$NON-NLS-1$
@@ -881,7 +881,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 2.1
    */
   public final static String EDITOR_CLOSE_JAVADOCS = "closeJavaDocs"; //$NON-NLS-1$
@@ -891,7 +891,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 2.1
    */
   public final static String EDITOR_ADD_JAVADOC_TAGS = "addJavaDocTags"; //$NON-NLS-1$
@@ -901,7 +901,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 2.1
    */
   public final static String EDITOR_FORMAT_JAVADOCS = "formatJavaDocs"; //$NON-NLS-1$
@@ -911,7 +911,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 2.1
    */
   public final static String EDITOR_SMART_PASTE = "smartPaste"; //$NON-NLS-1$
@@ -921,7 +921,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 2.1
    */
   public final static String EDITOR_CLOSE_STRINGS_HTML = "closeStringsHTML"; //$NON-NLS-1$
@@ -931,7 +931,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 2.1
    */
   public final static String EDITOR_CLOSE_BRACKETS_HTML = "closeBracketsHTML"; //$NON-NLS-1$
@@ -941,7 +941,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 2.1
    */
   public final static String EDITOR_SMART_HOME_END = AbstractTextEditor.PREFERENCE_NAVIGATION_SMART_HOME_END;
@@ -951,7 +951,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 2.1
    */
   public final static String EDITOR_SUB_WORD_NAVIGATION = "subWordNavigation"; //$NON-NLS-1$
@@ -985,7 +985,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>String</code>. A RGB color value encoded as a string using class <code>PreferenceConverter</code>
    * </p>
-   * 
+   *
    * @see org.eclipse.jface.resource.StringConverter
    * @see org.eclipse.jface.preference.PreferenceConverter
    * @see #EDITOR_LINE_NUMBER_RULER
@@ -997,7 +997,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>String</code>. A RGB color value encoded as a string using class <code>PreferenceConverter</code>
    * </p>
-   * 
+   *
    * @see org.eclipse.jface.resource.StringConverter
    * @see org.eclipse.jface.preference.PreferenceConverter
    */
@@ -1008,7 +1008,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>String</code>. A RGB color value encoded as a string using class <code>PreferenceConverter</code>
    * </p>
-   * 
+   *
    * @see org.eclipse.jface.resource.StringConverter
    * @see org.eclipse.jface.preference.PreferenceConverter
    */
@@ -1027,7 +1027,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>String</code>. A RGB color value encoded as a string using class <code>PreferenceConverter</code>
    * </p>
-   * 
+   *
    * @see org.eclipse.jface.resource.StringConverter
    * @see org.eclipse.jface.preference.PreferenceConverter
    */
@@ -1056,7 +1056,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>String</code>. A RGB color value encoded as a string using class <code>PreferenceConverter</code>
    * </p>
-   * 
+   *
    * @see org.eclipse.jface.resource.StringConverter
    * @see org.eclipse.jface.preference.PreferenceConverter
    */
@@ -1064,7 +1064,7 @@ public class PreferenceConstants {
 
   /**
    * The symbolic font name for the Java editor text font (value <code>"net.sourceforge.phpdt.ui.editors.textfont"</code>).
-   * 
+   *
    * @since 2.1
    */
   public final static String EDITOR_TEXT_FONT = "net.sourceforge.phpdt.ui.editors.textfont"; //$NON-NLS-1$
@@ -1083,7 +1083,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>String</code>. A RGB color value encoded as a string using class <code>PreferenceConverter</code>
    * </p>
-   * 
+   *
    * @see org.eclipse.jface.resource.StringConverter
    * @see org.eclipse.jface.preference.PreferenceConverter
    */
@@ -1103,7 +1103,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>String</code>. A RGB color value encoded as a string using class <code>PreferenceConverter</code>
    * </p>
-   * 
+   *
    * @see org.eclipse.jface.resource.StringConverter
    * @see org.eclipse.jface.preference.PreferenceConverter
    * @since 3.0
@@ -1115,7 +1115,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 3.0
    */
   public final static String EDITOR_PHP_OPERATOR_BOLD = IPreferenceConstants.PHP_OPERATOR + EDITOR_BOLD_SUFFIX;
@@ -1125,7 +1125,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 3.0
    */
   public final static String EDITOR_PHP_OPERATOR_ITALIC = IPreferenceConstants.PHP_OPERATOR + EDITOR_ITALIC_SUFFIX;
@@ -1135,7 +1135,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>String</code>. A RGB color value encoded as a string using class <code>PreferenceConverter</code>
    * </p>
-   * 
+   *
    * @see org.eclipse.jface.resource.StringConverter
    * @see org.eclipse.jface.preference.PreferenceConverter
    * @since 3.0
@@ -1147,7 +1147,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 3.0
    */
   public final static String EDITOR_PHP_BRACE_OPERATOR_BOLD = IPreferenceConstants.PHP_BRACE_OPERATOR + EDITOR_BOLD_SUFFIX;
@@ -1157,7 +1157,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 3.0
    */
   public final static String EDITOR_PHP_BRACE_OPERATOR_ITALIC = IPreferenceConstants.PHP_BRACE_OPERATOR + EDITOR_ITALIC_SUFFIX;
@@ -1167,7 +1167,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>String</code>. A RGB color value encoded as a string using class <code>PreferenceConverter</code>
    * </p>
-   * 
+   *
    * @see org.eclipse.jface.resource.StringConverter
    * @see org.eclipse.jface.preference.PreferenceConverter
    * @since 3.0
@@ -1179,7 +1179,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 3.0
    */
   public final static String EDITOR_PHP_KEYWORD_RETURN_BOLD = IPreferenceConstants.PHP_KEYWORD_RETURN + EDITOR_BOLD_SUFFIX;
@@ -1189,7 +1189,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 3.0
    */
   public final static String EDITOR_PHP_KEYWORD_RETURN_ITALIC = IPreferenceConstants.PHP_KEYWORD_RETURN + EDITOR_ITALIC_SUFFIX;
@@ -1199,7 +1199,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>String</code>. A RGB color value encoded as a string using class <code>PreferenceConverter</code>
    * </p>
-   * 
+   *
    * @see org.eclipse.jface.resource.StringConverter
    * @see org.eclipse.jface.preference.PreferenceConverter
    */
@@ -1218,7 +1218,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>String</code>. A RGB color value encoded as a string using class <code>PreferenceConverter</code>
    * </p>
-   * 
+   *
    * @see org.eclipse.jface.resource.StringConverter
    * @see org.eclipse.jface.preference.PreferenceConverter
    */
@@ -1237,7 +1237,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>String</code>. A RGB color value encoded as a string using class <code>PreferenceConverter</code>
    * </p>
-   * 
+   *
    * @see org.eclipse.jface.resource.StringConverter
    * @see org.eclipse.jface.preference.PreferenceConverter
    */
@@ -1256,7 +1256,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>String</code>. A RGB color value encoded as a string using class <code>PreferenceConverter</code>
    * </p>
-   * 
+   *
    * @see org.eclipse.jface.resource.StringConverter
    * @see org.eclipse.jface.preference.PreferenceConverter
    */
@@ -1275,7 +1275,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>String</code>. A RGB color value encoded as a string using class <code>PreferenceConverter</code>
    * </p>
-   * 
+   *
    * @see org.eclipse.jface.resource.StringConverter
    * @see org.eclipse.jface.preference.PreferenceConverter
    */
@@ -1293,7 +1293,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>String</code>. A RGB color value encoded as a string using class <code>PreferenceConverter</code>
    * </p>
-   * 
+   *
    * @see org.eclipse.jface.resource.StringConverter
    * @see org.eclipse.jface.preference.PreferenceConverter
    */
@@ -1312,7 +1312,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>String</code>. A RGB color value encoded as a string using class <code>PreferenceConverter</code>
    * </p>
-   * 
+   *
    * @see org.eclipse.jface.resource.StringConverter
    * @see org.eclipse.jface.preference.PreferenceConverter
    */
@@ -1331,7 +1331,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>String</code>. A RGB color value encoded as a string using class <code>PreferenceConverter</code>
    * </p>
-   * 
+   *
    * @see org.eclipse.jface.resource.StringConverter
    * @see org.eclipse.jface.preference.PreferenceConverter
    */
@@ -1360,7 +1360,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>String</code>. A RGB color value encoded as a string using class <code>PreferenceConverter</code>
    * </p>
-   * 
+   *
    * @see org.eclipse.jface.resource.StringConverter
    * @see org.eclipse.jface.preference.PreferenceConverter
    */
@@ -1379,7 +1379,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>String</code>. A RGB color value encoded as a string using class <code>PreferenceConverter</code>
    * </p>
-   * 
+   *
    * @see org.eclipse.jface.resource.StringConverter
    * @see org.eclipse.jface.preference.PreferenceConverter
    * @since 2.1
@@ -1391,7 +1391,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 2.1
    */
   public final static String EDITOR_TASK_TAG_BOLD = IPreferenceConstants.TASK_TAG + EDITOR_BOLD_SUFFIX;
@@ -1401,7 +1401,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>String</code>. A RGB color value encoded as a string using class <code>PreferenceConverter</code>
    * </p>
-   * 
+   *
    * @see org.eclipse.jface.resource.StringConverter
    * @see org.eclipse.jface.preference.PreferenceConverter
    */
@@ -1420,7 +1420,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>String</code>. A RGB color value encoded as a string using class <code>PreferenceConverter</code>
    * </p>
-   * 
+   *
    * @see org.eclipse.jface.resource.StringConverter
    * @see org.eclipse.jface.preference.PreferenceConverter
    */
@@ -1439,7 +1439,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>String</code>. A RGB color value encoded as a string using class <code>PreferenceConverter</code>
    * </p>
-   * 
+   *
    * @see org.eclipse.jface.resource.StringConverter
    * @see org.eclipse.jface.preference.PreferenceConverter
    */
@@ -1458,7 +1458,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>String</code>. A RGB color value encoded as a string using class <code>PreferenceConverter</code>
    * </p>
-   * 
+   *
    * @see org.eclipse.jface.resource.StringConverter
    * @see org.eclipse.jface.preference.PreferenceConverter
    */
@@ -1477,7 +1477,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>String</code>. A RGB color value encoded as a string using class <code>PreferenceConverter</code>
    * </p>
-   * 
+   *
    * @see org.eclipse.jface.resource.StringConverter
    * @see org.eclipse.jface.preference.PreferenceConverter
    * @since 2.1
@@ -1499,7 +1499,7 @@ public class PreferenceConstants {
    * EDITOR_NO_HOVER_CONFIGURED_ID</code> or
    * <code>EDITOR_DEFAULT_HOVER_CONFIGURED_ID</code> or the hover id of a hover contributed as <code>phpEditorTextHovers</code>.
    * </p>
-   * 
+   *
    * @see #EDITOR_NO_HOVER_CONFIGURED_ID
    * @see #EDITOR_DEFAULT_HOVER_CONFIGURED_ID
    * @see JavaUI
@@ -1514,7 +1514,7 @@ public class PreferenceConstants {
    * EDITOR_NO_HOVER_CONFIGURED_ID</code> or
    * <code>EDITOR_DEFAULT_HOVER_CONFIGURED_ID</code> or the hover id of a hover contributed as <code>phpEditorTextHovers</code>.
    * </p>
-   * 
+   *
    * @see #EDITOR_NO_HOVER_CONFIGURED_ID
    * @see #EDITOR_DEFAULT_HOVER_CONFIGURED_ID
    * @see JavaUI
@@ -1529,7 +1529,7 @@ public class PreferenceConstants {
    * EDITOR_NO_HOVER_CONFIGURED_ID</code> or
    * <code>EDITOR_DEFAULT_HOVER_CONFIGURED_ID</code> or the hover id of a hover contributed as <code>phpEditorTextHovers</code>.
    * </p>
-   * 
+   *
    * @see #EDITOR_NO_HOVER_CONFIGURED_ID
    * @see #EDITOR_DEFAULT_HOVER_CONFIGURED_ID
    * @see JavaUI ID_*_HOVER
@@ -1544,7 +1544,7 @@ public class PreferenceConstants {
    * EDITOR_NO_HOVER_CONFIGURED_ID</code> or
    * <code>EDITOR_DEFAULT_HOVER_CONFIGURED_ID</code> or the hover id of a hover contributed as <code>phpEditorTextHovers</code>.
    * </p>
-   * 
+   *
    * @see #EDITOR_NO_HOVER_CONFIGURED_ID
    * @see #EDITOR_DEFAULT_HOVER_CONFIGURED_ID
    * @see JavaUI ID_*_HOVER
@@ -1559,7 +1559,7 @@ public class PreferenceConstants {
    * EDITOR_NO_HOVER_CONFIGURED_ID</code> or
    * <code>EDITOR_DEFAULT_HOVER_CONFIGURED_ID</code> or the hover id of a hover contributed as <code>phpEditorTextHovers</code>.
    * </p>
-   * 
+   *
    * @see #EDITOR_NO_HOVER_CONFIGURED_ID
    * @see #EDITOR_DEFAULT_HOVER_CONFIGURED_ID
    * @see JavaUI ID_*_HOVER
@@ -1574,7 +1574,7 @@ public class PreferenceConstants {
    * EDITOR_NO_HOVER_CONFIGURED_ID</code> or
    * <code>EDITOR_DEFAULT_HOVER_CONFIGURED_ID</code> or the hover id of a hover contributed as <code>phpEditorTextHovers</code>.
    * </p>
-   * 
+   *
    * @see #EDITOR_NO_HOVER_CONFIGURED_ID
    * @see #EDITOR_DEFAULT_HOVER_CONFIGURED_ID
    * @see JavaUI ID_*_HOVER
@@ -1589,7 +1589,7 @@ public class PreferenceConstants {
    * EDITOR_NO_HOVER_CONFIGURED_ID</code>,
    * <code>EDITOR_DEFAULT_HOVER_CONFIGURED_ID</code> or the hover id of a hover contributed as <code>phpEditorTextHovers</code>.
    * </p>
-   * 
+   *
    * @see #EDITOR_NO_HOVER_CONFIGURED_ID
    * @see #EDITOR_DEFAULT_HOVER_CONFIGURED_ID
    * @see JavaUI ID_*_HOVER
@@ -1600,7 +1600,7 @@ public class PreferenceConstants {
   /**
    * A string value used by the named preferences for hover configuration to descibe that no hover should be shown for the given key
    * modifiers.
-   * 
+   *
    * @since 2.1
    */
   public static final String EDITOR_NO_HOVER_CONFIGURED_ID = "noHoverConfiguredId"; //$NON-NLS-1$
@@ -1608,7 +1608,7 @@ public class PreferenceConstants {
   /**
    * A string value used by the named preferences for hover configuration to descibe that the default hover should be shown for the
    * given key modifiers. The default hover is described by the <code>EDITOR_DEFAULT_HOVER</code> property.
-   * 
+   *
    * @since 2.1
    */
   public static final String EDITOR_DEFAULT_HOVER_CONFIGURED_ID = "defaultHoverConfiguredId"; //$NON-NLS-1$
@@ -1636,7 +1636,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 2.1
    */
   public static final String EDITOR_BROWSER_LIKE_LINKS = "browserLikeLinks"; //$NON-NLS-1$
@@ -1646,7 +1646,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>String</code>.
    * </p>
-   * 
+   *
    * @since 2.1
    */
   public static final String EDITOR_BROWSER_LIKE_LINKS_KEY_MODIFIER = "browserLikeLinksKeyModifier"; //$NON-NLS-1$
@@ -1656,7 +1656,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 3.0
    */
   public static final String EDITOR_MARK_OCCURRENCES = "markOccurrences"; //$NON-NLS-1$
@@ -1666,7 +1666,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 3.0
    */
   public static final String EDITOR_STICKY_OCCURRENCES = "stickyOccurrences"; //$NON-NLS-1$
@@ -1676,7 +1676,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 3.0
    */
   public static final String EDITOR_DISABLE_OVERWRITE_MODE = "disable_overwrite_mode"; //$NON-NLS-1$
@@ -1686,7 +1686,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 3.0
    */
   public static final String EDITOR_SMART_SEMICOLON = "smart_semicolon"; //$NON-NLS-1$
@@ -1695,7 +1695,7 @@ public class PreferenceConstants {
    * A named preference that controls the smart backspace behavior.
    * <p>
    * Value is of type <code>Boolean</code>.
-   * 
+   *
    * @since 3.0
    */
   public static final String EDITOR_SMART_BACKSPACE = "smart_backspace"; //$NON-NLS-1$
@@ -1705,7 +1705,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 3.0
    */
   public static final String EDITOR_SMART_OPENING_BRACE = "smart_opening_brace"; //$NON-NLS-1$
@@ -1714,19 +1714,19 @@ public class PreferenceConstants {
    * A named preference that controls the smart tab behaviour.
    * <p>
    * Value is of type <code>Boolean</code>.
-   * 
+   *
    * @since 3.0
    */
   public static final String EDITOR_SMART_TAB = "smart_tab"; //$NON-NLS-1$
 
   public static final String EDITOR_P_RTRIM_ON_SAVE = "editor_p_trim_on_save"; //$NON-NLS-1$
-  
+
   /**
    * A named preference that controls whether Java comments should be spell-checked.
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 3.0
    */
   public final static String SPELLING_CHECK_SPELLING = ISpellCheckPreferenceKeys.SPELLING_CHECK_SPELLING;
@@ -1736,7 +1736,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 3.0
    */
   public final static String SPELLING_IGNORE_DIGITS = ISpellCheckPreferenceKeys.SPELLING_IGNORE_DIGITS;
@@ -1746,7 +1746,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 3.0
    */
   public final static String SPELLING_IGNORE_MIXED = ISpellCheckPreferenceKeys.SPELLING_IGNORE_MIXED;
@@ -1756,7 +1756,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 3.0
    */
   public final static String SPELLING_IGNORE_SENTENCE = ISpellCheckPreferenceKeys.SPELLING_IGNORE_SENTENCE;
@@ -1766,7 +1766,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 3.0
    */
   public final static String SPELLING_IGNORE_UPPER = ISpellCheckPreferenceKeys.SPELLING_IGNORE_UPPER;
@@ -1776,7 +1776,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 3.0
    */
   public final static String SPELLING_IGNORE_URLS = ISpellCheckPreferenceKeys.SPELLING_IGNORE_URLS;
@@ -1786,7 +1786,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>String</code>.
    * </p>
-   * 
+   *
    * @since 3.0
    */
   public final static String SPELLING_LOCALE = ISpellCheckPreferenceKeys.SPELLING_LOCALE;
@@ -1796,7 +1796,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Integer</code>.
    * </p>
-   * 
+   *
    * @since 3.0
    */
   public final static String SPELLING_PROPOSAL_THRESHOLD = ISpellCheckPreferenceKeys.SPELLING_PROPOSAL_THRESHOLD;
@@ -1806,7 +1806,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Integer</code>.
    * </p>
-   * 
+   *
    * @since 3.0
    */
   public final static String SPELLING_USER_DICTIONARY = ISpellCheckPreferenceKeys.SPELLING_USER_DICTIONARY;
@@ -1816,7 +1816,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 3.0
    */
   public final static String SPELLING_ENABLE_CONTENTASSIST = ISpellCheckPreferenceKeys.SPELLING_ENABLE_CONTENTASSIST;
@@ -1826,7 +1826,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 3.0
    */
   public final static String FORMATTER_COMMENT_FORMATSOURCE = "comment_format_source_code"; //$NON-NLS-1$
@@ -1836,7 +1836,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 3.0
    */
   public final static String FORMATTER_COMMENT_INDENTPARAMETERDESCRIPTION = "comment_indent_parameter_description"; //$NON-NLS-1$
@@ -1846,7 +1846,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 3.0
    */
   public final static String FORMATTER_COMMENT_FORMATHEADER = "comment_format_header"; //$NON-NLS-1$
@@ -1856,7 +1856,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 3.0
    */
   public final static String FORMATTER_COMMENT_INDENTROOTTAGS = "comment_indent_root_tags"; //$NON-NLS-1$
@@ -1866,7 +1866,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 3.0
    */
   public final static String FORMATTER_COMMENT_FORMAT = "comment_format_comments"; //$NON-NLS-1$
@@ -1876,7 +1876,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 3.0
    */
   public final static String FORMATTER_COMMENT_NEWLINEFORPARAMETER = "comment_new_line_for_parameter"; //$NON-NLS-1$
@@ -1886,7 +1886,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 3.0
    */
   public final static String FORMATTER_COMMENT_SEPARATEROOTTAGS = "comment_separate_root_tags"; //$NON-NLS-1$
@@ -1896,7 +1896,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 3.0
    */
   public final static String FORMATTER_COMMENT_CLEARBLANKLINES = "comment_clear_blank_lines"; //$NON-NLS-1$
@@ -1906,7 +1906,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Integer</code>. The value must be at least 4 for reasonable formatting.
    * </p>
-   * 
+   *
    * @since 3.0
    */
   public final static String FORMATTER_COMMENT_LINELENGTH = "comment_line_length"; //$NON-NLS-1$
@@ -1916,7 +1916,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 3.0
    */
   public final static String FORMATTER_COMMENT_FORMATHTML = "comment_format_html"; //$NON-NLS-1$
@@ -1940,7 +1940,7 @@ public class PreferenceConstants {
   /**
    * A named preference that controls if code assist contains only visible proposals.
    * <p>
-   * Value is of type <code>Boolean</code>. if <code>true<code> code assist only contains visible members. If 
+   * Value is of type <code>Boolean</code>. if <code>true<code> code assist only contains visible members. If
    * <code>false</code> all members are included.
    * </p>
    */
@@ -1951,7 +1951,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 2.1
    */
   public final static String CODEASSIST_AUTOINSERT = "content_assist_autoinsert"; //$NON-NLS-1$
@@ -1961,7 +1961,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 2.1
    */
   public final static String CODEASSIST_ADDIMPORT = "content_assist_add_import"; //$NON-NLS-1$
@@ -1972,10 +1972,10 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 2.1
    */
-  public final static String CODEASSIST_INSERT_COMPLETION = "content_assist_insert_completion"; //$NON-NLS-1$  
+  public final static String CODEASSIST_INSERT_COMPLETION = "content_assist_insert_completion"; //$NON-NLS-1$
 
   /**
    * A named preference that controls whether code assist proposals filtering is case sensitive or not.
@@ -2009,7 +2009,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 2.1
    */
   public final static String CODEASSIST_GUESS_METHOD_ARGUMENTS = "content_assist_guess_method_arguments"; //$NON-NLS-1$
@@ -2043,7 +2043,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>String</code>. A RGB color value encoded as a string using class <code>PreferenceConverter</code>
    * </p>
-   * 
+   *
    * @see org.eclipse.jface.resource.StringConverter
    * @see org.eclipse.jface.preference.PreferenceConverter
    */
@@ -2054,7 +2054,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>String</code>. A RGB color value encoded as a string using class <code>PreferenceConverter</code>
    * </p>
-   * 
+   *
    * @see org.eclipse.jface.resource.StringConverter
    * @see org.eclipse.jface.preference.PreferenceConverter
    */
@@ -2065,7 +2065,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>String</code>. A RGB color value encoded as a string using class <code>PreferenceConverter</code>
    * </p>
-   * 
+   *
    * @see org.eclipse.jface.resource.StringConverter
    * @see org.eclipse.jface.preference.PreferenceConverter
    */
@@ -2076,7 +2076,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>String</code>. A RGB color value encoded as a string using class <code>PreferenceConverter</code>
    * </p>
-   * 
+   *
    * @see org.eclipse.jface.resource.StringConverter
    * @see org.eclipse.jface.preference.PreferenceConverter
    */
@@ -2087,7 +2087,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>String</code>. A RGB color value encoded as a string using class <code>PreferenceConverter</code>
    * </p>
-   * 
+   *
    * @see org.eclipse.jface.resource.StringConverter
    * @see org.eclipse.jface.preference.PreferenceConverter
    * @since 2.1
@@ -2099,7 +2099,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>String</code>. A RGB color value encoded as a string using class <code>PreferenceConverter</code>
    * </p>
-   * 
+   *
    * @see org.eclipse.jface.resource.StringConverter
    * @see org.eclipse.jface.preference.PreferenceConverter
    * @since 2.1
@@ -2114,7 +2114,7 @@ public class PreferenceConstants {
    * <code>REFACTOR_INFO_SEVERITY</code>,
    * <code>REFACTOR_OK_SEVERITY</code>.
    * </p>
-   * 
+   *
    * @see #REFACTOR_FATAL_SEVERITY
    * @see #REFACTOR_ERROR_SEVERITY
    * @see #REFACTOR_WARNING_SEVERITY
@@ -2125,35 +2125,35 @@ public class PreferenceConstants {
 
   /**
    * A string value used by the named preference <code>REFACTOR_ERROR_PAGE_SEVERITY_THRESHOLD</code>.
-   * 
+   *
    * @see #REFACTOR_ERROR_PAGE_SEVERITY_THRESHOLD
    */
   public static final String REFACTOR_FATAL_SEVERITY = "4"; //$NON-NLS-1$
 
   /**
    * A string value used by the named preference <code>REFACTOR_ERROR_PAGE_SEVERITY_THRESHOLD</code>.
-   * 
+   *
    * @see #REFACTOR_ERROR_PAGE_SEVERITY_THRESHOLD
    */
   public static final String REFACTOR_ERROR_SEVERITY = "3"; //$NON-NLS-1$
 
   /**
    * A string value used by the named preference <code>REFACTOR_ERROR_PAGE_SEVERITY_THRESHOLD</code>.
-   * 
+   *
    * @see #REFACTOR_ERROR_PAGE_SEVERITY_THRESHOLD
    */
   public static final String REFACTOR_WARNING_SEVERITY = "2"; //$NON-NLS-1$
 
   /**
    * A string value used by the named preference <code>REFACTOR_ERROR_PAGE_SEVERITY_THRESHOLD</code>.
-   * 
+   *
    * @see #REFACTOR_ERROR_PAGE_SEVERITY_THRESHOLD
    */
   public static final String REFACTOR_INFO_SEVERITY = "1"; //$NON-NLS-1$
 
   /**
    * A string value used by the named preference <code>REFACTOR_ERROR_PAGE_SEVERITY_THRESHOLD</code>.
-   * 
+   *
    * @see #REFACTOR_ERROR_PAGE_SEVERITY_THRESHOLD
    */
   public static final String REFACTOR_OK_SEVERITY = "0"; //$NON-NLS-1$
@@ -2171,7 +2171,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @see #LINK_PACKAGES_TO_EDITOR
    */
   public static final String BROWSING_LINK_VIEW_TO_EDITOR = "net.sourceforge.phpdt.ui.browsing.linktoeditor"; //$NON-NLS-1$
@@ -2190,7 +2190,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 2.1
    */
   public static final String TEMPLATES_USE_CODEFORMATTER = "net.sourceforge.phpdt.ui.template.format"; //$NON-NLS-1$
@@ -2201,7 +2201,7 @@ public class PreferenceConstants {
    * Value is of type <code>Boolean</code>. If <code>true<code> the annotation ruler column
    * uses a roll over to display multiple annotations
    * </p>
-   * 
+   *
    * @since 3.0
    */
   public static final String EDITOR_ANNOTATION_ROLL_OVER = "editor_annotation_roll_over"; //$NON-NLS-1$
@@ -2212,7 +2212,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>String</code>.
    * </p>
-   * 
+   *
    * @see #EDITOR_BROWSER_LIKE_LINKS_KEY_MODIFIER
    * @since 2.1.1
    */
@@ -2221,7 +2221,7 @@ public class PreferenceConstants {
   /**
    * A named preference that defines the key for the hover modifier state masks. The value is only used if the value of
    * <code>EDITOR_TEXT_HOVER_MODIFIERS</code> cannot be resolved to valid SWT modifier bits.
-   * 
+   *
    * @see JavaUI
    * @see #EDITOR_TEXT_HOVER_MODIFIERS
    * @since 2.1.1
@@ -2233,7 +2233,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 3.0
    */
   public static final String EDITOR_FOLDING_ENABLED = "editor_folding_enabled"; //$NON-NLS-1$
@@ -2243,7 +2243,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>String</code>.
    * </p>
-   * 
+   *
    * @since 3.0
    */
   public static final String EDITOR_FOLDING_PROVIDER = "editor_folding_provider"; //$NON-NLS-1$
@@ -2253,7 +2253,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 3.0
    */
   public static final String EDITOR_FOLDING_JAVADOC = "editor_folding_default_javadoc"; //$NON-NLS-1$
@@ -2263,7 +2263,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 3.0
    */
   public static final String EDITOR_FOLDING_INNERTYPES = "editor_folding_default_innertypes"; //$NON-NLS-1$
@@ -2273,7 +2273,7 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 3.0
    */
   public static final String EDITOR_FOLDING_METHODS = "editor_folding_default_methods"; //$NON-NLS-1$
@@ -2283,10 +2283,19 @@ public class PreferenceConstants {
    * <p>
    * Value is of type <code>Boolean</code>.
    * </p>
-   * 
+   *
    * @since 3.0
    */
-  public static final String EDITOR_FOLDING_IMPORTS = "editor_folding_default_imports"; //$NON-NLS-1$
+//  public static final String EDITOR_FOLDING_IMPORTS = "editor_folding_default_imports"; //$NON-NLS-1$
+  /**
+        * A named preference that stores the value for header comment folding for the default folding provider.
+        * <p>
+        * Value is of type <code>Boolean</code>.
+        * </p>
+        *
+        * @since 3.1
+        */
+       public static final String EDITOR_FOLDING_HEADERS= "editor_folding_default_headers"; //$NON-NLS-1$
 
   public static void initializeDefaultValues(IPreferenceStore store) {
     store.setDefault(PreferenceConstants.EDITOR_SHOW_SEGMENTS, false);
@@ -2331,7 +2340,7 @@ public class PreferenceConstants {
     store.setDefault(PreferenceConstants.CODEGEN_USE_GETTERSETTER_SUFFIX, false);
     store.setDefault(PreferenceConstants.CODEGEN_GETTERSETTER_PREFIX, "fg, f, _$, _, m_"); //$NON-NLS-1$
     store.setDefault(PreferenceConstants.CODEGEN_GETTERSETTER_SUFFIX, "_"); //$NON-NLS-1$
-    
+
     store.setDefault(PreferenceConstants.CODEGEN_KEYWORD_THIS, false);
        store.setDefault(PreferenceConstants.CODEGEN_IS_FOR_GETTERS, true);
        store.setDefault(PreferenceConstants.CODEGEN_EXCEPTION_VAR_NAME, "e"); //$NON-NLS-1$
@@ -2424,7 +2433,7 @@ public class PreferenceConstants {
 
     PreferenceConverter.setDefault(store, PreferenceConstants.EDITOR_PHP_VARIABLE_DOLLAR_COLOR, new RGB(127, 159, 191));
     store.setDefault(PreferenceConstants.EDITOR_PHP_VARIABLE_DOLLAR_BOLD, false);
-    
+
     PreferenceConverter.setDefault(store, PreferenceConstants.EDITOR_PHP_CONSTANT_COLOR, new RGB(127, 0, 85));
     store.setDefault(PreferenceConstants.EDITOR_PHP_CONSTANT_BOLD, false);
 
@@ -2436,7 +2445,7 @@ public class PreferenceConstants {
 
     PreferenceConverter.setDefault(store, PreferenceConstants.EDITOR_STRING_COLOR_SQ, PHPColorProvider.STRING_SQ);
     store.setDefault(PreferenceConstants.EDITOR_STRING_BOLD_SQ, true);
-    
+
     PreferenceConverter.setDefault(store, PreferenceConstants.EDITOR_JAVA_DEFAULT_COLOR, new RGB(0, 0, 0));
     store.setDefault(PreferenceConstants.EDITOR_JAVA_DEFAULT_BOLD, false);
 
@@ -2532,7 +2541,8 @@ public class PreferenceConstants {
     store.setDefault(PreferenceConstants.EDITOR_FOLDING_JAVADOC, true);
     store.setDefault(PreferenceConstants.EDITOR_FOLDING_INNERTYPES, true);
     store.setDefault(PreferenceConstants.EDITOR_FOLDING_METHODS, false);
-    store.setDefault(PreferenceConstants.EDITOR_FOLDING_IMPORTS, false);
+//    store.setDefault(PreferenceConstants.EDITOR_FOLDING_IMPORTS, false);
+    store.setDefault(PreferenceConstants.EDITOR_FOLDING_HEADERS, true);
 
     store.setDefault(PreferenceConstants.EDITOR_SMART_BACKSPACE, true);
     store.setDefault(PreferenceConstants.EDITOR_P_RTRIM_ON_SAVE, false);
@@ -2542,7 +2552,7 @@ public class PreferenceConstants {
 
   /**
    * Returns the JDT-UI preference store.
-   * 
+   *
    * @return the JDT-UI preference store
    */
   public static IPreferenceStore getPreferenceStore() {
@@ -2561,7 +2571,7 @@ public class PreferenceConstants {
   //   public static String encodeJRELibrary(String description, IClasspathEntry[] entries) {
   //           return NewJavaProjectPreferencePage.encodeJRELibrary(description, entries);
   //   }
-  //   
+  //
   //   /**
   //    * Decodes an encoded JRE library and returns its description string.
   //    *
@@ -2572,7 +2582,7 @@ public class PreferenceConstants {
   //   public static String decodeJRELibraryDescription(String encodedLibrary) {
   //           return NewJavaProjectPreferencePage.decodeJRELibraryDescription(encodedLibrary);
   //   }
-  //   
+  //
   //   /**
   //    * Decodes an encoded JRE library and returns its classpath entries.
   //    *
@@ -2583,7 +2593,7 @@ public class PreferenceConstants {
   //   public static IClasspathEntry[] decodeJRELibraryClasspathEntries(String encodedLibrary) {
   //           return NewJavaProjectPreferencePage.decodeJRELibraryClasspathEntries(encodedLibrary);
   //   }
-  //   
+  //
   //   /**
   //    * Returns the current configuration for the JRE to be used as default in new Java projects.
   //    * This is a convenience method to access the named preference <code>NEWPROJECT_JRELIBRARY_LIST