/*******************************************************************************
 * Copyright (c) 2000, 2021 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Sebastian Davids <sdavids@gmx.de> - Bug 37432 getInvertEqualsProposal
 *     Benjamin Muskalla <b.muskalla@gmx.net> - Bug 36350 convertToStringBufferPropsal
 *     Chris West (Faux) <eclipse@goeswhere.com> - [quick assist] "Use 'StringBuilder' for string concatenation" could fix existing misuses - https://bugs.eclipse.org/bugs/show_bug.cgi?id=282755
 *     Lukas Hanke <hanke@yatta.de> - Bug 241696 [quick fix] quickfix to iterate over a collection - https://bugs.eclipse.org/bugs/show_bug.cgi?id=241696
 *     Eugene Lucash <e.lucash@gmail.com> - [quick assist] Add key binding for Extract method Quick Assist - https://bugs.eclipse.org/424166
 *     Lukas Hanke <hanke@yatta.de> - Bug 430818 [1.8][quick fix] Quick fix for "for loop" is not shown for bare local variable/argument/field - https://bugs.eclipse.org/bugs/show_bug.cgi?id=430818
 *     Jeremie Bresson <dev@jmini.fr> - Bug 439912: [1.8][quick assist] Add quick assists to add and remove parentheses around single lambda parameter - https://bugs.eclipse.org/439912
 *     Jens Reimann <jens.reimann@ibh-systems.com>, Fabian Pfaff <fabian.pfaff@vogella.com> - Bug 197850: [quick assist] Add import static field/method - https://bugs.eclipse.org/bugs/show_bug.cgi?id=197850
 *     Pierre-Yves B. <pyvesdev@gmail.com> - [inline] Allow inlining of local variable initialized to null. - https://bugs.eclipse.org/93850
 *******************************************************************************/
package org.eclipse.jdt.internal.ui.text.correction;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.eclipse.swt.graphics.Image;

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

import org.eclipse.jface.text.link.LinkedPositionGroup;

import org.eclipse.ui.IEditorPart;

import org.eclipse.ltk.core.refactoring.Change;
import org.eclipse.ltk.core.refactoring.NullChange;
import org.eclipse.ltk.core.refactoring.Refactoring;

import org.eclipse.jdt.core.Flags;
import org.eclipse.jdt.core.IBuffer;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaModelMarker;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.NamingConventions;
import org.eclipse.jdt.core.compiler.IProblem;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTMatcher;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
import org.eclipse.jdt.core.dom.AnonymousClassDeclaration;
import org.eclipse.jdt.core.dom.ArrayAccess;
import org.eclipse.jdt.core.dom.ArrayCreation;
import org.eclipse.jdt.core.dom.ArrayInitializer;
import org.eclipse.jdt.core.dom.ArrayType;
import org.eclipse.jdt.core.dom.Assignment;
import org.eclipse.jdt.core.dom.Block;
import org.eclipse.jdt.core.dom.BodyDeclaration;
import org.eclipse.jdt.core.dom.CastExpression;
import org.eclipse.jdt.core.dom.CatchClause;
import org.eclipse.jdt.core.dom.ChildListPropertyDescriptor;
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.CreationReference;
import org.eclipse.jdt.core.dom.Dimension;
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.ExpressionMethodReference;
import org.eclipse.jdt.core.dom.ExpressionStatement;
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.ImportDeclaration;
import org.eclipse.jdt.core.dom.InfixExpression;
import org.eclipse.jdt.core.dom.Initializer;
import org.eclipse.jdt.core.dom.LabeledStatement;
import org.eclipse.jdt.core.dom.LambdaExpression;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.MethodInvocation;
import org.eclipse.jdt.core.dom.MethodReference;
import org.eclipse.jdt.core.dom.Modifier;
import org.eclipse.jdt.core.dom.Modifier.ModifierKeyword;
import org.eclipse.jdt.core.dom.Name;
import org.eclipse.jdt.core.dom.NameQualifiedType;
import org.eclipse.jdt.core.dom.NumberLiteral;
import org.eclipse.jdt.core.dom.ParameterizedType;
import org.eclipse.jdt.core.dom.ParenthesizedExpression;
import org.eclipse.jdt.core.dom.PostfixExpression;
import org.eclipse.jdt.core.dom.PrefixExpression;
import org.eclipse.jdt.core.dom.PrefixExpression.Operator;
import org.eclipse.jdt.core.dom.PrimitiveType;
import org.eclipse.jdt.core.dom.QualifiedName;
import org.eclipse.jdt.core.dom.QualifiedType;
import org.eclipse.jdt.core.dom.ReturnStatement;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.SimpleType;
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.SuperMethodInvocation;
import org.eclipse.jdt.core.dom.SuperMethodReference;
import org.eclipse.jdt.core.dom.SwitchCase;
import org.eclipse.jdt.core.dom.SwitchExpression;
import org.eclipse.jdt.core.dom.SwitchStatement;
import org.eclipse.jdt.core.dom.SynchronizedStatement;
import org.eclipse.jdt.core.dom.ThisExpression;
import org.eclipse.jdt.core.dom.ThrowStatement;
import org.eclipse.jdt.core.dom.TryStatement;
import org.eclipse.jdt.core.dom.Type;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.jdt.core.dom.TypeMethodReference;
import org.eclipse.jdt.core.dom.TypeParameter;
import org.eclipse.jdt.core.dom.UnionType;
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.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.core.dom.rewrite.ImportRewrite.TypeLocation;
import org.eclipse.jdt.core.dom.rewrite.ListRewrite;

import org.eclipse.jdt.internal.core.manipulation.StubUtility;
import org.eclipse.jdt.internal.core.manipulation.dom.ASTResolving;
import org.eclipse.jdt.internal.core.manipulation.util.BasicElementLabels;
import org.eclipse.jdt.internal.core.manipulation.util.Strings;
import org.eclipse.jdt.internal.corext.codemanipulation.ContextSensitiveImportRewriteContext;
import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility2Core;
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.CodeScopeBuilder;
import org.eclipse.jdt.internal.corext.dom.DimensionRewrite;
import org.eclipse.jdt.internal.corext.dom.JdtASTMatcher;
import org.eclipse.jdt.internal.corext.dom.LinkedNodeFinder;
import org.eclipse.jdt.internal.corext.dom.ModifierRewrite;
import org.eclipse.jdt.internal.corext.dom.ScopeAnalyzer;
import org.eclipse.jdt.internal.corext.dom.Selection;
import org.eclipse.jdt.internal.corext.dom.SelectionAnalyzer;
import org.eclipse.jdt.internal.corext.dom.TokenScanner;
import org.eclipse.jdt.internal.corext.fix.CleanUpConstants;
import org.eclipse.jdt.internal.corext.fix.ControlStatementsFix;
import org.eclipse.jdt.internal.corext.fix.ConvertLoopFix;
import org.eclipse.jdt.internal.corext.fix.IProposableFix;
import org.eclipse.jdt.internal.corext.fix.LambdaExpressionsFix;
import org.eclipse.jdt.internal.corext.fix.LinkedProposalModel;
import org.eclipse.jdt.internal.corext.fix.SwitchExpressionsFix;
import org.eclipse.jdt.internal.corext.fix.TypeParametersFix;
import org.eclipse.jdt.internal.corext.fix.UnnecessaryArrayCreationFix;
import org.eclipse.jdt.internal.corext.fix.VariableDeclarationFix;
import org.eclipse.jdt.internal.corext.refactoring.RefactoringAvailabilityTester;
import org.eclipse.jdt.internal.corext.refactoring.code.ConvertAnonymousToNestedRefactoring;
import org.eclipse.jdt.internal.corext.refactoring.code.ExtractConstantRefactoring;
import org.eclipse.jdt.internal.corext.refactoring.code.ExtractMethodRefactoring;
import org.eclipse.jdt.internal.corext.refactoring.code.ExtractTempRefactoring;
import org.eclipse.jdt.internal.corext.refactoring.code.InlineTempRefactoring;
import org.eclipse.jdt.internal.corext.refactoring.code.Invocations;
import org.eclipse.jdt.internal.corext.refactoring.code.PromoteTempToFieldRefactoring;
import org.eclipse.jdt.internal.corext.refactoring.structure.ImportRemover;
import org.eclipse.jdt.internal.corext.refactoring.surround.SurroundWithTryWithResourcesAnalyzer;
import org.eclipse.jdt.internal.corext.refactoring.surround.SurroundWithTryWithResourcesRefactoring;
import org.eclipse.jdt.internal.corext.refactoring.util.TightSourceRangeComputer;
import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
import org.eclipse.jdt.internal.corext.util.Messages;

import org.eclipse.jdt.ui.cleanup.CleanUpOptions;
import org.eclipse.jdt.ui.cleanup.ICleanUp;
import org.eclipse.jdt.ui.text.java.IInvocationContext;
import org.eclipse.jdt.ui.text.java.IJavaCompletionProposal;
import org.eclipse.jdt.ui.text.java.IProblemLocation;
import org.eclipse.jdt.ui.text.java.IQuickAssistProcessor;
import org.eclipse.jdt.ui.text.java.correction.ASTRewriteCorrectionProposal;
import org.eclipse.jdt.ui.text.java.correction.ChangeCorrectionProposal;
import org.eclipse.jdt.ui.text.java.correction.ICommandAccess;

import org.eclipse.jdt.internal.ui.JavaPlugin;
import org.eclipse.jdt.internal.ui.JavaPluginImages;
import org.eclipse.jdt.internal.ui.fix.ControlStatementsCleanUp;
import org.eclipse.jdt.internal.ui.fix.ConvertLoopCleanUp;
import org.eclipse.jdt.internal.ui.fix.LambdaExpressionsCleanUp;
import org.eclipse.jdt.internal.ui.fix.SwitchExpressionsCleanUp;
import org.eclipse.jdt.internal.ui.fix.TypeParametersCleanUp;
import org.eclipse.jdt.internal.ui.fix.UnnecessaryArrayCreationCleanUp;
import org.eclipse.jdt.internal.ui.fix.VariableDeclarationCleanUp;
import org.eclipse.jdt.internal.ui.javaeditor.JavaEditor;
import org.eclipse.jdt.internal.ui.text.correction.proposals.ASTRewriteRemoveImportsCorrectionProposal;
import org.eclipse.jdt.internal.ui.text.correction.proposals.AssignToVariableAssistProposal;
import org.eclipse.jdt.internal.ui.text.correction.proposals.FixCorrectionProposal;
import org.eclipse.jdt.internal.ui.text.correction.proposals.GenerateForLoopAssistProposal;
import org.eclipse.jdt.internal.ui.text.correction.proposals.LinkedCorrectionProposal;
import org.eclipse.jdt.internal.ui.text.correction.proposals.LinkedNamesAssistProposal;
import org.eclipse.jdt.internal.ui.text.correction.proposals.NewDefiningMethodProposal;
import org.eclipse.jdt.internal.ui.text.correction.proposals.RefactoringCorrectionProposal;
import org.eclipse.jdt.internal.ui.text.correction.proposals.RenameRefactoringProposal;
import org.eclipse.jdt.internal.ui.text.correction.proposals.TypeChangeCorrectionProposal;
import org.eclipse.jdt.internal.ui.util.ASTHelper;
import org.eclipse.jdt.internal.ui.viewsupport.JavaElementImageProvider;

/**
  */
public class QuickAssistProcessor implements IQuickAssistProcessor {

	public static final String SPLIT_JOIN_VARIABLE_DECLARATION_ID= "org.eclipse.jdt.ui.correction.splitJoinVariableDeclaration.assist"; //$NON-NLS-1$

	public static final String CONVERT_FOR_LOOP_ID= "org.eclipse.jdt.ui.correction.convertForLoop.assist"; //$NON-NLS-1$

	public static final String ASSIGN_TO_LOCAL_ID= "org.eclipse.jdt.ui.correction.assignToLocal.assist"; //$NON-NLS-1$

	public static final String ASSIGN_IN_TRY_WITH_RESOURCES_ID= "org.eclipse.jdt.ui.correction.assignInTryWithResources.assist"; //$NON-NLS-1$

	public static final String ASSIGN_TO_FIELD_ID= "org.eclipse.jdt.ui.correction.assignToField.assist"; //$NON-NLS-1$

	public static final String ASSIGN_PARAM_TO_FIELD_ID= "org.eclipse.jdt.ui.correction.assignParamToField.assist"; //$NON-NLS-1$

	public static final String ASSIGN_ALL_PARAMS_TO_NEW_FIELDS_ID= "org.eclipse.jdt.ui.correction.assignAllParamsToNewFields.assist"; //$NON-NLS-1$

	public static final String ADD_BLOCK_ID= "org.eclipse.jdt.ui.correction.addBlock.assist"; //$NON-NLS-1$

	public static final String EXTRACT_LOCAL_ID= "org.eclipse.jdt.ui.correction.extractLocal.assist"; //$NON-NLS-1$

	public static final String EXTRACT_LOCAL_NOT_REPLACE_ID= "org.eclipse.jdt.ui.correction.extractLocalNotReplaceOccurrences.assist"; //$NON-NLS-1$

	public static final String EXTRACT_CONSTANT_ID= "org.eclipse.jdt.ui.correction.extractConstant.assist"; //$NON-NLS-1$

	public static final String INLINE_LOCAL_ID= "org.eclipse.jdt.ui.correction.inlineLocal.assist"; //$NON-NLS-1$

	public static final String CONVERT_LOCAL_TO_FIELD_ID= "org.eclipse.jdt.ui.correction.convertLocalToField.assist"; //$NON-NLS-1$

	public static final String CONVERT_ANONYMOUS_TO_LOCAL_ID= "org.eclipse.jdt.ui.correction.convertAnonymousToLocal.assist"; //$NON-NLS-1$

	public static final String CONVERT_TO_STRING_BUFFER_ID= "org.eclipse.jdt.ui.correction.convertToStringBuffer.assist"; //$NON-NLS-1$

	public static final String CONVERT_TO_MESSAGE_FORMAT_ID= "org.eclipse.jdt.ui.correction.convertToMessageFormat.assist"; //$NON-NLS-1$

	public static final String CONVERT_TO_STRING_FORMAT_ID= "org.eclipse.jdt.ui.correction.convertToStringFormat.assist"; //$NON-NLS-1$

	public static final String EXTRACT_METHOD_INPLACE_ID= "org.eclipse.jdt.ui.correction.extractMethodInplace.assist"; //$NON-NLS-1$

	public static final String REMOVE_UNNECESSARY_ARRAY_CREATION_ID= "org.eclipse.jdt.ui.correction.removeArrayCreation.assist"; //$NON-NLS-1$

	public QuickAssistProcessor() {
		super();
	}

	@Override
	public boolean hasAssists(IInvocationContext context) throws CoreException {
		ASTNode coveringNode= context.getCoveringNode();
		if (coveringNode != null) {
			ArrayList<ASTNode> coveredNodes= AdvancedQuickAssistProcessor.getFullyCoveredNodes(context, coveringNode);
			return getCatchClauseToThrowsProposals(context, coveringNode, null)
					|| getPickoutTypeFromMulticatchProposals(context, coveringNode, coveredNodes, null)
					|| getConvertToMultiCatchProposals(context, coveringNode, null)
					|| getUnrollMultiCatchProposals(context, coveringNode, null)
					|| getRenameLocalProposals(context, coveringNode, null, null)
					|| getRenameRefactoringProposal(context, coveringNode, null, null)
					|| getAssignToVariableProposals(context, coveringNode, null, null)
					|| getUnWrapProposals(context, coveringNode, null)
					|| getAssignParamToFieldProposals(context, coveringNode, null)
					|| getAssignAllParamsToFieldsProposals(context, coveringNode, null)
					|| getJoinVariableProposals(context, coveringNode, null)
					|| getAddFinallyProposals(context, coveringNode, null)
					|| getAddElseProposals(context, coveringNode, null)
					|| getSplitVariableProposals(context, coveringNode, null)
					|| getAddBlockProposals(context, coveringNode, null)
					|| getTryWithResourceProposals(context, coveringNode, null, null)
					|| getArrayInitializerToArrayCreation(context, coveringNode, null)
					|| getCreateInSuperClassProposals(context, coveringNode, null)
					|| getInvertEqualsProposal(context, coveringNode, null)
					|| getConvertForLoopProposal(context, coveringNode, null)
					|| getConvertIterableLoopProposal(context, coveringNode, null)
					|| getConvertEnhancedForLoopProposal(context, coveringNode, null)
					|| getGenerateForLoopProposals(context, coveringNode, null, null)
					|| getUnnecessaryArrayCreationProposal(context, coveringNode, null)
					|| getExtractVariableProposal(context, false, null)
					|| getExtractMethodProposal(context, coveringNode, false, null)
					|| getInlineLocalProposal(context, coveringNode, null)
					|| getConvertLocalToFieldProposal(context, coveringNode, null)
					|| getConvertAnonymousToNestedProposal(context, coveringNode, null)
					|| getConvertAnonymousClassCreationsToLambdaProposals(context, coveringNode, null)
					|| getConvertLambdaToAnonymousClassCreationsProposals(context, coveringNode, null)
					|| getChangeLambdaBodyToBlockProposal(context, coveringNode, null)
					|| getChangeLambdaBodyToExpressionProposal(context, coveringNode, null)
					|| getAddInferredLambdaParameterTypes(context, coveringNode, null)
					|| getAddVarLambdaParameterTypes(context, coveringNode, null)
					|| getAddMethodDeclaration(context, coveringNode, null)
					|| getRemoveVarOrInferredLambdaParameterTypes(context, coveringNode, null)
					|| getConvertMethodReferenceToLambdaProposal(context, coveringNode, null)
					|| getConvertLambdaToMethodReferenceProposal(context, coveringNode, null)
					|| getConvertToSwitchExpressionProposals(context, coveringNode, null)
					|| getFixParenthesesInLambdaExpression(context, coveringNode, null)
					|| getRemoveBlockProposals(context, coveringNode, null)
					|| getMakeVariableDeclarationFinalProposals(context, null)
					|| getMissingCaseStatementProposals(context, coveringNode, null)
					|| ConvertStringConcatenationProposals.getProposals(context, null)
					|| getInferDiamondArgumentsProposal(context, coveringNode, null, null)
					|| getJUnitTestCaseProposal(context, coveringNode, null)
					|| getNewImplementationProposal(context, coveringNode, null)
					|| getAddStaticImportProposals(context, coveringNode, null)
					|| getSplitSwitchLabelProposal(context, coveringNode, null);
		}
		return false;
	}

	@Override
	public IJavaCompletionProposal[] getAssists(IInvocationContext context, IProblemLocation[] locations) throws CoreException {
		ASTNode coveringNode= context.getCoveringNode();
		if (coveringNode != null) {
			ArrayList<ASTNode> coveredNodes= AdvancedQuickAssistProcessor.getFullyCoveredNodes(context, coveringNode);
			ArrayList<ICommandAccess> resultingCollections= new ArrayList<>();
			boolean noErrorsAtLocation= noErrorsAtLocation(locations);

			// quick assists that show up also if there is an error/warning
			getRenameLocalProposals(context, coveringNode, locations, resultingCollections);
			getRenameRefactoringProposal(context, coveringNode, locations, resultingCollections);
			getAssignToVariableProposals(context, coveringNode, locations, resultingCollections);
			getAssignParamToFieldProposals(context, coveringNode, resultingCollections);
			getAssignAllParamsToFieldsProposals(context, coveringNode, resultingCollections);
			getInferDiamondArgumentsProposal(context, coveringNode, locations, resultingCollections);
			getGenerateForLoopProposals(context, coveringNode, locations, resultingCollections);
			getJUnitTestCaseProposal(context, coveringNode, resultingCollections);
			getNewImplementationProposal(context, coveringNode, resultingCollections);
			getSplitSwitchLabelProposal(context, coveringNode, resultingCollections);
			getAddMethodDeclaration(context, coveringNode, resultingCollections);

			if (noErrorsAtLocation) {
				boolean problemsAtLocation= locations.length != 0;
				getCatchClauseToThrowsProposals(context, coveringNode, resultingCollections);
				getPickoutTypeFromMulticatchProposals(context, coveringNode, coveredNodes, resultingCollections);
				getConvertToMultiCatchProposals(context, coveringNode, resultingCollections);
				getUnrollMultiCatchProposals(context, coveringNode, resultingCollections);
				getTryWithResourceProposals(context, coveringNode, coveredNodes, resultingCollections);
				getUnWrapProposals(context, coveringNode, resultingCollections);
				getJoinVariableProposals(context, coveringNode, resultingCollections);
				getSplitVariableProposals(context, coveringNode, resultingCollections);
				getAddFinallyProposals(context, coveringNode, resultingCollections);
				getAddElseProposals(context, coveringNode, resultingCollections);
				getAddBlockProposals(context, coveringNode, resultingCollections);
				getInvertEqualsProposal(context, coveringNode, resultingCollections);
				getArrayInitializerToArrayCreation(context, coveringNode, resultingCollections);
				getCreateInSuperClassProposals(context, coveringNode, resultingCollections);
				getExtractVariableProposal(context, problemsAtLocation, resultingCollections);
				getExtractMethodProposal(context, coveringNode, problemsAtLocation, resultingCollections);
				getInlineLocalProposal(context, coveringNode, resultingCollections);
				getConvertLocalToFieldProposal(context, coveringNode, resultingCollections);
				getConvertAnonymousToNestedProposal(context, coveringNode, resultingCollections);
				getConvertAnonymousClassCreationsToLambdaProposals(context, coveringNode, resultingCollections);
				getConvertLambdaToAnonymousClassCreationsProposals(context, coveringNode, resultingCollections);
				getChangeLambdaBodyToBlockProposal(context, coveringNode, resultingCollections);
				getChangeLambdaBodyToExpressionProposal(context, coveringNode, resultingCollections);
				getAddInferredLambdaParameterTypes(context, coveringNode, resultingCollections);
				getAddVarLambdaParameterTypes(context, coveringNode, resultingCollections);
				getRemoveVarOrInferredLambdaParameterTypes(context, coveringNode, resultingCollections);
				getConvertMethodReferenceToLambdaProposal(context, coveringNode, resultingCollections);
				getConvertLambdaToMethodReferenceProposal(context, coveringNode, resultingCollections);
				getFixParenthesesInLambdaExpression(context, coveringNode, resultingCollections);
				if (!getConvertForLoopProposal(context, coveringNode, resultingCollections))
					getConvertIterableLoopProposal(context, coveringNode, resultingCollections);
				getUnnecessaryArrayCreationProposal(context, coveringNode, resultingCollections);
				getConvertEnhancedForLoopProposal(context, coveringNode, resultingCollections);
				getRemoveBlockProposals(context, coveringNode, resultingCollections);
				getMakeVariableDeclarationFinalProposals(context, resultingCollections);
				ConvertStringConcatenationProposals.getProposals(context, resultingCollections);
				getMissingCaseStatementProposals(context, coveringNode, resultingCollections);
				getConvertVarTypeToResolvedTypeProposal(context, coveringNode, resultingCollections);
				getConvertResolvedTypeToVarTypeProposal(context, coveringNode, resultingCollections);
				getAddStaticImportProposals(context, coveringNode, resultingCollections);
				getConvertToSwitchExpressionProposals(context, coveringNode, resultingCollections);
			}
			return resultingCollections.toArray(new IJavaCompletionProposal[resultingCollections.size()]);
		}
		return null;
	}

	static boolean noErrorsAtLocation(IProblemLocation[] locations) {
		if (locations != null) {
			for (IProblemLocation location : locations) {
				if (location.isError()) {
					if (IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER.equals(location.getMarkerType())
							&& JavaCore.getOptionForConfigurableSeverity(location.getProblemId()) != null) {
						// continue (only drop out for severe (non-optional) errors)
					} else {
						return false;
					}
				}
			}
		}
		return true;
	}

	private static int getIndex(int offset, List<Statement> statements) {
		for (int i= 0; i < statements.size(); i++) {
			Statement s= statements.get(i);
			if (offset <= s.getStartPosition()) {
				return i;
			}
			if (offset < s.getStartPosition() + s.getLength()) {
				return -1;
			}
		}
		return statements.size();
	}

	private static boolean getExtractMethodProposal(IInvocationContext context, ASTNode coveringNode, boolean problemsAtLocation, Collection<ICommandAccess> proposals) throws CoreException {
		if (!(coveringNode instanceof Expression) && !(coveringNode instanceof Statement) && !(coveringNode instanceof Block)) {
			return false;
		}
		if (coveringNode instanceof Block) {
			List<Statement> statements= ((Block) coveringNode).statements();
			int startIndex= getIndex(context.getSelectionOffset(), statements);
			if (startIndex == -1)
				return false;
			int endIndex= getIndex(context.getSelectionOffset() + context.getSelectionLength(), statements);
			if (endIndex == -1 || endIndex <= startIndex)
				return false;
		}

		final ICompilationUnit cu= context.getCompilationUnit();
		final ExtractMethodRefactoring extractMethodRefactoring= new ExtractMethodRefactoring(context.getASTRoot(), context.getSelectionOffset(), context.getSelectionLength());
		extractMethodRefactoring.setMethodName("extracted"); //$NON-NLS-1$
		if (extractMethodRefactoring.checkInitialConditions(new NullProgressMonitor()).isOK()) {
			if (proposals == null) {
				return true;
			}
			String label= CorrectionMessages.QuickAssistProcessor_extractmethod_description;
			LinkedProposalModel linkedProposalModel= new LinkedProposalModel();
			extractMethodRefactoring.setLinkedProposalModel(linkedProposalModel);

			Image image= JavaPluginImages.get(JavaPluginImages.IMG_MISC_PUBLIC);
			int relevance= problemsAtLocation ? IProposalRelevance.EXTRACT_METHOD_ERROR : IProposalRelevance.EXTRACT_METHOD;
			RefactoringCorrectionProposal proposal= new RefactoringCorrectionProposal(label, cu, extractMethodRefactoring, relevance, image);
			proposal.setCommandId(EXTRACT_METHOD_INPLACE_ID);
			proposal.setLinkedProposalModel(linkedProposalModel);
			proposals.add(proposal);
			return true;
		}
		return false;
	}



	private static boolean getExtractVariableProposal(IInvocationContext context, boolean problemsAtLocation, Collection<ICommandAccess> proposals) throws CoreException {

		ASTNode node= context.getCoveredNode();

		if (!(node instanceof Expression)) {
			if (context.getSelectionLength() != 0) {
				return false;
			}
			node= context.getCoveringNode();
			if (!(node instanceof Expression)) {
				return false;
			}
		}
		final Expression expression= (Expression) node;

		ITypeBinding binding= expression.resolveTypeBinding();
		if (binding == null || Bindings.isVoidType(binding)) {
			return false;
		}
		if (proposals == null) {
			return true;
		}

		final ICompilationUnit cu= context.getCompilationUnit();
		ExtractTempRefactoring extractTempRefactoring= new ExtractTempRefactoring(context.getASTRoot(), context.getSelectionOffset(), context.getSelectionLength());
		if (extractTempRefactoring.checkInitialConditions(new NullProgressMonitor()).isOK()) {
			extractTempRefactoring.setReplaceAllOccurrences(true);
			LinkedProposalModel linkedProposalModel= new LinkedProposalModel();
			extractTempRefactoring.setLinkedProposalModel(linkedProposalModel);
			extractTempRefactoring.setCheckResultForCompileProblems(false);

			String label= CorrectionMessages.QuickAssistProcessor_extract_to_local_all_description;
			Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_LOCAL);
			int relevance;
			if (context.getSelectionLength() == 0) {
				relevance= IProposalRelevance.EXTRACT_LOCAL_ALL_ZERO_SELECTION;
			} else if (problemsAtLocation) {
				relevance= IProposalRelevance.EXTRACT_LOCAL_ALL_ERROR;
			} else {
				relevance= IProposalRelevance.EXTRACT_LOCAL_ALL;
			}
			RefactoringCorrectionProposal proposal= new RefactoringCorrectionProposal(label, cu, extractTempRefactoring, relevance, image) {
				@Override
				protected void init(Refactoring refactoring) throws CoreException {
					ExtractTempRefactoring etr= (ExtractTempRefactoring) refactoring;
					etr.setTempName(etr.guessTempName()); // expensive
				}
			};
			proposal.setCommandId(EXTRACT_LOCAL_ID);
			proposal.setLinkedProposalModel(linkedProposalModel);
			proposals.add(proposal);
		}

