/*******************************************************************************
 * Copyright (c) 2005, 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 425183 - [1.8][inference] make CaptureBinding18 safe
 *								Bug 466308 - [hovering] Javadoc header for parameter is wrong with annotation-based null analysis
 *******************************************************************************/
package org.eclipse.jdt.internal.core.util;

import java.util.ArrayList;

import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.ASTVisitor;
import org.eclipse.jdt.internal.compiler.Compiler;
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.ArrayReference;
import org.eclipse.jdt.internal.compiler.ast.Assignment;
import org.eclipse.jdt.internal.compiler.ast.CastExpression;
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
import org.eclipse.jdt.internal.compiler.ast.ConditionalExpression;
import org.eclipse.jdt.internal.compiler.ast.FieldReference;
import org.eclipse.jdt.internal.compiler.ast.MessageSend;
import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference;
import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Wildcard;
import org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding;
import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
import org.eclipse.jdt.internal.compiler.lookup.Binding;
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
import org.eclipse.jdt.internal.compiler.lookup.CaptureBinding;
import org.eclipse.jdt.internal.compiler.lookup.CaptureBinding18;
import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
import org.eclipse.jdt.internal.compiler.lookup.LocalTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
import org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.PlainPackageBinding;
import org.eclipse.jdt.internal.compiler.lookup.PolymorphicMethodBinding;
import org.eclipse.jdt.internal.compiler.lookup.RawTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
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.lookup.VariableBinding;
import org.eclipse.jdt.internal.compiler.lookup.WildcardBinding;
import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;

@SuppressWarnings({"rawtypes", "unchecked"})
public class BindingKeyResolver extends BindingKeyParser {

	/** Synthetic bindings for local variables (method arguments) restored from a binding key. */
	private final class SyntheticLocalVariableBinding extends LocalVariableBinding {

		private final MethodBinding enclosingMethod;
		private int paramPosition;
		private char[] key;

		SyntheticLocalVariableBinding(char[] name, TypeBinding type, MethodBinding enclosingMethod, int paramPosition) {
			super(name, type, 0, true);
			this.enclosingMethod = enclosingMethod;
			this.paramPosition = paramPosition;
		}

		@Override
		public char[] computeUniqueKey() {
			if (this.key == null) {
				// have no scope to find the enclosing method, so use the captured method:
				StringBuilder buf = new StringBuilder().append(this.enclosingMethod.computeUniqueKey());
				buf.append('#');
				buf.append(this.name);
				buf.append("#0#"); //$NON-NLS-1$
				buf.append(this.paramPosition);
				int length = buf.length();
				this.key = new char[length];
				buf.getChars(0, length, this.key, 0);
			}
			return this.key;
		}

		@Override
		public MethodBinding getEnclosingMethod() {
			return this.enclosingMethod;
		}

		@Override
		public int hashCode() {
			return CharOperation.hashCode(computeUniqueKey());
		}

		@Override
		public boolean equals(Object obj) {
			if (!(obj instanceof SyntheticLocalVariableBinding))
				return false;
			return CharOperation.equals(computeUniqueKey(), ((SyntheticLocalVariableBinding) obj).computeUniqueKey());
		}
	}

	Compiler compiler;
	Binding compilerBinding;

	char[][] compoundName;
	char[] moduleName;
	int dimension;
	LookupEnvironment environment;
	ReferenceBinding genericType;
	MethodBinding methodBinding;
	AnnotationBinding annotationBinding;

	char[] secondarySimpleName;
	CompilationUnitDeclaration parsedUnit;
	BlockScope scope;
	TypeBinding typeBinding;
	TypeDeclaration typeDeclaration;
	ArrayList types = new ArrayList();

	int wildcardRank;

	CompilationUnitDeclaration outerMostParsedUnit;

	/*
	 * A hash set of the file names of already resolved units
	 */
	HashtableOfObject resolvedUnits;

