fix #774 infinite loop in net.sourceforge.phpeclipse.builder.IdentifierIndexManager...
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / ui / JavaElementSorter.java
index 95bcc5e..dd2e04f 100644 (file)
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * 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
  * which accompanies this distribution, and is available at
@@ -15,11 +15,15 @@ import java.text.Collator;
 import net.sourceforge.phpdt.core.Flags;
 import net.sourceforge.phpdt.core.IField;
 import net.sourceforge.phpdt.core.IJavaElement;
+import net.sourceforge.phpdt.core.IMember;
 import net.sourceforge.phpdt.core.IMethod;
 import net.sourceforge.phpdt.core.IPackageFragment;
 import net.sourceforge.phpdt.core.IPackageFragmentRoot;
+import net.sourceforge.phpdt.core.IType;
 import net.sourceforge.phpdt.core.JavaModelException;
 import net.sourceforge.phpdt.core.Signature;
+import net.sourceforge.phpdt.internal.corext.util.JavaModelUtil;
+import net.sourceforge.phpdt.internal.corext.util.JdtFlags;
 import net.sourceforge.phpdt.internal.ui.preferences.MembersOrderPreferenceCache;
 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
 
@@ -28,6 +32,7 @@ import org.eclipse.core.resources.IFile;
 import org.eclipse.core.resources.IProject;
 import org.eclipse.core.resources.IStorage;
 import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IPath;
 import org.eclipse.jface.viewers.ContentViewer;
 import org.eclipse.jface.viewers.IBaseLabelProvider;
 import org.eclipse.jface.viewers.ILabelProvider;
@@ -35,9 +40,8 @@ import org.eclipse.jface.viewers.Viewer;
 import org.eclipse.jface.viewers.ViewerSorter;
 import org.eclipse.ui.model.IWorkbenchAdapter;
 
