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

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.SubProgressMonitor;

import org.eclipse.core.resources.IFile;

import org.eclipse.text.edits.ReplaceEdit;

import org.eclipse.ltk.core.refactoring.Change;
import org.eclipse.ltk.core.refactoring.GroupCategorySet;
import org.eclipse.ltk.core.refactoring.RefactoringDescriptor;
import org.eclipse.ltk.core.refactoring.RefactoringStatus;
import org.eclipse.ltk.core.refactoring.TextChange;
import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext;
import org.eclipse.ltk.core.refactoring.participants.RenameArguments;

import org.eclipse.jdt.core.Flags;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IMember;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.ITypeHierarchy;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.WorkingCopyOwner;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants;
import org.eclipse.jdt.core.refactoring.IJavaRefactorings;
import org.eclipse.jdt.core.refactoring.descriptors.JavaRefactoringDescriptor;
import org.eclipse.jdt.core.refactoring.descriptors.RenameJavaElementDescriptor;
import org.eclipse.jdt.core.search.IJavaSearchConstants;
import org.eclipse.jdt.core.search.IJavaSearchScope;
import org.eclipse.jdt.core.search.MethodDeclarationMatch;
import org.eclipse.jdt.core.search.SearchEngine;
import org.eclipse.jdt.core.search.SearchMatch;
import org.eclipse.jdt.core.search.SearchParticipant;
import org.eclipse.jdt.core.search.SearchPattern;
import org.eclipse.jdt.core.search.SearchRequestor;

import org.eclipse.jdt.internal.core.manipulation.util.BasicElementLabels;
import org.eclipse.jdt.internal.core.refactoring.descriptors.RefactoringSignatureDescriptorFactory;
import org.eclipse.jdt.internal.corext.refactoring.Checks;
import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptorComment;
import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringArguments;
import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringDescriptorUtil;
import org.eclipse.jdt.internal.corext.refactoring.RefactoringAvailabilityTester;
import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages;
import org.eclipse.jdt.internal.corext.refactoring.RefactoringScopeFactory;
import org.eclipse.jdt.internal.corext.refactoring.RefactoringSearchEngine;
import org.eclipse.jdt.internal.corext.refactoring.SearchResultGroup;
import org.eclipse.jdt.internal.corext.refactoring.base.ReferencesInBinaryContext;
import org.eclipse.jdt.internal.corext.refactoring.changes.DynamicValidationRefactoringChange;
import org.eclipse.jdt.internal.corext.refactoring.changes.TextChangeCompatibility;
import org.eclipse.jdt.internal.corext.refactoring.delegates.DelegateCreator;
import org.eclipse.jdt.internal.corext.refactoring.delegates.DelegateMethodCreator;
import org.eclipse.jdt.internal.corext.refactoring.participants.JavaProcessors;
import org.eclipse.jdt.internal.corext.refactoring.structure.ASTNodeSearchUtil;
import org.eclipse.jdt.internal.corext.refactoring.structure.CompilationUnitRewrite;
import org.eclipse.jdt.internal.corext.refactoring.tagging.IDelegateUpdating;
import org.eclipse.jdt.internal.corext.refactoring.tagging.IReferenceUpdating;
import org.eclipse.jdt.internal.corext.refactoring.util.JavaStatusContext;
import org.eclipse.jdt.internal.corext.refactoring.util.ResourceUtil;
import org.eclipse.jdt.internal.corext.refactoring.util.TextChangeManager;
import org.eclipse.jdt.internal.corext.util.CollectionsUtil;
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.SearchUtils;

import org.eclipse.jdt.ui.JavaElementLabels;
import org.eclipse.jdt.ui.refactoring.IRefactoringProcessorIds;
import org.eclipse.jdt.ui.refactoring.RefactoringSaveHelper;

import org.eclipse.jdt.internal.ui.JavaPlugin;

public abstract class RenameMethodProcessor extends JavaRenameProcessor implements IReferenceUpdating, IDelegateUpdating {

	private static final String ATTRIBUTE_DELEGATE= "delegate"; //$NON-NLS-1$
	private static final String ATTRIBUTE_DEPRECATE= "deprecate"; //$NON-NLS-1$

	private SearchResultGroup[] fOccurrences;
	private boolean fUpdateReferences;
	private IMethod fMethod;
	private Set<IMethod> fMethodsToRename;
	private TextChangeManager fChangeManager;
	private WorkingCopyOwner fWorkingCopyOwner;
	private boolean fIsComposite;
	private GroupCategorySet fCategorySet;
	private boolean fDelegateUpdating;
	private boolean fDelegateDeprecation;
	protected boolean fInitialized= false;

	/**
	 * Creates a new rename method processor.
	 * @param method the method, or <code>null</code> if invoked by scripting
	 */
	protected RenameMethodProcessor(IMethod method) {
		this(method, new TextChangeManager(true), null);
		fIsComposite= false;
	}
	/**
	 * Creates a new rename method processor.
	 * <p>
	 * This constructor is only invoked by <code>RenameTypeProcessor</code>.
	 * </p>
	 *
	 * @param method the method
	 * @param manager the change manager
	 * @param categorySet the group category set
	 */
	protected RenameMethodProcessor(IMethod method, TextChangeManager manager, GroupCategorySet categorySet) {
		initialize(method);
		fChangeManager= manager;
		fCategorySet= categorySet;
		fDelegateUpdating= false;
		fDelegateDeprecation= true;
		fIsComposite= true;
	}

