/*******************************************************************************
 * Copyright (c) 2000, 2015 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
 *     Stephan Herrmann - Contributions for
 *								bug 186342 - [compiler][null] Using annotations for null checking
 *								bug 367203 - [compiler][null] detect assigning null to nonnull argument
 *								bug 365519 - editorial cleanup after bug 186342 and bug 365387
 *								bug 365662 - [compiler][null] warn on contradictory and redundant null annotations
 *								bug 365531 - [compiler][null] investigate alternative strategy for internally encoding nullness defaults
 *								bug 388281 - [compiler][null] inheritance of null annotations as an option
 *								Bug 392099 - [1.8][compiler][null] Apply null annotation on types for null analysis
 *								Bug 417295 - [1.8[[null] Massage type annotated null analysis to gel well with deep encoded type bindings.
 *								Bug 400874 - [1.8][compiler] Inference infrastructure should evolve to meet JLS8 18.x (Part G of JSR335 spec)
 *								Bug 425152 - [1.8] [compiler] Lambda Expression not resolved but flow analyzed leading to NPE.
 *								Bug 423505 - [1.8] Implement "18.5.4 More Specific Method Inference"
 *								Bug 429958 - [1.8][null] evaluate new DefaultLocation attribute of @NonNullByDefault
 *								Bug 438012 - [1.8][null] Bogus Warning: The nullness annotation is redundant with a default that applies to this location
 *								Bug 440759 - [1.8][null] @NonNullByDefault should never affect wildcards and uses of a type variable
 *								Bug 443347 - [1.8][null] @NonNullByDefault should not affect constructor arguments of an anonymous instantiation
 *								Bug 435805 - [1.8][compiler][null] Java 8 compiler does not recognize declaration style null annotations
 *								Bug 466713 - Null Annotations: NullPointerException using <int @Nullable []> as Type Param
 *								Bug 456584 - [1.8][null] Bogus warning for return type variable's @NonNull annotation being 'redundant'
 *								Bug 471611 - Error on hover on call to generic method with null annotation
 *     Jesper Steen Moller - Contributions for
 *								Bug 412150 [1.8] [compiler] Enable reflected parameter names during annotation processing
 *******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;

import java.util.List;

import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.ClassFile;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Argument;
import org.eclipse.jdt.internal.compiler.ast.LambdaExpression;
import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.ast.TypeReference.AnnotationPosition;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.codegen.ConstantPool;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.util.Util;

@SuppressWarnings("rawtypes")
public class MethodBinding extends Binding {

	public int modifiers;
	public char[] selector;
	public TypeBinding returnType;
	public TypeBinding[] parameters;
	public TypeBinding receiver;  // JSR308 - explicit this parameter
	public ReferenceBinding[] thrownExceptions;
	public ReferenceBinding declaringClass;
	public TypeVariableBinding[] typeVariables = Binding.NO_TYPE_VARIABLES;
	char[] signature;
	public long tagBits;

	/** Store nullness information from annotation (incl. applicable default). */
	public Boolean[] parameterNonNullness;  // TRUE means @NonNull declared, FALSE means @Nullable declared, null means nothing declared
	public int defaultNullness; // for null *type* annotations

	/** Store parameter names from MethodParameters attribute (incl. applicable default). */
	public char[][] parameterNames = Binding.NO_PARAMETER_NAMES;

protected MethodBinding() {
	// for creating problem or synthetic method
}
public MethodBinding(int modifiers, char[] selector, TypeBinding returnType, TypeBinding[] parameters, ReferenceBinding[] thrownExceptions, ReferenceBinding declaringClass) {
	this.modifiers = modifiers;
	this.selector = selector;
	this.returnType = returnType;
	this.parameters = (parameters == null || parameters.length == 0) ? Binding.NO_PARAMETERS : parameters;
	this.thrownExceptions = (thrownExceptions == null || thrownExceptions.length == 0) ? Binding.NO_EXCEPTIONS : thrownExceptions;
	this.declaringClass = declaringClass;

	// propagate the strictfp & deprecated modifiers
	if (this.declaringClass != null) {
		if (this.declaringClass.isStrictfp())
			if (!(isNative() || isAbstract()))
				this.modifiers |= ClassFileConstants.AccStrictfp;
	}
}
public MethodBinding(int modifiers, TypeBinding[] parameters, ReferenceBinding[] thrownExceptions, ReferenceBinding declaringClass) {
	this(modifiers, TypeConstants.INIT, TypeBinding.VOID, parameters, thrownExceptions, declaringClass);
}
// special API used to change method declaring class for runtime visibility check
public MethodBinding(MethodBinding initialMethodBinding, ReferenceBinding declaringClass) {
	this.modifiers = initialMethodBinding.modifiers;
	this.selector = initialMethodBinding.selector;
	this.returnType = initialMethodBinding.returnType;
	this.parameters = initialMethodBinding.parameters;
	this.thrownExceptions = initialMethodBinding.thrownExceptions;
	this.declaringClass = declaringClass;
	if (declaringClass!=null) declaringClass.storeAnnotationHolder(this, initialMethodBinding.declaringClass.retrieveAnnotationHolder(initialMethodBinding, true)); // New AspectJ Extension - check for null
}
/* Answer true if the argument types & the receiver's parameters have the same erasure
*/
public final boolean areParameterErasuresEqual(MethodBinding method) {
	TypeBinding[] args = method.parameters;
	if (this.parameters == args)
		return true;

	int length = this.parameters.length;
	if (length != args.length)
		return false;

	for (int i = 0; i < length; i++)
		if (TypeBinding.notEquals(this.parameters[i], args[i]) && TypeBinding.notEquals(this.parameters[i].erasure(), args[i].erasure()))
			return false;
	return true;
}
/*
 * Returns true if given parameters are compatible with this method parameters.
 * Callers to this method should first check that the number of TypeBindings
 * passed as argument matches this MethodBinding number of parameters
 */
public final boolean areParametersCompatibleWith(TypeBinding[] arguments) {
	int paramLength = this.parameters.length;
	int argLength = arguments.length;
	int lastIndex = argLength;
	if (isVarargs()) {
		lastIndex = paramLength - 1;
		if (paramLength == argLength) { // accept X[] but not X or X[][]
			TypeBinding varArgType = this.parameters[lastIndex]; // is an ArrayBinding by definition
			TypeBinding lastArgument = arguments[lastIndex];
			if (TypeBinding.notEquals(varArgType, lastArgument) && !lastArgument.isCompatibleWith(varArgType))
				return false;
		} else if (paramLength < argLength) { // all remainig argument types must be compatible with the elementsType of varArgType
			TypeBinding varArgType = ((ArrayBinding) this.parameters[lastIndex]).elementsType();
			for (int i = lastIndex; i < argLength; i++)
				if (TypeBinding.notEquals(varArgType, arguments[i]) && !arguments[i].isCompatibleWith(varArgType))
					return false;
		} else if (lastIndex != argLength) { // can call foo(int i, X ... x) with foo(1) but NOT foo();
			return false;
		}
		// now compare standard arguments from 0 to lastIndex
	}
	for (int i = 0; i < lastIndex; i++)
		if (TypeBinding.notEquals(this.parameters[i], arguments[i]) && !arguments[i].isCompatibleWith(this.parameters[i]))
			return false;
	return true;
}
/* Answer true if the argument types & the receiver's parameters are equal
*/
public final boolean areParametersEqual(MethodBinding method) {
	TypeBinding[] args = method.parameters;
	if (this.parameters == args)
		return true;

	int length = this.parameters.length;
	if (length != args.length)
		return false;

	for (int i = 0; i < length; i++)
		if (TypeBinding.notEquals(this.parameters[i], args[i]))
			return false;
	return true;
}

