/*******************************************************************************
 * 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
 *     Stephan Herrmann - Contribution for
 *								bug 392862 - [1.8][compiler][null] Evaluate null annotations on array types
 *								bug 395002 - Self bound generic class doesn't resolve bounds properly for wildcards for certain parametrisation.
 *								bug 392384 - [1.8][compiler][null] Restore nullness info from type annotations in class files
 *								Bug 392099 - [1.8][compiler][null] Apply null annotation on types for null analysis
 *								Bug 415291 - [1.8][null] differentiate type incompatibilities due to null annotations
 *								Bug 415850 - [1.8] Ensure RunJDTCoreTests can cope with null annotations enabled
 *								Bug 416176 - [1.8][compiler][null] null type annotations cause grief on type variables
 *								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 425460 - [1.8] [inference] Type not inferred on stream.toArray
 *								Bug 426792 - [1.8][inference][impl] generify new type inference engine
 *								Bug 428019 - [1.8][compiler] Type inference failure with nested generic invocation.
 *								Bug 438458 - [1.8][null] clean up handling of null type annotations wrt type variables
 *								Bug 440759 - [1.8][null] @NonNullByDefault should never affect wildcards and uses of a type variable
 *								Bug 441693 - [1.8][null] Bogus warning for type argument annotated with @NonNull
 *     Jesper S Møller - Contributions for bug 381345 : [1.8] Take care of the Java 8 major version
 *								Bug 527554 - [18.3] Compiler support for JEP 286 Local-Variable Type
 *******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;

import java.util.List;
import java.util.Set;

import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.ClassFile;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.impl.Constant;

public final class ArrayBinding extends TypeBinding {
	// creation and initialization of the length field
	// the declaringClass of this field is intentionally set to null so it can be distinguished.
	public static final FieldBinding ArrayLength = new FieldBinding(TypeConstants.LENGTH, TypeBinding.INT, ClassFileConstants.AccPublic | ClassFileConstants.AccFinal, null, Constant.NotAConstant);

	public TypeBinding leafComponentType;
	public int dimensions;
	LookupEnvironment environment;
	char[] constantPoolName;
	char[] genericTypeSignature;

	// One bitset for each dimension plus one more for the leaf component type at position 'dimensions',
	// possible bits are TagBits.AnnotationNonNull and TagBits.AnnotationNullable
	// (only ever set when CompilerOptions.isAnnotationBasedNullAnalysisEnabled == true):
	public long[] nullTagBitsPerDimension;

	private MethodBinding clone;

public ArrayBinding(TypeBinding type, int dimensions, LookupEnvironment environment) {
	this.tagBits |= TagBits.IsArrayType;
	this.leafComponentType = type;
	this.dimensions = dimensions;
	this.environment = environment;
	if (type instanceof UnresolvedReferenceBinding)
		((UnresolvedReferenceBinding) type).addWrapper(this, environment);
	else
		this.tagBits |= type.tagBits & (TagBits.HasTypeVariable | TagBits.HasDirectWildcard | TagBits.HasMissingType | TagBits.ContainsNestedTypeReferences | TagBits.HasCapturedWildcard);
	long mask = type.tagBits & TagBits.AnnotationNullMASK;
	if (mask != 0) {
		this.nullTagBitsPerDimension = new long[this.dimensions + 1];
		this.nullTagBitsPerDimension[this.dimensions] = mask;
		this.tagBits |= TagBits.HasNullTypeAnnotation;
	}
}

@Override
public TypeBinding closestMatch() {
	if (isValidBinding()) {
		return this;
	}
	TypeBinding leafClosestMatch = this.leafComponentType.closestMatch();
	if (leafClosestMatch == null) {
		return null;
	}
	return this.environment.createArrayType(this.leafComponentType.closestMatch(), this.dimensions);
}

/**
 * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#collectMissingTypes(java.util.List)
 */