	protected void initialize(IMethod method) {
		assignMethod(method);
		if (!fInitialized) {
			if (method != null)
				setNewElementName(method.getElementName());
			fUpdateReferences= true;
			initializeWorkingCopyOwner();
		}
	}

	protected void initializeWorkingCopyOwner() {
		fWorkingCopyOwner= new WorkingCopyOwner() {/*must subclass*/};
	}

	protected void setData(RenameMethodProcessor other) {
		fUpdateReferences= other.fUpdateReferences;
		setNewElementName(other.getNewElementName());
	}

	@Override
	public String getIdentifier() {
		return IRefactoringProcessorIds.RENAME_METHOD_PROCESSOR;
	}

	@Override
	public boolean isApplicable() throws CoreException {
		return RefactoringAvailabilityTester.isRenameAvailable(fMethod);
	}

	@Override
	public String getProcessorName() {
		return RefactoringCoreMessages.RenameMethodRefactoring_name;
	}

	@Override
	protected String[] getAffectedProjectNatures() throws CoreException {
		return JavaProcessors.computeAffectedNatures(fMethod);
	}

	@Override
	public Object[] getElements() {
		return new Object[] {fMethod};
	}

	@Override
	protected RenameModifications computeRenameModifications() throws CoreException {
		RenameModifications result= new RenameModifications();
		RenameArguments args= new RenameArguments(getNewElementName(), getUpdateReferences());
		for (IMethod method : fMethodsToRename) {
			result.rename(method, args);
		}
		return result;
	}



	@Override
	protected IFile[] getChangedFiles() throws CoreException {
		return ResourceUtil.getFiles(fChangeManager.getAllCompilationUnits());
	}

	@Override
	public int getSaveMode() {
		return RefactoringSaveHelper.SAVE_REFACTORING;
	}

	//---- INameUpdating -------------------------------------

	@Override
	public final String getCurrentElementName(){
		return fMethod.getElementName();
	}

	@Override
	public final RefactoringStatus checkNewElementName(String newName) {
		Assert.isNotNull(newName, "new name"); //$NON-NLS-1$

		RefactoringStatus status= Checks.checkName(newName, JavaConventionsUtil.validateMethodName(newName, fMethod));
		if (status.isOK() && !Checks.startsWithLowerCase(newName))
			status= RefactoringStatus.createWarningStatus(fIsComposite
					? Messages.format(RefactoringCoreMessages.Checks_method_names_lowercase2, new String[] { BasicElementLabels.getJavaElementName(newName), getDeclaringTypeLabel()})
					: RefactoringCoreMessages.Checks_method_names_lowercase);

		if (Checks.isAlreadyNamed(fMethod, newName))
			status.addFatalError(fIsComposite
					? Messages.format(RefactoringCoreMessages.RenameMethodRefactoring_same_name2, new String[] { BasicElementLabels.getJavaElementName(newName), getDeclaringTypeLabel() } )
					: RefactoringCoreMessages.RenameMethodRefactoring_same_name,
					JavaStatusContext.create(fMethod));
		return status;
	}
	private String getDeclaringTypeLabel() {
		return JavaElementLabels.getElementLabel(fMethod.getDeclaringType(), JavaElementLabels.ALL_DEFAULT);
	}

	@Override
	public Object getNewElement() {
		return fMethod.getDeclaringType().getMethod(getNewElementName(), fMethod.getParameterTypes());
	}

	public final IMethod getMethod() {
		return fMethod;
	}

	private void initializeMethodsToRename(IProgressMonitor pm, ReferencesInBinaryContext binaryRefs) throws CoreException {
		if (fMethodsToRename == null) {
			IMethod[] rippleMethods= RippleMethodFinder2.getRelatedMethods(getMethod(), binaryRefs, pm, null);
			fMethodsToRename= new HashSet<>();
			for (IMethod method : rippleMethods) {
				if (!method.isLambdaMethod()) {
					fMethodsToRename.add(method);
				}
			}
		}
	}

	protected void setMethodsToRename(IMethod[] methods) {
		fMethodsToRename= new HashSet<>(Arrays.asList(methods));
	}

	protected Set<IMethod> getMethodsToRename() {
		return fMethodsToRename;
	}

	protected void assignMethod(IMethod method) {
		fMethod= method;
	}

	//---- IReferenceUpdating -----------------------------------

	@Override
	public final void setUpdateReferences(boolean update) {
		fUpdateReferences= update;
	}

	@Override
	public boolean getUpdateReferences() {
		return fUpdateReferences;
	}

	//------------------- IDelegateUpdating ----------------------

	@Override
	public boolean canEnableDelegateUpdating() {
		return true;
	}

	@Override
	public boolean getDelegateUpdating() {
		return fDelegateUpdating;
	}

