/*******************************************************************************
 * Copyright (c) 2000, 2019 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Fraunhofer FIRST - extended API and implementation
 *     Technical University Berlin - extended API and implementation
 *     Stephan Herrmann - Contribution for
 *								Bug 429813 - [1.8][dom ast] IMethodBinding#getJavaElement() should return IMethod for lambda
 *******************************************************************************/

package org.eclipse.jdt.core.dom;

import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
import org.eclipse.jdt.internal.compiler.lookup.ParameterizedGenericMethodBinding;
import org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
import org.eclipse.jdt.internal.compiler.lookup.TagBits;
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding;
import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
import org.eclipse.jdt.internal.core.JavaElement;
import org.eclipse.jdt.internal.core.util.Util;
import org.eclipse.objectteams.otdt.internal.core.compiler.model.MethodModel;

/**
 * Internal implementation of method bindings.
 */
class MethodBinding implements IMethodBinding {

	private static final int VALID_MODIFIERS = Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE |
//{ObjectTeams: callin:
		Modifier.OT_CALLIN |
// SH}
		Modifier.ABSTRACT | Modifier.STATIC | Modifier.FINAL | Modifier.SYNCHRONIZED | Modifier.NATIVE |
		Modifier.STRICTFP | Modifier.DEFAULT;
	private static final ITypeBinding[] NO_TYPE_BINDINGS = new ITypeBinding[0];
	static final IVariableBinding[] NO_VARIABLE_BINDINGS = new IVariableBinding[0];
	protected org.eclipse.jdt.internal.compiler.lookup.MethodBinding binding;
	protected BindingResolver resolver;
	private volatile ITypeBinding[] parameterTypes;
	private volatile ITypeBinding[] exceptionTypes;
	private volatile String name;
	private volatile ITypeBinding declaringClass;
	private volatile ITypeBinding returnType;
	private volatile String key;
	private volatile ITypeBinding[] typeParameters;
	private volatile ITypeBinding[] typeArguments;
	private volatile IAnnotationBinding[] annotations;
	private volatile IAnnotationBinding[][] parameterAnnotations;

	MethodBinding(BindingResolver resolver, org.eclipse.jdt.internal.compiler.lookup.MethodBinding binding) {
		this.resolver = resolver;
		this.binding = binding;
	}

	@Override
	public boolean isAnnotationMember() {
		return getDeclaringClass().isAnnotation();
	}

	/**
	 * @see IMethodBinding#isConstructor()
	 */
	@Override
	public boolean isConstructor() {
		return this.binding.isConstructor();
	}

	/**
	 * @see IMethodBinding#isDefaultConstructor()
	 * @since 3.0
	 */
	@Override
	public boolean isDefaultConstructor() {
		final ReferenceBinding declaringClassBinding = this.binding.declaringClass;
		if (declaringClassBinding.isRawType()) {
//{ObjectTeams: relax the cast to include half-raw dependent types:
/* orig:
			RawTypeBinding rawTypeBinding = (RawTypeBinding) declaringClassBinding;
  :giro */
			ParameterizedTypeBinding rawTypeBinding = (ParameterizedTypeBinding) declaringClassBinding;
// SH}
			if (rawTypeBinding.genericType().isBinaryBinding()) {
				return false;
			}
			return (this.binding.modifiers & ExtraCompilerModifiers.AccIsDefaultConstructor) != 0;
		}
		if (declaringClassBinding.isBinaryBinding()) {
			return false;
		}
		return (this.binding.modifiers & ExtraCompilerModifiers.AccIsDefaultConstructor) != 0;
	}

	/**
	 * @see IBinding#getName()
	 */
	@Override
	public String getName() {
		if (this.name == null) {
			if (this.binding.isConstructor()) {
				this.name = getDeclaringClass().getName();
			} else {
				this.name = new String(this.binding.selector);
			}
		}
		return this.name;
	}

	@Override
	public IAnnotationBinding[] getAnnotations() {
		if (this.annotations != null) {
			return this.annotations;
		}
		org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding[] internalAnnotations = this.binding.getAnnotations();
		return this.annotations = filterTypeAnnotations(internalAnnotations);
	}