@Override
public List<TypeBinding> collectMissingTypes(List<TypeBinding> missingTypes) {
	if ((this.tagBits & TagBits.HasMissingType) != 0) {
		missingTypes = this.leafComponentType.collectMissingTypes(missingTypes);
	}
	return missingTypes;
}

@Override
public void collectSubstitutes(Scope scope, TypeBinding actualType, InferenceContext inferenceContext, int constraint) {

	if ((this.tagBits & TagBits.HasTypeVariable) == 0) return;
	if (actualType == TypeBinding.NULL || actualType.kind() == POLY_TYPE) return;

	switch(actualType.kind()) {
		case Binding.ARRAY_TYPE :
	        int actualDim = actualType.dimensions();
	        if (actualDim == this.dimensions) {
			    this.leafComponentType.collectSubstitutes(scope, actualType.leafComponentType(), inferenceContext, constraint);
	        } else if (actualDim > this.dimensions) {
	            ArrayBinding actualReducedType = this.environment.createArrayType(actualType.leafComponentType(), actualDim - this.dimensions);
	            this.leafComponentType.collectSubstitutes(scope, actualReducedType, inferenceContext, constraint);
	        }
			break;
		case Binding.TYPE_PARAMETER :
			//TypeVariableBinding variable = (TypeVariableBinding) otherType;
			// TODO (philippe) should consider array bounds, and recurse
			break;
	}
}

@Override
public boolean mentionsAny(TypeBinding[] parameters, int idx) {
	return this.leafComponentType.mentionsAny(parameters, idx);
}

@Override
void collectInferenceVariables(Set<InferenceVariable> variables) {
	this.leafComponentType.collectInferenceVariables(variables);
}

@Override
TypeBinding substituteInferenceVariable(InferenceVariable var, TypeBinding substituteType) {
	TypeBinding substitutedLeaf = this.leafComponentType.substituteInferenceVariable(var, substituteType);
	if (TypeBinding.notEquals(substitutedLeaf, this.leafComponentType))
		return this.environment.createArrayType(substitutedLeaf, this.dimensions, this.typeAnnotations);
	return this;
}

/*
 * brakets leafUniqueKey
 * p.X[][] --> [[Lp/X;
 */
@Override
public char[] computeUniqueKey(boolean isLeaf) {
	char[] brackets = new char[this.dimensions];
	for (int i = this.dimensions - 1; i >= 0; i--) brackets[i] = '[';
	return CharOperation.concat(brackets, this.leafComponentType.computeUniqueKey(isLeaf));
 }

@Override
public char[] constantPoolName() {
	if (this.constantPoolName != null)
		return this.constantPoolName;

	char[] brackets = new char[this.dimensions];
	for (int i = this.dimensions - 1; i >= 0; i--) brackets[i] = '[';
	return this.constantPoolName = CharOperation.concat(brackets, this.leafComponentType.signature());
}
@Override
public String debugName() {
	if (this.hasTypeAnnotations())
		return annotatedDebugName();
	StringBuffer brackets = new StringBuffer(this.dimensions * 2);
	for (int i = this.dimensions; --i >= 0;)
		brackets.append("[]"); //$NON-NLS-1$
	return this.leafComponentType.debugName() + brackets.toString();
}

@Override
public String annotatedDebugName() {
	StringBuffer brackets = new StringBuffer(this.dimensions * 2);
	brackets.append(this.leafComponentType.annotatedDebugName());
	brackets.append(' ');
	AnnotationBinding [] annotations = getTypeAnnotations();
	for (int i = 0, j = -1; i < this.dimensions; i++) {
		if (annotations != null) {
			if (i != 0)
				brackets.append(' ');
			while (++j < annotations.length && annotations[j] != null) {
				brackets.append(annotations[j]);
				brackets.append(' ');
			}
		}
		brackets.append("[]"); //$NON-NLS-1$
	}
	return brackets.toString();
}

@Override
public int dimensions() {
	return this.dimensions;
}

