KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > corext > refactoring > Checks


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.corext.refactoring;
12
13 import java.util.ArrayList JavaDoc;
14 import java.util.List JavaDoc;
15
16 import org.eclipse.core.runtime.Assert;
17 import org.eclipse.core.runtime.CoreException;
18 import org.eclipse.core.runtime.IPath;
19 import org.eclipse.core.runtime.IProgressMonitor;
20 import org.eclipse.core.runtime.IStatus;
21
22 import org.eclipse.core.resources.IContainer;
23 import org.eclipse.core.resources.IFile;
24 import org.eclipse.core.resources.IMarker;
25 import org.eclipse.core.resources.IProject;
26 import org.eclipse.core.resources.IResource;
27 import org.eclipse.core.resources.ResourceAttributes;
28 import org.eclipse.core.resources.ResourcesPlugin;
29
30 import org.eclipse.ltk.core.refactoring.RefactoringStatus;
31
32 import org.eclipse.jdt.core.ICompilationUnit;
33 import org.eclipse.jdt.core.IJavaElement;
34 import org.eclipse.jdt.core.IJavaModelMarker;
35 import org.eclipse.jdt.core.IJavaProject;
36 import org.eclipse.jdt.core.ILocalVariable;
37 import org.eclipse.jdt.core.IMember;
38 import org.eclipse.jdt.core.IMethod;
39 import org.eclipse.jdt.core.IPackageFragment;
40 import org.eclipse.jdt.core.IPackageFragmentRoot;
41 import org.eclipse.jdt.core.IType;
42 import org.eclipse.jdt.core.JavaConventions;
43 import org.eclipse.jdt.core.JavaCore;
44 import org.eclipse.jdt.core.JavaModelException;
45 import org.eclipse.jdt.core.Signature;
46 import org.eclipse.jdt.core.dom.ASTNode;
47 import org.eclipse.jdt.core.dom.AnonymousClassDeclaration;
48 import org.eclipse.jdt.core.dom.Expression;
49 import org.eclipse.jdt.core.dom.IBinding;
50 import org.eclipse.jdt.core.dom.IMethodBinding;
51 import org.eclipse.jdt.core.dom.ITypeBinding;
52 import org.eclipse.jdt.core.dom.IVariableBinding;
53 import org.eclipse.jdt.core.dom.Name;
54 import org.eclipse.jdt.core.dom.SwitchCase;
55 import org.eclipse.jdt.core.dom.VariableDeclaration;
56
57 import org.eclipse.jdt.internal.corext.Corext;
58 import org.eclipse.jdt.internal.corext.dom.ASTNodes;
59 import org.eclipse.jdt.internal.corext.dom.Bindings;
60 import org.eclipse.jdt.internal.corext.refactoring.base.JavaStatusContext;
61 import org.eclipse.jdt.internal.corext.refactoring.base.RefactoringStatusCodes;
62 import org.eclipse.jdt.internal.corext.refactoring.changes.RenameResourceChange;
63 import org.eclipse.jdt.internal.corext.refactoring.util.JavaElementUtil;
64 import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
65 import org.eclipse.jdt.internal.corext.util.JdtFlags;
66 import org.eclipse.jdt.internal.corext.util.Messages;
67 import org.eclipse.jdt.internal.corext.util.Resources;
68
69 /**
70  * This class defines a set of reusable static checks methods.
71  */