	/**
	 * @see IMethodBinding#getDeclaringClass()
	 */
	@Override
	public ITypeBinding getDeclaringClass() {
		if (this.declaringClass == null) {
//{ObjectTeams: a role-ifc-method representing a one that is inherited from a non-role?
			if (this.binding.copyInheritanceSrc != null)
			{
				this.declaringClass = this.resolver.getTypeBinding(this.binding.copyInheritanceSrc.declaringClass);
				if (!this.declaringClass.isRole())
					return this.declaringClass;
			}
// SH}
			this.declaringClass = this.resolver.getTypeBinding(this.binding.declaringClass);
		}
		return this.declaringClass;
	}

	@Override
	public IBinding getDeclaringMember() {
		return null;
	}

	@Override
	public IAnnotationBinding[] getParameterAnnotations(int index) {
		if (getParameterTypes() == NO_TYPE_BINDINGS) {
			return AnnotationBinding.NoAnnotations;
		}
		if (this.parameterAnnotations != null) {
			return this.parameterAnnotations[index];
		}
		org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding[][] bindingAnnotations = this.binding.getParameterAnnotations();
		if (bindingAnnotations == null) return AnnotationBinding.NoAnnotations;

		int length = bindingAnnotations.length;
		IAnnotationBinding[][] domAnnotations = new IAnnotationBinding[length][];
		for (int i = 0; i < length; i++) {
			org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding[] paramBindingAnnotations = bindingAnnotations[i];
			int pLength = paramBindingAnnotations.length;
			domAnnotations[i] = new AnnotationBinding[pLength];
			for (int j=0; j<pLength; j++) {
				IAnnotationBinding domAnnotation = this.resolver.getAnnotationInstance(paramBindingAnnotations[j]);
				if (domAnnotation == null) {
					domAnnotations[i] = AnnotationBinding.NoAnnotations;
					break;
				}
				domAnnotations[i][j] = domAnnotation;
			}
		}
		this.parameterAnnotations = domAnnotations;

		return this.parameterAnnotations[index];
	}

	/**
	 * @see IMethodBinding#getParameterTypes()
	 */
	@Override
	public ITypeBinding[] getParameterTypes() {
		if (this.parameterTypes != null) {
			return this.parameterTypes;
		}
		org.eclipse.jdt.internal.compiler.lookup.TypeBinding[] parameters = this.binding.parameters;
//{ObjectTeams: retrench callin method:
		if ((this.getModifiers() & ExtraCompilerModifiers.AccCallin) != 0)
			parameters = this.binding.getMethodSignatureEnhancer().retrenchParameterTypes(parameters);
// SH}
		int length = parameters == null ? 0 : parameters.length;
		if (length == 0) {
			return this.parameterTypes = NO_TYPE_BINDINGS;
		} else {
			ITypeBinding[] paramTypes = new ITypeBinding[length];
			for (int i = 0; i < length; i++) {
				final TypeBinding parameterBinding = parameters[i];
				if (parameterBinding != null) {
					ITypeBinding typeBinding = this.resolver.getTypeBinding(parameterBinding);
					if (typeBinding == null) {
						return this.parameterTypes = NO_TYPE_BINDINGS;
					}
					paramTypes[i] = typeBinding;
				} else {
					// log error
					StringBuffer message = new StringBuffer("Report method binding where a parameter is null:\n");  //$NON-NLS-1$
					message.append(toString());
					Util.log(new IllegalArgumentException(), message.toString());
					// report no binding since one or more parameter has no binding
					return this.parameterTypes = NO_TYPE_BINDINGS;
				}
			}
			return this.parameterTypes = paramTypes;
		}
	}

	/**
	 * @see IMethodBinding#getDeclaredReceiverType()
	 */
	@Override
	public ITypeBinding getDeclaredReceiverType() {
		return this.resolver.getTypeBinding(this.binding.receiver);
	}
	/**
	 * @see IMethodBinding#getReturnType()
	 */
	@Override
	public ITypeBinding getReturnType() {
		if (this.returnType == null) {
//{ObjectTeams: retrench callin method:
		  if ((this.getModifiers() & ExtraCompilerModifiers.AccCallin) != 0) {
			TypeBinding realReturnType = MethodModel.getReturnType(this.binding);
			this.returnType = this.resolver.getTypeBinding(realReturnType);
		  } else
// SH}
			this.returnType = this.resolver.getTypeBinding(this.binding.returnType);
		}
		return this.returnType;
	}