	private BindingKeyResolver(BindingKeyParser parser, Compiler compiler, LookupEnvironment environment, CompilationUnitDeclaration outerMostParsedUnit, HashtableOfObject parsedUnits) {
		super(parser);
		this.compiler = compiler;
		this.environment = environment;
		this.outerMostParsedUnit = outerMostParsedUnit;
		this.resolvedUnits = parsedUnits;
	}

	public BindingKeyResolver(String key, Compiler compiler, LookupEnvironment environment) {
		super(key);
		this.compiler = compiler;
		this.environment = environment;
		this.resolvedUnits = new HashtableOfObject();
	}

	/*
	 * If not already cached, computes and cache the compound name (pkg name + top level name) of this key.
	 * Returns the package name if key is a pkg key.
	 * Returns an empty array if malformed.
	 * This key's scanner should be positioned on the package or type token.
	 */
	public char[][] compoundName() {
		return this.compoundName;
	}

	public char[] moduleName() {
		return this.moduleName;
	}

	@Override
	public void consumeAnnotation() {
		int size = this.types.size();
		if (size == 0) return;
		Binding annotationType = ((BindingKeyResolver) this.types.get(size-1)).compilerBinding;
		AnnotationBinding[] annotationBindings;
		if (this.compilerBinding == null && this.typeBinding instanceof ReferenceBinding) {
			annotationBindings = ((ReferenceBinding) this.typeBinding).getAnnotations();
		} else if (this.compilerBinding instanceof MethodBinding) {
			annotationBindings = ((MethodBinding) this.compilerBinding).getAnnotations();
		} else if (this.compilerBinding instanceof VariableBinding) {
			annotationBindings = ((VariableBinding) this.compilerBinding).getAnnotations();
		} else {
			return;
		}
		for (int i = 0, length = annotationBindings.length; i < length; i++) {
			AnnotationBinding binding = annotationBindings[i];
			if (binding.getAnnotationType() == annotationType) {
				this.annotationBinding = binding;
				break;
			}
		}
	}

	@Override
	public void consumeArrayDimension(char[] brakets) {
		this.dimension = brakets.length;
	}

	@Override
	public void consumeBaseType(char[] baseTypeSig) {
		this.compoundName = new char[][] {getKey().toCharArray()};
		TypeBinding baseTypeBinding = getBaseTypeBinding(baseTypeSig);
		if (baseTypeBinding != null) {
			this.typeBinding = baseTypeBinding;
		}
	}

	@Override
	public void consumeCapture18ID(int id, int position) {
		consumeAnyCapture(id, position);
	}