/* API
* Answer the receiver's binding type from Binding.BindingID.
*/

/* Answer true if the type variables have the same erasure
*/
public final boolean areTypeVariableErasuresEqual(MethodBinding method) {
	TypeVariableBinding[] vars = method.typeVariables;
	if (this.typeVariables == vars)
		return true;

	int length = this.typeVariables.length;
	if (length != vars.length)
		return false;

	for (int i = 0; i < length; i++)
		if (TypeBinding.notEquals(this.typeVariables[i], vars[i]) && TypeBinding.notEquals(this.typeVariables[i].erasure(), vars[i].erasure()))
			return false;
	return true;
}
public MethodBinding asRawMethod(LookupEnvironment env) {
	if (this.typeVariables == Binding.NO_TYPE_VARIABLES) return this;

	// substitute type arguments with raw types
	int length = this.typeVariables.length;
	TypeBinding[] arguments = new TypeBinding[length];
	for (int i = 0; i < length; i++) {
		TypeVariableBinding var = this.typeVariables[i];
		if (var.boundsCount() <= 1) {
			arguments[i] = env.convertToRawType(var.upperBound(), false /*do not force conversion of enclosing types*/);
		} else {
			// use an intersection type to retain full bound information if more than 1 bound
			TypeBinding[] itsSuperinterfaces = var.superInterfaces();
			int superLength = itsSuperinterfaces.length;
			TypeBinding rawFirstBound = null;
			TypeBinding[] rawOtherBounds = null;
			if (var.boundsCount() == superLength) {
				rawFirstBound = env.convertToRawType(itsSuperinterfaces[0], false);
				rawOtherBounds = new TypeBinding[superLength - 1];
				for (int s = 1; s < superLength; s++)
					rawOtherBounds[s - 1] = env.convertToRawType(itsSuperinterfaces[s], false);
			} else {
				rawFirstBound = env.convertToRawType(var.superclass(), false);
				rawOtherBounds = new TypeBinding[superLength];
				for (int s = 0; s < superLength; s++)
					rawOtherBounds[s] = env.convertToRawType(itsSuperinterfaces[s], false);
			}
			arguments[i] = env.createWildcard(null, 0, rawFirstBound, rawOtherBounds, org.eclipse.jdt.internal.compiler.ast.Wildcard.EXTENDS);
		}
	}
	return env.createParameterizedGenericMethod(this, arguments);
}
/* Answer true if the receiver is visible to the type provided by the scope.
* InvocationSite implements isSuperAccess() to provide additional information
* if the receiver is protected.
*
* NOTE: This method should ONLY be sent if the receiver is a constructor.
*
* NOTE: Cannot invoke this method with a compilation unit scope.
*/

//AspectJ Extension - made non-final
public boolean canBeSeenBy(InvocationSite invocationSite, Scope scope) {
	if (isPublic()) return true;

	// AspectJ Extension: was
	/*{
	SourceTypeBinding invocationType = scope.enclosingSourceType();
	if (TypeBinding.equalsEquals(invocationType, this.declaringClass)) return true;
	}*/// new:
    ReferenceBinding declaringType = original().declaringClass;  // AspectJ Extension - new local variable to hold the declaringType

	SourceTypeBinding invocationType = scope.invocationType();// AspectJ Extension - was enclosingSourceType();
	if (TypeBinding.equalsEquals(invocationType, declaringType)) return true; // AspectJ Extension - was declaringClass
	// Aspectj Extension end

	if (isProtected()) {
		// answer true if the receiver is in the same package as the invocationType
		if (invocationType.fPackage == declaringType.fPackage) return true; // AspectJ Extension - was == declaringClass.fPackage
		return invocationSite.isSuperAccess();
	}

	if (isPrivate()) {
		// answer true if the invocationType and the declaringClass have a common enclosingType
		// already know they are not the identical type
		ReferenceBinding outerInvocationType = invocationType;
		ReferenceBinding temp = outerInvocationType.enclosingType();
		while (temp != null) {
			outerInvocationType = temp;
			temp = temp.enclosingType();
		}

		ReferenceBinding outerDeclaringClass = (ReferenceBinding)declaringType.erasure(); // AspectJ Extension - changed declaringClass to declaringType
		temp = outerDeclaringClass.enclosingType();
		while (temp != null) {
			outerDeclaringClass = temp;
			temp = temp.enclosingType();
		}
		return TypeBinding.equalsEquals(outerInvocationType, outerDeclaringClass);
	}

	// isDefault()
	return invocationType.fPackage == declaringType.fPackage; // AspectJ Extension - changed declaringClass to declaringType
}

//AspectJ Extension
public MethodBinding getVisibleBinding(TypeBinding receiverType, InvocationSite invocationSite, Scope scope) {
	if (canBeSeenBy(receiverType, invocationSite, scope)) return this;
	return findPrivilegedBinding(scope.invocationType(), invocationSite);
}

public MethodBinding getVisibleBinding(InvocationSite invocationSite, Scope scope) {
	if (canBeSeenBy(invocationSite, scope)) return this;
	return findPrivilegedBinding(scope.invocationType(),invocationSite);
}


public MethodBinding findPrivilegedBinding(SourceTypeBinding invocationType, InvocationSite location) {
	if (Scope.findPrivilegedHandler(invocationType) != null) {
		ASTNode forLocation = null;
		if (location instanceof ASTNode) {
			forLocation = (ASTNode)location;
		}
		return Scope.findPrivilegedHandler(invocationType).getPrivilegedAccessMethod(this, forLocation); //notePrivilegedTypeAccess(this, null);
	} else {
		return null;
	}
}
//End AspectJ Extension

public final boolean canBeSeenBy(PackageBinding invocationPackage) {
	if (isPublic()) return true;
	if (isPrivate()) return false;

	// isProtected() or isDefault()
	return invocationPackage == this.declaringClass.getPackage();
}