	@Override
	public void setDelegateUpdating(boolean updating) {
		fDelegateUpdating= updating;
	}

	@Override
	public boolean getDeprecateDelegates() {
		return fDelegateDeprecation;
	}

	@Override
	public void setDeprecateDelegates(boolean deprecate) {
		fDelegateDeprecation= deprecate;
	}

	//----------- preconditions ------------------

	@Override
	public RefactoringStatus checkInitialConditions(IProgressMonitor pm) throws CoreException {
		if (! fMethod.exists()){
			String message= Messages.format(RefactoringCoreMessages.RenameMethodRefactoring_deleted,
								BasicElementLabels.getFileName(fMethod.getCompilationUnit()));
			return RefactoringStatus.createFatalErrorStatus(message);
		}

		RefactoringStatus result= Checks.checkAvailability(fMethod);
		if (result.hasFatalError())
				return result;
		result.merge(Checks.checkIfCuBroken(fMethod));
		if (JdtFlags.isNative(fMethod))
			result.addError(RefactoringCoreMessages.RenameMethodRefactoring_no_native);
		return result;
	}

	@Override
	protected RefactoringStatus doCheckFinalConditions(IProgressMonitor pm, CheckConditionsContext context) throws CoreException {
		try{
			RefactoringStatus result= new RefactoringStatus();
			pm.beginTask("", 9); //$NON-NLS-1$
			// TODO workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=40367
			if (!Checks.isAvailable(fMethod)) {
				result.addFatalError(RefactoringCoreMessages.RenameMethodProcessor_is_binary, JavaStatusContext.create(fMethod));
				return result;
			}
			result.merge(Checks.checkIfCuBroken(fMethod));
			if (result.hasFatalError())
				return result;
			pm.setTaskName(RefactoringCoreMessages.RenameMethodRefactoring_taskName_checkingPreconditions);
			result.merge(checkNewElementName(getNewElementName()));
			if (result.hasFatalError())
				return result;

			boolean mustAnalyzeShadowing;
			IMethod[] newNameMethods= searchForDeclarationsOfClashingMethods(new SubProgressMonitor(pm, 1));
			if (newNameMethods.length == 0) {
				mustAnalyzeShadowing= false;
				pm.worked(1);
			} else {
				IType[] outerTypes= searchForOuterTypesOfReferences(newNameMethods, new SubProgressMonitor(pm, 1));
				if (outerTypes.length > 0) {
					//There exists a reference to a clashing method, where the reference is in a nested type.
					//That nested type could be a type in a ripple method's hierarchy, which could
					//cause the reference to bind to the new ripple method instead of to
					//its old binding (a method of an enclosing scope).
					//-> Getting *more* references than before -> Semantics not preserved.
					//Examples: RenameVirtualMethodInClassTests#testFail39() and #testFail41()
					//TODO: could pass declaringTypes to the RippleMethodFinder and check whether
					//a hierarchy contains one of outerTypes (or an outer type of an outerType, recursively).
					mustAnalyzeShadowing= true;

				} else {
					boolean hasOldRefsInInnerTypes= true;
						//TODO: to implement this optimization:
						//- move search for references to before this check.
						//- collect references in inner types.
						//- for each reference, check for all supertypes and their enclosing types
						//(recursively), whether they declare a rippleMethod
					if (hasOldRefsInInnerTypes) {
						//There exists a reference to a ripple method in a nested type
						//of a type in the hierarchy of any ripple method.
						//When that reference is renamed, and one of the supertypes of the
						//nested type declared a method matching the new name, then
						//the renamed reference will bind to the method in its supertype,
						//since inherited methods bind stronger than methods from enclosing scopes.
						//Getting *less* references than before -> Semantics not preserved.
						//Examples: RenamePrivateMethodTests#testFail2(), RenamePrivateMethodTests#testFail5()
						mustAnalyzeShadowing= true;
					} else {
						mustAnalyzeShadowing= false;
					}
				}
			}

			String binaryRefsDescription= Messages.format(RefactoringCoreMessages.ReferencesInBinaryContext_ref_in_binaries_description , BasicElementLabels.getJavaElementName(getCurrentElementName()));
			ReferencesInBinaryContext binaryRefs= new ReferencesInBinaryContext(binaryRefsDescription);

			initializeMethodsToRename(new SubProgressMonitor(pm, 1), binaryRefs);
			pm.setTaskName(RefactoringCoreMessages.RenameMethodRefactoring_taskName_searchingForReferences);
			fOccurrences= getOccurrences(new SubProgressMonitor(pm, 3), result, binaryRefs);
			binaryRefs.addErrorIfNecessary(result);

			pm.setTaskName(RefactoringCoreMessages.RenameMethodRefactoring_taskName_checkingPreconditions);

			if (fUpdateReferences)
				result.merge(checkRelatedMethods());

			result.merge(analyzeCompilationUnits()); //removes CUs with syntax errors
			pm.worked(1);

			if (result.hasFatalError())
				return result;

			createChanges(new SubProgressMonitor(pm, 1), result);
			if (fUpdateReferences && mustAnalyzeShadowing)
				result.merge(analyzeRenameChanges(new SubProgressMonitor(pm, 1)));
			else
				pm.worked(1);

			return result;
		} finally{
			pm.done();
		}
	}

