/*******************************************************************************
 * Copyright (c) 2000, 2014 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Technical University Berlin - extended 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.
 *******************************************************************************/
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.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.impl.Constant;
import org.eclipse.objectteams.otdt.internal.core.compiler.util.TypeAnalyzer;
import org.eclipse.objectteams.otdt.internal.core.compiler.util.RoleTypeCreator.TypeArgumentUpdater;

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;

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;
	}
}

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)
 */
public List collectMissingTypes(List missingTypes) {
	if ((this.tagBits & TagBits.HasMissingType) != 0) {
		missingTypes = this.leafComponentType.collectMissingTypes(missingTypes);
	}
	return missingTypes;
}

/**
 * Collect the substitutes into a map for certain type variables inside the receiver type
 * e.g.   Collection<T>.collectSubstitutes(Collection<List<X>>, Map), will populate Map with: T --> List<X>
 * Constraints:
 *   A << F   corresponds to:   F.collectSubstitutes(..., A, ..., CONSTRAINT_EXTENDS (1))
 *   A = F   corresponds to:      F.collectSubstitutes(..., A, ..., CONSTRAINT_EQUAL (0))
 *   A >> F   corresponds to:   F.collectSubstitutes(..., A, ..., CONSTRAINT_SUPER (2))
*/
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);
}

//{ObjectTeams: cross the OT package, make protected:
protected
//SH}
void collectInferenceVariables(Set variables) {
	this.leafComponentType.collectInferenceVariables(variables);
}

//{ObjectTeams: cross the OT package, make protected:
protected
//SH}
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;
 */
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));
 }

/**
 * Answer the receiver's constant pool name.
 * NOTE: This method should only be used during/after code gen.
 * e.g. '[Ljava/lang/Object;'
 */
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());
}
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();
}

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();
}

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()
 */
public TypeBinding erasure() {
    TypeBinding erasedType = this.leafComponentType.erasure();
    if (TypeBinding.notEquals(this.leafComponentType, erasedType))
        return this.environment.createArrayType(erasedType, this.dimensions);
    return this;
}
public LookupEnvironment environment() {
    return this.environment;
}

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;
}

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

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)
*/
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.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 :
//{ObjectTeams: Confined[] \notsubtype Object ...
    		if (TypeAnalyzer.isConfined(this.leafComponentType))
    			return false;
// SH}
	        return true;
	}
	return false;
}

@Override
public boolean isSubtypeOf(TypeBinding otherType) {
	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);
			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;
	}
	switch (otherType.leafComponentType().id) {
	    case TypeIds.T_JavaLangObject :
	    case TypeIds.T_JavaLangCloneable :
	    case TypeIds.T_JavaIoSerializable :
	        return true;
	}
	return false;
}

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

public int kind() {
	return ARRAY_TYPE;
}

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

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.
*/
public int problemId() {
	return this.leafComponentType.problemId();
}
/**
* Answer the source name for the type.
* In the case of member types, as the qualified name from its top level type.
* For example, for a member type N defined inside M & A: "A.M.N".
*/

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);
}
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);
}

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) {
				switch (annotation.type.id) {
					case TypeIds.T_ConfiguredAnnotationNullable :
						nullTagBits  |= TagBits.AnnotationNullable;
						this.tagBits |= TagBits.HasNullTypeAnnotation;
						break;
					case TypeIds.T_ConfiguredAnnotationNonNull :
						nullTagBits  |= TagBits.AnnotationNonNull;
						this.tagBits |= TagBits.HasNullTypeAnnotation;
						break;
				}
			} 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
	}
}
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);
}
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);
}
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())
		*/ 
		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);
	}
}
//{ObjectTeams: role wrapping:
@Override
public TypeBinding maybeWrapRoleType(ASTNode typedNode, TypeArgumentUpdater updater) {
	if (!this.leafComponentType.isBaseType()) {
		TypeBinding updated = this.leafComponentType.maybeWrapRoleType(typedNode, updater);
		if (updated != this.leafComponentType) //$IDENTITY-COMPARISON$
			return this.environment.createArrayType(updated, this.dimensions);
	}
	return this;
}
// SH}
public String toString() {
	return this.leafComponentType != null ? debugName() : "NULL TYPE ARRAY"; //$NON-NLS-1$
}
public TypeBinding unannotated() {
	return this.hasTypeAnnotations() ? this.environment.getUnannotatedType(this) : this;
}
@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);
}

}