/* Answer true if the receiver is visible to the type provided by the scope.
* InvocationSite implements isSuperAccess() to provide additional information
* if the receiver is protected.
*
* NOTE: Cannot invoke this method with a compilation unit scope.
*/
//AspectJ Extension - made non-final
public boolean canBeSeenBy(TypeBinding receiverType, InvocationSite invocationSite, Scope scope) {

	SourceTypeBinding invocationType = scope.invocationType(); // AspectJ Extension - was scope.enclosingSourceType()

	if (this.declaringClass.isInterface() && isStatic()) {
		// Static interface methods can be explicitly invoked only through the type reference of the declaring interface or implicitly in the interface itself or via static import.
		if (scope.compilerOptions().sourceLevel < ClassFileConstants.JDK1_8)
			return false;
		if ((invocationSite.isTypeAccess() || invocationSite.receiverIsImplicitThis()) && TypeBinding.equalsEquals(receiverType, this.declaringClass))
			return true;
		return false;
	}
	
	if (isPublic()) return true;
	

	if (TypeBinding.equalsEquals(invocationType, this.declaringClass) && TypeBinding.equalsEquals(invocationType, receiverType)) return true;

	if (invocationType == null) // static import call
		return !isPrivate() && scope.getCurrentPackage() == this.declaringClass.fPackage;

	if (isProtected()) {
		// answer true if the invocationType is the declaringClass or they are in the same package
		// OR the invocationType is a subclass of the declaringClass
		//    AND the receiverType is the invocationType or its subclass
		//    OR the method is a static method accessed directly through a type
		//    OR previous assertions are true for one of the enclosing type
		if (TypeBinding.equalsEquals(invocationType, this.declaringClass)) return true;
		if (invocationType.fPackage == this.declaringClass.fPackage) return true;

		//	AspectJ Extension
		// replaced this one line:
        // ReferenceBinding currentType = invocationType;
        // with:
		// for protected we need to check based on the type of this
		ReferenceBinding currentType = scope.enclosingSourceType(); //invocationType();// NewNew AspectJ Extension - was enclosingSourceType();
		// MUST be in the same package as the invocationType though... (pr 71723)
		if (TypeBinding.notEquals(invocationType,currentType)) {
		    // this MUST be an ITD
		    if (invocationType.fPackage != currentType.fPackage) return false;
		}
		//	End AspectJ Extension
		TypeBinding receiverErasure = receiverType.erasure();
		ReferenceBinding declaringErasure = (ReferenceBinding) this.declaringClass.erasure();
		int depth = 0;
		do {
			if (currentType.findSuperTypeOriginatingFrom(declaringErasure) != null) {
				if (invocationSite.isSuperAccess())
					return true;
				// receiverType can be an array binding in one case... see if you can change it
				if (receiverType instanceof ArrayBinding)
					return false;
				if (isStatic()) {
					if (depth > 0) invocationSite.setDepth(depth);
					return true; // see 1FMEPDL - return invocationSite.isTypeAccess();
				}
				if (TypeBinding.equalsEquals(currentType, receiverErasure) || receiverErasure.findSuperTypeOriginatingFrom(currentType) != null) {
					if (depth > 0) invocationSite.setDepth(depth);
					return true;
				}
			}
			depth++;
			currentType = currentType.enclosingType();
		} while (currentType != null);
		return false;
	}

	if (isPrivate()) {
		// answer true if the receiverType is the declaringClass
		// AND the invocationType and the declaringClass have a common enclosingType
		receiverCheck: {
			if (TypeBinding.notEquals(receiverType, this.declaringClass)) {
				// special tolerance for type variable direct bounds, but only if compliance <= 1.6, see: https://bugs.eclipse.org/bugs/show_bug.cgi?id=334622
				if (scope.compilerOptions().complianceLevel <= ClassFileConstants.JDK1_6 && receiverType.isTypeVariable() && ((TypeVariableBinding) receiverType).isErasureBoundTo(this.declaringClass.erasure()))
					break receiverCheck;
				return false;
			}
		}

		if (TypeBinding.notEquals(invocationType, this.declaringClass)) {
			ReferenceBinding outerInvocationType = invocationType;
			ReferenceBinding temp = outerInvocationType.enclosingType();
			while (temp != null) {
				outerInvocationType = temp;
				temp = temp.enclosingType();
			}

			ReferenceBinding outerDeclaringClass = (ReferenceBinding)this.declaringClass.erasure();
			temp = outerDeclaringClass.enclosingType();
			while (temp != null) {
				outerDeclaringClass = temp;
				temp = temp.enclosingType();
			}
			if (TypeBinding.notEquals(outerInvocationType, outerDeclaringClass)) return false;
		}
		return true;
	}

	// isDefault()
	PackageBinding declaringPackage = this.declaringClass.fPackage;
	if (invocationType.fPackage != declaringPackage) return false;

	// receiverType can be an array binding in one case... see if you can change it
	if (receiverType instanceof ArrayBinding)
		return false;
	TypeBinding originalDeclaringClass = this.declaringClass.original();
	ReferenceBinding currentType = (ReferenceBinding) (receiverType);
	do {
		if (currentType.isCapture()) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=285002
			if (TypeBinding.equalsEquals(originalDeclaringClass, currentType.erasure().original())) return true;
		} else {
			if (TypeBinding.equalsEquals(originalDeclaringClass, currentType.original())) return true;
		}
		PackageBinding currentPackage = currentType.fPackage;
		// package could be null for wildcards/intersection types, ignore and recurse in superclass
		if (currentPackage != null && currentPackage != declaringPackage) return false;
	} while ((currentType = currentType.superclass()) != null);
	return false;
}

public List collectMissingTypes(List missingTypes) {
	if ((this.tagBits & TagBits.HasMissingType) != 0) {
		missingTypes = this.returnType.collectMissingTypes(missingTypes);
		for (int i = 0, max = this.parameters.length; i < max; i++) {
			missingTypes = this.parameters[i].collectMissingTypes(missingTypes);
		}
		for (int i = 0, max = this.thrownExceptions.length; i < max; i++) {
			missingTypes = this.thrownExceptions[i].collectMissingTypes(missingTypes);
		}
		for (int i = 0, max = this.typeVariables.length; i < max; i++) {
			TypeVariableBinding variable = this.typeVariables[i];
			missingTypes = variable.superclass().collectMissingTypes(missingTypes);
			ReferenceBinding[] interfaces = variable.superInterfaces();
			for (int j = 0, length = interfaces.length; j < length; j++) {
				missingTypes = interfaces[j].collectMissingTypes(missingTypes);
			}
		}
	}
	return missingTypes;
}

MethodBinding computeSubstitutedMethod(MethodBinding method, LookupEnvironment env) {
	int length = this.typeVariables.length;
	TypeVariableBinding[] vars = method.typeVariables;
	if (length != vars.length)
		return null;

	// must substitute to detect cases like:
	//   <T1 extends X<T1>> void dup() {}
	//   <T2 extends X<T2>> Object dup() {return null;}
	ParameterizedGenericMethodBinding substitute =
		env.createParameterizedGenericMethod(method, this.typeVariables);
	for (int i = 0; i < length; i++)
		if (!this.typeVariables[i].isInterchangeableWith(vars[i], substitute))
			return null;
	return substitute;
}

/*
 * declaringUniqueKey dot selector genericSignature
 * p.X { <T> void bar(X<T> t) } --> Lp/X;.bar<T:Ljava/lang/Object;>(LX<TT;>;)V
 */
