/*******************************************************************************
 * Copyright (c) 2000, 2014 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Dmitry Stalnov (dstalnov@fusionone.com) - contributed fix for
 *       bug "inline method - doesn't handle implicit cast" (see
 *       https://bugs.eclipse.org/bugs/show_bug.cgi?id=24941).
 *     Dmitry Stalnov (dstalnov@fusionone.com) - contributed fix for
 *       bug Encapsulate field can fail when two variables in one variable declaration (see
 *       https://bugs.eclipse.org/bugs/show_bug.cgi?id=51540).
 *******************************************************************************/
package org.eclipse.jdt.internal.corext.dom;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.eclipse.core.runtime.Assert;

import org.eclipse.text.edits.TextEdit;

import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.Document;

import org.eclipse.jdt.core.Flags;
import org.eclipse.jdt.core.IBuffer;
import org.eclipse.jdt.core.IField;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IMember;
import org.eclipse.jdt.core.ISourceReference;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.ITypeRoot;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.compiler.IProblem;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
import org.eclipse.jdt.core.dom.Annotation;
import org.eclipse.jdt.core.dom.AnonymousClassDeclaration;
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.BodyDeclaration;
import org.eclipse.jdt.core.dom.CastExpression;
import org.eclipse.jdt.core.dom.CharacterLiteral;
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.ConstructorInvocation;
import org.eclipse.jdt.core.dom.DoStatement;
import org.eclipse.jdt.core.dom.EnhancedForStatement;
import org.eclipse.jdt.core.dom.EnumConstantDeclaration;
import org.eclipse.jdt.core.dom.Expression;
import org.eclipse.jdt.core.dom.FieldAccess;
import org.eclipse.jdt.core.dom.FieldDeclaration;
import org.eclipse.jdt.core.dom.ForStatement;
import org.eclipse.jdt.core.dom.IBinding;
import org.eclipse.jdt.core.dom.IExtendedModifier;
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.InfixExpression;
import org.eclipse.jdt.core.dom.LambdaExpression;
import org.eclipse.jdt.core.dom.MemberValuePair;
import org.eclipse.jdt.core.dom.Message;
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.Name;
import org.eclipse.jdt.core.dom.NameQualifiedType;
import org.eclipse.jdt.core.dom.NodeFinder;
import org.eclipse.jdt.core.dom.ParameterizedType;
import org.eclipse.jdt.core.dom.ParenthesizedExpression;
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.StringLiteral;
import org.eclipse.jdt.core.dom.StructuralPropertyDescriptor;
import org.eclipse.jdt.core.dom.SuperConstructorInvocation;
import org.eclipse.jdt.core.dom.SuperMethodInvocation;
import org.eclipse.jdt.core.dom.Type;
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.internal.corext.codemanipulation.StubUtility;
import org.eclipse.jdt.internal.corext.util.CodeFormatterUtil;
import org.eclipse.jdt.internal.corext.util.JDTUIHelperClasses;
import org.eclipse.jdt.internal.corext.util.Strings;

import org.eclipse.jdt.internal.ui.JavaPlugin;
import org.eclipse.jdt.internal.ui.javaeditor.ASTProvider;
import org.eclipse.jdt.internal.ui.preferences.MembersOrderPreferenceCache;
import org.eclipse.jdt.internal.ui.text.correction.ASTResolving;

/**
 * JDT-UI-internal helper methods that deal with {@link ASTNode}s:
 * <ul>
 * <li>additional operations on {@link ASTNode}s and subtypes</li>
 * <li>finding related nodes in an AST</li>
 * <li>some methods that deal with bindings (new such methods should go into {@link Bindings})</li>
 * </ul>
 * 
 * @see JDTUIHelperClasses
 */
public class ASTNodes {

	public static final int NODE_ONLY=				0;
	public static final int INCLUDE_FIRST_PARENT= 	1;
	public static final int INCLUDE_ALL_PARENTS= 	2;

	public static final int WARNING=				1 << 0;
	public static final int ERROR=					1 << 1;
	public static final int PROBLEMS=				WARNING | ERROR;

	private static final Message[] EMPTY_MESSAGES= new Message[0];
	private static final IProblem[] EMPTY_PROBLEMS= new IProblem[0];

	private static final int CLEAR_VISIBILITY= ~(Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE);


	private ASTNodes() {
		// no instance;
	}

	public static String asString(ASTNode node) {
		ASTFlattener flattener= new ASTFlattener();
		node.accept(flattener);
		return flattener.getResult();
	}

	public static String asFormattedString(ASTNode node, int indent, String lineDelim, Map<String, String> options) {
		String unformatted= asString(node);
		TextEdit edit= CodeFormatterUtil.format2(node, unformatted, indent, lineDelim, options);
		if (edit != null) {
			Document document= new Document(unformatted);
			try {
				edit.apply(document, TextEdit.NONE);
			} catch (BadLocationException e) {
				JavaPlugin.log(e);
			}
			return document.get();
		}
		return unformatted; // unknown node
	}


	/**
	 * Returns the source of the given node from the location where it was parsed.
	 * @param node the node to get the source from
	 * @param extendedRange if set, the extended ranges of the nodes should ne used
	 * @param removeIndent if set, the indentation is removed.
	 * @return return the source for the given node or null if accessing the source failed.
	 */
	public static String getNodeSource(ASTNode node, boolean extendedRange, boolean removeIndent) {
		ASTNode root= node.getRoot();
		if (root instanceof CompilationUnit) {
			CompilationUnit astRoot= (CompilationUnit) root;
			ITypeRoot typeRoot= astRoot.getTypeRoot();
			try {
				if (typeRoot != null && typeRoot.getBuffer() != null) {
					IBuffer buffer= typeRoot.getBuffer();
					int offset= extendedRange ? astRoot.getExtendedStartPosition(node) : node.getStartPosition();
					int length= extendedRange ? astRoot.getExtendedLength(node) : node.getLength();
					String str= buffer.getText(offset, length);
					if (removeIndent) {
						IJavaProject project= typeRoot.getJavaProject();
						int indent= StubUtility.getIndentUsed(buffer, node.getStartPosition(), project);
						str= Strings.changeIndent(str, indent, project, new String(), typeRoot.findRecommendedLineSeparator());
					}
					return str;
				}
			} catch (JavaModelException e) {
				// ignore
			}
		}
		return null;
	}

    /**
     * Returns the list that contains the given ASTNode. If the node
     * isn't part of any list, <code>null</code> is returned.
     *
     * @param node the node in question
     * @return the list that contains the node or <code>null</code>
     */
    public static List<? extends ASTNode> getContainingList(ASTNode node) {
    	StructuralPropertyDescriptor locationInParent= node.getLocationInParent();
    	if (locationInParent != null && locationInParent.isChildListProperty()) {
    		return getChildListProperty(node.getParent(), (ChildListPropertyDescriptor) locationInParent);
    	}
    	return null;
    }

