/*******************************************************************************
 * Copyright (c) 2000, 2011 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Dmitry Stalnov (dstalnov@fusionone.com) - contributed fix for
 *       o bug "inline method - doesn't handle implicit cast" (see
 *         https://bugs.eclipse.org/bugs/show_bug.cgi?id=24941).
 *       o inline call that is used in a field initializer
 *         (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=38137)
 *       o inline call a field initializer: could detect self reference
 *         (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=44417)
 *******************************************************************************/
package org.eclipse.jdt.internal.corext.refactoring.code;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;

import org.eclipse.core.filebuffers.ITextFileBuffer;

import org.eclipse.text.edits.MalformedTreeException;
import org.eclipse.text.edits.MultiTextEdit;
import org.eclipse.text.edits.RangeMarker;
import org.eclipse.text.edits.TextEdit;
import org.eclipse.text.edits.TextEditProcessor;
import org.eclipse.text.edits.UndoEdit;

import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.text.TextUtilities;

import org.eclipse.ltk.core.refactoring.RefactoringStatus;

import org.eclipse.jdt.core.ITypeRoot;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.Block;
import org.eclipse.jdt.core.dom.CastExpression;
import org.eclipse.jdt.core.dom.ChildPropertyDescriptor;
import org.eclipse.jdt.core.dom.ClassInstanceCreation;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.ConditionalExpression;
import org.eclipse.jdt.core.dom.DoStatement;
import org.eclipse.jdt.core.dom.EnhancedForStatement;
import org.eclipse.jdt.core.dom.Expression;
import org.eclipse.jdt.core.dom.FieldAccess;
import org.eclipse.jdt.core.dom.ForStatement;
import org.eclipse.jdt.core.dom.IBinding;
import org.eclipse.jdt.core.dom.IMethodBinding;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.IVariableBinding;
import org.eclipse.jdt.core.dom.IfStatement;
import org.eclipse.jdt.core.dom.LabeledStatement;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.MethodInvocation;
import org.eclipse.jdt.core.dom.Modifier;
import org.eclipse.jdt.core.dom.Name;
import org.eclipse.jdt.core.dom.ParenthesizedExpression;
import org.eclipse.jdt.core.dom.ReturnStatement;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
import org.eclipse.jdt.core.dom.Statement;
import org.eclipse.jdt.core.dom.StructuralPropertyDescriptor;
import org.eclipse.jdt.core.dom.ThisExpression;
import org.eclipse.jdt.core.dom.WhileStatement;
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.internal.corext.codemanipulation.ContextSensitiveImportRewriteContext;
import org.eclipse.jdt.internal.corext.dom.ASTNodes;
import org.eclipse.jdt.internal.corext.dom.Bindings;
import org.eclipse.jdt.internal.corext.dom.CodeScopeBuilder;
import org.eclipse.jdt.internal.corext.dom.NecessaryParenthesesChecker;
import org.eclipse.jdt.internal.corext.refactoring.code.SourceAnalyzer.NameData;
import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringFileBuffers;
import org.eclipse.jdt.internal.corext.util.CodeFormatterUtil;
import org.eclipse.jdt.internal.corext.util.Strings;

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

/**
 * A SourceProvider encapsulates a piece of code (source) and the logic
 * to inline it into given CallContexts.
 */
public class SourceProvider {

	private ITypeRoot fTypeRoot;
	private IDocument fDocument;
	private MethodDeclaration fDeclaration;
	private SourceAnalyzer fAnalyzer;
	private boolean fMustEvalReturnedExpression;
	private boolean fReturnValueNeedsLocalVariable;
	private List<Expression> fReturnExpressions;
	private IDocument fSource;

	private static final int EXPRESSION_MODE= 1;
	private static final int STATEMENT_MODE= 2;
	private static final int RETURN_STATEMENT_MODE= 3;
	private int fMarkerMode;