public char[] computeUniqueKey(boolean isLeaf) {
	// declaring class
	char[] declaringKey = this.declaringClass.computeUniqueKey(false/*not a leaf*/);
	int declaringLength = declaringKey.length;

	// selector
	int selectorLength = this.selector == TypeConstants.INIT ? 0 : this.selector.length;

	// generic signature
	char[] sig = genericSignature();
	boolean isGeneric = sig != null;
	if (!isGeneric) sig = signature();
	int signatureLength = sig.length;

	// thrown exceptions
	int thrownExceptionsLength = this.thrownExceptions.length;
	int thrownExceptionsSignatureLength = 0;
	char[][] thrownExceptionsSignatures = null;
	boolean addThrownExceptions = thrownExceptionsLength > 0 && (!isGeneric || CharOperation.lastIndexOf('^', sig) < 0);
	if (addThrownExceptions) {
		thrownExceptionsSignatures = new char[thrownExceptionsLength][];
		for (int i = 0; i < thrownExceptionsLength; i++) {
			if (this.thrownExceptions[i] != null) {
				thrownExceptionsSignatures[i] = this.thrownExceptions[i].signature();
				thrownExceptionsSignatureLength += thrownExceptionsSignatures[i].length + 1;	// add one char for separator
			}
		}
	}

	char[] uniqueKey = new char[declaringLength + 1 + selectorLength + signatureLength + thrownExceptionsSignatureLength];
	int index = 0;
	System.arraycopy(declaringKey, 0, uniqueKey, index, declaringLength);
	index = declaringLength;
	uniqueKey[index++] = '.';
	System.arraycopy(this.selector, 0, uniqueKey, index, selectorLength);
	index += selectorLength;
	System.arraycopy(sig, 0, uniqueKey, index, signatureLength);
	if (thrownExceptionsSignatureLength > 0) {
		index += signatureLength;
		for (int i = 0; i < thrownExceptionsLength; i++) {
			char[] thrownExceptionSignature = thrownExceptionsSignatures[i];
			if (thrownExceptionSignature != null) {
				uniqueKey[index++] = '|';
				int length = thrownExceptionSignature.length;
				System.arraycopy(thrownExceptionSignature, 0, uniqueKey, index, length);
				index += length;
			}
		}
	}
	return uniqueKey;
}

/* Answer the receiver's constant pool name.
*
* <init> for constructors
* <clinit> for clinit methods
* or the source name of the method
*/
public final char[] constantPoolName() {
	return this.selector;
}

/**
 * After method verifier has finished, fill in missing @NonNull specification from the applicable default.
 */
protected void fillInDefaultNonNullness(AbstractMethodDeclaration sourceMethod) {
	if (this.parameterNonNullness == null)
		this.parameterNonNullness = new Boolean[this.parameters.length];
	boolean added = false;
	int length = this.parameterNonNullness.length;
	for (int i = 0; i < length; i++) {
		if (this.parameters[i].isBaseType())
			continue;
		if (this.parameterNonNullness[i] == null) {
			added = true;
			this.parameterNonNullness[i] = Boolean.TRUE;
			if (sourceMethod != null) {
				sourceMethod.arguments[i].binding.tagBits |= TagBits.AnnotationNonNull;
			}
		} else if (sourceMethod != null && this.parameterNonNullness[i].booleanValue()) {
			sourceMethod.scope.problemReporter().nullAnnotationIsRedundant(sourceMethod, i);
		}
	}
	if (added)
		this.tagBits |= TagBits.HasParameterAnnotations;
	if (   this.returnType != null
		&& !this.returnType.isBaseType()
		&& (this.tagBits & TagBits.AnnotationNullMASK) == 0)
	{
		this.tagBits |= TagBits.AnnotationNonNull;
	} else if (sourceMethod != null && (this.tagBits & TagBits.AnnotationNonNull) != 0) {
		sourceMethod.scope.problemReporter().nullAnnotationIsRedundant(sourceMethod, -1/*signifies method return*/);
	}
}

//pre: null annotation analysis is enabled
protected void fillInDefaultNonNullness18(AbstractMethodDeclaration sourceMethod, LookupEnvironment env) {
	if (hasNonNullDefaultFor(DefaultLocationParameter, true)) {
		boolean added = false;
		int length = this.parameters.length;
		for (int i = 0; i < length; i++) {
			TypeBinding parameter = this.parameters[i];
			if (!parameter.acceptsNonNullDefault())
				continue;
			long existing = parameter.tagBits & TagBits.AnnotationNullMASK;
			if (existing == 0L) {
				added = true;
				if (!parameter.isBaseType()) {
					this.parameters[i] = env.createAnnotatedType(parameter, new AnnotationBinding[]{env.getNonNullAnnotation()});
					if (sourceMethod != null)
						sourceMethod.arguments[i].binding.type = this.parameters[i];
				}
			} else if (sourceMethod != null && (parameter.tagBits & TagBits.AnnotationNonNull) != 0
							&& sourceMethod.arguments[i].hasNullTypeAnnotation(AnnotationPosition.MAIN_TYPE)) {
				sourceMethod.scope.problemReporter().nullAnnotationIsRedundant(sourceMethod, i);
			}
		}
		if (added)
			this.tagBits |= TagBits.HasParameterAnnotations;
	}
	if (this.returnType != null && hasNonNullDefaultFor(DefaultLocationReturnType, true) && this.returnType.acceptsNonNullDefault()) {
		if ((this.returnType.tagBits & TagBits.AnnotationNullMASK) == 0) {
			this.returnType = env.createAnnotatedType(this.returnType, new AnnotationBinding[]{env.getNonNullAnnotation()});
		} else if (sourceMethod instanceof MethodDeclaration && (this.returnType.tagBits & TagBits.AnnotationNonNull) != 0 
						&& ((MethodDeclaration)sourceMethod).hasNullTypeAnnotation(AnnotationPosition.MAIN_TYPE)) {
			sourceMethod.scope.problemReporter().nullAnnotationIsRedundant(sourceMethod, -1/*signifies method return*/);
		}
	}
}

public MethodBinding findOriginalInheritedMethod(MethodBinding inheritedMethod) {
	MethodBinding inheritedOriginal = inheritedMethod.original();
	TypeBinding superType = this.declaringClass.findSuperTypeOriginatingFrom(inheritedOriginal.declaringClass);
	if (superType == null || !(superType instanceof ReferenceBinding)) return null;

	if (TypeBinding.notEquals(inheritedOriginal.declaringClass, superType)) {
		// must find inherited method with the same substituted variables
		MethodBinding[] superMethods = ((ReferenceBinding) superType).getMethods(inheritedOriginal.selector, inheritedOriginal.parameters.length);
		for (int m = 0, l = superMethods.length; m < l; m++)
			if (superMethods[m].original() == inheritedOriginal)
				return superMethods[m];
	}
	return inheritedOriginal;
}

/**
 * <pre>
 *<typeParam1 ... typeParamM>(param1 ... paramN)returnType thrownException1 ... thrownExceptionP
 * T foo(T t) throws X<T>   --->   (TT;)TT;LX<TT;>;
 * void bar(X<T> t)   -->   (LX<TT;>;)V
 * <T> void bar(X<T> t)   -->  <T:Ljava.lang.Object;>(LX<TT;>;)V
 * </pre>
 */
public char[] genericSignature() {
	if ((this.modifiers & ExtraCompilerModifiers.AccGenericSignature) == 0) return null;
	StringBuffer sig = new StringBuffer(10);
	if (this.typeVariables != Binding.NO_TYPE_VARIABLES) {
		sig.append('<');
		for (int i = 0, length = this.typeVariables.length; i < length; i++) {
			sig.append(this.typeVariables[i].genericSignature());
		}
		sig.append('>');
	}
	sig.append('(');
	for (int i = 0, length = this.parameters.length; i < length; i++) {
		sig.append(this.parameters[i].genericTypeSignature());
	}
	sig.append(')');
	if (this.returnType != null)
		sig.append(this.returnType.genericTypeSignature());

	// only append thrown exceptions if any is generic/parameterized
	boolean needExceptionSignatures = false;
	int length = this.thrownExceptions.length;
	for (int i = 0; i < length; i++) {
		if((this.thrownExceptions[i].modifiers & ExtraCompilerModifiers.AccGenericSignature) != 0) {
			needExceptionSignatures = true;
			break;
		}
	}
	if (needExceptionSignatures) {
		for (int i = 0; i < length; i++) {
			sig.append('^');
			sig.append(this.thrownExceptions[i].genericTypeSignature());
		}
	}
	int sigLength = sig.length();
	char[] genericSignature = new char[sigLength];
	sig.getChars(0, sigLength, genericSignature, 0);
	return genericSignature;
}