	/**
	 * Variant of {@link ASTNode#getStructuralProperty(StructuralPropertyDescriptor)} that avoids
	 * unchecked casts in the caller.
	 * <p>
	 * To improve type-safety, callers can add the expected element type as explicit type argument, e.g.:
	 * <p>
	 * {@code ASTNodes.<BodyDeclaration>getChildListProperty(typeDecl, bodyDeclarationsProperty)}
	 * 
	 * @param node the node
	 * @param propertyDescriptor the child list property to get
	 * @return the child list
	 * @exception RuntimeException if this node does not have the given property
	 */
	@SuppressWarnings("unchecked")
	public static <T extends ASTNode> List<T> getChildListProperty(ASTNode node, ChildListPropertyDescriptor propertyDescriptor) {
		return (List<T>) node.getStructuralProperty(propertyDescriptor);
	}

	/**
	 * Returns a list of the direct children of a node. The siblings are ordered by start offset.
	 * @param node the node to get the children for
	 * @return the children
	 */
	public static List<ASTNode> getChildren(ASTNode node) {
		ChildrenCollector visitor= new ChildrenCollector();
		node.accept(visitor);
		return visitor.result;
	}

	private static class ChildrenCollector extends GenericVisitor {
		public List<ASTNode> result;

		public ChildrenCollector() {
			super(true);
			result= null;
		}
		@Override
		protected boolean visitNode(ASTNode node) {
			if (result == null) { // first visitNode: on the node's parent: do nothing, return true
				result= new ArrayList<ASTNode>();
				return true;
			}
			result.add(node);
			return false;
		}
	}

	/**
	 * Returns true if this is an existing node, i.e. it was created as part of
	 * a parsing process of a source code file. Returns false if this is a newly
	 * created node which has not yet been given a source position.
	 *
	 * @param node the node to be tested.
	 * @return true if this is an existing node, false if not.
	 */
	public static boolean isExistingNode(ASTNode node) {
		return node.getStartPosition() != -1;
	}

	/**
	 * Returns the element type. This is a convenience method that returns its
	 * argument if it is a simple type and the element type if the parameter is an array type.
	 * @param type The type to get the element type from.
	 * @return The element type of the type or the type itself.
	 */
	public static Type getElementType(Type type) {
		if (! type.isArrayType())
			return type;
		return ((ArrayType)type).getElementType();
	}

	public static ASTNode findDeclaration(IBinding binding, ASTNode root) {
		root= root.getRoot();
		if (root instanceof CompilationUnit) {
			return ((CompilationUnit)root).findDeclaringNode(binding);
		}
		return null;
	}

	public static VariableDeclaration findVariableDeclaration(IVariableBinding binding, ASTNode root) {
		if (binding.isField())
			return null;
		ASTNode result= findDeclaration(binding, root);
		if (result instanceof VariableDeclaration)
				return (VariableDeclaration)result;

		return null;
	}

	/**
	 * Returns the type node for the given declaration.
	 * 
	 * @param declaration the declaration
	 * @return the type node or <code>null</code> if the given declaration represents a type
	 *         inferred parameter in lambda expression
	 */
	public static Type getType(VariableDeclaration declaration) {
		if (declaration instanceof SingleVariableDeclaration) {
			return ((SingleVariableDeclaration)declaration).getType();
		} else if (declaration instanceof VariableDeclarationFragment) {
			ASTNode parent= ((VariableDeclarationFragment)declaration).getParent();
			if (parent instanceof VariableDeclarationExpression)
				return ((VariableDeclarationExpression)parent).getType();
			else if (parent instanceof VariableDeclarationStatement)
				return ((VariableDeclarationStatement)parent).getType();
			else if (parent instanceof FieldDeclaration)
				return ((FieldDeclaration)parent).getType();
			else if (parent instanceof LambdaExpression)
				return null;
		}
		Assert.isTrue(false, "Unknown VariableDeclaration"); //$NON-NLS-1$
		return null;
	}

	public static int getDimensions(VariableDeclaration declaration) {
		int dim= declaration.getExtraDimensions();
		if (declaration instanceof VariableDeclarationFragment && declaration.getParent() instanceof LambdaExpression) {
			LambdaExpression lambda= (LambdaExpression) declaration.getParent();
			IMethodBinding methodBinding= lambda.resolveMethodBinding();
			if (methodBinding != null) {
				ITypeBinding[] parameterTypes= methodBinding.getParameterTypes();
				int index= lambda.parameters().indexOf(declaration);
				ITypeBinding typeBinding= parameterTypes[index];
				return typeBinding.getDimensions();
			}
		} else {
			Type type= getType(declaration);
			if (type instanceof ArrayType) {
				dim+= ((ArrayType) type).getDimensions();
			}
		}
		return dim;
	}

	public static List<IExtendedModifier> getModifiers(VariableDeclaration declaration) {
		Assert.isNotNull(declaration);
		if (declaration instanceof SingleVariableDeclaration) {
			return ((SingleVariableDeclaration)declaration).modifiers();
		} else if (declaration instanceof VariableDeclarationFragment) {
			ASTNode parent= declaration.getParent();
			if (parent instanceof VariableDeclarationExpression)
				return ((VariableDeclarationExpression)parent).modifiers();
			else if (parent instanceof VariableDeclarationStatement)
				return ((VariableDeclarationStatement)parent).modifiers();
		}
		return new ArrayList<IExtendedModifier>(0);
	}

	public static boolean isSingleDeclaration(VariableDeclaration declaration) {
		Assert.isNotNull(declaration);
		if (declaration instanceof SingleVariableDeclaration) {
			return true;
		} else if (declaration instanceof VariableDeclarationFragment) {
			ASTNode parent= declaration.getParent();
			if (parent instanceof VariableDeclarationExpression)
				return ((VariableDeclarationExpression)parent).fragments().size() == 1;
			else if (parent instanceof VariableDeclarationStatement)
				return ((VariableDeclarationStatement)parent).fragments().size() == 1;
		}
		return false;
	}

	public static boolean isLiteral(Expression expression) {
		int type= expression.getNodeType();
		return type == ASTNode.BOOLEAN_LITERAL || type == ASTNode.CHARACTER_LITERAL || type == ASTNode.NULL_LITERAL ||
			type == ASTNode.NUMBER_LITERAL || type == ASTNode.STRING_LITERAL || type == ASTNode.TYPE_LITERAL;
	}

	public static boolean isLabel(SimpleName name) {
		int parentType= name.getParent().getNodeType();
		return parentType == ASTNode.LABELED_STATEMENT ||
			parentType == ASTNode.BREAK_STATEMENT || parentType != ASTNode.CONTINUE_STATEMENT;
	}

