/*******************************************************************************
 * Copyright (c) 2000, 2011 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
 *******************************************************************************/
package org.eclipse.jdt.internal.core;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Stack;

import org.eclipse.core.runtime.Assert;
import org.eclipse.jdt.core.Flags;
import org.eclipse.jdt.core.IAnnotation;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IMemberValuePair;
import org.eclipse.jdt.core.ITypeParameter;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.core.compiler.CategorizedProblem;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.core.compiler.IProblem;
import org.eclipse.jdt.internal.compiler.ISourceElementRequestor;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.Argument;
import org.eclipse.jdt.internal.compiler.ast.ArrayInitializer;
import org.eclipse.jdt.internal.compiler.ast.ClassLiteralAccess;
import org.eclipse.jdt.internal.compiler.ast.Expression;
import org.eclipse.jdt.internal.compiler.ast.ImportReference;
import org.eclipse.jdt.internal.compiler.ast.Literal;
import org.eclipse.jdt.internal.compiler.ast.MemberValuePair;
import org.eclipse.jdt.internal.compiler.ast.NullLiteral;
import org.eclipse.jdt.internal.compiler.ast.OperatorIds;
import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference;
import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
import org.eclipse.jdt.internal.compiler.ast.UnaryExpression;
import org.eclipse.jdt.internal.compiler.parser.Parser;
import org.eclipse.jdt.internal.compiler.parser.RecoveryScanner;
import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
import org.eclipse.jdt.internal.compiler.util.HashtableOfObjectToInt;
import org.eclipse.jdt.internal.core.util.ReferenceInfoAdapter;
import org.eclipse.jdt.internal.core.util.Util;
/**
 * A requestor for the fuzzy parser, used to compute the children of an ICompilationUnit.
 */
public class CompilationUnitStructureRequestor extends ReferenceInfoAdapter implements ISourceElementRequestor {
	
	/**
	 * The handle to the compilation unit being parsed
	 */
	protected ICompilationUnit unit;

	/**
	 * The info object for the compilation unit being parsed
	 */
	protected CompilationUnitElementInfo unitInfo;

	/**
	 * The import container info - null until created
	 */
	protected ImportContainerInfo importContainerInfo = null;
	protected ImportContainer importContainer;

	/**
	 * Hashtable of children elements of the compilation unit.
	 * Children are added to the table as they are found by
	 * the parser. Keys are handles, values are corresponding
	 * info objects.
	 */
	protected Map newElements;

	/*
	 * A table from a handle (with occurenceCount == 1) to the current occurence count for this handle
	 */
	private HashtableOfObjectToInt occurenceCounts;

	/**
	 * Stack of parent scope info objects. The info on the
	 * top of the stack is the parent of the next element found.
	 * For example, when we locate a method, the parent info object
	 * will be the type the method is contained in.
	 */
	protected Stack infoStack;

	/*
	 * Map from info to of ArrayList of IJavaElement representing the children
	 * of the given info.
	 */
	protected HashMap children;

	/**
	 * Stack of parent handles, corresponding to the info stack. We
	 * keep both, since info objects do not have back pointers to
	 * handles.
	 */
	protected Stack handleStack;

	/**
	 * The number of references reported thus far. Used to
	 * expand the arrays of reference kinds and names.
	 */
	protected int referenceCount= 0;

	/**
	 * Problem requestor which will get notified of discovered problems
	 */
	protected boolean hasSyntaxErrors = false;

	/*
	 * The parser this requestor is using.
	 */
	protected Parser parser;