	private IType[] searchForOuterTypesOfReferences(IMethod[] newNameMethods, IProgressMonitor pm) throws CoreException {
		final Set<IType> outerTypesOfReferences= new HashSet<>();
		SearchPattern pattern= RefactoringSearchEngine.createOrPattern(newNameMethods, IJavaSearchConstants.REFERENCES);
		IJavaSearchScope scope= createRefactoringScope(getMethod());
		SearchRequestor requestor= new SearchRequestor() {
			@Override
			public void acceptSearchMatch(SearchMatch match) throws CoreException {
				Object element= match.getElement();
				if (!(element instanceof IMember))
					return; // e.g. an IImportDeclaration for a static method import
				IMember member= (IMember) element;
				IType declaring= member.getDeclaringType();
				if (declaring == null)
					return;
				IType outer= declaring.getDeclaringType();
				if (outer != null)
					outerTypesOfReferences.add(declaring);
			}
		};
		new SearchEngine().search(pattern, SearchUtils.getDefaultSearchParticipants(),
				scope, requestor, pm);
		return outerTypesOfReferences.toArray(new IType[outerTypesOfReferences.size()]);
	}

	private IMethod[] searchForDeclarationsOfClashingMethods(IProgressMonitor pm) throws CoreException {
		final List<IMethod> results= new ArrayList<>();
		SearchPattern pattern= createNewMethodPattern();
		IJavaSearchScope scope= RefactoringScopeFactory.create(getMethod().getJavaProject());
		SearchRequestor requestor= new SearchRequestor() {
			@Override
			public void acceptSearchMatch(SearchMatch match) throws CoreException {
				Object method= match.getElement();
				if (method instanceof IMethod) // check for bug 90138: [refactoring] [rename] Renaming method throws internal exception
					results.add((IMethod) method);
				else
					JavaPlugin.logErrorMessage("Unexpected element in search match: " + match.toString()); //$NON-NLS-1$
			}
		};
		new SearchEngine().search(pattern, SearchUtils.getDefaultSearchParticipants(), scope, requestor, pm);
		return results.toArray(new IMethod[results.size()]);
	}

	private SearchPattern createNewMethodPattern() {
		StringBuilder stringPattern= new StringBuilder(getNewElementName()).append('(');
		int paramCount= getMethod().getNumberOfParameters();
		for (int i= 0; i < paramCount; i++) {
			if (i > 0)
				stringPattern.append(',');
			stringPattern.append('*');
		}
		stringPattern.append(')');

		return SearchPattern.createPattern(stringPattern.toString(), IJavaSearchConstants.METHOD,
				IJavaSearchConstants.DECLARATIONS, SearchUtils.GENERICS_AGNOSTIC_MATCH_RULE);
	}

	protected final IJavaSearchScope createRefactoringScope() throws CoreException {
		return createRefactoringScope(fMethod);
	}
	//TODO: shouldn't scope take all ripple methods into account?
	protected static final IJavaSearchScope createRefactoringScope(IMethod method) throws CoreException {
		return RefactoringScopeFactory.create(method, true, false);
	}

	protected SearchPattern createOccurrenceSearchPattern() {
		HashSet<IMethod> methods= new HashSet<>(fMethodsToRename);
		methods.add(fMethod);
		IMethod[] ms= methods.toArray(new IMethod[methods.size()]);
		return RefactoringSearchEngine.createOrPattern(ms, IJavaSearchConstants.ALL_OCCURRENCES);
	}

	protected SearchResultGroup[] getOccurrences(){
		return fOccurrences;
	}

	private SearchResultGroup[] getOccurrences(IProgressMonitor pm, RefactoringStatus status, ReferencesInBinaryContext binaryRefs) throws CoreException {
		SearchPattern pattern= createOccurrenceSearchPattern();
		return RefactoringSearchEngine.search(pattern, createRefactoringScope(),
			new MethodOccurenceCollector(getMethod().getElementName(), binaryRefs), pm, status);
	}

	private RefactoringStatus checkRelatedMethods() throws CoreException {
		RefactoringStatus result= new RefactoringStatus();
		for (IMethod method : fMethodsToRename) {
			result.merge(Checks.checkIfConstructorName(method, getNewElementName(), method.getDeclaringType().getElementName()));

			String[] msgData= new String[]{BasicElementLabels.getJavaElementName(method.getElementName()), BasicElementLabels.getJavaElementName(method.getDeclaringType().getFullyQualifiedName('.'))};
			if (! method.exists()){
				result.addFatalError(Messages.format(RefactoringCoreMessages.RenameMethodRefactoring_not_in_model, msgData));
				continue;
			}
			if (method.isBinary())
				result.addFatalError(Messages.format(RefactoringCoreMessages.RenameMethodRefactoring_no_binary, msgData));
			if (method.isReadOnly())
				result.addFatalError(Messages.format(RefactoringCoreMessages.RenameMethodRefactoring_no_read_only, msgData));
			if (JdtFlags.isNative(method))
				result.addError(Messages.format(RefactoringCoreMessages.RenameMethodRefactoring_no_native_1, msgData));
		}
		return result;
	}

