/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.wst.jsdt.internal.corext.refactoring; import java.util.ArrayList; import java.util.List; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ResourceAttributes; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.ltk.core.refactoring.RefactoringStatus; import org.eclipse.wst.jsdt.core.IJavaScriptUnit; import org.eclipse.wst.jsdt.core.IJavaScriptElement; import org.eclipse.wst.jsdt.core.IJavaScriptModelMarker; import org.eclipse.wst.jsdt.core.IJavaScriptProject; import org.eclipse.wst.jsdt.core.ILocalVariable; import org.eclipse.wst.jsdt.core.IMember; import org.eclipse.wst.jsdt.core.IFunction; import org.eclipse.wst.jsdt.core.IPackageFragment; import org.eclipse.wst.jsdt.core.IPackageFragmentRoot; import org.eclipse.wst.jsdt.core.IType; import org.eclipse.wst.jsdt.core.JavaScriptConventions; import org.eclipse.wst.jsdt.core.JavaScriptCore; import org.eclipse.wst.jsdt.core.JavaScriptModelException; import org.eclipse.wst.jsdt.core.Signature; import org.eclipse.wst.jsdt.core.dom.ASTNode; import org.eclipse.wst.jsdt.core.dom.AnonymousClassDeclaration; import org.eclipse.wst.jsdt.core.dom.Expression; import org.eclipse.wst.jsdt.core.dom.IBinding; import org.eclipse.wst.jsdt.core.dom.IFunctionBinding; import org.eclipse.wst.jsdt.core.dom.ITypeBinding; import org.eclipse.wst.jsdt.core.dom.IVariableBinding; import org.eclipse.wst.jsdt.core.dom.Name; import org.eclipse.wst.jsdt.core.dom.VariableDeclaration; import org.eclipse.wst.jsdt.internal.corext.dom.ASTNodes; import org.eclipse.wst.jsdt.internal.corext.dom.Bindings; import org.eclipse.wst.jsdt.internal.corext.refactoring.base.JavaStatusContext; import org.eclipse.wst.jsdt.internal.corext.refactoring.changes.RenameResourceChange; import org.eclipse.wst.jsdt.internal.corext.refactoring.util.JavaElementUtil; import org.eclipse.wst.jsdt.internal.corext.util.JavaModelUtil; import org.eclipse.wst.jsdt.internal.corext.util.Messages; import org.eclipse.wst.jsdt.internal.corext.util.Resources; /** * This class defines a set of reusable static checks methods. */ public class Checks { /* * no instances */ private Checks(){ } /* Constants returned by checkExpressionIsRValue */ public static final int IS_RVALUE= 0; public static final int NOT_RVALUE_MISC= 1; public static final int NOT_RVALUE_VOID= 2; /** * Checks if method will have a constructor name after renaming. * @param method * @param newMethodName * @param newTypeName * @return <code>RefactoringStatus</code> with <code>WARNING</code> severity if * the give method will have a constructor name after renaming * <code>null</code> otherwise. */ public static RefactoringStatus checkIfConstructorName(IFunction method, String newMethodName, String newTypeName){ if (! newMethodName.equals(newTypeName)) return null; else return RefactoringStatus.createWarningStatus( Messages.format(RefactoringCoreMessages.Checks_constructor_name, new Object[] {JavaElementUtil.createMethodSignature(method), JavaModelUtil.getFullyQualifiedName(method.getDeclaringType()) } )); } /** * Checks if the given name is a valid Java field name. * * @param name the java field name. * @return a refactoring status containing the error message if the * name is not a valid java field name. */ public static RefactoringStatus checkFieldName(String name) { return checkName(name, JavaScriptConventions.validateFieldName(name)); } /** * Checks if the given name is a valid Java type parameter name. * * @param name the java type parameter name. * @return a refactoring status containing the error message if the * name is not a valid java type parameter name. */ public static RefactoringStatus checkTypeParameterName(String name) { return checkName(name, JavaScriptConventions.validateTypeVariableName(name)); } /** * Checks if the given name is a valid Java identifier. * * @param name the java identifier. * @return a refactoring status containing the error message if the * name is not a valid java identifier. */ public static RefactoringStatus checkIdentifier(String name) { return checkName(name, JavaScriptConventions.validateIdentifier(name)); } /** * Checks if the given name is a valid Java method name. * * @param name the java method name. * @return a refactoring status containing the error message if the * name is not a valid java method name. */ public static RefactoringStatus checkMethodName(String name) { RefactoringStatus status= checkName(name, JavaScriptConventions.validateFunctionName(name)); if (status.isOK() && startsWithUpperCase(name)) return RefactoringStatus.createWarningStatus(RefactoringCoreMessages.Checks_method_names_lowercase); else return status; } /** * Checks if the given name is a valid Java type name. * * @param name the java method name. * @return a refactoring status containing the error message if the * name is not a valid java type name. */ public static RefactoringStatus checkTypeName(String name) { //fix for: 1GF5Z0Z: ITPJUI:WINNT - assertion failed after renameType refactoring // if (name.indexOf(".") != -1) //$NON-NLS-1$ // return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.Checks_no_dot); // else return checkName(name, JavaScriptConventions.validateJavaScriptTypeName(name)); } /** * Checks if the given name is a valid Java package name. * * @param name the java package name. * @return a refactoring status containing the error message if the * name is not a valid java package name. */ public static RefactoringStatus checkPackageName(String name) { return checkName(name, JavaScriptConventions.validatePackageName(name)); } /** * Checks if the given name is a valid compilation unit name. * * @param name the compilation unit name. * @return a refactoring status containing the error message if the * name is not a valid compilation unit name. */ public static RefactoringStatus checkCompilationUnitName(String name) { return checkName(name, JavaScriptConventions.validateCompilationUnitName(name)); } /** * Returns ok status if the new name is ok. This is when no other file with that name exists. * @param cu * @param newName * @return the status */ public static RefactoringStatus checkCompilationUnitNewName(IJavaScriptUnit cu, String newName) { String newCUName= JavaModelUtil.getRenamedCUName(cu, newName); if (resourceExists(RenameResourceChange.renamedResourcePath(cu.getResource().getFullPath(), newCUName))) return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.Checks_cu_name_used, newName)); else return new RefactoringStatus(); } public static boolean startsWithUpperCase(String s) { if (s == null) return false; else if ("".equals(s)) //$NON-NLS-1$ return false; else //workaround for JDK bug (see 26529) return s.charAt(0) == Character.toUpperCase(s.charAt(0)); } public static boolean startsWithLowerCase(String s){ if (s == null) return false; else if ("".equals(s)) //$NON-NLS-1$ return false; else //workaround for JDK bug (see 26529) return s.charAt(0) == Character.toLowerCase(s.charAt(0)); } public static boolean resourceExists(IPath resourcePath){ return ResourcesPlugin.getWorkspace().getRoot().findMember(resourcePath) != null; } public static boolean isTopLevel(IType type){ return type.getDeclaringType() == null; } public static boolean isAnonymous(IType type) throws JavaScriptModelException { return type.isAnonymous(); } public static boolean isTopLevelType(IMember member){ return member.getElementType() == IJavaScriptElement.TYPE && isTopLevel((IType) member); } public static boolean isInsideLocalType(IType type) throws JavaScriptModelException { while (type != null) { if (type.isLocal()) return true; type= type.getDeclaringType(); } return false; } public static boolean isAlreadyNamed(IJavaScriptElement element, String name){ return name.equals(element.getElementName()); } // //-------------- main and native method checks ------------------ // public static RefactoringStatus checkForMainAndNativeMethods(IJavaScriptUnit cu) throws JavaScriptModelException { // return checkForMainAndNativeMethods(cu.getTypes()); // } // // public static RefactoringStatus checkForMainAndNativeMethods(IType[] types) throws JavaScriptModelException { // RefactoringStatus result= new RefactoringStatus(); // for (int i= 0; i < types.length; i++) // result.merge(checkForMainAndNativeMethods(types[i])); // return result; // } // // public static RefactoringStatus checkForMainAndNativeMethods(IType type) throws JavaScriptModelException { // RefactoringStatus result= new RefactoringStatus(); // result.merge(checkForMainAndNativeMethods(type.getMethods())); // result.merge(checkForMainAndNativeMethods(type.getTypes())); // return result; // } // // private static RefactoringStatus checkForMainAndNativeMethods(IFunction[] methods) throws JavaScriptModelException { // RefactoringStatus result= new RefactoringStatus(); // for (int i= 0; i < methods.length; i++) { // if (JdtFlags.isNative(methods[i])){ // String msg= Messages.format(RefactoringCoreMessages.Checks_method_native, // new String[]{JavaModelUtil.getFullyQualifiedName(methods[i].getDeclaringType()), methods[i].getElementName(), "UnsatisfiedLinkError"});//$NON-NLS-1$ // result.addEntry(RefactoringStatus.ERROR, msg, JavaStatusContext.create(methods[i]), Corext.getPluginId(), RefactoringStatusCodes.NATIVE_METHOD); // } // if (methods[i].isMainMethod()) { // String msg= Messages.format(RefactoringCoreMessages.Checks_has_main, // JavaModelUtil.getFullyQualifiedName(methods[i].getDeclaringType())); // result.addEntry(RefactoringStatus.WARNING, msg, JavaStatusContext.create(methods[i]), Corext.getPluginId(), RefactoringStatusCodes.MAIN_METHOD); // } // } // return result; // } //---- New method name checking ------------------------------------------------------------- /** * Checks if the new method is already used in the given type. * @param type * @param methodName * @param parameters * @return the status */ public static RefactoringStatus checkMethodInType(ITypeBinding type, String methodName, ITypeBinding[] parameters) { RefactoringStatus result= new RefactoringStatus(); if (methodName.equals(type.getName())) result.addWarning(RefactoringCoreMessages.Checks_methodName_constructor); IFunctionBinding method= org.eclipse.wst.jsdt.internal.corext.dom.Bindings.findMethodInType(type, methodName, parameters); if (method != null) result.addError(Messages.format(RefactoringCoreMessages.Checks_methodName_exists, new Object[] {methodName, type.getName()}), JavaStatusContext.create(method)); return result; } /** * Checks if the new method somehow conflicts with an already existing method in * the hierarchy. The following checks are done: * <ul> * <li> if the new method overrides a method defined in the given type or in one of its * super classes. </li> * </ul> * @param type * @param methodName * @param returnType * @param parameters * @return the status */ public static RefactoringStatus checkMethodInHierarchy(ITypeBinding type, String methodName, ITypeBinding returnType, ITypeBinding[] parameters) { RefactoringStatus result= new RefactoringStatus(); IFunctionBinding method= Bindings.findMethodInHierarchy(type, methodName, parameters); if (method != null) { boolean returnTypeClash= false; ITypeBinding methodReturnType= method.getReturnType(); if (returnType != null && methodReturnType != null) { String returnTypeKey= returnType.getKey(); String methodReturnTypeKey= methodReturnType.getKey(); if (returnTypeKey == null && methodReturnTypeKey == null) { returnTypeClash= returnType != methodReturnType; } else if (returnTypeKey != null && methodReturnTypeKey != null) { returnTypeClash= !returnTypeKey.equals(methodReturnTypeKey); } } ITypeBinding dc= method.getDeclaringClass(); if (returnTypeClash) { result.addError(Messages.format(RefactoringCoreMessages.Checks_methodName_returnTypeClash, new Object[] {methodName, dc.getName()}), JavaStatusContext.create(method)); } else { result.addError(Messages.format(RefactoringCoreMessages.Checks_methodName_overrides, new Object[] {methodName, dc.getName()}), JavaStatusContext.create(method)); } } return result; } //---- Selection checks -------------------------------------------------------------------- public static boolean isExtractableExpression(ASTNode[] selectedNodes, ASTNode coveringNode) { ASTNode node= coveringNode; if (selectedNodes != null && selectedNodes.length == 1) node= selectedNodes[0]; return isExtractableExpression(node); } public static boolean isExtractableExpression(ASTNode node) { if (!(node instanceof Expression)) return false; if (node instanceof Name) { IBinding binding= ((Name) node).resolveBinding(); return !(binding instanceof ITypeBinding); } return true; } public static boolean isInsideJavadoc(ASTNode node) { do { if (node.getNodeType() == ASTNode.JSDOC) return true; node= node.getParent(); } while (node != null); return false; } /** * Returns a fatal error in case the name is empty. In all other cases, an * error based on the given status is returned. * * @param name a name * @param status a status * @return RefactoringStatus based on the given status or the name, if * empty. */ public static RefactoringStatus checkName(String name, IStatus status) { RefactoringStatus result= new RefactoringStatus(); if ("".equals(name)) //$NON-NLS-1$ return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.Checks_Choose_name); if (status.isOK()) return result; switch (status.getSeverity()){ case IStatus.ERROR: return RefactoringStatus.createFatalErrorStatus(status.getMessage()); case IStatus.WARNING: return RefactoringStatus.createWarningStatus(status.getMessage()); case IStatus.INFO: return RefactoringStatus.createInfoStatus(status.getMessage()); default: //no nothing return new RefactoringStatus(); } } /** * Finds a method in a type * This searches for a method with the same name and signature. Parameter types are only * compared by the simple name, no resolving for the fully qualified type name is done * @param name * @param parameterCount * @param isConstructor * @param type * @return The first found method or null, if nothing found * @throws JavaScriptModelException */ public static IFunction findMethod(String name, int parameterCount, boolean isConstructor, IType type) throws JavaScriptModelException { return findMethod(name, parameterCount, isConstructor, type.getFunctions()); } /** * Finds a method in a type. * Searches for a method with the same name and the same parameter count. * Parameter types are <b>not</b> compared. * @param method * @param type * @return The first found method or null, if nothing found * @throws JavaScriptModelException */ public static IFunction findMethod(IFunction method, IType type) throws JavaScriptModelException { return findMethod(method.getElementName(), method.getParameterTypes().length, method.isConstructor(), type.getFunctions()); } /** * Finds a method in an array of methods. * Searches for a method with the same name and the same parameter count. * Parameter types are <b>not</b> compared. * @param method * @param methods * @return The first found method or null, if nothing found * @throws JavaScriptModelException */ public static IFunction findMethod(IFunction method, IFunction[] methods) throws JavaScriptModelException { return findMethod(method.getElementName(), method.getParameterTypes().length, method.isConstructor(), methods); } public static IFunction findMethod(String name, int parameters, boolean isConstructor, IFunction[] methods) throws JavaScriptModelException { for (int i= methods.length-1; i >= 0; i--) { IFunction curr= methods[i]; if (name.equals(curr.getElementName())) { if (isConstructor == curr.isConstructor()) { if (parameters == curr.getParameterTypes().length) { return curr; } } } } return null; } /** * Finds a method in a type. * This searches for a method with the same name and signature. Parameter types are only * compared by the simple name, no resolving for the fully qualified type name is done * @param method * @param type * @return The first found method or null, if nothing found * @throws JavaScriptModelException */ public static IFunction findSimilarMethod(IFunction method, IType type) throws JavaScriptModelException { return findSimilarMethod(method, type.getFunctions()); } /** * Finds a method in an array of methods. * This searches for a method with the same name and signature. Parameter types are only * compared by the simple name, no resolving for the fully qualified type name is done * @param method * @param methods * @return The first found method or null, if nothing found * @throws JavaScriptModelException */ public static IFunction findSimilarMethod(IFunction method, IFunction[] methods) throws JavaScriptModelException { boolean isConstructor= method.isConstructor(); for (int i= 0; i < methods.length; i++) { IFunction otherMethod= methods[i]; if (otherMethod.isConstructor() == isConstructor && method.isSimilar(otherMethod)) return otherMethod; } return null; } /* * Compare two parameter signatures */ public static boolean compareParamTypes(String[] paramTypes1, String[] paramTypes2) { if (paramTypes1.length == paramTypes2.length) { int i= 0; while (i < paramTypes1.length) { String t1= Signature.getSimpleName(Signature.toString(paramTypes1[i])); String t2= Signature.getSimpleName(Signature.toString(paramTypes2[i])); if (!t1.equals(t2)) { return false; } i++; } return true; } return false; } //--------------------- public static RefactoringStatus checkIfCuBroken(IMember member) throws JavaScriptModelException{ IJavaScriptUnit cu= (IJavaScriptUnit)JavaScriptCore.create(member.getJavaScriptUnit().getResource()); if (cu == null) return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.Checks_cu_not_created); else if (! cu.isStructureKnown()) return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.Checks_cu_not_parsed); return new RefactoringStatus(); } /** * From SearchResultGroup[] passed as the parameter * this method removes all those that correspond to a non-parsable IJavaScriptUnit * and returns it as a result. * @param grouped the array of search result groups from which non parsable compilation * units are to be removed. * @param status a refactoring status to collect errors and problems * @return the array of search result groups * @throws JavaScriptModelException */ public static SearchResultGroup[] excludeCompilationUnits(SearchResultGroup[] grouped, RefactoringStatus status) throws JavaScriptModelException{ List result= new ArrayList(); boolean wasEmpty= grouped.length == 0; for (int i= 0; i < grouped.length; i++){ IResource resource= grouped[i].getResource(); IJavaScriptElement element= JavaScriptCore.create(resource); if (! (element instanceof IJavaScriptUnit)) continue; //XXX this is a workaround for a jcore feature that shows errors in cus only when you get the original element IJavaScriptUnit cu= (IJavaScriptUnit)JavaScriptCore.create(resource); if (! cu.isStructureKnown()){ String path= Checks.getFullPath(cu); status.addError(Messages.format(RefactoringCoreMessages.Checks_cannot_be_parsed, path)); continue; //removed, go to the next one } result.add(grouped[i]); } if ((!wasEmpty) && result.isEmpty()) status.addFatalError(RefactoringCoreMessages.Checks_all_excluded); return (SearchResultGroup[])result.toArray(new SearchResultGroup[result.size()]); } private static final String getFullPath(IJavaScriptUnit cu) { Assert.isTrue(cu.exists()); return cu.getResource().getFullPath().toString(); } public static RefactoringStatus checkCompileErrorsInAffectedFiles(SearchResultGroup[] grouped) throws JavaScriptModelException { RefactoringStatus result= new RefactoringStatus(); for (int i= 0; i < grouped.length; i++) checkCompileErrorsInAffectedFile(result, grouped[i].getResource()); return result; } public static void checkCompileErrorsInAffectedFile(RefactoringStatus result, IResource resource) throws JavaScriptModelException { if (hasCompileErrors(resource)) result.addWarning(Messages.format(RefactoringCoreMessages.Checks_cu_has_compile_errors, resource.getFullPath().makeRelative())); } public static RefactoringStatus checkCompileErrorsInAffectedFiles(SearchResultGroup[] references, IResource declaring) throws JavaScriptModelException { RefactoringStatus result= new RefactoringStatus(); for (int i= 0; i < references.length; i++){ IResource resource= references[i].getResource(); if (resource.equals(declaring)) declaring= null; checkCompileErrorsInAffectedFile(result, resource); } if (declaring != null) checkCompileErrorsInAffectedFile(result, declaring); return result; } private static boolean hasCompileErrors(IResource resource) throws JavaScriptModelException { try { IMarker[] problemMarkers= resource.findMarkers(IJavaScriptModelMarker.JAVASCRIPT_MODEL_PROBLEM_MARKER, true, IResource.DEPTH_INFINITE); for (int i= 0; i < problemMarkers.length; i++) { if (problemMarkers[i].getAttribute(IMarker.SEVERITY, -1) == IMarker.SEVERITY_ERROR) return true; } return false; } catch (JavaScriptModelException e){ throw e; } catch (CoreException e){ throw new JavaScriptModelException(e); } } //------ public static boolean isReadOnly(Object element) throws JavaScriptModelException{ if (element instanceof IResource) return isReadOnly((IResource)element); if (element instanceof IJavaScriptElement) { if ((element instanceof IPackageFragmentRoot) && isClasspathDelete((IPackageFragmentRoot)element)) return false; return isReadOnly(((IJavaScriptElement)element).getResource()); } Assert.isTrue(false, "not expected to get here"); //$NON-NLS-1$ return false; } public static boolean isReadOnly(IResource res) throws JavaScriptModelException { ResourceAttributes attributes= res.getResourceAttributes(); if (attributes != null && attributes.isReadOnly()) return true; if (! (res instanceof IContainer)) return false; IContainer container= (IContainer)res; try { IResource[] children= container.members(); for (int i= 0; i < children.length; i++) { if (isReadOnly(children[i])) return true; } return false; } catch (JavaScriptModelException e){ throw e; } catch (CoreException e) { throw new JavaScriptModelException(e); } } public static boolean isClasspathDelete(IPackageFragmentRoot pkgRoot) { IResource res= pkgRoot.getResource(); if (res == null) return true; IProject definingProject= res.getProject(); if (res.getParent() != null && pkgRoot.isArchive() && ! res.getParent().equals(definingProject)) return true; IProject occurringProject= pkgRoot.getJavaScriptProject().getProject(); return !definingProject.equals(occurringProject); } //-------- validateEdit checks ---- public static RefactoringStatus validateModifiesFiles(IFile[] filesToModify, Object context) { RefactoringStatus result= new RefactoringStatus(); IStatus status= Resources.checkInSync(filesToModify); if (!status.isOK()) result.merge(RefactoringStatus.create(status)); status= Resources.makeCommittable(filesToModify, context); if (!status.isOK()) { result.merge(RefactoringStatus.create(status)); if (!result.hasFatalError()) { result.addFatalError(RefactoringCoreMessages.Checks_validateEdit); } } return result; } public static RefactoringStatus validateEdit(IJavaScriptUnit unit, Object context) { IResource resource= unit.getPrimary().getResource(); RefactoringStatus result= new RefactoringStatus(); if (resource == null) return result; IStatus status= Resources.checkInSync(resource); if (!status.isOK()) result.merge(RefactoringStatus.create(status)); status= Resources.makeCommittable(resource, context); if (!status.isOK()) { result.merge(RefactoringStatus.create(status)); if (!result.hasFatalError()) { result.addFatalError(RefactoringCoreMessages.Checks_validateEdit); } } return result; } /** * Checks whether it is possible to modify the given <code>IJavaScriptElement</code>. * The <code>IJavaScriptElement</code> must exist and be non read-only to be modifiable. * Moreover, if it is a <code>IMember</code> it must not be binary. * The returned <code>RefactoringStatus</code> has <code>ERROR</code> severity if * it is not possible to modify the element. * @param javaElement * @return the status * @throws JavaScriptModelException * * @see IJavaScriptElement#exists * @see IJavaScriptElement#isReadOnly * @see IMember#isBinary * @see RefactoringStatus */ public static RefactoringStatus checkAvailability(IJavaScriptElement javaElement) throws JavaScriptModelException{ RefactoringStatus result= new RefactoringStatus(); if (! javaElement.exists()) result.addFatalError(Messages.format(RefactoringCoreMessages.Refactoring_not_in_model, javaElement.getElementName())); if (javaElement.isReadOnly()) result.addFatalError(Messages.format(RefactoringCoreMessages.Refactoring_read_only, javaElement.getElementName())); if (javaElement.exists() && !javaElement.isStructureKnown()) result.addFatalError(Messages.format(RefactoringCoreMessages.Refactoring_unknown_structure, javaElement.getElementName())); if (javaElement instanceof IMember && ((IMember)javaElement).isBinary()) result.addFatalError(Messages.format(RefactoringCoreMessages.Refactoring_binary, javaElement.getElementName())); return result; } public static boolean isAvailable(IJavaScriptElement javaElement) throws JavaScriptModelException { if (javaElement == null) return false; if (! javaElement.exists()) return false; if (javaElement.isReadOnly()) return false; // work around for https://bugs.eclipse.org/bugs/show_bug.cgi?id=48422 // the Java project is now cheating regarding its children so we shouldn't // call isStructureKnown if the project isn't open. // see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=52474 if (!(javaElement instanceof IJavaScriptProject) && !(javaElement instanceof ILocalVariable) && !javaElement.isStructureKnown()) return false; if (javaElement instanceof IMember && ((IMember)javaElement).isBinary()) return false; return true; } public static IType findTypeInPackage(IPackageFragment pack, String name) throws JavaScriptModelException { Assert.isTrue(pack.exists()); Assert.isTrue(!pack.isReadOnly()); /* IJavaScriptUnit.getType expects simple name*/ if (name.indexOf(".") != -1) //$NON-NLS-1$ name= name.substring(0, name.indexOf(".")); //$NON-NLS-1$ IJavaScriptUnit[] cus= pack.getJavaScriptUnits(); for (int i= 0; i < cus.length; i++){ if (cus[i].getType(name).exists()) return cus[i].getType(name); } return null; } public static RefactoringStatus checkTempName(String newName) { RefactoringStatus result= Checks.checkIdentifier(newName); if (result.hasFatalError()) return result; if (! Checks.startsWithLowerCase(newName)) result.addWarning(RefactoringCoreMessages.ExtractTempRefactoring_convention); return result; } public static RefactoringStatus checkEnumConstantName(String newName) { RefactoringStatus result= Checks.checkFieldName(newName); if (result.hasFatalError()) return result; for (int i= 0; i < newName.length(); i++) { char c= newName.charAt(i); if (Character.isLetter(c) && !Character.isUpperCase(c)) { result.addWarning(RefactoringCoreMessages.RenameEnumConstRefactoring_convention); break; } } return result; } public static RefactoringStatus checkConstantName(String newName) { RefactoringStatus result= Checks.checkFieldName(newName); if (result.hasFatalError()) return result; for (int i= 0; i < newName.length(); i++) { char c= newName.charAt(i); if (Character.isLetter(c) && !Character.isUpperCase(c)) { result.addWarning(RefactoringCoreMessages.ExtractConstantRefactoring_convention); break; } } return result; } public static boolean isException(IType iType, IProgressMonitor pm) throws JavaScriptModelException { try{ if (! iType.isClass()) return false; IType[] superTypes= iType.newSupertypeHierarchy(pm).getAllSuperclasses(iType); for (int i= 0; i < superTypes.length; i++) { if ("java.lang.Throwable".equals(superTypes[i].getFullyQualifiedName())) //$NON-NLS-1$ return true; } return false; } finally{ pm.done(); } } /** * @param e * @return int * Checks.IS_RVALUE if e is an rvalue * Checks.NOT_RVALUE_VOID if e is not an rvalue because its type is void * Checks.NOT_RVALUE_MISC if e is not an rvalue for some other reason */ public static int checkExpressionIsRValue(Expression e) { if(e instanceof Name) { if(!(((Name) e).resolveBinding() instanceof IVariableBinding)) { return NOT_RVALUE_MISC; } } ITypeBinding tb= e.resolveTypeBinding(); if (tb == null) return NOT_RVALUE_MISC; else if (tb.getName().equals("void")) //$NON-NLS-1$ return NOT_RVALUE_VOID; return IS_RVALUE; } public static boolean isDeclaredIn(VariableDeclaration tempDeclaration, Class astNodeClass) { ASTNode initializer= ASTNodes.getParent(tempDeclaration, astNodeClass); if (initializer == null) return false; ASTNode anonymous= ASTNodes.getParent(tempDeclaration, AnonymousClassDeclaration.class); if (anonymous == null) return true; // stupid code. Is to find out if the variable declaration isn't a field. if (ASTNodes.isParent(anonymous, initializer)) return false; return true; } }