		ExtractTempRefactoring extractTempRefactoringSelectedOnly= new ExtractTempRefactoring(context.getASTRoot(), context.getSelectionOffset(), context.getSelectionLength());
		extractTempRefactoringSelectedOnly.setReplaceAllOccurrences(false);
		if (extractTempRefactoringSelectedOnly.checkInitialConditions(new NullProgressMonitor()).isOK()) {
			LinkedProposalModel linkedProposalModel= new LinkedProposalModel();
			extractTempRefactoringSelectedOnly.setLinkedProposalModel(linkedProposalModel);
			extractTempRefactoringSelectedOnly.setCheckResultForCompileProblems(false);

			String label= CorrectionMessages.QuickAssistProcessor_extract_to_local_description;
			Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_LOCAL);
			int relevance;
			if (context.getSelectionLength() == 0) {
				relevance= IProposalRelevance.EXTRACT_LOCAL_ZERO_SELECTION;
			} else if (problemsAtLocation) {
				relevance= IProposalRelevance.EXTRACT_LOCAL_ERROR;
			} else {
				relevance= IProposalRelevance.EXTRACT_LOCAL;
			}
			RefactoringCorrectionProposal proposal= new RefactoringCorrectionProposal(label, cu, extractTempRefactoringSelectedOnly, relevance, image) {
				@Override
				protected void init(Refactoring refactoring) throws CoreException {
					ExtractTempRefactoring etr= (ExtractTempRefactoring) refactoring;
					etr.setTempName(etr.guessTempName()); // expensive
				}
			};
			proposal.setCommandId(EXTRACT_LOCAL_NOT_REPLACE_ID);
			proposal.setLinkedProposalModel(linkedProposalModel);
			proposals.add(proposal);
		}

		ExtractConstantRefactoring extractConstRefactoring= new ExtractConstantRefactoring(context.getASTRoot(), context.getSelectionOffset(), context.getSelectionLength());
		if (extractConstRefactoring.checkInitialConditions(new NullProgressMonitor()).isOK()) {
			LinkedProposalModel linkedProposalModel= new LinkedProposalModel();
			extractConstRefactoring.setLinkedProposalModel(linkedProposalModel);
			extractConstRefactoring.setCheckResultForCompileProblems(false);

			String label= CorrectionMessages.QuickAssistProcessor_extract_to_constant_description;
			Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_LOCAL);
			int relevance;
			if (context.getSelectionLength() == 0) {
				relevance= IProposalRelevance.EXTRACT_CONSTANT_ZERO_SELECTION;
			} else if (problemsAtLocation) {
				relevance= IProposalRelevance.EXTRACT_CONSTANT_ERROR;
			} else {
				relevance= IProposalRelevance.EXTRACT_CONSTANT;
			}
			RefactoringCorrectionProposal proposal= new RefactoringCorrectionProposal(label, cu, extractConstRefactoring, relevance, image) {
				@Override
				protected void init(Refactoring refactoring) throws CoreException {
					ExtractConstantRefactoring etr= (ExtractConstantRefactoring) refactoring;
					etr.setConstantName(etr.guessConstantName()); // expensive
				}
			};
			proposal.setCommandId(EXTRACT_CONSTANT_ID);
			proposal.setLinkedProposalModel(linkedProposalModel);
			proposals.add(proposal);
		}
		return false;
	}


	private static boolean getConvertAnonymousToNestedProposal(IInvocationContext context, final ASTNode node, Collection<ICommandAccess> proposals) throws CoreException {
		if (!(node instanceof Name))
			return false;

		ASTNode normalized= ASTNodes.getNormalizedNode(node);
		if (normalized.getLocationInParent() != ClassInstanceCreation.TYPE_PROPERTY)
			return false;

		final AnonymousClassDeclaration anonymTypeDecl= ((ClassInstanceCreation) normalized.getParent()).getAnonymousClassDeclaration();
		if (anonymTypeDecl == null || anonymTypeDecl.resolveBinding() == null) {
			return false;
		}

		if (proposals == null) {
			return true;
		}

		final ICompilationUnit cu= context.getCompilationUnit();
		final ConvertAnonymousToNestedRefactoring refactoring= new ConvertAnonymousToNestedRefactoring(anonymTypeDecl);

		String extTypeName= ASTNodes.getSimpleNameIdentifier((Name) node);
		ITypeBinding anonymTypeBinding= anonymTypeDecl.resolveBinding();
		String className;
		if (anonymTypeBinding.getInterfaces().length == 0) {
			className= Messages.format(CorrectionMessages.QuickAssistProcessor_name_extension_from_interface, extTypeName);
		} else {
			className= Messages.format(CorrectionMessages.QuickAssistProcessor_name_extension_from_class, extTypeName);
		}
		String[][] existingTypes= ((IType) anonymTypeBinding.getJavaElement()).resolveType(className);
		int i= 1;
		while (existingTypes != null) {
			i++;
			existingTypes= ((IType) anonymTypeBinding.getJavaElement()).resolveType(className + i);
		}
		refactoring.setClassName(i == 1 ? className : className + i);

		if (refactoring.checkInitialConditions(new NullProgressMonitor()).isOK()) {
			LinkedProposalModel linkedProposalModel= new LinkedProposalModel();
			refactoring.setLinkedProposalModel(linkedProposalModel);

			String label= CorrectionMessages.QuickAssistProcessor_convert_anonym_to_nested;
			Image image= JavaPlugin.getImageDescriptorRegistry().get(JavaElementImageProvider.getTypeImageDescriptor(true, false, Flags.AccPrivate, false));
			RefactoringCorrectionProposal proposal= new RefactoringCorrectionProposal(label, cu, refactoring, IProposalRelevance.CONVERT_ANONYMOUS_TO_NESTED, image);
			proposal.setLinkedProposalModel(linkedProposalModel);
			proposal.setCommandId(CONVERT_ANONYMOUS_TO_LOCAL_ID);
			proposals.add(proposal);
		}
		return false;
	}

	private static boolean getConvertAnonymousClassCreationsToLambdaProposals(IInvocationContext context, ASTNode covering, Collection<ICommandAccess> resultingCollections) {
		while (covering instanceof Name
				|| covering instanceof Type
				|| covering instanceof Dimension
				|| covering.getParent() instanceof MethodDeclaration
				|| covering.getLocationInParent() == AnonymousClassDeclaration.BODY_DECLARATIONS_PROPERTY) {
			covering= covering.getParent();
		}

		ClassInstanceCreation cic;
		if (covering instanceof ClassInstanceCreation) {
			cic= (ClassInstanceCreation) covering;
		} else if (covering.getLocationInParent() == ClassInstanceCreation.ANONYMOUS_CLASS_DECLARATION_PROPERTY) {
			cic= (ClassInstanceCreation) covering.getParent();
		} else if (covering instanceof Name) {
			ASTNode normalized= ASTNodes.getNormalizedNode(covering);
			if (normalized.getLocationInParent() != ClassInstanceCreation.TYPE_PROPERTY)
				return false;
			cic= (ClassInstanceCreation) normalized.getParent();
		} else {
			return false;
		}

		IProposableFix fix= LambdaExpressionsFix.createConvertToLambdaFix(cic);
		if (fix == null)
			return false;

		if (resultingCollections == null)
			return true;

		// add correction proposal
		Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
		Map<String, String> options= new Hashtable<>();
		options.put(CleanUpConstants.CONVERT_FUNCTIONAL_INTERFACES, CleanUpOptions.TRUE);
		options.put(CleanUpConstants.USE_LAMBDA, CleanUpOptions.TRUE);
		FixCorrectionProposal proposal= new FixCorrectionProposal(fix, new LambdaExpressionsCleanUp(options), IProposalRelevance.CONVERT_TO_LAMBDA_EXPRESSION, image, context);
		resultingCollections.add(proposal);
		return true;
	}

	public static boolean getConvertLambdaToAnonymousClassCreationsProposals(IInvocationContext context, ASTNode covering, Collection<ICommandAccess> resultingCollections) {
		LambdaExpression lambda;
		if (covering instanceof LambdaExpression) {
			lambda= (LambdaExpression) covering;
		} else if (covering.getLocationInParent() == LambdaExpression.BODY_PROPERTY) {
			lambda= (LambdaExpression) covering.getParent();
		} else {
			return false;
		}

		IProposableFix fix= LambdaExpressionsFix.createConvertToAnonymousClassCreationsFix(lambda);
		if (fix == null)
			return false;

		if (resultingCollections == null)
			return true;

		// add correction proposal
		Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
		Map<String, String> options= new Hashtable<>();
		options.put(CleanUpConstants.CONVERT_FUNCTIONAL_INTERFACES, CleanUpOptions.TRUE);
		options.put(CleanUpConstants.USE_ANONYMOUS_CLASS_CREATION, CleanUpOptions.TRUE);
		FixCorrectionProposal proposal= new FixCorrectionProposal(fix, new LambdaExpressionsCleanUp(options), IProposalRelevance.CONVERT_TO_SWITCH_EXPRESSION, image, context);
		resultingCollections.add(proposal);
		return true;
	}

	private static boolean getConvertMethodReferenceToLambdaProposal(IInvocationContext context, ASTNode covering, Collection<ICommandAccess> resultingCollections) throws JavaModelException {
		MethodReference methodReference;
		if (covering instanceof MethodReference) {
			methodReference= (MethodReference) covering;
		} else if (covering.getParent() instanceof MethodReference) {
			methodReference= (MethodReference) covering.getParent();
		} else {
			return false;
		}

		IMethodBinding functionalMethod= getFunctionalMethodForMethodReference(methodReference);
		if (functionalMethod == null || functionalMethod.isGenericMethod()) { // generic lambda expressions are not allowed
			return false;
		}

		if (resultingCollections == null)
			return true;

		ASTRewrite rewrite= ASTRewrite.create(methodReference.getAST());
		LinkedProposalModel linkedProposalModel= new LinkedProposalModel();

		LambdaExpression lambda= convertMethodRefernceToLambda(methodReference, functionalMethod, context.getASTRoot(), rewrite, linkedProposalModel, false);

		// add proposal
		String label= CorrectionMessages.QuickAssistProcessor_convert_to_lambda_expression;
		Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
		LinkedCorrectionProposal proposal= new LinkedCorrectionProposal(label, context.getCompilationUnit(), rewrite, IProposalRelevance.CONVERT_METHOD_REFERENCE_TO_LAMBDA, image);
		proposal.setLinkedProposalModel(linkedProposalModel);
		proposal.setEndPosition(rewrite.track(lambda));
		resultingCollections.add(proposal);
		return true;
	}

	private static boolean getConvertToSwitchExpressionProposals(IInvocationContext context, ASTNode covering, Collection<ICommandAccess> resultingCollections) {
		if (covering instanceof Block) {
			List<Statement> statements= ((Block) covering).statements();
			int startIndex= getIndex(context.getSelectionOffset(), statements);
			if (startIndex == -1 || startIndex >= statements.size()) {
				return false;
			}
			covering= statements.get(startIndex);
		} else {
			while (covering instanceof SwitchCase
					|| covering instanceof SwitchExpression) {
				covering= covering.getParent();
			}
		}

		SwitchStatement switchStatement;
		if (covering instanceof SwitchStatement) {
			switchStatement= (SwitchStatement) covering;
		} else {
			return false;
		}

		IProposableFix fix= SwitchExpressionsFix.createConvertToSwitchExpressionFix(switchStatement);
		if (fix == null)
			return false;

		if (resultingCollections == null)
			return true;

		// add correction proposal
		Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
		Map<String, String> options= new Hashtable<>();
		options.put(CleanUpConstants.CONTROL_STATEMENTS_CONVERT_TO_SWITCH_EXPRESSIONS, CleanUpOptions.TRUE);
		FixCorrectionProposal proposal= new FixCorrectionProposal(fix, new SwitchExpressionsCleanUp(options), IProposalRelevance.CONVERT_TO_SWITCH_EXPRESSION, image, context);
		resultingCollections.add(proposal);
		return true;
	}

	/**
	 * Returns the functional interface method being implemented by the given method reference.
	 *
	 * @param methodReference the method reference to get the functional method
	 * @return the functional interface method being implemented by <code>methodReference</code> or
	 *         <code>null</code> if it could not be derived
	 */
	public static IMethodBinding getFunctionalMethodForMethodReference(MethodReference methodReference) {
		ITypeBinding targetTypeBinding= ASTNodes.getTargetType(methodReference);
		if (targetTypeBinding == null)
			return null;

		IMethodBinding functionalMethod= targetTypeBinding.getFunctionalInterfaceMethod();
		if (functionalMethod.isSynthetic()) {
			functionalMethod= Bindings.findOverriddenMethodInType(functionalMethod.getDeclaringClass(), functionalMethod);
		}
		return functionalMethod;
	}

	/**
	 * Converts and replaces the given method reference with corresponding lambda expression in the
	 * given ASTRewrite.
	 *
	 * @param methodReference the method reference to convert
	 * @param functionalMethod the non-generic functional interface method to be implemented by the
	 *            lambda expression
	 * @param astRoot the AST root
	 * @param rewrite the ASTRewrite
	 * @param linkedProposalModel to create linked proposals for lambda's parameters or
	 *            <code>null</code> if linked proposals are not required
	 * @param createBlockBody <code>true</code> if lambda expression's body should be a block
	 *
	 * @return lambda expression used to replace the method reference in the given ASTRewrite
	 * @throws JavaModelException if an exception occurs while accessing the Java element
	 *             corresponding to the <code>functionalMethod</code>
	 */
	public static LambdaExpression convertMethodRefernceToLambda(MethodReference methodReference, IMethodBinding functionalMethod, CompilationUnit astRoot,
			ASTRewrite rewrite, LinkedProposalModel linkedProposalModel, boolean createBlockBody) throws JavaModelException {

		AST ast= astRoot.getAST();
		LambdaExpression lambda= ast.newLambdaExpression();

		String[] lambdaParamNames= getUniqueParameterNames(methodReference, functionalMethod);
		List<VariableDeclaration> lambdaParameters= lambda.parameters();
		for (int i= 0; i < lambdaParamNames.length; i++) {
			String paramName= lambdaParamNames[i];
			VariableDeclarationFragment lambdaParameter= ast.newVariableDeclarationFragment();
			SimpleName name= ast.newSimpleName(paramName);
			lambdaParameter.setName(name);
			lambdaParameters.add(lambdaParameter);
			if (linkedProposalModel != null) {
				linkedProposalModel.getPositionGroup(name.getIdentifier(), true).addPosition(rewrite.track(name), i == 0);
			}
		}

		int noOfLambdaParameters= lambdaParamNames.length;
		lambda.setParentheses(noOfLambdaParameters != 1);

		ITypeBinding returnTypeBinding= functionalMethod.getReturnType();
		IMethodBinding referredMethodBinding= methodReference.resolveMethodBinding(); // too often null, see bug 440000, bug 440344, bug 333665

		if (methodReference instanceof CreationReference) {
			CreationReference creationRef= (CreationReference) methodReference;
			Type type= creationRef.getType();
			if (type instanceof ArrayType) {
				ArrayCreation arrayCreation= ast.newArrayCreation();
				if (createBlockBody) {
					Block blockBody= getBlockBodyForLambda(arrayCreation, returnTypeBinding, ast);
					lambda.setBody(blockBody);
				} else {
					lambda.setBody(arrayCreation);
				}

				ArrayType arrayType= (ArrayType) type;
				Type copiedElementType= (Type) rewrite.createCopyTarget(arrayType.getElementType());
				arrayCreation.setType(ast.newArrayType(copiedElementType, arrayType.getDimensions()));
				SimpleName name= ast.newSimpleName(lambdaParamNames[0]);
				arrayCreation.dimensions().add(name);
				if (linkedProposalModel != null) {
					linkedProposalModel.getPositionGroup(name.getIdentifier(), false).addPosition(rewrite.track(name), LinkedPositionGroup.NO_STOP);
				}
			} else {
				ClassInstanceCreation cic= ast.newClassInstanceCreation();
				if (createBlockBody) {
					Block blockBody= getBlockBodyForLambda(cic, returnTypeBinding, ast);
					lambda.setBody(blockBody);
				} else {
					lambda.setBody(cic);
				}

				ITypeBinding typeBinding= type.resolveBinding();
				if (!(type instanceof ParameterizedType) && typeBinding != null && typeBinding.getTypeDeclaration().isGenericType()) {
					cic.setType(ast.newParameterizedType((Type) rewrite.createCopyTarget(type)));
				} else {
					cic.setType((Type) rewrite.createCopyTarget(type));
				}
				List<SimpleName> invocationArgs= getInvocationArguments(ast, 0, noOfLambdaParameters, lambdaParamNames);
				cic.arguments().addAll(invocationArgs);
				if (linkedProposalModel != null) {
					for (SimpleName name : invocationArgs) {
						linkedProposalModel.getPositionGroup(name.getIdentifier(), false).addPosition(rewrite.track(name), LinkedPositionGroup.NO_STOP);
					}
				}
				cic.typeArguments().addAll(getCopiedTypeArguments(rewrite, methodReference.typeArguments()));
			}

		} else if (referredMethodBinding != null && Modifier.isStatic(referredMethodBinding.getModifiers())) {
			MethodInvocation methodInvocation= ast.newMethodInvocation();
			if (createBlockBody) {
				Block blockBody= getBlockBodyForLambda(methodInvocation, returnTypeBinding, ast);
				lambda.setBody(blockBody);
			} else {
				lambda.setBody(methodInvocation);
			}

			Expression expr= null;
			boolean hasConflict= hasConflict(methodReference.getStartPosition(), referredMethodBinding, ScopeAnalyzer.METHODS | ScopeAnalyzer.CHECK_VISIBILITY, astRoot);
			if (hasConflict || !Bindings.isSuperType(referredMethodBinding.getDeclaringClass(), ASTNodes.getEnclosingType(methodReference)) || methodReference.typeArguments().size() != 0) {
				if (methodReference instanceof ExpressionMethodReference) {
					ExpressionMethodReference expressionMethodReference= (ExpressionMethodReference) methodReference;
					expr= (Expression) rewrite.createCopyTarget(expressionMethodReference.getExpression());
				} else if (methodReference instanceof TypeMethodReference) {
					Type type= ((TypeMethodReference) methodReference).getType();
					ITypeBinding typeBinding= type.resolveBinding();
					if (typeBinding != null) {
						ImportRewrite importRewrite= StubUtility.createImportRewrite(astRoot, true);
						expr= ast.newName(importRewrite.addImport(typeBinding));
					}
				}
			}
			methodInvocation.setExpression(expr);
			SimpleName methodName= getMethodInvocationName(methodReference);
			methodInvocation.setName((SimpleName) rewrite.createCopyTarget(methodName));
			List<SimpleName> invocationArgs= getInvocationArguments(ast, 0, noOfLambdaParameters, lambdaParamNames);
			methodInvocation.arguments().addAll(invocationArgs);
			if (linkedProposalModel != null) {
				for (SimpleName name : invocationArgs) {
					linkedProposalModel.getPositionGroup(name.getIdentifier(), false).addPosition(rewrite.track(name), LinkedPositionGroup.NO_STOP);
				}
			}
			methodInvocation.typeArguments().addAll(getCopiedTypeArguments(rewrite, methodReference.typeArguments()));

		} else if (methodReference instanceof SuperMethodReference) {
			SuperMethodInvocation superMethodInvocation= ast.newSuperMethodInvocation();
			if (createBlockBody) {
				Block blockBody= getBlockBodyForLambda(superMethodInvocation, returnTypeBinding, ast);
				lambda.setBody(blockBody);
			} else {
				lambda.setBody(superMethodInvocation);
			}

			Name superQualifier= ((SuperMethodReference) methodReference).getQualifier();
			if (superQualifier != null) {
				superMethodInvocation.setQualifier((Name) rewrite.createCopyTarget(superQualifier));
			}
			SimpleName methodName= getMethodInvocationName(methodReference);
			superMethodInvocation.setName((SimpleName) rewrite.createCopyTarget(methodName));
			List<SimpleName> invocationArgs= getInvocationArguments(ast, 0, noOfLambdaParameters, lambdaParamNames);
			superMethodInvocation.arguments().addAll(invocationArgs);
			if (linkedProposalModel != null) {
				for (SimpleName name : invocationArgs) {
					linkedProposalModel.getPositionGroup(name.getIdentifier(), false).addPosition(rewrite.track(name), LinkedPositionGroup.NO_STOP);
				}
			}
			superMethodInvocation.typeArguments().addAll(getCopiedTypeArguments(rewrite, methodReference.typeArguments()));

		} else {
			MethodInvocation methodInvocation= ast.newMethodInvocation();
			if (createBlockBody) {
				Block blockBody= getBlockBodyForLambda(methodInvocation, returnTypeBinding, ast);
				lambda.setBody(blockBody);
			} else {
				lambda.setBody(methodInvocation);
			}

			boolean isTypeReference= isTypeReferenceToInstanceMethod(methodReference);
			if (isTypeReference) {
				SimpleName name= ast.newSimpleName(lambdaParamNames[0]);
				methodInvocation.setExpression(name);
				if (linkedProposalModel != null) {
					linkedProposalModel.getPositionGroup(name.getIdentifier(), false).addPosition(rewrite.track(name), LinkedPositionGroup.NO_STOP);
				}
			} else {
				Expression expr= ((ExpressionMethodReference) methodReference).getExpression();
				if (!(expr instanceof ThisExpression) || (methodReference.typeArguments().size() != 0)) {
					methodInvocation.setExpression((Expression) rewrite.createCopyTarget(expr));
				}
			}
			SimpleName methodName= getMethodInvocationName(methodReference);
			methodInvocation.setName((SimpleName) rewrite.createCopyTarget(methodName));
			List<SimpleName> invocationArgs= getInvocationArguments(ast, isTypeReference ? 1 : 0, noOfLambdaParameters, lambdaParamNames);
			methodInvocation.arguments().addAll(invocationArgs);
			if (linkedProposalModel != null) {
				for (SimpleName name : invocationArgs) {
					linkedProposalModel.getPositionGroup(name.getIdentifier(), false).addPosition(rewrite.track(name), LinkedPositionGroup.NO_STOP);
				}
			}
			methodInvocation.typeArguments().addAll(getCopiedTypeArguments(rewrite, methodReference.typeArguments()));
		}

		rewrite.replace(methodReference, lambda, null);
		return lambda;
	}

	private static boolean hasConflict(int startPosition, IMethodBinding referredMethodBinding, int flags, CompilationUnit cu) {
		ScopeAnalyzer analyzer= new ScopeAnalyzer(cu);
		for (IBinding decl : analyzer.getDeclarationsInScope(startPosition, flags)) {
			if (decl.getName().equals(referredMethodBinding.getName()) && !referredMethodBinding.getMethodDeclaration().isEqualTo(decl))
				return true;
		}
		return false;
	}

	private static String[] getUniqueParameterNames(MethodReference methodReference, IMethodBinding functionalMethod) throws JavaModelException {
		String[] originalParameterNames= ((IMethod) functionalMethod.getJavaElement()).getParameterNames();
		String[] newNames= new String[originalParameterNames.length];
		Set<String> excludedNames= new HashSet<>(ASTNodes.getVisibleLocalVariablesInScope(methodReference));

		for (int i= 0; i < originalParameterNames.length; i++) {
			String paramName= originalParameterNames[i];

			if (excludedNames.contains(paramName)) {
				Set<String> allNamesToExclude= new HashSet<>(excludedNames);
				Collections.addAll(allNamesToExclude, originalParameterNames);

				String newParamName= createName(paramName, allNamesToExclude);

				excludedNames.add(newParamName);
				newNames[i]= newParamName;
			} else {
				newNames[i]= paramName;
			}
		}

		return newNames;
	}

	private static String createName(final String nameRoot, final Set<String> excludedNames) {
		int i= 1;
		String candidate;

		do {
			candidate= nameRoot + i++;
		} while (excludedNames.remove(candidate));

		return candidate;
	}

	private static boolean isTypeReferenceToInstanceMethod(MethodReference methodReference) {
		if (methodReference instanceof TypeMethodReference)
			return true;
		if (methodReference instanceof ExpressionMethodReference) {
			Expression expression= ((ExpressionMethodReference) methodReference).getExpression();
			if (expression instanceof Name) {
				IBinding nameBinding= ((Name) expression).resolveBinding();
				if (nameBinding instanceof ITypeBinding) {
					return true;
				}
			}
		}
		return false;
	}

	private static List<SimpleName> getInvocationArguments(AST ast, int begIndex, int noOfLambdaParameters, String[] lambdaParamNames) {
		List<SimpleName> args= new ArrayList<>();
		for (int i= begIndex; i < noOfLambdaParameters; i++) {
			args.add(ast.newSimpleName(lambdaParamNames[i]));
		}
		return args;
	}

	private static List<Type> getCopiedTypeArguments(ASTRewrite rewrite, List<Type> typeArguments) {
		List<Type> copiedTypeArgs= new ArrayList<>();
		for (Type typeArg : typeArguments) {
			copiedTypeArgs.add((Type) rewrite.createCopyTarget(typeArg));
		}
		return copiedTypeArgs;
	}

	private static SimpleName getMethodInvocationName(MethodReference methodReference) {
		SimpleName name= null;
		if (methodReference instanceof ExpressionMethodReference) {
			name= ((ExpressionMethodReference) methodReference).getName();
		} else if (methodReference instanceof TypeMethodReference) {
			name= ((TypeMethodReference) methodReference).getName();
		} else if (methodReference instanceof SuperMethodReference) {
			name= ((SuperMethodReference) methodReference).getName();
		}
		return name;
	}

	private static boolean getChangeLambdaBodyToBlockProposal(IInvocationContext context, ASTNode covering, Collection<ICommandAccess> resultingCollections) {
		LambdaExpression lambda;
		if (covering instanceof LambdaExpression) {
			lambda= (LambdaExpression) covering;
		} else if (covering.getLocationInParent() == LambdaExpression.BODY_PROPERTY) {
			lambda= (LambdaExpression) covering.getParent();
		} else {
			return false;
		}

		if (!(lambda.getBody() instanceof Expression))
			return false;
		if (lambda.resolveMethodBinding() == null)
			return false;

		if (resultingCollections == null)
			return true;

		AST ast= lambda.getAST();
		ASTRewrite rewrite= ASTRewrite.create(ast);

		changeLambdaBodyToBlock(lambda, ast, rewrite);

		// add proposal
		String label= CorrectionMessages.QuickAssistProcessor_change_lambda_body_to_block;
		Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
		ASTRewriteCorrectionProposal proposal= new ASTRewriteCorrectionProposal(label, context.getCompilationUnit(), rewrite, IProposalRelevance.CHANGE_LAMBDA_BODY_TO_BLOCK, image);
		resultingCollections.add(proposal);
		return true;
	}

	/**
	 * Changes the expression body of the given lambda expression to block form.
	 * {@link LambdaExpression#resolveMethodBinding()} should not be <code>null</code> for the given
	 * lambda expression.
	 *
	 * @param lambda the lambda expression to convert the body form
	 * @param ast the AST to create new nodes
	 * @param rewrite the ASTRewrite
	 */
	public static void changeLambdaBodyToBlock(LambdaExpression lambda, AST ast, ASTRewrite rewrite) {
		Expression bodyExpr= (Expression) rewrite.createMoveTarget(lambda.getBody());
		Block blockBody= getBlockBodyForLambda(bodyExpr, lambda.resolveMethodBinding().getReturnType(), ast);
		rewrite.set(lambda, LambdaExpression.BODY_PROPERTY, blockBody, null);
	}

	private static Block getBlockBodyForLambda(Expression bodyExpr, ITypeBinding returnTypeBinding, AST ast) {
		Statement statementInBlockBody;
		if (ast.resolveWellKnownType("void").isEqualTo(returnTypeBinding)) { //$NON-NLS-1$
			ExpressionStatement expressionStatement= ast.newExpressionStatement(bodyExpr);
			statementInBlockBody= expressionStatement;
		} else {
			ReturnStatement returnStatement= ast.newReturnStatement();
			returnStatement.setExpression(bodyExpr);
			statementInBlockBody= returnStatement;
		}
		Block blockBody= ast.newBlock();
		blockBody.statements().add(statementInBlockBody);
		return blockBody;
	}

	private static boolean getChangeLambdaBodyToExpressionProposal(IInvocationContext context, ASTNode covering, Collection<ICommandAccess> resultingCollections) {
		LambdaExpression lambda;
		if (covering instanceof LambdaExpression) {
			lambda= (LambdaExpression) covering;
		} else if (covering.getLocationInParent() == LambdaExpression.BODY_PROPERTY) {
			lambda= (LambdaExpression) covering.getParent();
		} else {
			return false;
		}

		if (!(lambda.getBody() instanceof Block))
			return false;

		Block lambdaBody= (Block) lambda.getBody();

		Expression exprBody= getSingleExpressionFromLambdaBody(lambdaBody);
		if (exprBody == null)
			return false;

		if (resultingCollections == null)
			return true;

		AST ast= lambda.getAST();
		ASTRewrite rewrite= ASTRewrite.create(ast);

		Expression movedBody= (Expression) rewrite.createMoveTarget(exprBody);
		rewrite.set(lambda, LambdaExpression.BODY_PROPERTY, movedBody, null);

		// add proposal
		String label= CorrectionMessages.QuickAssistProcessor_change_lambda_body_to_expression;
		Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
		ASTRewriteCorrectionProposal proposal= new ASTRewriteCorrectionProposal(label, context.getCompilationUnit(), rewrite, IProposalRelevance.CHANGE_LAMBDA_BODY_TO_EXPRESSION, image);
		resultingCollections.add(proposal);
		return true;
	}

	private static Expression getSingleExpressionFromLambdaBody(Block lambdaBody) {
		if (lambdaBody.statements().size() != 1)
			return null;
		Statement singleStatement= (Statement) lambdaBody.statements().get(0);
		if (singleStatement instanceof ReturnStatement) {
			return ((ReturnStatement) singleStatement).getExpression();
		} else if (singleStatement instanceof ExpressionStatement) {
			Expression expression= ((ExpressionStatement) singleStatement).getExpression();
			if (isValidLambdaExpressionBody(expression)) {
				return expression;
			}
		}
		return null;
	}

	private static boolean isValidLambdaExpressionBody(Expression expression) {
		if (expression instanceof Assignment
				|| expression instanceof ClassInstanceCreation
				|| expression instanceof MethodInvocation
				|| expression instanceof PostfixExpression
				|| expression instanceof SuperMethodInvocation) {
			return true;
		}
		if (expression instanceof PrefixExpression) {
			Operator operator= ((PrefixExpression) expression).getOperator();
			if (operator == Operator.INCREMENT || operator == Operator.DECREMENT) {
				return true;
			}
		}
		return false;
	}

	private static boolean getConvertLambdaToMethodReferenceProposal(IInvocationContext context, ASTNode coveringNode, Collection<ICommandAccess> resultingCollections) {
		LambdaExpression lambda;
		if (coveringNode instanceof LambdaExpression) {
			lambda= (LambdaExpression) coveringNode;
		} else if (coveringNode.getLocationInParent() == LambdaExpression.BODY_PROPERTY) {
			lambda= (LambdaExpression) coveringNode.getParent();
		} else {
			lambda= ASTResolving.findEnclosingLambdaExpression(coveringNode);
			if (lambda == null) {
				return false;
			}
		}

		ASTNode lambdaBody= lambda.getBody();
		Expression exprBody;
		if (lambdaBody instanceof Block) {
			exprBody= getSingleExpressionFromLambdaBody((Block) lambdaBody);
		} else {
			exprBody= (Expression) lambdaBody;
		}
		exprBody= ASTNodes.getUnparenthesedExpression(exprBody);
		if (exprBody == null || !isValidLambdaReferenceToMethod(exprBody))
			return false;

		if (!ASTNodes.isParent(exprBody, coveringNode)
				&& !representsDefiningNode(coveringNode, exprBody)) {
			return false;
		}

		List<Expression> lambdaParameters= new ArrayList<>();
		for (VariableDeclaration param : (List<VariableDeclaration>) lambda.parameters()) {
			lambdaParameters.add(param.getName());
		}
		if (exprBody instanceof ClassInstanceCreation) {
			ClassInstanceCreation cic= (ClassInstanceCreation) exprBody;
			if (cic.getExpression() != null || cic.getAnonymousClassDeclaration() != null)
				return false;
			if (!matches(lambdaParameters, cic.arguments()))
				return false;
		} else if (exprBody instanceof ArrayCreation) {
			List<Expression> dimensions= ((ArrayCreation) exprBody).dimensions();
			if (dimensions.size() != 1)
				return false;
			if (!matches(lambdaParameters, dimensions))
				return false;
		} else if (exprBody instanceof SuperMethodInvocation) {
			SuperMethodInvocation superMethodInvocation= (SuperMethodInvocation) exprBody;
			IMethodBinding methodBinding= superMethodInvocation.resolveMethodBinding();
			if (methodBinding == null)
				return false;
			if (Modifier.isStatic(methodBinding.getModifiers())) {
				ITypeBinding invocationTypeBinding= ASTNodes.getInvocationType(superMethodInvocation, methodBinding, superMethodInvocation.getQualifier());
				if (invocationTypeBinding == null)
					return false;
			}
			if (!matches(lambdaParameters, superMethodInvocation.arguments()))
				return false;
		} else { // MethodInvocation
			MethodInvocation methodInvocation= (MethodInvocation) exprBody;
			IMethodBinding methodBinding= methodInvocation.resolveMethodBinding();
			if (methodBinding == null)
				return false;

			Expression invocationExpr= methodInvocation.getExpression();
			if (Modifier.isStatic(methodBinding.getModifiers())) {
				ITypeBinding invocationTypeBinding= ASTNodes.getInvocationType(methodInvocation, methodBinding, invocationExpr);
				if (invocationTypeBinding == null)
					return false;
				if (!matches(lambdaParameters, methodInvocation.arguments()))
					return false;
			} else if ((lambda.parameters().size() - methodInvocation.arguments().size()) == 1) {
				if (invocationExpr == null)
					return false;
				ITypeBinding invocationTypeBinding= invocationExpr.resolveTypeBinding();
				if (invocationTypeBinding == null)
					return false;
				IMethodBinding lambdaMethodBinding= lambda.resolveMethodBinding();
				if (lambdaMethodBinding == null)
					return false;
				ITypeBinding firstParamType= lambdaMethodBinding.getParameterTypes()[0];
				if ((!Bindings.equals(invocationTypeBinding, firstParamType) && !Bindings.isSuperType(invocationTypeBinding, firstParamType))
						|| !JdtASTMatcher.doNodesMatch(lambdaParameters.get(0), invocationExpr)
						|| !matches(lambdaParameters.subList(1, lambdaParameters.size()), methodInvocation.arguments()))
					return false;
			} else if (!matches(lambdaParameters, methodInvocation.arguments())) {
				return false;
			}
		}

		if (resultingCollections == null)
			return true;

		AST ast= lambda.getAST();
		ASTRewrite rewrite= ASTRewrite.create(ast);
		ImportRewrite importRewrite= null;
		MethodReference replacement;

		if (exprBody instanceof ClassInstanceCreation) {
			CreationReference creationReference= ast.newCreationReference();
			replacement= creationReference;

			ClassInstanceCreation cic= (ClassInstanceCreation) exprBody;
			Type type= cic.getType();
			if (type.isParameterizedType() && ((ParameterizedType) type).typeArguments().size() == 0) {
				type= ((ParameterizedType) type).getType();
			}
			creationReference.setType((Type) rewrite.createCopyTarget(type));
			creationReference.typeArguments().addAll(getCopiedTypeArguments(rewrite, cic.typeArguments()));
		} else if (exprBody instanceof ArrayCreation) {
			CreationReference creationReference= ast.newCreationReference();
			replacement= creationReference;

			ArrayType arrayType= ((ArrayCreation) exprBody).getType();
			Type copiedElementType= (Type) rewrite.createCopyTarget(arrayType.getElementType());
			creationReference.setType(ast.newArrayType(copiedElementType, arrayType.getDimensions()));
		} else if (exprBody instanceof SuperMethodInvocation) {
			SuperMethodInvocation superMethodInvocation= (SuperMethodInvocation) exprBody;
			IMethodBinding methodBinding= superMethodInvocation.resolveMethodBinding();
			Name superQualifier= superMethodInvocation.getQualifier();

			if (Modifier.isStatic(methodBinding.getModifiers())) {
				TypeMethodReference typeMethodReference= ast.newTypeMethodReference();
				replacement= typeMethodReference;

				typeMethodReference.setName((SimpleName) rewrite.createCopyTarget(superMethodInvocation.getName()));
				importRewrite= StubUtility.createImportRewrite(context.getASTRoot(), true);
				ITypeBinding invocationTypeBinding= ASTNodes.getInvocationType(superMethodInvocation, methodBinding, superQualifier);
				typeMethodReference.setType(importRewrite.addImport(invocationTypeBinding.getTypeDeclaration(), ast));
				typeMethodReference.typeArguments().addAll(getCopiedTypeArguments(rewrite, superMethodInvocation.typeArguments()));
			} else {
				SuperMethodReference superMethodReference= ast.newSuperMethodReference();
				replacement= superMethodReference;

				if (superQualifier != null) {
					superMethodReference.setQualifier((Name) rewrite.createCopyTarget(superQualifier));
				}
				superMethodReference.setName((SimpleName) rewrite.createCopyTarget(superMethodInvocation.getName()));
				superMethodReference.typeArguments().addAll(getCopiedTypeArguments(rewrite, superMethodInvocation.typeArguments()));
			}
		} else { // MethodInvocation
			MethodInvocation methodInvocation= (MethodInvocation) exprBody;
			IMethodBinding methodBinding= methodInvocation.resolveMethodBinding();
			Expression invocationQualifier= methodInvocation.getExpression();

			boolean isStaticMethod= Modifier.isStatic(methodBinding.getModifiers());
			boolean isTypeRefToInstanceMethod= methodInvocation.arguments().size() != lambda.parameters().size();

			if (isStaticMethod || isTypeRefToInstanceMethod) {
				TypeMethodReference typeMethodReference= ast.newTypeMethodReference();
				replacement= typeMethodReference;

				typeMethodReference.setName((SimpleName) rewrite.createCopyTarget(methodInvocation.getName()));
				importRewrite= StubUtility.createImportRewrite(context.getASTRoot(), true);
				ITypeBinding invocationTypeBinding= ASTNodes.getInvocationType(methodInvocation, methodBinding, invocationQualifier);
				invocationTypeBinding= StubUtility2Core.replaceWildcardsAndCaptures(invocationTypeBinding);
				ImportRewriteContext importRewriteContext= new ContextSensitiveImportRewriteContext(lambda, importRewrite);
				typeMethodReference.setType(importRewrite.addImport(invocationTypeBinding, ast, importRewriteContext, TypeLocation.OTHER));
				typeMethodReference.typeArguments().addAll(getCopiedTypeArguments(rewrite, methodInvocation.typeArguments()));

			} else {
				ExpressionMethodReference exprMethodReference= ast.newExpressionMethodReference();
				replacement= exprMethodReference;

				exprMethodReference.setName((SimpleName) rewrite.createCopyTarget(methodInvocation.getName()));
				if (invocationQualifier != null) {
					exprMethodReference.setExpression((Expression) rewrite.createCopyTarget(invocationQualifier));
				} else {
					// check if method is in class scope or in super/nested class scope
					TypeDeclaration lambdaParentType= (TypeDeclaration) ASTResolving.findParentType(lambda);
					ITypeBinding lambdaMethodInvokingClass= lambdaParentType.resolveBinding();
					ITypeBinding lambdaMethodDeclaringClass= methodBinding.getDeclaringClass();

					ThisExpression newThisExpression= ast.newThisExpression();

					ITypeBinding nestedRootClass= getNestedRootClass(lambdaMethodInvokingClass);
					boolean isSuperClass= isSuperClass(lambdaMethodDeclaringClass, lambdaMethodInvokingClass);
					boolean isNestedClass= isNestedClass(lambdaMethodDeclaringClass, lambdaMethodInvokingClass);

					if (lambdaMethodDeclaringClass == lambdaMethodInvokingClass) {
						// use this::
					} else if (Modifier.isDefault(methodBinding.getModifiers())) {
						boolean nestedInterfaceClass= isNestedInterfaceClass(ast, lambdaMethodDeclaringClass, lambdaMethodInvokingClass);
						if (isNestedClass
								|| (nestedInterfaceClass && !isSuperClass)) {
							// Use this::
						} else if (!nestedInterfaceClass || (nestedRootClass != lambdaMethodInvokingClass)) {
							newThisExpression.setQualifier(ast.newName(nestedRootClass.getName()));
						}
					} else if (lambdaMethodDeclaringClass.isInterface()) {
						if (isSuperClass) {
							// use this::
						} else {
							newThisExpression.setQualifier(ast.newName(nestedRootClass.getName()));
						}
					} else if (isSuperClass) {
						// use this::
					} else {
						newThisExpression.setQualifier(ast.newName(nestedRootClass.getName()));
					}
					exprMethodReference.setExpression(newThisExpression);
				}
				exprMethodReference.typeArguments().addAll(getCopiedTypeArguments(rewrite, methodInvocation.typeArguments()));
			}
		}

		rewrite.replace(lambda, replacement, null);

		// add correction proposal
		String label= CorrectionMessages.QuickAssistProcessor_convert_to_method_reference;
		Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
		ASTRewriteCorrectionProposal proposal= new ASTRewriteCorrectionProposal(label, context.getCompilationUnit(), rewrite, IProposalRelevance.CONVERT_TO_METHOD_REFERENCE, image);
		if (importRewrite != null) {
			proposal.setImportRewrite(importRewrite);
		}
		resultingCollections.add(proposal);
		return true;
	}

	/*
	 * return TRUE if method declaration class is super class of lambda declaration class
	 */
	private static boolean isSuperClass(ITypeBinding methodDeclarationType, ITypeBinding lambdaDeclarationType) {
		ITypeBinding parent= lambdaDeclarationType.getSuperclass();
		while (parent != null) {
			if (parent == methodDeclarationType) {
				return true;
			}
			parent= parent.getSuperclass();
		}
		return false;
	}

	/*
	 * return TRUE if method declaration interface is super class of lambda declaration class
	 */
	private static boolean isNestedInterfaceClass(AST ast, ITypeBinding lambdaMethodDeclaringClass, ITypeBinding lambdaMethodInvokingClass) {
		ITypeBinding[] methodNarrowingTypes= ASTResolving.getRelaxingTypes(ast, lambdaMethodDeclaringClass);
		ITypeBinding[] lambdaNarrowingTypes= ASTResolving.getRelaxingTypes(ast, lambdaMethodInvokingClass);

		if (methodNarrowingTypes.length != 1) {
			return false;
		}
		ITypeBinding methodNarrowingType= methodNarrowingTypes[0];
		for (ITypeBinding lambdaNarrowingType : lambdaNarrowingTypes) {
			if (methodNarrowingType == lambdaNarrowingType) {
				return true;
			}
		}
		return false;
	}

	/*
	 * return TRUE if lambda declaration class is nested class of method declaration class
	 */
	private static boolean isNestedClass(ITypeBinding methodDeclarationType, ITypeBinding lambdaDeclarationType) {
		ITypeBinding parent= lambdaDeclarationType;
		while (parent.isNested()) {
			parent= parent.getDeclaringClass();
			if (parent == methodDeclarationType) {
				return true;
			}
		}
		return false;
	}

	private static ITypeBinding getNestedRootClass(ITypeBinding lambdaDeclarationType) {
		ITypeBinding parent= lambdaDeclarationType;
		while (parent.isNested()) {
			parent= parent.getDeclaringClass();
		}
		return parent;
	}

	private static boolean representsDefiningNode(ASTNode innerNode, ASTNode definingNode) {
		// Example: We want to enable the proposal when the method invocation node or
		// the method name is near the caret. But not when the caret is on an argument of the method invocation.
		if (innerNode == definingNode)
			return true;

		switch (definingNode.getNodeType()) {
			// types from isValidLambdaReferenceToMethod():
			case ASTNode.CLASS_INSTANCE_CREATION:
				return representsDefiningNode(innerNode, ((ClassInstanceCreation) definingNode).getType());
			case ASTNode.ARRAY_CREATION:
				return representsDefiningNode(innerNode, ((ArrayCreation) definingNode).getType());
			case ASTNode.SUPER_METHOD_INVOCATION:
				return innerNode == ((SuperMethodInvocation) definingNode).getName();
			case ASTNode.METHOD_INVOCATION:
				return innerNode == ((MethodInvocation) definingNode).getName();

			// subtypes of Type:
			case ASTNode.NAME_QUALIFIED_TYPE:
				return innerNode == ((NameQualifiedType) definingNode).getName();
			case ASTNode.QUALIFIED_TYPE:
				return innerNode == ((QualifiedType) definingNode).getName();
			case ASTNode.SIMPLE_TYPE:
				return innerNode == ((SimpleType) definingNode).getName();
			case ASTNode.ARRAY_TYPE:
				return representsDefiningNode(innerNode, ((ArrayType) definingNode).getElementType());
			case ASTNode.PARAMETERIZED_TYPE:
				return representsDefiningNode(innerNode, ((ParameterizedType) definingNode).getType());

			default:
				return false;
		}
	}

	private static boolean isValidLambdaReferenceToMethod(Expression expression) {
		return expression instanceof ClassInstanceCreation
				|| expression instanceof ArrayCreation
				|| expression instanceof SuperMethodInvocation
				|| expression instanceof MethodInvocation;
	}

	private static boolean matches(List<Expression> expected, List<Expression> toMatch) {
		if (toMatch.size() != expected.size())
			return false;
		for (int i= 0; i < toMatch.size(); i++) {
			if (!JdtASTMatcher.doNodesMatch(expected.get(i), toMatch.get(i)))
				return false;
		}
		return true;
	}

	private static boolean getFixParenthesesInLambdaExpression(IInvocationContext context, ASTNode coveringNode, Collection<ICommandAccess> resultingCollections) {
		LambdaExpression enclosingLambda= null;
		if (coveringNode instanceof LambdaExpression) {
			enclosingLambda= (LambdaExpression) coveringNode;
		} else if (coveringNode.getLocationInParent() == VariableDeclarationFragment.NAME_PROPERTY
				&& ((VariableDeclarationFragment) coveringNode.getParent()).getLocationInParent() == LambdaExpression.PARAMETERS_PROPERTY) {
			enclosingLambda= (LambdaExpression) coveringNode.getParent().getParent();
		} else {
			return false;
		}

		List<VariableDeclaration> lambdaParameters= enclosingLambda.parameters();
		if (lambdaParameters.size() != 1)
			return false;

		if (lambdaParameters.get(0) instanceof SingleVariableDeclaration)
			return false;

		if (resultingCollections == null) {
			return true;
		}

		String label;
		Boolean parenthesesPropertyNewValue;
		String imageKey;

		if (enclosingLambda.hasParentheses()) {
			label= CorrectionMessages.QuickAssistProcessor_removeParenthesesInLambda;
			parenthesesPropertyNewValue= Boolean.FALSE;
			imageKey= JavaPluginImages.IMG_CORRECTION_REMOVE;
		} else {
			label= CorrectionMessages.QuickAssistProcessor_addParenthesesInLambda;
			parenthesesPropertyNewValue= Boolean.TRUE;
			imageKey= JavaPluginImages.IMG_CORRECTION_CAST;
		}

		// Create the rewrite:
		ASTRewrite rewrite= ASTRewrite.create(enclosingLambda.getAST());
		rewrite.set(enclosingLambda, LambdaExpression.PARENTHESES_PROPERTY, parenthesesPropertyNewValue, null);

		// add correction proposal
		Image image= JavaPluginImages.get(imageKey);
		ASTRewriteCorrectionProposal proposal= new ASTRewriteCorrectionProposal(label, context.getCompilationUnit(), rewrite, IProposalRelevance.ADD_PARENTHESES_FOR_EXPRESSION, image);
		resultingCollections.add(proposal);
		return true;
	}

	public static boolean getAddInferredLambdaParameterTypes(IInvocationContext context, ASTNode covering, Collection<ICommandAccess> resultingCollections) {
		LambdaExpression lambda= null;
		boolean isLambdaParamVarType= false;
		ASTNode parent= covering.getParent();
		if (covering instanceof LambdaExpression) {
			lambda= (LambdaExpression) covering;
		} else if ((covering.getLocationInParent() == VariableDeclarationFragment.NAME_PROPERTY
				|| covering.getLocationInParent() == SingleVariableDeclaration.NAME_PROPERTY)
				&& parent.getLocationInParent() == LambdaExpression.PARAMETERS_PROPERTY) {
			lambda= (LambdaExpression) parent.getParent();
		}

		if (lambda == null) {
			return false;
		}

		List<VariableDeclaration> lambdaParameters= lambda.parameters();
		int noOfLambdaParams= lambdaParameters.size();
		if (noOfLambdaParams == 0)
			return false;

		VariableDeclaration firstLambdaParam= lambdaParameters.get(0);
		if (firstLambdaParam instanceof SingleVariableDeclaration) {
			CompilationUnit astRoot= context.getASTRoot();
			IJavaElement root= astRoot.getJavaElement();
			if (root != null) {
				IJavaProject javaProject= root.getJavaProject();
				if (javaProject != null && JavaModelUtil.is11OrHigher(javaProject)) {
					if (((SingleVariableDeclaration) firstLambdaParam).getType().isVar()) {
						isLambdaParamVarType= true;
					}
				}
			}
			if (!isLambdaParamVarType) {
				return false;
			}
		}

		IMethodBinding methodBinding= lambda.resolveMethodBinding();
		if (methodBinding == null)
			return false;

		if (resultingCollections == null)
			return true;

		AST ast= lambda.getAST();
		ASTRewrite rewrite= ASTRewrite.create(ast);
		ImportRewrite importRewrite= StubUtility.createImportRewrite(context.getASTRoot(), true);

		rewrite.set(lambda, LambdaExpression.PARENTHESES_PROPERTY, Boolean.TRUE, null);
		ContextSensitiveImportRewriteContext importRewriteContext= new ContextSensitiveImportRewriteContext(lambda, importRewrite);
		ITypeBinding[] parameterTypes= methodBinding.getParameterTypes();
		for (int i= 0; i < noOfLambdaParams; i++) {
			VariableDeclaration param= lambdaParameters.get(i);
			SingleVariableDeclaration newParam= ast.newSingleVariableDeclaration();
			newParam.setName(ast.newSimpleName(param.getName().getIdentifier()));
			ITypeBinding type= StubUtility2Core.replaceWildcardsAndCaptures(parameterTypes[i]);
			newParam.setType(importRewrite.addImport(type, ast, importRewriteContext, TypeLocation.PARAMETER));
			rewrite.replace(param, newParam, null);
		}

		// add proposal
		String label= CorrectionMessages.QuickAssistProcessor_add_inferred_lambda_parameter_types;
		if (isLambdaParamVarType) {
			label= CorrectionMessages.QuickAssistProcessor_replace_var_with_inferred_lambda_parameter_types;
		}
		Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
		ASTRewriteCorrectionProposal proposal= new ASTRewriteCorrectionProposal(label, context.getCompilationUnit(), rewrite, IProposalRelevance.ADD_INFERRED_LAMBDA_PARAMETER_TYPES, image);
		proposal.setImportRewrite(importRewrite);
		resultingCollections.add(proposal);
		return true;
	}

	public static boolean getAddVarLambdaParameterTypes(IInvocationContext context, ASTNode covering, Collection<ICommandAccess> resultingCollections) {
		CompilationUnit astRoot= context.getASTRoot();
		IJavaElement root= astRoot.getJavaElement();
		ASTNode parent= covering.getParent();
		if (parent == null || root == null) {
			return false;
		}
		IJavaProject javaProject= root.getJavaProject();
		if (javaProject == null) {
			return false;
		}
		if (!JavaModelUtil.is11OrHigher(javaProject)) {
			return false;
		}

		LambdaExpression lambda= null;
		boolean isLambdaParamExplicitType= false;
		if (covering instanceof LambdaExpression) {
			lambda= (LambdaExpression) covering;
		} else if ((covering.getLocationInParent() == VariableDeclarationFragment.NAME_PROPERTY
				|| covering.getLocationInParent() == SingleVariableDeclaration.NAME_PROPERTY)
				&& parent.getLocationInParent() == LambdaExpression.PARAMETERS_PROPERTY) {
			lambda= (LambdaExpression) parent.getParent();
		}

		if (lambda == null) {
			return false;
		}

		List<VariableDeclaration> lambdaParameters= lambda.parameters();
		int noOfLambdaParams= lambdaParameters.size();
		if (noOfLambdaParams == 0)
			return false;


		VariableDeclaration firstLambdaParam= lambdaParameters.get(0);
		if (firstLambdaParam instanceof SingleVariableDeclaration) {
			if (!((SingleVariableDeclaration) firstLambdaParam).getType().isVar()) {
				isLambdaParamExplicitType= true;
			} else {
				return false;
			}
		}


		IMethodBinding methodBinding= lambda.resolveMethodBinding();
		if (methodBinding == null)
			return false;

		if (resultingCollections == null)
			return true;

		String VAR_TYPE= "var"; //$NON-NLS-1$
		AST ast= lambda.getAST();
		ASTRewrite rewrite= ASTRewrite.create(ast);

		ImportRemover remover= new ImportRemover(context.getCompilationUnit().getJavaProject(), context.getASTRoot());

		ImportRewrite importRewrite= StubUtility.createImportRewrite(context.getASTRoot(), true);

		rewrite.set(lambda, LambdaExpression.PARENTHESES_PROPERTY, Boolean.TRUE, null);
		for (int i= 0; i < noOfLambdaParams; i++) {
			VariableDeclaration param= lambdaParameters.get(i);
			Type oldType= null;
			if (param instanceof SingleVariableDeclaration) {
				SingleVariableDeclaration curParent= (SingleVariableDeclaration) param;
				oldType= curParent.getType();
				if (oldType != null) {
					rewrite.replace(oldType, ast.newSimpleType(ast.newName(VAR_TYPE)), null);
					remover.registerRemovedNode(oldType);
				}
			}
			if (oldType == null) {
				SingleVariableDeclaration newParam= ast.newSingleVariableDeclaration();
				newParam.setName(ast.newSimpleName(param.getName().getIdentifier()));
				newParam.setType(ast.newSimpleType(ast.newName(VAR_TYPE)));
				rewrite.replace(param, newParam, null);
			}
		}

		// add proposal
		ASTRewriteCorrectionProposal proposal;
		String label= null;
		Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
		if (isLambdaParamExplicitType) {
			label= CorrectionMessages.QuickAssistProcessor_replace_lambda_parameter_types_with_var;
			ASTRewriteRemoveImportsCorrectionProposal newProposal= new ASTRewriteRemoveImportsCorrectionProposal(label, context.getCompilationUnit(), rewrite,
					IProposalRelevance.ADD_INFERRED_LAMBDA_PARAMETER_TYPES, image);
			newProposal.setImportRemover(remover);
			proposal= newProposal;

		} else {
			label= CorrectionMessages.QuickAssistProcessor_add_var_lambda_parameter_types;
			proposal= new ASTRewriteCorrectionProposal(label, context.getCompilationUnit(), rewrite, IProposalRelevance.ADD_INFERRED_LAMBDA_PARAMETER_TYPES, image);
		}
		proposal.setImportRewrite(importRewrite);
		resultingCollections.add(proposal);
		return true;
	}

	public static boolean getRemoveVarOrInferredLambdaParameterTypes(IInvocationContext context, ASTNode covering, Collection<ICommandAccess> resultingCollections) {
		CompilationUnit astRoot= context.getASTRoot();
		IJavaElement root= astRoot.getJavaElement();
		ASTNode parent= covering.getParent();
		if (parent == null || root == null) {
			return false;
		}
		IJavaProject javaProject= root.getJavaProject();
		if (javaProject == null) {
			return false;
		}
		boolean checkForVarTypes= false;
		if (JavaModelUtil.is11OrHigher(javaProject)) {
			checkForVarTypes= true;
		}

		LambdaExpression lambda;
		if (covering instanceof LambdaExpression) {
			lambda= (LambdaExpression) covering;
		} else if (covering.getLocationInParent() == SingleVariableDeclaration.NAME_PROPERTY &&
				((SingleVariableDeclaration) parent).getLocationInParent() == LambdaExpression.PARAMETERS_PROPERTY) {
			lambda= (LambdaExpression) covering.getParent().getParent();
		} else {
			return false;
		}

		List<VariableDeclaration> lambdaParameters= lambda.parameters();
		int noOfLambdaParams= lambdaParameters.size();
		if (noOfLambdaParams == 0)
			return false;

		if (!(lambdaParameters.get(0) instanceof SingleVariableDeclaration))
			return false;

		IMethodBinding methodBinding= lambda.resolveMethodBinding();
		if (methodBinding == null)
			return false;

		if (resultingCollections == null)
			return true;

		AST ast= lambda.getAST();
		ASTRewrite rewrite= ASTRewrite.create(ast);

		ImportRemover remover= new ImportRemover(context.getCompilationUnit().getJavaProject(), context.getASTRoot());

		ImportRewrite importRewrite= StubUtility.createImportRewrite(context.getASTRoot(), true);

		rewrite.set(lambda, LambdaExpression.PARENTHESES_PROPERTY, Boolean.TRUE, null);
		boolean removeImports= false;
		for (int i= 0; i < noOfLambdaParams; i++) {
			VariableDeclaration param= lambdaParameters.get(i);
			Type oldType= null;
			if (param instanceof SingleVariableDeclaration) {
				SingleVariableDeclaration curParent= (SingleVariableDeclaration) param;
				oldType= curParent.getType();
				if (oldType != null && (!checkForVarTypes || (checkForVarTypes && !oldType.isVar()))) {
					remover.registerRemovedNode(oldType);
					removeImports= true;
				}
				VariableDeclarationFragment newParam= ast.newVariableDeclarationFragment();
				newParam.setName(ast.newSimpleName(param.getName().getIdentifier()));
				rewrite.replace(param, newParam, null);
			}
		}

		// add proposal
		ASTRewriteCorrectionProposal proposal;
		Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
		String label= CorrectionMessages.QuickAssistProcessor_remove_lambda_parameter_types;
		if (removeImports) {
			ASTRewriteRemoveImportsCorrectionProposal newProposal= new ASTRewriteRemoveImportsCorrectionProposal(label, context.getCompilationUnit(), rewrite,
					IProposalRelevance.ADD_INFERRED_LAMBDA_PARAMETER_TYPES, image);
			newProposal.setImportRemover(remover);
			proposal= newProposal;
		} else {
			proposal= new ASTRewriteCorrectionProposal(label, context.getCompilationUnit(), rewrite, IProposalRelevance.ADD_INFERRED_LAMBDA_PARAMETER_TYPES, image);
		}
		proposal.setImportRewrite(importRewrite);
		resultingCollections.add(proposal);
		return true;
	}

	private static class ReturnType {
		public Type type;

		public ITypeBinding binding;
	}

	private static ReturnType getReturnType(AST ast, ImportRewrite importRewrite, Type variableType) {
		ReturnType returnType= new ReturnType();
		if (variableType instanceof ParameterizedType) {
			variableType= (Type) ((ParameterizedType) variableType).typeArguments().get(0);
			ITypeBinding returnTypeBinding= variableType.resolveBinding();
			if (returnTypeBinding != null) {
				if (returnTypeBinding.isCapture()) {
					returnType.binding= returnTypeBinding.getErasure();
					returnType.type= importRewrite.addImport(returnTypeBinding.getErasure(), ast);
				} else if (returnTypeBinding.isWildcardType()) {
					returnType.binding= returnTypeBinding.getBound();
					returnType.type= importRewrite.addImport(returnTypeBinding.getBound(), ast);
				} else {
					returnType.type= importRewrite.addImport(returnTypeBinding, ast);
					returnType.binding= returnTypeBinding;
				}
			}
		}
		return returnType;
	}

	private static Block getNewReturnBlock(AST ast, ITypeBinding returnTypeBinding) {
		Block newBlock= ast.newBlock();
		if (!"void".equals(returnTypeBinding.getName())) { //$NON-NLS-1$
			ReturnStatement newReturnStatement= ast.newReturnStatement();
			String bName= returnTypeBinding.getBinaryName();
			if ("Z".equals(bName)) { //$NON-NLS-1$
				newReturnStatement.setExpression(ast.newBooleanLiteral(false));
			} else if (returnTypeBinding.isPrimitive()) {
				newReturnStatement.setExpression(ast.newNumberLiteral());
			} else if ("java.lang.String".equals(bName)) { //$NON-NLS-1$
				newReturnStatement.setExpression(ast.newStringLiteral());
			} else {
				newReturnStatement.setExpression(ast.newNullLiteral());
			}
			newBlock.statements().add(newReturnStatement);
		}
		return newBlock;
	}

	private static boolean getAddMethodDeclaration(IInvocationContext context, ASTNode covering, Collection<ICommandAccess> resultingCollections) {
		CompilationUnit astRoot= context.getASTRoot();
		ExpressionMethodReference methodReferenceNode= covering instanceof ExpressionMethodReference
				? (ExpressionMethodReference) covering
				: ASTNodes.getParent(covering, ExpressionMethodReference.class);
		if (methodReferenceNode == null) {
			return false;
		}
		boolean addStaticModifier= false;
		TypeDeclaration typeDeclaration= ASTNodes.getParent(methodReferenceNode, TypeDeclaration.class);

		if (isTypeReferenceToInstanceMethod(methodReferenceNode)) {
			String methodReferenceQualifiedName= ((Name) methodReferenceNode.getExpression()).getFullyQualifiedName();
			String typeDeclarationName= astRoot.getPackage().getName().getFullyQualifiedName() + '.' + typeDeclaration.getName().getFullyQualifiedName();
			if (!methodReferenceQualifiedName.equals(typeDeclarationName)
					&& !methodReferenceQualifiedName.equals(typeDeclaration.getName().getFullyQualifiedName())) {
				// only propose for references in same class
				return false;
			}
			addStaticModifier= true;
		}

		AST ast= astRoot.getAST();
		ASTRewrite rewrite= ASTRewrite.create(ast);
		ListRewrite listRewrite= rewrite.getListRewrite(typeDeclaration, TypeDeclaration.BODY_DECLARATIONS_PROPERTY);

		String label= Messages.format(CorrectionMessages.AddUnimplementedMethodReferenceOperation_AddMissingMethod_group,
				new String[] { methodReferenceNode.getName().getIdentifier(), typeDeclaration.getName().getIdentifier() });
		Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
		ASTRewriteCorrectionProposal proposal= new ASTRewriteCorrectionProposal(label, context.getCompilationUnit(), rewrite, IProposalRelevance.ADD_INFERRED_LAMBDA_PARAMETER_TYPES, image);
		// ImportRewrite importRewrite= proposal.createImportRewrite(context.getASTRoot());
		ImportRewrite importRewrite= StubUtility.createImportRewrite(astRoot, true);

		VariableDeclarationStatement variableDeclarationStatement= ASTNodes.getParent(methodReferenceNode, VariableDeclarationStatement.class);
		MethodInvocation methodInvocationNode= ASTNodes.getParent(methodReferenceNode, MethodInvocation.class);
		Assignment variableAssignment= ASTNodes.getParent(methodReferenceNode, Assignment.class);

		if ((variableAssignment != null || variableDeclarationStatement != null) && methodInvocationNode == null) {
			/*
			 * variable declaration
			 */
			Type type= null;
			ReturnType returnType= null;
			if (variableDeclarationStatement != null) {
				type= variableDeclarationStatement.getType();
				returnType= getReturnType(ast, importRewrite, type);
			} else {
				Expression leftHandSide= variableAssignment.getLeftHandSide();
				ITypeBinding assignmentTypeBinding= leftHandSide.resolveTypeBinding();
				if (assignmentTypeBinding == null) {
					return false;
				}
				type= importRewrite.addImport(assignmentTypeBinding, ast);
				returnType= new ReturnType();
				returnType.type= type;
				returnType.binding= assignmentTypeBinding;
			}
			if (returnType.binding == null) {
				return false;
			}
			MethodDeclaration newMethodDeclaration= ast.newMethodDeclaration();
			newMethodDeclaration.setName((SimpleName) rewrite.createCopyTarget(methodReferenceNode.getName()));
			newMethodDeclaration.modifiers().add(ast.newModifier(ModifierKeyword.PRIVATE_KEYWORD));
			if (addStaticModifier) {
				newMethodDeclaration.modifiers().add(ast.newModifier(ModifierKeyword.STATIC_KEYWORD));
			}

			IMethodBinding functionalInterfaceMethod= variableDeclarationStatement == null
					? returnType.binding.getFunctionalInterfaceMethod()
					: variableDeclarationStatement.getType().resolveBinding().getFunctionalInterfaceMethod();
			if (functionalInterfaceMethod != null) {
				returnType.type= importRewrite.addImport(functionalInterfaceMethod.getReturnType(), ast);
				returnType.binding= functionalInterfaceMethod.getReturnType();
				ITypeBinding[] typeArguments= functionalInterfaceMethod.getParameterTypes();
				for (int i= 0; i < typeArguments.length; i++) {
					ITypeBinding iTypeBinding= typeArguments[i];
					SingleVariableDeclaration newSingleVariableDeclaration= ast.newSingleVariableDeclaration();
					newSingleVariableDeclaration.setName(ast.newSimpleName(iTypeBinding.getErasure().getName().toLowerCase() + (i + 1)));
					newSingleVariableDeclaration.setType(importRewrite.addImport(iTypeBinding.getErasure(), ast));
					newMethodDeclaration.parameters().add(newSingleVariableDeclaration);
				}
			}
			newMethodDeclaration.setReturnType2(returnType.type);
			Block newBlock= getNewReturnBlock(ast, returnType.binding);
			newMethodDeclaration.setBody(newBlock);
			listRewrite.insertLast(newMethodDeclaration, null);

			// add proposal
			resultingCollections.add(proposal);
			return true;
		}

		/*
		 * method invocation
		 */
		IMethodBinding methodBinding= methodInvocationNode == null ? null : methodInvocationNode.resolveMethodBinding();
		if (methodBinding == null) {
			return false;
		}
		List<ASTNode> arguments= methodInvocationNode.arguments();
		int index= -1;
		for (int i= 0; i < arguments.size(); i++) {
			ASTNode node= arguments.get(i);
			if (node.equals(methodReferenceNode)) {
				index= i;
				break;
			}
		}
		ITypeBinding[] parameterTypes= methodBinding.getParameterTypes();
		ITypeBinding[] typeArguments= methodBinding.getTypeArguments();
		ITypeBinding[] parameterTypesFunctionalInterface= parameterTypes[index].getFunctionalInterfaceMethod().getParameterTypes();
		ITypeBinding returnTypeBindingFunctionalInterface= parameterTypes[index].getFunctionalInterfaceMethod().getReturnType();
		MethodDeclaration newMethodDeclaration= ast.newMethodDeclaration();
		newMethodDeclaration.modifiers().add(ast.newModifier(ModifierKeyword.PRIVATE_KEYWORD));
		if (addStaticModifier) {
			newMethodDeclaration.modifiers().add(ast.newModifier(ModifierKeyword.STATIC_KEYWORD));
		}
		Type newReturnType= null;
		if (returnTypeBindingFunctionalInterface.isPrimitive()) {
			newReturnType= ast.newPrimitiveType(PrimitiveType.toCode(returnTypeBindingFunctionalInterface.getName()));
		} else {
			newReturnType= importRewrite.addImport(returnTypeBindingFunctionalInterface, ast);
			ITypeBinding[] typeParameters= typeDeclaration.resolveBinding().getTypeParameters();
			bIf: if (returnTypeBindingFunctionalInterface.isTypeVariable() || returnTypeBindingFunctionalInterface.isParameterizedType()) {
				for (ITypeBinding typeParameter : typeParameters) {
					// check if parameter type is a Type parameter of the class
					if (Bindings.equals(typeParameter, returnTypeBindingFunctionalInterface)) {
						break bIf;
					}
				}
				TypeParameter newTypeParameter= ast.newTypeParameter();
				newTypeParameter.setName(ast.newSimpleName(returnTypeBindingFunctionalInterface.getName()));
				addIfMissing(newMethodDeclaration, newTypeParameter);
			}
		}
		newMethodDeclaration.setName((SimpleName) rewrite.createCopyTarget(methodReferenceNode.getName()));
		newMethodDeclaration.setReturnType2(newReturnType);
		pLoop: for (int i= 0; i < parameterTypesFunctionalInterface.length; i++) {
			ITypeBinding parameterType2= parameterTypesFunctionalInterface[i];
			SingleVariableDeclaration newSingleVariableDeclaration= ast.newSingleVariableDeclaration();
			if (parameterType2.isCapture()) {
				newSingleVariableDeclaration.setName(ast.newSimpleName(parameterType2.getErasure().getName().toLowerCase() + (i + 1)));
				newSingleVariableDeclaration.setType(importRewrite.addImport(parameterType2.getErasure(), ast));
			} else {
				newSingleVariableDeclaration.setName(ast.newSimpleName(parameterType2.getName().toLowerCase() + (i + 1)));
				newSingleVariableDeclaration.setType(importRewrite.addImport(parameterType2, ast));
			}
			newMethodDeclaration.parameters().add(newSingleVariableDeclaration);
			ITypeBinding[] typeParameters= typeDeclaration.resolveBinding().getTypeParameters();
			if (parameterType2.isTypeVariable()) {
				// check if parameter type is a Type parameter of the class
				for (ITypeBinding typeParameter : typeParameters) {
					if (Bindings.equals(typeParameter, parameterType2)) {
						continue pLoop;
					}
				}

				TypeParameter newTypeParameter= ast.newTypeParameter();
				newTypeParameter.setName(ast.newSimpleName(importRewrite.addImport(parameterType2)));
				ITypeBinding[] typeBounds= parameterType2.getTypeBounds();
				for (ITypeBinding typeBound : typeBounds) {
					newTypeParameter.typeBounds().add(importRewrite.addImport(typeBound, ast));
				}
				addIfMissing(newMethodDeclaration, newTypeParameter);
			}
		}
		for (int i= 0; i < typeArguments.length; i++) {
			ITypeBinding typeArgument= typeArguments[i];
			SingleVariableDeclaration newSingleVariableDeclaration= ast.newSingleVariableDeclaration();
			newSingleVariableDeclaration.setName(ast.newSimpleName(typeArgument.getName().toLowerCase() + (i + 1)));
			newSingleVariableDeclaration.setType(importRewrite.addImport(typeArgument, ast));
			newMethodDeclaration.parameters().add(newSingleVariableDeclaration);
			if (typeArgument.isTypeVariable()) {
				TypeParameter newTypeParameter= ast.newTypeParameter();
				newTypeParameter.setName(ast.newSimpleName(importRewrite.addImport(typeArgument)));
				newMethodDeclaration.typeParameters().add(newTypeParameter);
			}
		}
		Block newBlock= getNewReturnBlock(ast, returnTypeBindingFunctionalInterface);
		newMethodDeclaration.setBody(newBlock);
		listRewrite.insertLast(newMethodDeclaration, null);

		// add proposal
		resultingCollections.add(proposal);
		return true;
	}

	private static void addIfMissing(MethodDeclaration methodDeclaration, TypeParameter newTypeParameter) {
		List<TypeParameter> typeParameters= methodDeclaration.typeParameters();
		for(TypeParameter typeParameter : typeParameters) {
			boolean equals= typeParameter.getName().getFullyQualifiedName().equals(newTypeParameter.getName().getFullyQualifiedName());
			if(equals) {
				return;
			}
		}
		typeParameters.add(newTypeParameter);
	}

	public static boolean getInferDiamondArgumentsProposal(IInvocationContext context, ASTNode node, IProblemLocation[] locations, Collection<ICommandAccess> resultingCollections) {
		// don't add if already added as quick fix
		if (containsMatchingProblem(locations, IProblem.DiamondNotBelow17))
			return false;
		ParameterizedType createdType= null;

		if (node instanceof Name) {
			Name name= ASTNodes.getTopMostName((Name) node);
			if (name.getLocationInParent() == SimpleType.NAME_PROPERTY ||
					name.getLocationInParent() == NameQualifiedType.NAME_PROPERTY) {
				ASTNode type= name.getParent();
				if (type.getLocationInParent() == ParameterizedType.TYPE_PROPERTY) {
					createdType= (ParameterizedType) type.getParent();
					if (createdType.getLocationInParent() != ClassInstanceCreation.TYPE_PROPERTY) {
						return false;
					}
				}
			}
		} else if (node instanceof ParameterizedType) {
			createdType= (ParameterizedType) node;
			if (createdType.getLocationInParent() != ClassInstanceCreation.TYPE_PROPERTY) {
				return false;
			}
		} else if (node instanceof ClassInstanceCreation) {
			ClassInstanceCreation creation= (ClassInstanceCreation) node;
			Type type= creation.getType();
			if (type instanceof ParameterizedType) {
				createdType= (ParameterizedType) type;
			}
		}

		IProposableFix fix= TypeParametersFix.createInsertInferredTypeArgumentsFix(context.getASTRoot(), createdType);
		if (fix != null && resultingCollections != null) {
			Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
			int relevance= locations == null ? IProposalRelevance.INSERT_INFERRED_TYPE_ARGUMENTS : IProposalRelevance.INSERT_INFERRED_TYPE_ARGUMENTS_ERROR; // if error -> higher than ReorgCorrectionsSubProcessor.getNeedHigherComplianceProposals()
			Map<String, String> options= new HashMap<>();
			options.put(CleanUpConstants.INSERT_INFERRED_TYPE_ARGUMENTS, CleanUpOptions.TRUE);
			FixCorrectionProposal proposal= new FixCorrectionProposal(fix, new TypeParametersCleanUp(options), relevance, image, context);
			resultingCollections.add(proposal);
		} else {
			return false;
		}
		return true;
	}

	private static boolean getJoinVariableProposals(IInvocationContext context, ASTNode node, Collection<ICommandAccess> resultingCollections) {
		ASTNode parent= node.getParent();

		VariableDeclarationFragment fragment= null;
		boolean onFirstAccess= false;
		if (node instanceof SimpleName && node.getLocationInParent() == Assignment.LEFT_HAND_SIDE_PROPERTY) {
			onFirstAccess= true;
			SimpleName name= (SimpleName) node;
			IBinding binding= name.resolveBinding();
			if (!(binding instanceof IVariableBinding)) {
				return false;
			}
			ASTNode declaring= context.getASTRoot().findDeclaringNode(binding);
			if (declaring instanceof VariableDeclarationFragment) {
				fragment= (VariableDeclarationFragment) declaring;
			} else {
				return false;
			}
		} else if (parent instanceof VariableDeclarationFragment) {
			fragment= (VariableDeclarationFragment) parent;
		} else {
			return false;
		}

		IVariableBinding binding= fragment.resolveBinding();
		Expression initializer= fragment.getInitializer();
		if ((initializer != null && initializer.getNodeType() != ASTNode.NULL_LITERAL) || binding == null || binding.isField()) {
			return false;
		}

		if (!(fragment.getParent() instanceof VariableDeclarationStatement)) {
			return false;
		}
		VariableDeclarationStatement statement= (VariableDeclarationStatement) fragment.getParent();

		SimpleName[] names= LinkedNodeFinder.findByBinding(statement.getParent(), binding);
		if (names.length <= 1 || names[0] != fragment.getName()) {
			return false;
		}
		SimpleName firstAccess= names[1];
		if (onFirstAccess) {
			if (firstAccess != node) {
				return false;
			}
		} else {
			if (firstAccess.getLocationInParent() != Assignment.LEFT_HAND_SIDE_PROPERTY) {
				return false;
			}
		}
		Assignment assignment= (Assignment) firstAccess.getParent();
		if (assignment.getLocationInParent() != ExpressionStatement.EXPRESSION_PROPERTY) {
			return false;
		}
		ExpressionStatement assignParent= (ExpressionStatement) assignment.getParent();
		IfStatement ifStatement= null;
		Expression thenExpression= null;
		Expression elseExpression= null;
		ITypeBinding exprBinding= null;

		ASTNode assignParentParent= assignParent.getParent();
		if (assignParentParent instanceof IfStatement
				|| (assignParentParent.getLocationInParent() == IfStatement.THEN_STATEMENT_PROPERTY
						&& !(assignParentParent.subtreeMatch(new ASTMatcher(), statement.getParent())))) {
			if (assignParentParent.getLocationInParent() == IfStatement.THEN_STATEMENT_PROPERTY) {
				assignParentParent= assignParentParent.getParent();
			}
			ifStatement= (IfStatement) assignParentParent;
			Statement thenStatement= getSingleStatement(ifStatement.getThenStatement());
			Statement elseStatement= getSingleStatement(ifStatement.getElseStatement());
			if (thenStatement == null || elseStatement == null) {
				return false;
			}

			if (thenStatement instanceof ExpressionStatement && elseStatement instanceof ExpressionStatement) {
				Expression inner1= ((ExpressionStatement) thenStatement).getExpression();
				Expression inner2= ((ExpressionStatement) elseStatement).getExpression();
				if (inner1 instanceof Assignment && inner2 instanceof Assignment) {
					Assignment assign1= (Assignment) inner1;
					Assignment assign2= (Assignment) inner2;
					Expression left1= assign1.getLeftHandSide();
					Expression left2= assign2.getLeftHandSide();
					if (left1 instanceof Name && left2 instanceof Name && assign1.getOperator() == assign2.getOperator()) {
						IBinding bind1= ((Name) left1).resolveBinding();
						IBinding bind2= ((Name) left2).resolveBinding();
						if (bind1 == bind2 && bind1 instanceof IVariableBinding) {
							exprBinding= ((IVariableBinding) bind1).getType();
							thenExpression= assign1.getRightHandSide();
							elseExpression= assign2.getRightHandSide();
						}
					}
				}
			}
			if (thenExpression == null || elseExpression == null) {
				return false;
			}
		} else {
			// Be conservative and don't allow anything but Blocks between the
			// VariableDeclarationStatement and the ExpressionStatement to join
			ASTNode n= assignParent.getParent();
			ASTNode statementParent= statement.getParent();
			ASTMatcher matcher= new ASTMatcher();
			boolean complete= false;
			while (!complete) {
				if (n != null && n.getNodeType() == statementParent.getNodeType()) {
					if (n.subtreeMatch(matcher, statementParent)) {
						break;
					}
				}
				if (n instanceof Block) {
					n= n.getParent();
				}
				return false;
			}
		}

		if (resultingCollections == null) {
			return true;
		}

		AST ast= statement.getAST();
		ASTRewrite rewrite= ASTRewrite.create(ast);
		TightSourceRangeComputer sourceRangeComputer= new TightSourceRangeComputer();
		sourceRangeComputer.addTightSourceNode(ifStatement != null ? ifStatement : assignParent);
		rewrite.setTargetSourceRangeComputer(sourceRangeComputer);

		String label= CorrectionMessages.QuickAssistProcessor_joindeclaration_description;
		Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_LOCAL);
		LinkedCorrectionProposal proposal= new LinkedCorrectionProposal(label, context.getCompilationUnit(), rewrite, IProposalRelevance.JOIN_VARIABLE_DECLARATION, image);
		proposal.setCommandId(SPLIT_JOIN_VARIABLE_DECLARATION_ID);

		if (ifStatement != null) {
			// prepare conditional expression
			ConditionalExpression conditionalExpression= ast.newConditionalExpression();
			Expression conditionCopy= (Expression) rewrite.createCopyTarget(ifStatement.getExpression());
			conditionalExpression.setExpression(conditionCopy);
			Expression thenCopy= (Expression) rewrite.createCopyTarget(thenExpression);
			Expression elseCopy= (Expression) rewrite.createCopyTarget(elseExpression);

			IJavaProject project= context.getCompilationUnit().getJavaProject();
			if (!JavaModelUtil.is50OrHigher(project)) {
				ITypeBinding thenBinding= thenExpression.resolveTypeBinding();
				ITypeBinding elseBinding= elseExpression.resolveTypeBinding();
				if (thenBinding != null && elseBinding != null && exprBinding != null && !elseBinding.isAssignmentCompatible(thenBinding)) {
					CastExpression castException= ast.newCastExpression();
					ImportRewrite importRewrite= proposal.createImportRewrite(context.getASTRoot());
					ImportRewriteContext importRewriteContext= new ContextSensitiveImportRewriteContext(node, importRewrite);
					castException.setType(importRewrite.addImport(exprBinding, ast, importRewriteContext, TypeLocation.CAST));
					castException.setExpression(elseCopy);
					elseCopy= castException;
				}
			} else if (JavaModelUtil.is1d7OrHigher(project)) {
				addExplicitTypeArgumentsIfNecessary(rewrite, proposal, thenExpression);
				addExplicitTypeArgumentsIfNecessary(rewrite, proposal, elseExpression);
			}
			conditionalExpression.setThenExpression(thenCopy);
			conditionalExpression.setElseExpression(elseCopy);
			rewrite.set(fragment, VariableDeclarationFragment.INITIALIZER_PROPERTY, conditionalExpression, null);
			rewrite.remove(ifStatement, null);
		} else {
			Expression placeholder= (Expression) rewrite.createMoveTarget(assignment.getRightHandSide());
			rewrite.set(fragment, VariableDeclarationFragment.INITIALIZER_PROPERTY, placeholder, null);

			if (onFirstAccess) {
				// replace assignment with variable declaration
				rewrite.replace(assignParent, rewrite.createMoveTarget(statement), null);
			} else {
				// different scopes -> remove assignments, set variable initializer
				if (ASTNodes.isControlStatementBody(assignParent.getLocationInParent())) {
					Block block= ast.newBlock();
					rewrite.replace(assignParent, block, null);
				} else {
					rewrite.remove(assignParent, null);
				}
			}
		}

		proposal.setEndPosition(rewrite.track(fragment.getName()));
		resultingCollections.add(proposal);
		return true;

	}

	private static void addExplicitTypeArgumentsIfNecessary(ASTRewrite rewrite, ASTRewriteCorrectionProposal proposal, Expression invocation) {
		if (Invocations.isResolvedTypeInferredFromExpectedType(invocation)) {
			ITypeBinding[] typeArguments= Invocations.getInferredTypeArguments(invocation);
			if (typeArguments == null)
				return;

			ImportRewrite importRewrite= proposal.getImportRewrite();
			if (importRewrite == null) {
				importRewrite= proposal.createImportRewrite((CompilationUnit) invocation.getRoot());
			}
			ImportRewriteContext importRewriteContext= new ContextSensitiveImportRewriteContext(invocation, importRewrite);

			AST ast= invocation.getAST();
			ListRewrite typeArgsRewrite= Invocations.getInferredTypeArgumentsRewrite(rewrite, invocation);

			for (ITypeBinding typeArgument : typeArguments) {
				Type typeArgumentNode= importRewrite.addImport(typeArgument, ast, importRewriteContext, TypeLocation.TYPE_ARGUMENT);
				typeArgsRewrite.insertLast(typeArgumentNode, null);
			}

			if (invocation instanceof MethodInvocation) {
				MethodInvocation methodInvocation= (MethodInvocation) invocation;
				Expression expression= methodInvocation.getExpression();
				if (expression == null) {
					IMethodBinding methodBinding= methodInvocation.resolveMethodBinding();
					if (methodBinding != null && Modifier.isStatic(methodBinding.getModifiers())) {
						expression= ast.newName(importRewrite.addImport(methodBinding.getDeclaringClass().getTypeDeclaration(), importRewriteContext));
					} else {
						expression= ast.newThisExpression();
					}
					rewrite.set(invocation, MethodInvocation.EXPRESSION_PROPERTY, expression, null);
				}
			}
		}
	}

	private static Statement getSingleStatement(Statement statement) {
		if (statement instanceof Block) {
			List<Statement> blockStatements= ((Block) statement).statements();
			if (blockStatements.size() != 1) {
				return null;
			}
			return blockStatements.get(0);
		}
		return statement;
	}

	private static boolean getSplitVariableProposals(IInvocationContext context, ASTNode node, Collection<ICommandAccess> resultingCollections) throws JavaModelException {
		if (resultingCollections == null) {
			return true;
		}
		VariableDeclarationFragment fragment;
		if (node instanceof VariableDeclarationFragment) {
			fragment= (VariableDeclarationFragment) node;
		} else if (node.getLocationInParent() == VariableDeclarationFragment.NAME_PROPERTY) {
			fragment= (VariableDeclarationFragment) node.getParent();
		} else {
			return false;
		}

		if (fragment.getInitializer() == null) {
			return false;
		}

		Statement statement;
		ASTNode fragParent= fragment.getParent();
		if (fragParent instanceof VariableDeclarationStatement) {
			statement= (VariableDeclarationStatement) fragParent;
		} else if (fragParent instanceof VariableDeclarationExpression) {
			if (fragParent.getLocationInParent() == TryStatement.RESOURCES2_PROPERTY) {
				return false;
			}
			statement= (Statement) fragParent.getParent();
		} else {
			return false;
		}
		// statement is ForStatement or VariableDeclarationStatement
		ASTNode statementParent= statement.getParent();
		StructuralPropertyDescriptor property= statement.getLocationInParent();
		if (!property.isChildListProperty()) {
			return false;
		}

		List<? extends ASTNode> list= ASTNodes.getChildListProperty(statementParent, (ChildListPropertyDescriptor) property);

		AST ast= statement.getAST();
		ASTRewrite rewrite= ASTRewrite.create(ast);

		String label= CorrectionMessages.QuickAssistProcessor_splitdeclaration_description;
		Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_LOCAL);
		ASTRewriteCorrectionProposal proposal= new ASTRewriteCorrectionProposal(label, context.getCompilationUnit(), rewrite, IProposalRelevance.SPLIT_VARIABLE_DECLARATION, image);
		boolean commandConflict= false;
		for (ICommandAccess completionProposal : resultingCollections) {
			if (completionProposal instanceof ChangeCorrectionProposal) {
				if (SPLIT_JOIN_VARIABLE_DECLARATION_ID.equals(((ChangeCorrectionProposal) completionProposal).getCommandId())) {
					commandConflict= true;
				}
			}
		}
		if (!commandConflict) {
			proposal.setCommandId(SPLIT_JOIN_VARIABLE_DECLARATION_ID);
		}

		// for multiple declarations; all must be moved outside, leave none behind
		if (statement instanceof ForStatement) {
			IBuffer buffer= context.getCompilationUnit().getBuffer();
			ForStatement forStatement= (ForStatement) statement;
			VariableDeclarationExpression oldVarDecl= (VariableDeclarationExpression) fragParent;
			Type type= oldVarDecl.getType();
			List<VariableDeclarationFragment> oldFragments= oldVarDecl.fragments();
			CompilationUnit cup= (CompilationUnit) oldVarDecl.getRoot();
			ListRewrite forListRewrite= rewrite.getListRewrite(forStatement, ForStatement.INITIALIZERS_PROPERTY);
			// create the new initializers
			for (VariableDeclarationFragment oldFragment : oldFragments) {
				int extendedStartPositionFragment= cup.getExtendedStartPosition(oldFragment);
				int extendedLengthFragment= cup.getExtendedLength(oldFragment);
				StringBuilder codeFragment= new StringBuilder(buffer.getText(extendedStartPositionFragment, extendedLengthFragment));
				if (oldFragment.getInitializer() == null) {
					ITypeBinding typeBinding= type.resolveBinding();
					if ("Z".equals(typeBinding.getBinaryName())) { //$NON-NLS-1$
						codeFragment.append(" = false"); //$NON-NLS-1$
					} else if (type.isPrimitiveType()) {
						codeFragment.append(" = 0"); //$NON-NLS-1$
					} else {
						codeFragment.append(" = null"); //$NON-NLS-1$
					}
				}
				Assignment newAssignmentFragment= (Assignment) rewrite.createStringPlaceholder(codeFragment.toString(), ASTNode.ASSIGNMENT);
				forListRewrite.insertLast(newAssignmentFragment, null);
			}

			// create the new declarations
			int extendedStartPositionDeclaration= cup.getExtendedStartPosition(oldVarDecl);
			int firstFragmentStart= ((ASTNode) oldVarDecl.fragments().get(0)).getStartPosition();
			String codeDeclaration= buffer.getText(extendedStartPositionDeclaration, firstFragmentStart - extendedStartPositionDeclaration);
			Type nType= (Type) rewrite.createStringPlaceholder(codeDeclaration.trim(), type.getNodeType());

			VariableDeclarationFragment newFrag= ast.newVariableDeclarationFragment();
			VariableDeclarationStatement newVarDec= ast.newVariableDeclarationStatement(newFrag);
			newVarDec.setType(nType);
			newFrag.setName(ast.newSimpleName(oldFragments.get(0).getName().getIdentifier()));
			newFrag.extraDimensions().addAll(DimensionRewrite.copyDimensions(oldFragments.get(0).extraDimensions(), rewrite));

			for (int i= 1; i < oldFragments.size(); i++) {
				VariableDeclarationFragment oldFragment= oldFragments.get(i);
				newFrag= ast.newVariableDeclarationFragment();
				newFrag.setName(ast.newSimpleName(oldFragment.getName().getIdentifier()));
				newFrag.extraDimensions().addAll(DimensionRewrite.copyDimensions(oldFragment.extraDimensions(), rewrite));
				newVarDec.fragments().add(newFrag);
			}
			newVarDec.modifiers().addAll(ASTNodeFactory.newModifiers(ast, oldVarDecl.getModifiers()));

			ListRewrite listRewriter= rewrite.getListRewrite(statementParent, (ChildListPropertyDescriptor) property);
			listRewriter.insertBefore(newVarDec, statement, null);

			rewrite.remove(oldVarDecl, null);

			resultingCollections.add(proposal);
			return true;
		}

		Statement newStatement= null;
		int insertIndex= list.indexOf(statement);
		ITypeBinding binding= fragment.getInitializer().resolveTypeBinding();
		Expression placeholder= (Expression) rewrite.createMoveTarget(fragment.getInitializer());
		if (placeholder instanceof ArrayInitializer && binding != null && binding.isArray()) {
			ArrayCreation creation= ast.newArrayCreation();
			creation.setInitializer((ArrayInitializer) placeholder);
			final ITypeBinding componentType= binding.getElementType();
			Type type= null;
			if (componentType.isPrimitive()) {
				type= ast.newPrimitiveType(PrimitiveType.toCode(componentType.getName()));
			} else {
				type= ast.newSimpleType(ast.newSimpleName(componentType.getName()));
			}
			creation.setType(ast.newArrayType(type, binding.getDimensions()));
			placeholder= creation;
		}
		if (statement instanceof VariableDeclarationStatement) {
			Assignment assignment= ast.newAssignment();
			assignment.setRightHandSide(placeholder);
			assignment.setLeftHandSide(ast.newSimpleName(fragment.getName().getIdentifier()));

			newStatement= ast.newExpressionStatement(assignment);
			insertIndex+= 1; // add after declaration
		}
		ListRewrite listRewriter= rewrite.getListRewrite(statementParent, (ChildListPropertyDescriptor) property);
		listRewriter.insertAt(newStatement, insertIndex, null);
		resultingCollections.add(proposal);
		return true;
	}

	public static boolean getAssignToVariableProposals(IInvocationContext context, ASTNode node, IProblemLocation[] locations, Collection<ICommandAccess> resultingCollections) {
		Statement statement= ASTResolving.findParentStatement(node);
		if (!(statement instanceof ExpressionStatement)) {
			return false;
		}
		ExpressionStatement expressionStatement= (ExpressionStatement) statement;

		Expression expression= expressionStatement.getExpression();
		if (expression.getNodeType() == ASTNode.ASSIGNMENT) {
			return false; // too confusing and not helpful
		}

		ITypeBinding typeBinding= expression.resolveTypeBinding();
		typeBinding= Bindings.normalizeTypeBinding(typeBinding);
		if (typeBinding == null) {
			return false;
		}
		if (resultingCollections == null) {
			return true;
		}

		// don't add if already added as quick fix
		if (containsMatchingProblem(locations, IProblem.UnusedObjectAllocation))
			return false;

		ICompilationUnit cu= context.getCompilationUnit();

		AssignToVariableAssistProposal localProposal= new AssignToVariableAssistProposal(cu, AssignToVariableAssistProposal.LOCAL, expressionStatement, typeBinding,
				IProposalRelevance.ASSIGN_TO_LOCAL);
		localProposal.setCommandId(ASSIGN_TO_LOCAL_ID);
		resultingCollections.add(localProposal);

		if (isAutoClosable(typeBinding)) {
			AssignToVariableAssistProposal tryWithResourcesProposal= new AssignToVariableAssistProposal(cu, AssignToVariableAssistProposal.TRY_WITH_RESOURCES, expressionStatement, typeBinding,
					IProposalRelevance.ASSIGN_IN_TRY_WITH_RESOURCES);
			tryWithResourcesProposal.setCommandId(ASSIGN_IN_TRY_WITH_RESOURCES_ID);
			resultingCollections.add(tryWithResourcesProposal);
		}

		ASTNode type= ASTResolving.findParentType(expression);
		if (type != null) {
			AssignToVariableAssistProposal fieldProposal= new AssignToVariableAssistProposal(cu, AssignToVariableAssistProposal.FIELD, expressionStatement, typeBinding,
					IProposalRelevance.ASSIGN_TO_FIELD);
			fieldProposal.setCommandId(ASSIGN_TO_FIELD_ID);
			resultingCollections.add(fieldProposal);
		}
		return true;

	}

	private static boolean containsMatchingProblem(IProblemLocation[] locations, int problemId) {
		if (locations != null) {
			for (IProblemLocation location : locations) {
				if (IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER.equals(location.getMarkerType())
						&& location.getProblemId() == problemId) {
					return true;
				}
			}
		}
		return false;
	}

	private static boolean getAssignParamToFieldProposals(IInvocationContext context, ASTNode node, Collection<ICommandAccess> resultingCollections) {
		node= ASTNodes.getNormalizedNode(node);
		ASTNode parent= node.getParent();
		if (!(parent instanceof SingleVariableDeclaration) || !(parent.getParent() instanceof MethodDeclaration)) {
			return false;
		}
		SingleVariableDeclaration paramDecl= (SingleVariableDeclaration) parent;
		IVariableBinding binding= paramDecl.resolveBinding();

		MethodDeclaration methodDecl= (MethodDeclaration) parent.getParent();
		if (binding == null || methodDecl.getBody() == null) {
			return false;
		}
		ITypeBinding typeBinding= binding.getType();
		if (typeBinding == null) {
			return false;
		}

		if (resultingCollections == null) {
			return true;
		}

		ITypeBinding parentType= Bindings.getBindingOfParentType(node);
		if (parentType != null) {
			if (parentType.isInterface()) {
				return false;
			}
			// assign to existing fields
			CompilationUnit root= context.getASTRoot();
			boolean isStaticContext= ASTResolving.isInStaticContext(node);
			for (IVariableBinding curr : parentType.getDeclaredFields()) {
				if (isStaticContext == Modifier.isStatic(curr.getModifiers()) && typeBinding.isAssignmentCompatible(curr.getType())) {
					ASTNode fieldDeclFrag= root.findDeclaringNode(curr);
					if (fieldDeclFrag instanceof VariableDeclarationFragment) {
						VariableDeclarationFragment fragment= (VariableDeclarationFragment) fieldDeclFrag;
						if (fragment.getInitializer() == null) {
							resultingCollections
									.add(new AssignToVariableAssistProposal(context.getCompilationUnit(), paramDecl, fragment, typeBinding, IProposalRelevance.ASSIGN_PARAM_TO_EXISTING_FIELD));
						}
					}
				}
			}
		}

		AssignToVariableAssistProposal fieldProposal= new AssignToVariableAssistProposal(context.getCompilationUnit(), paramDecl, null, typeBinding, IProposalRelevance.ASSIGN_PARAM_TO_NEW_FIELD);
		fieldProposal.setCommandId(ASSIGN_PARAM_TO_FIELD_ID);
		resultingCollections.add(fieldProposal);
		return true;
	}

	private static boolean getAssignAllParamsToFieldsProposals(IInvocationContext context, ASTNode node, Collection<ICommandAccess> resultingCollections) {
		node= ASTNodes.getNormalizedNode(node);
		ASTNode parent= node.getParent();
		if (!(parent instanceof SingleVariableDeclaration) || !(parent.getParent() instanceof MethodDeclaration)) {
			return false;
		}
		MethodDeclaration methodDecl= (MethodDeclaration) parent.getParent();
		if (methodDecl.getBody() == null) {
			return false;
		}
		List<SingleVariableDeclaration> parameters= methodDecl.parameters();
		if (parameters.size() <= 1) {
			return false;
		}
		ITypeBinding parentType= Bindings.getBindingOfParentType(node);
		if (parentType == null || parentType.isInterface()) {
			return false;
		}
		for (SingleVariableDeclaration param : parameters) {
			IVariableBinding binding= param.resolveBinding();
			if (binding == null || binding.getType() == null) {
				return false;
			}
		}
		if (resultingCollections == null) {
			return true;
		}

		AssignToVariableAssistProposal fieldProposal= new AssignToVariableAssistProposal(context.getCompilationUnit(), parameters, IProposalRelevance.ASSIGN_ALL_PARAMS_TO_NEW_FIELDS);
		fieldProposal.setCommandId(ASSIGN_ALL_PARAMS_TO_NEW_FIELDS_ID);
		resultingCollections.add(fieldProposal);
		return true;
	}

	private static boolean getAddFinallyProposals(IInvocationContext context, ASTNode node, Collection<ICommandAccess> resultingCollections) {
		TryStatement tryStatement= ASTResolving.findParentTryStatement(node);
		if (tryStatement == null || tryStatement.getFinally() != null) {
			return false;
		}
		Statement statement= ASTResolving.findParentStatement(node);
		if (tryStatement != statement && tryStatement.getBody() != statement) {
			return false; // an node inside a catch or finally block
		}

		if (resultingCollections == null) {
			return true;
		}

		AST ast= tryStatement.getAST();
		ASTRewrite rewrite= ASTRewrite.create(ast);
		Block finallyBody= ast.newBlock();

		rewrite.set(tryStatement, TryStatement.FINALLY_PROPERTY, finallyBody, null);

		String label= CorrectionMessages.QuickAssistProcessor_addfinallyblock_description;
		Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_ADD);
		ASTRewriteCorrectionProposal proposal= new ASTRewriteCorrectionProposal(label, context.getCompilationUnit(), rewrite, IProposalRelevance.ADD_FINALLY_BLOCK, image);
		resultingCollections.add(proposal);
		return true;
	}

	private static boolean getAddElseProposals(IInvocationContext context, ASTNode node, Collection<ICommandAccess> resultingCollections) {
		if (!(node instanceof IfStatement)) {
			return false;
		}
		IfStatement ifStatement= (IfStatement) node;
		if (ifStatement.getElseStatement() != null) {
			return false;
		}

		if (resultingCollections == null) {
			return true;
		}

		AST ast= node.getAST();
		ASTRewrite rewrite= ASTRewrite.create(ast);
		Block body= ast.newBlock();

		rewrite.set(ifStatement, IfStatement.ELSE_STATEMENT_PROPERTY, body, null);

		String label= CorrectionMessages.QuickAssistProcessor_addelseblock_description;
		Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_ADD);
		ASTRewriteCorrectionProposal proposal= new ASTRewriteCorrectionProposal(label, context.getCompilationUnit(), rewrite, IProposalRelevance.ADD_ELSE_BLOCK, image);
		resultingCollections.add(proposal);
		return true;
	}

	public static boolean getCatchClauseToThrowsProposals(IInvocationContext context, ASTNode node, Collection<ICommandAccess> resultingCollections) {
		CatchClause catchClause= (CatchClause) ASTResolving.findAncestor(node, ASTNode.CATCH_CLAUSE);
		if (catchClause == null) {
			return false;
		}

		Statement statement= ASTResolving.findParentStatement(node);
		if (statement != catchClause.getParent() && statement != catchClause.getBody()) {
			return false; // selection is in a statement inside the body
		}

		Type type= catchClause.getException().getType();
		if (!type.isSimpleType() && !type.isUnionType() && !type.isNameQualifiedType()) {
			return false;
		}

		BodyDeclaration bodyDeclaration= ASTResolving.findParentBodyDeclaration(catchClause);
		if (!(bodyDeclaration instanceof MethodDeclaration) && !(bodyDeclaration instanceof Initializer)) {
			return false;
		}

		if (resultingCollections == null) {
			return true;
		}

		AST ast= bodyDeclaration.getAST();
		Image image= JavaPluginImages.get(JavaPluginImages.IMG_OBJS_EXCEPTION);

		Type selectedMultiCatchType= null;
		if (type.isUnionType() && node instanceof Name) {
			Name topMostName= ASTNodes.getTopMostName((Name) node);
			ASTNode parent= topMostName.getParent();
			if (parent instanceof SimpleType) {
				selectedMultiCatchType= (SimpleType) parent;
			} else if (parent instanceof NameQualifiedType) {
				selectedMultiCatchType= (NameQualifiedType) parent;
			}
		}

		if (bodyDeclaration instanceof MethodDeclaration) {
			MethodDeclaration methodDeclaration= (MethodDeclaration) bodyDeclaration;

			ASTRewrite rewrite= ASTRewrite.create(ast);
			if (selectedMultiCatchType != null) {
				removeException(rewrite, (UnionType) type, selectedMultiCatchType);
				addExceptionToThrows(ast, methodDeclaration, rewrite, selectedMultiCatchType);
				String label= CorrectionMessages.QuickAssistProcessor_exceptiontothrows_description;
				ASTRewriteCorrectionProposal proposal= new ASTRewriteCorrectionProposal(label, context.getCompilationUnit(), rewrite, IProposalRelevance.REPLACE_EXCEPTION_WITH_THROWS, image);
				resultingCollections.add(proposal);
			} else {
				removeCatchBlock(rewrite, catchClause);
				if (type.isUnionType()) {
					UnionType unionType= (UnionType) type;
					List<Type> types= unionType.types();
					for (Type elementType : types) {
						if (!(elementType instanceof SimpleType)
								&& !(elementType instanceof NameQualifiedType))
							return false;
						addExceptionToThrows(ast, methodDeclaration, rewrite, elementType);
					}
				} else {
					addExceptionToThrows(ast, methodDeclaration, rewrite, type);
				}
				String label= CorrectionMessages.QuickAssistProcessor_catchclausetothrows_description;
				ASTRewriteCorrectionProposal proposal= new ASTRewriteCorrectionProposal(label, context.getCompilationUnit(), rewrite, IProposalRelevance.REPLACE_CATCH_CLAUSE_WITH_THROWS, image);
				resultingCollections.add(proposal);
			}
		}
		{ // for initializers or method declarations
			ASTRewrite rewrite= ASTRewrite.create(ast);
			if (selectedMultiCatchType != null) {
				removeException(rewrite, (UnionType) type, selectedMultiCatchType);
				String label= CorrectionMessages.QuickAssistProcessor_removeexception_description;
				ASTRewriteCorrectionProposal proposal= new ASTRewriteCorrectionProposal(label, context.getCompilationUnit(), rewrite, IProposalRelevance.REMOVE_EXCEPTION, image);
				resultingCollections.add(proposal);
			} else {
				removeCatchBlock(rewrite, catchClause);
				String label= CorrectionMessages.QuickAssistProcessor_removecatchclause_description;
				ASTRewriteCorrectionProposal proposal= new ASTRewriteCorrectionProposal(label, context.getCompilationUnit(), rewrite, IProposalRelevance.REMOVE_CATCH_CLAUSE, image);
				resultingCollections.add(proposal);
			}
		}

		return true;
	}

	private static void removeException(ASTRewrite rewrite, UnionType unionType, Type exception) {
		ListRewrite listRewrite= rewrite.getListRewrite(unionType, UnionType.TYPES_PROPERTY);
		List<Type> types= unionType.types();
		for (Type type : types) {
			if (type.equals(exception)) {
				listRewrite.remove(type, null);
			}
		}
	}

	private static void addExceptionToThrows(AST ast, MethodDeclaration methodDeclaration, ASTRewrite rewrite, Type type2) {
		ITypeBinding binding= type2.resolveBinding();
		if (binding == null || isNotYetThrown(binding, methodDeclaration.thrownExceptionTypes())) {
			Type newType= (Type) ASTNode.copySubtree(ast, type2);

			ListRewrite listRewriter= rewrite.getListRewrite(methodDeclaration, MethodDeclaration.THROWN_EXCEPTION_TYPES_PROPERTY);
			listRewriter.insertLast(newType, null);
		}
	}

	private static void removeCatchBlock(ASTRewrite rewrite, CatchClause catchClause) {
		TryStatement tryStatement= (TryStatement) catchClause.getParent();
		if (tryStatement.catchClauses().size() > 1 || tryStatement.getFinally() != null || !tryStatement.resources().isEmpty()) {
			rewrite.remove(catchClause, null);
		} else {
			Block block= tryStatement.getBody();
			List<Statement> statements= block.statements();
			int nStatements= statements.size();
			if (nStatements == 1) {
				ASTNode first= statements.get(0);
				rewrite.replace(tryStatement, rewrite.createCopyTarget(first), null);
			} else if (nStatements > 1) {
				ListRewrite listRewrite= rewrite.getListRewrite(block, Block.STATEMENTS_PROPERTY);
				ASTNode first= statements.get(0);
				ASTNode last= statements.get(statements.size() - 1);
				ASTNode newStatement= listRewrite.createCopyTarget(first, last);
				if (ASTNodes.isControlStatementBody(tryStatement.getLocationInParent())) {
					Block newBlock= rewrite.getAST().newBlock();
					newBlock.statements().add(newStatement);
					newStatement= newBlock;
				}
				rewrite.replace(tryStatement, newStatement, null);
			} else {
				rewrite.remove(tryStatement, null);
			}
		}
	}

	private static boolean isNotYetThrown(ITypeBinding binding, List<Type> thrownExceptions) {
		for (Type name : thrownExceptions) {
			ITypeBinding elem= name.resolveBinding();
			if (elem != null) {
				if (Bindings.isSuperType(elem, binding)) { // existing exception is base class of new
					return false;
				}
			}
		}
		return true;
	}

	private static boolean getPickoutTypeFromMulticatchProposals(IInvocationContext context, ASTNode node, ArrayList<ASTNode> coveredNodes, Collection<ICommandAccess> resultingCollections) {
		CatchClause catchClause= (CatchClause) ASTResolving.findAncestor(node, ASTNode.CATCH_CLAUSE);
		if (catchClause == null) {
			return false;
		}

		Statement statement= ASTResolving.findParentStatement(node);
		if (statement != catchClause.getParent() && statement != catchClause.getBody()) {
			return false; // selection is in a statement inside the body
		}

		Type type= catchClause.getException().getType();
		if (!type.isUnionType()) {
			return false;
		}

		Type selectedMultiCatchType= null;
		if (type.isUnionType() && node instanceof Name) {
			Name topMostName= ASTNodes.getTopMostName((Name) node);
			ASTNode parent= topMostName.getParent();
			if (parent instanceof SimpleType || parent instanceof NameQualifiedType) {
				selectedMultiCatchType= (Type) parent;
			}
		}

		boolean multipleExceptions= coveredNodes.size() > 1;
		if ((selectedMultiCatchType == null) && (!(node instanceof UnionType) || !multipleExceptions)) {
			return false;
		}

		if (!multipleExceptions) {
			coveredNodes.add(selectedMultiCatchType);
		}

		BodyDeclaration bodyDeclaration= ASTResolving.findParentBodyDeclaration(catchClause);
		if (!(bodyDeclaration instanceof MethodDeclaration) && !(bodyDeclaration instanceof Initializer)) {
			return false;
		}

		if (resultingCollections == null) {
			return true;
		}

		AST ast= bodyDeclaration.getAST();
		ASTRewrite rewrite= ASTRewrite.create(ast);

		CatchClause newCatchClause= ast.newCatchClause();
		SingleVariableDeclaration newSingleVariableDeclaration= ast.newSingleVariableDeclaration();
		UnionType newUnionType= ast.newUnionType();
		List<Type> types= newUnionType.types();
		for (ASTNode typeNode : coveredNodes) {
			types.add((Type) rewrite.createCopyTarget(typeNode));
			rewrite.remove(typeNode, null);
		}
		newSingleVariableDeclaration.setType(newUnionType);
		newSingleVariableDeclaration.setName((SimpleName) rewrite.createCopyTarget(catchClause.getException().getName()));
		newCatchClause.setException(newSingleVariableDeclaration);

		setCatchClauseBody(newCatchClause, rewrite, catchClause);

		TryStatement tryStatement= (TryStatement) catchClause.getParent();
		ListRewrite listRewrite= rewrite.getListRewrite(tryStatement, TryStatement.CATCH_CLAUSES_PROPERTY);
		listRewrite.insertAfter(newCatchClause, catchClause, null);

		Image image= JavaPluginImages.get(JavaPluginImages.IMG_OBJS_EXCEPTION);
		String label= !multipleExceptions
				? CorrectionMessages.QuickAssistProcessor_move_exception_to_separate_catch_block
				: CorrectionMessages.QuickAssistProcessor_move_exceptions_to_separate_catch_block;
		ASTRewriteCorrectionProposal proposal= new ASTRewriteCorrectionProposal(label, context.getCompilationUnit(), rewrite, IProposalRelevance.MOVE_EXCEPTION_TO_SEPERATE_CATCH_BLOCK, image);
		resultingCollections.add(proposal);
		return true;
	}

	private static boolean getConvertToMultiCatchProposals(IInvocationContext context, ASTNode covering, Collection<ICommandAccess> resultingCollections) {
		if (!JavaModelUtil.is1d7OrHigher(context.getCompilationUnit().getJavaProject()))
			return false;

		CatchClause catchClause= (CatchClause) ASTResolving.findAncestor(covering, ASTNode.CATCH_CLAUSE);
		if (catchClause == null) {
			return false;
		}

		Statement statement= ASTResolving.findParentStatement(covering);
		if (statement != catchClause.getParent() && statement != catchClause.getBody()) {
			return false; // selection is in a statement inside the body
		}

		Type type1= catchClause.getException().getType();
		Type selectedMultiCatchType= null;
		if (type1.isUnionType() && covering instanceof Name) {
			Name topMostName= ASTNodes.getTopMostName((Name) covering);
			ASTNode parent= topMostName.getParent();
			if (parent instanceof SimpleType || parent instanceof NameQualifiedType) {
				selectedMultiCatchType= (Type) parent;
			}
		}
		if (selectedMultiCatchType != null)
			return false;

		TryStatement tryStatement= (TryStatement) catchClause.getParent();
		List<CatchClause> catchClauses= tryStatement.catchClauses();
		if (catchClauses.size() <= 1)
			return false;

		String commonSource= null;
		try {
			IBuffer buffer= context.getCompilationUnit().getBuffer();
			for (CatchClause catchClause1 : catchClauses) {
				Block body= catchClause1.getBody();
				String source= buffer.getText(body.getStartPosition(), body.getLength());
				if (commonSource == null) {
					commonSource= source;
				} else {
					if (!commonSource.equals(source))
						return false;
				}
			}
		} catch (JavaModelException e) {
			return false;
		}

		if (resultingCollections == null)
			return true;

		AST ast= covering.getAST();
		ASTRewrite rewrite= ASTRewrite.create(ast);
		TightSourceRangeComputer sourceRangeComputer= new TightSourceRangeComputer();
		sourceRangeComputer.addTightSourceNode(catchClauses.get(catchClauses.size() - 1));
		rewrite.setTargetSourceRangeComputer(sourceRangeComputer);

		CatchClause firstCatchClause= catchClauses.get(0);

		UnionType newUnionType= ast.newUnionType();
		List<Type> types= newUnionType.types();
		for (CatchClause catchClause1 : catchClauses) {
			Type type= catchClause1.getException().getType();
			if (type instanceof UnionType) {
				List<Type> types2= ((UnionType) type).types();
				for (Type type2 : types2) {
					types.add((Type) rewrite.createCopyTarget(type2));
				}
			} else {
				types.add((Type) rewrite.createCopyTarget(type));
			}
		}

		SingleVariableDeclaration newExceptionDeclaration= ast.newSingleVariableDeclaration();
		newExceptionDeclaration.setType(newUnionType);
		newExceptionDeclaration.setName((SimpleName) rewrite.createCopyTarget(firstCatchClause.getException().getName()));
		rewrite.replace(firstCatchClause.getException(), newExceptionDeclaration, null);

		for (int i= 1; i < catchClauses.size(); i++) {
			rewrite.remove(catchClauses.get(i), null);
		}

		Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
		String label= CorrectionMessages.QuickAssistProcessor_convert_to_single_multicatch_block;
		ASTRewriteCorrectionProposal proposal= new ASTRewriteCorrectionProposal(label, context.getCompilationUnit(), rewrite, IProposalRelevance.COMBINE_CATCH_BLOCKS, image);
		resultingCollections.add(proposal);
		return true;
	}

	private static boolean getUnrollMultiCatchProposals(IInvocationContext context, ASTNode covering, Collection<ICommandAccess> resultingCollections) {
		if (!JavaModelUtil.is1d7OrHigher(context.getCompilationUnit().getJavaProject()))
			return false;

		CatchClause catchClause= (CatchClause) ASTResolving.findAncestor(covering, ASTNode.CATCH_CLAUSE);
		if (catchClause == null) {
			return false;
		}

		Statement statement= ASTResolving.findParentStatement(covering);
		if (statement != catchClause.getParent() && statement != catchClause.getBody()) {
			return false; // selection is in a statement inside the body
		}

		Type type1= catchClause.getException().getType();
		Type selectedMultiCatchType= null;
		if (type1.isUnionType() && covering instanceof Name) {
			Name topMostName= ASTNodes.getTopMostName((Name) covering);
			ASTNode parent= topMostName.getParent();
			if (parent instanceof SimpleType || parent instanceof NameQualifiedType) {
				selectedMultiCatchType= (Type) parent;
			}
		}
		if (selectedMultiCatchType != null)
			return false;

		SingleVariableDeclaration singleVariableDeclaration= catchClause.getException();
		Type type= singleVariableDeclaration.getType();
		if (!(type instanceof UnionType))
			return false;

		if (resultingCollections == null)
			return true;

		AST ast= covering.getAST();
		ASTRewrite rewrite= ASTRewrite.create(ast);

		TryStatement tryStatement= (TryStatement) catchClause.getParent();
		ListRewrite listRewrite= rewrite.getListRewrite(tryStatement, TryStatement.CATCH_CLAUSES_PROPERTY);

		UnionType unionType= (UnionType) type;
		List<Type> types= unionType.types();
		for (int i= types.size() - 1; i >= 0; i--) {
			Type type2= types.get(i);
			CatchClause newCatchClause= ast.newCatchClause();

			SingleVariableDeclaration newSingleVariableDeclaration= ast.newSingleVariableDeclaration();
			newSingleVariableDeclaration.setType((Type) rewrite.createCopyTarget(type2));
			newSingleVariableDeclaration.setName((SimpleName) rewrite.createCopyTarget(singleVariableDeclaration.getName()));
			newCatchClause.setException(newSingleVariableDeclaration);
			setCatchClauseBody(newCatchClause, rewrite, catchClause);
			listRewrite.insertAfter(newCatchClause, catchClause, null);
		}
		rewrite.remove(catchClause, null);

		Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
		String label= CorrectionMessages.QuickAssistProcessor_convert_to_multiple_singletype_catch_blocks;
		ASTRewriteCorrectionProposal proposal= new ASTRewriteCorrectionProposal(label, context.getCompilationUnit(), rewrite, IProposalRelevance.USE_SEPARATE_CATCH_BLOCKS, image);
		resultingCollections.add(proposal);
		return true;
	}

	private static void setCatchClauseBody(CatchClause newCatchClause, ASTRewrite rewrite, CatchClause catchClause) {
		// Workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=350285

//		newCatchClause.setBody((Block) rewrite.createCopyTarget(catchClause.getBody()));

		//newCatchClause#setBody() destroys the formatting, hence copy statement by statement.
		List<Statement> statements= catchClause.getBody().statements();
		for (Statement statement : statements) {
			newCatchClause.getBody().statements().add(rewrite.createCopyTarget(statement));
		}
	}

	private static boolean getRenameLocalProposals(IInvocationContext context, ASTNode node, IProblemLocation[] locations, Collection<ICommandAccess> resultingCollections) {
		if (!(node instanceof SimpleName)) {
			return false;
		}
		SimpleName name= (SimpleName) node;
		if (name.getAST().apiLevel() >= AST.JLS10 && name.isVar()) {
			return false;
		}
		IBinding binding= name.resolveBinding();
		if (binding != null && (binding.getKind() == IBinding.PACKAGE || binding.getKind() == IBinding.MODULE)) {
			return false;
		}

		if (containsQuickFixableRenameLocal(locations)) {
			return false;
		}

		if (resultingCollections == null) {
			return true;
		}

		LinkedNamesAssistProposal proposal= new LinkedNamesAssistProposal(context, name);
		if (locations.length != 0) {
			proposal.setRelevance(IProposalRelevance.LINKED_NAMES_ASSIST_ERROR);
		}

		resultingCollections.add(proposal);
		return true;
	}

	private static boolean getRenameRefactoringProposal(IInvocationContext context, ASTNode node, IProblemLocation[] locations, Collection<ICommandAccess> resultingCollections)
			throws CoreException {
		if (!(context instanceof AssistContext)) {
			return false;
		}
		IEditorPart editor= ((AssistContext) context).getEditor();
		if (!(editor instanceof JavaEditor))
			return false;

		if (!(node instanceof SimpleName)) {
			return false;
		}
		SimpleName name= (SimpleName) node;
		if (name.getAST().apiLevel() >= AST.JLS10 && name.isVar()) {
			return false;
		}
		IBinding binding= name.resolveBinding();
		if (binding == null) {
			return false;
		}

		IJavaElement javaElement= binding.getJavaElement();
		if (javaElement == null || !RefactoringAvailabilityTester.isRenameElementAvailable(javaElement)) {
			return false;
		}

		if (resultingCollections == null) {
			return true;
		}

		RenameRefactoringProposal proposal= new RenameRefactoringProposal((JavaEditor) editor);
		if (locations.length != 0) {
			proposal.setRelevance(IProposalRelevance.RENAME_REFACTORING_ERROR);
		} else if (containsQuickFixableRenameLocal(locations)) {
			proposal.setRelevance(IProposalRelevance.RENAME_REFACTORING_QUICK_FIX);
		}


		resultingCollections.add(proposal);
		return true;
	}

	private static boolean containsQuickFixableRenameLocal(IProblemLocation[] locations) {
		if (locations != null) {
			for (IProblemLocation location : locations) {
				if (IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER.equals(location.getMarkerType())) {
					switch (location.getProblemId()) {
						case IProblem.LocalVariableHidingLocalVariable:
						case IProblem.LocalVariableHidingField:
						case IProblem.FieldHidingLocalVariable:
						case IProblem.FieldHidingField:
						case IProblem.ArgumentHidingLocalVariable:
						case IProblem.ArgumentHidingField:
							return true;
					}
				}
			}
		}
		return false;
	}

	public static ASTNode getCopyOfInner(ASTRewrite rewrite, ASTNode statement, boolean toControlStatementBody) {
		if (statement.getNodeType() == ASTNode.BLOCK) {
			Block block= (Block) statement;
			List<Statement> innerStatements= block.statements();
			int nStatements= innerStatements.size();
			if (nStatements == 1) {
				return rewrite.createCopyTarget(innerStatements.get(0));
			} else if (nStatements > 1) {
				if (toControlStatementBody) {
					return rewrite.createCopyTarget(block);
				}
				ListRewrite listRewrite= rewrite.getListRewrite(block, Block.STATEMENTS_PROPERTY);
				ASTNode first= innerStatements.get(0);
				ASTNode last= innerStatements.get(nStatements - 1);
				return listRewrite.createCopyTarget(first, last);
			}
			return null;
		} else {
			return rewrite.createCopyTarget(statement);
		}
	}


	private static boolean getUnWrapProposals(IInvocationContext context, ASTNode node, Collection<ICommandAccess> resultingCollections) {
		ASTNode outer= node;

		Block block= null;
		if (outer.getNodeType() == ASTNode.BLOCK) {
			block= (Block) outer;
			outer= block.getParent();
		}

		ASTNode body= null;
		String label= null;
		if (outer instanceof IfStatement) {
			IfStatement ifStatement= (IfStatement) outer;
			Statement elseBlock= ifStatement.getElseStatement();
			if (elseBlock == null || elseBlock instanceof Block && ((Block) elseBlock).statements().isEmpty()) {
				body= ifStatement.getThenStatement();
			}
			label= CorrectionMessages.QuickAssistProcessor_unwrap_ifstatement;
		} else if (outer instanceof WhileStatement) {
			body= ((WhileStatement) outer).getBody();
			label= CorrectionMessages.QuickAssistProcessor_unwrap_whilestatement;
		} else if (outer instanceof ForStatement) {
			body= ((ForStatement) outer).getBody();
			label= CorrectionMessages.QuickAssistProcessor_unwrap_forstatement;
		} else if (outer instanceof EnhancedForStatement) {
			body= ((EnhancedForStatement) outer).getBody();
			label= CorrectionMessages.QuickAssistProcessor_unwrap_forstatement;
		} else if (outer instanceof SynchronizedStatement) {
			body= ((SynchronizedStatement) outer).getBody();
			label= CorrectionMessages.QuickAssistProcessor_unwrap_synchronizedstatement;
		} else if (outer instanceof SimpleName && outer.getParent() instanceof LabeledStatement) {
			LabeledStatement labeledStatement= (LabeledStatement) outer.getParent();
			outer= labeledStatement;
			body= labeledStatement.getBody();
			label= CorrectionMessages.QuickAssistProcessor_unwrap_labeledstatement;
		} else if (outer instanceof LabeledStatement) {
			body= ((LabeledStatement) outer).getBody();
			label= CorrectionMessages.QuickAssistProcessor_unwrap_labeledstatement;
		} else if (outer instanceof DoStatement) {
			body= ((DoStatement) outer).getBody();
			label= CorrectionMessages.QuickAssistProcessor_unwrap_dostatement;
		} else if (outer instanceof TryStatement) {
			TryStatement tryStatement= (TryStatement) outer;
			if (tryStatement.catchClauses().isEmpty() && tryStatement.resources().isEmpty()) {
				body= tryStatement.getBody();
			}
			label= CorrectionMessages.QuickAssistProcessor_unwrap_trystatement;
		} else if (outer instanceof AnonymousClassDeclaration) {
			List<BodyDeclaration> decls= ((AnonymousClassDeclaration) outer).bodyDeclarations();
			for (BodyDeclaration elem : decls) {
				if (elem instanceof MethodDeclaration) {
					Block curr= ((MethodDeclaration) elem).getBody();
					if (curr != null && !curr.statements().isEmpty()) {
						if (body != null) {
							return false;
						}
						body= curr;
					}
				} else if (elem instanceof TypeDeclaration) {
					return false;
				}
			}
			label= CorrectionMessages.QuickAssistProcessor_unwrap_anonymous;
			outer= ASTResolving.findParentStatement(outer);
			if (outer == null) {
				return false; // private Object o= new Object() { ... };
			}
		} else if (outer instanceof Block) {
			//	-> a block in a block
			body= block;
			outer= block;
			label= CorrectionMessages.QuickAssistProcessor_unwrap_block;
		} else if (outer instanceof ParenthesizedExpression) {
			//ParenthesizedExpression expression= (ParenthesizedExpression) outer;
			//body= expression.getExpression();
			//label= CorrectionMessages.getString("QuickAssistProcessor.unwrap.parenthesis");	 //$NON-NLS-1$
		} else if (outer instanceof MethodInvocation) {
			MethodInvocation invocation= (MethodInvocation) outer;
			if (invocation.arguments().size() == 1) {
				body= (ASTNode) invocation.arguments().get(0);
				if (invocation.getParent().getNodeType() == ASTNode.EXPRESSION_STATEMENT) {
					int kind= body.getNodeType();
					if (kind != ASTNode.ASSIGNMENT && kind != ASTNode.PREFIX_EXPRESSION && kind != ASTNode.POSTFIX_EXPRESSION
							&& kind != ASTNode.METHOD_INVOCATION && kind != ASTNode.SUPER_METHOD_INVOCATION) {
						body= null;
					}
				}
				label= CorrectionMessages.QuickAssistProcessor_unwrap_methodinvocation;
			}
		}
		if (body == null) {
			return false;
		}
		ASTRewrite rewrite= ASTRewrite.create(outer.getAST());
		ASTNode inner= getCopyOfInner(rewrite, body, ASTNodes.isControlStatementBody(outer.getLocationInParent()));
		if (inner == null) {
			return false;
		}
		if (resultingCollections == null) {
			return true;
		}

		rewrite.replace(outer, inner, null);
		Image image= JavaPluginImages.get(JavaPluginImages.IMG_OBJS_EXCEPTION);
		ASTRewriteCorrectionProposal proposal= new ASTRewriteCorrectionProposal(label, context.getCompilationUnit(), rewrite, IProposalRelevance.UNWRAP_STATEMENTS, image);
		resultingCollections.add(proposal);
		return true;
	}

	private static boolean isControlStatementWithBlock(ASTNode node) {
		switch (node.getNodeType()) {
			case ASTNode.IF_STATEMENT:
			case ASTNode.WHILE_STATEMENT:
			case ASTNode.FOR_STATEMENT:
			case ASTNode.ENHANCED_FOR_STATEMENT:
			case ASTNode.DO_STATEMENT:
				return true;
			default:
				return false;
		}
	}

	private static boolean getRemoveBlockProposals(IInvocationContext context, ASTNode coveringNode, Collection<ICommandAccess> resultingCollections) {
		IProposableFix[] fixes= ControlStatementsFix.createRemoveBlockFix(context.getASTRoot(), coveringNode);
		if (fixes != null) {
			if (resultingCollections == null) {
				return true;
			}
			Map<String, String> options= new Hashtable<>();
			options.put(CleanUpConstants.CONTROL_STATEMENTS_USE_BLOCKS, CleanUpOptions.TRUE);
			options.put(CleanUpConstants.CONTROL_STATEMENTS_USE_BLOCKS_NEVER, CleanUpOptions.TRUE);
			ICleanUp cleanUp= new ControlStatementsCleanUp(options);
			for (IProposableFix fix : fixes) {
				Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
				FixCorrectionProposal proposal= new FixCorrectionProposal(fix, cleanUp, IProposalRelevance.REMOVE_BLOCK_FIX, image, context);
				resultingCollections.add(proposal);
			}
			return true;
		}
		return false;
	}

	private static boolean getTryWithResourceProposals(IInvocationContext context, ASTNode node, ArrayList<ASTNode> coveredNodes, Collection<ICommandAccess> resultingCollections)
			throws IllegalArgumentException, CoreException {

		ASTNode parentStatement= ASTResolving.findAncestor(node, ASTNode.VARIABLE_DECLARATION_STATEMENT);
		if (!(parentStatement instanceof VariableDeclarationStatement) &&
				!(parentStatement instanceof ExpressionStatement) &&
				!(node instanceof SimpleName)
				&& (coveredNodes == null || coveredNodes.isEmpty())) {
			return false;
		}
		List<ASTNode> coveredStatements= new ArrayList<>();
		if (coveredNodes == null || coveredNodes.isEmpty() && parentStatement != null) {
			coveredStatements.add(parentStatement);
		} else {
			for (ASTNode coveredNode : coveredNodes) {
				Statement statement= ASTResolving.findParentStatement(coveredNode);
				if (statement == null) {
					continue;
				}
				if (!coveredStatements.contains(statement)) {
					coveredStatements.add(statement);
				}
			}
		}
		List<ASTNode> coveredAutoClosableNodes= getCoveredAutoClosableNodes(coveredStatements);
		if (coveredAutoClosableNodes.isEmpty()) {
			return false;
		}

		BodyDeclaration parentBodyDeclaration= ASTResolving.findParentBodyDeclaration(node);
		int start= coveredAutoClosableNodes.get(0).getStartPosition();
		int end= start;

		for (ASTNode astNode : coveredAutoClosableNodes) {
			int endPosition= findEndPostion(astNode);
			end= Math.max(end, endPosition);
		}

		// recursive loop to find all nodes affected by wrapping in try block
		List<ASTNode> nodesInRange= SurroundWithTryWithResourcesRefactoring.findNodesInRange(parentBodyDeclaration, start, end);
		int oldEnd= end;
		while (true) {
			int newEnd= oldEnd;
			for (ASTNode astNode : nodesInRange) {
				int endPosition= findEndPostion(astNode);
				newEnd= Math.max(newEnd, endPosition);
			}
			if (newEnd > oldEnd) {
				oldEnd= newEnd;
				nodesInRange= SurroundWithTryWithResourcesRefactoring.findNodesInRange(parentBodyDeclaration, start, newEnd);
				continue;
			}
			break;
		}
		nodesInRange.removeAll(coveredAutoClosableNodes);

		CompilationUnit cu= (CompilationUnit) node.getRoot();
		IBuffer buffer= context.getCompilationUnit().getBuffer();
		AST ast= node.getAST();
		ASTRewrite rewrite= ASTRewrite.create(ast);
		TryStatement newTryStatement= ast.newTryStatement();
		Block newTryBody= ast.newBlock();
		newTryStatement.setBody(newTryBody);
		ICompilationUnit icu= context.getCompilationUnit();
		ASTNode lastNode= nodesInRange.isEmpty() ? coveredAutoClosableNodes.get(coveredAutoClosableNodes.size() - 1)
				: nodesInRange.get(nodesInRange.size() - 1);
		Selection selection= Selection.createFromStartLength(start, lastNode.getStartPosition() - start + lastNode.getLength());
		SurroundWithTryWithResourcesAnalyzer analyzer= new SurroundWithTryWithResourcesAnalyzer(icu, selection);
		cu.accept(analyzer);
		ITypeBinding[] exceptions= analyzer.getExceptions(analyzer.getSelection());
		List<ITypeBinding> allExceptions= new ArrayList<>(Arrays.asList(exceptions));
		for (ASTNode coveredNode : coveredAutoClosableNodes) {
			ASTNode findAncestor= ASTResolving.findAncestor(coveredNode, ASTNode.VARIABLE_DECLARATION_STATEMENT);
			if (findAncestor == null) {
				findAncestor= ASTResolving.findAncestor(coveredNode, ASTNode.ASSIGNMENT);
			}
			if (findAncestor instanceof VariableDeclarationStatement) {
				VariableDeclarationStatement vds= (VariableDeclarationStatement) findAncestor;
				String commentToken= null;
				int extendedStatementStart= cu.getExtendedStartPosition(vds);
				if (vds.getStartPosition() > extendedStatementStart) {
					commentToken= buffer.getText(extendedStatementStart, vds.getStartPosition() - extendedStatementStart);
				}
				Type type= vds.getType();
				ITypeBinding typeBinding= type.resolveBinding();
				if (typeBinding != null) {
					IMethodBinding close= SurroundWithTryWithResourcesRefactoring.findAutocloseMethod(typeBinding);
					if (close != null) {
						for (ITypeBinding exceptionType : close.getExceptionTypes()) {
							if (!allExceptions.contains(exceptionType)) {
								allExceptions.add(exceptionType);
							}
						}
					}
				}
				String typeName= buffer.getText(type.getStartPosition(), type.getLength());

				for (Object object : vds.fragments()) {
					VariableDeclarationFragment variableDeclarationFragment= (VariableDeclarationFragment) object;
					VariableDeclarationFragment newVariableDeclarationFragment= ast.newVariableDeclarationFragment();
					SimpleName name= variableDeclarationFragment.getName();

					if (commentToken == null) {
						int extendedStart= cu.getExtendedStartPosition(variableDeclarationFragment);
						commentToken= buffer.getText(extendedStart, variableDeclarationFragment.getStartPosition() - extendedStart);
					}
					commentToken= Strings.trimTrailingTabsAndSpaces(commentToken);

					newVariableDeclarationFragment.setName(ast.newSimpleName(name.getIdentifier()));
					Expression newExpression= null;
					Expression initializer= variableDeclarationFragment.getInitializer();
					if (initializer == null) {
						rewrite.remove(coveredNode, null);
						continue;
					} else {
						newExpression= (Expression) rewrite.createMoveTarget(initializer);
					}
					newVariableDeclarationFragment.setInitializer(newExpression);
					VariableDeclarationExpression newVariableDeclarationExpression= ast.newVariableDeclarationExpression(newVariableDeclarationFragment);
					newVariableDeclarationExpression.setType(
							(Type) rewrite.createStringPlaceholder(commentToken + typeName, type.getNodeType()));
					newTryStatement.resources().add(newVariableDeclarationExpression);
					commentToken= null;
				}
			}
		}

		if (newTryStatement.resources().isEmpty()) {
			return false;
		}

		String label= CorrectionMessages.QuickAssistProcessor_convert_to_try_with_resource;
		Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
		LinkedCorrectionProposal proposal= new LinkedCorrectionProposal(label, context.getCompilationUnit(), rewrite, IProposalRelevance.SURROUND_WITH_TRY_CATCH, image);

		ImportRewrite imports= proposal.createImportRewrite(context.getASTRoot());
		ImportRewriteContext importRewriteContext= new ContextSensitiveImportRewriteContext(node, imports);

		CatchClause catchClause= ast.newCatchClause();
		SingleVariableDeclaration decl= ast.newSingleVariableDeclaration();
		String varName= StubUtility.getExceptionVariableName(icu.getJavaProject());
		parentBodyDeclaration.getRoot().accept(analyzer);
		CodeScopeBuilder.Scope scope= CodeScopeBuilder.perform(analyzer.getEnclosingBodyDeclaration(), selection).
				findScope(selection.getOffset(), selection.getLength());
		scope.setCursor(selection.getOffset());
		String name= scope.createName(varName, false);
		decl.setName(ast.newSimpleName(name));

		List<ITypeBinding> mustRethrowList= new ArrayList<>();
		List<ITypeBinding> catchExceptions= analyzer.calculateCatchesAndRethrows(ASTNodes.filterSubtypes(allExceptions), mustRethrowList);
		List<ITypeBinding> filteredExceptions= ASTNodes.filterSubtypes(catchExceptions);

		if (catchExceptions.size() > 0) {
			final String GROUP_EXC_NAME= "exc_name"; //$NON-NLS-1$
			final String GROUP_EXC_TYPE= "exc_type"; //$NON-NLS-1$
			LinkedProposalModel linkedProposalModel= new LinkedProposalModel();

			int i= 0;
			for (ITypeBinding mustThrow : mustRethrowList) {
				CatchClause newClause= ast.newCatchClause();
				SingleVariableDeclaration newDecl= ast.newSingleVariableDeclaration();
				newDecl.setName(ast.newSimpleName(name));
				Type importType= imports.addImport(mustThrow, ast, importRewriteContext, TypeLocation.EXCEPTION);
				newDecl.setType(importType);
				newClause.setException(newDecl);
				ThrowStatement newThrowStatement= ast.newThrowStatement();
				newThrowStatement.setExpression(ast.newSimpleName(name));
				linkedProposalModel.getPositionGroup(GROUP_EXC_NAME + i, true).addPosition(rewrite.track(decl.getName()), false);
				newClause.getBody().statements().add(newThrowStatement);
				newTryStatement.catchClauses().add(newClause);
				++i;
			}
			UnionType unionType= ast.newUnionType();
			List<Type> types= unionType.types();
			for (ITypeBinding exception : filteredExceptions) {
				Type type= imports.addImport(exception, ast, importRewriteContext, TypeLocation.EXCEPTION);
				types.add(type);
				linkedProposalModel.getPositionGroup(GROUP_EXC_TYPE + i, true).addPosition(rewrite.track(type), i == 0);
				i++;
			}

			decl.setType(unionType);
			catchClause.setException(decl);
			linkedProposalModel.getPositionGroup(GROUP_EXC_NAME + 0, true).addPosition(rewrite.track(decl.getName()), false);
			Statement st= null;
			String s= StubUtility.getCatchBodyContent(icu, "Exception", name, coveredNodes.get(0), icu.findRecommendedLineSeparator()); //$NON-NLS-1$
			if (s != null) {
				st= (Statement)rewrite.createStringPlaceholder(s, ASTNode.RETURN_STATEMENT);
			}
			if (st != null) {
				catchClause.getBody().statements().add(st);
			}
			newTryStatement.catchClauses().add(catchClause);
		}

		if (!nodesInRange.isEmpty()) {
			ASTNode firstNode= nodesInRange.get(0);
			ASTNode methodDeclaration= ASTResolving.findAncestor(firstNode, ASTNode.BLOCK);
			ListRewrite listRewrite= rewrite.getListRewrite(methodDeclaration, Block.STATEMENTS_PROPERTY);
			ASTNode createCopyTarget= listRewrite.createMoveTarget(firstNode, nodesInRange.get(nodesInRange.size() - 1));
			rewrite.getListRewrite(newTryBody, Block.STATEMENTS_PROPERTY).insertFirst(createCopyTarget, null);
		}

		// replace first node and delete the rest of selected nodes
		rewrite.replace(coveredAutoClosableNodes.get(0), newTryStatement, null);
		for (int i= 1; i < coveredAutoClosableNodes.size(); i++) {
			rewrite.remove(coveredAutoClosableNodes.get(i), null);
		}

		resultingCollections.add(proposal);
		return true;
	}

	private static int findEndPostion(ASTNode node) {
		int end= node.getStartPosition() + node.getLength();
		Map<SimpleName, IVariableBinding> nodeSimpleNameBindings= getVariableStatementBinding(node);
		List<SimpleName> nodeNames= new ArrayList<>(nodeSimpleNameBindings.keySet());
		if (nodeNames.isEmpty()) {
			return -1;
		}
		SimpleName nodeSimpleName= nodeNames.get(0);
		SimpleName[] coveredNodeBindings= LinkedNodeFinder.findByNode(node.getRoot(), nodeSimpleName);
		if (coveredNodeBindings.length == 0) {
			return -1;
		}
		for (ASTNode astNode : coveredNodeBindings) {
			end= Math.max(end, (astNode.getStartPosition() + astNode.getLength()));
		}
		return end;
	}

	/**
	 * Return the first auto closable nodes. When a node that isn't Autoclosable is found the method
	 * returns.
	 *
	 * @param astNodes The nodes covered.
	 * @return List of the first AutoClosable nodes found
	 */
	private static List<ASTNode> getCoveredAutoClosableNodes(List<ASTNode> astNodes) {
		List<ASTNode> autoClosableNodes= new ArrayList<>();
		for (ASTNode astNode : astNodes) {
			if (isAutoClosable(astNode)) {
				autoClosableNodes.add(astNode);
			} else {
				return autoClosableNodes;
			}
		}
		return autoClosableNodes;
	}

	private static boolean isAutoClosable(ASTNode astNode) {
		Map<SimpleName, IVariableBinding> simpleNames= getVariableStatementBinding(astNode);
		for (Entry<SimpleName, IVariableBinding> entry : simpleNames.entrySet()) {
			ITypeBinding typeBinding= null;
			switch (entry.getKey().getParent().getNodeType()) {
				case ASTNode.VARIABLE_DECLARATION_FRAGMENT:
				case ASTNode.VARIABLE_DECLARATION_STATEMENT:
				case ASTNode.ASSIGNMENT:
					typeBinding= entry.getValue().getType();
					break;
				default:
					continue;
			}
			if (typeBinding != null && isAutoClosable(typeBinding)) {
				return true;
			}
		}
		return false;
	}

	private static boolean isAutoClosable(ITypeBinding typeBinding) {
		return Bindings.findTypeInHierarchy(typeBinding, "java.lang.AutoCloseable") != null; //$NON-NLS-1$
	}

	private static Map<SimpleName, IVariableBinding> getVariableStatementBinding(ASTNode astNode) {
		Map<SimpleName, IVariableBinding> variableBindings= new HashMap<>();
		astNode.accept(new ASTVisitor() {
			@Override
			public boolean visit(VariableDeclarationStatement node) {
				for (Object o : node.fragments()) {
					if (o instanceof VariableDeclarationFragment) {
						VariableDeclarationFragment vdf= (VariableDeclarationFragment) o;
						SimpleName name= vdf.getName();
						IBinding binding= name.resolveBinding();
						if (binding instanceof IVariableBinding) {
							variableBindings.put(name, (IVariableBinding) binding);
							break;
						}
					}
				}
				return false;
			}
		});
		return variableBindings;
	}

	private static boolean getAddBlockProposals(IInvocationContext context, ASTNode node, Collection<ICommandAccess> resultingCollections) {
		if (!(node instanceof Statement)) {
			return false;
		}

		/*
		 * only show the quick assist when the selection is of the control statement keywords (if, else, while,...)
		 * but not inside the statement or the if expression.
		 */
		if (!isControlStatementWithBlock(node) && isControlStatementWithBlock(node.getParent())) {
			int statementStart= node.getStartPosition();
			int statementEnd= statementStart + node.getLength();

			int offset= context.getSelectionOffset();
			int length= context.getSelectionLength();
			if (length == 0) {
				if (offset != statementEnd) { // cursor at end
					return false;
				}
			} else {
				if (offset > statementStart || offset + length < statementEnd) { // statement selected
					return false;
				}
			}
			node= node.getParent();
		}

		StructuralPropertyDescriptor childProperty= null;
		ASTNode child= null;
		switch (node.getNodeType()) {
			case ASTNode.IF_STATEMENT:
				ASTNode then= ((IfStatement) node).getThenStatement();
				ASTNode elseStatement= ((IfStatement) node).getElseStatement();
				if ((then instanceof Block) && (elseStatement instanceof Block || elseStatement == null)) {
					break;
				}
				int thenEnd= then.getStartPosition() + then.getLength();
				int selectionEnd= context.getSelectionOffset() + context.getSelectionLength();
				if (!(then instanceof Block)) {
					if (selectionEnd <= thenEnd) {
						childProperty= IfStatement.THEN_STATEMENT_PROPERTY;
						child= then;
						break;
					} else if (elseStatement != null && selectionEnd < elseStatement.getStartPosition()) {
						// find out if we are before or after the 'else' keyword
						try {
							TokenScanner scanner= new TokenScanner(context.getCompilationUnit());
							int elseTokenStart= scanner.getNextStartOffset(thenEnd, true);
							if (selectionEnd < elseTokenStart) {
								childProperty= IfStatement.THEN_STATEMENT_PROPERTY;
								child= then;
								break;
							}
						} catch (CoreException e) {
							// ignore
						}
					}
				}
				if (elseStatement != null && !(elseStatement instanceof Block) && context.getSelectionOffset() >= thenEnd) {
					childProperty= IfStatement.ELSE_STATEMENT_PROPERTY;
					child= elseStatement;
				}
				break;
			case ASTNode.WHILE_STATEMENT:
				ASTNode whileBody= ((WhileStatement) node).getBody();
				if (!(whileBody instanceof Block)) {
					childProperty= WhileStatement.BODY_PROPERTY;
					child= whileBody;
				}
				break;
			case ASTNode.FOR_STATEMENT:
				ASTNode forBody= ((ForStatement) node).getBody();
				if (!(forBody instanceof Block)) {
					childProperty= ForStatement.BODY_PROPERTY;
					child= forBody;
				}
				break;
			case ASTNode.ENHANCED_FOR_STATEMENT:
				ASTNode enhancedForBody= ((EnhancedForStatement) node).getBody();
				if (!(enhancedForBody instanceof Block)) {
					childProperty= EnhancedForStatement.BODY_PROPERTY;
					child= enhancedForBody;
				}
				break;
			case ASTNode.DO_STATEMENT:
				ASTNode doBody= ((DoStatement) node).getBody();
				if (!(doBody instanceof Block)) {
					childProperty= DoStatement.BODY_PROPERTY;
					child= doBody;
				}
				break;
			default:
		}
		if (child == null) {
			return false;
		}

		if (resultingCollections == null) {
			return true;
		}
		AST ast= node.getAST();
		{
			ASTRewrite rewrite= ASTRewrite.create(ast);

			ASTNode childPlaceholder= rewrite.createMoveTarget(child);
			Block replacingBody= ast.newBlock();
			replacingBody.statements().add(childPlaceholder);
			rewrite.set(node, childProperty, replacingBody, null);

			String label;
			if (childProperty == IfStatement.THEN_STATEMENT_PROPERTY) {
				label= CorrectionMessages.QuickAssistProcessor_replacethenwithblock_description;
			} else if (childProperty == IfStatement.ELSE_STATEMENT_PROPERTY) {
				label= CorrectionMessages.QuickAssistProcessor_replaceelsewithblock_description;
			} else {
				label= CorrectionMessages.QuickAssistProcessor_replacebodywithblock_description;
			}

			Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
			LinkedCorrectionProposal proposal= new LinkedCorrectionProposal(label, context.getCompilationUnit(), rewrite, IProposalRelevance.ADD_BLOCK, image);
			proposal.setCommandId(ADD_BLOCK_ID);
			proposal.setEndPosition(rewrite.track(child));
			resultingCollections.add(proposal);
		}

		if (node.getNodeType() == ASTNode.IF_STATEMENT) {
			ASTRewrite rewrite= ASTRewrite.create(ast);

			while (node.getLocationInParent() == IfStatement.ELSE_STATEMENT_PROPERTY) {
				node= node.getParent();
			}

			boolean missingBlockFound= false;
			boolean foundElse= false;

			IfStatement ifStatement;
			Statement thenStatment;
			Statement elseStatment;
			do {
				ifStatement= (IfStatement) node;
				thenStatment= ifStatement.getThenStatement();
				elseStatment= ifStatement.getElseStatement();

				if (!(thenStatment instanceof Block)) {
					ASTNode childPlaceholder1= rewrite.createMoveTarget(thenStatment);
					Block replacingBody1= ast.newBlock();
					replacingBody1.statements().add(childPlaceholder1);
					rewrite.set(ifStatement, IfStatement.THEN_STATEMENT_PROPERTY, replacingBody1, null);
					if (thenStatment != child) {
						missingBlockFound= true;
					}
				}
				if (elseStatment != null) {
					foundElse= true;
				}
				node= elseStatment;
			} while (elseStatment instanceof IfStatement);

			if (elseStatment != null && !(elseStatment instanceof Block)) {
				ASTNode childPlaceholder2= rewrite.createMoveTarget(elseStatment);

				Block replacingBody2= ast.newBlock();
				replacingBody2.statements().add(childPlaceholder2);
				rewrite.set(ifStatement, IfStatement.ELSE_STATEMENT_PROPERTY, replacingBody2, null);
				if (elseStatment != child) {
					missingBlockFound= true;
				}
			}

			if (missingBlockFound && foundElse) {
				String label= CorrectionMessages.QuickAssistProcessor_replacethenelsewithblock_description;
				Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
				ASTRewriteCorrectionProposal proposal= new ASTRewriteCorrectionProposal(label, context.getCompilationUnit(), rewrite, IProposalRelevance.CHANGE_IF_ELSE_TO_BLOCK, image);
				resultingCollections.add(proposal);
			}
		}
		return true;
	}

	private static boolean getInvertEqualsProposal(IInvocationContext context, ASTNode node, Collection<ICommandAccess> resultingCollections) {
		if (!(node instanceof MethodInvocation)) {
			node= node.getParent();
			if (!(node instanceof MethodInvocation)) {
				return false;
			}
		}
		MethodInvocation method= (MethodInvocation) node;
		String identifier= method.getName().getIdentifier();
		if (!"equals".equals(identifier) && !"equalsIgnoreCase".equals(identifier)) { //$NON-NLS-1$ //$NON-NLS-2$
			return false;
		}
		List<Expression> arguments= method.arguments();
		if (arguments.size() != 1) { //overloaded equals w/ more than 1 argument
			return false;
		}
		Expression right= arguments.get(0);
		ITypeBinding binding= right.resolveTypeBinding();
		if (binding != null
				&& !binding.isClass()
				&& !binding.isInterface()
				&& !binding.isEnum()) { //overloaded equals w/ non-class/interface argument or null
			return false;
		}
		if (resultingCollections == null) {
			return true;
		}

		Expression left= method.getExpression();

		AST ast= method.getAST();
		ASTRewrite rewrite= ASTRewrite.create(ast);
		if (left == null) { // equals(x) -> x.equals(this)
			MethodInvocation replacement= ast.newMethodInvocation();
			replacement.setName((SimpleName) rewrite.createCopyTarget(method.getName()));
			replacement.arguments().add(ast.newThisExpression());
			replacement.setExpression((Expression) rewrite.createCopyTarget(right));
			rewrite.replace(method, replacement, null);
		} else if (right instanceof ThisExpression) { // x.equals(this) -> equals(x)
			MethodInvocation replacement= ast.newMethodInvocation();
			replacement.setName((SimpleName) rewrite.createCopyTarget(method.getName()));
			replacement.arguments().add(rewrite.createCopyTarget(left));
			rewrite.replace(method, replacement, null);
		} else {
			ASTNode leftExpression= ASTNodes.getUnparenthesedExpression(left);
			rewrite.replace(right, rewrite.createCopyTarget(leftExpression), null);

			if (right instanceof CastExpression
					|| right instanceof Assignment
					|| right instanceof ConditionalExpression
					|| right instanceof InfixExpression) {
				ParenthesizedExpression paren= ast.newParenthesizedExpression();
				paren.setExpression((Expression) rewrite.createCopyTarget(right));
				rewrite.replace(left, paren, null);
			} else {
				rewrite.replace(left, rewrite.createCopyTarget(right), null);
			}
		}

		String label= CorrectionMessages.QuickAssistProcessor_invertequals_description;
		Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);

		LinkedCorrectionProposal proposal= new LinkedCorrectionProposal(label, context.getCompilationUnit(), rewrite, IProposalRelevance.INVERT_EQUALS, image);
		resultingCollections.add(proposal);
		return true;
	}

	private static boolean getArrayInitializerToArrayCreation(IInvocationContext context, ASTNode node, Collection<ICommandAccess> resultingCollections) {
		if (!(node instanceof ArrayInitializer)) {
			return false;
		}
		ArrayInitializer initializer= (ArrayInitializer) node;

		ASTNode parent= initializer.getParent();
		while (parent instanceof ArrayInitializer) {
			initializer= (ArrayInitializer) parent;
			parent= parent.getParent();
		}
		ITypeBinding typeBinding= initializer.resolveTypeBinding();
		if (!(parent instanceof VariableDeclaration) || typeBinding == null || !typeBinding.isArray()) {
			return false;
		}
		if (resultingCollections == null) {
			return true;
		}

		AST ast= node.getAST();
		ASTRewrite rewrite= ASTRewrite.create(ast);

		String label= CorrectionMessages.QuickAssistProcessor_typetoarrayInitializer_description;
		Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);

		LinkedCorrectionProposal proposal= new LinkedCorrectionProposal(label, context.getCompilationUnit(), rewrite, IProposalRelevance.ADD_TYPE_TO_ARRAY_INITIALIZER, image);

		ImportRewrite imports= proposal.createImportRewrite(context.getASTRoot());
		ImportRewriteContext importRewriteContext= new ContextSensitiveImportRewriteContext(node, imports);
		String typeName= imports.addImport(typeBinding, importRewriteContext);

		ArrayCreation creation= ast.newArrayCreation();
		creation.setInitializer((ArrayInitializer) rewrite.createMoveTarget(initializer));
		creation.setType((ArrayType) ASTNodeFactory.newType(ast, typeName));

		rewrite.replace(initializer, creation, null);

		resultingCollections.add(proposal);
		return true;
	}


	public static boolean getCreateInSuperClassProposals(IInvocationContext context, ASTNode node, Collection<ICommandAccess> resultingCollections) throws CoreException {
		if (!(node instanceof SimpleName) || !(node.getParent() instanceof MethodDeclaration)) {
			return false;
		}
		MethodDeclaration decl= (MethodDeclaration) node.getParent();
		if (decl.getName() != node || decl.resolveBinding() == null || Modifier.isPrivate(decl.getModifiers())) {
			return false;
		}

		ICompilationUnit cu= context.getCompilationUnit();
		CompilationUnit astRoot= context.getASTRoot();

		IMethodBinding binding= decl.resolveBinding();
		ITypeBinding[] paramTypes= binding.getParameterTypes();

		ITypeBinding[] superTypes= Bindings.getAllSuperTypes(binding.getDeclaringClass());
		if (resultingCollections == null) {
			for (ITypeBinding curr : superTypes) {
				if (curr.isFromSource() && Bindings.findOverriddenMethodInType(curr, binding) == null) {
					return true;
				}
			}
			return false;
		}
		List<SingleVariableDeclaration> params= decl.parameters();
		String[] paramNames= new String[paramTypes.length];
		for (int i= 0; i < params.size(); i++) {
			SingleVariableDeclaration param= params.get(i);
			paramNames[i]= param.getName().getIdentifier();
		}

		for (ITypeBinding curr : superTypes) {
			if (curr.isFromSource()) {
				IMethodBinding method= Bindings.findOverriddenMethodInType(curr, binding);
				if (method == null) {
					ITypeBinding typeDecl= curr.getTypeDeclaration();
					ICompilationUnit targetCU= ASTResolving.findCompilationUnitForBinding(cu, astRoot, typeDecl);
					if (targetCU != null) {
						String label= Messages.format(CorrectionMessages.QuickAssistProcessor_createmethodinsuper_description,
								new String[] { BasicElementLabels.getJavaElementName(curr.getName()), BasicElementLabels.getJavaElementName(binding.getName()) });
						resultingCollections.add(new NewDefiningMethodProposal(label, targetCU, astRoot, typeDecl, binding, paramNames, IProposalRelevance.CREATE_METHOD_IN_SUPER));
					}
				}
			}
		}
		return true;
	}

	private static boolean getConvertEnhancedForLoopProposal(IInvocationContext context, ASTNode node, Collection<ICommandAccess> resultingCollections) {
		EnhancedForStatement enhancedForStatement= getEnclosingHeader(node, EnhancedForStatement.class, EnhancedForStatement.PARAMETER_PROPERTY, EnhancedForStatement.EXPRESSION_PROPERTY);
		if (enhancedForStatement == null) {
			return false;
		}
		SingleVariableDeclaration parameter= enhancedForStatement.getParameter();
		IVariableBinding parameterBinding= parameter.resolveBinding();
		if (parameterBinding == null) {
			return false;
		}
		Expression initializer= enhancedForStatement.getExpression();
		ITypeBinding initializerTypeBinding= initializer.resolveTypeBinding();
		if (initializerTypeBinding == null) {
			return false;
		}

		if (resultingCollections == null) {
			return true;
		}

		Statement topLabelStatement= enhancedForStatement;
		while (topLabelStatement.getLocationInParent() == LabeledStatement.BODY_PROPERTY) {
			topLabelStatement= (Statement) topLabelStatement.getParent();
		}

		IJavaProject project= context.getCompilationUnit().getJavaProject();
		AST ast= node.getAST();
		Statement enhancedForBody= enhancedForStatement.getBody();
		Collection<String> usedVarNames= Arrays.asList(ASTResolving.getUsedVariableNames(enhancedForBody));

		boolean initializerIsArray= initializerTypeBinding.isArray();
		ITypeBinding initializerListType= Bindings.findTypeInHierarchy(initializerTypeBinding, "java.util.List"); //$NON-NLS-1$
		ITypeBinding initializerIterableType= Bindings.findTypeInHierarchy(initializerTypeBinding, "java.lang.Iterable"); //$NON-NLS-1$

		if (initializerIterableType != null) {
			String label= CorrectionMessages.QuickAssistProcessor_convert_to_iterator_for_loop;
			Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);

			String iterNameKey= "iterName"; //$NON-NLS-1$
			ASTRewrite rewrite= ASTRewrite.create(ast);
			LinkedCorrectionProposal proposal= new LinkedCorrectionProposal(label, context.getCompilationUnit(), rewrite, IProposalRelevance.CONVERT_TO_ITERATOR_FOR_LOOP, image);

			// convert 'for' statement
			ForStatement forStatement= ast.newForStatement();

			// create initializer
			MethodInvocation iterInitializer= ast.newMethodInvocation();
			iterInitializer.setName(ast.newSimpleName("iterator")); //$NON-NLS-1$
			ImportRewrite imports= proposal.createImportRewrite(context.getASTRoot());
			ImportRewriteContext importRewriteContext= new ContextSensitiveImportRewriteContext(node, imports);
			Type iterType= ast.newSimpleType(ast.newName(imports.addImport("java.util.Iterator", importRewriteContext))); //$NON-NLS-1$
			if (initializerIterableType.getTypeArguments().length == 1) {
				Type iterTypeArgument= imports.addImport(Bindings.normalizeTypeBinding(initializerIterableType.getTypeArguments()[0]), ast, importRewriteContext, TypeLocation.TYPE_ARGUMENT);
				ParameterizedType parameterizedIterType= ast.newParameterizedType(iterType);
				parameterizedIterType.typeArguments().add(iterTypeArgument);
				iterType= parameterizedIterType;
			}
			String[] iterNames= StubUtility.getVariableNameSuggestions(NamingConventions.VK_LOCAL, project, iterType, iterInitializer, usedVarNames);
			String iterName= iterNames[0];
			SimpleName initializerIterName= ast.newSimpleName(iterName);

			VariableDeclarationFragment iterFragment= ast.newVariableDeclarationFragment();
			iterFragment.setName(initializerIterName);
			proposal.addLinkedPosition(rewrite.track(initializerIterName), 0, iterNameKey);
			for (String name : iterNames) {
				proposal.addLinkedPositionProposal(iterNameKey, name, null);
			}

			Expression initializerExpression= (Expression) rewrite.createCopyTarget(initializer);
			iterInitializer.setExpression(initializerExpression);
			iterFragment.setInitializer(iterInitializer);

			VariableDeclarationExpression iterVariable= ast.newVariableDeclarationExpression(iterFragment);
			iterVariable.setType(iterType);
			forStatement.initializers().add(iterVariable);

			// create condition
			MethodInvocation condition= ast.newMethodInvocation();
			condition.setName(ast.newSimpleName("hasNext")); //$NON-NLS-1$
			SimpleName conditionExpression= ast.newSimpleName(iterName);
			proposal.addLinkedPosition(rewrite.track(conditionExpression), LinkedPositionGroup.NO_STOP, iterNameKey);
			condition.setExpression(conditionExpression);
			forStatement.setExpression(condition);

			// create 'for' body element variable
			VariableDeclarationFragment elementFragment= ast.newVariableDeclarationFragment();
			elementFragment.extraDimensions().addAll(DimensionRewrite.copyDimensions(parameter.extraDimensions(), rewrite));
			elementFragment.setName((SimpleName) rewrite.createCopyTarget(parameter.getName()));

			SimpleName elementIterName= ast.newSimpleName(iterName);
			proposal.addLinkedPosition(rewrite.track(elementIterName), LinkedPositionGroup.NO_STOP, iterNameKey);

			MethodInvocation getMethodInvocation= ast.newMethodInvocation();
			getMethodInvocation.setName(ast.newSimpleName("next")); //$NON-NLS-1$
			getMethodInvocation.setExpression(elementIterName);
			elementFragment.setInitializer(getMethodInvocation);

			VariableDeclarationStatement elementVariable= ast.newVariableDeclarationStatement(elementFragment);
			ModifierRewrite.create(rewrite, elementVariable).copyAllModifiers(parameter, null);
			elementVariable.setType((Type) rewrite.createCopyTarget(parameter.getType()));

			Block newBody= ast.newBlock();
			List<Statement> statements= newBody.statements();
			statements.add(elementVariable);
			if (enhancedForBody instanceof Block) {
				List<Statement> oldStatements= ((Block) enhancedForBody).statements();
				if (oldStatements.size() > 0) {
					ListRewrite statementsRewrite= rewrite.getListRewrite(enhancedForBody, Block.STATEMENTS_PROPERTY);
					Statement oldStatementsCopy= (Statement) statementsRewrite.createCopyTarget(oldStatements.get(0), oldStatements.get(oldStatements.size() - 1));
					statements.add(oldStatementsCopy);
				}
			} else {
				statements.add((Statement) rewrite.createCopyTarget(enhancedForBody));
			}

			forStatement.setBody(newBody);
			rewrite.replace(enhancedForStatement, forStatement, null);

			resultingCollections.add(proposal);
		}

		if (initializerIsArray || initializerListType != null) {
			String label= CorrectionMessages.QuickAssistProcessor_convert_to_indexed_for_loop;
			Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);

			String varNameKey= "varName"; //$NON-NLS-1$
			String indexNameKey= "indexName"; //$NON-NLS-1$
			ASTRewrite rewrite= ASTRewrite.create(ast);
			LinkedCorrectionProposal proposal= new LinkedCorrectionProposal(label, context.getCompilationUnit(), rewrite, IProposalRelevance.CONVERT_TO_INDEXED_FOR_LOOP, image);

			// create temp variable from initializer if necessary
			String varName;
			boolean varNameGenerated;
			if (initializer instanceof SimpleName) {
				varName= ((SimpleName) initializer).getIdentifier();
				varNameGenerated= false;
			} else {
				VariableDeclarationFragment varFragment= ast.newVariableDeclarationFragment();
				String[] varNames= StubUtility.getVariableNameSuggestions(NamingConventions.VK_LOCAL, project, initializerTypeBinding, initializer, usedVarNames);
				varName= varNames[0];
				usedVarNames= new ArrayList<>(usedVarNames);
				usedVarNames.add(varName);
				varNameGenerated= true;
				SimpleName varNameNode= ast.newSimpleName(varName);
				varFragment.setName(varNameNode);
				proposal.addLinkedPosition(rewrite.track(varNameNode), 0, varNameKey);
				for (String name : varNames) {
					proposal.addLinkedPositionProposal(varNameKey, name, null);
				}

				varFragment.setInitializer((Expression) rewrite.createCopyTarget(initializer));

				VariableDeclarationStatement varDeclaration= ast.newVariableDeclarationStatement(varFragment);
				Type varType;
				if (initializerIsArray) {
					Type copiedType= DimensionRewrite.copyTypeAndAddDimensions(parameter.getType(), parameter.extraDimensions(), rewrite);
					varType= ASTNodeFactory.newArrayType(copiedType);
				} else {
					ImportRewrite imports= proposal.createImportRewrite(context.getASTRoot());
					ImportRewriteContext importRewriteContext= new ContextSensitiveImportRewriteContext(node, imports);
					varType= imports.addImport(Bindings.normalizeForDeclarationUse(initializerTypeBinding, ast), ast, importRewriteContext, TypeLocation.TYPE_ARGUMENT);
				}
				varDeclaration.setType(varType);

				if (!(topLabelStatement.getParent() instanceof Block)) {
					Block block= ast.newBlock();
					List<Statement> statements= block.statements();
					statements.add(varDeclaration);
					statements.add((Statement) rewrite.createCopyTarget(topLabelStatement));
					rewrite.replace(topLabelStatement, block, null);
				} else {
					rewrite.getListRewrite(topLabelStatement.getParent(), Block.STATEMENTS_PROPERTY).insertBefore(varDeclaration, topLabelStatement, null);
				}
			}

			// convert 'for' statement
			ForStatement forStatement= ast.newForStatement();

			// create initializer
			VariableDeclarationFragment indexFragment= ast.newVariableDeclarationFragment();
			NumberLiteral indexInitializer= ast.newNumberLiteral();
			indexFragment.setInitializer(indexInitializer);
			PrimitiveType indexType= ast.newPrimitiveType(PrimitiveType.INT);
			String[] indexNames= StubUtility.getVariableNameSuggestions(NamingConventions.VK_LOCAL, project, indexType, indexInitializer, usedVarNames);
			String indexName= indexNames[0];
			SimpleName initializerIndexName= ast.newSimpleName(indexName);
			indexFragment.setName(initializerIndexName);
			proposal.addLinkedPosition(rewrite.track(initializerIndexName), 0, indexNameKey);
			for (String name : indexNames) {
				proposal.addLinkedPositionProposal(indexNameKey, name, null);
			}
			VariableDeclarationExpression indexVariable= ast.newVariableDeclarationExpression(indexFragment);
			indexVariable.setType(indexType);
			forStatement.initializers().add(indexVariable);

			// create condition
			InfixExpression condition= ast.newInfixExpression();
			condition.setOperator(InfixExpression.Operator.LESS);
			SimpleName conditionLeft= ast.newSimpleName(indexName);
			proposal.addLinkedPosition(rewrite.track(conditionLeft), LinkedPositionGroup.NO_STOP, indexNameKey);
			condition.setLeftOperand(conditionLeft);
			SimpleName conditionRightName= ast.newSimpleName(varName);
			if (varNameGenerated) {
				proposal.addLinkedPosition(rewrite.track(conditionRightName), LinkedPositionGroup.NO_STOP, varNameKey);
			}
			Expression conditionRight;
			if (initializerIsArray) {
				conditionRight= ast.newQualifiedName(conditionRightName, ast.newSimpleName("length")); //$NON-NLS-1$
			} else {
				MethodInvocation sizeMethodInvocation= ast.newMethodInvocation();
				sizeMethodInvocation.setName(ast.newSimpleName("size")); //$NON-NLS-1$
				sizeMethodInvocation.setExpression(conditionRightName);
				conditionRight= sizeMethodInvocation;
			}
			condition.setRightOperand(conditionRight);
			forStatement.setExpression(condition);

			// create updater
			SimpleName indexUpdaterName= ast.newSimpleName(indexName);
			proposal.addLinkedPosition(rewrite.track(indexUpdaterName), LinkedPositionGroup.NO_STOP, indexNameKey);
			PostfixExpression indexUpdater= ast.newPostfixExpression();
			indexUpdater.setOperator(PostfixExpression.Operator.INCREMENT);
			indexUpdater.setOperand(indexUpdaterName);
			forStatement.updaters().add(indexUpdater);

			// create 'for' body element variable
			VariableDeclarationFragment elementFragment= ast.newVariableDeclarationFragment();
			elementFragment.extraDimensions().addAll(DimensionRewrite.copyDimensions(parameter.extraDimensions(), rewrite));
			elementFragment.setName((SimpleName) rewrite.createCopyTarget(parameter.getName()));

			SimpleName elementVarName= ast.newSimpleName(varName);
			if (varNameGenerated) {
				proposal.addLinkedPosition(rewrite.track(elementVarName), LinkedPositionGroup.NO_STOP, varNameKey);
			}
			SimpleName elementIndexName= ast.newSimpleName(indexName);
			proposal.addLinkedPosition(rewrite.track(elementIndexName), LinkedPositionGroup.NO_STOP, indexNameKey);

			Expression elementAccess;
			if (initializerIsArray) {
				ArrayAccess elementArrayAccess= ast.newArrayAccess();
				elementArrayAccess.setArray(elementVarName);
				elementArrayAccess.setIndex(elementIndexName);
				elementAccess= elementArrayAccess;
			} else {
				MethodInvocation getMethodInvocation= ast.newMethodInvocation();
				getMethodInvocation.setName(ast.newSimpleName("get")); //$NON-NLS-1$
				getMethodInvocation.setExpression(elementVarName);
				getMethodInvocation.arguments().add(elementIndexName);
				elementAccess= getMethodInvocation;
			}
			elementFragment.setInitializer(elementAccess);

			VariableDeclarationStatement elementVariable= ast.newVariableDeclarationStatement(elementFragment);
			ModifierRewrite.create(rewrite, elementVariable).copyAllModifiers(parameter, null);
			elementVariable.setType((Type) rewrite.createCopyTarget(parameter.getType()));

			Block newBody= ast.newBlock();
			List<Statement> statements= newBody.statements();
			statements.add(elementVariable);
			if (enhancedForBody instanceof Block) {
				List<Statement> oldStatements= ((Block) enhancedForBody).statements();
				if (oldStatements.size() > 0) {
					ListRewrite statementsRewrite= rewrite.getListRewrite(enhancedForBody, Block.STATEMENTS_PROPERTY);
					Statement oldStatementsCopy= (Statement) statementsRewrite.createCopyTarget(oldStatements.get(0), oldStatements.get(oldStatements.size() - 1));
					statements.add(oldStatementsCopy);
				}
			} else {
				statements.add((Statement) rewrite.createCopyTarget(enhancedForBody));
			}

			forStatement.setBody(newBody);
			rewrite.replace(enhancedForStatement, forStatement, null);

			resultingCollections.add(proposal);
		}

		return true;
	}

	private static boolean getUnnecessaryArrayCreationProposal(IInvocationContext context, ASTNode node, Collection<ICommandAccess> resultingCollections) {
		Expression methodInvocation= null;
		if (node instanceof MethodInvocation || node instanceof SuperMethodInvocation) {
			methodInvocation= (Expression) node;
		} else if (node.getParent() instanceof MethodInvocation || node.getParent() instanceof SuperMethodInvocation) {
			methodInvocation= (Expression) node.getParent();
		} else {
			ASTNode n= node;
			while (n != null && !(n instanceof CompilationUnit)) {
				if (n instanceof ArrayCreation) {
					ASTNode parent= n.getParent();
					if (parent instanceof MethodInvocation || parent instanceof SuperMethodInvocation) {
						methodInvocation= (Expression) parent;
						break;
					}
				}
				n= n.getParent();
			}
		}
		if (methodInvocation == null)
			return false;

		if (resultingCollections == null)
			return true;

		IProposableFix fix= UnnecessaryArrayCreationFix.createUnnecessaryArrayCreationFix(context.getASTRoot(), methodInvocation);
		if (fix == null)
			return false;

		Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
		Map<String, String> options= new HashMap<>();
		options.put(CleanUpConstants.REMOVE_UNNECESSARY_ARRAY_CREATION, CleanUpOptions.TRUE);
		ICleanUp cleanUp= new UnnecessaryArrayCreationCleanUp(options);
		FixCorrectionProposal proposal= new FixCorrectionProposal(fix, cleanUp, IProposalRelevance.REMOVE_UNNECESSARY_ARRAY_CREATION, image, context);
		proposal.setCommandId(REMOVE_UNNECESSARY_ARRAY_CREATION_ID);

		resultingCollections.add(proposal);
		return true;
	}

	private static boolean getConvertForLoopProposal(IInvocationContext context, ASTNode node, Collection<ICommandAccess> resultingCollections) {
		ForStatement forStatement= getEnclosingForStatementHeader(node);
		if (forStatement == null)
			return false;

		if (resultingCollections == null)
			return true;

		IProposableFix fix= ConvertLoopFix.createConvertForLoopToEnhancedFix(context.getASTRoot(), forStatement);
		if (fix == null)
			return false;

		Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
		Map<String, String> options= new HashMap<>();
		options.put(CleanUpConstants.CONTROL_STATEMENTS_CONVERT_FOR_LOOP_TO_ENHANCED, CleanUpOptions.TRUE);
		ICleanUp cleanUp= new ConvertLoopCleanUp(options);
		FixCorrectionProposal proposal= new FixCorrectionProposal(fix, cleanUp, IProposalRelevance.CONVERT_FOR_LOOP_TO_ENHANCED, image, context);
		proposal.setCommandId(CONVERT_FOR_LOOP_ID);

		resultingCollections.add(proposal);
		return true;
	}

	private static boolean getConvertIterableLoopProposal(IInvocationContext context, ASTNode node, Collection<ICommandAccess> resultingCollections) {
		ForStatement forStatement= getEnclosingForStatementHeader(node);
		if (forStatement == null)
			return false;

		if (resultingCollections == null)
			return true;

		IProposableFix fix= ConvertLoopFix.createConvertIterableLoopToEnhancedFix(context.getASTRoot(), forStatement);
		if (fix == null)
			return false;

		Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
		Map<String, String> options= new HashMap<>();
		options.put(CleanUpConstants.CONTROL_STATEMENTS_CONVERT_FOR_LOOP_TO_ENHANCED, CleanUpOptions.TRUE);
		ICleanUp cleanUp= new ConvertLoopCleanUp(options);
		FixCorrectionProposal proposal= new FixCorrectionProposal(fix, cleanUp, IProposalRelevance.CONVERT_ITERABLE_LOOP_TO_ENHANCED, image, context);
		proposal.setCommandId(CONVERT_FOR_LOOP_ID);

		resultingCollections.add(proposal);
		return true;
	}

	public static boolean getGenerateForLoopProposals(IInvocationContext context, ASTNode coveringNode, IProblemLocation[] locations, Collection<ICommandAccess> resultingCollections) {
//		if (containsMatchingProblem(locations, IProblem.ParsingErrorInsertToComplete))
//			return false;

		Statement statement= ASTResolving.findParentStatement(coveringNode);
		if (!(statement instanceof ExpressionStatement)) {
			return false;
		}

		ExpressionStatement expressionStatement= (ExpressionStatement) statement;
		Expression expression= expressionStatement.getExpression();
		if (expression instanceof Assignment) {
			Assignment assignment= (Assignment) expression;
			Expression leftHandSide= assignment.getLeftHandSide();
			if (leftHandSide instanceof FieldAccess && leftHandSide.getStartPosition() == assignment.getStartPosition() && leftHandSide.getLength() == assignment.getLength()) {
				// "this.fieldname" recovered as "this.fieldname = $missing$"
				expression= leftHandSide;
			}
		}
		ITypeBinding expressionType= null;
		if (expression instanceof MethodInvocation
				|| expression instanceof SimpleName
				|| expression instanceof FieldAccess
				|| expression instanceof QualifiedName) {
			expressionType= expression.resolveTypeBinding();
		} else {
			return false;
		}

		if (expressionType == null)
			return false;

		ICompilationUnit cu= context.getCompilationUnit();
		if (Bindings.findTypeInHierarchy(expressionType, "java.lang.Iterable") != null) { //$NON-NLS-1$
			if (resultingCollections == null)
				return true;
			resultingCollections.add(new GenerateForLoopAssistProposal(cu, expressionStatement, GenerateForLoopAssistProposal.GENERATE_ITERATOR_FOR));
			if (Bindings.findTypeInHierarchy(expressionType, "java.util.List") != null) { //$NON-NLS-1$
				resultingCollections.add(new GenerateForLoopAssistProposal(cu, expressionStatement, GenerateForLoopAssistProposal.GENERATE_ITERATE_LIST));
			}
		} else if (expressionType.isArray()) {
			if (resultingCollections == null)
				return true;
			resultingCollections.add(new GenerateForLoopAssistProposal(cu, expressionStatement, GenerateForLoopAssistProposal.GENERATE_ITERATE_ARRAY));
		} else {
			return false;
		}

		if (JavaModelUtil.is50OrHigher(cu.getJavaProject())) {
			resultingCollections.add(new GenerateForLoopAssistProposal(cu, expressionStatement, GenerateForLoopAssistProposal.GENERATE_FOREACH));
		}

		return true;
	}

	private static ForStatement getEnclosingForStatementHeader(ASTNode node) {
		return getEnclosingHeader(node, ForStatement.class, ForStatement.INITIALIZERS_PROPERTY, ForStatement.EXPRESSION_PROPERTY, ForStatement.UPDATERS_PROPERTY);
	}

	private static <T extends ASTNode> T getEnclosingHeader(ASTNode node, Class<T> headerType, StructuralPropertyDescriptor... headerProperties) {
		if (headerType.isInstance(node))
			return headerType.cast(node);

		while (node != null) {
			ASTNode parent= node.getParent();
			if (headerType.isInstance(parent)) {
				StructuralPropertyDescriptor locationInParent= node.getLocationInParent();
				for (StructuralPropertyDescriptor property : headerProperties) {
					if (locationInParent == property)
						return headerType.cast(parent);
				}
				return null;
			}
			node= parent;
		}
		return null;
	}

	private static boolean getMakeVariableDeclarationFinalProposals(IInvocationContext context, Collection<ICommandAccess> resultingCollections) {
		SelectionAnalyzer analyzer= new SelectionAnalyzer(Selection.createFromStartLength(context.getSelectionOffset(), context.getSelectionLength()), false);
		context.getASTRoot().accept(analyzer);
		ASTNode[] selectedNodes= analyzer.getSelectedNodes();
		if (selectedNodes.length == 0)
			return false;

		IProposableFix fix= VariableDeclarationFix.createChangeModifierToFinalFix(context.getASTRoot(), selectedNodes);
		if (fix == null)
			return false;

		if (resultingCollections == null)
			return true;

		Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
		Map<String, String> options= new Hashtable<>();
		options.put(CleanUpConstants.VARIABLE_DECLARATIONS_USE_FINAL, CleanUpOptions.TRUE);
		options.put(CleanUpConstants.VARIABLE_DECLARATIONS_USE_FINAL_LOCAL_VARIABLES, CleanUpOptions.TRUE);
		options.put(CleanUpConstants.VARIABLE_DECLARATIONS_USE_FINAL_PARAMETERS, CleanUpOptions.TRUE);
		options.put(CleanUpConstants.VARIABLE_DECLARATIONS_USE_FINAL_PRIVATE_FIELDS, CleanUpOptions.TRUE);
		VariableDeclarationCleanUp cleanUp= new VariableDeclarationCleanUp(options);
		FixCorrectionProposal proposal= new FixCorrectionProposal(fix, cleanUp, IProposalRelevance.MAKE_VARIABLE_DECLARATION_FINAL, image, context);
		resultingCollections.add(proposal);
		return true;
	}

	private static boolean getInlineLocalProposal(IInvocationContext context, final ASTNode node, Collection<ICommandAccess> proposals) throws CoreException {
		if (!(node instanceof SimpleName))
			return false;

		SimpleName name= (SimpleName) node;
		IBinding binding= name.resolveBinding();
		if (!(binding instanceof IVariableBinding))
			return false;
		IVariableBinding varBinding= (IVariableBinding) binding;
		if (varBinding.isField() || varBinding.isParameter())
			return false;
		ASTNode decl= context.getASTRoot().findDeclaringNode(varBinding);
		if (!(decl instanceof VariableDeclarationFragment) || decl.getLocationInParent() != VariableDeclarationStatement.FRAGMENTS_PROPERTY)
			return false;

		if (proposals == null) {
			return true;
		}

		InlineTempRefactoring refactoring= new InlineTempRefactoring((VariableDeclaration) decl);
		if (refactoring.checkInitialConditions(new NullProgressMonitor()).isOK()) {
			refactoring.setCheckResultForCompileProblems(false);
			String label= CorrectionMessages.QuickAssistProcessor_inline_local_description;
			Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
			RefactoringCorrectionProposal proposal= new RefactoringCorrectionProposal(label, context.getCompilationUnit(), refactoring, IProposalRelevance.INLINE_LOCAL, image);
			proposal.setCommandId(INLINE_LOCAL_ID);
			proposals.add(proposal);

		}
		return true;
	}

	private static boolean getMissingCaseStatementProposals(IInvocationContext context, ASTNode node, Collection<ICommandAccess> proposals) {
		if (node instanceof SwitchCase) {
			node= node.getParent();
		}
		if (!(node instanceof SwitchStatement))
			return false;

		SwitchStatement switchStatement= (SwitchStatement) node;
		ITypeBinding expressionBinding= switchStatement.getExpression().resolveTypeBinding();
		if (expressionBinding == null || !expressionBinding.isEnum())
			return false;

		ArrayList<String> missingEnumCases= new ArrayList<>();
		boolean hasDefault= LocalCorrectionsSubProcessor.evaluateMissingSwitchCases(expressionBinding, switchStatement.statements(), missingEnumCases);
		if (missingEnumCases.isEmpty() && hasDefault)
			return false;

		if (proposals == null)
			return true;

		LocalCorrectionsSubProcessor.createMissingCaseProposals(context, switchStatement, missingEnumCases, proposals);
		return true;
	}

	private static boolean getConvertVarTypeToResolvedTypeProposal(IInvocationContext context, ASTNode node, Collection<ICommandAccess> proposals) {
		CompilationUnit astRoot= context.getASTRoot();
		boolean isValid= ASTNodes.isVarType(node, astRoot);
		if (!isValid) {
			return false;
		}

		if (!(node instanceof SimpleName)) {
			return false;
		}

		SimpleName name= (SimpleName) node;
		IBinding binding= name.resolveBinding();
		if (!(binding instanceof IVariableBinding)) {
			return false;
		}
		IVariableBinding varBinding= (IVariableBinding) binding;
		if (varBinding.isField() || varBinding.isParameter()) {
			return false;
		}

		ITypeBinding typeBinding= varBinding.getType();
		if (typeBinding == null || typeBinding.isAnonymous() || typeBinding.isIntersectionType() || typeBinding.isWildcardType()) {
			return false;
		}

		proposals.add(new TypeChangeCorrectionProposal(context.getCompilationUnit(), varBinding, astRoot, typeBinding, false, IProposalRelevance.CHANGE_TYPE_FROM_VAR));
		return true;
	}

	private static boolean getConvertResolvedTypeToVarTypeProposal(IInvocationContext context, ASTNode node, Collection<ICommandAccess> proposals) {
		CompilationUnit astRoot= context.getASTRoot();
		IJavaElement root= astRoot.getJavaElement();
		if (root == null) {
			return false;
		}
		IJavaProject javaProject= root.getJavaProject();
		if (javaProject == null) {
			return false;
		}
		if (!JavaModelUtil.is10OrHigher(javaProject)) {
			return false;
		}

		if (!(node instanceof SimpleName)) {
			return false;
		}
		SimpleName name= (SimpleName) node;
		IBinding binding= name.resolveBinding();
		if (!(binding instanceof IVariableBinding)) {
			return false;
		}
		IVariableBinding varBinding= (IVariableBinding) binding;
		if (varBinding.isField() || varBinding.isParameter()) {
			return false;
		}

		ASTNode varDeclaration= astRoot.findDeclaringNode(varBinding);
		if (varDeclaration == null) {
			return false;
		}

		Type type= null;
		Expression expression= null;

		ITypeBinding typeBinding= varBinding.getType();
		if (typeBinding == null) {
			return false;
		}
		ITypeBinding expressionTypeBinding= null;

		if (varDeclaration instanceof SingleVariableDeclaration) {
			SingleVariableDeclaration svDecl= (SingleVariableDeclaration) varDeclaration;
			type= svDecl.getType();
			expression= svDecl.getInitializer();
			if (expression != null) {
				expressionTypeBinding= expression.resolveTypeBinding();
			} else {
				ASTNode parent= svDecl.getParent();
				if (parent instanceof EnhancedForStatement) {
					EnhancedForStatement efStmt= (EnhancedForStatement) parent;
					expression= efStmt.getExpression();
					if (expression != null) {
						ITypeBinding expBinding= expression.resolveTypeBinding();
						if (expBinding != null) {
							if (expBinding.isArray()) {
								expressionTypeBinding= expBinding.getElementType();
							} else {
								ITypeBinding iterable= Bindings.findTypeInHierarchy(expBinding, "java.lang.Iterable"); //$NON-NLS-1$
								if (iterable != null) {
									ITypeBinding[] typeArguments= iterable.getTypeArguments();
									if (typeArguments.length == 1) {
										expressionTypeBinding= typeArguments[0];
										expressionTypeBinding= Bindings.normalizeForDeclarationUse(expressionTypeBinding, context.getASTRoot().getAST());
									}
								}
							}
						}
					}
				}
			}
		} else if (varDeclaration instanceof VariableDeclarationFragment) {
			ASTNode parent= varDeclaration.getParent();
			expression= ((VariableDeclarationFragment) varDeclaration).getInitializer();
			if (expression != null) {
				expressionTypeBinding= expression.resolveTypeBinding();
			}
			if (parent instanceof VariableDeclarationStatement) {
				type= ((VariableDeclarationStatement) parent).getType();
			} else if (parent instanceof VariableDeclarationExpression) {
				VariableDeclarationExpression varDecl= (VariableDeclarationExpression) parent;
				// cannot convert a VariableDeclarationExpression with multiple fragments to var.
				if (varDecl.fragments().size() > 1) {
					return false;
				}
				type= varDecl.getType();
			}
		}

		if (type == null || type.isVar()) {
			return false;
		}
		if (expression == null || expression instanceof ArrayInitializer || expression instanceof LambdaExpression || expression instanceof MethodReference) {
			return false;
		}
		if (expressionTypeBinding == null || !expressionTypeBinding.isEqualTo(typeBinding)) {
			return false;
		}

		proposals.add(new TypeChangeCorrectionProposal(context.getCompilationUnit(), varBinding, astRoot, typeBinding, IProposalRelevance.CHANGE_TYPE_TO_VAR));
		return true;
	}

	private static boolean getConvertLocalToFieldProposal(IInvocationContext context, final ASTNode node, Collection<ICommandAccess> proposals) throws CoreException {
		if (!(node instanceof SimpleName))
			return false;

		SimpleName name= (SimpleName) node;
		IBinding binding= name.resolveBinding();
		if (!(binding instanceof IVariableBinding))
			return false;
		IVariableBinding varBinding= (IVariableBinding) binding;
		if (varBinding.isField() || varBinding.isParameter())
			return false;
		ASTNode decl= context.getASTRoot().findDeclaringNode(varBinding);
		if (decl == null || decl.getLocationInParent() != VariableDeclarationStatement.FRAGMENTS_PROPERTY)
			return false;

		if (proposals == null) {
			return true;
		}

		PromoteTempToFieldRefactoring refactoring= new PromoteTempToFieldRefactoring((VariableDeclaration) decl);
		if (refactoring.checkInitialConditions(new NullProgressMonitor()).isOK()) {
			String label= CorrectionMessages.QuickAssistProcessor_convert_local_to_field_description;
			Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
			LinkedProposalModel linkedProposalModel= new LinkedProposalModel();
			refactoring.setLinkedProposalModel(linkedProposalModel);

			RefactoringCorrectionProposal proposal= new RefactoringCorrectionProposal(label, context.getCompilationUnit(), refactoring, IProposalRelevance.CONVERT_LOCAL_TO_FIELD, image);
			proposal.setLinkedProposalModel(linkedProposalModel);
			proposal.setCommandId(CONVERT_LOCAL_TO_FIELD_ID);
			proposals.add(proposal);
		}
		return true;
	}

	/**
	 * Create static import proposal
	 *
	 * @param context the invocation context
	 * @param node the node to work on
	 * @param proposals the receiver of proposals, may be {@code null}
	 * @return {@code true} if the operation could or has been performed, {@code false otherwise}
	 */
	private static boolean getAddStaticImportProposals(IInvocationContext context, ASTNode node, Collection<ICommandAccess> proposals) {
		if (!(node instanceof SimpleName)) {
			return false;
		}

		final SimpleName name= (SimpleName) node;
		final IBinding binding;
		final ITypeBinding declaringClass;

		// get bindings for method invocation or variable access

		if (name.getParent() instanceof MethodInvocation) {
			MethodInvocation mi= (MethodInvocation) name.getParent();

			Expression expression= mi.getExpression();
			if (expression == null || expression.equals(name)) {
				return false;
			}

			binding= mi.resolveMethodBinding();
			if (binding == null) {
				return false;
			}

			declaringClass= ((IMethodBinding) binding).getDeclaringClass();
		} else if (name.getParent() instanceof QualifiedName) {
			QualifiedName qn= (QualifiedName) name.getParent();

			if (name.equals(qn.getQualifier()) || qn.getParent() instanceof ImportDeclaration) {
				return false;
			}

			binding= qn.resolveBinding();
			if (!(binding instanceof IVariableBinding)) {
				return false;
			}
			declaringClass= ((IVariableBinding) binding).getDeclaringClass();
		} else {
			return false;
		}

		// at this point binding cannot be null

		if (!Modifier.isStatic(binding.getModifiers())) {
			// only work with static bindings
			return false;
		}

		boolean needImport= false;
		if (!isDirectlyAccessible(name, declaringClass)) {
			if (Modifier.isPrivate(declaringClass.getModifiers())) {
				return false;
			}
			needImport= true;
		}

		if (proposals == null) {
			return true; // return early, just testing if we could do it
		}

		Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);

		try {
			ImportRewrite importRewrite= StubUtility.createImportRewrite(context.getCompilationUnit(), true);
			ImportRewrite importRewriteReplaceAllOccurences= StubUtility.createImportRewrite(context.getCompilationUnit(), true);
			ASTRewrite astRewrite= ASTRewrite.create(node.getAST());
			ASTRewrite astRewriteReplaceAllOccurrences= ASTRewrite.create(node.getAST());

			int[] allReferencesToDeclaringClass= new int[1];
			allReferencesToDeclaringClass[0]= 0;
			int[] referencesFromOtherOccurences= new int[1];
			referencesFromOtherOccurences[0]= 0;
			MethodInvocation mi= null;
			QualifiedName qn= null;
			if (name.getParent() instanceof MethodInvocation) {
				mi= (MethodInvocation) name.getParent();
				// convert the method invocation
				astRewrite.remove(mi.getExpression(), null);
				mi.typeArguments().forEach(type -> astRewrite.remove((Type) type, null));
			} else if (name.getParent() instanceof QualifiedName) {
				qn= (QualifiedName) name.getParent();
				// convert the field access
				astRewrite.replace(qn, ASTNodeFactory.newName(node.getAST(), name.getFullyQualifiedName()), null);
			} else {
				return false;
			}

			MethodInvocation miFinal= mi;
			name.getRoot().accept(new ASTVisitor() {
				@Override
				public boolean visit(MethodInvocation methodInvocation) {
					Expression methodInvocationExpression= methodInvocation.getExpression();
					if (methodInvocationExpression == null) {
						return super.visit(methodInvocation);
					}

					if (methodInvocationExpression instanceof Name) {
						String fullyQualifiedName= ((Name) methodInvocationExpression).getFullyQualifiedName();
						if (miFinal != null &&
								miFinal.getExpression() instanceof Name && ((Name) miFinal.getExpression()).getFullyQualifiedName().equals(fullyQualifiedName)
								&& miFinal.getName().getIdentifier().equals(methodInvocation.getName().getIdentifier())) {
							methodInvocation.typeArguments().forEach(type -> astRewriteReplaceAllOccurrences.remove((Type) type, null));
							astRewriteReplaceAllOccurrences.remove(methodInvocationExpression, null);
							allReferencesToDeclaringClass[0]++;
						} else if (declaringClass.getName().equals(fullyQualifiedName)) {
							allReferencesToDeclaringClass[0]++;
							referencesFromOtherOccurences[0]++;
						}
					} else if (methodInvocationExpression instanceof ClassInstanceCreation) {
						ClassInstanceCreation classInstanceCreation= (ClassInstanceCreation) methodInvocationExpression;
						if (classInstanceCreation.getType() instanceof SimpleType) {
							String typeName= ((SimpleType) classInstanceCreation.getType()).getName().getFullyQualifiedName();
							if (typeName.equals(declaringClass.getName())) {
								allReferencesToDeclaringClass[0]++;
								referencesFromOtherOccurences[0]++;
							}
						}
					}

					return super.visit(methodInvocation);
				}
			});
			QualifiedName qnFinal= qn;
			name.getRoot().accept(new ASTVisitor() {
				@Override
				public boolean visit(QualifiedName qualifiedName) {
					if (qnFinal != null &&
							qualifiedName.getFullyQualifiedName().equals(qnFinal.getFullyQualifiedName())) {
						astRewriteReplaceAllOccurrences.replace(qualifiedName, ASTNodeFactory.newName(node.getAST(), name.getFullyQualifiedName()), null);
						allReferencesToDeclaringClass[0]++;
					} else if (declaringClass.getName().equals(qualifiedName.getQualifier().getFullyQualifiedName())) {
						allReferencesToDeclaringClass[0]++;
						referencesFromOtherOccurences[0]++;
					}
					return super.visit(qualifiedName);
				}
			});

			// add the static import
			if (needImport) {
				importRewrite.addStaticImport(binding);
				if (allReferencesToDeclaringClass[0] == 1) { // If there are exactly 1 visits, the import can be removed
					importRewrite.removeImport(declaringClass.getQualifiedName());
				}
				importRewriteReplaceAllOccurences.addStaticImport(binding);
				if (referencesFromOtherOccurences[0] == 0) {
					importRewriteReplaceAllOccurences.removeImport(declaringClass.getQualifiedName());
				}
			}

			ASTRewriteCorrectionProposal proposal= new ASTRewriteCorrectionProposal(CorrectionMessages.QuickAssistProcessor_convert_to_static_import, context.getCompilationUnit(), astRewrite,
					IProposalRelevance.ADD_STATIC_IMPORT, image);
			proposal.setImportRewrite(importRewrite);
			proposals.add(proposal);
			ASTRewriteCorrectionProposal proposalReplaceAllOccurrences= new ASTRewriteCorrectionProposal(CorrectionMessages.QuickAssistProcessor_convert_to_static_import_replace_all,
					context.getCompilationUnit(), astRewriteReplaceAllOccurrences,
					IProposalRelevance.ADD_STATIC_IMPORT, image);
			proposalReplaceAllOccurrences.setImportRewrite(importRewriteReplaceAllOccurences);
			proposals.add(proposalReplaceAllOccurrences);
		} catch (IllegalArgumentException e) {
			// Wrong use of ASTRewrite or ImportRewrite API, see bug 541586
			JavaPlugin.log(e);
			return false;
		} catch (JavaModelException e) {
			return false;
		}

		return true;
	}

	private static boolean isDirectlyAccessible(ASTNode nameNode, ITypeBinding declaringClass) {
		ASTNode node= nameNode.getParent();
		while (node != null) {

			if (node instanceof AbstractTypeDeclaration) {
				ITypeBinding binding= ((AbstractTypeDeclaration) node).resolveBinding();
				if (binding != null && binding.isSubTypeCompatible(declaringClass)) {
					return true;
				}
			} else if (node instanceof AnonymousClassDeclaration) {
				ITypeBinding binding= ((AnonymousClassDeclaration) node).resolveBinding();
				if (binding != null && binding.isSubTypeCompatible(declaringClass)) {
					return true;
				}
			}

			node= node.getParent();
		}
		return false;
	}

	private boolean getJUnitTestCaseProposal(IInvocationContext context, ASTNode coveringNode, ArrayList<ICommandAccess> resultingCollections) {
		if (coveringNode instanceof SimpleName && coveringNode.getParent() instanceof AbstractTypeDeclaration) {
			SimpleName name= (SimpleName) coveringNode;
			String idName= name.getIdentifier() + JavaModelUtil.DEFAULT_CU_SUFFIX;
			String unitName= context.getCompilationUnit().getElementName();
			if (unitName.equals(idName)) {
				if (resultingCollections != null) {
					Image image= JavaPlugin.getImageDescriptorRegistry().get(JavaPluginImages.DESC_OBJS_TEST_CASE);
					String label= Messages.format(CorrectionMessages.QuickAssistProcessor_create_new_junit_test_case, unitName);
					Change change= new NullChange(CorrectionMessages.QuickAssistProcessor_create_new_junit_test_case_desc);
					NewJUnitTestCaseProposal proposal= new NewJUnitTestCaseProposal(label, change, IProposalRelevance.CREATE_JUNIT_TEST_CASE, image, context.getASTRoot());
					resultingCollections.add(proposal);
				}
				return true;
			}
		}
		return false;
	}

	private boolean getNewImplementationProposal(IInvocationContext context, ASTNode coveringNode, ArrayList<ICommandAccess> resultingCollections) {
		if (coveringNode instanceof SimpleName && coveringNode.getParent() instanceof TypeDeclaration) {
			TypeDeclaration typeDecl= ((TypeDeclaration)coveringNode.getParent());
			boolean isInterface= typeDecl.isInterface();
			boolean isAbstract= Modifier.isAbstract(typeDecl.getModifiers());

			if (!isInterface && !isAbstract) {
				return false;
			}

			SimpleName name= (SimpleName) coveringNode;
			String idName= name.getIdentifier() + JavaModelUtil.DEFAULT_CU_SUFFIX;
			String unitName= context.getCompilationUnit().getElementName();
			if (unitName.equals(idName)) {
				if (resultingCollections != null) {
					Image image= JavaPlugin.getImageDescriptorRegistry().get(JavaPluginImages.DESC_TOOL_NEWCLASS);
					String label= Messages.format(CorrectionMessages.QuickAssistProcessor_create_new_impl, unitName);
					Change change= new NullChange(CorrectionMessages.QuickAssistProcessor_create_new_impl_desc);
					NewImplementationProposal proposal= new NewImplementationProposal(label, change, IProposalRelevance.CREATE_IMPLEMENTATION_FROM_INTERFACE, image, context.getCompilationUnit());
					resultingCollections.add(proposal);
				}
				return true;
			}
		}
		return false;
	}

	private boolean getSplitSwitchLabelProposal(IInvocationContext context, ASTNode coveringNode, Collection<ICommandAccess> proposals) {
		AST ast= coveringNode.getAST();
		// Only continue if AST has preview enabled and selected node, or its parent is a SwitchCase
		if (!ASTHelper.isSwitchCaseExpressionsSupportedInAST(ast) ||
				(!(coveringNode instanceof SwitchCase) && !(coveringNode.getParent() instanceof SwitchCase))) {
			return false;
		}

		SwitchCase scase= null;
		ASTNode parent= null;

		// If selected node not a SwitchCase, its parent must be a SwitchCase
		if (coveringNode instanceof SwitchCase) {
			scase= (SwitchCase) coveringNode;
			parent= coveringNode.getParent();
		} else {
			scase= (SwitchCase) coveringNode.getParent();
			parent= coveringNode.getParent().getParent();
		}

		if (proposals != null && scase.expressions().size() > 1) {
			ASTRewrite astRewrite= ASTRewrite.create(ast);
			ChildListPropertyDescriptor descriptor;
			List<Statement> statements;
			if (parent instanceof SwitchStatement) {
				descriptor= SwitchStatement.STATEMENTS_PROPERTY;
				statements= ((SwitchStatement) parent).statements();
			} else {
				descriptor= SwitchExpression.STATEMENTS_PROPERTY;
				statements= ((SwitchExpression) parent).statements();
			}
			ListRewrite listRewrite= astRewrite.getListRewrite(parent, descriptor);

			// Figure out the list index of the switch case in the statement list
			// We care about duplicating the statement(s) occuring immediately after it
			int statementIndex= 0;
			for (Statement s : statements) {
				if (scase.equals(s)) {
					break;
				}
				statementIndex++;
			}
			statementIndex++;

			// Switch Case Statement(s)
			List<Statement> caseStatements= new ArrayList<>();
			for (int i= statementIndex; i < statements.size(); i++) {
				Statement curr= statements.get(i);
				if (curr instanceof SwitchCase) {
					break;
				}
				caseStatements.add(curr);
			}

			for (int i= 0; i < scase.expressions().size(); i++) {
				Expression elem= (Expression) scase.expressions().get(i);
				// SwitchCase
				SwitchCase newSwitchCase= ast.newSwitchCase();
				Expression newExpr= (Expression) astRewrite.createCopyTarget(elem);
				newSwitchCase.setSwitchLabeledRule(scase.isSwitchLabeledRule());
				newSwitchCase.expressions().add(newExpr);

				// Preserve order from left -> right, top -> bottom
				listRewrite.insertBefore(newSwitchCase, scase, null);
				for (Statement statement : caseStatements) {
					listRewrite.insertBefore(astRewrite.createCopyTarget(statement), scase, null);
				}
			}

			listRewrite.remove(scase, null);
			for (Statement statement : caseStatements) {
				listRewrite.remove(statement, null);
			}

			String label= CorrectionMessages.QuickAssistProcessor_split_case_labels;
			Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
			proposals.add(new ASTRewriteCorrectionProposal(label, context.getCompilationUnit(), astRewrite, IProposalRelevance.ADD_MISSING_CASE_STATEMENTS, image));
		}

		return true;
	}
}