	private RefactoringStatus analyzeCompilationUnits() throws CoreException {
		if (fOccurrences.length == 0)
			return null;

		RefactoringStatus result= new RefactoringStatus();
		fOccurrences= Checks.excludeCompilationUnits(fOccurrences, result);
		if (result.hasFatalError())
			return result;

		result.merge(Checks.checkCompileErrorsInAffectedFiles(fOccurrences));

		return result;
	}

	//-------

	private RefactoringStatus analyzeRenameChanges(IProgressMonitor pm) throws CoreException {
		ICompilationUnit[] newDeclarationWCs= null;
		try {
			pm.beginTask("", 4); //$NON-NLS-1$
			RefactoringStatus result= new RefactoringStatus();
			ICompilationUnit[] declarationCUs= getDeclarationCUs();
			newDeclarationWCs= RenameAnalyzeUtil.createNewWorkingCopies(declarationCUs,
					fChangeManager, fWorkingCopyOwner, new SubProgressMonitor(pm, 1));

			IMethod[] wcOldMethods= new IMethod[fMethodsToRename.size()];
			IMethod[] wcNewMethods= new IMethod[fMethodsToRename.size()];
			int i= 0;
			for (Iterator<IMethod> iter= fMethodsToRename.iterator(); iter.hasNext(); i++) {
				IMethod method= iter.next();
				ICompilationUnit newCu= RenameAnalyzeUtil.findWorkingCopyForCu(newDeclarationWCs, method.getCompilationUnit());
				IType typeWc= (IType) JavaModelUtil.findInCompilationUnit(newCu, method.getDeclaringType());
				if (typeWc == null) {
					// should not happen
					i--;
					wcOldMethods= CollectionsUtil.toArray(Arrays.asList(wcOldMethods).subList(0, wcOldMethods.length - 1), IMethod.class);
					wcNewMethods= CollectionsUtil.toArray(Arrays.asList(wcNewMethods).subList(0, wcNewMethods.length - 1), IMethod.class);
					continue;
				}
				wcOldMethods[i]= getMethodInWorkingCopy(method, getCurrentElementName(), typeWc);
				wcNewMethods[i]= getMethodInWorkingCopy(method, getNewElementName(), typeWc);
			}

//			SearchResultGroup[] newOccurrences= findNewOccurrences(newMethods, newDeclarationWCs, new SubProgressMonitor(pm, 3));
			SearchResultGroup[] newOccurrences= batchFindNewOccurrences(wcNewMethods, wcOldMethods, newDeclarationWCs, new SubProgressMonitor(pm, 3), result);

			result.merge(RenameAnalyzeUtil.analyzeRenameChanges2(fChangeManager, fOccurrences, newOccurrences, getNewElementName()));
			return result;
		} finally{
			pm.done();
			if (newDeclarationWCs != null){
				for (ICompilationUnit newDeclarationWC : newDeclarationWCs) {
					newDeclarationWC.discardWorkingCopy();
				}
			}
		}
	}

	//Lower memory footprint than batchFindNewOccurrences. Not used because it is too slow.
	//Final solution is maybe to do searches in chunks of ~ 50 CUs.
//	private SearchResultGroup[] findNewOccurrences(IMethod[] newMethods, ICompilationUnit[] newDeclarationWCs, IProgressMonitor pm) throws CoreException {
//		pm.beginTask("", fOccurrences.length * 2); //$NON-NLS-1$
//
//		SearchPattern refsPattern= RefactoringSearchEngine.createOrPattern(newMethods, IJavaSearchConstants.REFERENCES);
//		SearchParticipant[] searchParticipants= SearchUtils.getDefaultSearchParticipants();
//		IJavaSearchScope scope= RefactoringScopeFactory.create(newMethods);
//		MethodOccurenceCollector requestor= new MethodOccurenceCollector(getNewElementName());
//		SearchEngine searchEngine= new SearchEngine(fWorkingCopyOwner);
//
//		//TODO: should process only references
//		for (int j= 0; j < fOccurrences.length; j++) { //should be getReferences()
//			//cut memory peak by holding only one reference CU at a time in memory
//			ICompilationUnit originalCu= fOccurrences[j].getCompilationUnit();
//			ICompilationUnit newWc= null;
//			try {
//				ICompilationUnit wc= RenameAnalyzeUtil.findWorkingCopyForCu(newDeclarationWCs, originalCu);
//				if (wc == null) {
//					newWc= RenameAnalyzeUtil.createNewWorkingCopy(originalCu, fChangeManager, fWorkingCopyOwner,
//							new SubProgressMonitor(pm, 1));
//				}
//				searchEngine.search(refsPattern, searchParticipants, scope,	requestor, new SubProgressMonitor(pm, 1));
//			} finally {
//				if (newWc != null)
//					newWc.discardWorkingCopy();
//			}
//		}
//		SearchResultGroup[] newResults= RefactoringSearchEngine.groupByResource(requestor.getResults());
//		pm.done();
//		return newResults;
//	}

