6359918b0c39060951941042314f47c01c69a860
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / corext / util / JavaModelUtil.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2003 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Common Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-v10.html
7  *
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11 package net.sourceforge.phpdt.internal.corext.util;
12
13 import java.util.StringTokenizer;
14
15 import net.sourceforge.phpdt.core.Flags;
16 import net.sourceforge.phpdt.core.ICompilationUnit;
17 import net.sourceforge.phpdt.core.IField;
18 import net.sourceforge.phpdt.core.IJavaElement;
19 import net.sourceforge.phpdt.core.IMember;
20 import net.sourceforge.phpdt.core.IMethod;
21 import net.sourceforge.phpdt.core.IPackageFragment;
22 import net.sourceforge.phpdt.core.IPackageFragmentRoot;
23 import net.sourceforge.phpdt.core.IType;
24 import net.sourceforge.phpdt.core.JavaModelException;
25 import net.sourceforge.phpdt.core.Signature;
26 import net.sourceforge.phpdt.core.compiler.CharOperation;
27 //import net.sourceforge.phpdt.ui.JavaUI;
28 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
29 //import net.sourceforge.phpeclipse.phpeditor.EditorUtility;
30
31 import org.eclipse.core.resources.IResource;
32 import org.eclipse.core.runtime.CoreException;
33 import org.eclipse.core.runtime.IPath;
34
35 /**
36  * Utility methods for the Java Model.
37  */
38 public class JavaModelUtil {
39
40         /**
41          * Finds a type by its qualified type name (dot separated).
42          * 
43          * @param jproject
44          *            The java project to search in
45          * @param str
46          *            The fully qualified name (type name with enclosing type names
47          *            and package (all separated by dots))
48          * @return The type found, or null if not existing
49          */
50         // public static IType findType(IJavaProject jproject, String
51         // fullyQualifiedName) throws JavaModelException {
52         // //workaround for bug 22883
53         // IType type= jproject.findType(fullyQualifiedName);
54         // if (type != null)
55         // return type;
56         // IPackageFragmentRoot[] roots= jproject.getPackageFragmentRoots();
57         // for (int i= 0; i < roots.length; i++) {
58         // IPackageFragmentRoot root= roots[i];
59         // type= findType(root, fullyQualifiedName);
60         // if (type != null && type.exists())
61         // return type;
62         // }
63         // return null;
64         // }
65         /**
66          * Returns <code>true</code> if the given package fragment root is
67          * referenced. This means it is own by a different project but is referenced
68          * by the root's parent. Returns <code>false</code> if the given root
69          * doesn't have an underlying resource.
70          */
71         public static boolean isReferenced(IPackageFragmentRoot root) {
72                 // IResource resource= root.getResource();
73                 // if (resource != null) {
74                 // IProject jarProject= resource.getProject();
75                 // IProject container= root.getJavaProject().getProject();
76                 // return !container.equals(jarProject);
77                 // }
78                 return false;
79         }
80
81         // private static IType findType(IPackageFragmentRoot root, String
82         // fullyQualifiedName) throws JavaModelException{
83         // IJavaElement[] children= root.getChildren();
84         // for (int i= 0; i < children.length; i++) {
85         // IJavaElement element= children[i];
86         // if (element.getElementType() == IJavaElement.PACKAGE_FRAGMENT){
87         // IPackageFragment pack= (IPackageFragment)element;
88         // if (! fullyQualifiedName.startsWith(pack.getElementName()))
89         // continue;
90         // IType type= findType(pack, fullyQualifiedName);
91         // if (type != null && type.exists())
92         // return type;
93         // }
94         // }
95         // return null;
96         // }
97
98         // private static IType findType(IPackageFragment pack, String
99         // fullyQualifiedName) throws JavaModelException{
100         // ICompilationUnit[] cus= pack.getCompilationUnits();
101         // for (int i= 0; i < cus.length; i++) {
102         // ICompilationUnit unit= cus[i];
103         // ICompilationUnit wc= WorkingCopyUtil.getWorkingCopyIfExists(unit);
104         // IType type= findType(wc, fullyQualifiedName);
105         // if (type != null && type.exists())
106         // return type;
107         // }
108         // return null;
109         // }
110
111         // private static IType findType(ICompilationUnit cu, String
112         // fullyQualifiedName) throws JavaModelException{
113         // IType[] types= cu.getAllTypes();
114         // for (int i= 0; i < types.length; i++) {
115         // IType type= types[i];
116         // if (getFullyQualifiedName(type).equals(fullyQualifiedName))
117         // return type;
118         // }
119         // return null;
120         // }
121
122         /**
123          * Finds a type by package and type name.
124          * 
125          * @param jproject
126          *            the java project to search in
127          * @param pack
128          *            The package name
129          * @param typeQualifiedName
130          *            the type qualified name (type name with enclosing type names
131          *            (separated by dots))
132          * @return the type found, or null if not existing
133          * @deprecated Use IJavaProject.findType(String, String) instead
134          */
135         // public static IType findType(IJavaProject jproject, String pack, String
136         // typeQualifiedName) throws JavaModelException {
137         // return jproject.findType(pack, typeQualifiedName);
138         // }
139         /**
140          * Finds a type container by container name. The returned element will be of
141          * type <code>IType</code> or a <code>IPackageFragment</code>.
142          * <code>null</code> is returned if the type container could not be found.
143          * 
144          * @param jproject
145          *            The Java project defining the context to search
146          * @param typeContainerName
147          *            A dot separarted name of the type container
148          * @see #getTypeContainerName(IType)
149          */
150         // public static IJavaElement findTypeContainer(IJavaProject jproject,
151         // String typeContainerName) throws JavaModelException {
152         // // try to find it as type
153         // IJavaElement result= jproject.findType(typeContainerName);
154         // if (result == null) {
155         // // find it as package
156         // IPath path= new Path(typeContainerName.replace('.', '/'));
157         // result= jproject.findElement(path);
158         // if (!(result instanceof IPackageFragment)) {
159         // result= null;
160         // }
161         //
162         // }
163         // return result;
164         // }
165         /**
166          * Finds a type in a compilation unit. Typical usage is to find the
167          * corresponding type in a working copy.
168          * 
169          * @param cu
170          *            the compilation unit to search in
171          * @param typeQualifiedName
172          *            the type qualified name (type name with enclosing type names
173          *            (separated by dots))
174          * @return the type found, or null if not existing
175          */
176         public static IType findTypeInCompilationUnit(ICompilationUnit cu,
177                         String typeQualifiedName) throws JavaModelException {
178                 IType[] types = cu.getAllTypes();
179                 for (int i = 0; i < types.length; i++) {
180                         String currName = getTypeQualifiedName(types[i]);
181                         if (typeQualifiedName.equals(currName)) {
182                                 return types[i];
183                         }
184                 }
185                 return null;
186         }
187
188         /**
189          * Finds a a member in a compilation unit. Typical usage is to find the
190          * corresponding member in a working copy.
191          * 
192          * @param cu
193          *            the compilation unit (eg. working copy) to search in
194          * @param member
195          *            the member (eg. from the original)
196          * @return the member found, or null if not existing
197          */
198         public static IMember findMemberInCompilationUnit(ICompilationUnit cu,
199                         IMember member) throws JavaModelException {
200                 IJavaElement[] elements = cu.findElements(member);
201                 if (elements != null && elements.length > 0) {
202                         return (IMember) elements[0];
203                 }
204                 return null;
205         }
206
207         /**
208          * Returns the element of the given compilation unit which is "equal" to the
209          * given element. Note that the given element usually has a parent different
210          * from the given compilation unit.
211          * 
212          * @param cu
213          *            the cu to search in
214          * @param element
215          *            the element to look for
216          * @return an element of the given cu "equal" to the given element
217          */
218         public static IJavaElement findInCompilationUnit(ICompilationUnit cu,
219                         IJavaElement element) throws JavaModelException {
220                 IJavaElement[] elements = cu.findElements(element);
221                 if (elements != null && elements.length > 0) {
222                         return elements[0];
223                 }
224                 return null;
225         }
226
227         /**
228          * Returns the qualified type name of the given type using '.' as
229          * separators. This is a replace for IType.getTypeQualifiedName() which uses
230          * '$' as separators. As '$' is also a valid character in an id this is
231          * ambiguous. JavaCore PR: 1GCFUNT
232          */
233         public static String getTypeQualifiedName(IType type) {
234                 return type.getTypeQualifiedName('.');
235         }
236
237 //      private static void getTypeQualifiedName(IType type, StringBuffer buf) {
238 //              IType outerType = type.getDeclaringType();
239 //              if (outerType != null) {
240 //                      getTypeQualifiedName(outerType, buf);
241 //                      buf.append('.');
242 //              }
243 //              buf.append(type.getElementName());
244 //      }
245
246         /**
247          * Returns the fully qualified name of the given type using '.' as
248          * separators. This is a replace for IType.getFullyQualifiedTypeName which
249          * uses '$' as separators. As '$' is also a valid character in an id this is
250          * ambiguous. JavaCore PR: 1GCFUNT
251          */
252         public static String getFullyQualifiedName(IType type) {
253                 return type.getFullyQualifiedName('.');
254         }
255
256         /**
257          * Returns the fully qualified name of a type's container. (package name or
258          * enclosing type name)
259          */
260         public static String getTypeContainerName(IType type) {
261                 IType outerType = type.getDeclaringType();
262                 if (outerType != null) {
263                         return outerType.getFullyQualifiedName('.');
264                 } else {
265                         return type.getPackageFragment().getElementName();
266                 }
267         }
268
269         /**
270          * Concatenates two names. Uses a dot for separation. Both strings can be
271          * empty or <code>null</code>.
272          */
273         public static String concatenateName(String name1, String name2) {
274                 StringBuffer buf = new StringBuffer();
275                 if (name1 != null && name1.length() > 0) {
276                         buf.append(name1);
277                 }
278                 if (name2 != null && name2.length() > 0) {
279                         if (buf.length() > 0) {
280                                 buf.append('.');
281                         }
282                         buf.append(name2);
283                 }
284                 return buf.toString();
285         }
286
287         /**
288          * Concatenates two names. Uses a dot for separation. Both strings can be
289          * empty or <code>null</code>.
290          */
291         public static String concatenateName(char[] name1, char[] name2) {
292                 StringBuffer buf = new StringBuffer();
293                 if (name1 != null && name1.length > 0) {
294                         buf.append(name1);
295                 }
296                 if (name2 != null && name2.length > 0) {
297                         if (buf.length() > 0) {
298                                 buf.append('.');
299                         }
300                         buf.append(name2);
301                 }
302                 return buf.toString();
303         }
304
305         /**
306          * Evaluates if a member (possible from another package) is visible from
307          * elements in a package.
308          * 
309          * @param member
310          *            The member to test the visibility for
311          * @param pack
312          *            The package in focus
313          */
314         public static boolean isVisible(IMember member, IPackageFragment pack)
315                         throws JavaModelException {
316                 int otherflags = member.getFlags();
317
318                 if (Flags.isPublic(otherflags)) {
319                         return true;
320                 } else if (Flags.isPrivate(otherflags)) {
321                         return false;
322                 }
323
324                 IPackageFragment otherpack = (IPackageFragment) findParentOfKind(
325                                 member, IJavaElement.PACKAGE_FRAGMENT);
326                 return (pack != null && pack.equals(otherpack));
327         }
328
329         /**
330          * Returns the package fragment root of <code>IJavaElement</code>. If the
331          * given element is already a package fragment root, the element itself is
332          * returned.
333          */
334         public static IPackageFragmentRoot getPackageFragmentRoot(
335                         IJavaElement element) {
336                 return (IPackageFragmentRoot) element
337                                 .getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
338         }
339
340         /**
341          * Returns the parent of the supplied java element that conforms to the
342          * given parent type or <code>null</code>, if such a parent doesn't exit.
343          * 
344          * @deprecated Use element.getParent().getAncestor(kind);
345          */
346         public static IJavaElement findParentOfKind(IJavaElement element, int kind) {
347                 if (element != null && element.getParent() != null) {
348                         return element.getParent().getAncestor(kind);
349                 }
350                 return null;
351         }
352
353         /**
354          * Finds a method in a type. This searches for a method with the same name
355          * and signature. Parameter types are only compared by the simple name, no
356          * resolving for the fully qualified type name is done. Constructors are
357          * only compared by parameters, not the name.
358          * 
359          * @param name
360          *            The name of the method to find
361          * @param paramTypes
362          *            The type signatures of the parameters e.g.
363          *            <code>{"QString;","I"}</code>
364          * @param isConstructor
365          *            If the method is a constructor
366          * @return The first found method or <code>null</code>, if nothing found
367          */
368         public static IMethod findMethod(String name, String[] paramTypes,
369                         boolean isConstructor, IType type) throws JavaModelException {
370                 return findMethod(name, paramTypes, isConstructor, type.getMethods());
371         }
372
373         /**
374          * Finds a method by name. This searches for a method with a name and
375          * signature. Parameter types are only compared by the simple name, no
376          * resolving for the fully qualified type name is done. Constructors are
377          * only compared by parameters, not the name.
378          * 
379          * @param name
380          *            The name of the method to find
381          * @param paramTypes
382          *            The type signatures of the parameters e.g.
383          *            <code>{"QString;","I"}</code>
384          * @param isConstructor
385          *            If the method is a constructor
386          * @param methods
387          *            The methods to search in
388          * @return The found method or <code>null</code>, if nothing found
389          */
390         public static IMethod findMethod(String name, String[] paramTypes,
391                         boolean isConstructor, IMethod[] methods) throws JavaModelException {
392                 for (int i = methods.length - 1; i >= 0; i--) {
393                         if (isSameMethodSignature(name, paramTypes, isConstructor,
394                                         methods[i])) {
395                                 return methods[i];
396                         }
397                 }
398                 return null;
399         }
400
401         /**
402          * Finds a method declararion in a type's hierarchy. The search is top down,
403          * so this returns the first declaration of the method in the hierarchy.
404          * This searches for a method with a name and signature. Parameter types are
405          * only compared by the simple name, no resolving for the fully qualified
406          * type name is done. Constructors are only compared by parameters, not the
407          * name.
408          * 
409          * @param type
410          *            Searches in this type's supertypes.
411          * @param name
412          *            The name of the method to find
413          * @param paramTypes
414          *            The type signatures of the parameters e.g.
415          *            <code>{"QString;","I"}</code>
416          * @param isConstructor
417          *            If the method is a constructor
418          * @return The first method found or null, if nothing found
419          */
420         // public static IMethod findMethodDeclarationInHierarchy(ITypeHierarchy
421         // hierarchy, IType type, String name, String[] paramTypes, boolean
422         // isConstructor) throws JavaModelException {
423         // IType[] superTypes= hierarchy.getAllSupertypes(type);
424         // for (int i= superTypes.length - 1; i >= 0; i--) {
425         // IMethod first= findMethod(name, paramTypes, isConstructor,
426         // superTypes[i]);
427         // if (first != null && !Flags.isPrivate(first.getFlags())) {
428         // // the order getAllSupertypes does make assumptions of the order of inner
429         // elements -> search recursivly
430         // IMethod res= findMethodDeclarationInHierarchy(hierarchy,
431         // first.getDeclaringType(), name, paramTypes, isConstructor);
432         // if (res != null) {
433         // return res;
434         // }
435         // return first;
436         // }
437         // }
438         // return null;
439         // }
440         /**
441          * Finds a method implementation in a type's classhierarchy. The search is
442          * bottom-up, so this returns the nearest overridden method. Does not find
443          * methods in interfaces or abstract methods. This searches for a method
444          * with a name and signature. Parameter types are only compared by the
445          * simple name, no resolving for the fully qualified type name is done.
446          * Constructors are only compared by parameters, not the name.
447          * 
448          * @param type
449          *            Type to search the superclasses
450          * @param name
451          *            The name of the method to find
452          * @param paramTypes
453          *            The type signatures of the parameters e.g.
454          *            <code>{"QString;","I"}</code>
455          * @param isConstructor
456          *            If the method is a constructor
457          * @return The first method found or null, if nothing found
458          */
459         // public static IMethod findMethodImplementationInHierarchy(ITypeHierarchy
460         // hierarchy, IType type, String name, String[] paramTypes, boolean
461         // isConstructor) throws JavaModelException {
462         // IType[] superTypes= hierarchy.getAllSuperclasses(type);
463         // for (int i= 0; i < superTypes.length; i++) {
464         // IMethod found= findMethod(name, paramTypes, isConstructor,
465         // superTypes[i]);
466         // if (found != null) {
467         // if (Flags.isAbstract(found.getFlags())) {
468         // return null;
469         // }
470         // return found;
471         // }
472         // }
473         // return null;
474         // }
475         /**
476          * Tests if a method equals to the given signature. Parameter types are only
477          * compared by the simple name, no resolving for the fully qualified type
478          * name is done. Constructors are only compared by parameters, not the name.
479          * 
480          * @param Name
481          *            of the method
482          * @param The
483          *            type signatures of the parameters e.g.
484          *            <code>{"QString;","I"}</code>
485          * @param Specifies
486          *            if the method is a constructor
487          * @return Returns <code>true</code> if the method has the given name and
488          *         parameter types and constructor state.
489          */
490         public static boolean isSameMethodSignature(String name,
491                         String[] paramTypes, boolean isConstructor, IMethod curr)
492                         throws JavaModelException {
493                 if (isConstructor || name.equals(curr.getElementName())) {
494                         if (isConstructor == curr.isConstructor()) {
495                                 String[] currParamTypes = curr.getParameterTypes();
496                                 if (paramTypes.length == currParamTypes.length) {
497                                         for (int i = 0; i < paramTypes.length; i++) {
498                                                 String t1 = Signature.getSimpleName(Signature
499                                                                 .toString(paramTypes[i]));
500                                                 String t2 = Signature.getSimpleName(Signature
501                                                                 .toString(currParamTypes[i]));
502                                                 if (!t1.equals(t2)) {
503                                                         return false;
504                                                 }
505                                         }
506                                         return true;
507                                 }
508                         }
509                 }
510                 return false;
511         }
512
513         /**
514          * Checks whether the given type has a valid main method or not.
515          */
516         public static boolean hasMainMethod(IType type) throws JavaModelException {
517                 IMethod[] methods = type.getMethods();
518                 for (int i = 0; i < methods.length; i++) {
519                         if (methods[i].isMainMethod()) {
520                                 return true;
521                         }
522                 }
523                 return false;
524         }
525
526         /**
527          * Checks if the field is boolean.
528          */
529         public static boolean isBoolean(IField field) throws JavaModelException {
530                 return field.getTypeSignature().equals(Signature.SIG_BOOLEAN);
531         }
532
533         /**
534          * Returns true if the element is on the build path of the given project
535          * 
536          * @deprecated Use jproject.isOnClasspath(element);
537          */
538         // public static boolean isOnBuildPath(IJavaProject jproject, IJavaElement
539         // element) throws JavaModelException {
540         // return jproject.isOnClasspath(element);
541         // }
542         /**
543          * Tests if the given element is on the class path of its containing
544          * project. Handles the case that the containing project isn't a Java
545          * project.
546          */
547         // public static boolean isOnClasspath(IJavaElement element) {
548         // IJavaProject project= element.getJavaProject();
549         // if (!project.exists())
550         // return false;
551         // return project.isOnClasspath(element);
552         // }
553         /**
554          * Resolves a type name in the context of the declaring type.
555          * 
556          * @param refTypeSig
557          *            the type name in signature notation (for example 'QVector')
558          *            this can also be an array type, but dimensions will be
559          *            ignored.
560          * @param declaringType
561          *            the context for resolving (type where the reference was made
562          *            in)
563          * @return returns the fully qualified type name or build-in-type name. if a
564          *         unresoved type couldn't be resolved null is returned
565          */
566         public static String getResolvedTypeName(String refTypeSig,
567                         IType declaringType) throws JavaModelException {
568                 int arrayCount = Signature.getArrayCount(refTypeSig);
569                 char type = refTypeSig.charAt(arrayCount);
570                 if (type == Signature.C_UNRESOLVED) {
571                         int semi = refTypeSig
572                                         .indexOf(Signature.C_SEMICOLON, arrayCount + 1);
573                         if (semi == -1) {
574                                 throw new IllegalArgumentException();
575                         }
576                         //String name = refTypeSig.substring(arrayCount + 1, semi);
577
578                         // String[][] resolvedNames= declaringType.resolveType(name);
579                         // if (resolvedNames != null && resolvedNames.length > 0) {
580                         // return JavaModelUtil.concatenateName(resolvedNames[0][0],
581                         // resolvedNames[0][1]);
582                         // }
583                         return null;
584                 } else {
585                         return Signature.toString(refTypeSig.substring(arrayCount));
586                 }
587         }
588
589         /**
590          * Returns if a CU can be edited.
591          */
592         public static boolean isEditable(ICompilationUnit cu) {
593                 if (cu.isWorkingCopy()) {
594                         cu = (ICompilationUnit) cu.getOriginalElement();
595                 }
596                 IResource resource = cu.getResource();
597                 return (resource.exists() && !resource.getResourceAttributes()
598                                 .isReadOnly());
599         }
600
601         /**
602          * Finds a qualified import for a type name.
603          */
604         // public static IImportDeclaration findImport(ICompilationUnit cu, String
605         // simpleName) throws JavaModelException {
606         // IImportDeclaration[] existing= cu.getImports();
607         // for (int i= 0; i < existing.length; i++) {
608         // String curr= existing[i].getElementName();
609         // if (curr.endsWith(simpleName)) {
610         // int dotPos= curr.length() - simpleName.length() - 1;
611         // if ((dotPos == -1) || (dotPos > 0 && curr.charAt(dotPos) == '.')) {
612         // return existing[i];
613         // }
614         // }
615         // }
616         // return null;
617         // }
618         /**
619          * Returns the original if the given member. If the member is already an
620          * original the input is returned. The returned member must not exist
621          */
622         public static IMember toOriginal(IMember member) {
623                 if (member instanceof IMethod)
624                         return toOriginalMethod((IMethod) member);
625                 ICompilationUnit cu = member.getCompilationUnit();
626                 if (cu != null && cu.isWorkingCopy())
627                         return (IMember) cu.getOriginal(member);
628                 return member;
629         }
630
631         /*
632          * XXX workaround for bug 18568
633          * http://bugs.eclipse.org/bugs/show_bug.cgi?id=18568 to be removed once the
634          * bug is fixed
635          */
636         private static IMethod toOriginalMethod(IMethod method) {
637                 try {
638                         ICompilationUnit cu = method.getCompilationUnit();
639                         if (cu == null || !cu.isWorkingCopy())
640                                 return method;
641                         // use the workaround only if needed
642                         if (!method.getElementName().equals(
643                                         method.getDeclaringType().getElementName()))
644                                 return (IMethod) cu.getOriginal(method);
645
646                         IType originalType = (IType) toOriginal(method.getDeclaringType());
647                         IMethod[] methods = originalType.findMethods(method);
648                         boolean isConstructor = method.isConstructor();
649                         for (int i = 0; i < methods.length; i++) {
650                                 if (methods[i].isConstructor() == isConstructor)
651                                         return methods[i];
652                         }
653                         return null;
654                 } catch (JavaModelException e) {
655                         return null;
656                 }
657         }
658
659         /**
660          * Returns the original cu if the given cu. If the cu is already an original
661          * the input cu is returned. The returned cu must not exist
662          */
663         public static ICompilationUnit toOriginal(ICompilationUnit cu) {
664                 if (cu != null && cu.isWorkingCopy())
665                         return (ICompilationUnit) cu.getOriginal(cu);
666                 return cu;
667         }
668
669         /**
670          * Returns the working copy of the given member. If the member is already in
671          * a working copy or the member does not exist in the working copy the input
672          * is returned.
673          */
674         public static IMember toWorkingCopy(IMember member) {
675                 ICompilationUnit cu = member.getCompilationUnit();
676                 if (cu != null && !cu.isWorkingCopy()) {
677                         ICompilationUnit workingCopy = /*EditorUtility.*/getWorkingCopy(cu);
678                         if (workingCopy != null) {
679                                 IJavaElement[] members = workingCopy.findElements(member);
680                                 if (members != null && members.length > 0) {
681                                         return (IMember) members[0];
682                                 }
683                         }
684                 }
685                 return member;
686         }
687
688         /**
689          * Returns the working copy CU of the given CU. If the CU is already a
690          * working copy or the CU has no working copy the input CU is returned.
691          */
692         public static ICompilationUnit toWorkingCopy(ICompilationUnit cu) {
693                 if (!cu.isWorkingCopy()) {
694                         ICompilationUnit workingCopy = /*EditorUtility.*/getWorkingCopy(cu);
695                         if (workingCopy != null) {
696                                 return workingCopy;
697                         }
698                 }
699                 return cu;
700         }
701
702         /*
703          * http://bugs.eclipse.org/bugs/show_bug.cgi?id=19253
704          * 
705          * Reconciling happens in a separate thread. This can cause a situation
706          * where the Java element gets disposed after an exists test has been done.
707          * So we should not log not present exceptions when they happen in working
708          * copies.
709          */
710         public static boolean filterNotPresentException(CoreException exception) {
711                 if (!(exception instanceof JavaModelException))
712                         return true;
713                 JavaModelException je = (JavaModelException) exception;
714                 if (!je.isDoesNotExist())
715                         return true;
716                 IJavaElement[] elements = je.getJavaModelStatus().getElements();
717                 for (int i = 0; i < elements.length; i++) {
718                         IJavaElement element = elements[i];
719                         ICompilationUnit unit = (ICompilationUnit) element
720                                         .getAncestor(IJavaElement.COMPILATION_UNIT);
721                         if (unit == null)
722                                 return true;
723                         if (!unit.isWorkingCopy())
724                                 return true;
725                 }
726                 return false;
727         }
728
729         // public static IType[] getAllSuperTypes(IType type, IProgressMonitor pm)
730         // throws JavaModelException {
731         // //workaround for bugs 23644 and 23656
732         // try{
733         // pm.beginTask("", 3); //$NON-NLS-1$
734         // ITypeHierarchy hierarchy= type.newSupertypeHierarchy(new
735         // SubProgressMonitor(pm, 1));
736         //
737         // IProgressMonitor subPm= new SubProgressMonitor(pm, 2);
738         // List typeList= Arrays.asList(hierarchy.getAllSupertypes(type));
739         // subPm.beginTask("", typeList.size()); //$NON-NLS-1$
740         // Set types= new HashSet(typeList);
741         // for (Iterator iter= typeList.iterator(); iter.hasNext();) {
742         // IType superType= (IType)iter.next();
743         // IType[] superTypes= getAllSuperTypes(superType, new
744         // SubProgressMonitor(subPm, 1));
745         // types.addAll(Arrays.asList(superTypes));
746         // }
747         // types.add(type.getJavaProject().findType("java.lang.Object"));//$NON-NLS-1$
748         // subPm.done();
749         // return (IType[]) types.toArray(new IType[types.size()]);
750         // } finally {
751         // pm.done();
752         // }
753         // }
754
755         public static boolean isExcludedPath(IPath resourcePath,
756                         IPath[] exclusionPatterns) {
757                 char[] path = resourcePath.toString().toCharArray();
758                 for (int i = 0, length = exclusionPatterns.length; i < length; i++) {
759                         char[] pattern = exclusionPatterns[i].toString().toCharArray();
760                         if (CharOperation.pathMatch(pattern, path, true, '/')) {
761                                 return true;
762                         }
763                 }
764                 return false;
765         }
766
767         /*
768          * Returns whether the given resource path matches one of the exclusion
769          * patterns.
770          * 
771          * @see IClasspathEntry#getExclusionPatterns
772          */
773         public final static boolean isExcluded(IPath resourcePath,
774                         char[][] exclusionPatterns) {
775                 if (exclusionPatterns == null)
776                         return false;
777                 char[] path = resourcePath.toString().toCharArray();
778                 for (int i = 0, length = exclusionPatterns.length; i < length; i++)
779                         if (CharOperation.pathMatch(exclusionPatterns[i], path, true, '/'))
780                                 return true;
781                 return false;
782         }
783
784         private static final String ARGUMENTS_DELIMITER = "#"; //$NON-NLS-1$
785
786         private static final String EMPTY_ARGUMENT = "   "; //$NON-NLS-1$
787
788         /**
789          * Copied from net.sourceforge.phpdt.internal.core.ProjectPrefUtil;
790          */
791         public static String[] getProblemArgumentsFromMarker(String argumentsString) {
792                 if (argumentsString == null)
793                         return null;
794                 int index = argumentsString.indexOf(':');
795                 if (index == -1)
796                         return null;
797
798                 int length = argumentsString.length();
799                 int numberOfArg;
800                 try {
801                         numberOfArg = Integer.parseInt(argumentsString.substring(0, index));
802                 } catch (NumberFormatException e) {
803                         return null;
804                 }
805                 argumentsString = argumentsString.substring(index + 1, length);
806
807                 String[] args = new String[length];
808                 int count = 0;
809
810                 StringTokenizer tokenizer = new StringTokenizer(argumentsString,
811                                 ARGUMENTS_DELIMITER);
812                 while (tokenizer.hasMoreTokens()) {
813                         String argument = tokenizer.nextToken();
814                         if (argument.equals(EMPTY_ARGUMENT))
815                                 argument = ""; //$NON-NLS-1$
816                         args[count++] = argument;
817                 }
818
819                 if (count != numberOfArg)
820                         return null;
821
822                 System.arraycopy(args, 0, args = new String[count], 0, count);
823                 return args;
824         }
825
826         //incastrix
827         /**
828          * Gets the working copy of an compilation unit opened in an editor
829          * 
830          * @param part
831          *            the editor part
832          * @param cu
833          *            the original compilation unit (or another working copy)
834          * @return the working copy of the compilation unit, or null if not found
835          */
836         public static ICompilationUnit getWorkingCopy(ICompilationUnit cu) {
837                 if (cu == null)
838                         return null;
839                 if (cu.isWorkingCopy())
840                         return cu;
841
842                 return (ICompilationUnit) cu.findSharedWorkingCopy(PHPeclipsePlugin.getDefault()
843                                 .getBufferFactory());
844         }
845
846         // incastrix
847         /**
848          * Gets the working copy of an member opened in an editor
849          * 
850          * @param member
851          *            the original member or a member in a working copy
852          * @return the corresponding member in the shared working copy or
853          *         <code>null</code> if not found
854          */
855         public static IMember getWorkingCopy(IMember member)
856                         throws JavaModelException {
857                 ICompilationUnit cu = member.getCompilationUnit();
858                 if (cu != null) {
859                         ICompilationUnit workingCopy = getWorkingCopy(cu);
860                         if (workingCopy != null) {
861                                 return JavaModelUtil.findMemberInCompilationUnit(workingCopy,
862                                                 member);
863                         }
864                 }
865                 return null;
866         }
867 }