	protected IAnnotationBinding[] filterTypeAnnotations(org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding[] internalAnnotations) {
		int length = internalAnnotations == null ? 0 : internalAnnotations.length;
		if (length != 0) {
			IAnnotationBinding[] tempAnnotations = new IAnnotationBinding[length];
			int convertedAnnotationCount = 0;
			final boolean isConstructor = this.isConstructor();
			for (int i = 0; i < length; i++) {
				org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding internalAnnotation = internalAnnotations[i];
				final ReferenceBinding annotationType = internalAnnotation.getAnnotationType();
				long metaTagBits = annotationType.getAnnotationTagBits();

				// Exclude all other targets including TYPE_USE, even though TYPE_USE is accepted.
				if (isConstructor && (metaTagBits & TagBits.AnnotationForConstructor) == 0 &&
						((metaTagBits & TagBits.AnnotationTargetMASK) != 0)) {
					continue;
				}
				
				final IAnnotationBinding annotationInstance = this.resolver.getAnnotationInstance(internalAnnotation);
				if (annotationInstance == null) {
					continue;
				}
				tempAnnotations[convertedAnnotationCount++] = annotationInstance;
			}
			if (convertedAnnotationCount == length) return tempAnnotations;
			if (convertedAnnotationCount == 0) return AnnotationBinding.NoAnnotations;
			
			System.arraycopy(tempAnnotations, 0, (tempAnnotations = new IAnnotationBinding[convertedAnnotationCount]), 0, convertedAnnotationCount);
			return tempAnnotations;
		}
		return AnnotationBinding.NoAnnotations;
	}

	@Override
	public Object getDefaultValue() {
		if (isAnnotationMember())
			return MemberValuePairBinding.buildDOMValue(this.binding.getDefaultValue(), this.resolver);
		return null;
	}

	/**
	 * @see IMethodBinding#getExceptionTypes()
	 */
	@Override
	public ITypeBinding[] getExceptionTypes() {
		if (this.exceptionTypes != null) {
			return this.exceptionTypes;
		}
		org.eclipse.jdt.internal.compiler.lookup.TypeBinding[] exceptions = this.binding.thrownExceptions;
		int length = exceptions == null ? 0 : exceptions.length;
		if (length == 0) {
			return this.exceptionTypes = NO_TYPE_BINDINGS;
		}
		ITypeBinding[] exTypes = new ITypeBinding[length];
		for (int i = 0; i < length; i++) {
			ITypeBinding typeBinding = this.resolver.getTypeBinding(exceptions[i]);
			if (typeBinding == null) {
				return this.exceptionTypes = NO_TYPE_BINDINGS;
			}
			exTypes[i] = typeBinding;
		}
		return this.exceptionTypes = exTypes;
	}

	@Override
	public IJavaElement getJavaElement() {
		JavaElement element = getUnresolvedJavaElement();
		if (element == null)
			return null;
		return element.resolved(this.binding);
	}

	private JavaElement getUnresolvedJavaElement() {
		if (JavaCore.getPlugin() == null) {
			return null;
		}
		if (!(this.resolver instanceof DefaultBindingResolver)) return null;

		DefaultBindingResolver defaultBindingResolver = (DefaultBindingResolver) this.resolver;
		if (!defaultBindingResolver.fromJavaProject) return null;
		return Util.getUnresolvedJavaElement(
				this.binding,
				defaultBindingResolver.workingCopyOwner,
				defaultBindingResolver.getBindingsToNodesMap());
	}

	/**
	 * @see IBinding#getKind()
	 */
	@Override
	public int getKind() {
		return IBinding.METHOD;
	}

	/**
	 * @see IBinding#getModifiers()
	 */
	@Override
	public int getModifiers() {
		return this.binding.getAccessFlags() & VALID_MODIFIERS;
	}

	/**
	 * @see IBinding#isDeprecated()
	 */
	@Override
	public boolean isDeprecated() {
		return this.binding.isDeprecated();
	}

	/**
	 * @see IBinding#isRecovered()
	 */
	@Override
	public boolean isRecovered() {
		return false;
	}