72 public class Checks {
73     
74     /*
75      * no instances
76      */

77     private Checks(){
78     }
79     
80     /* Constants returned by checkExpressionIsRValue */
81     public static final int IS_RVALUE= 0;
82     public static final int NOT_RVALUE_MISC= 1;
83     public static final int NOT_RVALUE_VOID= 2;
84
85     /**
86      * Checks if method will have a constructor name after renaming.
87      * @param method
88      * @param newMethodName
89      * @param newTypeName
90      * @return <code>RefactoringStatus</code> with <code>WARNING</code> severity if
91      * the give method will have a constructor name after renaming
92      * <code>null</code> otherwise.
93      */

94     public static RefactoringStatus checkIfConstructorName(IMethod method, String JavaDoc newMethodName, String JavaDoc newTypeName){
95         if (! newMethodName.equals(newTypeName))
96             return null;
97         else
98             return RefactoringStatus.createWarningStatus(
99                 Messages.format(RefactoringCoreMessages.Checks_constructor_name,
100                 new Object JavaDoc[] {JavaElementUtil.createMethodSignature(method), JavaModelUtil.getFullyQualifiedName(method.getDeclaringType()) } ));
101     }
102         
103     /**
104      * Checks if the given name is a valid Java field name.
105      *
106      * @param name the java field name.
107      * @return a refactoring status containing the error message if the
108      * name is not a valid java field name.
109      */

110     public static RefactoringStatus checkFieldName(String JavaDoc name) {
111         return checkName(name, JavaConventions.validateFieldName(name));
112     }
113
114     /**
115      * Checks if the given name is a valid Java type parameter name.
116      *
117      * @param name the java type parameter name.
118      * @return a refactoring status containing the error message if the
119      * name is not a valid java type parameter name.
120      */

121     public static RefactoringStatus checkTypeParameterName(String JavaDoc name) {
122         return checkName(name, JavaConventions.validateTypeVariableName(name));
123     }
124
125     /**
126      * Checks if the given name is a valid Java identifier.
127      *
128      * @param name the java identifier.
129      * @return a refactoring status containing the error message if the
130      * name is not a valid java identifier.
131      */

132     public static RefactoringStatus checkIdentifier(String JavaDoc name) {
133         return checkName(name, JavaConventions.validateIdentifier(name));
134     }
135     
136     /**
137      * Checks if the given name is a valid Java method name.
138      *
139      * @param name the java method name.
140      * @return a refactoring status containing the error message if the
141      * name is not a valid java method name.
142      */

143     public static RefactoringStatus checkMethodName(String JavaDoc name) {
144         RefactoringStatus status= checkName(name, JavaConventions.validateMethodName(name));
145         if (status.isOK() && startsWithUpperCase(name))
146             return RefactoringStatus.createWarningStatus(RefactoringCoreMessages.Checks_method_names_lowercase);
147         else
148             return status;
149     }
150         
151     /**
152      * Checks if the given name is a valid Java type name.
153      *
154      * @param name the java method name.
155      * @return a refactoring status containing the error message if the
156      * name is not a valid java type name.
157      */

158     public static RefactoringStatus checkTypeName(String JavaDoc name) {
159         //fix for: 1GF5Z0Z: ITPJUI:WINNT - assertion failed after renameType refactoring
160
if (name.indexOf(".") != -1) //$NON-NLS-1$
161
return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.Checks_no_dot);
162         else
163             return checkName(name, JavaConventions.validateJavaTypeName(name));
164     }
165     
166     /**
167      * Checks if the given name is a valid Java package name.
168      *
169      * @param name the java package name.
170      * @return a refactoring status containing the error message if the
171      * name is not a valid java package name.
172      */

173     public static RefactoringStatus checkPackageName(String JavaDoc name) {
174         return checkName(name, JavaConventions.validatePackageName(name));
175     }
176     
177     /**
178      * Checks if the given name is a valid compilation unit name.
179      *
180      * @param name the compilation unit name.
181      * @return a refactoring status containing the error message if the
182      * name is not a valid compilation unit name.
183      */

184     public static RefactoringStatus checkCompilationUnitName(String JavaDoc name) {
185         return checkName(name, JavaConventions.validateCompilationUnitName(name));
186     }
187
188     /**
189      * Returns ok status if the new name is ok. This is when no other file with that name exists.
190      * @param cu
191      * @param newName
192      * @return the status
193      */