	public static boolean isStatic(BodyDeclaration declaration) {
		return Modifier.isStatic(declaration.getModifiers());
	}

	public static List<BodyDeclaration> getBodyDeclarations(ASTNode node) {
		if (node instanceof AbstractTypeDeclaration) {
			return ((AbstractTypeDeclaration)node).bodyDeclarations();
		} else if (node instanceof AnonymousClassDeclaration) {
			return ((AnonymousClassDeclaration)node).bodyDeclarations();
		}
		// should not happen.
		Assert.isTrue(false);
		return null;
	}

	/**
	 * Returns the structural property descriptor for the "bodyDeclarations" property
	 * of this node (element type: {@link BodyDeclaration}).
	 * 
	 * @param node the node, either an {@link AbstractTypeDeclaration} or an {@link AnonymousClassDeclaration}
	 * @return the property descriptor
	 */
	public static ChildListPropertyDescriptor getBodyDeclarationsProperty(ASTNode node) {
		if (node instanceof AbstractTypeDeclaration) {
			return ((AbstractTypeDeclaration)node).getBodyDeclarationsProperty();
		} else if (node instanceof AnonymousClassDeclaration) {
			return AnonymousClassDeclaration.BODY_DECLARATIONS_PROPERTY;
		}
		// should not happen.
		Assert.isTrue(false);
		return null;
	}

	/**
	 * Returns the simple name of the type, followed by array dimensions.
	 * Skips qualifiers, type arguments, and type annotations.
	 * <p>
	 * Does <b>not</b> work for WildcardTypes, etc.!
	 * 
	 * @param type a type that has a simple name
	 * @return the simple name, followed by array dimensions
	 * @see #getSimpleNameIdentifier(Name)
	 * @since 3.10
	 */
	public static String getTypeName(Type type) {
		final StringBuffer buffer= new StringBuffer();
		ASTVisitor visitor= new ASTVisitor() {
			@Override
			public boolean visit(PrimitiveType node) {
				buffer.append(node.getPrimitiveTypeCode().toString());
				return false;
			}
			@Override
			public boolean visit(SimpleType node) {
				buffer.append(getSimpleNameIdentifier(node.getName()));
				return false;
			}
			@Override
			public boolean visit(QualifiedType node) {
				buffer.append(node.getName().getIdentifier());
				return false;
			}
			@Override
			public boolean visit(NameQualifiedType node) {
				buffer.append(node.getName().getIdentifier());
				return false;
			}
			@Override
			public boolean visit(ParameterizedType node) {
				node.getType().accept(this);
				return false;
			}
			@Override
			public void endVisit(ArrayType node) {
				for (int i= 0; i < node.dimensions().size(); i++) {
					buffer.append("[]"); //$NON-NLS-1$
				}
			}
		};
		type.accept(visitor);
		return buffer.toString();
	}

	/**
	 * Returns the (potentially qualified) name of a type, followed by array dimensions.
	 * Skips type arguments and type annotations.
	 * 
	 * @param type a type that has a name
	 * @return the name, followed by array dimensions
	 * @since 3.10
	 */
	public static String getQualifiedTypeName(Type type) {
		final StringBuffer buffer= new StringBuffer();
		ASTVisitor visitor= new ASTVisitor() {
			@Override
			public boolean visit(SimpleType node) {
				buffer.append(node.getName().getFullyQualifiedName());
				return false;
			}
			@Override
			public boolean visit(QualifiedType node) {
				node.getQualifier().accept(this);
				buffer.append('.');
				buffer.append(node.getName().getIdentifier());
				return false;
			}
			@Override
			public boolean visit(NameQualifiedType node) {
				buffer.append(node.getQualifier().getFullyQualifiedName());
				buffer.append('.');
				buffer.append(node.getName().getIdentifier());
				return false;
			}
			@Override
			public boolean visit(ParameterizedType node) {
				node.getType().accept(this);
				return false;
			}
			@Override
			public void endVisit(ArrayType node) {
				for (int i= 0; i < node.dimensions().size(); i++) {
					buffer.append("[]"); //$NON-NLS-1$
				}
			}
		};
		type.accept(visitor);
		return buffer.toString();
	}
	
	public static InfixExpression.Operator convertToInfixOperator(Assignment.Operator operator) {
		if (operator.equals(Assignment.Operator.PLUS_ASSIGN))
			return InfixExpression.Operator.PLUS;

		if (operator.equals(Assignment.Operator.MINUS_ASSIGN))
			return InfixExpression.Operator.MINUS;

		if (operator.equals(Assignment.Operator.TIMES_ASSIGN))
			return InfixExpression.Operator.TIMES;

		if (operator.equals(Assignment.Operator.DIVIDE_ASSIGN))
			return InfixExpression.Operator.DIVIDE;

		if (operator.equals(Assignment.Operator.BIT_AND_ASSIGN))
			return InfixExpression.Operator.AND;

		if (operator.equals(Assignment.Operator.BIT_OR_ASSIGN))
			return InfixExpression.Operator.OR;

		if (operator.equals(Assignment.Operator.BIT_XOR_ASSIGN))
			return InfixExpression.Operator.XOR;

		if (operator.equals(Assignment.Operator.REMAINDER_ASSIGN))
			return InfixExpression.Operator.REMAINDER;

		if (operator.equals(Assignment.Operator.LEFT_SHIFT_ASSIGN))
			return InfixExpression.Operator.LEFT_SHIFT;

		if (operator.equals(Assignment.Operator.RIGHT_SHIFT_SIGNED_ASSIGN))
			return InfixExpression.Operator.RIGHT_SHIFT_SIGNED;

		if (operator.equals(Assignment.Operator.RIGHT_SHIFT_UNSIGNED_ASSIGN))
			return InfixExpression.Operator.RIGHT_SHIFT_UNSIGNED;

		Assert.isTrue(false, "Cannot convert assignment operator"); //$NON-NLS-1$
		return null;
	}

	/**
	 * Returns true if a node at a given location is a body of a control statement. Such body nodes are
	 * interesting as when replacing them, it has to be evaluates if a Block is needed instead.
	 * E.g. <code> if (x) do(); -> if (x) { do1(); do2() } </code>
	 *
	 * @param locationInParent Location of the body node
	 * @return Returns true if the location is a body node location of a control statement.
	 */
	public static boolean isControlStatementBody(StructuralPropertyDescriptor locationInParent) {
		return locationInParent == IfStatement.THEN_STATEMENT_PROPERTY
			|| locationInParent == IfStatement.ELSE_STATEMENT_PROPERTY
			|| locationInParent == ForStatement.BODY_PROPERTY
			|| locationInParent == EnhancedForStatement.BODY_PROPERTY
			|| locationInParent == WhileStatement.BODY_PROPERTY
			|| locationInParent == DoStatement.BODY_PROPERTY;
	}