	private class ReturnAnalyzer extends ASTVisitor {
		@Override
		public boolean visit(ReturnStatement node) {
			Expression expression= node.getExpression();
			if (!(ASTNodes.isLiteral(expression) || expression instanceof Name)) {
				fMustEvalReturnedExpression= true;
			}
			if (Invocations.isInvocation(expression) || expression instanceof ClassInstanceCreation) {
				fReturnValueNeedsLocalVariable= false;
			}
			fReturnExpressions.add(expression);
			return false;
		}
	}

	public SourceProvider(ITypeRoot typeRoot, MethodDeclaration declaration) {
		super();
		fTypeRoot= typeRoot;
		fDeclaration= declaration;
		List<SingleVariableDeclaration> parameters= fDeclaration.parameters();
		for (Iterator<SingleVariableDeclaration> iter= parameters.iterator(); iter.hasNext();) {
			SingleVariableDeclaration element= iter.next();
			ParameterData data= new ParameterData(element);
			element.setProperty(ParameterData.PROPERTY, data);
		}
		fAnalyzer= new SourceAnalyzer(fTypeRoot, fDeclaration);
		fReturnValueNeedsLocalVariable= true;
		fReturnExpressions= new ArrayList<Expression>();
	}

	/**
	 * TODO: unit's source does not match contents of source document and declaration node.
	 * @param typeRoot the type root
	 * @param source document containing the content of the type root
	 * @param declaration method declaration node
	 */
	public SourceProvider(ITypeRoot typeRoot, IDocument source, MethodDeclaration declaration) {
		this(typeRoot, declaration);
		fSource= source;
	}

	public RefactoringStatus checkActivation() throws JavaModelException {
		return fAnalyzer.checkActivation();
	}

	public void initialize() throws JavaModelException {
		fDocument= fSource == null ? new Document(fTypeRoot.getBuffer().getContents()) : fSource;
		fAnalyzer.initialize();
		if (hasReturnValue()) {
			ASTNode last= getLastStatement();
			if (last != null) {
				ReturnAnalyzer analyzer= new ReturnAnalyzer();
				last.accept(analyzer);
			}
		}
	}

	public boolean isExecutionFlowInterrupted() {
		return fAnalyzer.isExecutionFlowInterrupted();
	}

	static class VariableReferenceFinder extends ASTVisitor {
		private boolean fResult;
		private IVariableBinding fBinding;
		public VariableReferenceFinder(IVariableBinding binding) {
			fBinding= binding;
		}
		public boolean getResult() {
			return fResult;
		}
		@Override
		public boolean visit(SimpleName node) {
			if(!fResult) {
				fResult= Bindings.equals(fBinding, node.resolveBinding());
			}
			return false;
		}
	}

	/**
	 * Checks whether variable is referenced by the method declaration or not.
	 *
	 * @param binding binding of variable to check.
	 * @return <code>true</code> if variable is referenced by the method, otherwise <code>false</code>
	 */
	public boolean isVariableReferenced(IVariableBinding binding) {
		VariableReferenceFinder finder= new VariableReferenceFinder(binding);
		fDeclaration.accept(finder);
		return finder.getResult();
	}

	public boolean hasReturnValue() {
		IMethodBinding binding= fDeclaration.resolveBinding();
		return binding.getReturnType() != fDeclaration.getAST().resolveWellKnownType("void"); //$NON-NLS-1$
	}

	// returns true if the declaration has a vararg and
	// the body contains an array access to the vararg
	public boolean hasArrayAccess() {
		return fAnalyzer.hasArrayAccess();
	}

	public boolean hasSuperMethodInvocation() {
		return fAnalyzer.hasSuperMethodInvocation();
	}

	public boolean mustEvaluateReturnedExpression() {
		return fMustEvalReturnedExpression;
	}

	public boolean returnValueNeedsLocalVariable() {
		return fReturnValueNeedsLocalVariable;
	}

	public int getNumberOfStatements() {
		return fDeclaration.getBody().statements().size();
	}

	public boolean isSimpleFunction() {
		List<Statement> statements= fDeclaration.getBody().statements();
		if (statements.size() != 1)
			return false;
		return statements.get(0) instanceof ReturnStatement;
	}