194     public static RefactoringStatus checkCompilationUnitNewName(ICompilationUnit cu, String JavaDoc newName) {
195         String JavaDoc newCUName= JavaModelUtil.getRenamedCUName(cu, newName);
196         if (resourceExists(RenameResourceChange.renamedResourcePath(cu.getResource().getFullPath(), newCUName)))
197             return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.Checks_cu_name_used, newName));
198         else
199             return new RefactoringStatus();
200     }
201         
202     public static boolean startsWithUpperCase(String JavaDoc s) {
203         if (s == null)
204             return false;
205         else if ("".equals(s)) //$NON-NLS-1$
206
return false;
207         else
208             //workaround for JDK bug (see 26529)
209
return s.charAt(0) == Character.toUpperCase(s.charAt(0));
210     }
211         
212     public static boolean startsWithLowerCase(String JavaDoc s){
213         if (s == null)
214             return false;
215         else if ("".equals(s)) //$NON-NLS-1$
216
return false;
217         else
218             //workaround for JDK bug (see 26529)
219
return s.charAt(0) == Character.toLowerCase(s.charAt(0));
220     }
221
222     public static boolean resourceExists(IPath resourcePath){
223         return ResourcesPlugin.getWorkspace().getRoot().findMember(resourcePath) != null;
224     }
225     
226     public static boolean isTopLevel(IType type){
227         return type.getDeclaringType() == null;
228     }
229
230     public static boolean isAnonymous(IType type) throws JavaModelException {
231         return type.isAnonymous();
232     }
233
234     public static boolean isTopLevelType(IMember member){
235         return member.getElementType() == IJavaElement.TYPE && isTopLevel((IType) member);
236     }
237     
238     public static boolean isInsideLocalType(IType type) throws JavaModelException {
239         while (type != null) {
240             if (type.isLocal())
241                 return true;
242             type= type.getDeclaringType();
243         }
244         return false;
245     }
246
247     public static boolean isAlreadyNamed(IJavaElement element, String JavaDoc name){
248         return name.equals(element.getElementName());
249     }
250
251     //-------------- main and native method checks ------------------
252
public static RefactoringStatus checkForMainAndNativeMethods(ICompilationUnit cu) throws JavaModelException {
253         return checkForMainAndNativeMethods(cu.getTypes());
254     }
255     
256     public static RefactoringStatus checkForMainAndNativeMethods(IType[] types) throws JavaModelException {
257         RefactoringStatus result= new RefactoringStatus();
258         for (int i= 0; i < types.length; i++)
259             result.merge(checkForMainAndNativeMethods(types[i]));
260         return result;
261     }
262     
263     public static RefactoringStatus checkForMainAndNativeMethods(IType type) throws JavaModelException {
264         RefactoringStatus result= new RefactoringStatus();
265         result.merge(checkForMainAndNativeMethods(type.getMethods()));
266         result.merge(checkForMainAndNativeMethods(type.getTypes()));
267         return result;
268     }
269     
270     private static RefactoringStatus checkForMainAndNativeMethods(IMethod[] methods) throws JavaModelException {
271         RefactoringStatus result= new RefactoringStatus();
272         for (int i= 0; i < methods.length; i++) {
273             if (JdtFlags.isNative(methods[i])){
274                 String JavaDoc msg= Messages.format(RefactoringCoreMessages.Checks_method_native,
275                                 new String JavaDoc[]{JavaModelUtil.getFullyQualifiedName(methods[i].getDeclaringType()), methods[i].getElementName(), "UnsatisfiedLinkError"});//$NON-NLS-1$
276
result.addEntry(RefactoringStatus.ERROR, msg, JavaStatusContext.create(methods[i]), Corext.getPluginId(), RefactoringStatusCodes.NATIVE_METHOD);
277             }
278             if (methods[i].isMainMethod()) {
279                 String JavaDoc msg= Messages.format(RefactoringCoreMessages.Checks_has_main,
280                         JavaModelUtil.getFullyQualifiedName(methods[i].getDeclaringType()));
281                 result.addEntry(RefactoringStatus.WARNING, msg, JavaStatusContext.create(methods[i]), Corext.getPluginId(), RefactoringStatusCodes.MAIN_METHOD);
282             }
283         }
284         return result;
285     }
286     
287     //---- New method name checking -------------------------------------------------------------
288

289     /**
290      * Checks if the new method is already used in the given type.
291      * @param type
292      * @param methodName
293      * @param parameters
294      * @return the status
295      */

296     public static RefactoringStatus checkMethodInType(ITypeBinding type, String JavaDoc methodName, ITypeBinding[] parameters) {
297         RefactoringStatus result= new RefactoringStatus();
298         if (methodName.equals(type.getName()))
299             result.addWarning(RefactoringCoreMessages.Checks_methodName_constructor);
300         IMethodBinding method= org.eclipse.jdt.internal.corext.dom.Bindings.findMethodInType(type, methodName, parameters);
301         if (method != null)
302             result.addError(Messages.format(RefactoringCoreMessages.Checks_methodName_exists,
303                 new Object JavaDoc[] {methodName, type.getName()}),
304                 JavaStatusContext.create(method));
305         return result;
306     }
307     
308     /**
309      * Checks if the new method somehow conflicts with an already existing method in
310      * the hierarchy. The following checks are done:
311      * <ul>
312      * <li> if the new method overrides a method defined in the given type or in one of its
313      * super classes. </li>
314      * </ul>
315      * @param type
316      * @param methodName
317      * @param returnType
318      * @param parameters
319      * @return the status
320      */