	/**
	 * Returns the type to which an inlined variable initializer should be cast, or
	 * <code>null</code> if no cast is necessary.
	 * 
	 * @param initializer the initializer expression of the variable to inline
	 * @param reference the reference to the variable (which is to be inlined)
	 * @return a type binding to which the initializer should be cast, or <code>null</code> iff no cast is necessary
	 * @since 3.6
	 */
	public static ITypeBinding getExplicitCast(Expression initializer, Expression reference) {
		ITypeBinding initializerType= initializer.resolveTypeBinding();
		ITypeBinding referenceType= reference.resolveTypeBinding();
		if (initializerType == null || referenceType == null)
			return null;
		
		if (initializerType.isPrimitive() && referenceType.isPrimitive() && ! referenceType.isEqualTo(initializerType)) {
			return referenceType;
			
		} else if (initializerType.isPrimitive() && ! referenceType.isPrimitive()) { // initializer is autoboxed
			ITypeBinding unboxedReferenceType= Bindings.getUnboxedTypeBinding(referenceType, reference.getAST());
			if (!unboxedReferenceType.isEqualTo(initializerType))
				return unboxedReferenceType;
			else if (needsExplicitBoxing(reference))
				return referenceType;
			
		} else if (! initializerType.isPrimitive() && referenceType.isPrimitive()) { // initializer is autounboxed
			ITypeBinding unboxedInitializerType= Bindings.getUnboxedTypeBinding(initializerType, reference.getAST());
			if (!unboxedInitializerType.isEqualTo(referenceType))
				return referenceType;
			
		} else if (initializerType.isRawType() && referenceType.isParameterizedType()) {
			return referenceType; // don't lose the unchecked conversion

		} else if (initializer instanceof LambdaExpression || initializer instanceof MethodReference) {
			if (isTargetAmbiguous(reference)) {
				return referenceType;
			} else {
				ITypeBinding targetType= getTargetType(reference);
				if (targetType == null || targetType != referenceType) {
					return referenceType;
				}
			}

		} else if (! TypeRules.canAssign(initializerType, referenceType)) {
			if (!Bindings.containsTypeVariables(referenceType))
				return referenceType;
		}
		
		return null;
	}

	/**
	 * Checks whether overloaded methods can result in an ambiguous method call or a semantic change when the
	 * <code>expression</code> argument is replaced with a poly expression form of the functional
	 * interface instance.
	 * 
	 * @param expression the method argument, which is a functional interface instance
	 * @return <code>true</code> if overloaded methods can result in an ambiguous method call or a semantic change,
	 *         <code>false</code> otherwise
	 * 
	 * @since 3.10
	 */
	public static boolean isTargetAmbiguous(Expression expression) {
		StructuralPropertyDescriptor locationInParent= expression.getLocationInParent();

		while (locationInParent == ParenthesizedExpression.EXPRESSION_PROPERTY
				|| locationInParent == ConditionalExpression.THEN_EXPRESSION_PROPERTY
				|| locationInParent == ConditionalExpression.ELSE_EXPRESSION_PROPERTY) {
			expression= (Expression) expression.getParent();
			locationInParent= expression.getLocationInParent();
		}
		
		ASTNode parent= expression.getParent();
		IMethodBinding methodBinding;
		int argumentIndex;
		if (locationInParent == MethodInvocation.ARGUMENTS_PROPERTY) {
			MethodInvocation methodInvocation= (MethodInvocation) parent;
			methodBinding= methodInvocation.resolveMethodBinding();
			argumentIndex= methodInvocation.arguments().indexOf(expression);
		} else if (locationInParent == SuperMethodInvocation.ARGUMENTS_PROPERTY) {
			SuperMethodInvocation superMethodInvocation= (SuperMethodInvocation) parent;
			methodBinding= superMethodInvocation.resolveMethodBinding();
			argumentIndex= superMethodInvocation.arguments().indexOf(expression);
		} else if (locationInParent == ConstructorInvocation.ARGUMENTS_PROPERTY) {
			ConstructorInvocation constructorInvocation= (ConstructorInvocation) parent;
			methodBinding= constructorInvocation.resolveConstructorBinding();
			argumentIndex= constructorInvocation.arguments().indexOf(expression);
		} else if (locationInParent == SuperConstructorInvocation.ARGUMENTS_PROPERTY) {
			SuperConstructorInvocation superConstructorInvocation= (SuperConstructorInvocation) parent;
			methodBinding= superConstructorInvocation.resolveConstructorBinding();
			argumentIndex= superConstructorInvocation.arguments().indexOf(expression);
		} else if (locationInParent == ClassInstanceCreation.ARGUMENTS_PROPERTY) {
			ClassInstanceCreation creation= (ClassInstanceCreation) parent;
			methodBinding= creation.resolveConstructorBinding();
			argumentIndex= creation.arguments().indexOf(expression);
		} else if (locationInParent == EnumConstantDeclaration.ARGUMENTS_PROPERTY) {
			EnumConstantDeclaration enumConstantDecl= (EnumConstantDeclaration) parent;
			methodBinding= enumConstantDecl.resolveConstructorBinding();
			argumentIndex= enumConstantDecl.arguments().indexOf(expression);
		} else {
			return false;
		}

		if (methodBinding != null) {
			IMethodBinding methodDeclBinding= methodBinding.getMethodDeclaration();
			ITypeBinding declaringTypeBinding= methodDeclBinding.getDeclaringClass();
			TypeBindingVisitor visitor= new AmbiguousTargetMethodAnalyzer(declaringTypeBinding, methodDeclBinding, argumentIndex);
			return !(visitor.visit(declaringTypeBinding) && Bindings.visitHierarchy(declaringTypeBinding, visitor));
		}

		return true;
	}

	private static class AmbiguousTargetMethodAnalyzer implements TypeBindingVisitor {
		private ITypeBinding fDeclaringType;
		private IMethodBinding fOriginalMethod;
		private int fArgIndex;

		/**
		 * @param declaringType the type binding declaring the <code>originalMethod</code>
		 * @param originalMethod the method declaration binding corresponding to the method call
		 * @param argumentIndex the index of the functional interface instance argument in the
		 *            method call
		 */
		public AmbiguousTargetMethodAnalyzer(ITypeBinding declaringType, IMethodBinding originalMethod, int argumentIndex) {
			fDeclaringType= declaringType;
			fOriginalMethod= originalMethod;
			fArgIndex= argumentIndex;
		}