	@Override
	public void consumeCapture(final int position) {
		consumeAnyCapture(-1, position);
	}
	public void consumeAnyCapture(final int capture18id, final int position) {
		CompilationUnitDeclaration outerParsedUnit = this.outerMostParsedUnit == null ? this.parsedUnit : this.outerMostParsedUnit;
		if (outerParsedUnit == null) return;
		final Binding wildcardBinding = this.types.size() > 0  // 0 may happen for CaptureBinding18
				? ((BindingKeyResolver) this.types.get(0)).compilerBinding : null;
		class CaptureFinder extends ASTVisitor {
			CaptureBinding capture;
			boolean checkType(TypeBinding binding) {
				if (binding == null)
					return false;
				switch (binding.kind()) {
					case Binding.PARAMETERIZED_TYPE:
						TypeBinding[] arguments = ((ParameterizedTypeBinding) binding).arguments;
						if (arguments == null) return false;
						for (int i = 0, length = arguments.length; i < length; i++) {
							if (checkType(arguments[i]))
								return true;
						}
						break;
					case Binding.WILDCARD_TYPE:
						return checkType(((WildcardBinding) binding).bound);
					case Binding.INTERSECTION_TYPE:
						if (checkType(((WildcardBinding) binding).bound))
							return true;
						TypeBinding[] otherBounds = ((WildcardBinding) binding).otherBounds;
						// per construction, otherBounds is never null
						for (int i = 0, length = otherBounds.length; i < length; i++) {
							if (checkType(otherBounds[i]))
								return true;
						}
						break;
					case Binding.ARRAY_TYPE:
						return checkType(((ArrayBinding) binding).leafComponentType);
					case Binding.TYPE_PARAMETER:
						if (binding.isCapture()) {
							CaptureBinding captureBinding = (CaptureBinding) binding;
							if (captureBinding.end == position && captureBinding.wildcard == wildcardBinding) {
								if (captureBinding instanceof CaptureBinding18) {
									if (((CaptureBinding18)captureBinding).captureID != capture18id)
										return false;
								}
								this.capture = captureBinding;
								return true;
							}
						}
						break;
				}
				return false;
			}
			@Override
			public boolean visit(SingleNameReference singleNameReference, BlockScope blockScope) {
				if (checkType(singleNameReference.resolvedType))
					return false;
				return super.visit(singleNameReference, blockScope);
			}
			@Override
			public boolean visit(QualifiedNameReference qualifiedNameReference, BlockScope blockScope) {
				if (checkType(qualifiedNameReference.resolvedType))
					return false;
				return super.visit(qualifiedNameReference, blockScope);
			}
			@Override
			public boolean visit(MessageSend messageSend, BlockScope blockScope) {
				if (checkType(messageSend.resolvedType))
					return false;
				return super.visit(messageSend, blockScope);
			}
			@Override
			public boolean visit(FieldReference fieldReference, BlockScope blockScope) {
				if (checkType(fieldReference.resolvedType))
					return false;
				return super.visit(fieldReference, blockScope);
			}
			@Override
			public boolean visit(ConditionalExpression conditionalExpression, BlockScope blockScope) {
				if (checkType(conditionalExpression.resolvedType))
					return false;
				return super.visit(conditionalExpression, blockScope);
			}
			@Override
			public boolean visit(CastExpression castExpression, BlockScope blockScope) {
				if (checkType(castExpression.resolvedType))
					return false;
				return super.visit(castExpression, blockScope);
			}
			@Override
			public boolean visit(Assignment assignment, BlockScope blockScope) {
				if (checkType(assignment.resolvedType))
					return false;
				return super.visit(assignment, blockScope);
			}
			@Override
			public boolean visit(ArrayReference arrayReference, BlockScope blockScope) {
				if (checkType(arrayReference.resolvedType))
					return false;
				return super.visit(arrayReference, blockScope);
			}
		}
		CaptureFinder captureFinder = new CaptureFinder();
		outerParsedUnit.traverse(captureFinder, outerParsedUnit.scope);
		this.typeBinding = captureFinder.capture;
	}

	@Override
	public void consumeException() {
		this.types = new ArrayList();
	}

	@Override
	public void consumeField(char[] fieldName) {
		if (this.typeBinding == null)
			return;
		FieldBinding[] fields = ((ReferenceBinding) this.typeBinding).availableFields(); // resilience
	 	for (int i = 0, length = fields.length; i < length; i++) {
			FieldBinding field = fields[i];
			if (CharOperation.equals(fieldName, field.name)) {
				this.typeBinding = null;
				this.compilerBinding = field;
				return;
			}
		}
	}

	@Override
	public void consumeParameterizedGenericMethod() {
		if (this.methodBinding == null)
			return;
		TypeBinding[] arguments = getTypeBindingArguments();
		if (arguments == null) {
			this.methodBinding = null;
			this.compilerBinding = null;
			return;
		}
		if (arguments.length != this.methodBinding.typeVariables().length)
			this.methodBinding = this.environment.createParameterizedGenericMethod(this.methodBinding, (RawTypeBinding) null);
		else
	 		this.methodBinding = this.environment.createParameterizedGenericMethod(this.methodBinding, arguments);
		this.compilerBinding = this.methodBinding;
	}