321     public static RefactoringStatus checkMethodInHierarchy(ITypeBinding type, String JavaDoc methodName, ITypeBinding returnType, ITypeBinding[] parameters) {
322         RefactoringStatus result= new RefactoringStatus();
323         IMethodBinding method= Bindings.findMethodInHierarchy(type, methodName, parameters);
324         if (method != null) {
325             boolean returnTypeClash= false;
326             ITypeBinding methodReturnType= method.getReturnType();
327             if (returnType != null && methodReturnType != null) {
328                 String JavaDoc returnTypeKey= returnType.getKey();
329                 String JavaDoc methodReturnTypeKey= methodReturnType.getKey();
330                 if (returnTypeKey == null && methodReturnTypeKey == null) {
331                     returnTypeClash= returnType != methodReturnType;
332                 } else if (returnTypeKey != null && methodReturnTypeKey != null) {
333                     returnTypeClash= !returnTypeKey.equals(methodReturnTypeKey);
334                 }
335             }
336             ITypeBinding dc= method.getDeclaringClass();
337             if (returnTypeClash) {
338                 result.addError(Messages.format(RefactoringCoreMessages.Checks_methodName_returnTypeClash,
339                     new Object JavaDoc[] {methodName, dc.getName()}),
340                     JavaStatusContext.create(method));
341             } else {
342                 result.addError(Messages.format(RefactoringCoreMessages.Checks_methodName_overrides,
343                     new Object JavaDoc[] {methodName, dc.getName()}),
344                     JavaStatusContext.create(method));
345             }
346         }
347         return result;
348     }
349     
350     //---- Selection checks --------------------------------------------------------------------
351

352     public static boolean isExtractableExpression(ASTNode[] selectedNodes, ASTNode coveringNode) {
353         ASTNode node= coveringNode;
354         if (isEnumCase(node))
355             return false;
356         if (selectedNodes != null && selectedNodes.length == 1)
357             node= selectedNodes[0];
358         return isExtractableExpression(node);
359     }
360
361     public static boolean isEnumCase(ASTNode node) {
362         if (node instanceof SwitchCase) {
363             final SwitchCase caze= (SwitchCase) node;
364             final Expression expression= caze.getExpression();
365             if (expression instanceof Name) {
366                 final Name name= (Name) expression;
367                 final IBinding binding= name.resolveBinding();
368                 if (binding instanceof IVariableBinding) {
369                     IVariableBinding variableBinding= (IVariableBinding) binding;
370                     return variableBinding.isEnumConstant();
371                 }
372             }
373         }
374         return false;
375     }
376
377     public static boolean isExtractableExpression(ASTNode node) {
378         if (!(node instanceof Expression))
379             return false;
380         if (node instanceof Name) {
381             IBinding binding= ((Name) node).resolveBinding();
382             return !(binding instanceof ITypeBinding);
383         }
384         return true;
385     }
386
387     public static boolean isInsideJavadoc(ASTNode node) {
388         do {
389             if (node.getNodeType() == ASTNode.JAVADOC)
390                 return true;
391             node= node.getParent();
392         } while (node != null);
393         return false;
394     }
395
396     /**
397      * Returns a fatal error in case the name is empty. In all other cases, an
398      * error based on the given status is returned.
399      *
400      * @param name a name
401      * @param status a status
402      * @return RefactoringStatus based on the given status or the name, if
403      * empty.
404      */

405     public static RefactoringStatus checkName(String JavaDoc name, IStatus status) {
406         RefactoringStatus result= new RefactoringStatus();
407         if ("".equals(name)) //$NON-NLS-1$
408
return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.Checks_Choose_name);
409
410         if (status.isOK())
411             return result;
412         
413         switch (status.getSeverity()){
414             case IStatus.ERROR:
415                 return RefactoringStatus.createFatalErrorStatus(status.getMessage());
416             case IStatus.WARNING:
417                 return RefactoringStatus.createWarningStatus(status.getMessage());
418             case IStatus.INFO:
419                 return RefactoringStatus.createInfoStatus(status.getMessage());
420             default: //no nothing
421
return new RefactoringStatus();
422         }
423     }
424     
425     /**
426      * Finds a method in a type
427      * This searches for a method with the same name and signature. Parameter types are only
428      * compared by the simple name, no resolving for the fully qualified type name is done
429      * @param name
430      * @param parameterCount
431      * @param isConstructor
432      * @param type
433      * @return The first found method or null, if nothing found
434      * @throws JavaModelException
435      */