public final int getAccessFlags() {
	return this.modifiers & (ExtraCompilerModifiers.AccJustFlag | ExtraCompilerModifiers.AccDefaultMethod);
}

public AnnotationBinding[] getAnnotations() {
	MethodBinding originalMethod = original();
	return originalMethod.declaringClass.retrieveAnnotations(originalMethod);
}

/**
 * Compute the tagbits for standard annotations. For source types, these could require
 * lazily resolving corresponding annotation nodes, in case of forward references.
 * @see org.eclipse.jdt.internal.compiler.lookup.Binding#getAnnotationTagBits()
 */
public long getAnnotationTagBits() {
	MethodBinding originalMethod = original();
	if ((originalMethod.tagBits & TagBits.AnnotationResolved) == 0 && originalMethod.declaringClass instanceof SourceTypeBinding) {
		ClassScope scope = ((SourceTypeBinding) originalMethod.declaringClass).scope;
		if (scope != null) {
			TypeDeclaration typeDecl = scope.referenceContext;
			AbstractMethodDeclaration methodDecl = typeDecl.declarationOf(originalMethod);
			if (methodDecl != null)
				ASTNode.resolveAnnotations(methodDecl.scope, methodDecl.annotations, originalMethod);
			CompilerOptions options = scope.compilerOptions();
			if (options.isAnnotationBasedNullAnalysisEnabled) {
				boolean usesNullTypeAnnotations = scope.environment().usesNullTypeAnnotations();
				long nullDefaultBits = usesNullTypeAnnotations ? this.defaultNullness
						: this.tagBits & (TagBits.AnnotationNonNullByDefault|TagBits.AnnotationNullUnspecifiedByDefault);
				if (nullDefaultBits != 0 && this.declaringClass instanceof SourceTypeBinding) {
					SourceTypeBinding declaringSourceType = (SourceTypeBinding) this.declaringClass;
					if (declaringSourceType.checkRedundantNullnessDefaultOne(methodDecl, methodDecl.annotations, nullDefaultBits, usesNullTypeAnnotations)) {
						declaringSourceType.checkRedundantNullnessDefaultRecurse(methodDecl, methodDecl.annotations, nullDefaultBits, usesNullTypeAnnotations);
					}
				}
			}
		}
	}
	return originalMethod.tagBits;
}

/**
 * @return the default value for this annotation method or <code>null</code> if there is no default value
 */
public Object getDefaultValue() {
	MethodBinding originalMethod = original();
	if ((originalMethod.tagBits & TagBits.DefaultValueResolved) == 0) {
		//The method has not been resolved nor has its class been resolved.
		//It can only be from a source type within compilation units to process.
		if (originalMethod.declaringClass instanceof SourceTypeBinding) {
			SourceTypeBinding sourceType = (SourceTypeBinding) originalMethod.declaringClass;
			if (sourceType.scope != null) {
				AbstractMethodDeclaration methodDeclaration = originalMethod.sourceMethod();
				if (methodDeclaration != null && methodDeclaration.isAnnotationMethod()) {
					methodDeclaration.resolve(sourceType.scope);
				}
			}
		}
		originalMethod.tagBits |= TagBits.DefaultValueResolved;
	}
	AnnotationHolder holder = originalMethod.declaringClass.retrieveAnnotationHolder(originalMethod, true);
	return holder == null ? null : holder.getDefaultValue();
}

/**
 * @return the annotations for each of the method parameters or <code>null></code>
 * 	if there's no parameter or no annotation at all.
 */
public AnnotationBinding[][] getParameterAnnotations() {
	int length;
	if ((length = this.parameters.length) == 0) {
		return null;
	}
	MethodBinding originalMethod = original();
	AnnotationHolder holder = originalMethod.declaringClass.retrieveAnnotationHolder(originalMethod, true);
	AnnotationBinding[][] allParameterAnnotations = holder == null ? null : holder.getParameterAnnotations();
	if (allParameterAnnotations == null && (this.tagBits & TagBits.HasParameterAnnotations) != 0) {
		allParameterAnnotations = new AnnotationBinding[length][];
		// forward reference to method, where param annotations have not yet been associated to method
		if (this.declaringClass instanceof SourceTypeBinding) {
			SourceTypeBinding sourceType = (SourceTypeBinding) this.declaringClass;
			if (sourceType.scope != null) {
				AbstractMethodDeclaration methodDecl = sourceType.scope.referenceType().declarationOf(originalMethod);
				for (int i = 0; i < length; i++) {
					Argument argument = methodDecl.arguments[i];
					if (argument.annotations != null) {
						ASTNode.resolveAnnotations(methodDecl.scope, argument.annotations, argument.binding);
						allParameterAnnotations[i] = argument.binding.getAnnotations();
					} else {
						allParameterAnnotations[i] = Binding.NO_ANNOTATIONS;
					}
				}
			} else {
				for (int i = 0; i < length; i++) {
					allParameterAnnotations[i] = Binding.NO_ANNOTATIONS;
				}
			}
		} else {
			for (int i = 0; i < length; i++) {
				allParameterAnnotations[i] = Binding.NO_ANNOTATIONS;
			}
		}
		setParameterAnnotations(allParameterAnnotations);
	}
	return allParameterAnnotations;
}

public TypeVariableBinding getTypeVariable(char[] variableName) {
	for (int i = this.typeVariables.length; --i >= 0;)
		if (CharOperation.equals(this.typeVariables[i].sourceName, variableName))
			return this.typeVariables[i];
	return null;
}

/**
 * Returns true if method got substituted parameter types
 * (see ParameterizedMethodBinding)
 */
public boolean hasSubstitutedParameters() {
	return false;
}

/* Answer true if the return type got substituted.
 */
public boolean hasSubstitutedReturnType() {
	return false;
}

/* Answer true if the receiver is an abstract method
*/
public final boolean isAbstract() {
	return (this.modifiers & ClassFileConstants.AccAbstract) != 0;
}

/* Answer true if the receiver is a bridge method
*/
public final boolean isBridge() {
	return (this.modifiers & ClassFileConstants.AccBridge) != 0;
}

/* Answer true if the receiver is a constructor
*/
public final boolean isConstructor() {
	return this.selector == TypeConstants.INIT;
}

/* Answer true if the receiver has default visibility
*/
public final boolean isDefault() {
	return !isPublic() && !isProtected() && !isPrivate();
}

/* Answer true if the receiver is a system generated default abstract method
*/
public final boolean isDefaultAbstract() {
	return (this.modifiers & ExtraCompilerModifiers.AccDefaultAbstract) != 0;
}