/* Answer an array whose dimension size is one less than the receiver.
*
* When the receiver's dimension size is one then answer the leaf component type.
*/

public TypeBinding elementsType() {

	if (this.dimensions == 1)
		return this.leafComponentType;

	AnnotationBinding [] oldies = getTypeAnnotations();
	AnnotationBinding [] newbies = Binding.NO_ANNOTATIONS;

	for (int i = 0, length = oldies == null ? 0 : oldies.length; i < length; i++) {
		if (oldies[i] == null) {
			System.arraycopy(oldies, i+1, newbies = new AnnotationBinding[length - i - 1], 0, length - i - 1);
			break;
		}
	}
	return this.environment.createArrayType(this.leafComponentType, this.dimensions - 1, newbies);
}

/**
 * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#erasure()
 */
@Override
public TypeBinding erasure() {
    TypeBinding erasedType = this.leafComponentType.erasure();
    if (TypeBinding.notEquals(this.leafComponentType, erasedType))
        return this.environment.createArrayType(erasedType, this.dimensions);
    return this;
}

@Override
public ArrayBinding upwardsProjection(Scope scope, TypeBinding[] mentionedTypeVariables) {
	TypeBinding leafType = this.leafComponentType.upwardsProjection(scope, mentionedTypeVariables);
	return scope.environment().createArrayType(leafType, this.dimensions, this.typeAnnotations);
}

@Override
public ArrayBinding downwardsProjection(Scope scope, TypeBinding[] mentionedTypeVariables) {
	TypeBinding leafType = this.leafComponentType.downwardsProjection(scope, mentionedTypeVariables);
	return scope.environment().createArrayType(leafType, this.dimensions, this.typeAnnotations);
}

public LookupEnvironment environment() {
    return this.environment;
}

@Override
public char[] genericTypeSignature() {

    if (this.genericTypeSignature == null) {
		char[] brackets = new char[this.dimensions];
		for (int i = this.dimensions - 1; i >= 0; i--) brackets[i] = '[';
		this.genericTypeSignature = CharOperation.concat(brackets, this.leafComponentType.genericTypeSignature());
    }
    return this.genericTypeSignature;
}

@Override
public PackageBinding getPackage() {
	return this.leafComponentType.getPackage();
}

@Override
public int hashCode() {
	return this.leafComponentType == null ? super.hashCode() : this.leafComponentType.hashCode();
}

/* Answer true if the receiver type can be assigned to the argument type (right)
*/
@Override
public boolean isCompatibleWith(TypeBinding otherType, Scope captureScope) {
	if (equalsEquals(this, otherType))
		return true;

	switch (otherType.kind()) {
		case Binding.ARRAY_TYPE :
			ArrayBinding otherArray = (ArrayBinding) otherType;
			if (otherArray.leafComponentType.isBaseType())
				return false; // relying on the fact that all equal arrays are identical
			if (this.dimensions == otherArray.dimensions)
				return this.leafComponentType.isCompatibleWith(otherArray.leafComponentType);
			if (this.dimensions < otherArray.dimensions)
				return false; // cannot assign 'String[]' into 'Object[][]' but can assign 'byte[][]' into 'Object[]'
			break;
		case Binding.BASE_TYPE :
			return false;
		case Binding.WILDCARD_TYPE :
		case Binding.INTERSECTION_TYPE :
		    return ((WildcardBinding) otherType).boundCheck(this);

		case Binding.INTERSECTION_TYPE18:
			for (ReferenceBinding intersecting : ((IntersectionTypeBinding18) otherType).intersectingTypes) {
				if (!isCompatibleWith(intersecting, captureScope))
					return false;
			}
			return true;

		case Binding.TYPE_PARAMETER :
			// check compatibility with capture of ? super X
			if (otherType.isCapture()) {
				CaptureBinding otherCapture = (CaptureBinding) otherType;
				TypeBinding otherLowerBound;
				if ((otherLowerBound = otherCapture.lowerBound) != null) {
					if (!otherLowerBound.isArrayType()) return false;
					return isCompatibleWith(otherLowerBound, captureScope);
				}
			}
			return false;

	}
	//Check dimensions - Java does not support explicitly sized dimensions for types.
	//However, if it did, the type checking support would go here.
	switch (otherType.leafComponentType().id) {
	    case TypeIds.T_JavaLangObject :
	    case TypeIds.T_JavaLangCloneable :
	    case TypeIds.T_JavaIoSerializable :
	        return true;
	}
	return false;
}