		public boolean visit(ITypeBinding type) {
			IMethodBinding[] methods= type.getDeclaredMethods();
			for (int i= 0; i < methods.length; i++) {
				IMethodBinding candidate= methods[i];
				if (candidate == fOriginalMethod) {
					continue;
				}
				ITypeBinding candidateDeclaringType= candidate.getDeclaringClass();
				if (fDeclaringType != candidateDeclaringType) {
					int modifiers= candidate.getModifiers();
					if (candidateDeclaringType.isInterface() && Modifier.isStatic(modifiers)) {
						continue;
					}
					if (Modifier.isPrivate(modifiers)) {
						continue;
					}
				}
				if (fOriginalMethod.getName().equals(candidate.getName()) && !fOriginalMethod.overrides(candidate)) {
					ITypeBinding[] originalParameterTypes= fOriginalMethod.getParameterTypes();
					ITypeBinding[] candidateParameterTypes= candidate.getParameterTypes();
					if (originalParameterTypes.length == candidateParameterTypes.length
							|| fOriginalMethod.isVarargs() || candidate.isVarargs()) {
						ITypeBinding parameterType= ASTResolving.getParameterTypeBinding(candidate, fArgIndex);
						if (parameterType != null && parameterType.getFunctionalInterfaceMethod() != null) {
							ITypeBinding origParamType= ASTResolving.getParameterTypeBinding(fOriginalMethod, fArgIndex);
							boolean originalIsVoidCompatible=  Bindings.isVoidType(origParamType.getFunctionalInterfaceMethod().getReturnType());
							boolean candidateIsVoidCompatible= Bindings.isVoidType(parameterType.getFunctionalInterfaceMethod().getReturnType());
							if (originalIsVoidCompatible == candidateIsVoidCompatible) {
								return false;
							}
						}
					}
				}
			}
			return true;
		}
	}

	/**
	 * Derives the target type defined at the location of the given expression if the target context
	 * supports poly expressions.
	 * 
	 * @param expression the expression at whose location the target type is required
	 * @return the type binding of the target type defined at the location of the given expression
	 *         if the target context supports poly expressions, or <code>null</code> if the target
	 *         type could not be derived
	 * 
	 * @since 3.10
	 */
	public static ITypeBinding getTargetType(Expression expression) {
		ASTNode parent= expression.getParent();
		StructuralPropertyDescriptor locationInParent= expression.getLocationInParent();

		if (locationInParent == VariableDeclarationFragment.INITIALIZER_PROPERTY || locationInParent == SingleVariableDeclaration.INITIALIZER_PROPERTY) {
			return ((VariableDeclaration) parent).getName().resolveTypeBinding();

		} else if (locationInParent == Assignment.RIGHT_HAND_SIDE_PROPERTY) {
			return ((Assignment) parent).getLeftHandSide().resolveTypeBinding();

		} else if (locationInParent == ReturnStatement.EXPRESSION_PROPERTY) {
			return getTargetTypeForReturnStmt((ReturnStatement) parent);

		} else if (locationInParent == ArrayInitializer.EXPRESSIONS_PROPERTY) {
			return getTargetTypeForArrayInitializer((ArrayInitializer) parent);

		} else if (locationInParent == MethodInvocation.ARGUMENTS_PROPERTY) {
			MethodInvocation methodInvocation= (MethodInvocation) parent;
			IMethodBinding methodBinding= methodInvocation.resolveMethodBinding();
			if (methodBinding != null) {
				return getParameterTypeBinding(expression, methodInvocation.arguments(), methodBinding);
			}

		} else if (locationInParent == SuperMethodInvocation.ARGUMENTS_PROPERTY) {
			SuperMethodInvocation superMethodInvocation= (SuperMethodInvocation) parent;
			IMethodBinding superMethodBinding= superMethodInvocation.resolveMethodBinding();
			if (superMethodBinding != null) {
				return getParameterTypeBinding(expression, superMethodInvocation.arguments(), superMethodBinding);
			}

		} else if (locationInParent == ConstructorInvocation.ARGUMENTS_PROPERTY) {
			ConstructorInvocation constructorInvocation= (ConstructorInvocation) parent;
			IMethodBinding constructorBinding= constructorInvocation.resolveConstructorBinding();
			if (constructorBinding != null) {
				return getParameterTypeBinding(expression, constructorInvocation.arguments(), constructorBinding);
			}

		} else if (locationInParent == SuperConstructorInvocation.ARGUMENTS_PROPERTY) {
			SuperConstructorInvocation superConstructorInvocation= (SuperConstructorInvocation) parent;
			IMethodBinding superConstructorBinding= superConstructorInvocation.resolveConstructorBinding();
			if (superConstructorBinding != null) {
				return getParameterTypeBinding(expression, superConstructorInvocation.arguments(), superConstructorBinding);
			}

		} else if (locationInParent == ClassInstanceCreation.ARGUMENTS_PROPERTY) {
			ClassInstanceCreation creation= (ClassInstanceCreation) parent;
			IMethodBinding creationBinding= creation.resolveConstructorBinding();
			if (creationBinding != null) {
				return getParameterTypeBinding(expression, creation.arguments(), creationBinding);
			}

		} else if (locationInParent == EnumConstantDeclaration.ARGUMENTS_PROPERTY) {
			EnumConstantDeclaration enumConstantDecl= (EnumConstantDeclaration) parent;
			IMethodBinding enumConstructorBinding= enumConstantDecl.resolveConstructorBinding();
			if (enumConstructorBinding != null) {
				return getParameterTypeBinding(expression, enumConstantDecl.arguments(), enumConstructorBinding);
			}

		} else if (locationInParent == LambdaExpression.BODY_PROPERTY) {
			IMethodBinding methodBinding= ((LambdaExpression) parent).resolveMethodBinding();
			if (methodBinding != null) {
				return methodBinding.getReturnType();
			}

		} else if (locationInParent == ConditionalExpression.THEN_EXPRESSION_PROPERTY || locationInParent == ConditionalExpression.ELSE_EXPRESSION_PROPERTY) {
			return getTargetType((ConditionalExpression) parent);

		} else if (locationInParent == CastExpression.EXPRESSION_PROPERTY) {
			return ((CastExpression) parent).getType().resolveBinding();

		} else if (locationInParent == ParenthesizedExpression.EXPRESSION_PROPERTY) {
			return getTargetType((ParenthesizedExpression) parent);

		}
		return null;
	}

	private static ITypeBinding getParameterTypeBinding(Expression expression, List<Expression> arguments, IMethodBinding methodBinding) {
		IMethodBinding methodDeclBinding= methodBinding.getMethodDeclaration();
		int index= arguments.indexOf(expression);
		return ASTResolving.getParameterTypeBinding(methodDeclBinding, index);
	}

	private static ITypeBinding getTargetTypeForArrayInitializer(ArrayInitializer arrayInitializer) {
		ASTNode initializerParent= arrayInitializer.getParent();
		while (initializerParent instanceof ArrayInitializer) {
			initializerParent= initializerParent.getParent();
		}
		if (initializerParent instanceof ArrayCreation) {
			return ((ArrayCreation) initializerParent).getType().getElementType().resolveBinding();
		} else if (initializerParent instanceof VariableDeclaration) {
			ITypeBinding typeBinding= ((VariableDeclaration) initializerParent).getName().resolveTypeBinding();
			if (typeBinding != null) {
				return typeBinding.getElementType();
			}
		}
		return null;
	}

