/*******************************************************************************
 * Copyright (c) 2000, 2006 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.jdt.internal.corext.fix;

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

import org.eclipse.text.edits.TextEditGroup;

import org.eclipse.core.runtime.CoreException;

import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaProject;
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.ArrayAccess;
import org.eclipse.jdt.core.dom.Assignment;
import org.eclipse.jdt.core.dom.Block;
import org.eclipse.jdt.core.dom.CompilationUnit;
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.ITypeBinding;
import org.eclipse.jdt.core.dom.InfixExpression;
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.NumberLiteral;
import org.eclipse.jdt.core.dom.PostfixExpression;
import org.eclipse.jdt.core.dom.PrefixExpression;
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.Statement;
import org.eclipse.jdt.core.dom.SuperFieldAccess;
import org.eclipse.jdt.core.dom.Type;
import org.eclipse.jdt.core.dom.VariableDeclaration;
import org.eclipse.jdt.core.dom.VariableDeclarationExpression;
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
import org.eclipse.jdt.core.dom.VariableDeclarationStatement;
import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
import org.eclipse.jdt.core.dom.rewrite.ITrackedNodePosition;
import org.eclipse.jdt.core.dom.rewrite.ImportRewrite;
import org.eclipse.jdt.core.dom.rewrite.ListRewrite;

import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility;
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.ModifierRewrite;
import org.eclipse.jdt.internal.corext.dom.ScopeAnalyzer;
import org.eclipse.jdt.internal.corext.fix.LinkedFix.AbstractLinkedFixRewriteOperation;
import org.eclipse.jdt.internal.corext.refactoring.structure.CompilationUnitRewrite;
import org.eclipse.jdt.internal.corext.util.JavaModelUtil;


public class ConvertForLoopOperation extends AbstractLinkedFixRewriteOperation {

	private ForStatement fOldForStatement;
	private EnhancedForStatement fEnhancedForStatement;
	private AST fAst;
	private Name fCollectionName;
	private SingleVariableDeclaration fParameterDeclaration;
	private ITypeBinding fOldCollectionTypeBinding;
	private IBinding fOldCollectionBinding;
	private IBinding fIndexBinding;
	private boolean fCollectionIsMethodCall= false;
	private MethodInvocation fMethodInvocation;
	private final String fParameterName;
	private final ICompilationUnit fCompilationUnit;
	private FieldAccess fFieldAccess;
	private final CompilationUnit fRoot;
	private final boolean fAddBlock;
	private final boolean fRemoveUnnecessaryBlocks;

	/**
	 * Visitor class for finding all references to a certain Name within the
	 * specified scope (e.g. finds all references to a local variable within the
	 * Body of a For loop).
	 */
	private class LocalOccurencesFinder extends ASTVisitor {

		private List fOccurences;
		private ASTNode fScope;
		private IBinding fTempBinding;
		private ITypeBinding fTempTypeBinding;

		/**
		 * @param collectionName The inferred name of the collection to be
		 *        iterated over
		 * @param oldCollectionBinding The binding of the inferred collection
		 * @param oldCollectionTypeBinding The type binding of the inferred
		 *        collection
		 * @param scope The scope of the search (i.e. the body of a For
		 *        Statement
		 */
		public LocalOccurencesFinder(Name collectionName, IBinding oldCollectionBinding, ITypeBinding oldCollectionTypeBinding,
			ASTNode scope) {
			this.fScope= scope;
			fOccurences= new ArrayList();
			fTempBinding= oldCollectionBinding;
			fTempTypeBinding= oldCollectionTypeBinding;
		}

		public LocalOccurencesFinder(Name name, ASTNode scope) {
			this.fScope= scope;
			fOccurences= new ArrayList();
			fTempBinding= name.resolveBinding();
		}

		public LocalOccurencesFinder(IBinding binding, ASTNode scope) {
			this.fScope= scope;
			fOccurences= new ArrayList();
			fTempBinding= binding;
		}

		public void perform() {
			fScope.accept(this);
		}

		public boolean visit(SimpleName node) {
			if (node.getParent() instanceof VariableDeclaration) {
				if (((VariableDeclaration)node.getParent()).getName() == node)
					return true; //don't include declaration
			}
			if (fTempBinding != null && Bindings.equals(fTempBinding, node.resolveBinding())) {
				fOccurences.add(node);
			}
			return true;
		}

		public boolean visit(MethodInvocation methodInvocation) {
			ArrayAccess arrayAccess= (ArrayAccess)ASTNodes.getParent(methodInvocation, ArrayAccess.class);
			if (arrayAccess != null && fTempTypeBinding != null
					&& Bindings.equals(fTempBinding, methodInvocation.resolveMethodBinding())) {
				fOccurences.add(arrayAccess);
				return false;
			}
			return true;
		}

		public List getOccurences() {
			return fOccurences;
		}
	}

	/**
	 * @param forStatement The For statement to be converted
	 * @param root 
	 * @param addBlock 
	 * @param removeUnnecessaryBlocks 
	 */
	public ConvertForLoopOperation(CompilationUnit root, ForStatement forStatement, String parameterName, boolean addBlock, boolean removeUnnecessaryBlocks) {
		fRoot= root;
		fAddBlock= addBlock;
		fRemoveUnnecessaryBlocks= removeUnnecessaryBlocks;
		fCompilationUnit= (ICompilationUnit)root.getJavaElement();
		this.fOldForStatement= forStatement;
		fAst= root.getAST();
		fParameterName= parameterName;
	}

	/**
	 * Check if the OldFor can be converted to Enhanced For. Unless all
	 * preconditions hold true, there is no reason for this QuickAssist to pop
	 * up.
	 *
	 * @return true if all preconditions (arrayCanBeInferred &&
	 *         arrayOrIndexNotAssignedTo indexNotReferencedOutsideInferredArray &&
	 *         onlyOneIndexUsed && additionalTempsNotReferenced) are satisfied
	 */
	public boolean satisfiesPreconditions() {
		return JavaModelUtil.is50OrHigher(fCompilationUnit.getJavaProject())
			&& fOldForStatement.getExpression() != null
			&& arrayCanBeInferred()
			&& typeBindingsAreNotNull()
			&& bodySatifiesPreconditions()
			&& initializersSatisfyPreconditions()
			&& updatersSatifyPreconditions();
	}

	private boolean typeBindingsAreNotNull() {
		fIndexBinding= getIndexBinding();
		return fOldCollectionBinding != null && fOldCollectionTypeBinding != null && fIndexBinding != null;
	}

	private boolean bodySatifiesPreconditions() {
		// checks in a single pass through Loop's body that arrayOrIndexNotAssignedTo
		// and indexNotReferencedOutsideInferredArray
		final List writeAccesses= new ArrayList();
		final boolean isIndexReferenced[]= {false};

		fOldForStatement.getBody().accept(new ASTVisitor() {
			public boolean visit(Assignment assignment) {
				classifyWriteAccess(assignment.getLeftHandSide());
				return true;
			}
			public boolean visit(PostfixExpression node) {
				classifyWriteAccess(node.getOperand());
				return true;
			}
			public boolean visit(PrefixExpression node) {
				classifyWriteAccess(node.getOperand());
				return true;
			}
			public boolean visit(SimpleName name) {
				IBinding binding= name.resolveBinding();
				if (Bindings.equals(fIndexBinding, binding)) {
					ASTNode parent= name.getParent();
					// check if the direct parent is an ArrayAcces
					if (parent instanceof ArrayAccess){
						// even if the Index is referenced within an ArrayAccess
						// it could happen that the Array is not the same as the
						// inferred Array

						// On fixing bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=73890
						// had to treat the case when indexNotReferenced flag does not get overridden
						// by subsequent passes through this loop
						isIndexReferenced[0]= isIndexReferenced[0] || isAccessToADifferentArray((ArrayAccess)parent);
					}
					else {
						//otherwise the Index is referenced outside ArrayAccess
						isIndexReferenced[0]= true;
					}
				}
				return false;
			}
			private void classifyWriteAccess(Expression expression) {
				//check that
				if (expression instanceof ArrayAccess) {
					checkThatArrayIsNotAssigned(writeAccesses, expression);
				} else if (expression instanceof Name) {
					checkThatIndexIsNotAssigned(writeAccesses, expression);
				}
			}
		});
		return writeAccesses.isEmpty() && !isIndexReferenced[0];
	}

	private void checkThatIndexIsNotAssigned(final List writeAccesses, Expression expression) {
		Name name= (Name)expression;
		IBinding binding= name.resolveBinding();
		if (binding == fIndexBinding) {
			writeAccesses.add(name);
		}
	}

	private void checkThatArrayIsNotAssigned(final List writeAccesses, Expression expression) {
		ArrayAccess arrayAccess= (ArrayAccess)expression;
		Expression array= arrayAccess.getArray();
		IBinding binding= null;
		if (array instanceof Name) {
			binding= ((Name)array).resolveBinding();
		} else if (array instanceof FieldAccess) {
			binding= ((FieldAccess)array).resolveFieldBinding();
		} else if (array instanceof SuperFieldAccess) {
			binding= ((SuperFieldAccess)array).resolveFieldBinding();
		}
		if (binding == fOldCollectionBinding)
			writeAccesses.add(arrayAccess);
	}

	private boolean isAccessToADifferentArray(ArrayAccess arrayAccess) {
		Expression expression= arrayAccess.getArray();
		if (expression instanceof Name) {
			return isNameDifferentThanInferredArray((Name)expression);
		} else if (expression instanceof FieldAccess){
			FieldAccess fieldAccess= (FieldAccess)expression;
			return isNameDifferentThanInferredArray(fieldAccess.getName());
		} else if (expression instanceof MethodInvocation){
			//Be more conservative here, just because it's the same name
			//does not imply that it is the same array. The method can
			//return different arrays. It could even be a method call on
			//a different object. https://bugs.eclipse.org/bugs/show_bug.cgi?id=138353
			return true;
		}else {
			return true; //conservative approach: if it doesn't fall within the above cases
						 // I return that it's an access to a different Array (causing the precondition
						 // to fail)
		}
	}

	private boolean isNameDifferentThanInferredArray(Name name) {
		IBinding arrayBinding= name.resolveBinding();
		if (!Bindings.equals(fOldCollectionBinding, arrayBinding)) {
			return true;
		}
		return false;
	}

	private boolean updatersSatifyPreconditions() {
		return onlyOneIndexUsed() && indexNotDecremented();
	}

	private boolean indexNotDecremented() {
		ASTNode updater= (ASTNode)fOldForStatement.updaters().get(0);

		if (updater instanceof PostfixExpression) {
			if ("++".equals(((PostfixExpression)updater).getOperator().toString())) //$NON-NLS-1$
				return true;
		}

		if (updater instanceof PrefixExpression){
			if ("++".equals(((PrefixExpression)updater).getOperator().toString())) //$NON-NLS-1$
				return true;
		}
		return false;
	}

	private boolean initializersSatisfyPreconditions(){
		// Only one pass through Initializers
		// check if startsFromZero and additionalTempsNotReferenced

		final List tempVarsInInitializers= new ArrayList();
		final boolean startsFromZero[] = {false};
		List initializers= fOldForStatement.initializers();

		for (Iterator iter = initializers.iterator(); iter.hasNext();) {
			Expression element = (Expression) iter.next();
			if (!(element instanceof VariableDeclarationExpression))
				return false;
			
			element.accept(new ASTVisitor(){
				public boolean visit(VariableDeclarationFragment declarationFragment){
					Name indexName= declarationFragment.getName();
					tempVarsInInitializers.add(indexName);
					startsFromZero[0]= doesIndexStartFromZero(indexName, declarationFragment);
					return false;
				}
				public boolean visit(Assignment assignment){
					if (assignment.getLeftHandSide() instanceof Name) {
						Name indexName= (Name) assignment.getLeftHandSide();
						tempVarsInInitializers.add(indexName);
						startsFromZero[0]= doesIndexStartFromZero(indexName, assignment);
					}
					return false;
				}
			});
		}

		removeInferredIndexFrom(tempVarsInInitializers);

		return startsFromZero[0] && additionalTempsNotReferenced(tempVarsInInitializers);
	}

	private boolean doesIndexStartFromZero(Name indexName, ASTNode declaringNode) {
		IBinding binding= indexName.resolveBinding();
		if (Bindings.equals(fIndexBinding, binding)){
			Expression initializer = null;
			if (declaringNode instanceof VariableDeclarationFragment){
				initializer= ((VariableDeclarationFragment)declaringNode).getInitializer();
			} else if (declaringNode instanceof Assignment){
				initializer= ((Assignment) declaringNode).getRightHandSide();
			}

			if (initializer instanceof NumberLiteral){
				NumberLiteral number= (NumberLiteral) initializer;
				if (! "0".equals(number.getToken())) { //$NON-NLS-1$
					return false;
				}
			} else {
				//variable or method call, most probably not 0...
				//could also be a constant which is 0, but who would define such a constant?
				return false;
			}
		}
		return true; // we have to return true also for the cases when we test another variable besides
					 // Inferred Index
	}



	private void removeInferredIndexFrom(List localTemps) {
		Name indexName= null;
		for (Iterator iter= localTemps.iterator(); iter.hasNext();) {
			Name name= (Name)iter.next();
			IBinding binding= name.resolveBinding();
			//fIndexBinding has already been initialized via typeBindingsAreNotNull()
			if (Bindings.equals(fIndexBinding, binding)) {
				indexName= name;
				break;
			}
		}
		localTemps.remove(indexName);
	}

	private boolean additionalTempsNotReferenced(List localTemps) {
		for (Iterator iter= localTemps.iterator(); iter.hasNext();) {
			Name name= (Name)iter.next();
			LocalOccurencesFinder finder= new LocalOccurencesFinder(name, fOldForStatement.getBody());
			finder.perform();
			if (!finder.getOccurences().isEmpty())
				return false;
		}
		return true;
	}

	private boolean onlyOneIndexUsed() {
		return fOldForStatement.updaters().size() == 1;
	}

	private boolean arrayCanBeInferred() {
		doInferCollection();
		return (fCollectionName != null)
			&& fOldCollectionTypeBinding != null
			// for now, only iteration over Arrays are handled
			&& (fOldCollectionTypeBinding.isArray());
	}

	private IBinding inferIndexBinding() {
		List initializers= fOldForStatement.initializers();
		if (initializers.size() == 0)
			return null;
		
		Expression expression= (Expression)initializers.get(0);
		if (expression instanceof VariableDeclarationExpression) {
			VariableDeclarationFragment declaration= (VariableDeclarationFragment)((VariableDeclarationExpression)expression)
				.fragments().get(0);
			Name indexName= declaration.getName();
			fIndexBinding= indexName.resolveBinding();
		} else if (expression instanceof Assignment) {
			Assignment assignment= (Assignment)expression;
			Expression lhs= assignment.getLeftHandSide();
			if (lhs instanceof Name) {
				Name indexName= (Name)lhs;
				fIndexBinding= indexName.resolveBinding();
			}
		}
		return fIndexBinding;
	}

	private ITrackedNodePosition doConvert(ASTRewrite rewrite, ImportRewrite importRewrite, TextEditGroup group) throws CoreException {
		doInferCollection();
		doInferElement(importRewrite);
		doFindAndReplaceInBody(rewrite, group);

		AST ast= fOldForStatement.getAST();
		fEnhancedForStatement= ast.newEnhancedForStatement();
		if (fAddBlock && !(fOldForStatement.getBody() instanceof Block)) {
			Statement theBody= (Statement)rewrite.createMoveTarget(fOldForStatement.getBody());
			Block newBody= ast.newBlock();
			ListRewrite listRewrite= rewrite.getListRewrite(newBody, Block.STATEMENTS_PROPERTY);
			listRewrite.insertFirst(theBody, group);
			fEnhancedForStatement.setBody(newBody);
		} else if (fRemoveUnnecessaryBlocks && fOldForStatement.getBody() instanceof Block && ((Block)fOldForStatement.getBody()).statements().size() == 1) {
			Statement moveTarget= (Statement)rewrite.createMoveTarget((Statement)((Block)fOldForStatement.getBody()).statements().get(0));
			fEnhancedForStatement.setBody(moveTarget);
		} else {
			Statement theBody= (Statement)rewrite.createMoveTarget(fOldForStatement.getBody());
			fEnhancedForStatement.setBody(theBody);
		}
		fEnhancedForStatement.setExpression(createExpression(rewrite, ast));
		fEnhancedForStatement.setParameter(fParameterDeclaration);
		PositionGroup pg= getPositionGroup(fParameterName);
		pg.addFirstPosition(rewrite.track(fParameterDeclaration.getName()));

		String name= fParameterDeclaration.getName().getIdentifier();

		List proposals= getProposalsForElement();
		if (!proposals.contains(name))
			proposals.add(0, name);

		for (Iterator iterator= proposals.iterator(); iterator.hasNext();)
			pg.addProposal((String) iterator.next(), null);

		rewrite.replace(fOldForStatement, fEnhancedForStatement, group);
		return null;
	}

	private Expression createExpression(ASTRewrite rewrite, AST ast) {
		if (fCollectionIsMethodCall) {
			MethodInvocation methodCall= (MethodInvocation) rewrite.createMoveTarget(fMethodInvocation);
			return methodCall;
		} else
			if (fFieldAccess != null) {
				return (FieldAccess)rewrite.createMoveTarget(fFieldAccess);
			}
			return fCollectionName;
	}

	private List getProposalsForElement() {
		List list= new ArrayList();
		ICompilationUnit icu= fCompilationUnit;
		IJavaProject javaProject= icu.getJavaProject();
		int dimensions= fOldCollectionTypeBinding.getDimensions() - 1;
		final List used= getUsedVariableNames();
		String type= fOldCollectionTypeBinding.getName();
		if (fOldCollectionTypeBinding.isArray())
			type= fOldCollectionTypeBinding.getElementType().getName();
		String[] proposals= StubUtility.getLocalNameSuggestions(javaProject, type, dimensions, (String[]) used.toArray(new String[used.size()]));
		for (int i= 0; i < proposals.length; i++) {
			list.add(proposals[i]);
		}
		return list;
	}

	private List getUsedVariableNames() {
		CompilationUnit root= (CompilationUnit)fOldForStatement.getRoot();
		IBinding[] varsBefore= (new ScopeAnalyzer(root)).getDeclarationsInScope(fOldForStatement.getStartPosition(),
			ScopeAnalyzer.VARIABLES);
		IBinding[] varsAfter= (new ScopeAnalyzer(root)).getDeclarationsAfter(fOldForStatement.getStartPosition()
			+ fOldForStatement.getLength(), ScopeAnalyzer.VARIABLES);

		List names= new ArrayList();
		for (int i= 0; i < varsBefore.length; i++) {
			names.add(varsBefore[i].getName());
		}
		for (int i= 0; i < varsAfter.length; i++) {
			names.add(varsAfter[i].getName());
		}
		return names;
	}

	private void doFindAndReplaceInBody(ASTRewrite rewrite, TextEditGroup group) {
		LocalOccurencesFinder finder= new LocalOccurencesFinder(fCollectionName, fOldCollectionBinding,
			fOldCollectionTypeBinding, fOldForStatement.getBody());
		finder.perform();
		List occurences= finder.getOccurences();

		// this might be the "ideal" case (exercised in testNiceReduction)
		if (occurences.size() == 1) {
			ASTNode soleOccurence= (ASTNode)occurences.get(0);
			ArrayAccess arrayAccess= soleOccurence instanceof ArrayAccess
				? (ArrayAccess)soleOccurence
				: (ArrayAccess)ASTNodes.getParent(soleOccurence, ArrayAccess.class);
			if (arrayAccess != null) {
				if (arrayAccess.getParent() instanceof VariableDeclarationFragment) {
					replaceSingleVariableDeclaration(rewrite, arrayAccess, group);
					return;
				}
			}
		}

		replaceMultipleOccurences(rewrite, occurences, group);
	}

	private void replaceSingleVariableDeclaration(ASTRewrite rewrite, ArrayAccess arrayAccess, TextEditGroup group) {
		VariableDeclarationFragment declarationFragment= (VariableDeclarationFragment)arrayAccess.getParent();
		VariableDeclarationStatement declarationStatement= (VariableDeclarationStatement)declarationFragment.getParent();

		// if could not infer THE_ELEMENT from infer step, we might
		// be able to infer it from here
		if (fParameterDeclaration == null) {
			fParameterDeclaration= fAst.newSingleVariableDeclaration();
		}

		SimpleName theTempVariable= declarationFragment.getName();

		SimpleName name= fAst.newSimpleName(theTempVariable.getIdentifier());
		Type type= ASTNodeFactory.newType(getAst(), declarationFragment);
		fParameterDeclaration.setName(name);
		fParameterDeclaration.setType(type);
		if (ASTNodes.findModifierNode(Modifier.FINAL, declarationStatement.modifiers()) != null) {
			ModifierRewrite.create(rewrite, fParameterDeclaration).setModifiers(Modifier.FINAL, Modifier.NONE, group);
		}
		

		LocalOccurencesFinder finder2= new LocalOccurencesFinder(theTempVariable.resolveBinding(), fOldForStatement.getBody());
		finder2.perform();
		List occurences2= finder2.getOccurences();

		linkAllReferences(rewrite, occurences2);

		rewrite.replace(declarationStatement, null, group);
		return;
	}

	private void linkAllReferences(ASTRewrite rewrite, List occurences) {
		for (Iterator iter= occurences.iterator(); iter.hasNext();) {
			ASTNode variableRef= (ASTNode)iter.next();
			getPositionGroup(fParameterName).addPosition(rewrite.track(variableRef));
		}
	}

	private void replaceMultipleOccurences(ASTRewrite rewrite, List occurences, TextEditGroup group) {
		for (Iterator iter= occurences.iterator(); iter.hasNext();) {
			ASTNode element= (ASTNode)iter.next();
			ArrayAccess arrayAccess= element instanceof ArrayAccess ? (ArrayAccess)element : (ArrayAccess)ASTNodes.getParent(
				element, ArrayAccess.class);
			if (arrayAccess != null) {
				SimpleName elementReference= fAst.newSimpleName(fParameterDeclaration.getName().getIdentifier());

				rewrite.replace(arrayAccess, elementReference, group);
				getPositionGroup(fParameterName).addPosition(rewrite.track(elementReference));

			}
		}
	}

	private void doInferElement(ImportRewrite importRewrite) throws CoreException {
		if (fCollectionName == null) {
			createDefaultParameter();
		} else {
			if (fOldCollectionTypeBinding.isArray()) {
				final ITypeBinding elementType= fOldCollectionTypeBinding.getElementType();
				fParameterDeclaration= fAst.newSingleVariableDeclaration();
				SimpleName name= fAst.newSimpleName(fParameterName);
				fParameterDeclaration.setName(name);

				Type theType= importType(elementType, fOldForStatement, importRewrite, fRoot);
				if (fOldCollectionTypeBinding.getDimensions() != 1) {
					theType= fAst.newArrayType(theType, fOldCollectionTypeBinding.getDimensions() - 1);
				}
				fParameterDeclaration.setType(theType);
			}
		}
	}

	private void createDefaultParameter() {
		fParameterDeclaration= fAst.newSingleVariableDeclaration();
		SimpleName name= fAst.newSimpleName(fParameterName);
		Type type= fAst.newPrimitiveType(PrimitiveType.INT);
		fParameterDeclaration.setName(name);
		fParameterDeclaration.setType(type);
	}

	// Caches the inferred collection name and its bindings in local fields. These
	// won't change during the whole operation of the QuickFix.
	private void doInferCollection() {
		if (fCollectionName != null)
			return;

		doInferCollectionFromExpression();

		if (fCollectionName == null)
			doInferCollectionFromInitializers();

	}

	private void doInferCollectionFromExpression() {
		Expression stopCondition= fOldForStatement.getExpression();
		if (stopCondition.getNodeType() == ASTNode.INFIX_EXPRESSION) {
			Expression rightOperand= ((InfixExpression)stopCondition).getRightOperand();
			if (rightOperand.getNodeType() == ASTNode.QUALIFIED_NAME) {
				Name qualifier= ((QualifiedName)rightOperand).getQualifier();
				fCollectionName= ASTNodeFactory.newName(fAst,qualifier.getFullyQualifiedName());
				fOldCollectionBinding= qualifier.resolveBinding();
				fOldCollectionTypeBinding= qualifier.resolveTypeBinding();
			} else if (rightOperand.getNodeType() == ASTNode.METHOD_INVOCATION) {
				MethodInvocation methodCall= (MethodInvocation)rightOperand;
				Expression exp= methodCall.getExpression();
				if (exp instanceof Name) {
					Name collectionName= (Name)exp;
					fOldCollectionBinding= collectionName.resolveBinding();
					fOldCollectionTypeBinding= collectionName.resolveTypeBinding();
					fCollectionName= ASTNodeFactory.newName(fAst,collectionName.getFullyQualifiedName());
				}
			} else if (rightOperand instanceof FieldAccess){
				// this treats the case when the stop condition is a method call or field access
				// which returns an Array on which the "length" field is queried
				FieldAccess fieldAccess= (FieldAccess) rightOperand;
				if ("length".equals(fieldAccess.getName().getIdentifier())) { //$NON-NLS-1$
					if (fieldAccess.getExpression() instanceof MethodInvocation){
						fCollectionIsMethodCall= true;
						MethodInvocation methodCall= (MethodInvocation) fieldAccess.getExpression();
						fMethodInvocation= methodCall;
						fOldCollectionBinding= methodCall.resolveMethodBinding();
						fOldCollectionTypeBinding= methodCall.resolveTypeBinding();
						fCollectionName= ASTNodeFactory.newName(fAst, methodCall.getName().getFullyQualifiedName());
					} else if (fieldAccess.getExpression() instanceof FieldAccess) {
						FieldAccess fieldCall= (FieldAccess)fieldAccess.getExpression();
						fFieldAccess= fieldCall;
						fOldCollectionBinding= fieldCall.resolveFieldBinding();
						fOldCollectionTypeBinding= fieldCall.resolveTypeBinding();
						fCollectionName= ASTNodeFactory.newName(fAst, fieldCall.getName().getFullyQualifiedName());
					}
				}

			}
		}
	}

	private void doInferCollectionFromInitializers() {
		List initializers= fOldForStatement.initializers();
		for (Iterator iter= initializers.iterator(); iter.hasNext();) {
			Object next= iter.next();
			if (next instanceof VariableDeclarationExpression) {
				VariableDeclarationExpression element= (VariableDeclarationExpression)next;
				List declarationFragments= element.fragments();
				for (Iterator iterator= declarationFragments.iterator(); iterator.hasNext();) {
					VariableDeclarationFragment fragment= (VariableDeclarationFragment)iterator.next();
					Expression initializer= fragment.getInitializer();
					if (initializer != null)
						doInferCollectionFromExpression(initializer);
				}
			} else if (next instanceof Assignment) {
				Assignment assignemnt= (Assignment)next;
				doInferCollectionFromExpression(assignemnt.getRightHandSide());
			}
		}
	}

	/**
	 * @param expression Expression to visit. This helper method is useful
	 *        for the IDIOM when the stop condition is expressed with another
	 *        variable within loop: for (int i=0, max= array.length; i < max;
	 *        i++){}
	 */
	private void doInferCollectionFromExpression(Expression expression) {
		final boolean[] foundMoreThenOneArray= new boolean[1];
		foundMoreThenOneArray[0]= false;
		expression.accept(new ASTVisitor() {
			public boolean visit(QualifiedName qualifiedName) {
				initializeBindings(qualifiedName.getQualifier());
				return false;
			}
			public boolean visit(SimpleName simpleName) {
				initializeBindings(simpleName);
				return false;
			}
			public boolean visit(MethodInvocation methodCall){
				ITypeBinding typeBinding= methodCall.resolveTypeBinding();
				if (typeBinding.isArray()){
					fCollectionIsMethodCall= true;
					fMethodInvocation= methodCall;
					fOldCollectionTypeBinding= typeBinding;
					fOldCollectionBinding= methodCall.resolveMethodBinding();
					fCollectionName= ASTNodeFactory.newName(fAst, methodCall.getName().getFullyQualifiedName());
				}
				return false;
			}
			public boolean visit(FieldAccess field) {
				if (initializeBindings(field.getName())) {
					fFieldAccess= field;
				}
				return true;
			}
			private boolean initializeBindings(Name name) {
				ITypeBinding typeBinding= name.resolveTypeBinding();
				if (typeBinding != null && typeBinding.isArray()) {
					fOldCollectionTypeBinding= typeBinding;
					if (fOldCollectionBinding == null) {
						fOldCollectionBinding= name.resolveBinding();
						fCollectionName= ASTNodeFactory.newName(fAst,name.getFullyQualifiedName());
						return true;
					} else {
						if (name.resolveBinding() != fOldCollectionBinding) {
							foundMoreThenOneArray[0]= true;
						}
						return true;
					}
				}
				return false;
			}
		});
		if (foundMoreThenOneArray[0]) {
			fOldCollectionBinding= null;
			fCollectionName= null;
		}
	}

	private AST getAst() {
		return fAst;
	}

	// lazy load. Caches the binding of the For's index in a field since it cannot
	// be change during the whole QuickFix
	private IBinding getIndexBinding(){
		if (fIndexBinding != null)
			return fIndexBinding;
		else return inferIndexBinding();
	}

	/* (non-Javadoc)
	 * @see org.eclipse.jdt.internal.corext.fix.LinkedFix.ILinkedFixRewriteOperation#rewriteAST(org.eclipse.jdt.internal.corext.refactoring.structure.CompilationUnitRewrite, java.util.List, java.util.List)
	 */
	public ITrackedNodePosition rewriteAST(CompilationUnitRewrite cuRewrite, List textEditGroups, List positionGroups) throws CoreException {
		TextEditGroup group= createTextEditGroup(FixMessages.Java50Fix_ConvertToEnhancedForLoop_description);
		textEditGroups.add(group);
		clearPositionGroups();
		ITrackedNodePosition endPosition= doConvert(cuRewrite.getASTRewrite(), cuRewrite.getImportRewrite(), group);
		positionGroups.addAll(getAllPositionGroups());
		return endPosition;
	}

}