/* Answer true if the receiver is a default method (Java 8 feature) */
public boolean isDefaultMethod() {
	return (this.modifiers & ExtraCompilerModifiers.AccDefaultMethod) != 0;
}

/* Answer true if the receiver is a deprecated method
*/
public final boolean isDeprecated() {
	return (this.modifiers & ClassFileConstants.AccDeprecated) != 0;
}

/* Answer true if the receiver is final and cannot be overridden
*/
public boolean isFinal() { // AspectJ Extension, made non-final
	return (this.modifiers & ClassFileConstants.AccFinal) != 0;
}

/* Answer true if the receiver is implementing another method
 * in other words, it is overriding and concrete, and overriden method is abstract
 * Only set for source methods
*/
public final boolean isImplementing() {
	return (this.modifiers & ExtraCompilerModifiers.AccImplementing) != 0;
}

/*
 * Answer true if the receiver is a "public static void main(String[])" method
 */
public final boolean isMain() {
	if (this.selector.length == 4 && CharOperation.equals(this.selector, TypeConstants.MAIN)
			&& ((this.modifiers & (ClassFileConstants.AccPublic | ClassFileConstants.AccStatic)) != 0)
			&& TypeBinding.VOID == this.returnType
			&& this.parameters.length == 1) {
		TypeBinding paramType = this.parameters[0];
		if (paramType.dimensions() == 1 && paramType.leafComponentType().id == TypeIds.T_JavaLangString) {
			return true;
		}
	}
	return false;
}

/* Answer true if the receiver is a native method
*/
public final boolean isNative() {
	return (this.modifiers & ClassFileConstants.AccNative) != 0;
}

/* Answer true if the receiver is overriding another method
 * Only set for source methods
*/
public final boolean isOverriding() {
	return (this.modifiers & ExtraCompilerModifiers.AccOverriding) != 0;
}
/* Answer true if the receiver has private visibility
*/
public final boolean isPrivate() {
	return (this.modifiers & ClassFileConstants.AccPrivate) != 0;
}

/* Answer true if the receiver has private visibility or if any of its enclosing types do.
*/
public final boolean isOrEnclosedByPrivateType() {
	if ((this.modifiers & ClassFileConstants.AccPrivate) != 0)
		return true;
	return this.declaringClass != null && this.declaringClass.isOrEnclosedByPrivateType();
}

/* Answer true if the receiver has protected visibility
*/
public final boolean isProtected() {
	return (this.modifiers & ClassFileConstants.AccProtected) != 0;
}

/* Answer true if the receiver has public visibility
*/
public final boolean isPublic() {
	return (this.modifiers & ClassFileConstants.AccPublic) != 0;
}

/* Answer true if the receiver is a static method
*/
public final boolean isStatic() {
	return (this.modifiers & ClassFileConstants.AccStatic) != 0;
}

/* Answer true if all float operations must adher to IEEE 754 float/double rules
*/
public final boolean isStrictfp() {
	return (this.modifiers & ClassFileConstants.AccStrictfp) != 0;
}

/* Answer true if the receiver is a synchronized method
*/
public final boolean isSynchronized() {
	return (this.modifiers & ClassFileConstants.AccSynchronized) != 0;
}

/* Answer true if the receiver has public visibility
*/
public final boolean isSynthetic() {
	return (this.modifiers & ClassFileConstants.AccSynthetic) != 0;
}

/* Answer true if the receiver has private visibility and is used locally
*/
public final boolean isUsed() {
	return (this.modifiers & ExtraCompilerModifiers.AccLocallyUsed) != 0;
}

/* Answer true if the receiver method has varargs
*/
public boolean isVarargs() {
	return (this.modifiers & ClassFileConstants.AccVarargs) != 0;
}
public boolean isPolymorphic() {
	return false;
}
/* Answer true if the receiver's declaring type is deprecated (or any of its enclosing types)
*/
public final boolean isViewedAsDeprecated() {
	return (this.modifiers & (ClassFileConstants.AccDeprecated | ExtraCompilerModifiers.AccDeprecatedImplicitly)) != 0;
}

public final int kind() {
	return Binding.METHOD;
}
/* Answer true if the receiver is visible to the invocationPackage.
*/

/**
 * Returns the original method (as opposed to parameterized/polymorphic instances)
 */
public MethodBinding original() {
	return this;
}

/**
 * Strips one level of parameterization, so if both class & method are parameterized,
 * leave the class parameters in place.
 */
public MethodBinding shallowOriginal() {
	return original();
}

public MethodBinding genericMethod() {
	return this;
}

public char[] readableName() /* foo(int, Thread) */ {
	StringBuffer buffer = new StringBuffer(this.parameters.length + 1 * 20);
	if (isConstructor())
		buffer.append(this.declaringClass.sourceName());
	else
		buffer.append(this.selector);
	buffer.append('(');
	if (this.parameters != Binding.NO_PARAMETERS) {
		for (int i = 0, length = this.parameters.length; i < length; i++) {
			if (i > 0)
				buffer.append(", "); //$NON-NLS-1$
			buffer.append(this.parameters[i].sourceName());
		}
	}
	buffer.append(')');
	return buffer.toString().toCharArray();
}
public void setAnnotations(AnnotationBinding[] annotations) {
	this.declaringClass.storeAnnotations(this, annotations);
}
public void setAnnotations(AnnotationBinding[] annotations, AnnotationBinding[][] parameterAnnotations, Object defaultValue, LookupEnvironment optionalEnv) {
	this.declaringClass.storeAnnotationHolder(this,  AnnotationHolder.storeAnnotations(annotations, parameterAnnotations, defaultValue, optionalEnv));
}
public void setDefaultValue(Object defaultValue) {
	MethodBinding originalMethod = original();
	originalMethod.tagBits |= TagBits.DefaultValueResolved;

	AnnotationHolder holder = this.declaringClass.retrieveAnnotationHolder(this, false);
	if (holder == null)
		setAnnotations(null, null, defaultValue, null);
	else
		setAnnotations(holder.getAnnotations(), holder.getParameterAnnotations(), defaultValue, null);
}
public void setParameterAnnotations(AnnotationBinding[][] parameterAnnotations) {
	AnnotationHolder holder = this.declaringClass.retrieveAnnotationHolder(this, false);
	if (holder == null)
		setAnnotations(null, parameterAnnotations, null, null);
	else
		setAnnotations(holder.getAnnotations(), parameterAnnotations, holder.getDefaultValue(), null);
}
protected final void setSelector(char[] selector) {
	this.selector = selector;
	this.signature = null;
}

/**
 * @see org.eclipse.jdt.internal.compiler.lookup.Binding#shortReadableName()
 */
public char[] shortReadableName() {
	StringBuffer buffer = new StringBuffer(this.parameters.length + 1 * 20);
	if (isConstructor())
		buffer.append(this.declaringClass.shortReadableName());
	else
		buffer.append(this.selector);
	buffer.append('(');
	if (this.parameters != Binding.NO_PARAMETERS) {
		for (int i = 0, length = this.parameters.length; i < length; i++) {
			if (i > 0)
				buffer.append(", "); //$NON-NLS-1$
			buffer.append(this.parameters[i].shortReadableName());
		}
	}
	buffer.append(')');
	int nameLength = buffer.length();
	char[] shortReadableName = new char[nameLength];
	buffer.getChars(0, nameLength, shortReadableName, 0);
	return shortReadableName;
}