436     public static IMethod findMethod(String JavaDoc name, int parameterCount, boolean isConstructor, IType type) throws JavaModelException {
437         return findMethod(name, parameterCount, isConstructor, type.getMethods());
438     }
439     
440     /**
441      * Finds a method in a type.
442      * Searches for a method with the same name and the same parameter count.
443      * Parameter types are <b>not</b> compared.
444      * @param method
445      * @param type
446      * @return The first found method or null, if nothing found
447      * @throws JavaModelException
448      */

449     public static IMethod findMethod(IMethod method, IType type) throws JavaModelException {
450         return findMethod(method.getElementName(), method.getParameterTypes().length, method.isConstructor(), type.getMethods());
451     }
452
453     /**
454      * Finds a method in an array of methods.
455      * Searches for a method with the same name and the same parameter count.
456      * Parameter types are <b>not</b> compared.
457      * @param method
458      * @param methods
459      * @return The first found method or null, if nothing found
460      * @throws JavaModelException
461      */

462     public static IMethod findMethod(IMethod method, IMethod[] methods) throws JavaModelException {
463         return findMethod(method.getElementName(), method.getParameterTypes().length, method.isConstructor(), methods);
464     }
465     
466     public static IMethod findMethod(String JavaDoc name, int parameters, boolean isConstructor, IMethod[] methods) throws JavaModelException {
467         for (int i= methods.length-1; i >= 0; i--) {
468             IMethod curr= methods[i];
469             if (name.equals(curr.getElementName())) {
470                 if (isConstructor == curr.isConstructor()) {
471                     if (parameters == curr.getParameterTypes().length) {
472                         return curr;
473                     }
474                 }
475             }
476         }
477         return null;
478     }
479
480     /**
481      * Finds a method in a type.
482      * This searches for a method with the same name and signature. Parameter types are only
483      * compared by the simple name, no resolving for the fully qualified type name is done
484      * @param method
485      * @param type
486      * @return The first found method or null, if nothing found
487      * @throws JavaModelException
488      */

489     public static IMethod findSimilarMethod(IMethod method, IType type) throws JavaModelException {
490         return findSimilarMethod(method, type.getMethods());
491     }
492
493     /**
494      * Finds a method in an array of methods.
495      * This searches for a method with the same name and signature. Parameter types are only
496      * compared by the simple name, no resolving for the fully qualified type name is done
497      * @param method
498      * @param methods
499      * @return The first found method or null, if nothing found
500      * @throws JavaModelException
501      */

502     public static IMethod findSimilarMethod(IMethod method, IMethod[] methods) throws JavaModelException {
503         boolean isConstructor= method.isConstructor();
504         for (int i= 0; i < methods.length; i++) {
505             IMethod otherMethod= methods[i];
506             if (otherMethod.isConstructor() == isConstructor && method.isSimilar(otherMethod))
507                 return otherMethod;
508         }
509         return null;
510     }
511                 
512     /*
513      * Compare two parameter signatures
514      */

515     public static boolean compareParamTypes(String JavaDoc[] paramTypes1, String JavaDoc[] paramTypes2) {
516         if (paramTypes1.length == paramTypes2.length) {
517             int i= 0;
518             while (i < paramTypes1.length) {
519                 String JavaDoc t1= Signature.getSimpleName(Signature.toString(paramTypes1[i]));
520                 String JavaDoc t2= Signature.getSimpleName(Signature.toString(paramTypes2[i]));
521                 if (!t1.equals(t2)) {
522                     return false;
523                 }
524                 i++;
525             }
526             return true;
527         }
528         return false;
529     }
530     
531     //---------------------
532

533     public static RefactoringStatus checkIfCuBroken(IMember member) throws JavaModelException{
534         ICompilationUnit cu= (ICompilationUnit)JavaCore.create(member.getCompilationUnit().getResource());
535         if (cu == null)
536             return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.Checks_cu_not_created);
537         else if (! cu.isStructureKnown())
538             return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.Checks_cu_not_parsed);
539         return new RefactoringStatus();
540     }
541     
542     /**
543      * From SearchResultGroup[] passed as the parameter
544      * this method removes all those that correspond to a non-parsable ICompilationUnit
545      * and returns it as a result.
546      * @param grouped the array of search result groups from which non parsable compilation
547      * units are to be removed.
548      * @param status a refactoring status to collect errors and problems
549      * @return the array of search result groups
550      * @throws JavaModelException
551      */