	@Override
	public void consumeLocalType(char[] uniqueKey) {
		if (this.parsedUnit == null) {
			this.typeBinding = null;
			return;
		}
 		LocalTypeBinding[] localTypeBindings  = this.parsedUnit.localTypes;
 		for (int i = 0; i < this.parsedUnit.localTypeCount; i++)
 			if (CharOperation.equals(uniqueKey, localTypeBindings[i].computeUniqueKey(false/*not a leaf*/))) {
 				this.typeBinding = localTypeBindings[i];
 				return;
 			}
	}

	@Override
	public void consumeLocalVar(char[] varName, int occurrenceCount, int argumentPosition) {
		if (this.scope == null) {
			if (this.methodBinding == null)
				return;
			AbstractMethodDeclaration sourceMethod = this.methodBinding.sourceMethod();
			if (sourceMethod != null) {
				this.scope = sourceMethod.scope;
			} else {
				char[][] parameterNames = this.methodBinding.parameterNames;
				int paramPosition = -1;
				if (parameterNames.length == 0) {
					paramPosition = argumentPosition;
				} else {
					for (int i = 0; i < parameterNames.length; i++) {
						if (CharOperation.equals(parameterNames[i], varName)) {
							paramPosition = i;
							break;
						}
					}
				}
				if (paramPosition != -1) {
					// we don't have a compiler binding for this argument, but we can craft one:
					this.compilerBinding = new SyntheticLocalVariableBinding(varName, this.methodBinding.parameters[paramPosition], this.methodBinding, paramPosition);
					this.methodBinding = null;
					return;
				}
			}
		}
		if (this.scope != null) {
		 	for (int i = 0; i < this.scope.localIndex; i++) {
				LocalVariableBinding local = this.scope.locals[i];
				if (CharOperation.equals(local.name, varName)
						&& occurrenceCount-- == 0) {
					this.methodBinding = null;
					this.compilerBinding = local;
					return;
				}
			}
		}
	}

	@Override
	public void consumeMethod(char[] selector, char[] signature) {
		if (this.typeBinding == null)
			return;
		MethodBinding[] methods = ((ReferenceBinding) this.typeBinding).availableMethods(); // resilience
	 	for (int i = 0, methodLength = methods.length; i < methodLength; i++) {
			MethodBinding method = methods[i];
			if (CharOperation.equals(selector, method.selector) || (selector.length == 0 && method.isConstructor())) {
				char[] methodSignature = method.genericSignature();
				if (methodSignature == null)
					methodSignature = method.signature();
				if (CharOperation.equals(signature, methodSignature)) {
					this.typeBinding = null;
					this.methodBinding = method;
					this.compilerBinding = this.methodBinding;
					return;
				} else if ((method.tagBits & TagBits.AnnotationPolymorphicSignature) != 0) {
					this.typeBinding = null;
					char[][] typeParameters = Signature.getParameterTypes(signature);
					int length = typeParameters.length;
					TypeBinding[] parameterTypes = new TypeBinding[length];
					for (int j = 0; j < length; j++) {
						parameterTypes[j] = getType(typeParameters[j]);
					}
					PolymorphicMethodBinding polymorphicMethod = this.environment.createPolymorphicMethod(method, parameterTypes, this.scope);
					this.methodBinding = polymorphicMethod;
					this.methodBinding = this.environment.updatePolymorphicMethodReturnType(
							polymorphicMethod,
							getType(Signature.getReturnType(signature)));
					this.compilerBinding = this.methodBinding;
					return;
				}
			}
		}
	}