/* Answer the receiver's signature.
*
* NOTE: This method should only be used during/after code gen.
* The signature is cached so if the signature of the return type or any parameter
* type changes, the cached state is invalid.
*/
public final char[] signature() /* (ILjava/lang/Thread;)Ljava/lang/Object; */ {
	if (this.signature != null)
		return this.signature;

	StringBuffer buffer = new StringBuffer(this.parameters.length + 1 * 20);
	buffer.append('(');

	TypeBinding[] targetParameters = this.parameters;
	boolean isConstructor = isConstructor();
	if (isConstructor && this.declaringClass.isEnum()) { // insert String name,int ordinal
		buffer.append(ConstantPool.JavaLangStringSignature);
		buffer.append(TypeBinding.INT.signature());
	}
	boolean needSynthetics = isConstructor && this.declaringClass.isNestedType();
	if (needSynthetics) {
		// take into account the synthetic argument type signatures as well
		ReferenceBinding[] syntheticArgumentTypes = this.declaringClass.syntheticEnclosingInstanceTypes();
		if (syntheticArgumentTypes != null) {
			for (int i = 0, count = syntheticArgumentTypes.length; i < count; i++) {
				buffer.append(syntheticArgumentTypes[i].signature());
			}
		}

		if (this instanceof SyntheticMethodBinding) {
			targetParameters = ((SyntheticMethodBinding)this).targetMethod.parameters;
		}
	}

	if (targetParameters != Binding.NO_PARAMETERS) {
		for (int i = 0; i < targetParameters.length; i++) {
			buffer.append(targetParameters[i].signature());
		}
	}
	if (needSynthetics) {
		SyntheticArgumentBinding[] syntheticOuterArguments = this.declaringClass.syntheticOuterLocalVariables();
		int count = syntheticOuterArguments == null ? 0 : syntheticOuterArguments.length;
		for (int i = 0; i < count; i++) {
			buffer.append(syntheticOuterArguments[i].type.signature());
		}
		// move the extra padding arguments of the synthetic constructor invocation to the end
		for (int i = targetParameters.length, extraLength = this.parameters.length; i < extraLength; i++) {
			buffer.append(this.parameters[i].signature());
		}
	}
	buffer.append(')');
	if (this.returnType != null)
		buffer.append(this.returnType.signature());
	int nameLength = buffer.length();
	this.signature = new char[nameLength];
	buffer.getChars(0, nameLength, this.signature, 0);

	return this.signature;
}
/*
 * This method is used to record references to nested types inside the method signature.
 * This is the one that must be used during code generation.
 *
 * See https://bugs.eclipse.org/bugs/show_bug.cgi?id=171184
 */
public final char[] signature(ClassFile classFile) {
	if (this.signature != null) {
		if ((this.tagBits & TagBits.ContainsNestedTypeReferences) != 0) {
			// we need to record inner classes references
			boolean isConstructor = isConstructor();
			TypeBinding[] targetParameters = this.parameters;
			boolean needSynthetics = isConstructor && this.declaringClass.isNestedType();
			if (needSynthetics) {
				// take into account the synthetic argument type signatures as well
				ReferenceBinding[] syntheticArgumentTypes = this.declaringClass.syntheticEnclosingInstanceTypes();
				if (syntheticArgumentTypes != null) {
					for (int i = 0, count = syntheticArgumentTypes.length; i < count; i++) {
						ReferenceBinding syntheticArgumentType = syntheticArgumentTypes[i];
						if ((syntheticArgumentType.tagBits & TagBits.ContainsNestedTypeReferences) != 0) {
							Util.recordNestedType(classFile, syntheticArgumentType);
						}
					}
				}
				if (this instanceof SyntheticMethodBinding) {
					targetParameters = ((SyntheticMethodBinding)this).targetMethod.parameters;
				}
			}

			if (targetParameters != Binding.NO_PARAMETERS) {
				for (int i = 0, max = targetParameters.length; i < max; i++) {
					TypeBinding targetParameter = targetParameters[i];
					TypeBinding leafTargetParameterType = targetParameter.leafComponentType();
					if ((leafTargetParameterType.tagBits & TagBits.ContainsNestedTypeReferences) != 0) {
						Util.recordNestedType(classFile, leafTargetParameterType);
					}
				}
			}
			if (needSynthetics) {
				// move the extra padding arguments of the synthetic constructor invocation to the end
				for (int i = targetParameters.length, extraLength = this.parameters.length; i < extraLength; i++) {
					TypeBinding parameter = this.parameters[i];
					TypeBinding leafParameterType = parameter.leafComponentType();
					if ((leafParameterType.tagBits & TagBits.ContainsNestedTypeReferences) != 0) {
						Util.recordNestedType(classFile, leafParameterType);
					}
				}
			}
			if (this.returnType != null) {
				TypeBinding ret = this.returnType.leafComponentType();
				if ((ret.tagBits & TagBits.ContainsNestedTypeReferences) != 0) {
					Util.recordNestedType(classFile, ret);
				}
			}
		}
		return this.signature;
	}

	StringBuffer buffer = new StringBuffer((this.parameters.length + 1) * 20);
	buffer.append('(');

	TypeBinding[] targetParameters = this.parameters;
	boolean isConstructor = isConstructor();
	if (isConstructor && this.declaringClass.isEnum()) { // insert String name,int ordinal
		buffer.append(ConstantPool.JavaLangStringSignature);
		buffer.append(TypeBinding.INT.signature());
	}
	boolean needSynthetics = isConstructor && this.declaringClass.isNestedType();
	if (needSynthetics) {
		// take into account the synthetic argument type signatures as well
		ReferenceBinding[] syntheticArgumentTypes = this.declaringClass.syntheticEnclosingInstanceTypes();
		if (syntheticArgumentTypes != null) {
			for (int i = 0, count = syntheticArgumentTypes.length; i < count; i++) {
				ReferenceBinding syntheticArgumentType = syntheticArgumentTypes[i];
				if ((syntheticArgumentType.tagBits & TagBits.ContainsNestedTypeReferences) != 0) {
					this.tagBits |= TagBits.ContainsNestedTypeReferences;
					Util.recordNestedType(classFile, syntheticArgumentType);
				}
				buffer.append(syntheticArgumentType.signature());
			}
		}

		if (this instanceof SyntheticMethodBinding) {
			targetParameters = ((SyntheticMethodBinding)this).targetMethod.parameters;
		}
	}

	if (targetParameters != Binding.NO_PARAMETERS) {
		for (int i = 0, max = targetParameters.length; i < max; i++) {
			TypeBinding targetParameter = targetParameters[i];
			TypeBinding leafTargetParameterType = targetParameter.leafComponentType();
			if ((leafTargetParameterType.tagBits & TagBits.ContainsNestedTypeReferences) != 0) {
				this.tagBits |= TagBits.ContainsNestedTypeReferences;
				Util.recordNestedType(classFile, leafTargetParameterType);
			}
			buffer.append(targetParameter.signature());
		}
	}
	if (needSynthetics) {
		SyntheticArgumentBinding[] syntheticOuterArguments = this.declaringClass.syntheticOuterLocalVariables();
		int count = syntheticOuterArguments == null ? 0 : syntheticOuterArguments.length;
		for (int i = 0; i < count; i++) {
			buffer.append(syntheticOuterArguments[i].type.signature());
		}
		// move the extra padding arguments of the synthetic constructor invocation to the end
		for (int i = targetParameters.length, extraLength = this.parameters.length; i < extraLength; i++) {
			TypeBinding parameter = this.parameters[i];
			TypeBinding leafParameterType = parameter.leafComponentType();
			if ((leafParameterType.tagBits & TagBits.ContainsNestedTypeReferences) != 0) {
				this.tagBits |= TagBits.ContainsNestedTypeReferences;
				Util.recordNestedType(classFile, leafParameterType);
			}
			buffer.append(parameter.signature());
		}
	}
	buffer.append(')');
	if (this.returnType != null) {
		TypeBinding ret = this.returnType.leafComponentType();
		if ((ret.tagBits & TagBits.ContainsNestedTypeReferences) != 0) {
			this.tagBits |= TagBits.ContainsNestedTypeReferences;
			Util.recordNestedType(classFile, ret);
		}
		buffer.append(this.returnType.signature());
	}
	int nameLength = buffer.length();
	this.signature = new char[nameLength];
	buffer.getChars(0, nameLength, this.signature, 0);

	return this.signature;
}
public final int sourceEnd() {
	AbstractMethodDeclaration method = sourceMethod();
	if (method == null) {
		if (this.declaringClass instanceof SourceTypeBinding)
			return ((SourceTypeBinding) this.declaringClass).sourceEnd();
		return 0;
	}
	return method.sourceEnd;
}
public AbstractMethodDeclaration sourceMethod() {
	// AspectJ Extension
	// AspectJ has synthetic methods that do have a source rep (e.g. pointcuts)
	// TODO could do this through overriding? maybe if we did use a subtype, but not sure we do
	// TODO can't recognize via ajc$ because they might be annotation style 
	// old code:
//	if (isSynthetic()) {
//		return null;
//	}
	SourceTypeBinding sourceType;
	//	AspectJ Extension
	if (declaringClass instanceof BinaryTypeBinding) return null;
	//	End AspectJ Extension
	try {
		sourceType = (SourceTypeBinding) this.declaringClass;
	} catch (ClassCastException e) {
		return null;
	}

	// AspectJ Extension
	// guard due to pr154923 - an npe occurs that is probably disguising an underlying problem that will be reported properly
	if (sourceType.scope==null || sourceType.scope.referenceContext==null || sourceType.scope.referenceContext.methods==null) return null;
	// End AspectJ Extension
	AbstractMethodDeclaration[] methods = sourceType.scope != null ? sourceType.scope.referenceContext.methods : null;
	if (methods != null) {
		for (int i = methods.length; --i >= 0;)
			if (this == methods[i].binding)
				return methods[i];
	}
	return null;
}
public LambdaExpression sourceLambda() {
	return null;
}
public final int sourceStart() {
	AbstractMethodDeclaration method = sourceMethod();
	if (method == null) {
		// AspectJ Extension - add check to ensure not asking binary for positions (AJ462782)
		if (this.declaringClass instanceof SourceTypeBinding && !(this.declaringClass instanceof BinaryTypeBinding))
			return ((SourceTypeBinding) this.declaringClass).sourceStart();
		return 0;
	}
	return method.sourceStart;
}
    //AspectJ Extension	
	/**
	 * Subtypes can override this to return true if an access method should be
	 * used when referring to this method binding.  Currently used
	 * for AspectJ's inter-type method declarations.
	 */
	public boolean alwaysNeedsAccessMethod() { return false; }


	/**
	 * This will only be called if alwaysNeedsAccessMethod() returns true.
	 * In that case it should return the access method to be used.
	 */
	public MethodBinding getAccessMethod(boolean staticReference) {
		throw new RuntimeException("unimplemented");
	}
	//	End AspectJ Extension