552     public static SearchResultGroup[] excludeCompilationUnits(SearchResultGroup[] grouped, RefactoringStatus status) throws JavaModelException{
553         List JavaDoc result= new ArrayList JavaDoc();
554         boolean wasEmpty= grouped.length == 0;
555         for (int i= 0; i < grouped.length; i++){
556             IResource resource= grouped[i].getResource();
557             IJavaElement element= JavaCore.create(resource);
558             if (! (element instanceof ICompilationUnit))
559                 continue;
560             //XXX this is a workaround for a jcore feature that shows errors in cus only when you get the original element
561
ICompilationUnit cu= (ICompilationUnit)JavaCore.create(resource);
562             if (! cu.isStructureKnown()){
563                 String JavaDoc path= Checks.getFullPath(cu);
564                 status.addError(Messages.format(RefactoringCoreMessages.Checks_cannot_be_parsed, path));
565                 continue; //removed, go to the next one
566
}
567             result.add(grouped[i]);
568         }
569         
570         if ((!wasEmpty) && result.isEmpty())
571             status.addFatalError(RefactoringCoreMessages.Checks_all_excluded);
572         
573         return (SearchResultGroup[])result.toArray(new SearchResultGroup[result.size()]);
574     }
575     
576     private static final String JavaDoc getFullPath(ICompilationUnit cu) {
577         Assert.isTrue(cu.exists());
578         return cu.getResource().getFullPath().toString();
579     }
580     
581     
582     public static RefactoringStatus checkCompileErrorsInAffectedFiles(SearchResultGroup[] grouped) throws JavaModelException {
583         RefactoringStatus result= new RefactoringStatus();
584         for (int i= 0; i < grouped.length; i++)
585             checkCompileErrorsInAffectedFile(result, grouped[i].getResource());
586         return result;
587     }
588     
589     public static void checkCompileErrorsInAffectedFile(RefactoringStatus result, IResource resource) throws JavaModelException {
590         if (hasCompileErrors(resource))
591             result.addWarning(Messages.format(RefactoringCoreMessages.Checks_cu_has_compile_errors, resource.getFullPath().makeRelative()));
592     }
593     
594     public static RefactoringStatus checkCompileErrorsInAffectedFiles(SearchResultGroup[] references, IResource declaring) throws JavaModelException {
595         RefactoringStatus result= new RefactoringStatus();
596         for (int i= 0; i < references.length; i++){
597             IResource resource= references[i].getResource();
598             if (resource.equals(declaring))
599                 declaring= null;
600             checkCompileErrorsInAffectedFile(result, resource);
601         }
602         if (declaring != null)
603             checkCompileErrorsInAffectedFile(result, declaring);
604         return result;
605     }
606     
607     private static boolean hasCompileErrors(IResource resource) throws JavaModelException {
608         try {
609             IMarker[] problemMarkers= resource.findMarkers(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER, true, IResource.DEPTH_INFINITE);
610             for (int i= 0; i < problemMarkers.length; i++) {
611                 if (problemMarkers[i].getAttribute(IMarker.SEVERITY, -1) == IMarker.SEVERITY_ERROR)
612                     return true;
613             }
614             return false;
615         } catch (JavaModelException e){
616             throw e;
617         } catch (CoreException e){
618             throw new JavaModelException(e);
619         }
620     }
621     
622     //------
623
public static boolean isReadOnly(Object JavaDoc element) throws JavaModelException{
624         if (element instanceof IResource)
625             return isReadOnly((IResource)element);
626         
627         if (element instanceof IJavaElement) {
628             if ((element instanceof IPackageFragmentRoot) && isClasspathDelete((IPackageFragmentRoot)element))
629                 return false;
630             return isReadOnly(((IJavaElement)element).getResource());
631         }
632         
633         Assert.isTrue(false, "not expected to get here"); //$NON-NLS-1$
634
return false;
635     }
636     
637     public static boolean isReadOnly(IResource res) throws JavaModelException {
638         ResourceAttributes attributes= res.getResourceAttributes();
639         if (attributes != null && attributes.isReadOnly())
640             return true;
641         
642         if (! (res instanceof IContainer))
643             return false;
644         
645         IContainer container= (IContainer)res;
646         try {
647             IResource[] children= container.members();
648             for (int i= 0; i < children.length; i++) {
649                 if (isReadOnly(children[i]))
650                     return true;
651             }
652             return false;
653         } catch (JavaModelException e){
654             throw e;
655         } catch (CoreException e) {
656             throw new JavaModelException(e);
657         }
658     }
659     
660     public static boolean isClasspathDelete(IPackageFragmentRoot pkgRoot) {
661         IResource res= pkgRoot.getResource();
662         if (res == null)
663             return true;
664         IProject definingProject= res.getProject();
665         if (res.getParent() != null && pkgRoot.isArchive() && ! res.getParent().equals(definingProject))
666             return true;
667         
668         IProject occurringProject= pkgRoot.getJavaProject().getProject();
669         return !definingProject.equals(occurringProject);
670     }
671     
672     //-------- validateEdit checks ----
673