	private TypeBinding getType(char[] type) {
		TypeBinding binding = null;
		int length = type.length;
		switch(length) {
			case 1 :
				switch (type[0]) {
					case 'I' :
						binding = TypeBinding.INT;
						break;
					case 'Z' :
						binding = TypeBinding.BOOLEAN;
						break;
					case 'V' :
						binding = TypeBinding.VOID;
						break;
					case 'C' :
						binding = TypeBinding.CHAR;
						break;
					case 'D' :
						binding = TypeBinding.DOUBLE;
						break;
					case 'B' :
						binding = TypeBinding.BYTE;
						break;
					case 'F' :
						binding = TypeBinding.FLOAT;
						break;
					case 'J' :
						binding = TypeBinding.LONG;
						break;
					case 'S' :
						binding = TypeBinding.SHORT;
						break;
				}
				break;
			default:
				int dimensions = 0;
				int start = 0;
				while (type[start] == '[') {
					start++;
					dimensions++;
				}
				binding = this.environment.getType(CharOperation.splitOn('/', type, start + 1, length - 1));
				if (dimensions != 0) {
					binding = this.environment.createArrayType(binding, dimensions);
				}
		}
		return binding;
	}
	@Override
	public void consumeMemberType(char[] simpleTypeName) {
		this.typeBinding = getTypeBinding(simpleTypeName);
	}

	@Override
	public void consumePackage(char[] pkgName) {
		this.compoundName = CharOperation.splitOn('/', pkgName);
		this.compilerBinding = new PlainPackageBinding(this.compoundName, null, this.environment, this.environment.module); //TODO(SHMOD) enclosingModule
	}

	@Override
	public void consumeParameterizedType(char[] simpleTypeName, boolean isRaw) {
		if (this.typeBinding == null)
			return;
		TypeBinding[] arguments = getTypeBindingArguments();
		if (arguments == null) {
			this.typeBinding = null;
			this.genericType = null;
			return;
		}
		if (simpleTypeName != null) {
			if (this.genericType == null) {
				// parameterized member type with raw enclosing type
				this.genericType = ((ReferenceBinding) this.typeBinding).getMemberType(simpleTypeName);
			} else {
				// parameterized member type with parameterized enclosing type
				this.genericType = this.genericType.getMemberType(simpleTypeName);
			}
			if (!isRaw)
				this.typeBinding = this.environment.createParameterizedType(this.genericType, arguments, (ReferenceBinding) this.typeBinding);
			else
				// raw type
				this.typeBinding = this.environment.createRawType(this.genericType, (ReferenceBinding) this.typeBinding);
		} else {
			// parameterized top level type or parameterized member type with raw enclosing type
			this.genericType = (ReferenceBinding) this.typeBinding;
			ReferenceBinding enclosing = this.genericType.enclosingType();
			if (enclosing != null) enclosing = (ReferenceBinding) this.environment.convertToRawType(enclosing, false /*do not force conversion of enclosing types*/);
			this.typeBinding = this.environment.createParameterizedType(this.genericType, arguments, enclosing);
		}
	}


	@Override
	public void consumeParser(BindingKeyParser parser) {
		this.types.add(parser);
	}

	@Override
	public void consumeScope(int scopeNumber) {
		if (this.scope == null) {
			if (this.methodBinding == null)
				return;
			this.scope = this.methodBinding.sourceMethod().scope;
		}
		if (scopeNumber >= this.scope.subscopeCount)
			return; // malformed key
		this.scope = (BlockScope) this.scope.subscopes[scopeNumber];
	}

	@Override
	public void consumeRawType() {
		if (this.typeBinding == null) return;
		this.typeBinding = this.environment.convertToRawType(this.typeBinding, false /*do not force conversion of enclosing types*/);
	}
	@Override
	public void consumeSecondaryType(char[] simpleTypeName) {
		this.secondarySimpleName = simpleTypeName;
	}

	@Override
	public void consumeFullyQualifiedName(char[] fullyQualifiedName) {
		this.compoundName = CharOperation.splitOn('/', fullyQualifiedName);
	}

	@Override
	public void consumeTopLevelType() {
		char[] fileName;
		this.parsedUnit = getCompilationUnitDeclaration();
		if (this.parsedUnit != null && this.compiler != null && !this.resolvedUnits.containsKey(fileName = this.parsedUnit.getFileName())) {
			this.compiler.process(this.parsedUnit, this.compiler.totalUnits+1); // unit is resolved only once thanks to the resolvedUnits protection
			this.resolvedUnits.put(fileName, fileName);
		}
		if (this.parsedUnit == null) {
			this.typeBinding = getBinaryBinding();
		} else {
			char[] typeName = this.secondarySimpleName == null ? this.compoundName[this.compoundName.length-1] : this.secondarySimpleName;
			this.typeBinding = getTypeBinding(typeName);
		}
	}