/**
 * Returns the method to use during tiebreak (usually the method itself).
 * For generic method invocations, tiebreak needs to use generic method with erasure substitutes.
 */
public MethodBinding tiebreakMethod() {
	return this;
}
public String toString() {
	StringBuffer output = new StringBuffer(10);
	if ((this.modifiers & ExtraCompilerModifiers.AccUnresolved) != 0) {
		output.append("[unresolved] "); //$NON-NLS-1$
	}
	ASTNode.printModifiers(this.modifiers, output);
	output.append(this.returnType != null ? this.returnType.debugName() : "<no type>"); //$NON-NLS-1$
	output.append(" "); //$NON-NLS-1$
	output.append(this.selector != null ? new String(this.selector) : "<no selector>"); //$NON-NLS-1$
	output.append("("); //$NON-NLS-1$
	if (this.parameters != null) {
		if (this.parameters != Binding.NO_PARAMETERS) {
			for (int i = 0, length = this.parameters.length; i < length; i++) {
				if (i  > 0)
					output.append(", "); //$NON-NLS-1$
				output.append(this.parameters[i] != null ? this.parameters[i].debugName() : "<no argument type>"); //$NON-NLS-1$
			}
		}
	} else {
		output.append("<no argument types>"); //$NON-NLS-1$
	}
	output.append(") "); //$NON-NLS-1$

	if (this.thrownExceptions != null) {
		if (this.thrownExceptions != Binding.NO_EXCEPTIONS) {
			output.append("throws "); //$NON-NLS-1$
			for (int i = 0, length = this.thrownExceptions.length; i < length; i++) {
				if (i  > 0)
					output.append(", "); //$NON-NLS-1$
				output.append((this.thrownExceptions[i] != null) ? this.thrownExceptions[i].debugName() : "<no exception type>"); //$NON-NLS-1$
			}
		}
	} else {
		output.append("<no exception types>"); //$NON-NLS-1$
	}
	return output.toString();
}
public TypeVariableBinding[] typeVariables() {
	return this.typeVariables;
}
//pre: null annotation analysis is enabled
public boolean hasNonNullDefaultFor(int location, boolean useTypeAnnotations) {
	if ((this.modifiers & ExtraCompilerModifiers.AccIsDefaultConstructor) != 0)
		return false;
	if (useTypeAnnotations) {
		if (this.defaultNullness != 0)
			return (this.defaultNullness & location) != 0;
	} else {
		if ((this.tagBits & TagBits.AnnotationNonNullByDefault) != 0)
			return true;
		if ((this.tagBits & TagBits.AnnotationNullUnspecifiedByDefault) != 0)
			return false;
	}
	return this.declaringClass.hasNonNullDefaultFor(location, useTypeAnnotations);
}

public boolean redeclaresPublicObjectMethod(Scope scope) {
	ReferenceBinding javaLangObject = scope.getJavaLangObject();
	MethodBinding [] methods = javaLangObject.getMethods(this.selector);
	for (int i = 0, length = methods == null ? 0 : methods.length; i < length; i++) {
		final MethodBinding method = methods[i];
		if (!method.isPublic() || method.isStatic() || method.parameters.length != this.parameters.length) 
			continue;
		if (MethodVerifier.doesMethodOverride(this, method, scope.environment())) 
			return true;
	}
	return false;
}
public boolean isVoidMethod() {
	return this.returnType == TypeBinding.VOID;
}
}
