/*******************************************************************************
 * Copyright (c) 2000, 2020 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.jdt.internal.corext.refactoring;

import java.util.ArrayList;
import java.util.List;

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.core.runtime.Platform;

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.resources.mapping.IResourceChangeDescriptionFactory;

import org.eclipse.ltk.core.refactoring.RefactoringStatus;
import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext;
import org.eclipse.ltk.core.refactoring.participants.ResourceChangeChecker;

import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaModelMarker;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.ILocalVariable;
import org.eclipse.jdt.core.IMember;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.Annotation;
import org.eclipse.jdt.core.dom.AnonymousClassDeclaration;
import org.eclipse.jdt.core.dom.Expression;
import org.eclipse.jdt.core.dom.IBinding;
import org.eclipse.jdt.core.dom.IMethodBinding;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.IVariableBinding;
import org.eclipse.jdt.core.dom.Name;
import org.eclipse.jdt.core.dom.SwitchCase;
import org.eclipse.jdt.core.dom.VariableDeclaration;
import org.eclipse.jdt.core.manipulation.JavaManipulation;

import org.eclipse.jdt.internal.core.manipulation.JavaElementLabelsCore;
import org.eclipse.jdt.internal.core.manipulation.dom.ASTResolving;
import org.eclipse.jdt.internal.core.manipulation.util.BasicElementLabels;
import org.eclipse.jdt.internal.corext.dom.ASTNodes;
import org.eclipse.jdt.internal.corext.dom.Bindings;
import org.eclipse.jdt.internal.corext.refactoring.base.RefactoringStatusCodes;
import org.eclipse.jdt.internal.corext.refactoring.util.JavaElementUtil;
import org.eclipse.jdt.internal.corext.refactoring.util.JavaStatusContext;
import org.eclipse.jdt.internal.corext.util.JavaConventionsUtil;
import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
import org.eclipse.jdt.internal.corext.util.JdtFlags;
import org.eclipse.jdt.internal.corext.util.Messages;
import org.eclipse.jdt.internal.corext.util.Resources;

import org.eclipse.jdt.internal.ui.util.ASTHelper;

/**
 * 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;

	/**
	 * @since 3.6
	 */
	public static final int IS_RVALUE_GUESSED= 3;

	/**
	 * 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(IMethod 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), JavaElementLabelsCore.getElementLabel(method.getDeclaringType(), JavaElementLabelsCore.ALL_FULLY_QUALIFIED) } ));
	}

	/**
	 * Checks if the given name is a valid Java field name.
	 *
	 * @param name the java field name.
	 * @param context an {@link IJavaElement} or <code>null</code>
	 * @return a refactoring status containing the error message if the
	 *  name is not a valid java field name.
	 */
	public static RefactoringStatus checkFieldName(String name, IJavaElement context) {
		return checkName(name, JavaConventionsUtil.validateFieldName(name, context));
	}

	/**
	 * Checks if the given name is a valid Java type parameter name.
	 *
	 * @param name the java type parameter name.
	 * @param context an {@link IJavaElement} or <code>null</code>
	 * @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, IJavaElement context) {
		return checkName(name, JavaConventionsUtil.validateTypeVariableName(name, context));
	}

	/**
	 * Checks if the given name is a valid Java identifier.
	 *
	 * @param name the java identifier.
	 * @param context an {@link IJavaElement} or <code>null</code>
	 * @return a refactoring status containing the error message if the
	 *  name is not a valid java identifier.
	 */
	public static RefactoringStatus checkIdentifier(String name, IJavaElement context) {
		return checkName(name, JavaConventionsUtil.validateIdentifier(name, context));
	}

	/**
	 * Checks if the given name is a valid Java method name.
	 *
	 * @param name the java method name.
	 * @param context an {@link IJavaElement} or <code>null</code>
	 * @return a refactoring status containing the error message if the
	 *  name is not a valid java method name.
	 */
	public static RefactoringStatus checkMethodName(String name, IJavaElement context) {
		RefactoringStatus status= checkName(name, JavaConventionsUtil.validateMethodName(name, context));
		if (status.isOK() && !startsWithLowerCase(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.
	 * @param context an {@link IJavaElement} or <code>null</code>
	 * @return a refactoring status containing the error message if the
	 *  name is not a valid java type name.
	 */
	public static RefactoringStatus checkTypeName(String name, IJavaElement context) {
		//fix for: 1GF5Z0Z: ITPJUI:WINNT - assertion failed after renameType refactoring
		if (name.contains(".")) //$NON-NLS-1$
			return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.Checks_no_dot);
		else
			return checkName(name, JavaConventionsUtil.validateJavaTypeName(name, context));
	}

	/**
	 * Checks if the given name is a valid Java package name.
	 *
	 * @param name the java package name.
	 * @param context an {@link IJavaElement} or <code>null</code>
	 * @return a refactoring status containing the error message if the
	 *  name is not a valid java package name.
	 */
	public static RefactoringStatus checkPackageName(String name, IJavaElement context) {
		return checkName(name, JavaConventionsUtil.validatePackageName(name, context));
	}

	/**
	 * Checks if the given name is a valid compilation unit name.
	 *
	 * @param name the compilation unit name.
	 * @param context an {@link IJavaElement} or <code>null</code>
	 * @return a refactoring status containing the error message if the
	 *  name is not a valid compilation unit name.
	 */
	public static RefactoringStatus checkCompilationUnitName(String name, IJavaElement context) {
		return checkName(name, JavaConventionsUtil.validateCompilationUnitName(name, context));
	}

	/**
	 * Returns OK status if the new name is OK, i.e. when no file with that name exists.
	 * The name of the given CU is not OK.
	 *
	 * @param cu CU to rename
	 * @param newBareName the new name of the CU (without extension)
	 * @return the status: FATAL if the CU already exists, OK if OK
	 */
	public static RefactoringStatus checkCompilationUnitNewName(ICompilationUnit cu, String newBareName) {
		String newCUName= JavaModelUtil.getRenamedCUName(cu, newBareName);
		IPath renamedResourcePath= cu.getParent().getPath().append(newCUName);
		if (resourceExists(renamedResourcePath))
			return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.Checks_cu_name_used, BasicElementLabels.getResourceName(newCUName)));
		else
			return new RefactoringStatus();
	}

	public static boolean startsWithLowerCase(String s){
		if (null == s)
			return false;
		else switch (s) {
		case "": //$NON-NLS-1$
			return false;
		default:
			//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 JavaModelException {
		return type.isAnonymous();
	}

	public static boolean isTopLevelType(IMember member){
		return  member.getElementType() == IJavaElement.TYPE && isTopLevel((IType) member);
	}

	public static boolean isInsideLocalType(IType type) throws JavaModelException {
		while (type != null) {
			if (type.isLocal())
				return true;
			type= type.getDeclaringType();
		}
		return false;
	}

	public static boolean isAlreadyNamed(IJavaElement element, String name){
		return name.equals(element.getElementName());
	}

	//-------------- main and native method checks ------------------
	public static RefactoringStatus checkForMainAndNativeMethods(ICompilationUnit cu) throws JavaModelException {
		return checkForMainAndNativeMethods(cu.getTypes());
	}

	public static RefactoringStatus checkForMainAndNativeMethods(IType[] types) throws JavaModelException {
		RefactoringStatus result= new RefactoringStatus();
		for (IType type : types) {
			result.merge(checkForMainAndNativeMethods(type));
		}
		return result;
	}

	public static RefactoringStatus checkForMainAndNativeMethods(IType type) throws JavaModelException {
		RefactoringStatus result= new RefactoringStatus();
		result.merge(checkForMainAndNativeMethods(type.getMethods()));
		result.merge(checkForMainAndNativeMethods(type.getTypes()));
		return result;
	}

	private static RefactoringStatus checkForMainAndNativeMethods(IMethod[] methods) throws JavaModelException {
		RefactoringStatus result= new RefactoringStatus();
		for (IMethod method : methods) {
			if (JdtFlags.isNative(method)) {
				String typeName= JavaElementLabelsCore.getElementLabel(method.getDeclaringType(), JavaElementLabelsCore.ALL_FULLY_QUALIFIED);
				String methodName= JavaElementLabelsCore.getElementLabel(method, JavaElementLabelsCore.ALL_DEFAULT);
				String msg= Messages.format(RefactoringCoreMessages.Checks_method_native,
					new String[]{typeName, methodName, "UnsatisfiedLinkError"});//$NON-NLS-1$
				result.addEntry(RefactoringStatus.ERROR, msg, JavaStatusContext.create(method), JavaManipulation.getPreferenceNodeId(), RefactoringStatusCodes.NATIVE_METHOD);
			}
			if (method.isMainMethod()) {
				String msg= Messages.format(RefactoringCoreMessages.Checks_has_main, JavaElementLabelsCore.getElementLabel(method.getDeclaringType(), JavaElementLabelsCore.ALL_FULLY_QUALIFIED));
				result.addEntry(RefactoringStatus.WARNING, msg, JavaStatusContext.create(method), JavaManipulation.getPreferenceNodeId(), 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();
		IMethodBinding method= org.eclipse.jdt.internal.corext.dom.Bindings.findMethodInType(type, methodName, parameters);
		if (method != null) {
			if (method.isConstructor()) {
				result.addWarning(Messages.format(RefactoringCoreMessages.Checks_methodName_constructor,
						new Object[] { BasicElementLabels.getJavaElementName(type.getName()) }));
			} else {
				result.addError(Messages.format(RefactoringCoreMessages.Checks_methodName_exists,
						new Object[] { BasicElementLabels.getJavaElementName(methodName), BasicElementLabels.getJavaElementName(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();
		IMethodBinding 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[] {BasicElementLabels.getJavaElementName(methodName), BasicElementLabels.getJavaElementName(dc.getName())}),
					JavaStatusContext.create(method));
			} else {
				if (method.isConstructor()) {
					result.addWarning(Messages.format(RefactoringCoreMessages.Checks_methodName_constructor,
							new Object[] { BasicElementLabels.getJavaElementName(dc.getName()) }));
				} else {
					result.addError(Messages.format(RefactoringCoreMessages.Checks_methodName_overrides,
							new Object[] { BasicElementLabels.getJavaElementName(methodName), BasicElementLabels.getJavaElementName(dc.getName()) }),
							JavaStatusContext.create(method));
				}
			}
		}
		return result;
	}

	//---- Selection checks --------------------------------------------------------------------

	public static boolean isExtractableExpression(ASTNode[] selectedNodes, ASTNode coveringNode) {
		ASTNode node= coveringNode;
		if (isEnumCase(node))
			return false;
		if (selectedNodes != null && selectedNodes.length == 1)
			node= selectedNodes[0];
		return isExtractableExpression(node);
	}

	public static boolean isEnumCase(ASTNode node) {
		if (node instanceof SwitchCase) {
			final SwitchCase caze= (SwitchCase) node;
			if (ASTHelper.isSwitchCaseExpressionsSupportedInAST(node.getAST())) {
				List<Expression> expressions= caze.expressions();
				boolean isEnumConst= true;
				for (Expression expression : expressions) {
					isEnumConst= isEnumConst && isEnumConst(expression);
				}
				return isEnumConst;
			} else {
				Expression expression= caze.getExpression();
				return isEnumConst(expression);
			}
		}
		return false;
	}

	private static boolean isEnumConst(final Expression expression) {
		if (expression instanceof Name) {
			final Name name= (Name) expression;
			final IBinding binding= name.resolveBinding();
			if (binding instanceof IVariableBinding) {
				IVariableBinding variableBinding= (IVariableBinding) binding;
				return variableBinding.isEnumConstant();
			}
		}
		return false;
	}

	public static boolean isExtractableExpression(ASTNode node) {
		if (!(node instanceof Expression))
			return false;
		if (node instanceof Name) {
			IBinding binding= ((Name) node).resolveBinding();
			return binding == null || binding instanceof IVariableBinding;
		}
		return true;
	}

	public static boolean isInsideJavadoc(ASTNode node) {
		do {
			if (node.getNodeType() == ASTNode.JAVADOC)
				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 JavaModelException
	 */
	public static IMethod findMethod(String name, int parameterCount, boolean isConstructor, IType type) throws JavaModelException {
		return findMethod(name, parameterCount, isConstructor, type.getMethods());
	}

	/**
	 * 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 JavaModelException
	 */
	public static IMethod findMethod(IMethod method, IType type) throws JavaModelException {
		return findMethod(method.getElementName(), method.getParameterTypes().length, method.isConstructor(), type.getMethods());
	}

	/**
	 * 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 JavaModelException
	 */
	public static IMethod findMethod(IMethod method, IMethod[] methods) throws JavaModelException {
		return findMethod(method.getElementName(), method.getParameterTypes().length, method.isConstructor(), methods);
	}

	public static IMethod findMethod(String name, int parameters, boolean isConstructor, IMethod[] methods) throws JavaModelException {
		for (int i= methods.length-1; i >= 0; i--) {
			IMethod 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 JavaModelException
	 */
	public static IMethod findSimilarMethod(IMethod method, IType type) throws JavaModelException {
		return findSimilarMethod(method, type.getMethods());
	}

	/**
	 * 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 JavaModelException
	 */
	public static IMethod findSimilarMethod(IMethod method, IMethod[] methods) throws JavaModelException {
		boolean isConstructor= method.isConstructor();
		for (IMethod otherMethod : methods) {
			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 JavaModelException{
		ICompilationUnit cu= (ICompilationUnit)JavaCore.create(member.getCompilationUnit().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 ICompilationUnit
	 * 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 JavaModelException
	 */
	public static SearchResultGroup[] excludeCompilationUnits(SearchResultGroup[] grouped, RefactoringStatus status) throws JavaModelException{
		List<SearchResultGroup> result= new ArrayList<>();
		boolean wasEmpty= grouped.length == 0;
		for (SearchResultGroup g : grouped) {
			IResource resource= g.getResource();
			IJavaElement element= JavaCore.create(resource);
			if (! (element instanceof ICompilationUnit))
				continue;
			//XXX this is a workaround 	for a jcore feature that shows errors in cus only when you get the original element
			ICompilationUnit cu= (ICompilationUnit)JavaCore.create(resource);
			if (! cu.isStructureKnown()){
				status.addError(Messages.format(RefactoringCoreMessages.Checks_cannot_be_parsed, BasicElementLabels.getPathLabel(cu.getPath(), false)));
				continue; //removed, go to the next one
			}
			result.add(g);
		}

		if ((!wasEmpty) && result.isEmpty())
			status.addFatalError(RefactoringCoreMessages.Checks_all_excluded);

		return result.toArray(new SearchResultGroup[result.size()]);
	}

	public static RefactoringStatus checkCompileErrorsInAffectedFiles(SearchResultGroup[] grouped) throws JavaModelException {
		RefactoringStatus result= new RefactoringStatus();
		for (SearchResultGroup g : grouped) {
			checkCompileErrorsInAffectedFile(result, g.getResource());
		}
		return result;
	}

	public static void checkCompileErrorsInAffectedFile(RefactoringStatus result, IResource resource) throws JavaModelException {
		if (hasCompileErrors(resource))
			result.addWarning(Messages.format(RefactoringCoreMessages.Checks_cu_has_compile_errors, BasicElementLabels.getPathLabel(resource.getFullPath(), false)));
	}

	public static RefactoringStatus checkCompileErrorsInAffectedFiles(SearchResultGroup[] references, IResource declaring) throws JavaModelException {
		RefactoringStatus result= new RefactoringStatus();
		for (SearchResultGroup reference : references) {
			IResource resource= reference.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 JavaModelException {
		try {
			for (IMarker problemMarker : resource.findMarkers(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER, true, IResource.DEPTH_INFINITE)) {
				if (problemMarker.getAttribute(IMarker.SEVERITY, -1) == IMarker.SEVERITY_ERROR) {
					return true;
				}
			}
			return false;
		} catch (JavaModelException e){
			throw e;
		} catch (CoreException e){
			throw new JavaModelException(e);
		}
	}

	//------
	public static boolean isReadOnly(Object element) throws JavaModelException{
		if (element instanceof IResource)
			return isReadOnly((IResource)element);

		if (element instanceof IJavaElement) {
			if ((element instanceof IPackageFragmentRoot) && isClasspathDelete((IPackageFragmentRoot)element))
				return false;
			return isReadOnly(((IJavaElement)element).getResource());
		}

		Assert.isTrue(false, "not expected to get here");	 //$NON-NLS-1$
		return false;
	}

	public static boolean isReadOnly(IResource res) throws JavaModelException {
		ResourceAttributes attributes= res.getResourceAttributes();
		if (attributes != null && attributes.isReadOnly())
			return true;

		if (! (res instanceof IContainer))
			return false;

		IContainer container= (IContainer)res;
		try {
			for (IResource child : container.members()) {
				if (isReadOnly(child)) {
					return true;
				}
			}
			return false;
		} catch (JavaModelException e){
			throw e;
		} catch (CoreException e) {
			throw new JavaModelException(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.getJavaProject().getProject();
		return !definingProject.equals(occurringProject);
	}

	//-------- validateEdit checks ----

	public static RefactoringStatus validateModifiesFiles(IFile[] filesToModify, Object context, IProgressMonitor pm) throws CoreException {
		RefactoringStatus result= new RefactoringStatus();
		IStatus status= Resources.checkInSync(filesToModify);
		if (!status.isOK()) {
			boolean autoRefresh= Platform.getPreferencesService().getBoolean(ResourcesPlugin.PI_RESOURCES, ResourcesPlugin.PREF_LIGHTWEIGHT_AUTO_REFRESH, false, null);
			if (autoRefresh) {
				for (IFile resource : filesToModify) {
					resource.refreshLocal(IResource.DEPTH_INFINITE, pm);
				}
				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 void addModifiedFilesToChecker(IFile[] filesToModify, CheckConditionsContext context) {
		ResourceChangeChecker checker= context.getChecker(ResourceChangeChecker.class);
		IResourceChangeDescriptionFactory deltaFactory= checker.getDeltaFactory();

		for (IFile file : filesToModify) {
			deltaFactory.change(file);
		}
	}


	public static RefactoringStatus validateEdit(ICompilationUnit unit, Object context, IProgressMonitor pm) throws CoreException {
		IResource resource= unit.getPrimary().getResource();
		RefactoringStatus result= new RefactoringStatus();
		if (resource == null)
			return result;
		IStatus status= Resources.checkInSync(resource);
		if (!status.isOK()) {
			boolean autoRefresh= Platform.getPreferencesService().getBoolean(ResourcesPlugin.PI_RESOURCES, ResourcesPlugin.PREF_LIGHTWEIGHT_AUTO_REFRESH, false, null);
			if (autoRefresh) {
				resource.refreshLocal(IResource.DEPTH_INFINITE, pm);
				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>IJavaElement</code>.
	 * The <code>IJavaElement</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 JavaModelException
	 *
	 * @see IJavaElement#exists
	 * @see IJavaElement#isReadOnly
	 * @see IMember#isBinary
	 * @see RefactoringStatus
	 */
	public static RefactoringStatus checkAvailability(IJavaElement javaElement) throws JavaModelException{
		RefactoringStatus result= new RefactoringStatus();
		if (! javaElement.exists())
			result.addFatalError(Messages.format(RefactoringCoreMessages.Refactoring_not_in_model, getJavaElementName(javaElement)));
		if (javaElement.isReadOnly())
			result.addFatalError(Messages.format(RefactoringCoreMessages.Refactoring_read_only, getJavaElementName(javaElement)));
		if (javaElement.exists() && !javaElement.isStructureKnown())
			result.addFatalError(Messages.format(RefactoringCoreMessages.Refactoring_unknown_structure, getJavaElementName(javaElement)));
		if (javaElement instanceof IMember && ((IMember)javaElement).isBinary())
			result.addFatalError(Messages.format(RefactoringCoreMessages.Refactoring_binary, getJavaElementName(javaElement)));
		return result;
	}

	private static String getJavaElementName(IJavaElement element) {
		return JavaElementLabelsCore.getElementLabel(element, JavaElementLabelsCore.ALL_DEFAULT);
	}

	public static boolean isAvailable(IJavaElement javaElement) throws JavaModelException {
		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 IJavaProject) && !(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 elementName) throws JavaModelException {
		Assert.isTrue(pack.exists());
		Assert.isTrue(!pack.isReadOnly());

		String packageName= pack.getElementName();
		elementName= packageName.length() > 0 ? packageName + '.' + elementName : elementName;

		return pack.getJavaProject().findType(elementName, (IProgressMonitor) null);
	}

	public static RefactoringStatus checkTempName(String newName, IJavaElement context) {
		RefactoringStatus result= Checks.checkIdentifier(newName, context);
		if (result.hasFatalError())
			return result;
		if (! Checks.startsWithLowerCase(newName))
			result.addWarning(RefactoringCoreMessages.ExtractTempRefactoring_convention);
		return result;
	}

	public static RefactoringStatus checkEnumConstantName(String newName, IJavaElement context) {
		RefactoringStatus result= Checks.checkFieldName(newName, context);
		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, IJavaElement context) {
		RefactoringStatus result= Checks.checkFieldName(newName, context);
		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 JavaModelException {
		try{
			if (! iType.isClass())
				return false;
			IType[] superTypes= iType.newSupertypeHierarchy(pm).getAllSupertypes(iType);
			for (IType superType : superTypes) {
				if ("java.lang.Throwable".equals(superType.getFullyQualifiedName())) { //$NON-NLS-1$
					return true;
				}
			}
			return false;
		} finally{
			pm.done();
		}
	}

	/**
	 * @param e
	 * @return int
	 *          Checks.IS_RVALUE			if e is an rvalue
	 *          Checks.IS_RVALUE_GUESSED	if e is guessed as 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;
			}
		}
		if (e instanceof Annotation)
			return NOT_RVALUE_MISC;


		ITypeBinding tb= e.resolveTypeBinding();
		boolean guessingRequired= false;
		if (tb == null) {
			guessingRequired= true;
			tb= ASTResolving.guessBindingForReference(e);
		}
		if (tb == null)
			return NOT_RVALUE_MISC;
		else if ("void".equals(tb.getName())) //$NON-NLS-1$
			return NOT_RVALUE_VOID;

		return guessingRequired ? IS_RVALUE_GUESSED : IS_RVALUE;
	}

	public static boolean isDeclaredIn(VariableDeclaration tempDeclaration, Class<? extends ASTNode> astNodeClass) {
		ASTNode initializer= ASTNodes.getParent(tempDeclaration, astNodeClass);
		if (initializer == null)
			return false;
		AnonymousClassDeclaration 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;
	}
}