	@Override
	public void consumeKey() {
		if (this.typeBinding != null) {
			this.typeBinding = getArrayBinding(this.dimension, this.typeBinding);
			this.compilerBinding = this.typeBinding;
		}
	}

	@Override
	public void consumeTypeVariable(char[] position, char[] typeVariableName) {
		if (position.length > 0) {
			if (this.typeBinding == null)
				return;
			int pos = Integer.parseInt(new String(position));
			MethodBinding[] methods = ((ReferenceBinding) this.typeBinding).availableMethods(); // resilience
			if (methods != null && pos < methods.length) {
				this.methodBinding = methods[pos];
			}
		}
	 	TypeVariableBinding[] typeVariableBindings;
	 	if (this.methodBinding != null) {
	 		typeVariableBindings = this.methodBinding.typeVariables();
	 	} else if (this.typeBinding != null) {
	 		typeVariableBindings = this.typeBinding.typeVariables();
	 	} else {
	 		return;
	 	}
	 	for (int i = 0, length = typeVariableBindings.length; i < length; i++) {
			TypeVariableBinding typeVariableBinding = typeVariableBindings[i];
			if (CharOperation.equals(typeVariableName, typeVariableBinding.sourceName())) {
				this.typeBinding = typeVariableBinding;
				return;
			}
		}
	}

	@Override
	public void consumeTypeWithCapture() {
		BindingKeyResolver resolver = (BindingKeyResolver) this.types.get(0);
		this.typeBinding =(TypeBinding) resolver.compilerBinding;
	}

	@Override
	public void consumeWildcardRank(int aRank) {
		this.wildcardRank = aRank;
	}

	@Override
	public void consumeWildCard(int kind) {
		switch (kind) {
			case Wildcard.EXTENDS:
			case Wildcard.SUPER:
				BindingKeyResolver boundResolver = (BindingKeyResolver) this.types.get(0);
				// https://bugs.eclipse.org/bugs/show_bug.cgi?id=157847, do not allow creation of
				// internally inconsistent wildcards of the form '? super <null>' or '? extends <null>'
				final Binding boundBinding = boundResolver.compilerBinding;
				if (boundBinding instanceof TypeBinding) {
					this.typeBinding = this.environment.createWildcard((ReferenceBinding) this.typeBinding, this.wildcardRank, (TypeBinding) boundBinding, null /*no extra bound*/, kind);
				} else {
					this.typeBinding = null;
				}
				break;
			case Wildcard.UNBOUND:
				this.typeBinding = this.environment.createWildcard((ReferenceBinding) this.typeBinding, this.wildcardRank, null/*no bound*/, null /*no extra bound*/, kind);
				break;
		}
	}

	@Override
	public void consumeModule(char[] aModuleName) {
		this.moduleName = aModuleName;
		this.compilerBinding = this.environment.getModule(aModuleName);
	}

	public AnnotationBinding getAnnotationBinding() {
		return this.annotationBinding;
	}

	/*
	 * If the given dimension is greater than 0 returns an array binding for the given type binding.
	 * Otherwise return the given type binding.
	 * Returns null if the given type binding is null.
	 */
	private TypeBinding getArrayBinding(int dim, TypeBinding binding) {
		if (binding == null) return null;
		if (dim == 0) return binding;
		return this.environment.createArrayType(binding, dim);
	}

