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
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package net.sourceforge.phpdt.internal.corext.util;
13 import java.util.StringTokenizer;
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;
31 import org.eclipse.core.resources.IResource;
32 import org.eclipse.core.runtime.CoreException;
33 import org.eclipse.core.runtime.IPath;
36 * Utility methods for the Java Model.
38 public class JavaModelUtil {
41 * Finds a type by its qualified type name (dot separated).
44 * The java project to search in
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
50 // public static IType findType(IJavaProject jproject, String
51 // fullyQualifiedName) throws JavaModelException {
52 // //workaround for bug 22883
53 // IType type= jproject.findType(fullyQualifiedName);
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())
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.
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);
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()))
90 // IType type= findType(pack, fullyQualifiedName);
91 // if (type != null && type.exists())
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())
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))
123 * Finds a type by package and type name.
126 * the java project to search in
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
135 // public static IType findType(IJavaProject jproject, String pack, String
136 // typeQualifiedName) throws JavaModelException {
137 // return jproject.findType(pack, typeQualifiedName);
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.
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)
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)) {
166 * Finds a type in a compilation unit. Typical usage is to find the
167 * corresponding type in a working copy.
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
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)) {
189 * Finds a a member in a compilation unit. Typical usage is to find the
190 * corresponding member in a working copy.
193 * the compilation unit (eg. working copy) to search in
195 * the member (eg. from the original)
196 * @return the member found, or null if not existing
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];
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.
213 * the cu to search in
215 * the element to look for
216 * @return an element of the given cu "equal" to the given element
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) {
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
233 public static String getTypeQualifiedName(IType type) {
234 return type.getTypeQualifiedName('.');
237 // private static void getTypeQualifiedName(IType type, StringBuffer buf) {
238 // IType outerType = type.getDeclaringType();
239 // if (outerType != null) {
240 // getTypeQualifiedName(outerType, buf);
243 // buf.append(type.getElementName());
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
252 public static String getFullyQualifiedName(IType type) {
253 return type.getFullyQualifiedName('.');
257 * Returns the fully qualified name of a type's container. (package name or
258 * enclosing type name)
260 public static String getTypeContainerName(IType type) {
261 IType outerType = type.getDeclaringType();
262 if (outerType != null) {
263 return outerType.getFullyQualifiedName('.');
265 return type.getPackageFragment().getElementName();
270 * Concatenates two names. Uses a dot for separation. Both strings can be
271 * empty or <code>null</code>.
273 public static String concatenateName(String name1, String name2) {
274 StringBuffer buf = new StringBuffer();
275 if (name1 != null && name1.length() > 0) {
278 if (name2 != null && name2.length() > 0) {
279 if (buf.length() > 0) {
284 return buf.toString();
288 * Concatenates two names. Uses a dot for separation. Both strings can be
289 * empty or <code>null</code>.
291 public static String concatenateName(char[] name1, char[] name2) {
292 StringBuffer buf = new StringBuffer();
293 if (name1 != null && name1.length > 0) {
296 if (name2 != null && name2.length > 0) {
297 if (buf.length() > 0) {
302 return buf.toString();
306 * Evaluates if a member (possible from another package) is visible from
307 * elements in a package.
310 * The member to test the visibility for
312 * The package in focus
314 public static boolean isVisible(IMember member, IPackageFragment pack)
315 throws JavaModelException {
316 int otherflags = member.getFlags();
318 if (Flags.isPublic(otherflags)) {
320 } else if (Flags.isPrivate(otherflags)) {
324 IPackageFragment otherpack = (IPackageFragment) findParentOfKind(
325 member, IJavaElement.PACKAGE_FRAGMENT);
326 return (pack != null && pack.equals(otherpack));
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
334 public static IPackageFragmentRoot getPackageFragmentRoot(
335 IJavaElement element) {
336 return (IPackageFragmentRoot) element
337 .getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
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.
344 * @deprecated Use element.getParent().getAncestor(kind);
346 public static IJavaElement findParentOfKind(IJavaElement element, int kind) {
347 if (element != null && element.getParent() != null) {
348 return element.getParent().getAncestor(kind);
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.
360 * The name of the method to find
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
368 public static IMethod findMethod(String name, String[] paramTypes,
369 boolean isConstructor, IType type) throws JavaModelException {
370 return findMethod(name, paramTypes, isConstructor, type.getMethods());
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.
380 * The name of the method to find
382 * The type signatures of the parameters e.g.
383 * <code>{"QString;","I"}</code>
384 * @param isConstructor
385 * If the method is a constructor
387 * The methods to search in
388 * @return The found method or <code>null</code>, if nothing found
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,
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
410 * Searches in this type's supertypes.
412 * The name of the method to find
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
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,
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) {
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.
449 * Type to search the superclasses
451 * The name of the method to find
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
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,
466 // if (found != null) {
467 // if (Flags.isAbstract(found.getFlags())) {
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.
483 * type signatures of the parameters e.g.
484 * <code>{"QString;","I"}</code>
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.
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)) {
514 * Checks whether the given type has a valid main method or not.
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()) {
527 * Checks if the field is boolean.
529 public static boolean isBoolean(IField field) throws JavaModelException {
530 return field.getTypeSignature().equals(Signature.SIG_BOOLEAN);
534 * Returns true if the element is on the build path of the given project
536 * @deprecated Use jproject.isOnClasspath(element);
538 // public static boolean isOnBuildPath(IJavaProject jproject, IJavaElement
539 // element) throws JavaModelException {
540 // return jproject.isOnClasspath(element);
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
547 // public static boolean isOnClasspath(IJavaElement element) {
548 // IJavaProject project= element.getJavaProject();
549 // if (!project.exists())
551 // return project.isOnClasspath(element);
554 * Resolves a type name in the context of the declaring type.
557 * the type name in signature notation (for example 'QVector')
558 * this can also be an array type, but dimensions will be
560 * @param declaringType
561 * the context for resolving (type where the reference was made
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
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);
574 throw new IllegalArgumentException();
576 //String name = refTypeSig.substring(arrayCount + 1, semi);
578 // String[][] resolvedNames= declaringType.resolveType(name);
579 // if (resolvedNames != null && resolvedNames.length > 0) {
580 // return JavaModelUtil.concatenateName(resolvedNames[0][0],
581 // resolvedNames[0][1]);
585 return Signature.toString(refTypeSig.substring(arrayCount));
590 * Returns if a CU can be edited.
592 public static boolean isEditable(ICompilationUnit cu) {
593 if (cu.isWorkingCopy()) {
594 cu = (ICompilationUnit) cu.getOriginalElement();
596 IResource resource = cu.getResource();
597 return (resource.exists() && !resource.getResourceAttributes()
602 * Finds a qualified import for a type name.
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];
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
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);
632 * XXX workaround for bug 18568
633 * http://bugs.eclipse.org/bugs/show_bug.cgi?id=18568 to be removed once the
636 private static IMethod toOriginalMethod(IMethod method) {
638 ICompilationUnit cu = method.getCompilationUnit();
639 if (cu == null || !cu.isWorkingCopy())
641 // use the workaround only if needed
642 if (!method.getElementName().equals(
643 method.getDeclaringType().getElementName()))
644 return (IMethod) cu.getOriginal(method);
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)
654 } catch (JavaModelException e) {
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
663 public static ICompilationUnit toOriginal(ICompilationUnit cu) {
664 if (cu != null && cu.isWorkingCopy())
665 return (ICompilationUnit) cu.getOriginal(cu);
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
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];
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.
692 public static ICompilationUnit toWorkingCopy(ICompilationUnit cu) {
693 if (!cu.isWorkingCopy()) {
694 ICompilationUnit workingCopy = /*EditorUtility.*/getWorkingCopy(cu);
695 if (workingCopy != null) {
703 * http://bugs.eclipse.org/bugs/show_bug.cgi?id=19253
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
710 public static boolean filterNotPresentException(CoreException exception) {
711 if (!(exception instanceof JavaModelException))
713 JavaModelException je = (JavaModelException) exception;
714 if (!je.isDoesNotExist())
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);
723 if (!unit.isWorkingCopy())
729 // public static IType[] getAllSuperTypes(IType type, IProgressMonitor pm)
730 // throws JavaModelException {
731 // //workaround for bugs 23644 and 23656
733 // pm.beginTask("", 3); //$NON-NLS-1$
734 // ITypeHierarchy hierarchy= type.newSupertypeHierarchy(new
735 // SubProgressMonitor(pm, 1));
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));
747 // types.add(type.getJavaProject().findType("java.lang.Object"));//$NON-NLS-1$
749 // return (IType[]) types.toArray(new IType[types.size()]);
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, '/')) {
768 * Returns whether the given resource path matches one of the exclusion
771 * @see IClasspathEntry#getExclusionPatterns
773 public final static boolean isExcluded(IPath resourcePath,
774 char[][] exclusionPatterns) {
775 if (exclusionPatterns == null)
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, '/'))
784 private static final String ARGUMENTS_DELIMITER = "#"; //$NON-NLS-1$
786 private static final String EMPTY_ARGUMENT = " "; //$NON-NLS-1$
789 * Copied from net.sourceforge.phpdt.internal.core.ProjectPrefUtil;
791 public static String[] getProblemArgumentsFromMarker(String argumentsString) {
792 if (argumentsString == null)
794 int index = argumentsString.indexOf(':');
798 int length = argumentsString.length();
801 numberOfArg = Integer.parseInt(argumentsString.substring(0, index));
802 } catch (NumberFormatException e) {
805 argumentsString = argumentsString.substring(index + 1, length);
807 String[] args = new String[length];
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;
819 if (count != numberOfArg)
822 System.arraycopy(args, 0, args = new String[count], 0, count);
828 * Gets the working copy of an compilation unit opened in an editor
833 * the original compilation unit (or another working copy)
834 * @return the working copy of the compilation unit, or null if not found
836 public static ICompilationUnit getWorkingCopy(ICompilationUnit cu) {
839 if (cu.isWorkingCopy())
842 return (ICompilationUnit) cu.findSharedWorkingCopy(PHPeclipsePlugin.getDefault()
843 .getBufferFactory());
848 * Gets the working copy of an member opened in an editor
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
855 public static IMember getWorkingCopy(IMember member)
856 throws JavaModelException {
857 ICompilationUnit cu = member.getCompilationUnit();
859 ICompilationUnit workingCopy = getWorkingCopy(cu);
860 if (workingCopy != null) {
861 return JavaModelUtil.findMemberInCompilationUnit(workingCopy,