674     public static RefactoringStatus validateModifiesFiles(IFile[] filesToModify, Object JavaDoc context) {
675         RefactoringStatus result= new RefactoringStatus();
676         IStatus status= Resources.checkInSync(filesToModify);
677         if (!status.isOK())
678             result.merge(RefactoringStatus.create(status));
679         status= Resources.makeCommittable(filesToModify, context);
680         if (!status.isOK()) {
681             result.merge(RefactoringStatus.create(status));
682             if (!result.hasFatalError()) {
683                 result.addFatalError(RefactoringCoreMessages.Checks_validateEdit);
684             }
685         }
686         return result;
687     }
688     
689     public static RefactoringStatus validateEdit(ICompilationUnit unit, Object JavaDoc context) {
690         IResource resource= unit.getPrimary().getResource();
691         RefactoringStatus result= new RefactoringStatus();
692         if (resource == null)
693             return result;
694         IStatus status= Resources.checkInSync(resource);
695         if (!status.isOK())
696             result.merge(RefactoringStatus.create(status));
697         status= Resources.makeCommittable(resource, context);
698         if (!status.isOK()) {
699             result.merge(RefactoringStatus.create(status));
700             if (!result.hasFatalError()) {
701                 result.addFatalError(RefactoringCoreMessages.Checks_validateEdit);
702             }
703         }
704         return result;
705     }
706
707     /**
708      * Checks whether it is possible to modify the given <code>IJavaElement</code>.
709      * The <code>IJavaElement</code> must exist and be non read-only to be modifiable.
710      * Moreover, if it is a <code>IMember</code> it must not be binary.
711      * The returned <code>RefactoringStatus</code> has <code>ERROR</code> severity if
712      * it is not possible to modify the element.
713      * @param javaElement
714      * @return the status
715      * @throws JavaModelException
716      *
717      * @see IJavaElement#exists
718      * @see IJavaElement#isReadOnly
719      * @see IMember#isBinary
720      * @see RefactoringStatus
721      */