	public boolean isLastStatementReturn() {
		List<Statement> statements= fDeclaration.getBody().statements();
		if (statements.size() == 0)
			return false;
		return statements.get(statements.size() - 1) instanceof ReturnStatement;
	}

	public boolean isDangligIf() {
		List<Statement> statements= fDeclaration.getBody().statements();
		if (statements.size() != 1)
			return false;

		ASTNode p= statements.get(0);

		while (true) {
			if (p instanceof IfStatement) {
				return ((IfStatement) p).getElseStatement() == null;
			} else {

				ChildPropertyDescriptor childD;
				if (p instanceof WhileStatement) {
					childD= WhileStatement.BODY_PROPERTY;
				} else if (p instanceof ForStatement) {
					childD= ForStatement.BODY_PROPERTY;
				} else if (p instanceof EnhancedForStatement) {
					childD= EnhancedForStatement.BODY_PROPERTY;
				} else if (p instanceof DoStatement) {
					childD= DoStatement.BODY_PROPERTY;
				} else if (p instanceof LabeledStatement) {
					childD= LabeledStatement.BODY_PROPERTY;
				} else {
					return false;
				}
				Statement body= (Statement) p.getStructuralProperty(childD);
				if (body instanceof Block) {
					return false;
				} else {
					p= body;
				}
			}
		}
	}

	public MethodDeclaration getDeclaration() {
		return fDeclaration;
	}

	public String getMethodName() {
		return fDeclaration.getName().getIdentifier();
	}

	public ITypeBinding getReturnType() {
		return fDeclaration.resolveBinding().getReturnType();
	}

	public List<Expression> getReturnExpressions() {
		return fReturnExpressions;
	}

	public boolean returnTypeMatchesReturnExpressions() {
		ITypeBinding returnType= getReturnType();
		for (Iterator<Expression> iter= fReturnExpressions.iterator(); iter.hasNext();) {
			Expression expression= iter.next();
			if (!Bindings.equals(returnType, expression.resolveTypeBinding()))
				return false;
		}
		return true;
	}

	public ParameterData getParameterData(int index) {
		SingleVariableDeclaration decl= (SingleVariableDeclaration)fDeclaration.parameters().get(index);
		return (ParameterData)decl.getProperty(ParameterData.PROPERTY);
	}

	public ITypeRoot getTypeRoot() {
		return fTypeRoot;
	}

	public boolean needsReturnedExpressionParenthesis(ASTNode parent, StructuralPropertyDescriptor locationInParent) {
		ASTNode last= getLastStatement();
		if (last instanceof ReturnStatement) {
			return NecessaryParenthesesChecker.needsParentheses(((ReturnStatement)last).getExpression(), parent, locationInParent);
		}
		return false;
	}

	public boolean returnsConditionalExpression() {
		ASTNode last= getLastStatement();
		if (last instanceof ReturnStatement) {
			return ((ReturnStatement)last).getExpression() instanceof ConditionalExpression;
		}
		return false;
	}

	public int getReceiversToBeUpdated() {
		return fAnalyzer.getImplicitReceivers().size();
	}

	public boolean isVarargs() {
		return fDeclaration.isVarargs();
	}

	public int getVarargIndex() {
		return fDeclaration.parameters().size() - 1;
	}

	public TextEdit getDeleteEdit() {
		final ASTRewrite rewriter= ASTRewrite.create(fDeclaration.getAST());
		rewriter.remove(fDeclaration, null);
		return rewriter.rewriteAST(fDocument, fTypeRoot.getJavaProject().getOptions(true));
	}

