/*******************************************************************************
 * Copyright (c) 2000, 2018 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.structure;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;

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

import org.eclipse.core.resources.IFile;

import org.eclipse.text.edits.TextEditGroup;

import org.eclipse.ltk.core.refactoring.Change;
import org.eclipse.ltk.core.refactoring.RefactoringDescriptor;
import org.eclipse.ltk.core.refactoring.RefactoringStatus;
import org.eclipse.ltk.core.refactoring.RefactoringStatusContext;
import org.eclipse.ltk.core.refactoring.RefactoringStatusEntry;
import org.eclipse.ltk.core.refactoring.TextChange;
import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext;
import org.eclipse.ltk.core.refactoring.participants.RefactoringParticipant;
import org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor;
import org.eclipse.ltk.core.refactoring.participants.SharableParticipants;

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.IMethod;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.ITypeHierarchy;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.core.compiler.IProblem;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ASTParser;
import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
import org.eclipse.jdt.core.dom.Block;
import org.eclipse.jdt.core.dom.BodyDeclaration;
import org.eclipse.jdt.core.dom.ClassInstanceCreation;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.ConstructorInvocation;
import org.eclipse.jdt.core.dom.Dimension;
import org.eclipse.jdt.core.dom.EnumConstantDeclaration;
import org.eclipse.jdt.core.dom.EnumDeclaration;
import org.eclipse.jdt.core.dom.Expression;
import org.eclipse.jdt.core.dom.ExpressionMethodReference;
import org.eclipse.jdt.core.dom.IMethodBinding;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.ImportDeclaration;
import org.eclipse.jdt.core.dom.Javadoc;
import org.eclipse.jdt.core.dom.LambdaExpression;
import org.eclipse.jdt.core.dom.MemberRef;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.MethodInvocation;
import org.eclipse.jdt.core.dom.MethodRef;
import org.eclipse.jdt.core.dom.MethodRefParameter;
import org.eclipse.jdt.core.dom.Modifier;
import org.eclipse.jdt.core.dom.Name;
import org.eclipse.jdt.core.dom.NodeFinder;
import org.eclipse.jdt.core.dom.PrimitiveType;
import org.eclipse.jdt.core.dom.QualifiedName;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
import org.eclipse.jdt.core.dom.SuperConstructorInvocation;
import org.eclipse.jdt.core.dom.SuperMethodInvocation;
import org.eclipse.jdt.core.dom.TagElement;
import org.eclipse.jdt.core.dom.TextElement;
import org.eclipse.jdt.core.dom.Type;
import org.eclipse.jdt.core.dom.VariableDeclaration;
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
import org.eclipse.jdt.core.dom.rewrite.ImportRewrite;
import org.eclipse.jdt.core.dom.rewrite.ImportRewrite.ImportRewriteContext;
import org.eclipse.jdt.core.dom.rewrite.ListRewrite;
import org.eclipse.jdt.core.refactoring.IJavaRefactorings;
import org.eclipse.jdt.core.refactoring.descriptors.ChangeMethodSignatureDescriptor;
import org.eclipse.jdt.core.refactoring.descriptors.JavaRefactoringDescriptor;
import org.eclipse.jdt.core.refactoring.participants.ChangeMethodSignatureArguments;
import org.eclipse.jdt.core.refactoring.participants.ChangeMethodSignatureArguments.Parameter;
import org.eclipse.jdt.core.refactoring.participants.ChangeMethodSignatureArguments.ThrownException;
import org.eclipse.jdt.core.refactoring.participants.IRefactoringProcessorIds;
import org.eclipse.jdt.core.refactoring.participants.JavaParticipantManager;
import org.eclipse.jdt.core.search.IJavaSearchConstants;
import org.eclipse.jdt.core.search.IJavaSearchScope;
import org.eclipse.jdt.core.search.MethodReferenceMatch;
import org.eclipse.jdt.core.search.SearchEngine;
import org.eclipse.jdt.core.search.SearchMatch;
import org.eclipse.jdt.core.search.SearchPattern;

import org.eclipse.jdt.internal.core.manipulation.StubUtility;
import org.eclipse.jdt.internal.core.manipulation.util.BasicElementLabels;
import org.eclipse.jdt.internal.core.refactoring.descriptors.RefactoringSignatureDescriptorFactory;
import org.eclipse.jdt.internal.corext.Corext;
import org.eclipse.jdt.internal.corext.SourceRangeFactory;
import org.eclipse.jdt.internal.corext.codemanipulation.ContextSensitiveImportRewriteContext;
import org.eclipse.jdt.internal.corext.dom.ASTNodeFactory;
import org.eclipse.jdt.internal.corext.dom.ASTNodes;
import org.eclipse.jdt.internal.corext.dom.Bindings;
import org.eclipse.jdt.internal.corext.dom.IASTSharedValues;
import org.eclipse.jdt.internal.corext.dom.ModifierRewrite;
import org.eclipse.jdt.internal.corext.dom.Selection;
import org.eclipse.jdt.internal.corext.dom.SelectionAnalyzer;
import org.eclipse.jdt.internal.corext.refactoring.Checks;
import org.eclipse.jdt.internal.corext.refactoring.CuCollectingSearchRequestor;
import org.eclipse.jdt.internal.corext.refactoring.ExceptionInfo;
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.ParameterInfo;
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.ReturnTypeInfo;
import org.eclipse.jdt.internal.corext.refactoring.SearchResultGroup;
import org.eclipse.jdt.internal.corext.refactoring.StubTypeContext;
import org.eclipse.jdt.internal.corext.refactoring.TypeContextChecker;
import org.eclipse.jdt.internal.corext.refactoring.base.JavaStringStatusContext;
import org.eclipse.jdt.internal.corext.refactoring.base.RefactoringStatusCodes;
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.code.Invocations;
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.rename.MethodChecks;
import org.eclipse.jdt.internal.corext.refactoring.rename.RefactoringAnalyzeUtil;
import org.eclipse.jdt.internal.corext.refactoring.rename.RippleMethodFinder2;
import org.eclipse.jdt.internal.corext.refactoring.rename.TempOccurrenceAnalyzer;
import org.eclipse.jdt.internal.corext.refactoring.tagging.IDelegateUpdating;
import org.eclipse.jdt.internal.corext.refactoring.util.JavaElementUtil;
import org.eclipse.jdt.internal.corext.refactoring.util.JavaStatusContext;
import org.eclipse.jdt.internal.corext.refactoring.util.JavadocUtil;
import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringASTParser;
import org.eclipse.jdt.internal.corext.refactoring.util.ResourceUtil;
import org.eclipse.jdt.internal.corext.refactoring.util.TextChangeManager;
import org.eclipse.jdt.internal.corext.refactoring.util.TightSourceRangeComputer;
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.internal.ui.JavaPlugin;


public class ChangeSignatureProcessor extends RefactoringProcessor implements IDelegateUpdating {

	private static final String ATTRIBUTE_RETURN= "return"; //$NON-NLS-1$
	private static final String ATTRIBUTE_VISIBILITY= "visibility"; //$NON-NLS-1$
	private static final String ATTRIBUTE_PARAMETER= "parameter"; //$NON-NLS-1$
	private static final String ATTRIBUTE_DEFAULT= "default"; //$NON-NLS-1$
	private static final String ATTRIBUTE_KIND= "kind"; //$NON-NLS-1$
	private static final String ATTRIBUTE_DELEGATE= "delegate"; //$NON-NLS-1$
	private static final String ATTRIBUTE_DEPRECATE= "deprecate"; //$NON-NLS-1$

	private List<ParameterInfo> fParameterInfos;

	private CompilationUnitRewrite fBaseCuRewrite;
	private List<ExceptionInfo> fExceptionInfos;
	private TextChangeManager fChangeManager;

	private IMethod fMethod;
	private IMethod fTopMethod;
	private IMethod[] fRippleMethods;
	private SearchResultGroup[] fOccurrences;
	private ReturnTypeInfo fReturnTypeInfo;
	private String fMethodName;
	private int fVisibility;
	private static final String CONST_CLASS_DECL = "class A{";//$NON-NLS-1$
	private static final String CONST_ASSIGN = " i=";		//$NON-NLS-1$
	private static final String CONST_CLOSE = ";}";			//$NON-NLS-1$

	private StubTypeContext fContextCuStartEnd;
	private int fOldVarargIndex; // initialized in checkVarargs()

	private BodyUpdater fBodyUpdater;
	private IDefaultValueAdvisor fDefaultValueAdvisor;

	private ITypeHierarchy fCachedTypeHierarchy= null;
	private boolean fDelegateUpdating;
	private boolean fDelegateDeprecation;

	public ChangeSignatureProcessor(JavaRefactoringArguments arguments, RefactoringStatus status) throws JavaModelException {
		this((IMethod) null);
		status.merge(initialize(arguments));
	}

	/**
	 * Creates a new change signature refactoring.
	 * @param method the method, or <code>null</code> if invoked by scripting framework
	 * @throws JavaModelException if something's wrong with the given method
	 */
	public ChangeSignatureProcessor(IMethod method) throws JavaModelException {
		fMethod= method;
		fOldVarargIndex= -1;
		fDelegateUpdating= false;
		fDelegateDeprecation= true;
		if (fMethod != null) {
			fParameterInfos= createParameterInfoList(method);
			// fExceptionInfos is created in checkInitialConditions
			fReturnTypeInfo= new ReturnTypeInfo(Signature.toString(Signature.getReturnType(fMethod.getSignature())));
			fMethodName= fMethod.getElementName();
			fVisibility= JdtFlags.getVisibilityCode(fMethod);
		}
	}

	private static List<ParameterInfo> createParameterInfoList(IMethod method) {
		try {
			String[] typeNames= method.getParameterTypes();
			String[] oldNames= method.getParameterNames();
			List<ParameterInfo> result= new ArrayList<>(typeNames.length);
			for (int i= 0; i < oldNames.length; i++){
				ParameterInfo parameterInfo;
				if (i == oldNames.length - 1 && Flags.isVarargs(method.getFlags())) {
					String varargSignature= typeNames[i];
					int arrayCount= Signature.getArrayCount(varargSignature);
					String baseSignature= Signature.getElementType(varargSignature);
					if (arrayCount > 1)
						baseSignature= Signature.createArraySignature(baseSignature, arrayCount - 1);
					parameterInfo= new ParameterInfo(Signature.toString(baseSignature) + ParameterInfo.ELLIPSIS, oldNames[i], i);
				} else {
					parameterInfo= new ParameterInfo(Signature.toString(typeNames[i]), oldNames[i], i);
				}
				result.add(parameterInfo);
			}
			return result;
		} catch(JavaModelException e) {
			JavaPlugin.log(e);
			return new ArrayList<>(0);
		}
	}

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

	public IMethod getMethod() {
		return fMethod;
	}

	public String getMethodName() {
		return fMethodName;
	}

	public String getReturnTypeString() {
		return fReturnTypeInfo.getNewTypeName();
	}

	public void setNewMethodName(String newMethodName){
		Assert.isNotNull(newMethodName);
		fMethodName= newMethodName;
	}

	public void setNewReturnTypeName(String newReturnTypeName){
		Assert.isNotNull(newReturnTypeName);
		fReturnTypeInfo.setNewTypeName(newReturnTypeName);
	}

	public boolean canChangeNameAndReturnType(){
		try {
			return ! fMethod.isConstructor();
		} catch (JavaModelException e) {
			JavaPlugin.log(e);
			return false;
		}
	}

	/**
	 * @return visibility
	 * @see org.eclipse.jdt.core.dom.Modifier
	 */
	public int getVisibility(){
		return fVisibility;
	}

	/**
	 * @param visibility new visibility
	 * @see org.eclipse.jdt.core.dom.Modifier
	 */
	public void setVisibility(int visibility){
		Assert.isTrue(	visibility == Modifier.PUBLIC ||
						visibility == Modifier.PROTECTED ||
						visibility == Modifier.NONE ||
						visibility == Modifier.PRIVATE);
		fVisibility= visibility;
	}

	/*
	 * @see JdtFlags
	 */
	public int[] getAvailableVisibilities() throws JavaModelException{
		if (fTopMethod.getDeclaringType().isInterface())
			return new int[]{Modifier.PUBLIC};
		else if (fTopMethod.getDeclaringType().isEnum() && fTopMethod.isConstructor())
			return new int[]{	Modifier.NONE,
								Modifier.PRIVATE};
		else
			return new int[]{	Modifier.PUBLIC,
								Modifier.PROTECTED,
								Modifier.NONE,
								Modifier.PRIVATE};
	}

	/**
	 *
	 * @return List of <code>ParameterInfo</code> objects.
	 */
	public List<ParameterInfo> getParameterInfos(){
		return fParameterInfos;
	}

	/**
	 * @return List of <code>ExceptionInfo</code> objects.
	 */
	public List<ExceptionInfo> getExceptionInfos(){
		return fExceptionInfos;
	}

	public void setBodyUpdater(BodyUpdater bodyUpdater) {
		fBodyUpdater= bodyUpdater;
	}

	public CompilationUnitRewrite getBaseCuRewrite() {
		return fBaseCuRewrite;
	}

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

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

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

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

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

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

	@Override
	public String getDelegateUpdatingTitle(boolean plural) {
		if (plural)
			return RefactoringCoreMessages.DelegateCreator_keep_original_changed_plural;
		else
			return RefactoringCoreMessages.DelegateCreator_keep_original_changed_singular;
	}

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

	public RefactoringStatus checkSignature() {
		return checkSignature(false);
	}

	private RefactoringStatus checkSignature(boolean resolveBindings) {
		RefactoringStatus result= new RefactoringStatus();
		checkMethodName(result);
		if (result.hasFatalError())
			return result;

		checkParameterNamesAndValues(result);
		if (result.hasFatalError())
			return result;

		checkForDuplicateParameterNames(result);
		if (result.hasFatalError())
			return result;

		try {
			RefactoringStatus[] typeStati;
			if (resolveBindings)
				typeStati= TypeContextChecker.checkAndResolveMethodTypes(fMethod, getStubTypeContext(), getNotDeletedInfos(), fReturnTypeInfo);
			else
				typeStati= TypeContextChecker.checkMethodTypesSyntax(fMethod, getNotDeletedInfos(), fReturnTypeInfo);
			for (RefactoringStatus status : typeStati) {
				result.merge(status);
			}

			result.merge(checkVarargs());
		} catch (CoreException e) {
			//cannot do anything here
			throw new RuntimeException(e);
		}

		//checkExceptions() unnecessary (IType always ok)
		return result;
	}

	public boolean isSignatureSameAsInitial() throws JavaModelException {
		if (! isVisibilitySameAsInitial())
			return false;
		if (! isMethodNameSameAsInitial())
			return false;
		if (! isReturnTypeSameAsInitial())
			return false;
		if (! areExceptionsSameAsInitial())
			return false;

		if (fMethod.getNumberOfParameters() == 0 && fParameterInfos.isEmpty())
			return true;

		if (areNamesSameAsInitial() && isOrderSameAsInitial() && areParameterTypesSameAsInitial())
			return true;

		return false;
	}

	/**
	 * @return true if the new method cannot coexist with the old method since
	 *         the signatures are too much alike
	 */
	public boolean isSignatureClashWithInitial() {

		if (!isMethodNameSameAsInitial())
			return false; // name has changed.

		if (fMethod.getNumberOfParameters() == 0 && fParameterInfos.isEmpty())
			return true; // name is equal and both parameter lists are empty

		// name is equal and there are some parameters.
		// check if there are more or less parameters than before

		int no= getNotDeletedInfos().size();

		if (fMethod.getNumberOfParameters() != no)
			return false;

		// name is equal and parameter count is equal.
		// check whether types remained the same

		if (isOrderSameAsInitial())
			return areParameterTypesSameAsInitial();
		else
			return false; // could be more specific here
	}

	private boolean areParameterTypesSameAsInitial() {
		for (ParameterInfo info : fParameterInfos) {
			if (! info.isAdded() && ! info.isDeleted() && info.isTypeNameChanged())
				return false;
		}
		return true;
	}

	private boolean isReturnTypeSameAsInitial() {
		return ! fReturnTypeInfo.isTypeNameChanged();
	}

	private boolean isMethodNameSameAsInitial() {
		return fMethodName.equals(fMethod.getElementName());
	}

	private boolean areExceptionsSameAsInitial() {
		for (ExceptionInfo info : fExceptionInfos) {
			if (! info.isOld())
				return false;
		}
		return true;
	}

	private void checkParameterNamesAndValues(RefactoringStatus result) {
		int i= 1;
		for (Iterator<ParameterInfo> iter= fParameterInfos.iterator(); iter.hasNext(); i++) {
			ParameterInfo info= iter.next();
			if (info.isDeleted())
				continue;
			checkParameterName(result, info, i);
			if (result.hasFatalError())
				return;
			if (info.isAdded())	{
				checkParameterDefaultValue(result, info);
				if (result.hasFatalError())
					return;
			}
		}
	}

	private void checkParameterName(RefactoringStatus result, ParameterInfo info, int position) {
		if (info.getNewName().trim().length() == 0) {
			result.addFatalError(Messages.format(
					RefactoringCoreMessages.ChangeSignatureRefactoring_param_name_not_empty, Integer.toString(position)));
		} else {
			result.merge(Checks.checkTempName(info.getNewName(), fMethod));
		}
	}

	private void checkMethodName(RefactoringStatus result) {
		if (isMethodNameSameAsInitial() || ! canChangeNameAndReturnType())
			return;
		if ("".equals(fMethodName.trim())) { //$NON-NLS-1$
			String msg= RefactoringCoreMessages.ChangeSignatureRefactoring_method_name_not_empty;
			result.addFatalError(msg);
			return;
		}
		if (fMethodName.equals(fMethod.getDeclaringType().getElementName())) {
			String msg= RefactoringCoreMessages.ChangeSignatureRefactoring_constructor_name;
			result.addWarning(msg);
		}
		result.merge(Checks.checkMethodName(fMethodName, fMethod));
	}

	private void checkParameterDefaultValue(RefactoringStatus result, ParameterInfo info) {
		if (fDefaultValueAdvisor != null)
			return;
		if (info.isNewVarargs()) {
			if (! isValidVarargsExpression(info.getDefaultValue())){
				String msg= Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_invalid_expression, new String[]{info.getDefaultValue()});
				result.addFatalError(msg);
			}
			return;
		}

		if (info.getDefaultValue().trim().isEmpty()){
			String msg= Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_default_value, BasicElementLabels.getJavaElementName(info.getNewName()));
			result.addFatalError(msg);
			return;
		}
		if (! isValidExpression(info.getDefaultValue())){
			String msg= Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_invalid_expression, new String[]{info.getDefaultValue()});
			result.addFatalError(msg);
		}
	}

	private RefactoringStatus checkVarargs() throws JavaModelException {
		RefactoringStatus result= checkOriginalVarargs();
		if (result != null)
			return result;

		if (fRippleMethods != null) {
			for (IMethod rippleMethod : fRippleMethods) {
				if (! JdtFlags.isVarargs(rippleMethod))
					continue;

				// Vararg method can override method that takes an array as last argument
				fOldVarargIndex= rippleMethod.getNumberOfParameters() - 1;
				List<ParameterInfo> notDeletedInfos= getNotDeletedInfos();
				for (ParameterInfo info : notDeletedInfos) {
					if (fOldVarargIndex != -1 && info.getOldIndex() == fOldVarargIndex && ! info.isNewVarargs()) {
						String rippleMethodType= rippleMethod.getDeclaringType().getFullyQualifiedName('.');
						String message= Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_ripple_cannot_convert_vararg, new Object[] { BasicElementLabels.getJavaElementName(info.getNewName()), BasicElementLabels.getJavaElementName(rippleMethodType)});
						return RefactoringStatus.createFatalErrorStatus(message, JavaStatusContext.create(rippleMethod));
					}
				}
			}
		}

		return null;
	}

	private RefactoringStatus checkOriginalVarargs() throws JavaModelException {
		if (JdtFlags.isVarargs(fMethod))
			fOldVarargIndex= fMethod.getNumberOfParameters() - 1;
		List<ParameterInfo> notDeletedInfos= getNotDeletedInfos();
		for (int i= 0; i < notDeletedInfos.size(); i++) {
			ParameterInfo info= notDeletedInfos.get(i);
			if (info.isOldVarargs() && ! info.isNewVarargs())
				return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_cannot_convert_vararg, BasicElementLabels.getJavaElementName(info.getNewName())));
			if (i != notDeletedInfos.size() - 1) {
				// not the last parameter
				if (info.isNewVarargs())
					return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_vararg_must_be_last, BasicElementLabels.getJavaElementName(info.getNewName())));
			}
		}
		return null;
	}

	private RefactoringStatus checkTypeVariables() {
		if (fRippleMethods.length == 1)
			return null;

		RefactoringStatus result= new RefactoringStatus();
		if (fReturnTypeInfo.isTypeNameChanged() && fReturnTypeInfo.getNewTypeBinding() != null) {
			HashSet<ITypeBinding> typeVariablesCollector= new HashSet<>();
			collectTypeVariables(fReturnTypeInfo.getNewTypeBinding(), typeVariablesCollector);
			if (!typeVariablesCollector.isEmpty()) {
				ITypeBinding first= typeVariablesCollector.iterator().next();
				String msg= Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_return_type_contains_type_variable, new String[] {BasicElementLabels.getJavaElementName(fReturnTypeInfo.getNewTypeName()), BasicElementLabels.getJavaElementName(first.getName())});
				result.addError(msg);
			}
		}

		for (ParameterInfo info : getNotDeletedInfos()) {
			if (info.isTypeNameChanged() && info.getNewTypeBinding() != null) {
				HashSet<ITypeBinding> typeVariablesCollector= new HashSet<>();
				collectTypeVariables(info.getNewTypeBinding(), typeVariablesCollector);
				if (!typeVariablesCollector.isEmpty()) {
					ITypeBinding first= typeVariablesCollector.iterator().next();
					String msg= Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_parameter_type_contains_type_variable, new String[] {BasicElementLabels.getJavaElementName(info.getNewTypeName()), BasicElementLabels.getJavaElementName(info.getNewName()), BasicElementLabels.getJavaElementName(first.getName())});
					result.addError(msg);
				}
			}
		}
		return result;
	}

	private void collectTypeVariables(ITypeBinding typeBinding, Set<ITypeBinding> typeVariablesCollector) {
		if (typeBinding.isTypeVariable()) {
			typeVariablesCollector.add(typeBinding);
			for (ITypeBinding typeBound : typeBinding.getTypeBounds()) {
				collectTypeVariables(typeBound, typeVariablesCollector);
			}

		} else if (typeBinding.isArray()) {
			collectTypeVariables(typeBinding.getElementType(), typeVariablesCollector);

		} else if (typeBinding.isParameterizedType()) {
			for (ITypeBinding typeArgument : typeBinding.getTypeArguments()) {
				collectTypeVariables(typeArgument, typeVariablesCollector);
			}

		} else if (typeBinding.isWildcardType()) {
			ITypeBinding bound= typeBinding.getBound();
			if (bound != null) {
				collectTypeVariables(bound, typeVariablesCollector);
			}
		}
	}

	public static boolean isValidExpression(String string){
		String trimmed= string.trim();
		if ("".equals(trimmed)) //speed up for a common case //$NON-NLS-1$
			return false;
		StringBuilder cuBuff= new StringBuilder();
		cuBuff.append(CONST_CLASS_DECL)
			  .append("Object") //$NON-NLS-1$
			  .append(CONST_ASSIGN);
		int offset= cuBuff.length();
		cuBuff.append(trimmed)
			  .append(CONST_CLOSE);
		ASTParser p= ASTParser.newParser(IASTSharedValues.SHARED_AST_LEVEL);
		p.setSource(cuBuff.toString().toCharArray());
		CompilationUnit cu= (CompilationUnit) p.createAST(null);
		Selection selection= Selection.createFromStartLength(offset, trimmed.length());
		SelectionAnalyzer analyzer= new SelectionAnalyzer(selection, false);
		cu.accept(analyzer);
		ASTNode selected= analyzer.getFirstSelectedNode();
		return (selected instanceof Expression) &&
				trimmed.equals(cuBuff.substring(cu.getExtendedStartPosition(selected), cu.getExtendedStartPosition(selected) + cu.getExtendedLength(selected)));
	}

	public static boolean isValidVarargsExpression(String string) {
		String trimmed= string.trim();
		if ("".equals(trimmed)) //speed up for a common case //$NON-NLS-1$
			return true;
		StringBuilder cuBuff= new StringBuilder();
		cuBuff.append("class A{ {m("); //$NON-NLS-1$
		int offset= cuBuff.length();
		cuBuff.append(trimmed)
			  .append(");}}"); //$NON-NLS-1$
		ASTParser p= ASTParser.newParser(IASTSharedValues.SHARED_AST_LEVEL);
		p.setSource(cuBuff.toString().toCharArray());
		CompilationUnit cu= (CompilationUnit) p.createAST(null);
		Selection selection= Selection.createFromStartLength(offset, trimmed.length());
		SelectionAnalyzer analyzer= new SelectionAnalyzer(selection, false);
		cu.accept(analyzer);
		ASTNode[] selectedNodes= analyzer.getSelectedNodes();
		if (selectedNodes.length == 0)
			return false;
		for (ASTNode selectedNode : selectedNodes) {
			if (!(selectedNode instanceof Expression)) {
				return false;
			}
		}
		return true;
	}

	public StubTypeContext getStubTypeContext() {
		try {
			if (fContextCuStartEnd == null)
				fContextCuStartEnd= TypeContextChecker.createStubTypeContext(getCu(), fBaseCuRewrite.getRoot(), fMethod.getSourceRange().getOffset());
		} catch (CoreException e) {
			//cannot do anything here
			throw new RuntimeException(e);
		}
		return fContextCuStartEnd;
	}

	private ITypeHierarchy getCachedTypeHierarchy(IProgressMonitor monitor) throws JavaModelException {
		if (fCachedTypeHierarchy == null)
			fCachedTypeHierarchy= fMethod.getDeclaringType().newTypeHierarchy(new SubProgressMonitor(monitor, 1));
		return fCachedTypeHierarchy;
	}

	@Override
	public RefactoringStatus checkInitialConditions(IProgressMonitor monitor) throws CoreException {
		try {
			monitor.beginTask("", 5); //$NON-NLS-1$
			RefactoringStatus result= Checks.checkIfCuBroken(fMethod);
			if (result.hasFatalError())
				return result;
			if (fMethod == null || !fMethod.exists()) {
				String message= Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_method_deleted, BasicElementLabels.getFileName(getCu()));
				return RefactoringStatus.createFatalErrorStatus(message);
			}
			if (fMethod.getDeclaringType().isInterface()) {
				fTopMethod= MethodChecks.overridesAnotherMethod(fMethod, fMethod.getDeclaringType().newSupertypeHierarchy(new SubProgressMonitor(monitor, 1)));
				monitor.worked(1);
			} else if (MethodChecks.isVirtual(fMethod)) {
				ITypeHierarchy hierarchy= getCachedTypeHierarchy(new SubProgressMonitor(monitor, 1));
				fTopMethod= MethodChecks.isDeclaredInInterface(fMethod, hierarchy, new SubProgressMonitor(monitor, 1));
				if (fTopMethod == null)
					fTopMethod= MethodChecks.overridesAnotherMethod(fMethod, hierarchy);
			}
			if (fTopMethod == null)
				fTopMethod= fMethod;
			if (! fTopMethod.equals(fMethod)) {
				if (fTopMethod.getDeclaringType().isInterface()) {
					RefactoringStatusContext context= JavaStatusContext.create(fTopMethod);
					String message= Messages.format(RefactoringCoreMessages.MethodChecks_implements,
							new String[]{JavaElementUtil.createMethodSignature(fTopMethod), BasicElementLabels.getJavaElementName(fTopMethod.getDeclaringType().getFullyQualifiedName('.'))});
					return RefactoringStatus.createStatus(RefactoringStatus.FATAL, message, context, Corext.getPluginId(), RefactoringStatusCodes.METHOD_DECLARED_IN_INTERFACE, fTopMethod);
				} else {
					RefactoringStatusContext context= JavaStatusContext.create(fTopMethod);
					String message= Messages.format(RefactoringCoreMessages.MethodChecks_overrides,
							new String[]{JavaElementUtil.createMethodSignature(fTopMethod), BasicElementLabels.getJavaElementName(fTopMethod.getDeclaringType().getFullyQualifiedName('.'))});
					return RefactoringStatus.createStatus(RefactoringStatus.FATAL, message, context, Corext.getPluginId(), RefactoringStatusCodes.OVERRIDES_ANOTHER_METHOD, fTopMethod);
				}
			}

			if (monitor.isCanceled())
				throw new OperationCanceledException();

			if (fBaseCuRewrite == null || !fBaseCuRewrite.getCu().equals(getCu())) {
				fBaseCuRewrite= new CompilationUnitRewrite(getCu());
				fBaseCuRewrite.getASTRewrite().setTargetSourceRangeComputer(new TightSourceRangeComputer());
			}
			for (RefactoringStatus status : TypeContextChecker.checkMethodTypesSyntax(fMethod, getParameterInfos(), fReturnTypeInfo)) {
				result.merge(status);
			}
			monitor.worked(1);
			result.merge(createExceptionInfoList());
			monitor.worked(1);
			return result;
		} finally {
			monitor.done();
		}
	}

	private RefactoringStatus createExceptionInfoList() {
		if (fExceptionInfos == null || fExceptionInfos.isEmpty()) {
			fExceptionInfos= new ArrayList<>(0);
			try {
				ASTNode nameNode= NodeFinder.perform(fBaseCuRewrite.getRoot(), fMethod.getNameRange());
				if (nameNode == null || !(nameNode instanceof Name) || !(nameNode.getParent() instanceof MethodDeclaration))
					return null;
				MethodDeclaration methodDeclaration= (MethodDeclaration) nameNode.getParent();
				List<Type> exceptions= methodDeclaration.thrownExceptionTypes();
				List<ExceptionInfo> result= new ArrayList<>(exceptions.size());
				for (Type type : exceptions) {
					ITypeBinding typeBinding= type.resolveBinding();
					if (typeBinding == null)
						return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ChangeSignatureRefactoring_no_exception_binding);
					IJavaElement element= typeBinding.getJavaElement();
					result.add(ExceptionInfo.createInfoForOldException(element, typeBinding));
				}
				fExceptionInfos= result;
			} catch (JavaModelException e) {
				JavaPlugin.log(e);
			}
		}
		return null;
	}

	@Override
	public RefactoringStatus checkFinalConditions(IProgressMonitor pm, CheckConditionsContext context) throws CoreException, OperationCanceledException {
		try {
			pm.beginTask(RefactoringCoreMessages.ChangeSignatureRefactoring_checking_preconditions, 8);
			RefactoringStatus result= new RefactoringStatus();
			clearManagers();
			fBaseCuRewrite.clearASTAndImportRewrites();
			fBaseCuRewrite.getASTRewrite().setTargetSourceRangeComputer(new TightSourceRangeComputer());

			if (isSignatureSameAsInitial())
				return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ChangeSignatureRefactoring_unchanged);
			result.merge(checkSignature(true));
			if (result.hasFatalError())
				return result;

			if (fDelegateUpdating && isSignatureClashWithInitial())
				result.merge(RefactoringStatus.createErrorStatus(RefactoringCoreMessages.ChangeSignatureRefactoring_old_and_new_signatures_not_sufficiently_different ));

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

			fRippleMethods= RippleMethodFinder2.getRelatedMethods(fMethod, binaryRefs, new SubProgressMonitor(pm, 1), null);
			result.merge(checkVarargs());
			if (result.hasFatalError())
				return result;

			fOccurrences= findOccurrences(new SubProgressMonitor(pm, 1), binaryRefs, result);
			binaryRefs.addErrorIfNecessary(result);

			result.merge(checkVisibilityChanges());
			result.merge(checkTypeVariables());

			//TODO:
			// We need a common way of dealing with possible compilation errors for all occurrences,
			// including visibility problems, shadowing and missing throws declarations.

			if (! isOrderSameAsInitial())
				result.merge(checkReorderings(new SubProgressMonitor(pm, 1)));
			else
				pm.worked(1);

			//TODO (bug 58616): check whether changed signature already exists somewhere in the ripple,
			// - error if exists
			// - warn if exists with different parameter types (may cause overloading)

			if (! areNamesSameAsInitial())
				result.merge(checkRenamings(new SubProgressMonitor(pm, 1)));
			else
				pm.worked(1);
			if (result.hasFatalError())
				return result;

//			resolveTypesWithoutBindings(new SubProgressMonitor(pm, 1)); // already done in checkSignature(true)

			createChangeManager(new SubProgressMonitor(pm, 1), result);
			fCachedTypeHierarchy= null;

			if (mustAnalyzeAstOfDeclaringCu())
				result.merge(checkCompilationofDeclaringCu()); //TODO: should also check in ripple methods (move into createChangeManager)
			if (result.hasFatalError())
				return result;

			Checks.addModifiedFilesToChecker(getAllFilesToModify(), context);
			return result;
		} finally {
			pm.done();
		}
	}

	protected void clearManagers() {
		fChangeManager= null;
	}

	private RefactoringStatus checkVisibilityChanges() throws JavaModelException {
		if (isVisibilitySameAsInitial())
			return null;
		if (fRippleMethods.length == 1)
			return null;
		Assert.isTrue(JdtFlags.getVisibilityCode(fMethod) != Modifier.PRIVATE);
		if (fVisibility == Modifier.PRIVATE)
			return RefactoringStatus.createWarningStatus(RefactoringCoreMessages.ChangeSignatureRefactoring_non_virtual);
		return null;
	}

	public String getOldMethodSignature() throws JavaModelException{
		StringBuilder buff= new StringBuilder();

		int flags= getMethod().getFlags();
		buff.append(getVisibilityString(flags));
		if (Flags.isStatic(flags)) {
			buff.append("static "); //$NON-NLS-1$
		} else if (Flags.isDefaultMethod(flags)) {
			buff.append("default "); //$NON-NLS-1$
		}
		if (! getMethod().isConstructor())
			buff.append(fReturnTypeInfo.getOldTypeName())
				.append(' ');

		buff.append(JavaElementLabels.getElementLabel(fMethod.getParent(), JavaElementLabels.ALL_FULLY_QUALIFIED));
		buff.append('.');
		buff.append(fMethod.getElementName())
			.append(Signature.C_PARAM_START)
			.append(getOldMethodParameters())
			.append(Signature.C_PARAM_END);

		buff.append(getOldMethodThrows());

		return BasicElementLabels.getJavaCodeString(buff.toString());
	}

	public String getNewMethodSignature() throws JavaModelException{
		StringBuilder buff= new StringBuilder();

		buff.append(getVisibilityString(fVisibility));
		int flags= getMethod().getFlags();
		if (Flags.isStatic(flags)) {
			buff.append("static "); //$NON-NLS-1$
		} else if (Flags.isDefaultMethod(flags)) {
			buff.append("default "); //$NON-NLS-1$
		}
		if (! getMethod().isConstructor())
			buff.append(getReturnTypeString())
				.append(' ');

		buff.append(getMethodName())
			.append(Signature.C_PARAM_START)
			.append(getMethodParameters())
			.append(Signature.C_PARAM_END);

		buff.append(getMethodThrows());

		return BasicElementLabels.getJavaCodeString(buff.toString());
	}

	private String getVisibilityString(int visibility) {
		String visibilityString= JdtFlags.getVisibilityString(visibility);
		if ("".equals(visibilityString)) //$NON-NLS-1$
			return visibilityString;
		return visibilityString + ' ';
	}

	private String getMethodThrows() {
		final String throwsString= " throws "; //$NON-NLS-1$
		StringBuilder buff= new StringBuilder(throwsString);
		for (ExceptionInfo info : fExceptionInfos) {
			if (! info.isDeleted()) {
				buff.append(info.getElement().getElementName());
				buff.append(", "); //$NON-NLS-1$
			}
		}
		if (buff.length() == throwsString.length())
			return ""; //$NON-NLS-1$
		buff.delete(buff.length() - 2, buff.length());
		return buff.toString();
	}

	private String getOldMethodThrows() {
		final String throwsString= " throws "; //$NON-NLS-1$
		StringBuilder buff= new StringBuilder(throwsString);
		for (ExceptionInfo info : fExceptionInfos) {
			if (! info.isAdded()) {
				buff.append(info.getElement().getElementName());
				buff.append(", "); //$NON-NLS-1$
			}
		}
		if (buff.length() == throwsString.length())
			return ""; //$NON-NLS-1$
		buff.delete(buff.length() - 2, buff.length());
		return buff.toString();
	}

	private void checkForDuplicateParameterNames(RefactoringStatus result){
		Set<String> found= new HashSet<>();
		Set<String> doubled= new HashSet<>();
		for (ParameterInfo info : getNotDeletedInfos()) {
			String newName= info.getNewName();
			if (found.contains(newName) && !doubled.contains(newName)){
				result.addFatalError(Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_duplicate_name, BasicElementLabels.getJavaElementName(newName)));
				doubled.add(newName);
			} else {
				found.add(newName);
			}
		}
	}

	private ICompilationUnit getCu() {
		return fMethod.getCompilationUnit();
	}

	private boolean mustAnalyzeAstOfDeclaringCu() throws JavaModelException{
		return !JdtFlags.isAbstract(getMethod())
				&& !JdtFlags.isNative(getMethod())
				&& !getMethod().getDeclaringType().isInterface();
	}

	private RefactoringStatus checkCompilationofDeclaringCu() throws CoreException {
		ICompilationUnit cu= getCu();
		TextChange change= fChangeManager.get(cu);
		String newCuSource= change.getPreviewContent(new NullProgressMonitor());
		CompilationUnit newCUNode= new RefactoringASTParser(IASTSharedValues.SHARED_AST_LEVEL).parse(newCuSource, cu, true, false, null);
		RefactoringStatus result= new RefactoringStatus();
		for (IProblem problem : RefactoringAnalyzeUtil.getIntroducedCompileProblems(newCUNode, fBaseCuRewrite.getRoot())) {
			if (shouldReport(problem, newCUNode))
				result.addEntry(new RefactoringStatusEntry((problem.isError() ? RefactoringStatus.ERROR : RefactoringStatus.WARNING), problem.getMessage(), new JavaStringStatusContext(newCuSource, SourceRangeFactory.create(problem))));
		}
		return result;
	}

	/**
	 * Evaluates if a problem needs to be reported.
	 * @param problem the problem
	 * @param cu the AST containing the new source
	 * @return return <code>true</code> if the problem needs to be reported
	 */
	protected boolean shouldReport(IProblem problem, CompilationUnit cu) {
		if (! problem.isError())
			return false;
		if (problem.getID() == IProblem.UndefinedType) //reported when trying to import
			return false;
		return true;
	}

	private String getOldMethodParameters() {
		StringBuilder buff= new StringBuilder();
		int i= 0;
		for (Iterator<ParameterInfo> iter= getNotAddedInfos().iterator(); iter.hasNext(); i++) {
			ParameterInfo info= iter.next();
			if (i != 0 )
				buff.append(", ");  //$NON-NLS-1$
			buff.append(createDeclarationString(info));
		}
		return buff.toString();
	}

	private String getMethodParameters() {
		StringBuilder buff= new StringBuilder();
		int i= 0;
		for (Iterator<ParameterInfo> iter= getNotDeletedInfos().iterator(); iter.hasNext(); i++) {
			ParameterInfo info= iter.next();
			if (i != 0 )
				buff.append(", ");  //$NON-NLS-1$
			buff.append(createDeclarationString(info));
		}
		return buff.toString();
	}

	private List<ParameterInfo> getAddedInfos(){
		List<ParameterInfo> result= new ArrayList<>(1);
		for (ParameterInfo info : fParameterInfos) {
			if (info.isAdded())
				result.add(info);
		}
		return result;
	}

	private List<ParameterInfo> getDeletedInfos(){
		List<ParameterInfo> result= new ArrayList<>(1);
		for (ParameterInfo info : fParameterInfos) {
			if (info.isDeleted())
				result.add(info);
		}
		return result;
	}

	private List<ParameterInfo> getNotAddedInfos(){
		List<ParameterInfo> all= new ArrayList<>(fParameterInfos);
		all.removeAll(getAddedInfos());
		return all;
	}

	private List<ParameterInfo> getNotDeletedInfos(){
		List<ParameterInfo> all= new ArrayList<>(fParameterInfos);
		all.removeAll(getDeletedInfos());
		return all;
	}

	private boolean areNamesSameAsInitial() {
		for (ParameterInfo info : fParameterInfos) {
			if (info.isRenamed())
				return false;
		}
		return true;
	}

	private boolean isOrderSameAsInitial(){
		int i= 0;
		for (Iterator<ParameterInfo> iter= fParameterInfos.iterator(); iter.hasNext(); i++) {
			ParameterInfo info= iter.next();
			if (info.getOldIndex() != i) // includes info.isAdded()
				return false;
			if (info.isDeleted())
				return false;
		}
		return true;
	}

	private RefactoringStatus checkReorderings(IProgressMonitor pm) throws JavaModelException {
		try{
			pm.beginTask(RefactoringCoreMessages.ChangeSignatureRefactoring_checking_preconditions, 1);
			return checkNativeMethods();
		} finally{
			pm.done();
		}
	}

	private RefactoringStatus checkRenamings(IProgressMonitor pm) throws JavaModelException {
		try{
			pm.beginTask(RefactoringCoreMessages.ChangeSignatureRefactoring_checking_preconditions, 1);
			return checkParameterNamesInRippleMethods();
		} finally{
			pm.done();
		}
	}

	private RefactoringStatus checkParameterNamesInRippleMethods() throws JavaModelException {
		RefactoringStatus result= new RefactoringStatus();
		Set<String> newParameterNames= getNewParameterNamesList();
		for (IMethod rippleMethod : fRippleMethods) {
			for (String paramName : rippleMethod.getParameterNames()) {
				if (newParameterNames.contains(paramName)) {
					String[] args= new String[]{JavaElementUtil.createMethodSignature(rippleMethod), BasicElementLabels.getJavaElementName(paramName)};
					String msg= Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_already_has, args);
					RefactoringStatusContext context= JavaStatusContext.create(rippleMethod.getCompilationUnit(), rippleMethod.getNameRange());
					result.addError(msg, context);
				}
			}
		}
		return result;
	}

	private Set<String> getNewParameterNamesList() {
		Set<String> oldNames= getOriginalParameterNames();
		Set<String> currentNames= getNamesOfNotDeletedParameters();
		currentNames.removeAll(oldNames);
		return currentNames;
	}

	private Set<String> getNamesOfNotDeletedParameters() {
		Set<String> result= new HashSet<>();
		for (ParameterInfo info : getNotDeletedInfos()) {
			result.add(info.getNewName());
		}
		return result;
	}

	private Set<String> getOriginalParameterNames() {
		Set<String> result= new HashSet<>();
		for (ParameterInfo info : fParameterInfos) {
			if (! info.isAdded())
				result.add(info.getOldName());
		}
		return result;
	}

	private RefactoringStatus checkNativeMethods() throws JavaModelException{
		RefactoringStatus result= new RefactoringStatus();
		for (IMethod rippleMethod : fRippleMethods) {
			if (JdtFlags.isNative(rippleMethod)) {
				String message= Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_native, new String[]{JavaElementUtil.createMethodSignature(rippleMethod), BasicElementLabels.getJavaElementName(rippleMethod.getDeclaringType().getFullyQualifiedName('.'))});
				result.addError(message, JavaStatusContext.create(rippleMethod));
			}
		}
		return result;
	}

	private IFile[] getAllFilesToModify(){
		return ResourceUtil.getFiles(fChangeManager.getAllCompilationUnits());
	}

	public Change[] getAllChanges() {
		return fChangeManager.getAllChanges();
	}

	@Override
	public Change createChange(IProgressMonitor pm) {
		pm.beginTask("", 1); //$NON-NLS-1$
		try {
			return new DynamicValidationRefactoringChange(createDescriptor(), doGetRefactoringChangeName(), getAllChanges());
		} finally {
			clearManagers();
			pm.done();
		}
	}

	private ChangeMethodSignatureArguments getParticipantArguments() {
		ArrayList<Parameter> parameterList= new ArrayList<>();
		String[] originalParameterTypeSigs= fMethod.getParameterTypes();

		for (ParameterInfo pi : getParameterInfos()) {
			if (!pi.isDeleted()) {
				int oldIndex= pi.isAdded() ? -1 : pi.getOldIndex();
				String newName= pi.getNewName();
				String typeSig;
				if (pi.isTypeNameChanged()) {
					String newType= pi.getNewTypeName();
					if (pi.isNewVarargs()) {
						newType= ParameterInfo.stripEllipsis(newType) + "[]"; //$NON-NLS-1$
					}
					typeSig= Signature.createTypeSignature(newType, false);
				} else {
					typeSig= originalParameterTypeSigs[pi.getOldIndex()];
				}
				String defaultValue= pi.getDefaultValue();
				parameterList.add(new Parameter(oldIndex, newName, typeSig, defaultValue));
			}
		}
		Parameter[] parameters= parameterList.toArray(new Parameter[parameterList.size()]);

		ArrayList<ThrownException> exceptionList= new ArrayList<>();
		List<ExceptionInfo> exceptionInfos= getExceptionInfos();
		for (int i= 0; i < exceptionInfos.size(); i++) {
			ExceptionInfo ei= exceptionInfos.get(i);
			if (!ei.isDeleted()) {
				int oldIndex= ei.isAdded() ? -1 : i;
				String qualifiedTypeName= ei.getFullyQualifiedName();
				String newTypeSig= Signature.createTypeSignature(qualifiedTypeName, true);
				exceptionList.add(new ThrownException(oldIndex, newTypeSig));
			}
		}
		ThrownException[] exceptions= exceptionList.toArray(new ThrownException[exceptionList.size()]);
		String returnTypeSig;
		if (fReturnTypeInfo.isTypeNameChanged()) {
			returnTypeSig= Signature.createTypeSignature(fReturnTypeInfo.getNewTypeName(), false);
		} else {
			try {
				returnTypeSig= fMethod.getReturnType();
			} catch (JavaModelException e) {
				returnTypeSig= Signature.createTypeSignature(fReturnTypeInfo.getNewTypeName(), false);
			}
		}
		return new ChangeMethodSignatureArguments(fMethodName, returnTypeSig, fVisibility, parameters, exceptions, fDelegateUpdating);
	}


	public JavaRefactoringDescriptor createDescriptor() {
		final Map<String, String> arguments= new HashMap<>();
		String project= null;
		IJavaProject javaProject= fMethod.getJavaProject();
		if (javaProject != null)
			project= javaProject.getElementName();
		ChangeMethodSignatureDescriptor descriptor= null;
		try {
			final String description= Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_descriptor_description_short, BasicElementLabels.getJavaElementName(fMethod.getElementName()));
			final String header= Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_descriptor_description, new String[] { getOldMethodSignature(), getNewMethodSignature()});
			final JDTRefactoringDescriptorComment comment= createComment(project, header);
			descriptor= RefactoringSignatureDescriptorFactory.createChangeMethodSignatureDescriptor(project, description, comment.asString(), arguments, getDescriptorFlags());
			arguments.put(JavaRefactoringDescriptorUtil.ATTRIBUTE_INPUT, JavaRefactoringDescriptorUtil.elementToHandle(project,fMethod));
			arguments.put(JavaRefactoringDescriptorUtil.ATTRIBUTE_NAME, fMethodName);
			arguments.put(ATTRIBUTE_DELEGATE, Boolean.toString(fDelegateUpdating));
			arguments.put(ATTRIBUTE_DEPRECATE, Boolean.toString(fDelegateDeprecation));
			if (fReturnTypeInfo.isTypeNameChanged())
				arguments.put(ATTRIBUTE_RETURN, fReturnTypeInfo.getNewTypeName());
			try {
				if (!isVisibilitySameAsInitial())
					arguments.put(ATTRIBUTE_VISIBILITY, Integer.toString(fVisibility));
			} catch (JavaModelException exception) {
				JavaPlugin.log(exception);
			}
			int count= 1;
			for (ParameterInfo info : fParameterInfos) {
				final StringBuilder buffer= new StringBuilder(64);
				if (info.isAdded())
					buffer.append("{added}"); //$NON-NLS-1$
				else
					 buffer.append(info.getOldTypeName());
				buffer.append(" "); //$NON-NLS-1$
				if (info.isAdded())
					buffer.append("{added}"); //$NON-NLS-1$
				else
					 buffer.append(info.getOldName());
				buffer.append(" "); //$NON-NLS-1$
				buffer.append(info.getOldIndex());
				buffer.append(" "); //$NON-NLS-1$
				if (info.isDeleted())
					buffer.append("{deleted}"); //$NON-NLS-1$
				else
					buffer.append(info.getNewTypeName().replaceAll(" ", ""));  //$NON-NLS-1$//$NON-NLS-2$
				buffer.append(" "); //$NON-NLS-1$
				if (info.isDeleted())
					buffer.append("{deleted}"); //$NON-NLS-1$
				else
					buffer.append(info.getNewName());
				buffer.append(" "); //$NON-NLS-1$
				buffer.append(info.isDeleted());
				arguments.put(ATTRIBUTE_PARAMETER + count, buffer.toString());
				final String value= info.getDefaultValue();
				if (value != null && !"".equals(value)) //$NON-NLS-1$
					arguments.put(ATTRIBUTE_DEFAULT + count, value);
				count++;
			}
			count= 1;
			for (ExceptionInfo info : fExceptionInfos) {
				arguments.put(JavaRefactoringDescriptorUtil.ATTRIBUTE_ELEMENT + count, JavaRefactoringDescriptorUtil.elementToHandle(project,info.getElement()));
				arguments.put(ATTRIBUTE_KIND + count, Integer.toString(info.getKind()));
				count++;
			}
		} catch (JavaModelException exception) {
			JavaPlugin.log(exception);
			return null;
		}
		return descriptor;
	}

	protected int getDescriptorFlags() {
		int flags= JavaRefactoringDescriptor.JAR_MIGRATION | JavaRefactoringDescriptor.JAR_REFACTORING | RefactoringDescriptor.STRUCTURAL_CHANGE;
		try {
			if (!Flags.isPrivate(fMethod.getFlags()))
				flags|= RefactoringDescriptor.MULTI_CHANGE;
			final IType declaring= fMethod.getDeclaringType();
			if (declaring.isAnonymous() || declaring.isLocal())
				flags|= JavaRefactoringDescriptor.JAR_SOURCE_ATTACHMENT;
		} catch (JavaModelException exception) {
			JavaPlugin.log(exception);
		}
		return flags;
	}

	private JDTRefactoringDescriptorComment createComment(String project, final String header) throws JavaModelException {
		final JDTRefactoringDescriptorComment comment= new JDTRefactoringDescriptorComment(project, this, header);
		if (!fMethod.getElementName().equals(fMethodName))
			comment.addSetting(Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_new_name_pattern, BasicElementLabels.getJavaElementName(fMethodName)));
		if (!isVisibilitySameAsInitial()) {
			String visibility= JdtFlags.getVisibilityString(fVisibility);
			if ("".equals(visibility)) //$NON-NLS-1$
				visibility= RefactoringCoreMessages.ChangeSignatureRefactoring_default_visibility;
			comment.addSetting(Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_new_visibility_pattern, visibility));
		}
		if (fReturnTypeInfo.isTypeNameChanged())
			comment.addSetting(Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_new_return_type_pattern, BasicElementLabels.getJavaElementName(fReturnTypeInfo.getNewTypeName())));
		List<String> deleted= new ArrayList<>();
		List<String> added= new ArrayList<>();
		List<String> changed= new ArrayList<>();
		for (ParameterInfo info : fParameterInfos) {
			if (info.isDeleted())
				deleted.add(Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_deleted_parameter_pattern, new String[] { BasicElementLabels.getJavaElementName(info.getOldTypeName()), BasicElementLabels.getJavaElementName(info.getOldName())}));
			else if (info.isAdded())
				added.add(Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_added_parameter_pattern, new String[] { BasicElementLabels.getJavaElementName(info.getNewTypeName()), BasicElementLabels.getJavaElementName(info.getNewName())}));
			else if (info.isRenamed() || info.isTypeNameChanged() || info.isVarargChanged())
				changed.add(Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_changed_parameter_pattern, new String[] { BasicElementLabels.getJavaElementName(info.getOldTypeName()), BasicElementLabels.getJavaElementName(info.getOldName())}));
		}
		if (!added.isEmpty())
			comment.addSetting(JDTRefactoringDescriptorComment.createCompositeSetting(RefactoringCoreMessages.ChangeSignatureRefactoring_added_parameters, added.toArray(new String[added.size()])));
		if (!deleted.isEmpty())
			comment.addSetting(JDTRefactoringDescriptorComment.createCompositeSetting(RefactoringCoreMessages.ChangeSignatureRefactoring_removed_parameters, deleted.toArray(new String[deleted.size()])));
		if (!changed.isEmpty())
			comment.addSetting(JDTRefactoringDescriptorComment.createCompositeSetting(RefactoringCoreMessages.ChangeSignatureRefactoring_changed_parameters, changed.toArray(new String[changed.size()])));
		added.clear();
		deleted.clear();
		changed.clear();
		for (ExceptionInfo info : fExceptionInfos) {
			if (info.isAdded())
				added.add(info.getElement().getElementName());
			else if (info.isDeleted())
				deleted.add(info.getElement().getElementName());
		}
		if (!added.isEmpty())
			comment.addSetting(JDTRefactoringDescriptorComment.createCompositeSetting(RefactoringCoreMessages.ChangeSignatureRefactoring_added_exceptions, added.toArray(new String[added.size()])));
		if (!deleted.isEmpty())
			comment.addSetting(JDTRefactoringDescriptorComment.createCompositeSetting(RefactoringCoreMessages.ChangeSignatureRefactoring_removed_exceptions, deleted.toArray(new String[deleted.size()])));
		return comment;
	}

	protected String doGetRefactoringChangeName() {
		return RefactoringCoreMessages.ChangeSignatureRefactoring_restructure_parameters;
	}

	private TextChangeManager createChangeManager(IProgressMonitor pm, RefactoringStatus result) throws CoreException {
		pm.beginTask(RefactoringCoreMessages.ChangeSignatureRefactoring_preview, 2);
		fChangeManager= new TextChangeManager();
		boolean isNoArgConstructor= isNoArgConstructor();
		Map<ICompilationUnit, Set<IType>> namedSubclassMapping= null;
		if (isNoArgConstructor){
			//create only when needed;
			namedSubclassMapping= createNamedSubclassMapping(new SubProgressMonitor(pm, 1));
		}else{
			pm.worked(1);
		}
		for (SearchResultGroup occurrence : fOccurrences) {
			if (pm.isCanceled())
				throw new OperationCanceledException();
			SearchResultGroup group= occurrence;
			ICompilationUnit cu= group.getCompilationUnit();
			if (cu == null)
				continue;
			CompilationUnitRewrite cuRewrite;
			if (cu.equals(getCu())) {
				cuRewrite= fBaseCuRewrite;
			} else {
				cuRewrite= new CompilationUnitRewrite(cu);
				cuRewrite.getASTRewrite().setTargetSourceRangeComputer(new TightSourceRangeComputer());
			}
			//IntroduceParameterObjectRefactoring needs to update declarations first:
			List<OccurrenceUpdate<? extends ASTNode>> deferredUpdates= new ArrayList<>();
			for (ASTNode node : ASTNodeSearchUtil.findNodes(group.getSearchResults(), cuRewrite.getRoot())) {
				OccurrenceUpdate<? extends ASTNode> update= createOccurrenceUpdate(node, cuRewrite, result);
				if (update instanceof DeclarationUpdate) {
					update.updateNode();
				} else {
					deferredUpdates.add(update);
				}
			}
			for (OccurrenceUpdate<? extends ASTNode> occurrenceUpdate : deferredUpdates) {
				occurrenceUpdate.updateNode();
			}

			if (isNoArgConstructor && namedSubclassMapping.containsKey(cu)){
				//only non-anonymous subclasses may have noArgConstructors to modify - see bug 43444
				for (IType subtype : namedSubclassMapping.get(cu)) {
					AbstractTypeDeclaration subtypeNode= ASTNodeSearchUtil.getAbstractTypeDeclarationNode(subtype, cuRewrite.getRoot());
					if (subtypeNode != null)
						modifyImplicitCallsToNoArgConstructor(subtypeNode, cuRewrite);
				}
			}
			TextChange change= cuRewrite.createChange(true);
			if (change != null)
				fChangeManager.manage(cu, change);
		}

		pm.done();
		return fChangeManager;
	}

	private Map<ICompilationUnit, Set<IType>> createNamedSubclassMapping(IProgressMonitor pm) throws JavaModelException{
		Map<ICompilationUnit, Set<IType>> result= new HashMap<>();
		for (IType subclass : getCachedTypeHierarchy(new SubProgressMonitor(pm, 1)).getSubclasses(fMethod.getDeclaringType())) {
			if (subclass.isAnonymous())
				continue;
			ICompilationUnit cu= subclass.getCompilationUnit();
			if (! result.containsKey(cu))
				result.put(cu, new HashSet<IType>());
			result.get(cu).add(subclass);
		}
		return result;
	}

	private void modifyImplicitCallsToNoArgConstructor(AbstractTypeDeclaration subclass, CompilationUnitRewrite cuRewrite) {
		MethodDeclaration[] constructors= getAllConstructors(subclass);
		if (constructors.length == 0){
			addNewConstructorToSubclass(subclass, cuRewrite);
		} else {
			for (MethodDeclaration constructor : constructors) {
				if (!containsImplicitCallToSuperConstructor(constructor)) {
					continue;
				}
				addExplicitSuperConstructorCall(constructor, cuRewrite);
			}
		}
	}

	private void addExplicitSuperConstructorCall(MethodDeclaration constructor, CompilationUnitRewrite cuRewrite) {
		SuperConstructorInvocation superCall= constructor.getAST().newSuperConstructorInvocation();
		addArgumentsToNewSuperConstructorCall(superCall, cuRewrite);
		String msg= RefactoringCoreMessages.ChangeSignatureRefactoring_add_super_call;
		TextEditGroup description= cuRewrite.createGroupDescription(msg);
		cuRewrite.getASTRewrite().getListRewrite(constructor.getBody(), Block.STATEMENTS_PROPERTY).insertFirst(superCall, description);
	}

	private void addArgumentsToNewSuperConstructorCall(SuperConstructorInvocation superCall, CompilationUnitRewrite cuRewrite) {
		Iterator<ParameterInfo> iter= getNotDeletedInfos().iterator();
		while (iter.hasNext()) {
			ParameterInfo info= iter.next();
			Expression newExpression= createNewExpression(info, getParameterInfos(), superCall.arguments(), cuRewrite, ASTNodes.getParent(superCall, MethodDeclaration.class));
			if (newExpression != null)
				superCall.arguments().add(newExpression);
		}
	}

	private static boolean containsImplicitCallToSuperConstructor(MethodDeclaration constructor) {
		Assert.isTrue(constructor.isConstructor());
		Block body= constructor.getBody();
		if (body == null)
			return false;
		if (body.statements().size() == 0)
			return true;
		if (body.statements().get(0) instanceof ConstructorInvocation)
			return false;
		if (body.statements().get(0) instanceof SuperConstructorInvocation)
			return false;
		return true;
	}

	private void addNewConstructorToSubclass(AbstractTypeDeclaration subclass, CompilationUnitRewrite cuRewrite) {
		AST ast= subclass.getAST();
		MethodDeclaration newConstructor= ast.newMethodDeclaration();
		newConstructor.setName(ast.newSimpleName(subclass.getName().getIdentifier()));
		newConstructor.setConstructor(true);
		newConstructor.setJavadoc(null);
		newConstructor.modifiers().addAll(ASTNodeFactory.newModifiers(ast, getAccessModifier(subclass)));
		newConstructor.setReturnType2(ast.newPrimitiveType(PrimitiveType.VOID));
		Block body= ast.newBlock();
		newConstructor.setBody(body);
		SuperConstructorInvocation superCall= ast.newSuperConstructorInvocation();
		addArgumentsToNewSuperConstructorCall(superCall, cuRewrite);
		body.statements().add(superCall);

		String msg= RefactoringCoreMessages.ChangeSignatureRefactoring_add_constructor;
		TextEditGroup description= cuRewrite.createGroupDescription(msg);
		cuRewrite.getASTRewrite().getListRewrite(subclass, subclass.getBodyDeclarationsProperty()).insertFirst(newConstructor, description);

		// TODO use AbstractTypeDeclaration
	}

	private static int getAccessModifier(AbstractTypeDeclaration subclass) {
		int modifiers= subclass.getModifiers();
		if (Modifier.isPublic(modifiers))
			return Modifier.PUBLIC;
		else if (Modifier.isProtected(modifiers))
			return Modifier.PROTECTED;
		else if (Modifier.isPrivate(modifiers))
			return Modifier.PRIVATE;
		else
			return Modifier.NONE;
	}

	private MethodDeclaration[] getAllConstructors(AbstractTypeDeclaration typeDeclaration) {
		BodyDeclaration decl;
		List<BodyDeclaration> result= new ArrayList<>(1);
		for (Iterator<BodyDeclaration> it = typeDeclaration.bodyDeclarations().listIterator(); it.hasNext(); ) {
			decl= it.next();
			if (decl instanceof MethodDeclaration && ((MethodDeclaration) decl).isConstructor())
				result.add(decl);
		}
		return result.toArray(new MethodDeclaration[result.size()]);
	}

	private boolean isNoArgConstructor() throws JavaModelException {
		return fMethod.isConstructor() && fMethod.getNumberOfParameters() == 0;
	}

	private Expression createNewExpression(ParameterInfo info, List<ParameterInfo> parameterInfos, List<Expression> nodes, CompilationUnitRewrite cuRewrite, MethodDeclaration method) {
		if (info.isNewVarargs() && info.getDefaultValue().trim().length() == 0)
			return null;
		else {
			if (fDefaultValueAdvisor == null)
				return (Expression) cuRewrite.getASTRewrite().createStringPlaceholder(info.getDefaultValue(), ASTNode.METHOD_INVOCATION);
			else
				return fDefaultValueAdvisor.createDefaultExpression(nodes, info, parameterInfos, method, false, cuRewrite);
		}
	}

	private boolean isVisibilitySameAsInitial() throws JavaModelException {
		return fVisibility == JdtFlags.getVisibilityCode(fMethod);
	}

	private IJavaSearchScope createRefactoringScope()  throws JavaModelException{
		return RefactoringScopeFactory.create(fMethod, true, false);
	}

	private SearchResultGroup[] findOccurrences(IProgressMonitor pm, ReferencesInBinaryContext binaryRefs, RefactoringStatus status) throws JavaModelException{
		final boolean isConstructor= fMethod.isConstructor();
		CuCollectingSearchRequestor requestor= new CuCollectingSearchRequestor(binaryRefs) {
			@Override
			protected void acceptSearchMatch(ICompilationUnit unit, SearchMatch match) throws CoreException {
				// workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=27236 :
				if (isConstructor && match instanceof MethodReferenceMatch) {
					MethodReferenceMatch mrm= (MethodReferenceMatch) match;
					if (mrm.isSynthetic()) {
						return;
					}
				}
				collectMatch(match);
			}
		};

		SearchPattern pattern;
		if (isConstructor) {

//			// workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=226151 : don't find binary refs for constructors for now
//			return ConstructorReferenceFinder.getConstructorOccurrences(fMethod, pm, status);

//			SearchPattern occPattern= SearchPattern.createPattern(fMethod, IJavaSearchConstants.ALL_OCCURRENCES, SearchUtils.GENERICS_AGNOSTIC_MATCH_RULE);
			SearchPattern declPattern= SearchPattern.createPattern(fMethod, IJavaSearchConstants.DECLARATIONS, SearchUtils.GENERICS_AGNOSTIC_MATCH_RULE);
			SearchPattern refPattern= SearchPattern.createPattern(fMethod, IJavaSearchConstants.REFERENCES, SearchUtils.GENERICS_AGNOSTIC_MATCH_RULE);
//			pattern= SearchPattern.createOrPattern(declPattern, refPattern);
//			pattern= occPattern;

			// workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=226151 : do two searches
			try {
				SearchEngine engine= new SearchEngine();
				engine.search(declPattern, SearchUtils.getDefaultSearchParticipants(), createRefactoringScope(), requestor, new NullProgressMonitor());
				engine.search(refPattern, SearchUtils.getDefaultSearchParticipants(), createRefactoringScope(), requestor, pm);
			} catch (CoreException e) {
				throw new JavaModelException(e);
			}
			return RefactoringSearchEngine.groupByCu(requestor.getResults(), status);

		} else {
			pattern= RefactoringSearchEngine.createOrPattern(fRippleMethods, IJavaSearchConstants.ALL_OCCURRENCES);
		}
		return RefactoringSearchEngine.search(pattern, createRefactoringScope(), requestor, pm, status);
	}

	private static String createDeclarationString(ParameterInfo info) {
		String newTypeName= info.getNewTypeName();
		int varargsIndex= newTypeName.lastIndexOf("..."); //$NON-NLS-1$
		if (varargsIndex != -1) {
			newTypeName= newTypeName.substring(0, varargsIndex);
		}
		int index= newTypeName.lastIndexOf('.');
		if (index != -1) {
			newTypeName= newTypeName.substring(index+1);
		}
		return newTypeName + (varargsIndex != -1 ? "..." : "") + " " + info.getNewName(); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
	}

	private static final boolean BUG_89686= true; //see bug 83693: Search for References to methods/constructors: do ranges include parameter lists?

	private OccurrenceUpdate<? extends ASTNode> createOccurrenceUpdate(ASTNode node, CompilationUnitRewrite cuRewrite, RefactoringStatus result) {
		if (BUG_89686 && node instanceof SimpleName && node.getParent() instanceof EnumConstantDeclaration)
			node= node.getParent();

		if (Invocations.isInvocationWithArguments(node))
			return new ReferenceUpdate(node, cuRewrite, result);

		else if (node instanceof SimpleName && node.getParent() instanceof MethodDeclaration)
			return new DeclarationUpdate((MethodDeclaration) node.getParent(), cuRewrite, result);

		else if (node instanceof MemberRef || node instanceof MethodRef)
			return new DocReferenceUpdate(node, cuRewrite, result);

		else if (ASTNodes.getParent(node, ImportDeclaration.class) != null)
			return new StaticImportUpdate(ASTNodes.getParent(node, ImportDeclaration.class), cuRewrite, result);

		else if (node instanceof LambdaExpression)
			return new LambdaExpressionUpdate((LambdaExpression) node, cuRewrite, result);

		else if (node.getLocationInParent() == ExpressionMethodReference.NAME_PROPERTY)
			return new ExpressionMethodRefUpdate((ExpressionMethodReference) node.getParent(), cuRewrite, result);

		else
			return new NullOccurrenceUpdate(node, cuRewrite, result);
	}

	abstract class OccurrenceUpdate<N extends ASTNode> {
		protected final CompilationUnitRewrite fCuRewrite;
		protected final TextEditGroup fDescription;
		protected RefactoringStatus fResult;

		protected OccurrenceUpdate(CompilationUnitRewrite cuRewrite, TextEditGroup description, RefactoringStatus result) {
			fCuRewrite= cuRewrite;
			fDescription= description;
			fResult= result;
		}

		protected final ASTRewrite getASTRewrite() {
			return fCuRewrite.getASTRewrite();
		}

		protected final ImportRewrite getImportRewrite() {
			return fCuRewrite.getImportRewrite();
		}

		protected final ImportRemover getImportRemover() {
			return fCuRewrite.getImportRemover();
		}

		protected final CompilationUnitRewrite getCompilationUnitRewrite() {
			return fCuRewrite;
		}

		protected int getStartPosition() {
			return getMethodNameNode().getStartPosition();
		}

		public abstract void updateNode() throws CoreException;

		protected void registerImportRemoveNode(ASTNode node) {
			getImportRemover().registerRemovedNode(node);
		}

		protected final void reshuffleElements() {
			if (isOrderSameAsInitial())
				return;

			//varargs; method(p1, p2, .., pn), call(a1, a2, .., ax) :
			// if (method_was_vararg) {
			//     assert fOldVarargIndex != -1
			//     if (vararg_retained) {
			//         assert vararg_is_last_non_deleted (pn)
			//         assert no_other_varargs
			//         => reshuffle [1..n-1] then append remaining nodes [n..x], possibly none
			//
			//     } else (vararg_deleted) {
			//         assert all_are_non_vararg
			//         => reshuffle [1..n-1], drop all remaining nodes [n..x], possibly none
			//     }
			//
			// } else if (method_became_vararg) {
			//     assert n == x
			//     assert fOldVarargIndex == -1
			//     => reshuffle [1..n]
			//
			// } else (JLS2_case) {
			//     assert n == x
			//     assert fOldVarargIndex == -1
			//     => reshuffle [1..n]
			// }

			ListRewrite listRewrite= getParamgumentsRewrite();
			Map<N, N> newOldMap= new LinkedHashMap<>();
			List<N> nodes= listRewrite.getRewrittenList();
			Iterator<N> rewriteIter= nodes.iterator();
			List<N> original= listRewrite.getOriginalList();
			for (N n : original) {
				newOldMap.put(rewriteIter.next(),n);
			}
			List<N> newNodes= new ArrayList<>();
			// register removed nodes, and collect nodes in new sequence:
			for (ParameterInfo info : fParameterInfos) {
				int oldIndex= info.getOldIndex();

				if (info.isDeleted()) {
					if (oldIndex != fOldVarargIndex) {
						registerImportRemoveNode(nodes.get(oldIndex));
					} else {
						//vararg deleted -> remove all remaining nodes:
						for (int n= oldIndex; n < nodes.size(); n++) {
							registerImportRemoveNode(nodes.get(n));
						}
					}

				} else if (info.isAdded()) {
					N newParamgument= createNewParamgument(info, fParameterInfos, nodes);
					if (newParamgument != null)
						newNodes.add(newParamgument);

				} else /* parameter stays */ {
					if (oldIndex != fOldVarargIndex) {
						N oldNode= nodes.get(oldIndex);
						N movedNode= moveNode(oldNode, getASTRewrite());
						newNodes.add(movedNode);
					} else {
						//vararg stays and is last parameter -> copy all remaining nodes:
						for (int n= oldIndex; n < nodes.size(); n++) {
							N oldNode= nodes.get(n);
							N movedNode= moveNode(oldNode, getASTRewrite());
							newNodes.add(movedNode);
						}
					}
				}
			}

			Iterator<N> nodesIter= nodes.iterator();
			Iterator<N> newIter= newNodes.iterator();
			//replace existing nodes with new ones:
			while (nodesIter.hasNext() && newIter.hasNext()) {
				ASTNode node= nodesIter.next();
				ASTNode newNode= newIter.next();
				if (!ASTNodes.isExistingNode(node)) //XXX:should better be addressed in ListRewriteEvent.replaceEntry(ASTNode, ASTNode)
					listRewrite.replace(newOldMap.get(node), newNode, fDescription);
				else
					listRewrite.replace(node, newNode, fDescription);
			}
			//remove remaining existing nodes:
			while (nodesIter.hasNext()) {
				ASTNode node= nodesIter.next();
				if (!ASTNodes.isExistingNode(node))
					listRewrite.remove(newOldMap.get(node), fDescription);
				else
					listRewrite.remove(node, fDescription);
			}
			//add additional new nodes:
			while (newIter.hasNext()) {
				ASTNode node= newIter.next();
				listRewrite.insertLast(node, fDescription);
			}
		}

		/**
		 * @return ListRewrite of parameters or arguments
		 */
		protected abstract ListRewrite getParamgumentsRewrite();

		protected final void changeParamguments() {
			for (ParameterInfo info : getParameterInfos()) {
				if (info.isAdded() || info.isDeleted())
					continue;

				if (info.isRenamed())
					changeParamgumentName(info);

				if (info.isTypeNameChanged())
					changeParamgumentType(info);
			}
		}

		/**
		 * @param info the parameter info
		 */
		protected void changeParamgumentName(ParameterInfo info) {
			// no-op
		}

		/**
		 * @param info the parameter info
		 */
		protected void changeParamgumentType(ParameterInfo info) {
			// no-op
		}

		protected final void replaceTypeNode(Type typeNode, String newTypeName, ITypeBinding newTypeBinding){
			Type newTypeNode= createNewTypeNode(newTypeName, newTypeBinding);
			getASTRewrite().replace(typeNode, newTypeNode, fDescription);
			registerImportRemoveNode(typeNode);
			getTightSourceRangeComputer().addTightSourceNode(typeNode);
		}

		/**
		 * @param info TODO
		 * @param parameterInfos TODO
		 * @param nodes TODO
		 * @return a new method parameter or argument, or <code>null</code> for an empty vararg argument
		 */
		protected abstract N createNewParamgument(ParameterInfo info, List<ParameterInfo> parameterInfos, List<N> nodes);

		protected abstract SimpleName getMethodNameNode();

		protected final void changeMethodName() {
			if (! isMethodNameSameAsInitial()) {
				SimpleName nameNode= getMethodNameNode();
				if (nameNode != null) {
					SimpleName newNameNode= nameNode.getAST().newSimpleName(fMethodName);
					getASTRewrite().replace(nameNode, newNameNode, fDescription);
					registerImportRemoveNode(nameNode);
					getTightSourceRangeComputer().addTightSourceNode(nameNode);
				}
			}
		}

		protected final Type createNewTypeNode(String newTypeName, ITypeBinding newTypeBinding) {
			Type newTypeNode;
			if (newTypeBinding == null) {
				if (fDefaultValueAdvisor != null)
					newTypeNode= fDefaultValueAdvisor.createType(newTypeName, getStartPosition(), getCompilationUnitRewrite());
				else
					newTypeNode= (Type) getASTRewrite().createStringPlaceholder(newTypeName, ASTNode.SIMPLE_TYPE);
				//Don't import if not resolved.
			} else {
				ImportRewriteContext importRewriteContext= new ContextSensitiveImportRewriteContext(fCuRewrite.getRoot(), getStartPosition(), getImportRewrite());
				newTypeNode= getImportRewrite().addImport(newTypeBinding, fCuRewrite.getAST(), importRewriteContext);
				getImportRemover().registerAddedImports(newTypeNode);
			}
			return newTypeNode;
		}

		protected final TightSourceRangeComputer getTightSourceRangeComputer() {
			return (TightSourceRangeComputer) fCuRewrite.getASTRewrite().getExtendedSourceRangeComputer();
		}
	}

	class ReferenceUpdate extends OccurrenceUpdate<Expression> {
		/** isReferenceNode(fNode) */
		private ASTNode fNode;

		protected ReferenceUpdate(ASTNode node, CompilationUnitRewrite cuRewrite, RefactoringStatus result) {
			super(cuRewrite, cuRewrite.createGroupDescription(RefactoringCoreMessages.ChangeSignatureRefactoring_update_reference), result);
			fNode= node; //holds: Assert.isTrue(isReferenceNode(node));
		}

		@Override
		public void updateNode() {
			reshuffleElements();
			changeMethodName();
		}

		/** @return {@inheritDoc} (element type: Expression) */
		@Override
		protected ListRewrite getParamgumentsRewrite() {
			return getASTRewrite().getListRewrite(fNode, Invocations.getArgumentsProperty(fNode));
		}

		@Override
		protected Expression createNewParamgument(ParameterInfo info, List<ParameterInfo> parameterInfos, List<Expression> nodes) {
			CompilationUnitRewrite cuRewrite= getCompilationUnitRewrite();
			MethodDeclaration declaration= ASTNodes.getParent(fNode, MethodDeclaration.class);
			if (isRecursiveReference()) {
				return createNewExpressionRecursive(info, parameterInfos, nodes, cuRewrite, declaration);
			} else
				return createNewExpression(info, parameterInfos, nodes, cuRewrite, declaration);
		}

		private Expression createNewExpressionRecursive(ParameterInfo info, List<ParameterInfo> parameterInfos, List<Expression> nodes, CompilationUnitRewrite cuRewrite, MethodDeclaration methodDeclaration) {
			if (fDefaultValueAdvisor != null && info.isAdded()) {
				return fDefaultValueAdvisor.createDefaultExpression(nodes, info, parameterInfos, methodDeclaration, true, cuRewrite);
			}
			return (Expression) getASTRewrite().createStringPlaceholder(info.getNewName(), ASTNode.METHOD_INVOCATION);
		}

		@Override
		protected SimpleName getMethodNameNode() {
			if (fNode instanceof MethodInvocation)
				return ((MethodInvocation)fNode).getName();

			if (fNode instanceof SuperMethodInvocation)
				return ((SuperMethodInvocation)fNode).getName();

			return null;
		}

		private boolean isRecursiveReference() {
			MethodDeclaration enclosingMethodDeclaration= ASTNodes.getParent(fNode, MethodDeclaration.class);
			if (enclosingMethodDeclaration == null)
				return false;

			IMethodBinding enclosingMethodBinding= enclosingMethodDeclaration.resolveBinding();
			if (enclosingMethodBinding == null)
				return false;

			if (fNode instanceof MethodInvocation)
				return enclosingMethodBinding == ((MethodInvocation)fNode).resolveMethodBinding();

			if (fNode instanceof SuperMethodInvocation) {
				IMethodBinding methodBinding= ((SuperMethodInvocation)fNode).resolveMethodBinding();
				return isSameMethod(methodBinding, enclosingMethodBinding);
			}

			if (fNode instanceof ClassInstanceCreation)
				return enclosingMethodBinding == ((ClassInstanceCreation)fNode).resolveConstructorBinding();

			if (fNode instanceof ConstructorInvocation)
				return enclosingMethodBinding == ((ConstructorInvocation)fNode).resolveConstructorBinding();

			if (fNode instanceof SuperConstructorInvocation) {
				return false; //Constructors don't override -> enclosing has not been changed -> no recursion
			}

			if (fNode instanceof EnumConstantDeclaration) {
				return false; //cannot define enum constant inside enum constructor
			}

			Assert.isTrue(false);
			return false;
		}

		/**
		 * @param m1 method 1
		 * @param m2 method 2
		 * @return true iff
		 * 		<ul><li>the methods are both constructors with same argument types, or</li>
		 *	 		<li>the methods have the same name and the same argument types</li></ul>
		 */
		private boolean isSameMethod(IMethodBinding m1, IMethodBinding m2) {
			if (m1.isConstructor()) {
				if (! m2.isConstructor())
					return false;
			} else {
				if (! m1.getName().equals(m2.getName()))
					return false;
			}

			ITypeBinding[] m1Parameters= m1.getParameterTypes();
			ITypeBinding[] m2Parameters= m2.getParameterTypes();
			if (m1Parameters.length != m2Parameters.length)
				return false;
			for (int i= 0; i < m1Parameters.length; i++) {
				if (m1Parameters[i].getErasure() != m2Parameters[i].getErasure())
					return false;
			}
			return true;
		}

	}


	class ExpressionMethodRefUpdate extends OccurrenceUpdate<VariableDeclaration> {
		private ExpressionMethodReference fMethodRef;

		protected ExpressionMethodRefUpdate(ExpressionMethodReference decl, CompilationUnitRewrite cuRewrite, RefactoringStatus result) {
			super(cuRewrite, cuRewrite.createGroupDescription(RefactoringCoreMessages.ChangeSignatureRefactoring_change_signature), result);
			fMethodRef= decl;
		}

		@Override
		public void updateNode() throws CoreException {
			if (canChangeNameAndReturnType())
				changeMethodName();
		}

		@Override
		protected SimpleName getMethodNameNode() {
			return fMethodRef.getName();
		}

		@Override
		protected ListRewrite getParamgumentsRewrite() {
			return null;
		}

		@Override
		protected VariableDeclaration createNewParamgument(ParameterInfo info, List<ParameterInfo> parameterInfos, List<VariableDeclaration> nodes) {
			return null;
		}

	}

	/**
	 * Abstraction for handling MethodDeclaration and LambdaExpression updates.
	 * @param <N> type of the parameter nodes
	 */
	abstract class AbstractDeclarationUpdate<N extends VariableDeclaration> extends OccurrenceUpdate<N> {

		protected AbstractDeclarationUpdate(CompilationUnitRewrite cuRewrite, TextEditGroup description, RefactoringStatus result) {
			super(cuRewrite, description, result);
		}

		protected abstract ASTNode getNode();

		protected abstract VariableDeclaration getParameter(int index);

		@Override
		protected void changeParamgumentName(ParameterInfo info) {
			VariableDeclaration param= getParameter(info.getOldIndex());
			if (!info.getOldName().equals(param.getName().getIdentifier()))
				return; //don't change if original parameter name != name in rippleMethod

			String msg= RefactoringCoreMessages.ChangeSignatureRefactoring_update_parameter_references;
			TextEditGroup description= fCuRewrite.createGroupDescription(msg);
			TempOccurrenceAnalyzer analyzer= new TempOccurrenceAnalyzer(param, false);
			analyzer.perform();
			// @param tags are updated in changeJavaDocTags()
			for (SimpleName occurrence : analyzer.getReferenceAndDeclarationNodes()) {
				getASTRewrite().set(occurrence, SimpleName.IDENTIFIER_PROPERTY, info.getNewName(), description);
			}
		}

		@Override
		protected void changeParamgumentType(ParameterInfo info) {
			VariableDeclaration oldParam= getParameter(info.getOldIndex());
			if (oldParam instanceof SingleVariableDeclaration) {
				getASTRewrite().set(oldParam, SingleVariableDeclaration.VARARGS_PROPERTY, Boolean.valueOf(info.isNewVarargs()), fDescription);
				SingleVariableDeclaration oldSVDParam= (SingleVariableDeclaration) oldParam;
				replaceTypeNode(oldSVDParam.getType(), ParameterInfo.stripEllipsis(info.getNewTypeName()), info.getNewTypeBinding());
				removeExtraDimensions(oldSVDParam);
			}
		}

		private void removeExtraDimensions(SingleVariableDeclaration oldParam) {
			ListRewrite listRewrite= getASTRewrite().getListRewrite(oldParam, SingleVariableDeclaration.EXTRA_DIMENSIONS2_PROPERTY);
			for (Dimension dimension : (List<Dimension>) oldParam.extraDimensions()) {
				listRewrite.remove(dimension, fDescription);
			}
		}

		//TODO: already reported as compilation error -> don't report there?
		protected void checkIfDeletedParametersUsed() {
			for (ParameterInfo info : getDeletedInfos()) {
				VariableDeclaration paramDecl= getParameter(info.getOldIndex());
				TempOccurrenceAnalyzer analyzer= new TempOccurrenceAnalyzer(paramDecl, false);
				analyzer.perform();
				SimpleName[] paramRefs= analyzer.getReferenceNodes();

				if (paramRefs.length > 0) {
					RefactoringStatusContext context= JavaStatusContext.create(fCuRewrite.getCu(), paramRefs[0]);
					String typeName= getFullTypeName();
					Object[] keys= new String[] { BasicElementLabels.getJavaElementName(paramDecl.getName().getIdentifier()),
						BasicElementLabels.getJavaElementName(getMethod().getElementName()),
						BasicElementLabels.getJavaElementName(typeName) };
					String msg= Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_parameter_used, keys);
					fResult.addError(msg, context);
				}
			}
		}

		protected String getFullTypeName() {
			ASTNode node= getNode();
			while (true) {
				node= node.getParent();
				if (node instanceof AbstractTypeDeclaration) {
					String typeName= ((AbstractTypeDeclaration) node).getName().getIdentifier();
					if (getNode() instanceof LambdaExpression) {
						return Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_lambda_expression, typeName);
					}
					return typeName;
				} else if (node instanceof ClassInstanceCreation) {
					ClassInstanceCreation cic= (ClassInstanceCreation) node;
					return Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_anonymous_subclass, BasicElementLabels.getJavaElementName(ASTNodes.asString(cic.getType())));
				} else if (node instanceof EnumConstantDeclaration) {
					EnumDeclaration ed= (EnumDeclaration) node.getParent();
					return Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_anonymous_subclass, BasicElementLabels.getJavaElementName(ASTNodes.asString(ed.getName())));
				}
			}
		}

		protected SingleVariableDeclaration createNewSingleVariableDeclaration(ParameterInfo info) {
			SingleVariableDeclaration newP= getASTRewrite().getAST().newSingleVariableDeclaration();
			newP.setName(getASTRewrite().getAST().newSimpleName(info.getNewName()));
			newP.setType(createNewTypeNode(ParameterInfo.stripEllipsis(info.getNewTypeName()), info.getNewTypeBinding()));
			newP.setVarargs(info.isNewVarargs());
			return newP;
		}
	}

	class LambdaExpressionUpdate extends AbstractDeclarationUpdate<VariableDeclaration> {
		private LambdaExpression fLambdaDecl;

		protected LambdaExpressionUpdate(LambdaExpression decl, CompilationUnitRewrite cuRewrite, RefactoringStatus result) {
			super(cuRewrite, cuRewrite.createGroupDescription(RefactoringCoreMessages.ChangeSignatureRefactoring_change_signature), result);
			fLambdaDecl= decl;
		}

		@Override
		public void updateNode() throws CoreException {
			changeParamguments();

			reshuffleElements();

			if (fBodyUpdater == null || fBodyUpdater.needsParameterUsedCheck())
				checkIfDeletedParametersUsed();
		}

		/** @return {@inheritDoc} (element type: VariableDeclaration) */
		@Override
		protected ListRewrite getParamgumentsRewrite() {
			return getASTRewrite().getListRewrite(fLambdaDecl, LambdaExpression.PARAMETERS_PROPERTY);
		}

		@Override
		protected VariableDeclaration createNewParamgument(ParameterInfo info, List<ParameterInfo> parameterInfos, List<VariableDeclaration> nodes) {
			List<VariableDeclaration> parameters= fLambdaDecl.parameters();
			if (!parameters.isEmpty() && parameters.get(0) instanceof SingleVariableDeclaration) {
				return createNewSingleVariableDeclaration(info);
			}
			VariableDeclarationFragment newP= getASTRewrite().getAST().newVariableDeclarationFragment();
			newP.setName(getASTRewrite().getAST().newSimpleName(info.getNewName()));
			return newP;
		}

		@Override
		protected int getStartPosition() {
			return fLambdaDecl.getStartPosition();
		}

		@Override
		protected ASTNode getNode() {
			return fLambdaDecl;
		}

		@Override
		protected VariableDeclaration getParameter(int index) {
			return (VariableDeclaration) fLambdaDecl.parameters().get(index);
		}

		@Override
		protected SimpleName getMethodNameNode() {
			return null;
		}
	}

	class DeclarationUpdate extends AbstractDeclarationUpdate<SingleVariableDeclaration> {
		private MethodDeclaration fMethDecl;

		protected DeclarationUpdate(MethodDeclaration decl, CompilationUnitRewrite cuRewrite, RefactoringStatus result) {
			super(cuRewrite, cuRewrite.createGroupDescription(RefactoringCoreMessages.ChangeSignatureRefactoring_change_signature), result);
			fMethDecl= decl;
		}

		// Prevent import removing if delegate is created.
		@Override
		protected void registerImportRemoveNode(ASTNode node) {
			if (!fDelegateUpdating)
				super.registerImportRemoveNode(node);
		}

		@Override
		public void updateNode() throws CoreException {
			changeParamguments();

			if (canChangeNameAndReturnType()) {
				changeMethodName();
				changeReturnType();
			}

			if (needsVisibilityUpdate())
				changeVisibility();
			reshuffleElements();
			changeExceptions();

			changeJavadocTags();

			if (fBodyUpdater == null || fBodyUpdater.needsParameterUsedCheck())
				checkIfDeletedParametersUsed();

			if (fBodyUpdater != null)
				fBodyUpdater.updateBody(fMethDecl, fCuRewrite, fResult);

			if (fDelegateUpdating)
				addDelegate();
		}

		private void addDelegate() throws JavaModelException {

			DelegateMethodCreator creator= new DelegateMethodCreator();
			creator.setDeclaration(fMethDecl);
			creator.setDeclareDeprecated(fDelegateDeprecation);
			creator.setSourceRewrite(fCuRewrite);
			creator.prepareDelegate();

			/*
			 * The delegate now contains a call and a javadoc reference to the
			 * old method (i.e., to itself).
			 *
			 * Use ReferenceUpdate() / DocReferenceUpdate() to update these
			 * references like any other reference.
			 */
			final ASTNode delegateInvocation= creator.getDelegateInvocation();
			if (delegateInvocation != null)
				// may be null if the delegate is an interface method or
				// abstract -> no body
				new ReferenceUpdate(delegateInvocation, creator.getDelegateRewrite(), fResult).updateNode();
			MethodRef javadocReference= creator.getJavadocReference();
			if (javadocReference != null)
				new DocReferenceUpdate(javadocReference, creator.getDelegateRewrite(), fResult).updateNode();

			creator.createEdit();
		}

		/** @return {@inheritDoc} (element type: SingleVariableDeclaration) */
		@Override
		protected ListRewrite getParamgumentsRewrite() {
			return getASTRewrite().getListRewrite(fMethDecl, MethodDeclaration.PARAMETERS_PROPERTY);
		}

		private void changeReturnType() {
			if (isReturnTypeSameAsInitial())
				return;
			replaceTypeNode(fMethDecl.getReturnType2(), fReturnTypeInfo.getNewTypeName(), fReturnTypeInfo.getNewTypeBinding());
			removeExtraDimensions(fMethDecl);
			//Remove expression from return statement when changed to void? No, would lose information!
			//Could add return statement with default value and add todo comment, but compile error is better.
		}

		private void removeExtraDimensions(MethodDeclaration methDecl) {
			ListRewrite listRewrite= getASTRewrite().getListRewrite(methDecl, MethodDeclaration.EXTRA_DIMENSIONS2_PROPERTY);
			for (Dimension dimension : (List<Dimension>) methDecl.extraDimensions()) {
				listRewrite.remove(dimension, fDescription);
			}
		}

		private boolean needsVisibilityUpdate() throws JavaModelException {
			if (isVisibilitySameAsInitial())
				return false;
			if (isIncreasingVisibility())
				return JdtFlags.isHigherVisibility(fVisibility, JdtFlags.getVisibilityCode(fMethDecl));
			else
				return JdtFlags.isHigherVisibility(JdtFlags.getVisibilityCode(fMethDecl), fVisibility);
		}

		private boolean isIncreasingVisibility() throws JavaModelException{
			return JdtFlags.isHigherVisibility(fVisibility, JdtFlags.getVisibilityCode(fMethod));
		}

		private void changeVisibility() {
			ModifierRewrite.create(getASTRewrite(), fMethDecl).setVisibility(fVisibility, fDescription);
		}

		private void changeExceptions() {
			for (ExceptionInfo info : fExceptionInfos) {
				if (info.isOld())
					continue;
				if (info.isDeleted())
					removeExceptionFromNodeList(info, fMethDecl.thrownExceptionTypes());
				else
					addExceptionToNodeList(info, getASTRewrite().getListRewrite(fMethDecl, MethodDeclaration.THROWN_EXCEPTION_TYPES_PROPERTY));
			}
		}

		private void removeExceptionFromNodeList(ExceptionInfo toRemove, List<Type> list) {
			ITypeBinding typeToRemove= toRemove.getTypeBinding();
			for (Type currentExcType : list) {
				ITypeBinding currentType= currentExcType.resolveBinding();
				/* Maybe remove all subclasses of typeToRemove too.
				 * Problem:
				 * - B extends A;
				 * - A.m() throws IOException, Exception;
				 * - B.m() throws IOException, AWTException;
				 * Removing Exception should remove AWTException,
				 * but NOT remove IOException (or a subclass of JavaModelException). */
				 // if (Bindings.isSuperType(typeToRemove, currentType))
				if (currentType == null)
					continue; // newly added or unresolvable type
				if (Bindings.equals(currentType, typeToRemove) || toRemove.getElement().getElementName().equals(currentType.getName())) {
					getASTRewrite().remove(currentExcType, fDescription);
					registerImportRemoveNode(currentExcType);
				}
			}
		}

		private void addExceptionToNodeList(ExceptionInfo exceptionInfo, ListRewrite exceptionListRewrite) {
			String fullyQualified= exceptionInfo.getFullyQualifiedName();
			for (Iterator<? extends ASTNode> iter= exceptionListRewrite.getOriginalList().iterator(); iter.hasNext(); ) {
				Type exType= (Type) iter.next();
				//XXX: existing superclasses of the added exception are redundant and could be removed
				ITypeBinding typeBinding= exType.resolveBinding();
				if (typeBinding == null)
					continue; // newly added or unresolvable type
				if (typeBinding.getQualifiedName().equals(fullyQualified))
					return; // don't add it again
			}
			String importedType= getImportRewrite().addImport(exceptionInfo.getFullyQualifiedName());
			getImportRemover().registerAddedImport(importedType);
			ASTNode exNode= getASTRewrite().createStringPlaceholder(importedType, ASTNode.SIMPLE_TYPE);
			exceptionListRewrite.insertLast(exNode, fDescription);
		}

		private void changeJavadocTags() throws JavaModelException {
			//update tags in javadoc: @param, @return, @exception, @throws, ...
			Javadoc javadoc= fMethDecl.getJavadoc();
			if (javadoc == null)
				return;

			ITypeBinding typeBinding= Bindings.getBindingOfParentType(fMethDecl);
			if (typeBinding == null)
				return;
			IMethodBinding methodBinding= fMethDecl.resolveBinding();
			if (methodBinding == null)
				return;

			boolean isTopOfRipple= (Bindings.findOverriddenMethod(methodBinding, false) == null);
			//add tags: only iff top of ripple; change and remove: always.
			//TODO: should have preference for adding tags in (overriding) methods (with template: todo, inheritDoc, ...)

			List<TagElement> tags= javadoc.tags();
			ListRewrite tagsRewrite= getASTRewrite().getListRewrite(javadoc, Javadoc.TAGS_PROPERTY);

			if (! isReturnTypeSameAsInitial()) {
				if (PrimitiveType.VOID.toString().equals(fReturnTypeInfo.getNewTypeName())) {
					for (TagElement tag : tags) {
						if (TagElement.TAG_RETURN.equals(tag.getTagName())) {
							getASTRewrite().remove(tag, fDescription);
							registerImportRemoveNode(tag);
						}
					}
				} else if (isTopOfRipple && Signature.SIG_VOID.equals(fMethod.getReturnType())){
					TagElement returnNode= createReturnTag();
					TagElement previousTag= findTagElementToInsertAfter(tags, TagElement.TAG_RETURN);
					insertTag(returnNode, previousTag, tagsRewrite);
					tags= tagsRewrite.getRewrittenList();
				}
			}

			if (!areNamesSameAsInitial() || !isOrderSameAsInitial()) {
				ArrayList<TagElement> paramTags= new ArrayList<>(); // <TagElement>, only not deleted tags with simpleName
				// delete & rename:
				for (TagElement tag : tags) {
					String tagName= tag.getTagName();
					List<? extends ASTNode> fragments= tag.fragments();
					if (!TagElement.TAG_PARAM.equals(tagName)
							|| fragments.isEmpty()
							|| !(fragments.get(0) instanceof SimpleName))
						continue;
					SimpleName simpleName= (SimpleName) fragments.get(0);
					String identifier= simpleName.getIdentifier();
					boolean removed= false;
					for (ParameterInfo info : fParameterInfos) {
						if (identifier.equals(info.getOldName())) {
							if (info.isDeleted()) {
								getASTRewrite().remove(tag, fDescription);
								registerImportRemoveNode(tag);
								removed= true;
							} else if (info.isRenamed()) {
								SimpleName newName= simpleName.getAST().newSimpleName(info.getNewName());
								getASTRewrite().replace(simpleName, newName, fDescription);
								registerImportRemoveNode(tag);
							}
							break;
						}
					}
					if (! removed)
						paramTags.add(tag);
				}
				tags= tagsRewrite.getRewrittenList();

				if (! isOrderSameAsInitial()) {
					// reshuffle (sort in declaration sequence) & add (only add to top of ripple):
					TagElement previousTag= findTagElementToInsertAfter(tags, TagElement.TAG_PARAM);
					boolean first= true; // workaround for bug 92111: preserve first tag if possible
					// reshuffle:
					for (ParameterInfo info : fParameterInfos) {
						String oldName= info.getOldName();
						String newName= info.getNewName();
						if (info.isAdded()) {
							first= false;
							if (! isTopOfRipple)
								continue;
							TagElement paramNode= JavadocUtil.createParamTag(newName, fCuRewrite.getRoot().getAST(), fCuRewrite.getCu().getJavaProject());
							insertTag(paramNode, previousTag, tagsRewrite);
							previousTag= paramNode;
						} else {
							for (Iterator<TagElement> tagIter= paramTags.iterator(); tagIter.hasNext();) {
								TagElement tag= tagIter.next();
								SimpleName tagName= (SimpleName) tag.fragments().get(0);
								if (oldName.equals(tagName.getIdentifier())) {
									tagIter.remove();
									if (first) {
										previousTag= tag;
									} else {
										TagElement movedTag= (TagElement) getASTRewrite().createMoveTarget(tag);
										getASTRewrite().remove(tag, fDescription);
										insertTag(movedTag, previousTag, tagsRewrite);
										previousTag= movedTag;
									}
								}
								first= false;
							}
						}
					}
					// params with bad names:
					for (TagElement tag : paramTags) {
						TagElement movedTag= (TagElement) getASTRewrite().createMoveTarget(tag);
						getASTRewrite().remove(tag, fDescription);
						insertTag(movedTag, previousTag, tagsRewrite);
						previousTag= movedTag;
					}
				}
				tags= tagsRewrite.getRewrittenList();
			}

			if (! areExceptionsSameAsInitial()) {
				// collect exceptionTags and remove deleted:
				ArrayList<TagElement> exceptionTags= new ArrayList<>(); // <TagElement>, only not deleted tags with name
				for (TagElement tag : tags) {
					if (! TagElement.TAG_THROWS.equals(tag.getTagName()) && ! TagElement.TAG_EXCEPTION.equals(tag.getTagName()))
						continue;
					if (tag.fragments().isEmpty() || !(tag.fragments().get(0) instanceof Name))
						continue;
					boolean tagDeleted= false;
					Name name= (Name) tag.fragments().get(0);
					for (ExceptionInfo info : fExceptionInfos) {
						if (info.isDeleted()) {
							boolean remove= false;
							final ITypeBinding nameBinding= name.resolveTypeBinding();
							if (nameBinding != null) {
								final ITypeBinding infoBinding= info.getTypeBinding();
								if ((infoBinding != null && Bindings.equals(infoBinding, nameBinding))
										|| info.getElement().getElementName().equals(nameBinding.getName()))
									remove= true;
								if (remove) {
									getASTRewrite().remove(tag, fDescription);
									registerImportRemoveNode(tag);
									tagDeleted= true;
									break;
								}
							}
						}
					}
					if (! tagDeleted)
						exceptionTags.add(tag);
				}
				// reshuffle:
				tags= tagsRewrite.getRewrittenList();
				TagElement previousTag= findTagElementToInsertAfter(tags, TagElement.TAG_THROWS);
				for (ExceptionInfo info : fExceptionInfos) {
					if (info.isAdded()) {
						if (!isTopOfRipple)
							continue;
						TagElement excptNode= createExceptionTag(info.getElement().getElementName());
						insertTag(excptNode, previousTag, tagsRewrite);
						previousTag= excptNode;
					} else {
						for (Iterator<TagElement> tagIter= exceptionTags.iterator(); tagIter.hasNext();) {
							TagElement tag= tagIter.next();
							Name tagName= (Name) tag.fragments().get(0);
							final ITypeBinding nameBinding= tagName.resolveTypeBinding();
							if (nameBinding != null) {
								boolean process= false;
								final ITypeBinding infoBinding= info.getTypeBinding();
								if ((infoBinding != null && Bindings.equals(infoBinding, nameBinding))
										|| info.getElement().getElementName().equals(nameBinding.getName())) {
									process= true;
								}
								if (process) {
									tagIter.remove();
									TagElement movedTag= (TagElement) getASTRewrite().createMoveTarget(tag);
									getASTRewrite().remove(tag, fDescription);
									insertTag(movedTag, previousTag, tagsRewrite);
									previousTag= movedTag;
								}
							}
						}
					}
				}
				// exceptions with bad names:
				for (TagElement tag : exceptionTags) {
					TagElement movedTag= (TagElement) getASTRewrite().createMoveTarget(tag);
					getASTRewrite().remove(tag, fDescription);
					insertTag(movedTag, previousTag, tagsRewrite);
					previousTag= movedTag;
				}
			}
		}

		private TagElement createReturnTag() {
			TagElement returnNode= getASTRewrite().getAST().newTagElement();
			returnNode.setTagName(TagElement.TAG_RETURN);

			TextElement textElement= getASTRewrite().getAST().newTextElement();
			String text= StubUtility.getTodoTaskTag(fCuRewrite.getCu().getJavaProject());
			if (text != null)
				textElement.setText(text); //TODO: use template with {@todo} ...
			returnNode.fragments().add(textElement);

			return returnNode;
		}

		private TagElement createExceptionTag(String simpleName) {
			TagElement excptNode= getASTRewrite().getAST().newTagElement();
			excptNode.setTagName(TagElement.TAG_THROWS);

			SimpleName nameNode= getASTRewrite().getAST().newSimpleName(simpleName);
			excptNode.fragments().add(nameNode);

			TextElement textElement= getASTRewrite().getAST().newTextElement();
			String text= StubUtility.getTodoTaskTag(fCuRewrite.getCu().getJavaProject());
			if (text != null)
				textElement.setText(text); //TODO: use template with {@todo} ...
			excptNode.fragments().add(textElement);

			return excptNode;
		}

		private void insertTag(TagElement tag, TagElement previousTag, ListRewrite tagsRewrite) {
			if (previousTag == null)
				tagsRewrite.insertFirst(tag, fDescription);
			else
				tagsRewrite.insertAfter(tag, previousTag, fDescription);
		}

		/**
		 * @param tags existing tags
		 * @param tagName name of tag to add
		 * @return the <code>TagElement<code> just before a new <code>TagElement</code> with name
		 *         <code>tagName</code>, or <code>null</code>.
		 */
		private TagElement findTagElementToInsertAfter(List<TagElement> tags, String tagName) {
			List<String> tagOrder= Arrays.asList(
					TagElement.TAG_AUTHOR,
					TagElement.TAG_VERSION,
					TagElement.TAG_PARAM,
					TagElement.TAG_RETURN,
					TagElement.TAG_THROWS,
					TagElement.TAG_EXCEPTION,
					TagElement.TAG_SEE,
					TagElement.TAG_SINCE,
					TagElement.TAG_SERIAL,
					TagElement.TAG_SERIALFIELD,
					TagElement.TAG_SERIALDATA,
					TagElement.TAG_DEPRECATED,
					TagElement.TAG_VALUE
			);
			int goalOrdinal= tagOrder.indexOf(tagName);
			if (goalOrdinal == -1) // unknown tag -> to end
				return (tags.isEmpty()) ? null : (TagElement) tags.get(tags.size());
			for (int i= 0; i < tags.size(); i++) {
				int tagOrdinal= tagOrder.indexOf(tags.get(i).getTagName());
				if (tagOrdinal >= goalOrdinal)
					return (i == 0) ? null : (TagElement) tags.get(i - 1);
			}
			return (tags.isEmpty()) ? null : (TagElement) tags.get(tags.size() - 1);
		}


		@Override
		protected SingleVariableDeclaration createNewParamgument(ParameterInfo info, List<ParameterInfo> parameterInfos, List<SingleVariableDeclaration> nodes) {
			return createNewSingleVariableDeclaration(info);
		}

		@Override
		protected ASTNode getNode() {
			return fMethDecl;
		}

		@Override
		protected VariableDeclaration getParameter(int index) {
			return (VariableDeclaration) fMethDecl.parameters().get(index);
		}

		@Override
		protected SimpleName getMethodNameNode() {
			return fMethDecl.getName();
		}

	}

	class DocReferenceUpdate extends OccurrenceUpdate<MethodRefParameter> {
		/** instanceof MemberRef || MethodRef */
		private ASTNode fNode;

		protected DocReferenceUpdate(ASTNode node, CompilationUnitRewrite cuRewrite, RefactoringStatus result) {
			super(cuRewrite, cuRewrite.createGroupDescription(RefactoringCoreMessages.ChangeSignatureRefactoring_update_javadoc_reference), result);
			fNode= node;
		}

		@Override
		public void updateNode() {
			if (fNode instanceof MethodRef) {
				changeParamguments();
				reshuffleElements();
			}
			if (canChangeNameAndReturnType())
				changeMethodName();
		}

		@Override
		protected MethodRefParameter createNewParamgument(ParameterInfo info, List<ParameterInfo> parameterInfos, List<MethodRefParameter> nodes) {
			return createNewMethodRefParameter(info);
		}

		private MethodRefParameter createNewMethodRefParameter(ParameterInfo info) {
			MethodRefParameter newP= getASTRewrite().getAST().newMethodRefParameter();

			// only add name iff first parameter already has a name:
			List<? extends ASTNode> parameters= getParamgumentsRewrite().getOriginalList();
			if (parameters.size() > 0)
				if (((MethodRefParameter) parameters.get(0)).getName() != null)
					newP.setName(getASTRewrite().getAST().newSimpleName(info.getNewName()));

			newP.setType(createNewDocRefType(info));
			newP.setVarargs(info.isNewVarargs());
			return newP;
		}

		private Type createNewDocRefType(ParameterInfo info) {
			String newTypeName= ParameterInfo.stripEllipsis(info.getNewTypeName());
			ITypeBinding newTypeBinding= info.getNewTypeBinding();
			if (newTypeBinding != null)
				newTypeBinding= newTypeBinding.getErasure(); //see bug 83127: Javadoc references are raw (erasures)
			return createNewTypeNode(newTypeName, newTypeBinding);
		}

		@Override
		protected SimpleName getMethodNameNode() {
			if (fNode instanceof MemberRef)
				return ((MemberRef) fNode).getName();

			if (fNode instanceof MethodRef)
				return ((MethodRef) fNode).getName();

			return null;
		}

		/** @return {@inheritDoc} (element type: MethodRefParameter) */
		@Override
		protected ListRewrite getParamgumentsRewrite() {
			return getASTRewrite().getListRewrite(fNode, MethodRef.PARAMETERS_PROPERTY);
		}

		@Override
		protected void changeParamgumentName(ParameterInfo info) {
			if (! (fNode instanceof MethodRef))
				return;

			MethodRefParameter oldParam= (MethodRefParameter) ((MethodRef) fNode).parameters().get(info.getOldIndex());
			SimpleName oldParamName= oldParam.getName();
			if (oldParamName != null)
				getASTRewrite().set(oldParamName, SimpleName.IDENTIFIER_PROPERTY, info.getNewName(), fDescription);
		}

		@Override
		protected void changeParamgumentType(ParameterInfo info) {
			if (! (fNode instanceof MethodRef))
				return;

			MethodRefParameter oldParam= (MethodRefParameter) ((MethodRef) fNode).parameters().get(info.getOldIndex());
			Type oldTypeNode= oldParam.getType();
			Type newTypeNode= createNewDocRefType(info);
			if (info.isNewVarargs()) {
				if (info.isOldVarargs() && ! oldParam.isVarargs()) {
					// leave as array reference if old reference was not vararg
					newTypeNode= ASTNodeFactory.newArrayType(newTypeNode);
				} else {
					getASTRewrite().set(oldParam, MethodRefParameter.VARARGS_PROPERTY, Boolean.TRUE, fDescription);
				}
			} else {
				if (oldParam.isVarargs()) {
					getASTRewrite().set(oldParam, MethodRefParameter.VARARGS_PROPERTY, Boolean.FALSE, fDescription);
				}
			}

			getASTRewrite().replace(oldTypeNode, newTypeNode, fDescription);
			registerImportRemoveNode(oldTypeNode);
		}
	}

	class StaticImportUpdate extends OccurrenceUpdate<ASTNode> {

		private final ImportDeclaration fImportDecl;

		public StaticImportUpdate(ImportDeclaration importDecl, CompilationUnitRewrite cuRewrite, RefactoringStatus result) {
			super(cuRewrite, null, result);
			fImportDecl= importDecl;
		}

		@Override
		public void updateNode() throws JavaModelException {
			ImportRewrite importRewrite= fCuRewrite.getImportRewrite();
			QualifiedName name= (QualifiedName) fImportDecl.getName();
			//will be removed by importRemover if not used elsewhere ... importRewrite.removeStaticImport(name.getFullyQualifiedName());
			importRewrite.addStaticImport(name.getQualifier().getFullyQualifiedName(), fMethodName, false);
		}

		@Override
		protected ListRewrite getParamgumentsRewrite() {
			return null;
		}

		@Override
		protected ASTNode createNewParamgument(ParameterInfo info, List<ParameterInfo> parameterInfos, List<ASTNode> nodes) {
			return null;
		}

		@Override
		protected SimpleName getMethodNameNode() {
			return null;
		}
	}

	class NullOccurrenceUpdate extends OccurrenceUpdate<ASTNode> {
		private ASTNode fNode;
		protected NullOccurrenceUpdate(ASTNode node, CompilationUnitRewrite cuRewrite, RefactoringStatus result) {
			super(cuRewrite, null, result);
			fNode= node;
		}
		@Override
		public void updateNode() throws JavaModelException {
			int start= fNode.getStartPosition();
			int length= fNode.getLength();
			String msg= "Cannot update found node: nodeType=" + fNode.getNodeType() + "; "  //$NON-NLS-1$//$NON-NLS-2$
					+ fNode.toString() + "[" + start + ", " + length + "] in " + fCuRewrite.getCu();  //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
			JavaPlugin.log(new Exception(msg + ":\n" + fCuRewrite.getCu().getSource().substring(start, start + length))); //$NON-NLS-1$
			fResult.addError(msg, JavaStatusContext.create(fCuRewrite.getCu(), fNode));
		}
		@Override
		protected ListRewrite getParamgumentsRewrite() {
			return null;
		}
		@Override
		protected ASTNode createNewParamgument(ParameterInfo info, List<ParameterInfo> parameterInfos, List<ASTNode> nodes) {
			return null;
		}
		@Override
		protected SimpleName getMethodNameNode() {
			return null;
		}
	}

	private RefactoringStatus initialize(JavaRefactoringArguments arguments) {
		final String handle= arguments.getAttribute(JavaRefactoringDescriptorUtil.ATTRIBUTE_INPUT);
		if (handle != null) {
			final IJavaElement element= JavaRefactoringDescriptorUtil.handleToElement(arguments.getProject(), handle, false);
			if (element == null || !element.exists() || element.getElementType() != IJavaElement.METHOD)
				return JavaRefactoringDescriptorUtil.createInputFatalStatus(element, getProcessorName(), IJavaRefactorings.CHANGE_METHOD_SIGNATURE);
			else {
				fMethod= (IMethod) element;
				fMethodName= fMethod.getElementName();
				try {
					fVisibility= JdtFlags.getVisibilityCode(fMethod);
					fReturnTypeInfo= new ReturnTypeInfo(Signature.toString(Signature.getReturnType(fMethod.getSignature())));
				} catch (JavaModelException exception) {
					return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_illegal_argument, new Object[] { Integer.valueOf(fVisibility),
							ATTRIBUTE_VISIBILITY }));
				}
			}
		} else
			return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JavaRefactoringDescriptorUtil.ATTRIBUTE_INPUT));
		final String name= arguments.getAttribute(JavaRefactoringDescriptorUtil.ATTRIBUTE_NAME);
		if (name != null) {
			fMethodName= name;
			final RefactoringStatus status= Checks.checkMethodName(fMethodName, fMethod);
			if (status.hasError())
				return status;
		} else
			return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JavaRefactoringDescriptorUtil.ATTRIBUTE_NAME));
		final String type= arguments.getAttribute(ATTRIBUTE_RETURN);
		if (type != null && !"".equals(type)) //$NON-NLS-1$
			fReturnTypeInfo.setNewTypeName(type);
		final String visibility= arguments.getAttribute(ATTRIBUTE_VISIBILITY);
		if (visibility != null && !"".equals(visibility)) {//$NON-NLS-1$
			int flag= 0;
			try {
				flag= Integer.parseInt(visibility);
			} catch (NumberFormatException exception) {
				return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_VISIBILITY));
			}
			fVisibility= flag;
		}
		int count= 1;
		String attribute= ATTRIBUTE_PARAMETER + count;
		String value= null;
		fParameterInfos= new ArrayList<>(3);
		while ((value= arguments.getAttribute(attribute)) != null) {
			StringTokenizer tokenizer= new StringTokenizer(value, " "); //$NON-NLS-1$
			if (tokenizer.countTokens() < 6)
				return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_illegal_argument, new Object[] { value, ATTRIBUTE_PARAMETER }));
			String oldTypeName= tokenizer.nextToken();
			String oldName= tokenizer.nextToken();
			String oldIndex= tokenizer.nextToken();
			String newTypeName= tokenizer.nextToken();
			String newName= tokenizer.nextToken();
			String deleted= tokenizer.nextToken();
			ParameterInfo info= null;
			try {
				int index= Integer.parseInt(oldIndex);
				if (index == -1) {
					String result= arguments.getAttribute(ATTRIBUTE_DEFAULT + count);
					if (result == null)
						result= ""; //$NON-NLS-1$
					info= ParameterInfo.createInfoForAddedParameter(newTypeName, newName, result);
				} else {
					info= new ParameterInfo(oldTypeName, oldName, index);
					info.setNewTypeName(newTypeName);
					info.setNewName(newName);
					if (Boolean.parseBoolean(deleted))
						info.markAsDeleted();
				}
				fParameterInfos.add(info);
			} catch (NumberFormatException exception) {
				return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_illegal_argument, new Object[] { value, ATTRIBUTE_PARAMETER }));
			}
			count++;
			attribute= ATTRIBUTE_PARAMETER + count;
		}
		count= 1;
		fExceptionInfos= new ArrayList<>(2);
		attribute= JavaRefactoringDescriptorUtil.ATTRIBUTE_ELEMENT + count;
		while ((value= arguments.getAttribute(attribute)) != null) {
			ExceptionInfo info= null;
			final String kind= arguments.getAttribute(ATTRIBUTE_KIND + count);
			if (kind != null) {
				final IJavaElement element= JavaRefactoringDescriptorUtil.handleToElement(arguments.getProject(), value, false);
				if (element == null || !element.exists())
					return JavaRefactoringDescriptorUtil.createInputFatalStatus(element, getProcessorName(), IJavaRefactorings.CHANGE_METHOD_SIGNATURE);
				else {
					try {
						info= new ExceptionInfo(element, Integer.parseInt(kind), null);
					} catch (NumberFormatException exception) {
						return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_illegal_argument, new Object[] { kind, ATTRIBUTE_KIND }));
					}
				}
			} else
				return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_illegal_argument, new Object[] { kind, ATTRIBUTE_KIND }));
			fExceptionInfos.add(info);
			count++;
			attribute= JavaRefactoringDescriptorUtil.ATTRIBUTE_ELEMENT + count;
		}
		final String deprecate= arguments.getAttribute(ATTRIBUTE_DEPRECATE);
		if (deprecate != null) {
			fDelegateDeprecation= Boolean.parseBoolean(deprecate);
		} else
			return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_DEPRECATE));
		final String delegate= arguments.getAttribute(ATTRIBUTE_DELEGATE);
		if (delegate != null) {
			fDelegateUpdating= Boolean.parseBoolean(delegate);
		} else
			return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_DELEGATE));
		return new RefactoringStatus();
	}

	/**
	 * If this occurrence update is called from within a declaration update
	 * (i.e., to update the call inside the newly created delegate), the old
	 * node does not yet exist and therefore cannot be a move target.
	 *
	 * Normally, always use createMoveTarget as this has the advantage of
	 * being able to add changes inside changed nodes (for example, a method
	 * call within a method call, see test case #4) and preserving comments
	 * inside calls.
	 * @param oldNode original node
	 * @param rewrite an AST rewrite
	 * @return the node to insert at the target location
	 */
	protected <T extends ASTNode> T moveNode(T oldNode, ASTRewrite rewrite) {
		T movedNode;
		if (ASTNodes.isExistingNode(oldNode))
			movedNode= ASTNodes.createMoveTarget(rewrite, oldNode); //node must be one of ast
		else
			movedNode= ASTNodes.copySubtree(rewrite.getAST(), oldNode);
		return movedNode;
	}

	public IDefaultValueAdvisor getDefaultValueAdvisor() {
		return fDefaultValueAdvisor;
	}

	public void setDefaultValueAdvisor(IDefaultValueAdvisor defaultValueAdvisor) {
		fDefaultValueAdvisor= defaultValueAdvisor;
	}

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

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

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

	@Override
	public RefactoringParticipant[] loadParticipants(RefactoringStatus status, SharableParticipants sharedParticipants) throws CoreException {
		String[] affectedNatures= JavaProcessors.computeAffectedNatures(fMethod);
		return JavaParticipantManager.loadChangeMethodSignatureParticipants(status, this, fMethod, getParticipantArguments(), null, affectedNatures, sharedParticipants);
	}
}