	private static ITypeBinding getTargetTypeForReturnStmt(ReturnStatement returnStmt) {
		LambdaExpression enclosingLambdaExpr= ASTResolving.findEnclosingLambdaExpression(returnStmt);
		if (enclosingLambdaExpr != null) {
			IMethodBinding methodBinding= enclosingLambdaExpr.resolveMethodBinding();
			return methodBinding == null ? null : methodBinding.getReturnType();
		}
		MethodDeclaration enclosingMethodDecl= ASTResolving.findParentMethodDeclaration(returnStmt);
		if (enclosingMethodDecl != null) {
			IMethodBinding methodBinding= enclosingMethodDecl.resolveBinding();
			return methodBinding == null ? null : methodBinding.getReturnType();
		}
		return null;
	}

	/**
	 * Returns whether an expression at the given location needs explicit boxing.
	 * 
	 * @param expression the expression
	 * @return <code>true</code> iff an expression at the given location needs explicit boxing
	 * @since 3.6
	 */
	private static boolean needsExplicitBoxing(Expression expression) {
		StructuralPropertyDescriptor locationInParent= expression.getLocationInParent();
		if (locationInParent == ParenthesizedExpression.EXPRESSION_PROPERTY)
			return needsExplicitBoxing((ParenthesizedExpression) expression.getParent());
		
		if (locationInParent == ClassInstanceCreation.EXPRESSION_PROPERTY
				|| locationInParent == FieldAccess.EXPRESSION_PROPERTY
				|| locationInParent == MethodInvocation.EXPRESSION_PROPERTY)
			return true;
		
		return false;
	}

	/**
	 * Returns the closest ancestor of <code>node</code> that is an instance of <code>parentClass</code>, or <code>null</code> if none.
	 * <p>
	 * <b>Warning:</b> This method does not stop at any boundaries like parentheses, statements, body declarations, etc.
	 * The resulting node may be in a totally different scope than the given node.
	 * Consider using one of the {@link ASTResolving}<code>.find(..)</code> methods instead.
	 * </p>
	 * @param node the node
	 * @param parentClass the class of the sought ancestor node
	 * @return the closest ancestor of <code>node</code> that is an instance of <code>parentClass</code>, or <code>null</code> if none
	 */
	public static ASTNode getParent(ASTNode node, Class<? extends ASTNode> parentClass) {
		do {
			node= node.getParent();
		} while (node != null && !parentClass.isInstance(node));
		return node;
	}

	/**
	 * Returns the closest ancestor of <code>node</code> whose type is <code>nodeType</code>, or <code>null</code> if none.
	 * <p>
	 * <b>Warning:</b> This method does not stop at any boundaries like parentheses, statements, body declarations, etc.
	 * The resulting node may be in a totally different scope than the given node.
	 * Consider using one of the {@link ASTResolving}<code>.find(..)</code> methods instead.
	 * </p>
	 * @param node the node
	 * @param nodeType the node type constant from {@link ASTNode}
	 * @return the closest ancestor of <code>node</code> whose type is <code>nodeType</code>, or <code>null</code> if none
	 */
	public static ASTNode getParent(ASTNode node, int nodeType) {
		do {
			node= node.getParent();
		} while (node != null && node.getNodeType() != nodeType);
		return node;
	}

	public static ASTNode findParent(ASTNode node, StructuralPropertyDescriptor[][] pathes) {
		for (int p= 0; p < pathes.length; p++) {
			StructuralPropertyDescriptor[] path= pathes[p];
			ASTNode current= node;
			int d= path.length - 1;
			for (; d >= 0 && current != null; d--) {
				StructuralPropertyDescriptor descriptor= path[d];
				if (!descriptor.equals(current.getLocationInParent()))
					break;
				current= current.getParent();
			}
			if (d < 0)
				return current;
		}
		return null;
	}

	/**
	 * For {@link Name} or {@link Type} nodes, returns the topmost {@link Type} node
	 * that shares the same type binding as the given node.
	 * 
	 * @param node an ASTNode
	 * @return the normalized {@link Type} node or the original node
	 */
	public static ASTNode getNormalizedNode(ASTNode node) {
		ASTNode current= node;
		// normalize name
		if (QualifiedName.NAME_PROPERTY.equals(current.getLocationInParent())) {
			current= current.getParent();
		}
		// normalize type
		if (QualifiedType.NAME_PROPERTY.equals(current.getLocationInParent())
				|| SimpleType.NAME_PROPERTY.equals(current.getLocationInParent())
				|| NameQualifiedType.NAME_PROPERTY.equals(current.getLocationInParent())) {
			current= current.getParent();
		}
		// normalize parameterized types
		if (ParameterizedType.TYPE_PROPERTY.equals(current.getLocationInParent())) {
			current= current.getParent();
		}
		return current;
	}

	/**
	 * Returns <code>true</code> iff <code>parent</code> is a true ancestor of <code>node</code>
	 * (i.e. returns <code>false</code> if <code>parent == node</code>).
	 * 
	 * @param node node to test
	 * @param parent assumed parent
	 * @return <code>true</code> iff <code>parent</code> is a true ancestor of <code>node</code>
	 */
	public static boolean isParent(ASTNode node, ASTNode parent) {
		Assert.isNotNull(parent);
		do {
			node= node.getParent();
			if (node == parent)
				return true;
		} while (node != null);
		return false;
	}

	public static int getExclusiveEnd(ASTNode node){
		return node.getStartPosition() + node.getLength();
	}

	public static int getInclusiveEnd(ASTNode node){
		return node.getStartPosition() + node.getLength() - 1;
	}

	public static IMethodBinding getMethodBinding(Name node) {
		IBinding binding= node.resolveBinding();
		if (binding instanceof IMethodBinding)
			return (IMethodBinding)binding;
		return null;
	}

	public static IVariableBinding getVariableBinding(Name node) {
		IBinding binding= node.resolveBinding();
		if (binding instanceof IVariableBinding)
			return (IVariableBinding)binding;
		return null;
	}

	public static IVariableBinding getLocalVariableBinding(Name node) {
		IVariableBinding result= getVariableBinding(node);
		if (result == null || result.isField())
			return null;

		return result;
	}

	public static IVariableBinding getFieldBinding(Name node) {
		IVariableBinding result= getVariableBinding(node);
		if (result == null || !result.isField())
			return null;

		return result;
	}

	public static ITypeBinding getTypeBinding(Name node) {
		IBinding binding= node.resolveBinding();
		if (binding instanceof ITypeBinding)
			return (ITypeBinding)binding;
		return null;
	}