	protected HashtableOfObject fieldRefCache;
	protected HashtableOfObject messageRefCache;
	protected HashtableOfObject typeRefCache;
	protected HashtableOfObject unknownRefCache;

protected CompilationUnitStructureRequestor(ICompilationUnit unit, CompilationUnitElementInfo unitInfo, Map newElements) {
	this.unit = unit;
	this.unitInfo = unitInfo;
	this.newElements = newElements;
	this.occurenceCounts = new HashtableOfObjectToInt();
}
/**
 * @see ISourceElementRequestor
 */
public void acceptImport(int declarationStart, int declarationEnd, int nameSourceStart, int nameSourceEnd, char[][] tokens, boolean onDemand, int modifiers) {
	JavaElement parentHandle= (JavaElement) this.handleStack.peek();
	if (!(parentHandle.getElementType() == IJavaElement.COMPILATION_UNIT)) {
		Assert.isTrue(false); // Should not happen
	}

	ICompilationUnit parentCU= (ICompilationUnit)parentHandle;
	//create the import container and its info
	if (this.importContainer == null) {
		this.importContainer = createImportContainer(parentCU);
		this.importContainerInfo = new ImportContainerInfo();
		Object parentInfo = this.infoStack.peek();
		addToChildren(parentInfo, this.importContainer);
		this.newElements.put(this.importContainer, this.importContainerInfo);
	}

	String elementName = JavaModelManager.getJavaModelManager().intern(new String(CharOperation.concatWith(tokens, '.')));
	ImportDeclaration handle = createImportDeclaration(this.importContainer, elementName, onDemand);
	resolveDuplicates(handle);

	ImportDeclarationElementInfo info = new ImportDeclarationElementInfo();
	info.setSourceRangeStart(declarationStart);
	info.setSourceRangeEnd(declarationEnd);
	info.setNameSourceStart(nameSourceStart);
	info.setNameSourceEnd(nameSourceEnd);
	info.setFlags(modifiers);

	addToChildren(this.importContainerInfo, handle);
	this.newElements.put(handle, info);
}
/*
 * Table of line separator position. This table is passed once at the end
 * of the parse action, so as to allow computation of normalized ranges.
 *
 * A line separator might corresponds to several characters in the source,
 *
 */
public void acceptLineSeparatorPositions(int[] positions) {
	// ignore line separator positions
}
/**
 * @see ISourceElementRequestor
 */
public void acceptPackage(ImportReference importReference) {

		Object parentInfo = this.infoStack.peek();
		JavaElement parentHandle= (JavaElement) this.handleStack.peek();
		PackageDeclaration handle = null;

		if (parentHandle.getElementType() == IJavaElement.COMPILATION_UNIT) {
			char[] name = CharOperation.concatWith(importReference.getImportName(), '.');
			handle = createPackageDeclaration(parentHandle, new String(name));
		}
		else {
			Assert.isTrue(false); // Should not happen
		}
		resolveDuplicates(handle);

		AnnotatableInfo info = new AnnotatableInfo();
		info.setSourceRangeStart(importReference.declarationSourceStart);
		info.setSourceRangeEnd(importReference.declarationSourceEnd);
		info.setNameSourceStart(importReference.sourceStart);
		info.setNameSourceEnd(importReference.sourceEnd);

		addToChildren(parentInfo, handle);
		this.newElements.put(handle, info);

		if (importReference.annotations != null) {
			for (int i = 0, length = importReference.annotations.length; i < length; i++) {
				org.eclipse.jdt.internal.compiler.ast.Annotation annotation = importReference.annotations[i];
				acceptAnnotation(annotation, info, handle);
			}
		}
}
public void acceptProblem(CategorizedProblem problem) {
	if ((problem.getID() & IProblem.Syntax) != 0){
		this.hasSyntaxErrors = true;
	}
}
private void addToChildren(Object parentInfo, JavaElement handle) {
	ArrayList childrenList = (ArrayList) this.children.get(parentInfo);
	if (childrenList == null)
		this.children.put(parentInfo, childrenList = new ArrayList());
	childrenList.add(handle);
}
protected Annotation createAnnotation(JavaElement parent, String name) {
	return new Annotation(parent, name);
}
protected SourceField createField(JavaElement parent, FieldInfo fieldInfo) {
	String fieldName = JavaModelManager.getJavaModelManager().intern(new String(fieldInfo.name));
	return new SourceField(parent, fieldName);
}
protected ImportContainer createImportContainer(ICompilationUnit parent) {
	return (ImportContainer)parent.getImportContainer();
}
protected ImportDeclaration createImportDeclaration(ImportContainer parent, String name, boolean onDemand) {
	return new ImportDeclaration(parent, name, onDemand);
}
protected Initializer createInitializer(JavaElement parent) {
	return new Initializer(parent, 1);
}
protected SourceMethod createMethodHandle(JavaElement parent, MethodInfo methodInfo) {
	String selector = JavaModelManager.getJavaModelManager().intern(new String(methodInfo.name));
	String[] parameterTypeSigs = convertTypeNamesToSigs(methodInfo.parameterTypes);
	return new SourceMethod(parent, selector, parameterTypeSigs);
}
protected PackageDeclaration createPackageDeclaration(JavaElement parent, String name) {
	return new PackageDeclaration((CompilationUnit) parent, name);
}
protected SourceType createTypeHandle(JavaElement parent, TypeInfo typeInfo) {
	String nameString= new String(typeInfo.name);
	return new SourceType(parent, nameString);
}
protected TypeParameter createTypeParameter(JavaElement parent, String name) {
	return new TypeParameter(parent, name);
}
/**
 * Convert these type names to signatures.
 * @see Signature
 */
protected static String[] convertTypeNamesToSigs(char[][] typeNames) {
	if (typeNames == null)
		return CharOperation.NO_STRINGS;
	int n = typeNames.length;
	if (n == 0)
		return CharOperation.NO_STRINGS;
	JavaModelManager manager = JavaModelManager.getJavaModelManager();
	String[] typeSigs = new String[n];
	for (int i = 0; i < n; ++i) {
		typeSigs[i] = manager.intern(Signature.createTypeSignature(typeNames[i], false));
	}
	return typeSigs;
}
protected IAnnotation acceptAnnotation(org.eclipse.jdt.internal.compiler.ast.Annotation annotation, AnnotatableInfo parentInfo, JavaElement parentHandle) {
	String nameString = new String(CharOperation.concatWith(annotation.type.getTypeName(), '.'));
	Annotation handle = createAnnotation(parentHandle, nameString); //NB: occurenceCount is computed in resolveDuplicates
	resolveDuplicates(handle);

	AnnotationInfo info = new AnnotationInfo();

	// populate the maps here as getValue(...) below may need them
	this.newElements.put(handle, info);
	this.handleStack.push(handle);

	info.setSourceRangeStart(annotation.sourceStart());
	info.nameStart = annotation.type.sourceStart();
	info.nameEnd = annotation.type.sourceEnd();
	MemberValuePair[] memberValuePairs = annotation.memberValuePairs();
	int membersLength = memberValuePairs.length;
	if (membersLength == 0) {
		info.members = Annotation.NO_MEMBER_VALUE_PAIRS;
	} else {
		info.members = getMemberValuePairs(memberValuePairs);
	}

	if (parentInfo != null) {
		IAnnotation[] annotations = parentInfo.annotations;
		int length = annotations.length;
		System.arraycopy(annotations, 0, annotations = new IAnnotation[length+1], 0, length);
		annotations[length] = handle;
		parentInfo.annotations = annotations;
	}
	info.setSourceRangeEnd(annotation.declarationSourceEnd);
	this.handleStack.pop();
	return handle;
}
/**
 * @see ISourceElementRequestor
 */
public void enterCompilationUnit() {
	this.infoStack = new Stack();
	this.children = new HashMap();
	this.handleStack= new Stack();
	this.infoStack.push(this.unitInfo);
	this.handleStack.push(this.unit);
}
/**
 * @see ISourceElementRequestor
 */
public void enterConstructor(MethodInfo methodInfo) {
	enterMethod(methodInfo);
}
/**
 * @see ISourceElementRequestor
 */
public void enterField(FieldInfo fieldInfo) {

	TypeInfo parentInfo = (TypeInfo) this.infoStack.peek();
	JavaElement parentHandle= (JavaElement) this.handleStack.peek();
	SourceField handle = null;
	if (parentHandle.getElementType() == IJavaElement.TYPE) {
		handle = createField(parentHandle, fieldInfo);
	}
	else {
		Assert.isTrue(false); // Should not happen
	}
	resolveDuplicates(handle);

	addToChildren(parentInfo, handle);
	parentInfo.childrenCategories.put(handle, fieldInfo.categories);

	this.infoStack.push(fieldInfo);
	this.handleStack.push(handle);

}
/**
 * @see ISourceElementRequestor
 */
public void enterInitializer(int declarationSourceStart, int modifiers) {
	Object parentInfo = this.infoStack.peek();
	JavaElement parentHandle= (JavaElement) this.handleStack.peek();
	Initializer handle = null;

	if (parentHandle.getElementType() == IJavaElement.TYPE) {
		handle = createInitializer(parentHandle);
	}
	else {
		Assert.isTrue(false); // Should not happen
	}
	resolveDuplicates(handle);
	
	addToChildren(parentInfo, handle);

	this.infoStack.push(new int[] {declarationSourceStart, modifiers});
	this.handleStack.push(handle);
}
/**
 * @see ISourceElementRequestor
 */
public void enterMethod(MethodInfo methodInfo) {

	TypeInfo parentInfo = (TypeInfo) this.infoStack.peek();
	JavaElement parentHandle= (JavaElement) this.handleStack.peek();
	SourceMethod handle = null;

	// translate nulls to empty arrays
	if (methodInfo.parameterTypes == null) {
		methodInfo.parameterTypes= CharOperation.NO_CHAR_CHAR;
	}
	if (methodInfo.parameterNames == null) {
		methodInfo.parameterNames= CharOperation.NO_CHAR_CHAR;
	}
	if (methodInfo.exceptionTypes == null) {
		methodInfo.exceptionTypes= CharOperation.NO_CHAR_CHAR;
	}

	if (parentHandle.getElementType() == IJavaElement.TYPE) {
		handle = createMethodHandle(parentHandle, methodInfo);
	}
	else {
		Assert.isTrue(false); // Should not happen
	}
	resolveDuplicates(handle);

	this.infoStack.push(methodInfo);
	this.handleStack.push(handle);
	
	addToChildren(parentInfo, handle);
	parentInfo.childrenCategories.put(handle, methodInfo.categories);
}
private SourceMethodElementInfo createMethodInfo(MethodInfo methodInfo, SourceMethod handle) {
	IJavaElement[] elements = getChildren(methodInfo);
	SourceMethodElementInfo info;
	if (methodInfo.isConstructor) {
		info = elements.length == 0 ? new SourceConstructorInfo() : new SourceConstructorWithChildrenInfo(elements);
	} else if (methodInfo.isAnnotation) {
		info = new SourceAnnotationMethodInfo();
	} else {
		info = elements.length == 0 ? new SourceMethodInfo() : new SourceMethodWithChildrenInfo(elements);
	}
	info.setSourceRangeStart(methodInfo.declarationStart);
	int flags = methodInfo.modifiers;
	info.setNameSourceStart(methodInfo.nameSourceStart);
	info.setNameSourceEnd(methodInfo.nameSourceEnd);
	info.setFlags(flags);
	JavaModelManager manager = JavaModelManager.getJavaModelManager();
	char[][] parameterNames = methodInfo.parameterNames;
	for (int i = 0, length = parameterNames.length; i < length; i++)
		parameterNames[i] = manager.intern(parameterNames[i]);
	info.setArgumentNames(parameterNames);
	char[] returnType = methodInfo.returnType == null ? new char[]{'v', 'o','i', 'd'} : methodInfo.returnType;
	info.setReturnType(manager.intern(returnType));
	char[][] exceptionTypes = methodInfo.exceptionTypes;
	info.setExceptionTypeNames(exceptionTypes);
	for (int i = 0, length = exceptionTypes.length; i < length; i++)
		exceptionTypes[i] = manager.intern(exceptionTypes[i]);
	this.newElements.put(handle, info);

	if (methodInfo.typeParameters != null) {
		for (int i = 0, length = methodInfo.typeParameters.length; i < length; i++) {
			TypeParameterInfo typeParameterInfo = methodInfo.typeParameters[i];
			acceptTypeParameter(typeParameterInfo, info);
		}
	}
	if (methodInfo.annotations != null) {
		int length = methodInfo.annotations.length;
		this.unitInfo.annotationNumber += length;
		for (int i = 0; i < length; i++) {
			org.eclipse.jdt.internal.compiler.ast.Annotation annotation = methodInfo.annotations[i];
			acceptAnnotation(annotation, info, handle);
		}
	}
	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=334783
	// Process the parameter annotations from the arguments
	if (methodInfo.node != null && methodInfo.node.arguments != null) {
		info.arguments = acceptMethodParameters(methodInfo.node.arguments, handle, methodInfo);
	}
	return info;
}
private LocalVariable[] acceptMethodParameters(Argument[] arguments, JavaElement methodHandle, MethodInfo methodInfo) {
	if (arguments == null) return null;
	LocalVariable[] result = new LocalVariable[arguments.length];
	Annotation[][] paramAnnotations = new Annotation[arguments.length][];
	for(int i = 0; i < arguments.length; i++) {
		Argument argument = arguments[i];
		AnnotatableInfo localVarInfo = new AnnotatableInfo();
		localVarInfo.setSourceRangeStart(argument.declarationSourceStart);
		localVarInfo.setSourceRangeEnd(argument.declarationSourceStart);
		localVarInfo.setNameSourceStart(argument.sourceStart);
		localVarInfo.setNameSourceEnd(argument.sourceEnd);
		
		String paramTypeSig = JavaModelManager.getJavaModelManager().intern(Signature.createTypeSignature(methodInfo.parameterTypes[i], false));
		result[i] = new LocalVariable(
				methodHandle,
				new String(argument.name),
				argument.declarationSourceStart,
				argument.declarationSourceEnd,
				argument.sourceStart,
				argument.sourceEnd,
				paramTypeSig,
				argument.annotations,
				argument.modifiers, 
				true);
		this.newElements.put(result[i], localVarInfo);
		this.infoStack.push(localVarInfo);
		this.handleStack.push(result[i]);
		if (argument.annotations != null) {
			paramAnnotations[i] = new Annotation[argument.annotations.length];
			for (int  j = 0; j < argument.annotations.length; j++ ) {
				org.eclipse.jdt.internal.compiler.ast.Annotation annotation = argument.annotations[j];
				acceptAnnotation(annotation, localVarInfo, result[i]);
			}
		}
		this.infoStack.pop();
		this.handleStack.pop();
	}
	return result;
}

/**
 * @see ISourceElementRequestor
 */
public void enterType(TypeInfo typeInfo) {

	Object parentInfo = this.infoStack.peek();
	JavaElement parentHandle= (JavaElement) this.handleStack.peek();
	SourceType handle = createTypeHandle(parentHandle, typeInfo); //NB: occurenceCount is computed in resolveDuplicates
	resolveDuplicates(handle);

	this.infoStack.push(typeInfo);
	this.handleStack.push(handle);

	if (parentHandle.getElementType() == IJavaElement.TYPE)
		((TypeInfo) parentInfo).childrenCategories.put(handle, typeInfo.categories);
	addToChildren(parentInfo, handle);
}
private SourceTypeElementInfo createTypeInfo(TypeInfo typeInfo, SourceType handle) {
	SourceTypeElementInfo info =
		typeInfo.anonymousMember ?
			new SourceTypeElementInfo() {
				public boolean isAnonymousMember() {
					return true;
				}
			} :
		new SourceTypeElementInfo();
	info.setHandle(handle);
	info.setSourceRangeStart(typeInfo.declarationStart);
	info.setFlags(typeInfo.modifiers);
	info.setNameSourceStart(typeInfo.nameSourceStart);
	info.setNameSourceEnd(typeInfo.nameSourceEnd);
	JavaModelManager manager = JavaModelManager.getJavaModelManager();
	char[] superclass = typeInfo.superclass;
	info.setSuperclassName(superclass == null ? null : manager.intern(superclass));
	char[][] superinterfaces = typeInfo.superinterfaces;
	for (int i = 0, length = superinterfaces == null ? 0 : superinterfaces.length; i < length; i++)
		superinterfaces[i] = manager.intern(superinterfaces[i]);
	info.setSuperInterfaceNames(superinterfaces);
	info.addCategories(handle, typeInfo.categories);
	this.newElements.put(handle, info);

	if (typeInfo.typeParameters != null) {
		for (int i = 0, length = typeInfo.typeParameters.length; i < length; i++) {
			TypeParameterInfo typeParameterInfo = typeInfo.typeParameters[i];
			acceptTypeParameter(typeParameterInfo, info);
		}
	}
	if (typeInfo.annotations != null) {
		int length = typeInfo.annotations.length;
		this.unitInfo.annotationNumber += length;
		for (int i = 0; i < length; i++) {
			org.eclipse.jdt.internal.compiler.ast.Annotation annotation = typeInfo.annotations[i];
			acceptAnnotation(annotation, info, handle);
		}
	}
	if (typeInfo.childrenCategories != null) {
		Iterator iterator = typeInfo.childrenCategories.entrySet().iterator();
		while (iterator.hasNext()) {
			Map.Entry entry = (Map.Entry) iterator.next();
			info.addCategories((IJavaElement) entry.getKey(), (char[][]) entry.getValue());
		}
		
	}
	return info;
}
protected void acceptTypeParameter(TypeParameterInfo typeParameterInfo, JavaElementInfo parentInfo) {
	JavaElement parentHandle = (JavaElement) this.handleStack.peek();
	String nameString = new String(typeParameterInfo.name);
	TypeParameter handle = createTypeParameter(parentHandle, nameString); //NB: occurenceCount is computed in resolveDuplicates
	resolveDuplicates(handle);

	TypeParameterElementInfo info = new TypeParameterElementInfo();
	info.setSourceRangeStart(typeParameterInfo.declarationStart);
	info.nameStart = typeParameterInfo.nameSourceStart;
	info.nameEnd = typeParameterInfo.nameSourceEnd;
	info.bounds = typeParameterInfo.bounds;
	if (parentInfo instanceof SourceTypeElementInfo) {
		SourceTypeElementInfo elementInfo = (SourceTypeElementInfo) parentInfo;
		ITypeParameter[] typeParameters = elementInfo.typeParameters;
		int length = typeParameters.length;
		System.arraycopy(typeParameters, 0, typeParameters = new ITypeParameter[length+1], 0, length);
		typeParameters[length] = handle;
		elementInfo.typeParameters = typeParameters;
	} else {
		SourceMethodElementInfo elementInfo = (SourceMethodElementInfo) parentInfo;
		ITypeParameter[] typeParameters = elementInfo.typeParameters;
		int length = typeParameters.length;
		System.arraycopy(typeParameters, 0, typeParameters = new ITypeParameter[length+1], 0, length);
		typeParameters[length] = handle;
		elementInfo.typeParameters = typeParameters;
	}
	this.newElements.put(handle, info);
	info.setSourceRangeEnd(typeParameterInfo.declarationEnd);
}
/**
 * @see ISourceElementRequestor
 */
public void exitCompilationUnit(int declarationEnd) {
	// set import container children
	if (this.importContainerInfo != null) {
		this.importContainerInfo.children = getChildren(this.importContainerInfo);
	}

	this.unitInfo.children = getChildren(this.unitInfo);
	this.unitInfo.setSourceLength(declarationEnd + 1);

	// determine if there were any parsing errors
	this.unitInfo.setIsStructureKnown(!this.hasSyntaxErrors);
}
/**
 * @see ISourceElementRequestor
 */
public void exitConstructor(int declarationEnd) {
	exitMethod(declarationEnd, null);
}
/**
 * @see ISourceElementRequestor
 */
public void exitField(int initializationStart, int declarationEnd, int declarationSourceEnd) {
	JavaElement handle = (JavaElement) this.handleStack.peek();
	FieldInfo fieldInfo = (FieldInfo) this.infoStack.peek();
	IJavaElement[] elements = getChildren(fieldInfo);
	SourceFieldElementInfo info = elements.length == 0 ? new SourceFieldElementInfo() : new SourceFieldWithChildrenInfo(elements);
	info.setNameSourceStart(fieldInfo.nameSourceStart);
	info.setNameSourceEnd(fieldInfo.nameSourceEnd);
	info.setSourceRangeStart(fieldInfo.declarationStart);
	info.setFlags(fieldInfo.modifiers);
	char[] typeName = JavaModelManager.getJavaModelManager().intern(fieldInfo.type);
	info.setTypeName(typeName);
	this.newElements.put(handle, info);

	if (fieldInfo.annotations != null) {
		int length = fieldInfo.annotations.length;
		this.unitInfo.annotationNumber += length;
		for (int i = 0; i < length; i++) {
			org.eclipse.jdt.internal.compiler.ast.Annotation annotation = fieldInfo.annotations[i];
			acceptAnnotation(annotation, info, handle);
		}
	}
	info.setSourceRangeEnd(declarationSourceEnd);
	this.handleStack.pop();
	this.infoStack.pop();
	
	// remember initializer source if field is a constant
	if (initializationStart != -1) {
		int flags = info.flags;
		Object typeInfo;
		if (Flags.isStatic(flags) && Flags.isFinal(flags)
				|| ((typeInfo = this.infoStack.peek()) instanceof TypeInfo
					 && (Flags.isInterface(((TypeInfo)typeInfo).modifiers)))) {
			int length = declarationEnd - initializationStart;
			if (length > 0) {
				char[] initializer = new char[length];
				System.arraycopy(this.parser.scanner.source, initializationStart, initializer, 0, length);
				info.initializationSource = initializer;
			}
		}
	}
}
/**
 * @see ISourceElementRequestor
 */
public void exitInitializer(int declarationEnd) {
	JavaElement handle = (JavaElement) this.handleStack.peek();
	int[] initializerInfo = (int[]) this.infoStack.peek();
	IJavaElement[] elements = getChildren(initializerInfo);
	
	InitializerElementInfo info = elements.length == 0 ? new InitializerElementInfo() : new InitializerWithChildrenInfo(elements);
	info.setSourceRangeStart(initializerInfo[0]);
	info.setFlags(initializerInfo[1]);
	info.setSourceRangeEnd(declarationEnd);

	this.newElements.put(handle, info);
	
	this.handleStack.pop();
	this.infoStack.pop();
}
/**
 * @see ISourceElementRequestor
 */
public void exitMethod(int declarationEnd, Expression defaultValue) {
	SourceMethod handle = (SourceMethod) this.handleStack.peek();
	MethodInfo methodInfo = (MethodInfo) this.infoStack.peek();
	
	SourceMethodElementInfo info = createMethodInfo(methodInfo, handle);
	info.setSourceRangeEnd(declarationEnd);
	
	// remember default value of annotation method
	if (info.isAnnotationMethod() && defaultValue != null) {
		SourceAnnotationMethodInfo annotationMethodInfo = (SourceAnnotationMethodInfo) info;
		annotationMethodInfo.defaultValueStart = defaultValue.sourceStart;
		annotationMethodInfo.defaultValueEnd = defaultValue.sourceEnd;
		JavaElement element = (JavaElement) this.handleStack.peek();
		org.eclipse.jdt.internal.core.MemberValuePair defaultMemberValuePair = new org.eclipse.jdt.internal.core.MemberValuePair(element.getElementName());
		defaultMemberValuePair.value = getMemberValue(defaultMemberValuePair, defaultValue);
		annotationMethodInfo.defaultValue = defaultMemberValuePair;
	}
	
	this.handleStack.pop();
	this.infoStack.pop();
}
/**
 * @see ISourceElementRequestor
 */
public void exitType(int declarationEnd) {
	SourceType handle = (SourceType) this.handleStack.peek();
	TypeInfo typeInfo = (TypeInfo) this.infoStack.peek();
	SourceTypeElementInfo info = createTypeInfo(typeInfo, handle);
	info.setSourceRangeEnd(declarationEnd);
	info.children = getChildren(typeInfo);
	
	this.handleStack.pop();
	this.infoStack.pop();
}
/**
 * Resolves duplicate handles by incrementing the occurrence count
 * of the handle being created.
 */
protected void resolveDuplicates(SourceRefElement handle) {
	int occurenceCount = this.occurenceCounts.get(handle);
	if (occurenceCount == -1)
		this.occurenceCounts.put(handle, 1);
	else {
		this.occurenceCounts.put(handle, ++occurenceCount);
		handle.occurrenceCount = occurenceCount;
	}
}
protected IMemberValuePair getMemberValuePair(MemberValuePair memberValuePair) {
	String memberName = new String(memberValuePair.name);
	org.eclipse.jdt.internal.core.MemberValuePair result = new org.eclipse.jdt.internal.core.MemberValuePair(memberName);
	result.value = getMemberValue(result, memberValuePair.value);
	return result;
}
protected IMemberValuePair[] getMemberValuePairs(MemberValuePair[] memberValuePairs) {
	int membersLength = memberValuePairs.length;
	IMemberValuePair[] members = new IMemberValuePair[membersLength];
	for (int j = 0; j < membersLength; j++) {
		members[j] = getMemberValuePair(memberValuePairs[j]);
	}
	return members;
}
private IJavaElement[] getChildren(Object info) {
	ArrayList childrenList = (ArrayList) this.children.get(info);
	if (childrenList != null) {
		return (IJavaElement[]) childrenList.toArray(new IJavaElement[childrenList.size()]);
	}
	return JavaElement.NO_ELEMENTS;
}
/*
 * Creates the value from the given expression, and sets the valueKind on the given memberValuePair
 */
protected Object getMemberValue(org.eclipse.jdt.internal.core.MemberValuePair memberValuePair, Expression expression) {
	if (expression instanceof NullLiteral) {
		return null;
	} else if (expression instanceof Literal) {
		((Literal) expression).computeConstant();
		return Util.getAnnotationMemberValue(memberValuePair, expression.constant);
	} else if (expression instanceof org.eclipse.jdt.internal.compiler.ast.Annotation) {
		org.eclipse.jdt.internal.compiler.ast.Annotation annotation = (org.eclipse.jdt.internal.compiler.ast.Annotation) expression;
		Object handle = acceptAnnotation(annotation, null, (JavaElement) this.handleStack.peek());
		memberValuePair.valueKind = IMemberValuePair.K_ANNOTATION;
		return handle;
	} else if (expression instanceof ClassLiteralAccess) {
		ClassLiteralAccess classLiteral = (ClassLiteralAccess) expression;
		char[] name = CharOperation.concatWith(classLiteral.type.getTypeName(), '.');
		memberValuePair.valueKind = IMemberValuePair.K_CLASS;
		return new String(name);
	} else if (expression instanceof QualifiedNameReference) {
		char[] qualifiedName = CharOperation.concatWith(((QualifiedNameReference) expression).tokens, '.');
		memberValuePair.valueKind = IMemberValuePair.K_QUALIFIED_NAME;
		return new String(qualifiedName);
	} else if (expression instanceof SingleNameReference) {
		char[] simpleName = ((SingleNameReference) expression).token;
		if (simpleName == RecoveryScanner.FAKE_IDENTIFIER) {
			memberValuePair.valueKind = IMemberValuePair.K_UNKNOWN;
			return null;
		}
		memberValuePair.valueKind = IMemberValuePair.K_SIMPLE_NAME;
		return new String(simpleName);
	} else if (expression instanceof ArrayInitializer) {
		memberValuePair.valueKind = -1; // modified below by the first call to getMemberValue(...)
		Expression[] expressions = ((ArrayInitializer) expression).expressions;
		int length = expressions == null ? 0 : expressions.length;
		Object[] values = new Object[length];
		for (int i = 0; i < length; i++) {
			int previousValueKind = memberValuePair.valueKind;
			Object value = getMemberValue(memberValuePair, expressions[i]);
			if (previousValueKind != -1 && memberValuePair.valueKind != previousValueKind) {
				// values are heterogeneous, value kind is thus unknown
				memberValuePair.valueKind = IMemberValuePair.K_UNKNOWN;
			}
			values[i] = value;
		}
		if (memberValuePair.valueKind == -1)
			memberValuePair.valueKind = IMemberValuePair.K_UNKNOWN;
		return values;
	} else if (expression instanceof UnaryExpression) {			// to deal with negative numerals (see bug - 248312)
		UnaryExpression unaryExpression = (UnaryExpression) expression;
		if ((unaryExpression.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT == OperatorIds.MINUS) {
			if (unaryExpression.expression instanceof Literal) {
				Literal subExpression = (Literal) unaryExpression.expression;
				subExpression.computeConstant();
				return Util.getNegativeAnnotationMemberValue(memberValuePair, subExpression.constant);
			}
		}
		memberValuePair.valueKind = IMemberValuePair.K_UNKNOWN;
		return null;
	} else {
		memberValuePair.valueKind = IMemberValuePair.K_UNKNOWN;
		return null;
	}
}
}