722     public static RefactoringStatus checkAvailability(IJavaElement javaElement) throws JavaModelException{
723         RefactoringStatus result= new RefactoringStatus();
724         if (! javaElement.exists())
725             result.addFatalError(Messages.format(RefactoringCoreMessages.Refactoring_not_in_model, javaElement.getElementName()));
726         if (javaElement.isReadOnly())
727             result.addFatalError(Messages.format(RefactoringCoreMessages.Refactoring_read_only, javaElement.getElementName()));
728         if (javaElement.exists() && !javaElement.isStructureKnown())
729             result.addFatalError(Messages.format(RefactoringCoreMessages.Refactoring_unknown_structure, javaElement.getElementName()));
730         if (javaElement instanceof IMember && ((IMember)javaElement).isBinary())
731             result.addFatalError(Messages.format(RefactoringCoreMessages.Refactoring_binary, javaElement.getElementName()));
732         return result;
733     }
734     
735     public static boolean isAvailable(IJavaElement javaElement) throws JavaModelException {
736         if (javaElement == null)
737             return false;
738         if (! javaElement.exists())
739             return false;
740         if (javaElement.isReadOnly())
741             return false;
742         // work around for https://bugs.eclipse.org/bugs/show_bug.cgi?id=48422
743
// the Java project is now cheating regarding its children so we shouldn't
744
// call isStructureKnown if the project isn't open.
745
// see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=52474
746
if (!(javaElement instanceof IJavaProject) && !(javaElement instanceof ILocalVariable) && !javaElement.isStructureKnown())
747             return false;
748         if (javaElement instanceof IMember && ((IMember)javaElement).isBinary())
749             return false;
750         return true;
751     }
752
753     public static IType findTypeInPackage(IPackageFragment pack, String JavaDoc name) throws JavaModelException {
754         Assert.isTrue(pack.exists());
755         Assert.isTrue(!pack.isReadOnly());
756         
757         /* ICompilationUnit.getType expects simple name*/
758         if (name.indexOf(".") != -1) //$NON-NLS-1$
759
name= name.substring(0, name.indexOf(".")); //$NON-NLS-1$
760
ICompilationUnit[] cus= pack.getCompilationUnits();
761         for (int i= 0; i < cus.length; i++){
762             if (cus[i].getType(name).exists())
763                 return cus[i].getType(name);
764         }
765         return null;
766     }
767
768     public static RefactoringStatus checkTempName(String JavaDoc newName) {
769         RefactoringStatus result= Checks.checkIdentifier(newName);
770         if (result.hasFatalError())
771             return result;
772         if (! Checks.startsWithLowerCase(newName))
773             result.addWarning(RefactoringCoreMessages.ExtractTempRefactoring_convention);
774         return result;
775     }
776
777     public static RefactoringStatus checkEnumConstantName(String JavaDoc newName) {
778         RefactoringStatus result= Checks.checkFieldName(newName);
779         if (result.hasFatalError())
780             return result;
781         for (int i= 0; i < newName.length(); i++) {
782             char c= newName.charAt(i);
783             if (Character.isLetter(c) && !Character.isUpperCase(c)) {
784                 result.addWarning(RefactoringCoreMessages.RenameEnumConstRefactoring_convention);
785                 break;
786             }
787         }
788         return result;
789     }
790
791     public static RefactoringStatus checkConstantName(String JavaDoc newName) {
792         RefactoringStatus result= Checks.checkFieldName(newName);
793         if (result.hasFatalError())
794             return result;
795         for (int i= 0; i < newName.length(); i++) {
796             char c= newName.charAt(i);
797             if (Character.isLetter(c) && !Character.isUpperCase(c)) {
798                 result.addWarning(RefactoringCoreMessages.ExtractConstantRefactoring_convention);
799                 break;
800             }
801         }
802         return result;
803     }
804
805     public static boolean isException(IType iType, IProgressMonitor pm) throws JavaModelException {
806         try{
807             if (! iType.isClass())
808                 return false;
809             IType[] superTypes= iType.newSupertypeHierarchy(pm).getAllSupertypes(iType);
810             for (int i= 0; i < superTypes.length; i++) {
811                 if ("java.lang.Throwable".equals(superTypes[i].getFullyQualifiedName())) //$NON-NLS-1$
812
return true;
813             }
814             return false;
815         } finally{
816             pm.done();
817         }
818     }
819         
820     /**
821      * @param e
822      * @return int
823      * Checks.IS_RVALUE if e is an rvalue
824      * Checks.NOT_RVALUE_VOID if e is not an rvalue because its type is void
825      * Checks.NOT_RVALUE_MISC if e is not an rvalue for some other reason
826      */

827     public static int checkExpressionIsRValue(Expression e) {
828         if(e instanceof Name) {
829             if(!(((Name) e).resolveBinding() instanceof IVariableBinding)) {
830                 return NOT_RVALUE_MISC;
831             }
832         }
833         
834         ITypeBinding tb= e.resolveTypeBinding();
835         if (tb == null)
836             return NOT_RVALUE_MISC;
837         else if (tb.getName().equals("void")) //$NON-NLS-1$
838
return NOT_RVALUE_VOID;
839
840         return IS_RVALUE;
841     }
842
843     public static boolean isDeclaredIn(VariableDeclaration tempDeclaration, Class JavaDoc astNodeClass) {
844         ASTNode initializer= ASTNodes.getParent(tempDeclaration, astNodeClass);
845         if (initializer == null)
846             return false;
847         ASTNode anonymous= ASTNodes.getParent(tempDeclaration, AnonymousClassDeclaration.class);
848         if (anonymous == null)
849             return true;
850         // stupid code. Is to find out if the variable declaration isn't a field.
851
if (ASTNodes.isParent(anonymous, initializer))
852             return false;
853         return true;
854     }
855 }
856
Popular Tags