	/**
	 * Returns the receiver's type binding of the given method invocation.
	 *
	 * @param invocation method invocation to resolve type of
	 * @return the type binding of the receiver
	 */
	public static ITypeBinding getReceiverTypeBinding(MethodInvocation invocation) {
		ITypeBinding result= null;
		Expression exp= invocation.getExpression();
		if(exp != null) {
			return exp.resolveTypeBinding();
		}
		else {
			AbstractTypeDeclaration type= (AbstractTypeDeclaration)getParent(invocation, AbstractTypeDeclaration.class);
			if (type != null)
				return type.resolveBinding();
		}
		return result;
	}

	public static ITypeBinding getEnclosingType(ASTNode node) {
		while(node != null) {
			if (node instanceof AbstractTypeDeclaration) {
				return ((AbstractTypeDeclaration)node).resolveBinding();
			} else if (node instanceof AnonymousClassDeclaration) {
				return ((AnonymousClassDeclaration)node).resolveBinding();
			}
			node= node.getParent();
		}
		return null;
	}

	public static IProblem[] getProblems(ASTNode node, int scope, int severity) {
		ASTNode root= node.getRoot();
		if (!(root instanceof CompilationUnit))
			return EMPTY_PROBLEMS;
		IProblem[] problems= ((CompilationUnit)root).getProblems();
		if (root == node)
			return problems;
		final int iterations= computeIterations(scope);
		List<IProblem> result= new ArrayList<IProblem>(5);
		for (int i= 0; i < problems.length; i++) {
			IProblem problem= problems[i];
			boolean consider= false;
			if ((severity & PROBLEMS) == PROBLEMS)
				consider= true;
			else if ((severity & WARNING) != 0)
				consider= problem.isWarning();
			else if ((severity & ERROR) != 0)
				consider= problem.isError();
			if (consider) {
				ASTNode temp= node;
				int count= iterations;
				do {
					int nodeOffset= temp.getStartPosition();
					int problemOffset= problem.getSourceStart();
					if (nodeOffset <= problemOffset && problemOffset < nodeOffset + temp.getLength()) {
						result.add(problem);
						count= 0;
					} else {
						count--;
					}
				} while ((temp= temp.getParent()) != null && count > 0);
			}
		}
		return result.toArray(new IProblem[result.size()]);
	}

	public static Message[] getMessages(ASTNode node, int flags) {
		ASTNode root= node.getRoot();
		if (!(root instanceof CompilationUnit))
			return EMPTY_MESSAGES;
		Message[] messages= ((CompilationUnit)root).getMessages();
		if (root == node)
			return messages;
		final int iterations= computeIterations(flags);
		List<Message> result= new ArrayList<Message>(5);
		for (int i= 0; i < messages.length; i++) {
			Message message= messages[i];
			ASTNode temp= node;
			int count= iterations;
			do {
				int nodeOffset= temp.getStartPosition();
				int messageOffset= message.getStartPosition();
				if (nodeOffset <= messageOffset && messageOffset < nodeOffset + temp.getLength()) {
					result.add(message);
					count= 0;
				} else {
					count--;
				}
			} while ((temp= temp.getParent()) != null && count > 0);
		}
		return result.toArray(new Message[result.size()]);
	}

	private static int computeIterations(int flags) {
		switch (flags) {
			case NODE_ONLY:
				return 1;
			case INCLUDE_ALL_PARENTS:
				return Integer.MAX_VALUE;
			case INCLUDE_FIRST_PARENT:
				return 2;
			default:
				return 1;
		}
	}


	private static int getOrderPreference(BodyDeclaration member, MembersOrderPreferenceCache store) {
		int memberType= member.getNodeType();
		int modifiers= member.getModifiers();

		switch (memberType) {
			case ASTNode.TYPE_DECLARATION:
			case ASTNode.ENUM_DECLARATION :
			case ASTNode.ANNOTATION_TYPE_DECLARATION :
				return store.getCategoryIndex(MembersOrderPreferenceCache.TYPE_INDEX) * 2;
			case ASTNode.FIELD_DECLARATION:
				if (Modifier.isStatic(modifiers)) {
					int index= store.getCategoryIndex(MembersOrderPreferenceCache.STATIC_FIELDS_INDEX) * 2;
					if (Modifier.isFinal(modifiers)) {
						return index; // first final static, then static
					}
					return index + 1;
				}
				return store.getCategoryIndex(MembersOrderPreferenceCache.FIELDS_INDEX) * 2;
			case ASTNode.INITIALIZER:
				if (Modifier.isStatic(modifiers)) {
					return store.getCategoryIndex(MembersOrderPreferenceCache.STATIC_INIT_INDEX) * 2;
				}
				return store.getCategoryIndex(MembersOrderPreferenceCache.INIT_INDEX) * 2;
			case ASTNode.ANNOTATION_TYPE_MEMBER_DECLARATION:
				return store.getCategoryIndex(MembersOrderPreferenceCache.METHOD_INDEX) * 2;
			case ASTNode.METHOD_DECLARATION:
				if (Modifier.isStatic(modifiers)) {
					return store.getCategoryIndex(MembersOrderPreferenceCache.STATIC_METHODS_INDEX) * 2;
				}
				if (((MethodDeclaration) member).isConstructor()) {
					return store.getCategoryIndex(MembersOrderPreferenceCache.CONSTRUCTORS_INDEX) * 2;
				}
				return store.getCategoryIndex(MembersOrderPreferenceCache.METHOD_INDEX) * 2;
			default:
				return 100;
		}
	}

	/**
	 * Computes the insertion index to be used to add the given member to the
	 * the list <code>container</code>.
	 * @param member the member to add
	 * @param container a list containing objects of type <code>BodyDeclaration</code>
	 * @return the insertion index to be used
	 */
	public static int getInsertionIndex(BodyDeclaration member, List<? extends BodyDeclaration> container) {
		int containerSize= container.size();

		MembersOrderPreferenceCache orderStore= JavaPlugin.getDefault().getMemberOrderPreferenceCache();

		int orderIndex= getOrderPreference(member, orderStore);

		int insertPos= containerSize;
		int insertPosOrderIndex= -1;

		for (int i= containerSize - 1; i >= 0; i--) {
			int currOrderIndex= getOrderPreference(container.get(i), orderStore);
			if (orderIndex == currOrderIndex) {
				if (insertPosOrderIndex != orderIndex) { // no perfect match yet
					insertPos= i + 1; // after a same kind
					insertPosOrderIndex= orderIndex; // perfect match
				}
			} else if (insertPosOrderIndex != orderIndex) { // not yet a perfect match
				if (currOrderIndex < orderIndex) { // we are bigger
					if (insertPosOrderIndex == -1) {
						insertPos= i + 1; // after
						insertPosOrderIndex= currOrderIndex;
					}
				} else {
					insertPos= i; // before
					insertPosOrderIndex= currOrderIndex;
				}
			}
		}
		return insertPos;
	}