	/**
	 * @see IBinding#isSynthetic()
	 */
	@Override
	public boolean isSynthetic() {
		return this.binding.isSynthetic();
	}

	/**
	 * @see org.eclipse.jdt.core.dom.IMethodBinding#isVarargs()
	 * @since 3.1
	 */
	@Override
	public boolean isVarargs() {
		return this.binding.isVarargs();
	}

	/**
	 * @see IBinding#getKey()
	 */
	@Override
	public String getKey() {
		if (this.key == null) {
			this.key = new String(this.binding.computeUniqueKey());
		}
		return this.key;
	}

	/**
	 * @see IBinding#isEqualTo(IBinding)
	 * @since 3.1
	 */
	@Override
	public boolean isEqualTo(IBinding other) {
		if (other == this) {
			// identical binding - equal (key or no key)
			return true;
		}
		if (other == null) {
			// other binding missing
			return false;
		}
		if (!(other instanceof MethodBinding)) {
			return false;
		}
		org.eclipse.jdt.internal.compiler.lookup.MethodBinding otherBinding = ((MethodBinding) other).binding;
		return BindingComparator.isEqual(this.binding, otherBinding);
	}

	/**
	 * @see org.eclipse.jdt.core.dom.IMethodBinding#getTypeParameters()
	 */
	@Override
	public ITypeBinding[] getTypeParameters() {
		if (this.typeParameters != null) {
			return this.typeParameters;
		}
		TypeVariableBinding[] typeVariableBindings = this.binding.typeVariables();
		int typeVariableBindingsLength = typeVariableBindings == null ? 0 : typeVariableBindings.length;
		if (typeVariableBindingsLength == 0) {
			return this.typeParameters = NO_TYPE_BINDINGS;
		}
		ITypeBinding[] tParameters = new ITypeBinding[typeVariableBindingsLength];
		for (int i = 0; i < typeVariableBindingsLength; i++) {
			ITypeBinding typeBinding = this.resolver.getTypeBinding(typeVariableBindings[i]);
			if (typeBinding == null) {
				return this.typeParameters = NO_TYPE_BINDINGS;
			}
			tParameters[i] = typeBinding;
		}
		return this.typeParameters = tParameters;
	}

	/**
	 * @see org.eclipse.jdt.core.dom.IMethodBinding#isGenericMethod()
	 * @since 3.1
	 */
	@Override
	public boolean isGenericMethod() {
		// equivalent to return getTypeParameters().length > 0;
		if (this.typeParameters != null) {
			return this.typeParameters.length > 0;
		}
		TypeVariableBinding[] typeVariableBindings = this.binding.typeVariables();
		return (typeVariableBindings != null && typeVariableBindings.length > 0);
	}

	/**
	 * @see org.eclipse.jdt.core.dom.IMethodBinding#getTypeArguments()
	 */
	@Override
	public ITypeBinding[] getTypeArguments() {
		if (this.typeArguments != null) {
			return this.typeArguments;
		}

		if (this.binding instanceof ParameterizedGenericMethodBinding) {
			ParameterizedGenericMethodBinding genericMethodBinding = (ParameterizedGenericMethodBinding) this.binding;
			org.eclipse.jdt.internal.compiler.lookup.TypeBinding[] typeArgumentsBindings = genericMethodBinding.typeArguments;
			int typeArgumentsLength = typeArgumentsBindings == null ? 0 : typeArgumentsBindings.length;
			if (typeArgumentsLength != 0) {
				ITypeBinding[] tArguments = new ITypeBinding[typeArgumentsLength];
				for (int i = 0; i < typeArgumentsLength; i++) {
					ITypeBinding typeBinding = this.resolver.getTypeBinding(typeArgumentsBindings[i]);
					if (typeBinding == null) {
						return this.typeArguments = NO_TYPE_BINDINGS;
					}
					tArguments[i] = typeBinding;
				}
				return this.typeArguments = tArguments;
			}
		}
		return this.typeArguments = NO_TYPE_BINDINGS;
	}

	/**
	 * @see org.eclipse.jdt.core.dom.IMethodBinding#isParameterizedMethod()
	 */
	@Override
	public boolean isParameterizedMethod() {
		return (this.binding instanceof ParameterizedGenericMethodBinding)
			&& !((ParameterizedGenericMethodBinding) this.binding).isRaw;
	}