	private SearchResultGroup[] batchFindNewOccurrences(IMethod[] wcNewMethods, final IMethod[] wcOldMethods, ICompilationUnit[] newDeclarationWCs, IProgressMonitor pm, RefactoringStatus status) throws CoreException {
		pm.beginTask("", 2); //$NON-NLS-1$

		SearchPattern refsPattern= RefactoringSearchEngine.createOrPattern(wcNewMethods, IJavaSearchConstants.REFERENCES);
		SearchParticipant[] searchParticipants= SearchUtils.getDefaultSearchParticipants();
		IJavaSearchScope scope= RefactoringScopeFactory.create(wcNewMethods);

		MethodOccurenceCollector requestor;
		if (getDelegateUpdating()) {
			// There will be two new matches inside the delegate(s) (the invocation
			// and the javadoc) which are OK and must not be reported.
			// Note that except these ocurrences, the delegate bodies are empty
			// (as they were created this way).
			requestor= new MethodOccurenceCollector(getNewElementName()) {
				@Override
				public void acceptSearchMatch(ICompilationUnit unit, SearchMatch match) throws CoreException {
					for (IMethod occurrence : wcOldMethods) {
						if (occurrence.equals(match.getElement())) {
							return;
						}
					}
					super.acceptSearchMatch(unit, match);
				}
			};
		} else
			requestor= new MethodOccurenceCollector(getNewElementName());

		SearchEngine searchEngine= new SearchEngine(fWorkingCopyOwner);

		ArrayList<ICompilationUnit> needWCs= new ArrayList<>();
		HashSet<ICompilationUnit> declaringCUs= new HashSet<>(newDeclarationWCs.length);
		for (ICompilationUnit newDeclarationWC : newDeclarationWCs) {
			declaringCUs.add(newDeclarationWC.getPrimary());
		}
		for (SearchResultGroup occurrence : fOccurrences) {
			ICompilationUnit cu= occurrence.getCompilationUnit();
			if (! declaringCUs.contains(cu))
				needWCs.add(cu);
		}
		ICompilationUnit[] otherWCs= null;
		try {
			otherWCs= RenameAnalyzeUtil.createNewWorkingCopies(
					needWCs.toArray(new ICompilationUnit[needWCs.size()]),
					fChangeManager, fWorkingCopyOwner, new SubProgressMonitor(pm, 1));
			searchEngine.search(refsPattern, searchParticipants, scope,	requestor, new SubProgressMonitor(pm, 1));
		} finally {
			pm.done();
			if (otherWCs != null) {
				for (ICompilationUnit otherWC : otherWCs) {
					otherWC.discardWorkingCopy();
				}
			}
		}
		SearchResultGroup[] newResults= RefactoringSearchEngine.groupByCu(requestor.getResults(), status);
		return newResults;
	}

	private ICompilationUnit[] getDeclarationCUs() {
		Set<ICompilationUnit> cus= new HashSet<>();
		for (IMethod method : fMethodsToRename) {
			cus.add(method.getCompilationUnit());
		}
		return cus.toArray(new ICompilationUnit[cus.size()]);
	}

	private IMethod getMethodInWorkingCopy(IMethod method, String elementName, IType typeWc) {
		String[] paramTypeSignatures= method.getParameterTypes();
		return typeWc.getMethod(elementName, paramTypeSignatures);
	}

	//-------
	private static IMethod[] classesDeclareMethodName(ITypeHierarchy hier, List<IType> classes, IMethod method, String newName)  throws CoreException {
		Set<IMethod> result= new HashSet<>();
		IType type= method.getDeclaringType();
		List<IType> subtypes= Arrays.asList(hier.getAllSubtypes(type));

		int parameterCount= method.getParameterTypes().length;
		boolean isMethodPrivate= JdtFlags.isPrivate(method);

		for (IType clazz : classes) {
			boolean isSubclass= subtypes.contains(clazz);
			for (IMethod m : clazz.getMethods()) {
				IMethod foundMethod= Checks.findMethod(newName, parameterCount, false, new IMethod[]{m});
				if (foundMethod == null)
					continue;
				if (isSubclass
						|| type.equals(clazz)
						|| (!isMethodPrivate && !JdtFlags.isPrivate(m))) {
					result.add(foundMethod);
				}
			}
		}
		return result.toArray(new IMethod[result.size()]);
	}

	final static IMethod[] hierarchyDeclaresMethodName(IProgressMonitor pm, ITypeHierarchy hierarchy, IMethod method, String newName) throws CoreException {
		try {
			Set<IMethod> result= new HashSet<>();
			IType type= method.getDeclaringType();
			IMethod foundMethod= Checks.findMethod(newName, method.getParameterTypes().length, false, type);
			if (foundMethod != null)
				result.add(foundMethod);
			IMethod[] foundInHierarchyClasses= classesDeclareMethodName(hierarchy, Arrays.asList(hierarchy.getAllClasses()), method, newName);
			if (foundInHierarchyClasses != null)
				result.addAll(Arrays.asList(foundInHierarchyClasses));
			IType[] implementingClasses= hierarchy.getImplementingClasses(type);
			IMethod[] foundInImplementingClasses= classesDeclareMethodName(hierarchy, Arrays.asList(implementingClasses), method, newName);
			if (foundInImplementingClasses != null)
				result.addAll(Arrays.asList(foundInImplementingClasses));
			return result.toArray(new IMethod[result.size()]);
		} finally {
			if (pm != null) {
				pm.done();
			}
		}
	}