@Override
public boolean isSubtypeOf(TypeBinding otherType, boolean simulatingBugJDK8026527) {
	if (equalsEquals(this, otherType))
		return true;

	switch (otherType.kind()) {
		case Binding.ARRAY_TYPE :
			ArrayBinding otherArray = (ArrayBinding) otherType;
			if (otherArray.leafComponentType.isBaseType())
				return false; // relying on the fact that all equal arrays are identical
			if (this.dimensions == otherArray.dimensions)
				return this.leafComponentType.isSubtypeOf(otherArray.leafComponentType, simulatingBugJDK8026527);
			if (this.dimensions < otherArray.dimensions)
				return false; // cannot assign 'String[]' into 'Object[][]' but can assign 'byte[][]' into 'Object[]'
			break;
		case Binding.BASE_TYPE :
			return false;
		case Binding.INTERSECTION_TYPE18:
			for (ReferenceBinding intersecting : ((IntersectionTypeBinding18) otherType).intersectingTypes) {
				if (!isSubtypeOf(intersecting, simulatingBugJDK8026527))
					return false;
			}
			return true;
		case Binding.TYPE_PARAMETER:
			// check compatibility with capture of ? super X
			if (otherType.isCapture()) {
				CaptureBinding otherCapture = (CaptureBinding) otherType;
				TypeBinding otherLowerBound;
				if ((otherLowerBound = otherCapture.lowerBound) != null) {
					if (!otherLowerBound.isArrayType()) return false;
					return isSubtypeOf(otherLowerBound, simulatingBugJDK8026527);
				}
			}
	}
	switch (otherType.leafComponentType().id) {
	    case TypeIds.T_JavaLangObject :
	    case TypeIds.T_JavaLangCloneable :
	    case TypeIds.T_JavaIoSerializable :
	        return true;
	}
	return false;
}

@Override
public boolean isProperType(boolean admitCapture18) {
	return this.leafComponentType.isProperType(admitCapture18);
}

@Override
public int kind() {
	return ARRAY_TYPE;
}

@Override
public TypeBinding leafComponentType(){
	return this.leafComponentType;
}

@Override
public char[] nullAnnotatedReadableName(CompilerOptions options, boolean shortNames) /* java.lang.Object @o.e.j.a.NonNull[] */ {
	if (this.nullTagBitsPerDimension == null)
		return shortNames ? shortReadableName() : readableName();
	char[][] brackets = new char[this.dimensions][];
	for (int i = 0; i < this.dimensions; i++) {
		if ((this.nullTagBitsPerDimension[i] & TagBits.AnnotationNullMASK) != 0) {
			char[][] fqAnnotationName;
			if ((this.nullTagBitsPerDimension[i] & TagBits.AnnotationNonNull) != 0)
				fqAnnotationName = options.nonNullAnnotationName;
			else
				fqAnnotationName = options.nullableAnnotationName;
			char[] annotationName = shortNames
										? fqAnnotationName[fqAnnotationName.length-1]
										: CharOperation.concatWith(fqAnnotationName, '.');
			brackets[i] = new char[annotationName.length+3];
			brackets[i][0] = '@';
			System.arraycopy(annotationName, 0, brackets[i], 1, annotationName.length);
			brackets[i][annotationName.length+1] = '[';
			brackets[i][annotationName.length+2] = ']';
		} else {
			brackets[i] = new char[]{'[', ']'};
		}
	}
	return CharOperation.concat(this.leafComponentType.nullAnnotatedReadableName(options, shortNames),
								 CharOperation.concatWith(brackets, ' '),
								 ' ');
}