	public String[] getCodeBlocks(CallContext context, ImportRewrite importRewrite) throws CoreException {
		final ASTRewrite rewriter= ASTRewrite.create(fDeclaration.getAST());
		replaceParameterWithExpression(rewriter, context, importRewrite);
		updateImplicitReceivers(rewriter, context);
		makeNamesUnique(rewriter, context.scope);
		updateTypeReferences(rewriter, context);
		updateStaticReferences(rewriter, context);
		updateTypeVariables(rewriter, context);
		updateMethodTypeVariable(rewriter, context);

		List<IRegion> ranges= null;
		if (hasReturnValue()) {
			if (context.callMode == ASTNode.RETURN_STATEMENT) {
				ranges= getStatementRanges();
			} else {
				ranges= getExpressionRanges();
			}
		} else {
			ASTNode last= getLastStatement();
			if (last != null && last.getNodeType() == ASTNode.RETURN_STATEMENT) {
				ranges= getReturnStatementRanges();
			} else {
				ranges= getStatementRanges();
			}
		}

		final TextEdit dummy= rewriter.rewriteAST(fDocument, fTypeRoot.getJavaProject().getOptions(true));
		int size= ranges.size();
		RangeMarker[] markers= new RangeMarker[size];
		for (int i= 0; i < markers.length; i++) {
			IRegion range= ranges.get(i);
			markers[i]= new RangeMarker(range.getOffset(), range.getLength());
		}
		int split;
		if (size <= 1) {
			split= Integer.MAX_VALUE;
		} else {
			IRegion region= ranges.get(0);
			split= region.getOffset() + region.getLength();
		}
		TextEdit[] edits= dummy.removeChildren();
		for (int i= 0; i < edits.length; i++) {
			TextEdit edit= edits[i];
			int pos= edit.getOffset() >= split ? 1 : 0;
			markers[pos].addChild(edit);
		}
		MultiTextEdit root= new MultiTextEdit(0, fDocument.getLength());
		root.addChildren(markers);

		try {
			TextEditProcessor processor= new TextEditProcessor(fDocument, root, TextEdit.CREATE_UNDO | TextEdit.UPDATE_REGIONS);
			UndoEdit undo= processor.performEdits();
			String[] result= getBlocks(markers);
			// It is faster to undo the changes than coping the buffer over and over again.
			processor= new TextEditProcessor(fDocument, undo, TextEdit.UPDATE_REGIONS);
			processor.performEdits();
			return result;
		} catch (MalformedTreeException exception) {
			JavaPlugin.log(exception);
		} catch (BadLocationException exception) {
			JavaPlugin.log(exception);
		}
		return new String[] {};
	}

	private Expression createParenthesizedExpression(Expression newExpression, AST ast) {
		ParenthesizedExpression parenthesized= ast.newParenthesizedExpression();
		parenthesized.setExpression(newExpression);
		return parenthesized;
	}

	private void replaceParameterWithExpression(ASTRewrite rewriter, CallContext context, ImportRewrite importRewrite) throws CoreException {
		Expression[] arguments= context.arguments;
		try {
			ITextFileBuffer buffer= RefactoringFileBuffers.acquire(context.compilationUnit);
			for (int i= 0; i < arguments.length; i++) {
				Expression expression= arguments[i];
				String expressionString= null;
				if (expression instanceof SimpleName) {
					expressionString= ((SimpleName)expression).getIdentifier();
				} else {
					try {
						expressionString= buffer.getDocument().get(expression.getStartPosition(), expression.getLength());
					} catch (BadLocationException exception) {
						JavaPlugin.log(exception);
						continue;
					}
				}
				ParameterData parameter= getParameterData(i);
				List<SimpleName> references= parameter.references();
				for (Iterator<SimpleName> iter= references.iterator(); iter.hasNext();) {
					ASTNode element= iter.next();
					Expression newExpression= (Expression)rewriter.createStringPlaceholder(expressionString, expression.getNodeType());
					AST ast= rewriter.getAST();
					ITypeBinding explicitCast= ASTNodes.getExplicitCast(expression, (Expression)element);
					if (explicitCast != null) {
						CastExpression cast= ast.newCastExpression();
						if (NecessaryParenthesesChecker.needsParentheses(expression, cast, CastExpression.EXPRESSION_PROPERTY)) {
							newExpression= createParenthesizedExpression(newExpression, ast);
						}
						cast.setExpression(newExpression);
						ImportRewriteContext importRewriteContext= new ContextSensitiveImportRewriteContext(expression, importRewrite);
						cast.setType(importRewrite.addImport(explicitCast, ast, importRewriteContext));
						expression= newExpression= cast;
					}
					if (NecessaryParenthesesChecker.needsParentheses(expression, element.getParent(), element.getLocationInParent())) {
						newExpression= createParenthesizedExpression(newExpression, ast);
					}
					rewriter.replace(element, newExpression, null);
				}
			}
		} finally {
			RefactoringFileBuffers.release(context.compilationUnit);
		}
	}