	/**
	 * @see org.eclipse.jdt.core.dom.IMethodBinding#isRawMethod()
	 */
	@Override
	public boolean isRawMethod() {
		return (this.binding instanceof ParameterizedGenericMethodBinding)
			&& ((ParameterizedGenericMethodBinding) this.binding).isRaw;
	}

	@Override
	public boolean isSubsignature(IMethodBinding otherMethod) {
		try {
			LookupEnvironment lookupEnvironment = this.resolver.lookupEnvironment();
			return lookupEnvironment != null
				&& lookupEnvironment.methodVerifier().isMethodSubsignature(this.binding, ((MethodBinding) otherMethod).binding);
		} catch (AbortCompilation e) {
			// don't surface internal exception to clients
			// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=143013
			return false;
		}
	}

	/**
	 * @see org.eclipse.jdt.core.dom.IMethodBinding#getMethodDeclaration()
	 */
	@Override
	public IMethodBinding getMethodDeclaration() {
		return this.resolver.getMethodBinding(this.binding.original());
	}

	/**
	 * @see IMethodBinding#overrides(IMethodBinding)
	 */
	@Override
	public boolean overrides(IMethodBinding otherMethod) {
			LookupEnvironment lookupEnvironment = this.resolver.lookupEnvironment();
			return lookupEnvironment != null
				&& lookupEnvironment.methodVerifier().doesMethodOverride(this.binding, ((MethodBinding) otherMethod).binding);
	}

	/**
	 * For debugging purpose only.
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		return this.binding.toString();
	}
//{ObjectTeams: new query:
	@Override
	public boolean isCopied() {
		return this.binding.copyInheritanceSrc != null;
	}
// SH}

	/*
	 * Method binding representing a lambda expression.
	 * Most properties are read from the SAM descriptor,
	 * but key, parameter types, and annotations are taken from the lambda implementation.
	 * Additionally we store the declaring member (see #getDeclaringMember()).
	 */
	static class LambdaMethod extends MethodBinding {

		private MethodBinding implementation;
		private IBinding declaringMember;
		private IVariableBinding[] syntheticOuterLocalVariables;

		public LambdaMethod(DefaultBindingResolver resolver,
							org.eclipse.jdt.internal.compiler.lookup.MethodBinding lambdaDescriptor,
							org.eclipse.jdt.internal.compiler.lookup.MethodBinding implementation,
							IBinding declaringMember)
		{
			super(resolver, lambdaDescriptor);
			this.implementation = new MethodBinding(resolver, implementation);
			this.declaringMember = declaringMember;
		}

		/**
		 * @see IBinding#getModifiers()
		 */
		@Override
		public int getModifiers() {
			return super.getModifiers() & ~ClassFileConstants.AccAbstract;
		}

		/**
		 * @see IBinding#getKey()
		 */
		@Override
		public String getKey() {
			return this.implementation.getKey();
		}

		@Override
		public ITypeBinding[] getParameterTypes() {
			return this.implementation.getParameterTypes();
		}

		@Override
		public IAnnotationBinding[] getParameterAnnotations(int paramIndex) {
			return this.implementation.getParameterAnnotations(paramIndex);
		}

		@Override
		public IAnnotationBinding[] getAnnotations() {
			return this.implementation.getAnnotations();
		}

		@Override
		public IBinding getDeclaringMember() {
			return this.declaringMember;
		}

		@Override
		public IMethodBinding getMethodDeclaration() {
			return this.resolver.getMethodBinding(this.binding);
		}

		@Override
		public String toString() {
			return super.toString().replace("public abstract ", "public ");  //$NON-NLS-1$//$NON-NLS-2$
		}

		@Override
		public IVariableBinding[] getSyntheticOuterLocals() {
			if (this.syntheticOuterLocalVariables != null) {
				return this.syntheticOuterLocalVariables;
			}
			return NO_VARIABLE_BINDINGS;
		}

		public  void setSyntheticOuterLocals(IVariableBinding[] syntheticOuterLocalVariables) {
			this.syntheticOuterLocalVariables = syntheticOuterLocalVariables;
		}
	}

	@Override
	public IVariableBinding[] getSyntheticOuterLocals() {
		return NO_VARIABLE_BINDINGS;
	}
}