content: /*******************************************************************************
   * Copyright (c) 2000, 2009 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.wst.jsdt.internal.corext.refactoring.code;
  
  import java.util.ArrayList;
  import java.util.Arrays;
  import java.util.Collection;
  import java.util.Collections;
  import java.util.Comparator;
  import java.util.HashMap;
  import java.util.HashSet;
  import java.util.Iterator;
  import java.util.List;
  import java.util.Map;
  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.SubProgressMonitor;
  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.RefactoringStatusEntry;
  import org.eclipse.ltk.core.refactoring.TextChange;
  import org.eclipse.ltk.core.refactoring.participants.RefactoringArguments;
  import org.eclipse.text.edits.TextEditGroup;
  import org.eclipse.wst.jsdt.core.IJavaScriptUnit;
  import org.eclipse.wst.jsdt.core.IJavaScriptElement;
  import org.eclipse.wst.jsdt.core.IJavaScriptProject;
  import org.eclipse.wst.jsdt.core.JavaScriptModelException;
  import org.eclipse.wst.jsdt.core.compiler.IProblem;
  import org.eclipse.wst.jsdt.core.dom.AST;
  import org.eclipse.wst.jsdt.core.dom.ASTNode;
  import org.eclipse.wst.jsdt.core.dom.ASTVisitor;
  import org.eclipse.wst.jsdt.core.dom.ArrayInitializer;
  import org.eclipse.wst.jsdt.core.dom.Assignment;
  import org.eclipse.wst.jsdt.core.dom.Block;
  import org.eclipse.wst.jsdt.core.dom.BodyDeclaration;
  import org.eclipse.wst.jsdt.core.dom.CatchClause;
  import org.eclipse.wst.jsdt.core.dom.ClassInstanceCreation;
  import org.eclipse.wst.jsdt.core.dom.JavaScriptUnit;
  import org.eclipse.wst.jsdt.core.dom.ConstructorInvocation;
  import org.eclipse.wst.jsdt.core.dom.DoStatement;
  import org.eclipse.wst.jsdt.core.dom.EnhancedForStatement;
  import org.eclipse.wst.jsdt.core.dom.Expression;
  import org.eclipse.wst.jsdt.core.dom.ExpressionStatement;
  import org.eclipse.wst.jsdt.core.dom.FieldAccess;
  import org.eclipse.wst.jsdt.core.dom.ForInStatement;
  import org.eclipse.wst.jsdt.core.dom.ForStatement;
  import org.eclipse.wst.jsdt.core.dom.IBinding;
  import org.eclipse.wst.jsdt.core.dom.IFunctionBinding;
  import org.eclipse.wst.jsdt.core.dom.ITypeBinding;
  import org.eclipse.wst.jsdt.core.dom.IVariableBinding;
  import org.eclipse.wst.jsdt.core.dom.IfStatement;
  import org.eclipse.wst.jsdt.core.dom.Initializer;
  import org.eclipse.wst.jsdt.core.dom.FunctionDeclaration;
  import org.eclipse.wst.jsdt.core.dom.Name;
  import org.eclipse.wst.jsdt.core.dom.NullLiteral;
  import org.eclipse.wst.jsdt.core.dom.ParenthesizedExpression;
  import org.eclipse.wst.jsdt.core.dom.PostfixExpression;
  import org.eclipse.wst.jsdt.core.dom.PrefixExpression;
  import org.eclipse.wst.jsdt.core.dom.QualifiedName;
  import org.eclipse.wst.jsdt.core.dom.SimpleName;
  import org.eclipse.wst.jsdt.core.dom.SingleVariableDeclaration;
  import org.eclipse.wst.jsdt.core.dom.Statement;
  import org.eclipse.wst.jsdt.core.dom.StructuralPropertyDescriptor;
  import org.eclipse.wst.jsdt.core.dom.SuperConstructorInvocation;
  import org.eclipse.wst.jsdt.core.dom.SwitchCase;
  import org.eclipse.wst.jsdt.core.dom.VariableDeclarationExpression;
  import org.eclipse.wst.jsdt.core.dom.VariableDeclarationFragment;
  import org.eclipse.wst.jsdt.core.dom.VariableDeclarationStatement;
  import org.eclipse.wst.jsdt.core.dom.WhileStatement;
  import org.eclipse.wst.jsdt.core.dom.WithStatement;
  import org.eclipse.wst.jsdt.core.dom.rewrite.ASTRewrite;
  import org.eclipse.wst.jsdt.core.dom.rewrite.ListRewrite;
  import org.eclipse.wst.jsdt.core.refactoring.IJavaScriptRefactorings;
  import org.eclipse.wst.jsdt.internal.corext.Corext;
  import org.eclipse.wst.jsdt.internal.corext.SourceRange;
  import org.eclipse.wst.jsdt.internal.corext.codemanipulation.StubUtility;
  import org.eclipse.wst.jsdt.internal.corext.dom.ASTNodes;
  import org.eclipse.wst.jsdt.internal.corext.dom.ScopeAnalyzer;
  import org.eclipse.wst.jsdt.internal.corext.dom.fragments.ASTFragmentFactory;
  import org.eclipse.wst.jsdt.internal.corext.dom.fragments.IASTFragment;
  import org.eclipse.wst.jsdt.internal.corext.dom.fragments.IExpressionFragment;
  import org.eclipse.wst.jsdt.internal.corext.fix.LinkedProposalModel;
  import org.eclipse.wst.jsdt.internal.corext.fix.LinkedProposalPositionGroup;
  import org.eclipse.wst.jsdt.internal.corext.refactoring.Checks;
  import org.eclipse.wst.jsdt.internal.corext.refactoring.JDTRefactoringDescriptor;
  import org.eclipse.wst.jsdt.internal.corext.refactoring.JDTRefactoringDescriptorComment;
  import org.eclipse.wst.jsdt.internal.corext.refactoring.JavaRefactoringArguments;
  import org.eclipse.wst.jsdt.internal.corext.refactoring.RefactoringCoreMessages;
  import org.eclipse.wst.jsdt.internal.corext.refactoring.base.JavaStatusContext;
  import org.eclipse.wst.jsdt.internal.corext.refactoring.base.JavaStringStatusContext;
  import org.eclipse.wst.jsdt.internal.corext.refactoring.base.RefactoringStatusCodes;
  import org.eclipse.wst.jsdt.internal.corext.refactoring.changes.RefactoringDescriptorChange;
  import org.eclipse.wst.jsdt.internal.corext.refactoring.rename.RefactoringAnalyzeUtil;
  import org.eclipse.wst.jsdt.internal.corext.refactoring.structure.CompilationUnitRewrite;
  import org.eclipse.wst.jsdt.internal.corext.refactoring.util.NoCommentSourceRangeComputer;
  import org.eclipse.wst.jsdt.internal.corext.refactoring.util.RefactoringASTParser;
  import org.eclipse.wst.jsdt.internal.corext.refactoring.util.ResourceUtil;
  import org.eclipse.wst.jsdt.internal.corext.util.Messages;
  import org.eclipse.wst.jsdt.internal.ui.JavaScriptPlugin;
  import org.eclipse.wst.jsdt.internal.ui.viewsupport.BindingLabelProvider;
  import org.eclipse.wst.jsdt.ui.JavaScriptElementLabels;
  
  /**
   * Extract Local Variable (from selected expression inside method or initializer).
   */
  public class ExtractTempRefactoring extends ScriptableRefactoring {
  
  	private static final String ATTRIBUTE_REPLACE= "replace"; //$NON-NLS-1$
  	private static final String ATTRIBUTE_FINAL= "final"; //$NON-NLS-1$
  
  	private static final class ForStatementChecker extends ASTVisitor {
  
  		private final Collection fForInitializerVariables;
  
  		private boolean fReferringToForVariable= false;
  
  		public ForStatementChecker(Collection forInitializerVariables) {
  			Assert.isNotNull(forInitializerVariables);
  			fForInitializerVariables= forInitializerVariables;
  		}
  
  		public boolean isReferringToForVariable() {
  			return fReferringToForVariable;
  		}
  
  		public boolean visit(SimpleName node) {
  			IBinding binding= node.resolveBinding();
  			if (binding != null && fForInitializerVariables.contains(binding)) {
  				fReferringToForVariable= true;
  			}
  			return false;
  		}
  	}
  
  
  
  	private static boolean allArraysEqual(Object[][] arrays, int position) {
  		Object element= arrays[0][position];
  		for (int i= 0; i < arrays.length; i++) {
  			Object[] array= arrays[i];
  			if (!element.equals(array[position]))
  				return false;
  		}
  		return true;
  	}
  
  	private static boolean canReplace(IASTFragment fragment) {
  		ASTNode node= fragment.getAssociatedNode();
  		ASTNode parent= node.getParent();
  		if (parent instanceof VariableDeclarationFragment) {
  			VariableDeclarationFragment vdf= (VariableDeclarationFragment) parent;
  			if (node.equals(vdf.getName()))
  				return false;
  		}
  		if (isMethodParameter(node))
  			return false;
  		if (isThrowableInCatchBlock(node))
  			return false;
  		if (parent instanceof ExpressionStatement)
  			return false;
  		if (isLeftValue(node))
  			return false;
  		if (isReferringToLocalVariableFromFor((Expression) node))
  			return false;
  		if (isUsedInForInitializerOrUpdater((Expression) node))
  			return false;
  		if (parent instanceof SwitchCase)
  			return false;
  		return true;
  	}
  
  	private static Object[] getArrayPrefix(Object[] array, int prefixLength) {
  		Assert.isTrue(prefixLength <= array.length);
  		Assert.isTrue(prefixLength >= 0);
  		Object[] prefix= new Object[prefixLength];
  		for (int i= 0; i < prefix.length; i++) {
  			prefix[i]= array[i];
  		}
  		return prefix;
  	}
  
  	// return List<IVariableBinding>
  	private static List getForInitializedVariables(VariableDeclarationExpression variableDeclarations) {
  		List forInitializerVariables= new ArrayList(1);
  		for (Iterator iter= variableDeclarations.fragments().iterator(); iter.hasNext();) {
  			VariableDeclarationFragment fragment= (VariableDeclarationFragment) iter.next();
  			IVariableBinding binding= fragment.resolveBinding();
  			if (binding != null)
  				forInitializerVariables.add(binding);
  		}
  		return forInitializerVariables;
  	}
  
  	private static Object[] getLongestArrayPrefix(Object[][] arrays) {
  		int length= -1;
  		if (arrays.length == 0)
  			return new Object[0];
  		int minArrayLength= arrays[0].length;
  		for (int i= 1; i < arrays.length; i++)
  			minArrayLength= Math.min(minArrayLength, arrays[i].length);
  
  		for (int i= 0; i < minArrayLength; i++) {
  			if (!allArraysEqual(arrays, i))
  				break;
  			length++;
  		}
  		if (length == -1)
  			return new Object[0];
  		return getArrayPrefix(arrays[0], length + 1);
  	}
  
  	private static ASTNode[] getParents(ASTNode node) {
  		ASTNode current= node;
  		List parents= new ArrayList();
  		do {
  			parents.add(current.getParent());
  			current= current.getParent();
  		} while (current.getParent() != null);
  		Collections.reverse(parents);
  		return (ASTNode[]) parents.toArray(new ASTNode[parents.size()]);
  	}
  
  	private static boolean isLeftValue(ASTNode node) {
  		ASTNode parent= node.getParent();
  		if (parent instanceof Assignment) {
  			Assignment assignment= (Assignment) parent;
  			if (assignment.getLeftHandSide() == node)
  				return true;
  		}
  		if (parent instanceof PostfixExpression)
  			return true;
  		if (parent instanceof PrefixExpression) {
  			PrefixExpression.Operator op= ((PrefixExpression) parent).getOperator();
  			if (op.equals(PrefixExpression.Operator.DECREMENT))
  				return true;
  			if (op.equals(PrefixExpression.Operator.INCREMENT))
  				return true;
  			return false;
  		}
  		return false;
  	}
  
  	private static boolean isMethodParameter(ASTNode node) {
  		return (node instanceof SimpleName) && (node.getParent() instanceof SingleVariableDeclaration) && (node.getParent().getParent() instanceof FunctionDeclaration);
  	}
  
  	private static boolean isReferringToLocalVariableFromFor(Expression expression) {
  		ASTNode current= expression;
  		ASTNode parent= current.getParent();
  		while (parent != null && !(parent instanceof BodyDeclaration)) {
  			if (parent instanceof ForStatement) {
  				ForStatement forStmt= (ForStatement) parent;
  				if (forStmt.initializers().contains(current) || forStmt.updaters().contains(current) || forStmt.getExpression() == current) {
  					List initializers= forStmt.initializers();
  					if (initializers.size() == 1 && initializers.get(0) instanceof VariableDeclarationExpression) {
  						List forInitializerVariables= getForInitializedVariables((VariableDeclarationExpression) initializers.get(0));
  						ForStatementChecker checker= new ForStatementChecker(forInitializerVariables);
  						expression.accept(checker);
  						if (checker.isReferringToForVariable())
  							return true;
  					}
  				}
  			}
  			else if (parent instanceof ForInStatement) {
  				ForInStatement forInStmt= (ForInStatement) parent;
  				if (forInStmt.getIterationVariable().equals(current)  || forInStmt.getCollection() == current) {
  					if (forInStmt.getIterationVariable() instanceof VariableDeclarationStatement) {
  						List forInitializerVariables= new ArrayList(1);
  						forInitializerVariables.add(  ((VariableDeclarationStatement) forInStmt.getIterationVariable()).resolveBinding());
  						ForStatementChecker checker= new ForStatementChecker(forInitializerVariables);
  						expression.accept(checker);
  						if (checker.isReferringToForVariable())
  							return true;
  					}
  				}
  			}
  			current= parent;
  			parent= current.getParent();
  		}
  		return false;
  	}
  
  	private static boolean isThrowableInCatchBlock(ASTNode node) {
  		return (node instanceof SimpleName) && (node.getParent() instanceof SingleVariableDeclaration) && (node.getParent().getParent() instanceof CatchClause);
  	}
  
  	private static boolean isUsedInForInitializerOrUpdater(Expression expression) {
  		ASTNode parent= expression.getParent();
  		if (parent instanceof ForStatement) {
  			ForStatement forStmt= (ForStatement) parent;
  			return forStmt.initializers().contains(expression) || forStmt.updaters().contains(expression);
  		}
  		return false;
  	}
  
  	private static IASTFragment[] retainOnlyReplacableMatches(IASTFragment[] allMatches) {
  		List result= new ArrayList(allMatches.length);
  		for (int i= 0; i < allMatches.length; i++) {
  			if (canReplace(allMatches[i]))
  				result.add(allMatches[i]);
  		}
  		return (IASTFragment[]) result.toArray(new IASTFragment[result.size()]);
  	}
  
  	private JavaScriptUnit fCompilationUnitNode;
  	
  	private CompilationUnitRewrite fCURewrite;
  
  	private IJavaScriptUnit fCu;
  
  	private boolean fDeclareFinal;
  
  	private String[] fExcludedVariableNames;
  
  	private boolean fReplaceAllOccurrences;
  
  	// caches:
  	private IExpressionFragment fSelectedExpression;
  
  	private int fSelectionLength;
  
  	private int fSelectionStart;
  
  	private String fTempName;
  	private String[] fGuessedTempNames;
  
  	private TextChange fChange;
  	
  	private LinkedProposalModel fLinkedProposalModel;
  	
  	private static final String KEY_NAME= "name"; //$NON-NLS-1$
  //	private static final String KEY_TYPE= "type"; //$NON-NLS-1$
  	
  
  	/**
  	 * Creates a new extract temp refactoring
  	 * @param unit the compilation unit, or <code>null</code> if invoked by scripting
  	 * @param selectionStart
  	 * @param selectionLength
  	 */
  	public ExtractTempRefactoring(IJavaScriptUnit unit, int selectionStart, int selectionLength) {
  		Assert.isTrue(selectionStart >= 0);
  		Assert.isTrue(selectionLength >= 0);
  		fSelectionStart= selectionStart;
  		fSelectionLength= selectionLength;
  		fCu= unit;
  		fCompilationUnitNode= null;
  
  		fReplaceAllOccurrences= true; // default
  		fDeclareFinal= false; // default
  		fTempName= ""; //$NON-NLS-1$
  		
  		fLinkedProposalModel= null;
  	}
  	
  	public ExtractTempRefactoring(JavaScriptUnit astRoot, int selectionStart, int selectionLength) {
  		Assert.isTrue(selectionStart >= 0);
  		Assert.isTrue(selectionLength >= 0);
  		Assert.isTrue(astRoot.getTypeRoot() instanceof IJavaScriptUnit);
  		
  		fSelectionStart= selectionStart;
  		fSelectionLength= selectionLength;
  		fCu= (IJavaScriptUnit) astRoot.getTypeRoot();
  		fCompilationUnitNode= astRoot;
  
  		fReplaceAllOccurrences= true; // default
  		fDeclareFinal= false; // default
  		fTempName= ""; //$NON-NLS-1$
  		
  		fLinkedProposalModel= null;
  	}
  	
  	public void setLinkedProposalModel(LinkedProposalModel linkedProposalModel) {
  		fLinkedProposalModel= linkedProposalModel;
  	}
  
  	private void addReplaceExpressionWithTemp() throws JavaScriptModelException {
  		IASTFragment[] fragmentsToReplace= retainOnlyReplacableMatches(getMatchingFragments());
  		//TODO: should not have to prune duplicates here...
  		ASTRewrite rewrite= fCURewrite.getASTRewrite();
  		HashSet seen= new HashSet();
  		for (int i= 0; i < fragmentsToReplace.length; i++) {
  			IASTFragment fragment= fragmentsToReplace[i];
  			if (! seen.add(fragment))
  				continue;
  			SimpleName tempName= fCURewrite.getAST().newSimpleName(fTempName);
  			TextEditGroup description= fCURewrite.createGroupDescription(RefactoringCoreMessages.ExtractTempRefactoring_replace);
  
  			fragment.replace(rewrite, tempName, description);
  			if (fLinkedProposalModel != null)
  				fLinkedProposalModel.getPositionGroup(KEY_NAME, true).addPosition(rewrite.track(tempName), false);
  		}
  	}
  
  	private RefactoringStatus checkExpression() throws JavaScriptModelException {
  		Expression selectedExpression= getSelectedExpression().getAssociatedExpression();
  		if (selectedExpression != null) {
  			final ASTNode parent= selectedExpression.getParent();
  			if (selectedExpression instanceof NullLiteral) {
  				return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractTempRefactoring_null_literals);
  			} else if (selectedExpression instanceof ArrayInitializer) {
  				return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractTempRefactoring_array_initializer);
  			} else if (selectedExpression instanceof Assignment) {
  				if (parent instanceof Expression && !(parent instanceof ParenthesizedExpression))
  					return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractTempRefactoring_assignment);
  				else
  					return null;
  
  			} else if (selectedExpression instanceof SimpleName) {
  				if ((((SimpleName) selectedExpression)).isDeclaration())
  					return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractTempRefactoring_names_in_declarations);
  				if (parent instanceof QualifiedName && selectedExpression.getLocationInParent() == QualifiedName.NAME_PROPERTY || parent instanceof FieldAccess && selectedExpression.getLocationInParent() == FieldAccess.NAME_PROPERTY)
  					return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractTempRefactoring_select_expression);
  			}
  		}
  
  		return null;
  	}
  
  	// !! Same as in ExtractConstantRefactoring
  	private RefactoringStatus checkExpressionFragmentIsRValue() throws JavaScriptModelException {
  		switch (Checks.checkExpressionIsRValue(getSelectedExpression().getAssociatedExpression())) {
  			case Checks.NOT_RVALUE_MISC:
  				return RefactoringStatus.createStatus(RefactoringStatus.FATAL, RefactoringCoreMessages.ExtractTempRefactoring_select_expression, null, Corext.getPluginId(), RefactoringStatusCodes.EXPRESSION_NOT_RVALUE, null); 
  			case Checks.NOT_RVALUE_VOID:
  				return RefactoringStatus.createStatus(RefactoringStatus.FATAL, RefactoringCoreMessages.ExtractTempRefactoring_no_void, null, Corext.getPluginId(), RefactoringStatusCodes.EXPRESSION_NOT_RVALUE_VOID, null); 
  			case Checks.IS_RVALUE:
  				return new RefactoringStatus();
  			default:
  				Assert.isTrue(false);
  				return null;
  		}
  	}
  	
  	public TextChange createTextChange(IProgressMonitor pm) throws CoreException {
  		try {
  			pm.beginTask(RefactoringCoreMessages.ExtractTempRefactoring_checking_preconditions, 3);
  			
  			fCURewrite= new CompilationUnitRewrite(fCu, fCompilationUnitNode);
  			fCURewrite.getASTRewrite().setTargetSourceRangeComputer(new NoCommentSourceRangeComputer());
  			
  			doCreateChange(new SubProgressMonitor(pm, 2));
  			
  			return fCURewrite.createChange(RefactoringCoreMessages.ExtractTempRefactoring_change_name, true, new SubProgressMonitor(pm, 1));
  		} finally {
  			pm.done();
  		}
  	}
  	
  
  	public RefactoringStatus checkFinalConditions(IProgressMonitor pm) throws CoreException {
  		fChange= createTextChange(pm);
  
  		RefactoringStatus result= new RefactoringStatus();
  		if (Arrays.asList(getExcludedVariableNames()).contains(fTempName))
  			result.addWarning(Messages.format(RefactoringCoreMessages.ExtractTempRefactoring_another_variable, fTempName)); 
  
  		result.merge(checkMatchingFragments());
  		
  		fChange.setKeepPreviewEdits(true);
  		checkNewSource(result);
  		
  		return result;
  	}
  	
  	private final JDTRefactoringDescriptor createRefactoringDescriptor() {
  		final Map arguments= new HashMap();
  		String project= null;
  		IJavaScriptProject javaProject= fCu.getJavaScriptProject();
  		if (javaProject != null)
  			project= javaProject.getElementName();
  		final String description= Messages.format(RefactoringCoreMessages.ExtractTempRefactoring_descriptor_description_short, fTempName);
  		final String expression= ASTNodes.asString(fSelectedExpression.getAssociatedExpression());
  		final String header= Messages.format(RefactoringCoreMessages.ExtractTempRefactoring_descriptor_description, new String[] { fTempName, expression});
  		final JDTRefactoringDescriptorComment comment= new JDTRefactoringDescriptorComment(project, this, header);
  		comment.addSetting(Messages.format(RefactoringCoreMessages.ExtractTempRefactoring_name_pattern, fTempName));
  		final BodyDeclaration decl= (BodyDeclaration) ASTNodes.getParent(fSelectedExpression.getAssociatedExpression(), BodyDeclaration.class);
  		if (decl instanceof FunctionDeclaration) {
  			final IFunctionBinding method= ((FunctionDeclaration) decl).resolveBinding();
  			final String label= method != null ? BindingLabelProvider.getBindingLabel(method, JavaScriptElementLabels.ALL_FULLY_QUALIFIED) : '{' + JavaScriptElementLabels.ELLIPSIS_STRING + '}';
  			comment.addSetting(Messages.format(RefactoringCoreMessages.ExtractTempRefactoring_destination_pattern, label));
  		}
  		comment.addSetting(Messages.format(RefactoringCoreMessages.ExtractTempRefactoring_expression_pattern, expression));
  		if (fReplaceAllOccurrences)
  			comment.addSetting(RefactoringCoreMessages.ExtractTempRefactoring_replace_occurrences);
  		if (fDeclareFinal)
  			comment.addSetting(RefactoringCoreMessages.ExtractTempRefactoring_declare_final);
  		final JDTRefactoringDescriptor descriptor= new JDTRefactoringDescriptor(IJavaScriptRefactorings.EXTRACT_LOCAL_VARIABLE, project, description, comment.asString(), arguments, RefactoringDescriptor.NONE);
  		arguments.put(JDTRefactoringDescriptor.ATTRIBUTE_INPUT, descriptor.elementToHandle(fCu));
  		arguments.put(JDTRefactoringDescriptor.ATTRIBUTE_NAME, fTempName);
  		arguments.put(JDTRefactoringDescriptor.ATTRIBUTE_SELECTION, Integer.valueOf(fSelectionStart).toString() + " " + Integer.valueOf(fSelectionLength).toString()); //$NON-NLS-1$
  		arguments.put(ATTRIBUTE_REPLACE, Boolean.valueOf(fReplaceAllOccurrences).toString());
  		arguments.put(ATTRIBUTE_FINAL, Boolean.valueOf(fDeclareFinal).toString());
  		return descriptor;
  	}
  	
  	private void doCreateChange(IProgressMonitor pm) throws CoreException {
  		try {
  			pm.beginTask(RefactoringCoreMessages.ExtractTempRefactoring_checking_preconditions, 1);
  			try {
  				createTempDeclaration();
  			} catch (CoreException exception) {
  				JavaScriptPlugin.log(exception);
  			}
  			addReplaceExpressionWithTemp();
  		} finally {
  			pm.done();
  		}
  	}
  
  	private void checkNewSource(RefactoringStatus result) throws CoreException {
  		String newCuSource= fChange.getPreviewContent(new NullProgressMonitor());
  		JavaScriptUnit newCUNode= new RefactoringASTParser(AST.JLS3).parse(newCuSource, fCu, true, true, null);
  		IProblem[] newProblems= RefactoringAnalyzeUtil.getIntroducedCompileProblems(newCUNode, fCompilationUnitNode);
  		for (int i= 0; i < newProblems.length; i++) {
  			IProblem problem= newProblems[i];
  			if (problem.isError())
  				result.addEntry(new RefactoringStatusEntry((problem.isError() ? RefactoringStatus.ERROR : RefactoringStatus.WARNING), problem.getMessage(), new JavaStringStatusContext(newCuSource, new SourceRange(problem))));
  		}
  	}
  		
  	public RefactoringStatus checkInitialConditions(IProgressMonitor pm) throws CoreException {
  		try {
  			pm.beginTask("", 6); //$NON-NLS-1$
  
  			RefactoringStatus result= Checks.validateModifiesFiles(ResourceUtil.getFiles(new IJavaScriptUnit[] { fCu}), getValidationContext());
  			if (result.hasFatalError())
  				return result;
  
  			if (fCompilationUnitNode == null) {
  				fCompilationUnitNode= RefactoringASTParser.parseWithASTProvider(fCu, true, new SubProgressMonitor(pm, 3));
  			} else {
  				pm.worked(3);
  			}
  			
  			result.merge(checkSelection(new SubProgressMonitor(pm, 3)));
  			if (!result.hasFatalError() && isLiteralNodeSelected())
  				fReplaceAllOccurrences= false;
  			return result;
  
  		} finally {
  			pm.done();
  		}
  	}
  
  	private RefactoringStatus checkMatchingFragments() throws JavaScriptModelException {
  		RefactoringStatus result= new RefactoringStatus();
  		IASTFragment[] matchingFragments= getMatchingFragments();
  		for (int i= 0; i < matchingFragments.length; i++) {
  			ASTNode node= matchingFragments[i].getAssociatedNode();
  			if (isLeftValue(node) && !isReferringToLocalVariableFromFor((Expression) node)) {
  				String msg= RefactoringCoreMessages.ExtractTempRefactoring_assigned_to; 
  				result.addWarning(msg, JavaStatusContext.create(fCu, node));
  			}
  		}
  		return result;
  	}
  
  	private RefactoringStatus checkSelection(IProgressMonitor pm) throws JavaScriptModelException {
  		try {
  			pm.beginTask("", 8); //$NON-NLS-1$
  
  			IExpressionFragment selectedExpression= getSelectedExpression();
  
  			if (selectedExpression == null) {
  				String message= RefactoringCoreMessages.ExtractTempRefactoring_select_expression;
  				return CodeRefactoringUtil.checkMethodSyntaxErrors(fSelectionStart, fSelectionLength, fCompilationUnitNode, message);
  			}
  			pm.worked(1);
  
  			if (isUsedInExplicitConstructorCall())
  				return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractTempRefactoring_explicit_constructor); 
  			pm.worked(1);
  
  			if (getEnclosingBodyNode() == null)
  				return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractTempRefactoring_expr_in_method_or_initializer); 
  			pm.worked(1);
  
  			ASTNode associatedNode= selectedExpression.getAssociatedNode();
  			if (associatedNode instanceof Name && associatedNode.getParent() instanceof ClassInstanceCreation && associatedNode.getLocationInParent() == ClassInstanceCreation.TYPE_PROPERTY)
  				return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractTempRefactoring_name_in_new); 
  			pm.worked(1);
  
  			RefactoringStatus result= new RefactoringStatus();
  			result.merge(checkExpression());
  			if (result.hasFatalError())
  				return result;
  			pm.worked(1);
  
  			result.merge(checkExpressionFragmentIsRValue());
  			if (result.hasFatalError())
  				return result;
  			pm.worked(1);
  
  			if (isUsedInForInitializerOrUpdater(getSelectedExpression().getAssociatedExpression()))
  				return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractTempRefactoring_for_initializer_updater); 
  			pm.worked(1);
  
  			if (isReferringToLocalVariableFromFor(getSelectedExpression().getAssociatedExpression()))
  				return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ExtractTempRefactoring_refers_to_for_variable); 
  			pm.worked(1);
  
  			return result;
  		} finally {
  			pm.done();
  		}
  	}
  
  	public RefactoringStatus checkTempName(String newName) {
  		RefactoringStatus status= Checks.checkTempName(newName);
  		if (Arrays.asList(getExcludedVariableNames()).contains(newName))
  			status.addWarning(Messages.format(RefactoringCoreMessages.ExtractTempRefactoring_another_variable, newName)); 
  		return status;
  	}
  
  	private void createAndInsertTempDeclaration() throws CoreException {
  		Expression initializer= getSelectedExpression().createCopyTarget(fCURewrite.getASTRewrite());
  		VariableDeclarationStatement vds= createTempDeclaration(initializer);
  		
  		if ((!fReplaceAllOccurrences) || (retainOnlyReplacableMatches(getMatchingFragments()).length <= 1)) {
  			insertAt(getSelectedExpression().getAssociatedNode(), vds);
  			return;
  		}
  		
  		ASTNode[] firstReplaceNodeParents= getParents(getFirstReplacedExpression().getAssociatedNode());
  		ASTNode[] commonPath= findDeepestCommonSuperNodePathForReplacedNodes();
  		Assert.isTrue(commonPath.length <= firstReplaceNodeParents.length);
  		
  		ASTNode deepestCommonParent= firstReplaceNodeParents[commonPath.length - 1];
  		if (deepestCommonParent instanceof Block)
  			insertAt(firstReplaceNodeParents[commonPath.length], vds);
  		else
  			insertAt(deepestCommonParent, vds);
  	}
  
  	private VariableDeclarationStatement createTempDeclaration(Expression initializer) throws CoreException {
  		AST ast= fCURewrite.getAST();
  		
  		VariableDeclarationFragment vdf= ast.newVariableDeclarationFragment();
  		vdf.setName(ast.newSimpleName(fTempName));
  		vdf.setInitializer(initializer);
  		
  		VariableDeclarationStatement vds= ast.newVariableDeclarationStatement(vdf);
  //		if (fDeclareFinal) {
  //			vds.modifiers().add(ast.newModifier(ModifierKeyword.FINAL_KEYWORD));
  //		}
  //		vds.setType(createTempType());
  		
  		if (fLinkedProposalModel != null) {
  			ASTRewrite rewrite= fCURewrite.getASTRewrite();
  			LinkedProposalPositionGroup nameGroup= fLinkedProposalModel.getPositionGroup(KEY_NAME, true);
  			nameGroup.addPosition(rewrite.track(vdf.getName()), true);
  			
  			String[] nameSuggestions= guessTempNames();
  			if (nameSuggestions.length > 0 && !nameSuggestions[0].equals(fTempName)) {
  				nameGroup.addProposal(fTempName, null, nameSuggestions.length + 1);
  			}
  			for (int i= 0; i < nameSuggestions.length; i++) {
  				nameGroup.addProposal(nameSuggestions[i], null, nameSuggestions.length - i);
  			}
  		}
  		return vds;
  	}
  
  	private void insertAt(ASTNode target, Statement declaration) throws JavaScriptModelException {
  		ASTRewrite rewrite= fCURewrite.getASTRewrite();
  		TextEditGroup groupDescription= fCURewrite.createGroupDescription(RefactoringCoreMessages.ExtractTempRefactoring_declare_local_variable);
  		
  		ASTNode parent= target.getParent();
  		while (! (parent instanceof Block)) {
  			StructuralPropertyDescriptor locationInParent= target.getLocationInParent();
  			if (locationInParent == IfStatement.THEN_STATEMENT_PROPERTY
  					|| locationInParent == IfStatement.ELSE_STATEMENT_PROPERTY
  					|| locationInParent == ForStatement.BODY_PROPERTY
  					|| locationInParent == ForInStatement.BODY_PROPERTY
  					|| locationInParent == EnhancedForStatement.BODY_PROPERTY
  					|| locationInParent == DoStatement.BODY_PROPERTY
  					|| locationInParent == WhileStatement.BODY_PROPERTY
  					|| locationInParent == WithStatement.BODY_PROPERTY
  					) {
  				Block replacement= rewrite.getAST().newBlock();
  				ListRewrite replacementRewrite= rewrite.getListRewrite(replacement, Block.STATEMENTS_PROPERTY);
  				replacementRewrite.insertFirst(declaration, null);
  				replacementRewrite.insertLast(rewrite.createMoveTarget(target), null);
  				rewrite.replace(target, replacement, groupDescription);
  				return;
  			}
  			target= parent;
  			parent= parent.getParent();
  		}
  		ListRewrite listRewrite= rewrite.getListRewrite(parent, Block.STATEMENTS_PROPERTY);
  		listRewrite.insertBefore(declaration, target, groupDescription);
  	}
  
  	public Change createChange(IProgressMonitor pm) throws CoreException {
  		try {
  			pm.beginTask(RefactoringCoreMessages.ExtractTempRefactoring_checking_preconditions, 1);
  			JDTRefactoringDescriptor descriptor= createRefactoringDescriptor();
  			return new RefactoringDescriptorChange(descriptor, RefactoringCoreMessages.ExtractTempRefactoring_extract_temp, new Change[] { fChange});
  		} finally {
  			pm.done();
  		}
  	}
  	
  	private void createTempDeclaration() throws CoreException {
  		if (shouldReplaceSelectedExpressionWithTempDeclaration())
  			replaceSelectedExpressionWithTempDeclaration();
  		else
  			createAndInsertTempDeclaration();
  	}
  
  	public boolean declareFinal() {
  		return fDeclareFinal;
  	}
  
  	private ASTNode[] findDeepestCommonSuperNodePathForReplacedNodes() throws JavaScriptModelException {
  		ASTNode[] matchNodes= getMatchNodes();
  
  		ASTNode[][] matchingNodesParents= new ASTNode[matchNodes.length][];
  		for (int i= 0; i < matchNodes.length; i++) {
  			matchingNodesParents[i]= getParents(matchNodes[i]);
  		}
  		List l= Arrays.asList(getLongestArrayPrefix(matchingNodesParents));
  		return (ASTNode[]) l.toArray(new ASTNode[l.size()]);
  	}
  
  	private Block getEnclosingBodyNode() throws JavaScriptModelException {
  		ASTNode node= getSelectedExpression().getAssociatedNode();
  		do {
  			switch (node.getNodeType()) {
  				case ASTNode.FUNCTION_DECLARATION:
  					return ((FunctionDeclaration) node).getBody();
  				case ASTNode.INITIALIZER:
  					return ((Initializer) node).getBody();
  			}
  			node= node.getParent();
  		} while (node != null);
  		return null;
  	}
  
  	private String[] getExcludedVariableNames() {
  		if (fExcludedVariableNames == null) {
  			try {
  				IBinding[] bindings= new ScopeAnalyzer(fCompilationUnitNode).getDeclarationsInScope(getSelectedExpression().getStartPosition(), ScopeAnalyzer.VARIABLES);
  				fExcludedVariableNames= new String[bindings.length];
  				for (int i= 0; i < bindings.length; i++) {
  					fExcludedVariableNames[i]= bindings[i].getName();
  				}
  			} catch (JavaScriptModelException e) {
  				fExcludedVariableNames= new String[0];
  			}
  		}
  		return fExcludedVariableNames;
  	}
  
  	private IExpressionFragment getFirstReplacedExpression() throws JavaScriptModelException {
  		if (!fReplaceAllOccurrences)
  			return getSelectedExpression();
  		IASTFragment[] nodesToReplace= retainOnlyReplacableMatches(getMatchingFragments());
  		if (nodesToReplace.length == 0)
  			return getSelectedExpression();
  		Comparator comparator= new Comparator() {
  
  			public int compare(Object o1, Object o2) {
  				return ((IASTFragment) o1).getStartPosition() - ((IASTFragment) o2).getStartPosition();
  			}
  		};
  		Arrays.sort(nodesToReplace, comparator);
  		return (IExpressionFragment) nodesToReplace[0];
  	}
  
  	private IASTFragment[] getMatchingFragments() throws JavaScriptModelException {
  		if (fReplaceAllOccurrences) {
  			IASTFragment[] allMatches= ASTFragmentFactory.createFragmentForFullSubtree(getEnclosingBodyNode()).getSubFragmentsMatching(getSelectedExpression());
  			return allMatches;
  		} else
  			return new IASTFragment[] { getSelectedExpression()};
  	}
  
  	private ASTNode[] getMatchNodes() throws JavaScriptModelException {
  		IASTFragment[] matches= retainOnlyReplacableMatches(getMatchingFragments());
  		ASTNode[] result= new ASTNode[matches.length];
  		for (int i= 0; i < matches.length; i++)
  			result[i]= matches[i].getAssociatedNode();
  		return result;
  	}
  
  	public String getName() {
  		return RefactoringCoreMessages.ExtractTempRefactoring_name; 
  	}
  
  
  	private IExpressionFragment getSelectedExpression() throws JavaScriptModelException {
  		if (fSelectedExpression != null)
  			return fSelectedExpression;
  		IASTFragment selectedFragment= ASTFragmentFactory.createFragmentForSourceRange(new SourceRange(fSelectionStart, fSelectionLength), fCompilationUnitNode, fCu);
  
  		if (selectedFragment instanceof IExpressionFragment && !Checks.isInsideJavadoc(selectedFragment.getAssociatedNode())) {
  			fSelectedExpression= (IExpressionFragment) selectedFragment;
  		} else if (selectedFragment != null) {
  			if (selectedFragment.getAssociatedNode() instanceof ExpressionStatement) {
  				ExpressionStatement exprStatement= (ExpressionStatement) selectedFragment.getAssociatedNode();
  				Expression expression= exprStatement.getExpression();
  				fSelectedExpression= (IExpressionFragment) ASTFragmentFactory.createFragmentForFullSubtree(expression);
  			} else if (selectedFragment.getAssociatedNode() instanceof Assignment) {
  				Assignment assignment= (Assignment) selectedFragment.getAssociatedNode();
  				fSelectedExpression= (IExpressionFragment) ASTFragmentFactory.createFragmentForFullSubtree(assignment);
  			}
  		}
  		
  		return fSelectedExpression;
  	}
  
  //	private Type createTempType() throws CoreException {
  //		Expression expression= getSelectedExpression().getAssociatedExpression();
  //		
  //		Type resultingType= null;
  //		ITypeBinding typeBinding= expression.resolveTypeBinding();
  //		
  //		ASTRewrite rewrite= fCURewrite.getASTRewrite();
  //		AST ast= rewrite.getAST();
  //		
  //		if (expression instanceof ClassInstanceCreation) {
  //			resultingType= (Type) rewrite.createCopyTarget(((ClassInstanceCreation) expression).getType());
  //		} else if (expression instanceof CastExpression) {
  //			resultingType= (Type) rewrite.createCopyTarget(((CastExpression) expression).getType());
  //		} else {
  //			if (typeBinding == null) {
  //				typeBinding= ASTResolving.guessBindingForReference(expression);
  //			}
  //			if (typeBinding != null) {
  //				typeBinding= Bindings.normalizeForDeclarationUse(typeBinding, ast);
  //				resultingType= fCURewrite.getImportRewrite().addImport(typeBinding, ast);
  //			} else {
  //				resultingType= ast.newSimpleType(ast.newSimpleName("Object")); //$NON-NLS-1$
  //			}
  //		}
  //		if (fLinkedProposalModel != null) {
  //			LinkedProposalPositionGroup typeGroup= fLinkedProposalModel.getPositionGroup(KEY_TYPE, true);
  //			typeGroup.addPosition(rewrite.track(resultingType), false);
  //			if (typeBinding != null) {
  //				ITypeBinding[] relaxingTypes= ASTResolving.getNarrowingTypes(ast, typeBinding);
  //				for (int i= 0; i < relaxingTypes.length; i++) {
  //					typeGroup.addProposal(relaxingTypes[i], fCURewrite.getCu(), relaxingTypes.length - i);
  //				}
  //			}
  //		}
  //		return resultingType;
  //	}
  
  	public String guessTempName() {
  		String[] proposals= guessTempNames();
  		if (proposals.length == 0)
  			return fTempName;
  		else
  			return proposals[0];
  	}
  
  	/**
  	 * @return proposed variable names (may be empty, but not null). The first proposal should be used as "best guess" (if it exists).
  	 */
  	public String[] guessTempNames() {
  		if (fGuessedTempNames == null) {
  			try {
  				Expression expression= getSelectedExpression().getAssociatedExpression();
  				if (expression != null) {
  					ITypeBinding binding= expression.resolveTypeBinding();
  					fGuessedTempNames= StubUtility.getVariableNameSuggestions(StubUtility.LOCAL, fCu.getJavaScriptProject(), binding, expression, Arrays.asList(getExcludedVariableNames()));
  				} 
  			} catch (JavaScriptModelException e) {
  			}
  			if (fGuessedTempNames == null)
  				fGuessedTempNames= new String[0];
  		}
  		return fGuessedTempNames;
  	}
  
  	private boolean isLiteralNodeSelected() throws JavaScriptModelException {
  		IExpressionFragment fragment= getSelectedExpression();
  		if (fragment == null)
  			return false;
  		Expression expression= fragment.getAssociatedExpression();
  		if (expression == null)
  			return false;
  		switch (expression.getNodeType()) {
  			case ASTNode.BOOLEAN_LITERAL:
  			case ASTNode.CHARACTER_LITERAL:
  			case ASTNode.NULL_LITERAL:
  			case ASTNode.NUMBER_LITERAL:
  			case ASTNode.REGULAR_EXPRESSION_LITERAL:
  			case ASTNode.UNDEFINED_LITERAL:
  				return true;
  
  			default:
  				return false;
  		}
  	}
  
  	private boolean isUsedInExplicitConstructorCall() throws JavaScriptModelException {
  		Expression selectedExpression= getSelectedExpression().getAssociatedExpression();
  		if (ASTNodes.getParent(selectedExpression, ConstructorInvocation.class) != null)
  			return true;
  		if (ASTNodes.getParent(selectedExpression, SuperConstructorInvocation.class) != null)
  			return true;
  		return false;
  	}
  
  	public boolean replaceAllOccurrences() {
  		return fReplaceAllOccurrences;
  	}
  
  	private void replaceSelectedExpressionWithTempDeclaration() throws CoreException {
  		ASTRewrite rewrite= fCURewrite.getASTRewrite();
  		Expression selectedExpression= getSelectedExpression().getAssociatedExpression(); // whole expression selected
  		
  		Expression initializer= (Expression) rewrite.createMoveTarget(selectedExpression);
  		ASTNode replacement= createTempDeclaration(initializer); // creates a VariableDeclarationStatement
  		
  		ExpressionStatement parent= (ExpressionStatement) selectedExpression.getParent();
  		if (ASTNodes.isControlStatementBody(parent.getLocationInParent())) {
  			Block block= rewrite.getAST().newBlock();
  			block.statements().add(replacement);
  			replacement= block;
  			
  		}
  		rewrite.replace(parent, replacement, fCURewrite.createGroupDescription(RefactoringCoreMessages.ExtractTempRefactoring_declare_local_variable));
  	}
  
  	public void setDeclareFinal(boolean declareFinal) {
  		fDeclareFinal= declareFinal;
  	}
  
  	public void setReplaceAllOccurrences(boolean replaceAllOccurrences) {
  		fReplaceAllOccurrences= replaceAllOccurrences;
  	}
  
  	public void setTempName(String newName) {
  		fTempName= newName;
  	}
  
  	private boolean shouldReplaceSelectedExpressionWithTempDeclaration() throws JavaScriptModelException {
  		IExpressionFragment selectedFragment= getSelectedExpression();
  		return selectedFragment.getAssociatedNode().getParent() instanceof ExpressionStatement
  			&& selectedFragment.matches(ASTFragmentFactory.createFragmentForFullSubtree(selectedFragment.getAssociatedNode()));
  	}
  
  	public RefactoringStatus initialize(final RefactoringArguments arguments) {
  		if (arguments instanceof JavaRefactoringArguments) {
  			final JavaRefactoringArguments extended= (JavaRefactoringArguments) arguments;
  			final String selection= extended.getAttribute(JDTRefactoringDescriptor.ATTRIBUTE_SELECTION);
  			if (selection != null) {
  				int offset= -1;
  				int length= -1;
  				final StringTokenizer tokenizer= new StringTokenizer(selection);
  				if (tokenizer.hasMoreTokens())
  					offset= Integer.valueOf(tokenizer.nextToken()).intValue();
  				if (tokenizer.hasMoreTokens())
  					length= Integer.valueOf(tokenizer.nextToken()).intValue();
  				if (offset >= 0 && length >= 0) {
  					fSelectionStart= offset;
  					fSelectionLength= length;
  				} else
  					return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_illegal_argument, new Object[] { selection, JDTRefactoringDescriptor.ATTRIBUTE_SELECTION}));
  			} else
  				return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JDTRefactoringDescriptor.ATTRIBUTE_SELECTION));
  			final String handle= extended.getAttribute(JDTRefactoringDescriptor.ATTRIBUTE_INPUT);
  			if (handle != null) {
  				final IJavaScriptElement element= JDTRefactoringDescriptor.handleToElement(extended.getProject(), handle, false);
  				if (element == null || !element.exists() || element.getElementType() != IJavaScriptElement.JAVASCRIPT_UNIT)
  					return createInputFatalStatus(element, IJavaScriptRefactorings.EXTRACT_LOCAL_VARIABLE);
  				else
  					fCu= (IJavaScriptUnit) element;
  			} else
  				return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JDTRefactoringDescriptor.ATTRIBUTE_INPUT));
  			final String name= extended.getAttribute(JDTRefactoringDescriptor.ATTRIBUTE_NAME);
  			if (name != null && !"".equals(name)) //$NON-NLS-1$
  				fTempName= name;
  			else
  				return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JDTRefactoringDescriptor.ATTRIBUTE_NAME));
  			final String replace= extended.getAttribute(ATTRIBUTE_REPLACE);
  			if (replace != null) {
  				fReplaceAllOccurrences= Boolean.valueOf(replace).booleanValue();
  			} else
  				return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_REPLACE));
  			final String declareFinal= extended.getAttribute(ATTRIBUTE_FINAL);
  			if (declareFinal != null) {
  				fDeclareFinal= Boolean.valueOf(declareFinal).booleanValue();
  			} else
  				return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_FINAL));
  		} else
  			return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.InitializableRefactoring_inacceptable_arguments);
  		return new RefactoringStatus();
  	}
  }
  