	private void makeNamesUnique(ASTRewrite rewriter, CodeScopeBuilder.Scope scope) {
		Collection<NameData> usedCalleeNames= fAnalyzer.getUsedNames();
		for (Iterator<NameData> iter= usedCalleeNames.iterator(); iter.hasNext();) {
			SourceAnalyzer.NameData nd= iter.next();
			if (scope.isInUse(nd.getName())) {
				String newName= scope.createName(nd.getName(), true);
				List<SimpleName> references= nd.references();
				for (Iterator<SimpleName> refs= references.iterator(); refs.hasNext();) {
					SimpleName element= refs.next();
					ASTNode newNode= rewriter.createStringPlaceholder(newName, ASTNode.METHOD_INVOCATION);
					rewriter.replace(element, newNode, null);
				}
			}
		}
	}

	private void updateImplicitReceivers(ASTRewrite rewriter, CallContext context) {
		if (context.receiver == null)
			return;
		List<Expression> implicitReceivers= fAnalyzer.getImplicitReceivers();
		for (Iterator<Expression> iter= implicitReceivers.iterator(); iter.hasNext();) {
			ASTNode node= iter.next();
			ImportRewriteContext importRewriteContext= new ContextSensitiveImportRewriteContext(node, context.importer);
			if (node instanceof MethodInvocation) {
				final MethodInvocation inv= (MethodInvocation)node;
				rewriter.set(inv, MethodInvocation.EXPRESSION_PROPERTY, createReceiver(rewriter, context, (IMethodBinding)inv.getName().resolveBinding(), importRewriteContext), null);
			} else if (node instanceof ClassInstanceCreation) {
				final ClassInstanceCreation inst= (ClassInstanceCreation)node;
				rewriter.set(inst, ClassInstanceCreation.EXPRESSION_PROPERTY, createReceiver(rewriter, context, inst.resolveConstructorBinding(), importRewriteContext), null);
			} else if (node instanceof ThisExpression) {
				rewriter.replace(node, rewriter.createStringPlaceholder(context.receiver, ASTNode.METHOD_INVOCATION), null);
			} else if (node instanceof FieldAccess) {
				final FieldAccess access= (FieldAccess)node;
				rewriter.set(access, FieldAccess.EXPRESSION_PROPERTY, createReceiver(rewriter, context, access.resolveFieldBinding(), importRewriteContext), null);
			} else if (node instanceof SimpleName && ((SimpleName)node).resolveBinding() instanceof IVariableBinding) {
				IVariableBinding vb= (IVariableBinding)((SimpleName)node).resolveBinding();
				if (vb.isField()) {
					Expression receiver= createReceiver(rewriter, context, vb, importRewriteContext);
					if (receiver != null) {
						FieldAccess access= node.getAST().newFieldAccess();
						ASTNode target= rewriter.createMoveTarget(node);
						access.setName((SimpleName)target);
						access.setExpression(receiver);
						rewriter.replace(node, access, null);
					}
				}
			}
		}
	}

	private void updateTypeReferences(ASTRewrite rewriter, CallContext context) {
		ImportRewrite importer= context.importer;
		for (Iterator<SimpleName> iter= fAnalyzer.getTypesToImport().iterator(); iter.hasNext();) {
			Name element= iter.next();
			ITypeBinding binding= ASTNodes.getTypeBinding(element);
			if (binding != null && !binding.isLocal()) {
				// We have collected names not types. So we have to import
				// the declaration type if we reference a parameterized type
				// since we have an entry for every name node (e.g. one for
				// Vector and one for Integer in Vector<Integer>.
				if (binding.isParameterizedType()) {
					binding= binding.getTypeDeclaration();
				}
				String s= importer.addImport(binding);
				if (!ASTNodes.asString(element).equals(s)) {
					rewriter.replace(element, rewriter.createStringPlaceholder(s, ASTNode.SIMPLE_NAME), null);
				}
			}
		}
	}

