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