	public static SimpleName getLeftMostSimpleName(Name name) {
		if (name instanceof SimpleName) {
			return (SimpleName)name;
		} else {
			final SimpleName[] result= new SimpleName[1];
			ASTVisitor visitor= new ASTVisitor() {
				@Override
				public boolean visit(QualifiedName qualifiedName) {
					Name left= qualifiedName.getQualifier();
					if (left instanceof SimpleName)
						result[0]= (SimpleName)left;
					else
						left.accept(this);
					return false;
				}
			};
			name.accept(visitor);
			return result[0];
		}
	}

	/**
	 * Returns the topmost ancestor of <code>name</code> that is still a {@link Name}.
	 * <p>
	 * <b>Note:</b> The returned node may resolve to a different binding than the given <code>name</code>!
	 * 
	 * @param name a name node
	 * @return the topmost name
	 * @see #getNormalizedNode(ASTNode)
	 */
	public static Name getTopMostName(Name name) {
		Name result= name;
		while(result.getParent() instanceof Name) {
			result= (Name)result.getParent();
		}
		return result;
	}

	/**
	 * Returns the topmost ancestor of <code>node</code> that is a {@link Type} (but not a {@link UnionType}).
	 * <p>
	 * <b>Note:</b> The returned node often resolves to a different binding than the given <code>node</code>!
	 * 
	 * @param node the starting node, can be <code>null</code>
	 * @return the topmost type or <code>null</code> if the node is not a descendant of a type node
	 * @see #getNormalizedNode(ASTNode)
	 */
	public static Type getTopMostType(ASTNode node) {
		ASTNode result= null;
		while (node instanceof Type && !(node instanceof UnionType)
				|| node instanceof Name
				|| node instanceof Annotation || node instanceof MemberValuePair
				|| node instanceof Expression) { // Expression could maybe be reduced to expression node types that can appear in an annotation
			result= node;
			node= node.getParent();
		}
		
		if (result instanceof Type)
			return (Type) result;
		
		return null;
	}

	public static int changeVisibility(int modifiers, int visibility) {
		return (modifiers & CLEAR_VISIBILITY) | visibility;
	}

	/**
	 * Adds flags to the given node and all its descendants.
	 * @param root The root node
	 * @param flags The flags to set
	 */
	public static void setFlagsToAST(ASTNode root, final int flags) {
		root.accept(new GenericVisitor(true) {
			@Override
			protected boolean visitNode(ASTNode node) {
				node.setFlags(node.getFlags() | flags);
				return true;
			}
		});
	}

	public static String getQualifier(Name name) {
		if (name.isQualifiedName()) {
			return ((QualifiedName) name).getQualifier().getFullyQualifiedName();
		}
		return ""; //$NON-NLS-1$
	}

	public static String getSimpleNameIdentifier(Name name) {
		if (name.isQualifiedName()) {
			return ((QualifiedName) name).getName().getIdentifier();
		} else {
			return ((SimpleName) name).getIdentifier();
		}
	}

	public static boolean isDeclaration(Name name) {
		if (name.isQualifiedName()) {
			return ((QualifiedName) name).getName().isDeclaration();
		} else {
			return ((SimpleName) name).isDeclaration();
		}
	}

	public static Modifier findModifierNode(int flag, List<IExtendedModifier> modifiers) {
		for (int i= 0; i < modifiers.size(); i++) {
			Object curr= modifiers.get(i);
			if (curr instanceof Modifier && ((Modifier) curr).getKeyword().toFlagValue() == flag) {
				return (Modifier) curr;
			}
		}
		return null;
	}

	public static ITypeBinding getTypeBinding(CompilationUnit root, IType type) throws JavaModelException {
		if (type.isAnonymous()) {
			final IJavaElement parent= type.getParent();
			if (parent instanceof IField && Flags.isEnum(((IMember) parent).getFlags())) {
				final EnumConstantDeclaration constant= (EnumConstantDeclaration) NodeFinder.perform(root, ((ISourceReference) parent).getSourceRange());
				if (constant != null) {
					final AnonymousClassDeclaration declaration= constant.getAnonymousClassDeclaration();
					if (declaration != null)
						return declaration.resolveBinding();
				}
			} else {
				final ClassInstanceCreation creation= (ClassInstanceCreation) getParent(NodeFinder.perform(root, type.getNameRange()), ClassInstanceCreation.class);
				if (creation != null)
					return creation.resolveTypeBinding();
			}
		} else {
			final AbstractTypeDeclaration declaration= (AbstractTypeDeclaration) getParent(NodeFinder.perform(root, type.getNameRange()), AbstractTypeDeclaration.class);
			if (declaration != null)
				return declaration.resolveBinding();
		}
		return null;
	}

	/**
	 * Escapes a string value to a literal that can be used in Java source.
	 * 
	 * @param stringValue the string value 
	 * @return the escaped string
	 * @see StringLiteral#getEscapedValue()
	 */
	public static String getEscapedStringLiteral(String stringValue) {
		StringLiteral stringLiteral= AST.newAST(ASTProvider.SHARED_AST_LEVEL).newStringLiteral();
		stringLiteral.setLiteralValue(stringValue);
		return stringLiteral.getEscapedValue();
	}

	/**
	 * Escapes a character value to a literal that can be used in Java source.
	 * 
	 * @param ch the character value 
	 * @return the escaped string
	 * @see CharacterLiteral#getEscapedValue()
	 */
	public static String getEscapedCharacterLiteral(char ch) {
		CharacterLiteral characterLiteral= AST.newAST(ASTProvider.SHARED_AST_LEVEL).newCharacterLiteral();
		characterLiteral.setCharValue(ch);
		return characterLiteral.getEscapedValue();
	}

	/**
	 * Type-safe variant of {@link ASTRewrite#createMoveTarget(ASTNode)}.
	 * 
	 * @param rewrite ASTRewrite for the given node
	 * @param node the node to create a move placeholder for
	 * @return the new placeholder node
	 * @throws IllegalArgumentException if the node is null, or if the node
	 * is not part of the rewrite's AST
	 */
	@SuppressWarnings("unchecked")
	public static <T extends ASTNode> T createMoveTarget(ASTRewrite rewrite, T node) {
		return (T) rewrite.createMoveTarget(node);
	}

	/**
	 * Type-safe variant of {@link ASTNode#copySubtree(AST, ASTNode)}.
	 * 
	 * @param target the AST that is to own the nodes in the result
	 * @param node the node to copy, or <code>null</code> if none
	 * @return the copied node, or <code>null</code> if <code>node</code>
	 *    is <code>null</code>
	 */
	@SuppressWarnings("unchecked")
	public static <T extends ASTNode> T copySubtree(AST target, T node) {
		return (T) ASTNode.copySubtree(target, node);
	}

}