	private void updateStaticReferences(ASTRewrite rewriter, CallContext context) {
		ImportRewrite importer= context.importer;
		for (Iterator<SimpleName> iter= fAnalyzer.getStaticsToImport().iterator(); iter.hasNext();) {
			Name element= iter.next();
			IBinding binding= element.resolveBinding();
			if (binding != null) {
				String s= importer.addStaticImport(binding);
				if (!ASTNodes.asString(element).equals(s)) {
					rewriter.replace(element, rewriter.createStringPlaceholder(s, ASTNode.SIMPLE_NAME), null);
				}
			}
		}

	}

	private Expression createReceiver(ASTRewrite rewriter, CallContext context, IMethodBinding method, ImportRewriteContext importRewriteContext) {
		String receiver= getReceiver(context, method.getModifiers(), importRewriteContext);
		if (receiver == null)
			return null;
		return (Expression)rewriter.createStringPlaceholder(receiver, ASTNode.METHOD_INVOCATION);
	}

	private Expression createReceiver(ASTRewrite rewriter, CallContext context, IVariableBinding field, ImportRewriteContext importRewriteContext) {
		String receiver= getReceiver(context, field.getModifiers(), importRewriteContext);
		if (receiver == null)
			return null;
		return (Expression)rewriter.createStringPlaceholder(receiver, ASTNode.SIMPLE_NAME);
	}

	private String getReceiver(CallContext context, int modifiers, ImportRewriteContext importRewriteContext) {
		String receiver= context.receiver;
		ITypeBinding invocationType= ASTNodes.getEnclosingType(context.invocation);
		ITypeBinding sourceType= fDeclaration.resolveBinding().getDeclaringClass();
		if (!context.receiverIsStatic && Modifier.isStatic(modifiers)) {
			if ("this".equals(receiver) && invocationType != null && Bindings.equals(invocationType, sourceType)) { //$NON-NLS-1$
				receiver= null;
			} else {
				receiver= context.importer.addImport(sourceType, importRewriteContext);
			}
		}
		return receiver;
	}

	private void updateTypeVariables(ASTRewrite rewriter, CallContext context) {
		ITypeBinding type= context.getReceiverType();
		if (type == null)
			return;
		rewriteReferences(rewriter, type.getTypeArguments(), fAnalyzer.getTypeParameterReferences());
	}

	private void updateMethodTypeVariable(ASTRewrite rewriter, CallContext context) {
		IMethodBinding method= Invocations.resolveBinding(context.invocation);
		if (method == null)
			return;
		rewriteReferences(rewriter, method.getTypeArguments(), fAnalyzer.getMethodTypeParameterReferences());
	}

	private void rewriteReferences(ASTRewrite rewriter, ITypeBinding[] typeArguments, List<NameData> typeParameterReferences) {
		if (typeArguments.length == 0)
			return;
		Assert.isTrue(typeArguments.length == typeParameterReferences.size());
		for (int i= 0; i < typeArguments.length; i++) {
			SourceAnalyzer.NameData refData= typeParameterReferences.get(i);
			List<SimpleName> references= refData.references();
			String newName= typeArguments[i].getName();
			for (Iterator<SimpleName> iter= references.iterator(); iter.hasNext();) {
				SimpleName name= iter.next();
				rewriter.replace(name, rewriter.createStringPlaceholder(newName, ASTNode.SIMPLE_NAME), null);
			}
		}
	}

	private ASTNode getLastStatement() {
		List<Statement> statements= fDeclaration.getBody().statements();
		if (statements.isEmpty())
			return null;
		return statements.get(statements.size() - 1);
	}