/* API
* Answer the problem id associated with the receiver.
* NoError if the receiver is a valid binding.
*/
@Override
public int problemId() {
	return this.leafComponentType.problemId();
}

@Override
public char[] qualifiedSourceName() {
	char[] brackets = new char[this.dimensions * 2];
	for (int i = this.dimensions * 2 - 1; i >= 0; i -= 2) {
		brackets[i] = ']';
		brackets[i - 1] = '[';
	}
	return CharOperation.concat(this.leafComponentType.qualifiedSourceName(), brackets);
}
@Override
public char[] readableName() /* java.lang.Object[] */ {
	char[] brackets = new char[this.dimensions * 2];
	for (int i = this.dimensions * 2 - 1; i >= 0; i -= 2) {
		brackets[i] = ']';
		brackets[i - 1] = '[';
	}
	return CharOperation.concat(this.leafComponentType.readableName(), brackets);
}

@Override
public void setTypeAnnotations(AnnotationBinding[] annotations, boolean evalNullAnnotations) {
	this.tagBits |= TagBits.HasTypeAnnotations;
	if (annotations == null || annotations.length == 0)
		return;
	this.typeAnnotations = annotations;

	if (evalNullAnnotations) {
		long nullTagBits = 0;
		if (this.nullTagBitsPerDimension == null)
			this.nullTagBitsPerDimension = new long[this.dimensions + 1];

		int dimension = 0;
		for (int i = 0, length = annotations.length; i < length; i++) {
			AnnotationBinding annotation = annotations[i];
			if (annotation != null) {
				if (annotation.type.hasNullBit(TypeIds.BitNullableAnnotation)) {
					nullTagBits  |= TagBits.AnnotationNullable;
					this.tagBits |= TagBits.HasNullTypeAnnotation;
				} else if (annotation.type.hasNullBit(TypeIds.BitNonNullAnnotation)) {
					nullTagBits  |= TagBits.AnnotationNonNull;
					this.tagBits |= TagBits.HasNullTypeAnnotation;
				}
			} else {
				// null signals end of annotations for the current dimension in the serialized form.
				if (nullTagBits != 0) {
					this.nullTagBitsPerDimension[dimension] = nullTagBits;
					nullTagBits = 0;
				}
				dimension++;
			}
		}
		this.tagBits |= this.nullTagBitsPerDimension[0]; // outer-most dimension
	}
}
@Override
public char[] shortReadableName(){
	char[] brackets = new char[this.dimensions * 2];
	for (int i = this.dimensions * 2 - 1; i >= 0; i -= 2) {
		brackets[i] = ']';
		brackets[i - 1] = '[';
	}
	return CharOperation.concat(this.leafComponentType.shortReadableName(), brackets);
}
@Override
public char[] sourceName() {
	char[] brackets = new char[this.dimensions * 2];
	for (int i = this.dimensions * 2 - 1; i >= 0; i -= 2) {
		brackets[i] = ']';
		brackets[i - 1] = '[';
	}
	return CharOperation.concat(this.leafComponentType.sourceName(), brackets);
}
@Override
public void swapUnresolved(UnresolvedReferenceBinding unresolvedType, ReferenceBinding resolvedType, LookupEnvironment env) {
	if (this.leafComponentType == unresolvedType) { //$IDENTITY-COMPARISON$
		this.leafComponentType = env.convertUnresolvedBinaryToRawType(resolvedType);
		/* Leaf component type is the key in the type system. If it undergoes change, the array has to be rehashed.
		   We achieve by creating a fresh array with the new component type and equating this array's id with that.
		   This means this array can still be found under the old key, but that is harmless (since the component type
		   is always consulted (see TypeSystem.getArrayType()).

		   This also means that this array type is not a fully interned singleton: There is `this' object and there is
		   the array that is being created down below that gets cached by the type system and doled out for all further
		   array creations against the same (raw) component type, dimensions and annotations. This again is harmless,
		   since TypeBinding.id is consulted for (in)equality checks.

		   See https://bugs.eclipse.org/bugs/show_bug.cgi?id=430425 for details and a test case.
		*/
		if (this.leafComponentType != resolvedType) //$IDENTITY-COMPARISON$
			this.id = env.createArrayType(this.leafComponentType, this.dimensions, this.typeAnnotations).id;
		this.tagBits |= this.leafComponentType.tagBits & (TagBits.HasTypeVariable | TagBits.HasDirectWildcard | TagBits.HasMissingType | TagBits.HasCapturedWildcard);
	}
}
@Override
public String toString() {
	return this.leafComponentType != null ? debugName() : "NULL TYPE ARRAY"; //$NON-NLS-1$
}
@Override
public TypeBinding unannotated() {
	return this.hasTypeAnnotations() ? this.environment.getUnannotatedType(this) : this;
}
@Override
public TypeBinding withoutToplevelNullAnnotation() {
	if (!hasNullTypeAnnotations())
		return this;
	AnnotationBinding[] newAnnotations = this.environment.filterNullTypeAnnotations(this.typeAnnotations);
	return this.environment.createArrayType(this.leafComponentType, this.dimensions, newAnnotations);
}
@Override
public TypeBinding uncapture(Scope scope) {
	if ((this.tagBits & TagBits.HasCapturedWildcard) == 0)
		return this;
	TypeBinding leafType = this.leafComponentType.uncapture(scope);
	return scope.environment().createArrayType(leafType, this.dimensions, this.typeAnnotations);
}
@Override
public boolean acceptsNonNullDefault() {
	return true;
}
@Override
public long updateTagBits() {
	if (this.leafComponentType != null)
		this.tagBits |= this.leafComponentType.updateTagBits();
	return super.updateTagBits();
}