	private TypeBinding getBaseTypeBinding(char[] signature) {
		switch (signature[0]) {
			case 'I' :
				return TypeBinding.INT;
			case 'Z' :
				return TypeBinding.BOOLEAN;
			case 'V' :
				return TypeBinding.VOID;
			case 'C' :
				return TypeBinding.CHAR;
			case 'D' :
				return TypeBinding.DOUBLE;
			case 'B' :
				return TypeBinding.BYTE;
			case 'F' :
				return TypeBinding.FLOAT;
			case 'J' :
				return TypeBinding.LONG;
			case 'S' :
				return TypeBinding.SHORT;
			case 'N':
				return TypeBinding.NULL;
			default :
				return null;
		}
	}

	/*
	 * Returns a binary binding corresonding to this key's compound name.
	 * Returns null if not found.
	 */
	private TypeBinding getBinaryBinding() {
		if (this.compoundName.length == 0) return null;
		return this.environment.getType(this.compoundName);
	}

	/*
	 * Finds the compilation unit declaration corresponding to the key in the given lookup environment.
	 * Returns null if no compilation unit declaration could be found.
	 * This key's scanner should be positioned on the package token.
	 */
	public CompilationUnitDeclaration getCompilationUnitDeclaration() {
		char[][] name = this.compoundName;
		if (name.length == 0) return null;
		if (this.environment == null) return null;
		ReferenceBinding binding = this.environment.getType(name);
		if (!(binding instanceof SourceTypeBinding)) {
			if (this.secondarySimpleName == null)
				return null;
			// case of a secondary type with no primary type (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=177115)
			int length = name.length;
			System.arraycopy(name, 0, name = new char[length][], 0, length-1);
			name[length-1] = this.secondarySimpleName;
			binding = this.environment.getType(name);
			if (!(binding instanceof SourceTypeBinding))
				return null;
		}
		SourceTypeBinding sourceTypeBinding = (SourceTypeBinding) binding;
		if (sourceTypeBinding.scope == null)
			return null;
		return sourceTypeBinding.scope.compilationUnitScope().referenceContext;
	}

	/*
	 * Returns the compiler binding corresponding to this key.
	 * Returns null is malformed.
	 * This key's scanner should be positioned on the package token.
	 */
	public Binding getCompilerBinding() {
		try {
			parse();
			return this.compilerBinding;
		} catch (RuntimeException e) {
			Util.log(e, "Could not create binding from binding key: " + getKey()); //$NON-NLS-1$
			return null;
		}
	}

	private TypeBinding getTypeBinding(char[] simpleTypeName) {
		if (this.typeBinding instanceof ReferenceBinding) {
			return ((ReferenceBinding) this.typeBinding).getMemberType(simpleTypeName);
		}
		TypeDeclaration[] typeDeclarations =
			this.typeDeclaration == null ?
				(this.parsedUnit == null ? null : this.parsedUnit.types) :
				this.typeDeclaration.memberTypes;
		if (typeDeclarations == null) return null;
		for (int i = 0, length = typeDeclarations.length; i < length; i++) {
			TypeDeclaration declaration = typeDeclarations[i];
			if (CharOperation.equals(simpleTypeName, declaration.name)) {
				this.typeDeclaration = declaration;
				return declaration.binding;
			}
		}
		return null;
	}

	private TypeBinding[] getTypeBindingArguments() {
		int size = this.types.size();
		TypeBinding[] arguments = new TypeBinding[size];
		for (int i = 0; i < size; i++) {
			BindingKeyResolver resolver = (BindingKeyResolver) this.types.get(i);
			TypeBinding compilerBinding2 = (TypeBinding) resolver.compilerBinding;
			if (compilerBinding2 == null) {
				this.types = new ArrayList();
				return null;
			}
			arguments[i] = compilerBinding2;
		}
		this.types = new ArrayList();
		return arguments;
	}

	@Override
	public void malformedKey() {
		this.compoundName = CharOperation.NO_CHAR_CHAR;
	}

	@Override
	public BindingKeyParser newParser() {
		return new BindingKeyResolver(this, this.compiler, this.environment, this.outerMostParsedUnit == null ? this.parsedUnit : this.outerMostParsedUnit, this.resolvedUnits);
	}

	@Override
	public String toString() {
		return getKey();
	}

}