	private List<IRegion> getReturnStatementRanges() {
		fMarkerMode= RETURN_STATEMENT_MODE;
		List<IRegion> result= new ArrayList<IRegion>(1);
		List<Statement> statements= fDeclaration.getBody().statements();
		int size= statements.size();
		if (size <= 1)
			return result;
		result.add(createRange(statements, size - 2));
		return result;
	}

	private List<IRegion> getStatementRanges() {
		fMarkerMode= STATEMENT_MODE;
		List<IRegion> result= new ArrayList<IRegion>(1);
		List<Statement> statements= fDeclaration.getBody().statements();
		int size= statements.size();
		if (size == 0)
			return result;
		result.add(createRange(statements, size - 1));
		return result;
	}

	private List<IRegion> getExpressionRanges() {
		fMarkerMode= EXPRESSION_MODE;
		List<IRegion> result= new ArrayList<IRegion>(2);
		List<Statement> statements= fDeclaration.getBody().statements();
		ReturnStatement rs= null;
		int size= statements.size();
		ASTNode node;
		switch (size) {
			case 0:
				return result;
			case 1:
				node= statements.get(0);
				if (node.getNodeType() == ASTNode.RETURN_STATEMENT) {
					rs= (ReturnStatement)node;
				} else {
					result.add(createRange(node, node));
				}
				break;
			default: {
				node= statements.get(size - 1);
				if (node.getNodeType() == ASTNode.RETURN_STATEMENT) {
					result.add(createRange(statements, size - 2));
					rs= (ReturnStatement)node;
				} else {
					result.add(createRange(statements, size - 1));
				}
				break;
			}
		}
		if (rs != null) {
			Expression exp= rs.getExpression();
			result.add(createRange(exp, exp));
		}
		return result;
	}

	private IRegion createRange(List<Statement> statements, int end) {
		ASTNode first= statements.get(0);
		ASTNode last= statements.get(end);
		return createRange(first, last);
	}

	private IRegion createRange(ASTNode first, ASTNode last) {
		ASTNode root= first.getRoot();
		if (root instanceof CompilationUnit) {
			CompilationUnit unit= (CompilationUnit)root;
			int start= unit.getExtendedStartPosition(first);
			int length = unit.getExtendedStartPosition(last) - start + unit.getExtendedLength(last);
			IRegion range= new Region(start, length);
			return range;
		} else {
			int start= first.getStartPosition();
			int length = last.getStartPosition() - start + last.getLength();
			IRegion range= new Region(start, length);
			return range;
		}
	}

	private String[] getBlocks(RangeMarker[] markers) throws BadLocationException {
		String[] result= new String[markers.length];
		for (int i= 0; i < markers.length; i++) {
			RangeMarker marker= markers[i];
			String content= fDocument.get(marker.getOffset(), marker.getLength());
			String lines[]= Strings.convertIntoLines(content);
			Strings.trimIndentation(lines, fTypeRoot.getJavaProject(), false);
			if (fMarkerMode == STATEMENT_MODE && lines.length == 2 && isSingleControlStatementWithoutBlock()) {
				lines[1]= CodeFormatterUtil.createIndentString(1, fTypeRoot.getJavaProject()) + lines[1];
			}
			result[i]= Strings.concatenate(lines, TextUtilities.getDefaultLineDelimiter(fDocument));
		}
		return result;
	}

	private boolean isSingleControlStatementWithoutBlock() {
		List<Statement> statements= fDeclaration.getBody().statements();
		int size= statements.size();
		if (size != 1)
			return false;
		Statement statement= statements.get(size - 1);
		int nodeType= statement.getNodeType();
		if (nodeType == ASTNode.IF_STATEMENT) {
			IfStatement ifStatement= (IfStatement) statement;
			return !(ifStatement.getThenStatement() instanceof Block)
				&& !(ifStatement.getElseStatement() instanceof Block);
		} else if (nodeType == ASTNode.FOR_STATEMENT) {
			return !(((ForStatement)statement).getBody() instanceof Block);
		} else if (nodeType == ASTNode.WHILE_STATEMENT) {
			return !(((WhileStatement)statement).getBody() instanceof Block);
		}
		return false;
	}
}