/**
 * The type of x.clone() is substituted from 'Object' into the type of the receiver array (non-null)
 */
public MethodBinding getCloneMethod(final MethodBinding originalMethod) {
	if (this.clone != null)
		return this.clone;
	MethodBinding method = new MethodBinding() {
		@Override
		public char[] signature(ClassFile classFile) {
			return originalMethod.signature(); // for codeGen we need to answer the signature of j.l.Object.clone()
		}
	};
	method.modifiers = originalMethod.modifiers;
	method.selector = originalMethod.selector;
	method.declaringClass = originalMethod.declaringClass; // cannot set array binding as declaring class, will be tweaked in CodeStream.getConstantPoolDeclaringClass()
	method.typeVariables = Binding.NO_TYPE_VARIABLES;
	method.parameters = originalMethod.parameters;
	method.thrownExceptions = Binding.NO_EXCEPTIONS;
	method.tagBits = originalMethod.tagBits;
	method.returnType = this.environment.globalOptions.sourceLevel >= ClassFileConstants.JDK1_5 ? this : originalMethod.returnType;
	if (this.environment.globalOptions.isAnnotationBasedNullAnalysisEnabled) {
		if (this.environment.usesNullTypeAnnotations())
			method.returnType = this.environment.createAnnotatedType(method.returnType, new AnnotationBinding[] { this.environment.getNonNullAnnotation() });
		else
			method.tagBits |= TagBits.AnnotationNonNull;
	}
	if ((method.returnType.tagBits & TagBits.HasMissingType) != 0) {
		method.tagBits |=  TagBits.HasMissingType;
	}
	return this.clone = method;
}
public static boolean isArrayClone(TypeBinding receiverType, MethodBinding binding) {
	if (receiverType instanceof ArrayBinding) {
		MethodBinding clone = ((ArrayBinding) receiverType).clone;
		return clone != null && binding == clone;
	}
	return false;
}
}