	@Override
	public Change createChange(IProgressMonitor monitor) throws CoreException {
		try {
			final TextChange[] changes= fChangeManager.getAllChanges();
			final List<TextChange> list= new ArrayList<>(changes.length);
			list.addAll(Arrays.asList(changes));
			String project= null;
			IJavaProject javaProject= fMethod.getJavaProject();
			if (javaProject != null)
				project= javaProject.getElementName();
			int flags= JavaRefactoringDescriptor.JAR_MIGRATION | JavaRefactoringDescriptor.JAR_REFACTORING | RefactoringDescriptor.STRUCTURAL_CHANGE;
			try {
				if (!Flags.isPrivate(fMethod.getFlags()))
					flags|= RefactoringDescriptor.MULTI_CHANGE;
			} catch (JavaModelException exception) {
				JavaPlugin.log(exception);
			}
			final IType declaring= fMethod.getDeclaringType();
			try {
				if (declaring.isAnonymous() || declaring.isLocal())
					flags|= JavaRefactoringDescriptor.JAR_SOURCE_ATTACHMENT;
			} catch (JavaModelException exception) {
				JavaPlugin.log(exception);
			}
			final String description= Messages.format(RefactoringCoreMessages.RenameMethodProcessor_descriptor_description_short, BasicElementLabels.getJavaElementName(fMethod.getElementName()));
			final String header= Messages.format(RefactoringCoreMessages.RenameMethodProcessor_descriptor_description, new String[] { JavaElementLabels.getTextLabel(fMethod, JavaElementLabels.ALL_FULLY_QUALIFIED), BasicElementLabels.getJavaElementName(getNewElementName())});
			final String comment= new JDTRefactoringDescriptorComment(project, this, header).asString();
			final RenameJavaElementDescriptor descriptor= RefactoringSignatureDescriptorFactory.createRenameJavaElementDescriptor(IJavaRefactorings.RENAME_METHOD);
			descriptor.setProject(project);
			descriptor.setDescription(description);
			descriptor.setComment(comment);
			descriptor.setFlags(flags);
			descriptor.setJavaElement(fMethod);
			descriptor.setNewName(getNewElementName());
			descriptor.setUpdateReferences(fUpdateReferences);
			descriptor.setKeepOriginal(fDelegateUpdating);
			descriptor.setDeprecateDelegate(fDelegateDeprecation);
			return new DynamicValidationRefactoringChange(descriptor, RefactoringCoreMessages.RenameMethodProcessor_change_name, list.toArray(new Change[list.size()]));
		} finally {
			monitor.done();
		}
	}

	protected TextChangeManager createChanges(IProgressMonitor pm, RefactoringStatus status) throws CoreException {
		if (!fIsComposite)
			fChangeManager.clear();
		addOccurrences(fChangeManager, pm, status);
		return fChangeManager;
	}

	/**
	 * Add occurrences
	 *
	 * @param manager the text change manager
	 * @param pm the progress monitor
	 * @param status the status
	 * @throws CoreException if change creation failed
	 */
	protected void addOccurrences(TextChangeManager manager, IProgressMonitor pm, RefactoringStatus status) throws CoreException/*thrown in subtype*/{
		pm.beginTask("", fOccurrences.length);				 //$NON-NLS-1$
		for (SearchResultGroup occurrence : fOccurrences) {
			ICompilationUnit cu= occurrence.getCompilationUnit();
			if (cu == null)
				continue;
			// Split matches into declaration and non-declaration matches

			List<SearchMatch> declarationsInThisCu= new ArrayList<>();
			List<SearchMatch> referencesInThisCu= new ArrayList<>();
			for (SearchMatch result : occurrence.getSearchResults()) {
				if (result instanceof MethodDeclarationMatch) {
					declarationsInThisCu.add(result);
				} else {
					referencesInThisCu.add(result);
				}
			}
			// First, handle the declarations
			if (declarationsInThisCu.size() > 0) {

				if (fDelegateUpdating) {
					// Update with delegates
					CompilationUnitRewrite rewrite= new CompilationUnitRewrite(cu);
					rewrite.setResolveBindings(true);

					for (SearchMatch element : declarationsInThisCu) {
						MethodDeclaration method= ASTNodeSearchUtil.getMethodDeclarationNode((IMethod) element.getElement(), rewrite.getRoot());
						DelegateCreator creator= new DelegateMethodCreator();
						creator.setDeclareDeprecated(fDelegateDeprecation);
						creator.setDeclaration(method);
						creator.setSourceRewrite(rewrite);
						creator.setNewElementName(getNewElementName());
						creator.prepareDelegate();
						creator.createEdit();
					}
					// Need to handle all delegates first as this
					// creates a completely new change object.
					TextChange changeForThisCu= rewrite.createChange(true);
					changeForThisCu.setKeepPreviewEdits(true);
					manager.manage(cu, changeForThisCu);
				}

				// Update the normal methods
				for (SearchMatch element : declarationsInThisCu) {
					simpleUpdate(element, cu, manager.get(cu));
				}
			}

			// Second, handle references
			if (fUpdateReferences) {
				for (SearchMatch element : referencesInThisCu) {
					simpleUpdate(element, cu, manager.get(cu));
				}
			}

			pm.worked(1);
			if (pm.isCanceled())
				throw new OperationCanceledException();
		}
		pm.done();
	}