-
 /**
- * Sorter for Java elements. Ordered by element category, then by element name. 
+ * Sorter for Java elements. Ordered by element category, then by element name.
  * Package fragment roots are sorted as ordered on the classpath.
  * 
  * <p>
@@ -47,37 +51,53 @@ import org.eclipse.ui.model.IWorkbenchAdapter;
  * @since 2.0
  */
 public class JavaElementSorter extends ViewerSorter {
-       
-       private static final int PROJECTS= 1;
-       private static final int PACKAGEFRAGMENTROOTS= 2;
-       private static final int PACKAGEFRAGMENT= 3;
-
-       private static final int COMPILATIONUNITS= 4;
-       private static final int CLASSFILES= 5;
-       
-       private static final int RESOURCEFOLDERS= 7;
-       private static final int RESOURCES= 8;
-       private static final int STORAGE= 9;    
-       
-       private static final int PACKAGE_DECL=  10;
-       private static final int IMPORT_CONTAINER= 11;
-       private static final int IMPORT_DECLARATION= 12;
-       
+
+       private static final int PROJECTS = 1;
+
+       private static final int PACKAGEFRAGMENTROOTS = 2;
+
+       private static final int PACKAGEFRAGMENT = 3;
+
+       private static final int COMPILATIONUNITS = 4;
+
+       private static final int CLASSFILES = 5;
+
+       private static final int RESOURCEFOLDERS = 7;
+
+       private static final int RESOURCES = 8;
+
+       private static final int STORAGE = 9;
+
+       private static final int PACKAGE_DECL = 10;
+
+       private static final int IMPORT_CONTAINER = 11;
+
+       private static final int IMPORT_DECLARATION = 12;
+
        // Includes all categories ordered using the OutlineSortOrderPage:
        // types, initializers, methods & fields
-       private static final int MEMBERSOFFSET= 15;
-       
-       private static final int JAVAELEMENTS= 50;
-       private static final int OTHERS= 51;
-       
+       private static final int MEMBERSOFFSET = 15;
+
+       private static final int JAVAELEMENTS = 50;
+
+       private static final int OTHERS = 51;
+
+       private MembersOrderPreferenceCache fMemberOrderCache;
+
+       /**
+        * Constructor.
+        */
        public JavaElementSorter() {
                super(null); // delay initialization of collator
+               fMemberOrderCache = PHPeclipsePlugin.getDefault()
+                               .getMemberOrderPreferenceCache();
        }
-               
+
        /**
-        * @deprecated Bug 22518. Method never used: does not override ViewerSorter#isSorterProperty(Object, String).
-        * Method could be removed, but kept for API compatibility.
-        */     
+        * @deprecated Bug 22518. Method never used: does not override
+        *             ViewerSorter#isSorterProperty(Object, String). Method could
+        *             be removed, but kept for API compatibility.
+        */
        public boolean isSorterProperty(Object element, Object property) {
                return true;
        }
@@ -88,63 +108,64 @@ public class JavaElementSorter extends ViewerSorter {
        public int category(Object element) {
                if (element instanceof IJavaElement) {
                        try {
-                               IJavaElement je= (IJavaElement) element;
+                               IJavaElement je = (IJavaElement) element;
 
                                switch (je.getElementType()) {
-                                       case IJavaElement.METHOD:
-                                               {
-                                                       IMethod method= (IMethod) je;
-                                                       if (method.isConstructor()) {
-                                                               return getMemberCategory(MembersOrderPreferenceCache.CONSTRUCTORS_INDEX);
-                                                       }
-                                                       int flags= method.getFlags();
-                                                       if (Flags.isStatic(flags))
-                                                               return getMemberCategory(MembersOrderPreferenceCache.STATIC_METHODS_INDEX);
-                                                       else
-                                                               return getMemberCategory(MembersOrderPreferenceCache.METHOD_INDEX);
-                                               }
-                                       case IJavaElement.FIELD :
-                                               {
-                                                       int flags= ((IField) je).getFlags();
-                                                       if (Flags.isStatic(flags))
-                                                               return getMemberCategory(MembersOrderPreferenceCache.STATIC_FIELDS_INDEX);
-                                                       else
-                                                               return getMemberCategory(MembersOrderPreferenceCache.FIELDS_INDEX);
-                                               }
-//                                     case IJavaElement.INITIALIZER :
-//                                             {
-//                                                     int flags= ((IInitializer) je).getFlags();
-//                                                     if (Flags.isStatic(flags))
-//                                                             return getMemberCategory(MembersOrderPreferenceCache.STATIC_INIT_INDEX);
-//                                                     else
-//                                                             return getMemberCategory(MembersOrderPreferenceCache.INIT_INDEX);
-//                                             }
-                                       case IJavaElement.TYPE :
-                                               return getMemberCategory(MembersOrderPreferenceCache.TYPE_INDEX);
-                                       case IJavaElement.PACKAGE_DECLARATION :
-                                               return PACKAGE_DECL;
-                                       case IJavaElement.IMPORT_CONTAINER :
-                                               return IMPORT_CONTAINER;
-                                       case IJavaElement.IMPORT_DECLARATION :
-                                               return IMPORT_DECLARATION;
-                                       case IJavaElement.PACKAGE_FRAGMENT :
-                                               IPackageFragment pack= (IPackageFragment) je;
-                                               if (pack.getParent().getResource() instanceof IProject) {
-                                                       return PACKAGEFRAGMENTROOTS;
-                                               }
-                                               return PACKAGEFRAGMENT;
-                                       case IJavaElement.PACKAGE_FRAGMENT_ROOT :
+                               case IJavaElement.METHOD: {
+                                       IMethod method = (IMethod) je;
+                                       if (method.isConstructor()) {
+                                               return getMemberCategory(MembersOrderPreferenceCache.CONSTRUCTORS_INDEX);
+                                       }
+                                       int flags = method.getFlags();
+                                       if (Flags.isStatic(flags))
+                                               return getMemberCategory(MembersOrderPreferenceCache.STATIC_METHODS_INDEX);
+                                       else
+                                               return getMemberCategory(MembersOrderPreferenceCache.METHOD_INDEX);
+                               }
+                               case IJavaElement.FIELD: {
+                                       int flags = ((IField) je).getFlags();
+                                       if (Flags.isStatic(flags))
+                                               return getMemberCategory(MembersOrderPreferenceCache.STATIC_FIELDS_INDEX);
+                                       else
+                                               return getMemberCategory(MembersOrderPreferenceCache.FIELDS_INDEX);
+                               }
+                                       // case IJavaElement.INITIALIZER :
+                                       // {
+                                       // int flags= ((IInitializer) je).getFlags();
+                                       // if (Flags.isStatic(flags))
+                                       // return
+                                       // getMemberCategory(MembersOrderPreferenceCache.STATIC_INIT_INDEX);
+                                       // else
+                                       // return
+                                       // getMemberCategory(MembersOrderPreferenceCache.INIT_INDEX);
+                                       // }
+                               case IJavaElement.TYPE:
+                                       return getMemberCategory(MembersOrderPreferenceCache.TYPE_INDEX);
+                               case IJavaElement.PACKAGE_DECLARATION:
+                                       return PACKAGE_DECL;
+                               case IJavaElement.IMPORT_CONTAINER:
+                                       return IMPORT_CONTAINER;
+                               case IJavaElement.IMPORT_DECLARATION:
+                                       return IMPORT_DECLARATION;
+                               case IJavaElement.PACKAGE_FRAGMENT:
+                                       IPackageFragment pack = (IPackageFragment) je;
+                                       if (pack.getParent().getResource() instanceof IProject) {
                                                return PACKAGEFRAGMENTROOTS;
-                                       case IJavaElement.JAVA_PROJECT :
-                                               return PROJECTS;
-                                       case IJavaElement.CLASS_FILE :
-                                               return CLASSFILES;
-                                       case IJavaElement.COMPILATION_UNIT :
-                                               return COMPILATIONUNITS;
+                                       }
+                                       return PACKAGEFRAGMENT;
+                               case IJavaElement.PACKAGE_FRAGMENT_ROOT:
+                                       return PACKAGEFRAGMENTROOTS;
+                               case IJavaElement.JAVA_PROJECT:
+                                       return PROJECTS;
+                               case IJavaElement.CLASS_FILE:
+                                       return CLASSFILES;
+                               case IJavaElement.COMPILATION_UNIT:
+                                       return COMPILATIONUNITS;
                                }
 
                        } catch (JavaModelException e) {
-                               PHPeclipsePlugin.log(e);
+                               if (!e.isDoesNotExist())
+                                       PHPeclipsePlugin.log(e);
                        }
                        return JAVAELEMENTS;
                } else if (element instanceof IFile) {
@@ -155,64 +176,113 @@ public class JavaElementSorter extends ViewerSorter {
                        return RESOURCEFOLDERS;
                } else if (element instanceof IStorage) {
                        return STORAGE;
-//             } else if (element instanceof ClassPathContainer) {
-//                     return PACKAGEFRAGMENTROOTS;
                }
+               // else if (element instanceof ClassPathContainer) {
+               // return PACKAGEFRAGMENTROOTS;
+               // }
                return OTHERS;
        }
-       
+
        private int getMemberCategory(int kind) {
-               int offset= PHPeclipsePlugin.getDefault().getMemberOrderPreferenceCache().getIndex(kind);
+               int offset = fMemberOrderCache.getCategoryIndex(kind);
                return offset + MEMBERSOFFSET;
-       }               
+       }
 
        /*
         * @see ViewerSorter#compare
         */
        public int compare(Viewer viewer, Object e1, Object e2) {
-               int cat1= category(e1);
-               int cat2= category(e2);
+               int cat1 = category(e1);
+               int cat2 = category(e2);
 
                if (cat1 != cat2)
                        return cat1 - cat2;
-               
+
                if (cat1 == PROJECTS) {
-                       IWorkbenchAdapter a1= (IWorkbenchAdapter)((IAdaptable)e1).getAdapter(IWorkbenchAdapter.class);
-                       IWorkbenchAdapter a2= (IWorkbenchAdapter)((IAdaptable)e2).getAdapter(IWorkbenchAdapter.class);
-                               return getCollator().compare(a1.getLabel(e1), a2.getLabel(e2));
+                       IWorkbenchAdapter a1 = (IWorkbenchAdapter) ((IAdaptable) e1)
+                                       .getAdapter(IWorkbenchAdapter.class);
+                       IWorkbenchAdapter a2 = (IWorkbenchAdapter) ((IAdaptable) e2)
+                                       .getAdapter(IWorkbenchAdapter.class);
+                       return getCollator().compare(a1.getLabel(e1), a2.getLabel(e2));
                }
-                       
-//             if (cat1 == PACKAGEFRAGMENTROOTS) {
-//                     IPackageFragmentRoot root1= getPackageFragmentRoot(e1);
-//                     IPackageFragmentRoot root2= getPackageFragmentRoot(e2);
-//                     if (!root1.getPath().equals(root2.getPath())) {
-//                             int p1= getClassPathIndex(root1);
-//                             int p2= getClassPathIndex(root2);
-//                             if (p1 != p2) {
-//                                     return p1 - p2;
-//                             }
-//                     }
-//             }
-               // non - java resources are sorted using the label from the viewers label provider
-               if (cat1 == PROJECTS || cat1 == RESOURCES || cat1 == RESOURCEFOLDERS || cat1 == STORAGE || cat1 == OTHERS) {
+
+               if (cat1 == PACKAGEFRAGMENTROOTS) {
+                       IPackageFragmentRoot root1 = getPackageFragmentRoot(e1);
+                       IPackageFragmentRoot root2 = getPackageFragmentRoot(e2);
+                       if (root1 == null) {
+                               if (root2 == null) {
+                                       return 0;
+                               } else {
+                                       return 1;
+                               }
+                       } else if (root2 == null) {
+                               return -1;
+                       }
+                       if (!root1.getPath().equals(root2.getPath())) {
+                               int p1 = getClassPathIndex(root1);
+                               int p2 = getClassPathIndex(root2);
+                               if (p1 != p2) {
+                                       return p1 - p2;
+                               }
+                       }
+                       e1 = root1; // normalize classpath container to root
+                       e2 = root2;
+               }
+               // non - java resources are sorted using the label from the viewers
+               // label provider
+               if (cat1 == PROJECTS || cat1 == RESOURCES || cat1 == RESOURCEFOLDERS
+                               || cat1 == STORAGE || cat1 == OTHERS) {
                        return compareWithLabelProvider(viewer, e1, e2);
                }
-               
-               String name1= ((IJavaElement) e1).getElementName();
-               String name2= ((IJavaElement) e2).getElementName();
-               
-               // java element are sorted by name
-               int cmp= getCollator().compare(name1, name2);
+
+               if (e1 instanceof IMember) {
+                       if (fMemberOrderCache.isSortByVisibility()) {
+                               try {
+                                       int flags1 = JdtFlags.getVisibilityCode((IMember) e1);
+                                       int flags2 = JdtFlags.getVisibilityCode((IMember) e2);
+                                       int vis = fMemberOrderCache.getVisibilityIndex(flags1)
+                                                       - fMemberOrderCache.getVisibilityIndex(flags2);
+                                       if (vis != 0) {
+                                               return vis;
+                                       }
+                               } catch (JavaModelException ignore) {
+                               }
+                       }
+               }
+
+               String name1 = ((IJavaElement) e1).getElementName();
+               String name2 = ((IJavaElement) e2).getElementName();
+
+               if (e1 instanceof IType) { // handle anonymous types
+                       if (name1.length() == 0) {
+                               if (name2.length() == 0) {
+                                       try {
+                                               return getCollator().compare(
+                                                               ((IType) e1).getSuperclassName(),
+                                                               ((IType) e2).getSuperclassName());
+                                       } catch (JavaModelException e) {
+                                               return 0;
+                                       }
+                               } else {
+                                       return 1;
+                               }
+                       } else if (name2.length() == 0) {
+                               return -1;
+                       }
+               }
+
+               int cmp = getCollator().compare(name1, name2);
                if (cmp != 0) {
                        return cmp;
                }
-               
+
                if (e1 instanceof IMethod) {
-                       String[] params1= ((IMethod) e1).getParameterTypes();
-                       String[] params2= ((IMethod) e2).getParameterTypes();
-                       int len= Math.min(params1.length, params2.length);
+                       String[] params1 = ((IMethod) e1).getParameterTypes();
+                       String[] params2 = ((IMethod) e2).getParameterTypes();
+                       int len = Math.min(params1.length, params2.length);
                        for (int i = 0; i < len; i++) {
-                               cmp= getCollator().compare(Signature.toString(params1[i]), Signature.toString(params2[i]));
+                               cmp = getCollator().compare(Signature.toString(params1[i]),
+                                               Signature.toString(params2[i]));
                                if (cmp != 0) {
                                        return cmp;
                                }
@@ -222,24 +292,25 @@ public class JavaElementSorter extends ViewerSorter {
                return 0;
        }
 
-//     private IPackageFragmentRoot getPackageFragmentRoot(Object element) {
-//             if (element instanceof ClassPathContainer) {
-//                     // return first package fragment root from the container
-//                     ClassPathContainer cp= (ClassPathContainer)element;
-//                     Object[] roots= cp.getPackageFragmentRoots();
-//                     if (roots.length > 0)
-//                             return (IPackageFragmentRoot)roots[0];
-//                     // non resolvable - return a dummy package fragment root
-//                     return cp.getJavaProject().getPackageFragmentRoot("Non-Resolvable");  //$NON-NLS-1$
-//             }
-//             return JavaModelUtil.getPackageFragmentRoot((IJavaElement)element);
-//     }
-       
+       private IPackageFragmentRoot getPackageFragmentRoot(Object element) {
+               // if (element instanceof ClassPathContainer) {
+               // // return first package fragment root from the container
+               // ClassPathContainer cp= (ClassPathContainer)element;
+               // Object[] roots= cp.getPackageFragmentRoots();
+               // if (roots.length > 0)
+               // return (IPackageFragmentRoot)roots[0];
+               // // non resolvable - return null
+               // return null;
+               // }
+               return JavaModelUtil.getPackageFragmentRoot((IJavaElement) element);
+       }
+
        private int compareWithLabelProvider(Viewer viewer, Object e1, Object e2) {
                if (viewer == null || !(viewer instanceof ContentViewer)) {
-                       IBaseLabelProvider prov = ((ContentViewer) viewer).getLabelProvider();
+                       IBaseLabelProvider prov = ((ContentViewer) viewer)
+                                       .getLabelProvider();
                        if (prov instanceof ILabelProvider) {
-                               ILabelProvider lprov= (ILabelProvider) prov;
+                               ILabelProvider lprov = (ILabelProvider) prov;
                                String name1 = lprov.getText(e1);
                                String name2 = lprov.getText(e2);
                                if (name1 != null && name2 != null) {
@@ -249,28 +320,31 @@ public class JavaElementSorter extends ViewerSorter {
                }
                return 0; // can't compare
        }
-                       
-//     private int getClassPathIndex(IPackageFragmentRoot root) {
-//             try {
-//                     IPath rootPath= root.getPath();
-//                     IPackageFragmentRoot[] roots= root.getJavaProject().getPackageFragmentRoots();
-//                     for (int i= 0; i < roots.length; i++) {
-//                             if (roots[i].getPath().equals(rootPath)) {
-//                                     return i;
-//                             }
-//                     }
-//             } catch (JavaModelException e) {
-//             }
-//
-//             return Integer.MAX_VALUE;
-//     }
-       
-       /* (non-Javadoc)
+
+       private int getClassPathIndex(IPackageFragmentRoot root) {
+               try {
+                       IPath rootPath = root.getPath();
+                       IPackageFragmentRoot[] roots = root.getJavaProject()
+                                       .getPackageFragmentRoots();
+                       for (int i = 0; i < roots.length; i++) {
+                               if (roots[i].getPath().equals(rootPath)) {
+                                       return i;
+                               }
+                       }
+               } catch (JavaModelException e) {
+               }
+
+               return Integer.MAX_VALUE;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
         * @see org.eclipse.jface.viewers.ViewerSorter#getCollator()
         */
        public final Collator getCollator() {
                if (collator == null) {
-                       collator= Collator.getInstance();
+                       collator = Collator.getInstance();
                }
                return collator;
        }