	private void simpleUpdate(SearchMatch element, ICompilationUnit cu, TextChange textChange) {
		String editName= RefactoringCoreMessages.RenameMethodRefactoring_update_occurrence;
		ReplaceEdit replaceEdit= createReplaceEdit(element, cu);
		addTextEdit(textChange, editName, replaceEdit);
	}

	protected final ReplaceEdit createReplaceEdit(SearchMatch searchResult, ICompilationUnit cu) {
		if (searchResult.isImplicit()) { // handle Annotation Element references, see bug 94062
			StringBuilder sb= new StringBuilder(getNewElementName());
			if (JavaCore.INSERT.equals(cu.getJavaProject().getOption(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_ASSIGNMENT_OPERATOR, true)))
				sb.append(' ');
			sb.append('=');
			if (JavaCore.INSERT.equals(cu.getJavaProject().getOption(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_ASSIGNMENT_OPERATOR, true)))
				sb.append(' ');
			return new ReplaceEdit(searchResult.getOffset(), 0, sb.toString());
		} else {
			return new ReplaceEdit(searchResult.getOffset(), searchResult.getLength(), getNewElementName());
		}
	}

	/**
	 * Initializes the refactoring from scripting arguments.
	 * Used by {@link RenameVirtualMethodProcessor} and {@link RenameNonVirtualMethodProcessor}
	 *
	 * @param extended the arguments
	 * @return the resulting status
	 */
	protected final RefactoringStatus initialize(JavaRefactoringArguments extended) {
		fInitialized= true;
		final String handle= extended.getAttribute(JavaRefactoringDescriptorUtil.ATTRIBUTE_INPUT);
		if (handle != null) {
			final IJavaElement element= JavaRefactoringDescriptorUtil.handleToElement(extended.getProject(), handle, false);
			final String refactoring= getProcessorName();
			if (element instanceof IMethod) {
				final IMethod method= (IMethod) element;
				final IType declaring= method.getDeclaringType();
				if (declaring != null && declaring.exists()) {
					final IMethod[] methods= declaring.findMethods(method);
					if (methods != null && methods.length == 1 && methods[0] != null) {
						if (!methods[0].exists())
							return JavaRefactoringDescriptorUtil.createInputFatalStatus(methods[0], refactoring, IJavaRefactorings.RENAME_METHOD);
						assignMethod(methods[0]);
						initializeWorkingCopyOwner();
					} else
						return JavaRefactoringDescriptorUtil.createInputFatalStatus(null, refactoring, IJavaRefactorings.RENAME_METHOD);
				} else
					return JavaRefactoringDescriptorUtil.createInputFatalStatus(element, refactoring, IJavaRefactorings.RENAME_METHOD);
			} else
				return JavaRefactoringDescriptorUtil.createInputFatalStatus(element, refactoring, IJavaRefactorings.RENAME_METHOD);
		} else
			return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JavaRefactoringDescriptorUtil.ATTRIBUTE_INPUT));
		final String name= extended.getAttribute(JavaRefactoringDescriptorUtil.ATTRIBUTE_NAME);
		if (name != null && !"".equals(name)) //$NON-NLS-1$
			setNewElementName(name);
		else
			return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JavaRefactoringDescriptorUtil.ATTRIBUTE_NAME));
		final String references= extended.getAttribute(JavaRefactoringDescriptorUtil.ATTRIBUTE_REFERENCES);
		if (references != null) {
			fUpdateReferences= Boolean.parseBoolean(references);
		} else
			return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JavaRefactoringDescriptorUtil.ATTRIBUTE_REFERENCES));
		final String delegate= extended.getAttribute(ATTRIBUTE_DELEGATE);
		if (delegate != null) {
			fDelegateUpdating= Boolean.parseBoolean(delegate);
		} else
			return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_DELEGATE));
		final String deprecate= extended.getAttribute(ATTRIBUTE_DEPRECATE);
		if (deprecate != null) {
			fDelegateDeprecation= Boolean.parseBoolean(deprecate);
		} else
			return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_DEPRECATE));
		return new RefactoringStatus();
	}

	protected void addTextEdit(TextChange change, String editName, ReplaceEdit replaceEdit) {
		if (fIsComposite)
			TextChangeCompatibility.addTextEdit(change, editName, replaceEdit, fCategorySet);
		else
			TextChangeCompatibility.addTextEdit(change, editName, replaceEdit);

	}
}
