/*******************************************************************************
 * Copyright (c) 2000, 2006 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.search.indexing;

import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.core.search.SearchDocument;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException;
import org.eclipse.jdt.internal.compiler.classfmt.FieldInfo;
import org.eclipse.jdt.internal.compiler.classfmt.MethodInfo;
import org.eclipse.jdt.internal.compiler.env.ClassSignature;
import org.eclipse.jdt.internal.compiler.env.EnumConstantSignature;
import org.eclipse.jdt.internal.compiler.env.IBinaryAnnotation;
import org.eclipse.jdt.internal.compiler.env.IBinaryElementValuePair;
import org.eclipse.jdt.internal.compiler.lookup.TagBits;
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
import org.eclipse.jdt.internal.compiler.util.SuffixConstants;

public class BinaryIndexer extends AbstractIndexer implements SuffixConstants {
	private static final char[] BYTE = "byte".toCharArray(); //$NON-NLS-1$
	private static final char[] CHAR = "char".toCharArray(); //$NON-NLS-1$
	private static final char[] DOUBLE = "double".toCharArray(); //$NON-NLS-1$
	private static final char[] FLOAT = "float".toCharArray(); //$NON-NLS-1$
	private static final char[] INT = "int".toCharArray(); //$NON-NLS-1$
	private static final char[] LONG = "long".toCharArray(); //$NON-NLS-1$
	private static final char[] SHORT = "short".toCharArray(); //$NON-NLS-1$
	private static final char[] BOOLEAN = "boolean".toCharArray(); //$NON-NLS-1$
	private static final char[] VOID = "void".toCharArray(); //$NON-NLS-1$
	private static final char[] INIT = "<init>".toCharArray(); //$NON-NLS-1$

	public BinaryIndexer(SearchDocument document) {
		super(document);
	}
	private void addBinaryStandardAnnotations(long annotationTagBits) {
		if ((annotationTagBits & TagBits.AnnotationTargetMASK) != 0) {
			char[][] compoundName = TypeConstants.JAVA_LANG_ANNOTATION_TARGET;
			addTypeReference(compoundName[compoundName.length-1]);
			addBinaryTargetAnnotation(annotationTagBits);
		}
		if ((annotationTagBits & TagBits.AnnotationRetentionMASK) != 0) {
			char[][] compoundName = TypeConstants.JAVA_LANG_ANNOTATION_RETENTION;
			addTypeReference(compoundName[compoundName.length-1]);
			addBinaryRetentionAnnotation(annotationTagBits);
		}
		if ((annotationTagBits & TagBits.AnnotationDeprecated) != 0) {
			char[][] compoundName = TypeConstants.JAVA_LANG_DEPRECATED;
			addTypeReference(compoundName[compoundName.length-1]);
		}
		if ((annotationTagBits & TagBits.AnnotationDocumented) != 0) {
			char[][] compoundName = TypeConstants.JAVA_LANG_ANNOTATION_DOCUMENTED;
			addTypeReference(compoundName[compoundName.length-1]);
		}
		if ((annotationTagBits & TagBits.AnnotationInherited) != 0) {
			char[][] compoundName = TypeConstants.JAVA_LANG_ANNOTATION_INHERITED;
			addTypeReference(compoundName[compoundName.length-1]);
		}
		if ((annotationTagBits & TagBits.AnnotationOverride) != 0) {
			char[][] compoundName = TypeConstants.JAVA_LANG_OVERRIDE;
			addTypeReference(compoundName[compoundName.length-1]);
		}
		if ((annotationTagBits & TagBits.AnnotationSuppressWarnings) != 0) {
			char[][] compoundName = TypeConstants.JAVA_LANG_SUPPRESSWARNINGS;
			addTypeReference(compoundName[compoundName.length-1]);
		}
	}
	private void addBinaryTargetAnnotation(long bits) {
		char[][] compoundName = null;
		if ((bits & TagBits.AnnotationForAnnotationType) != 0) {
			compoundName = TypeConstants.JAVA_LANG_ANNOTATION_ELEMENTTYPE;
			addTypeReference(compoundName[compoundName.length-1]);
			addFieldReference(TypeConstants.UPPER_ANNOTATION_TYPE);
		}
		if ((bits & TagBits.AnnotationForConstructor) != 0) {
			if (compoundName == null) {
				compoundName = TypeConstants.JAVA_LANG_ANNOTATION_ELEMENTTYPE;
				addTypeReference(compoundName[compoundName.length-1]);
			}
			addFieldReference(TypeConstants.UPPER_CONSTRUCTOR);
		}
		if ((bits & TagBits.AnnotationForField) != 0) {
			if (compoundName == null) {
				compoundName = TypeConstants.JAVA_LANG_ANNOTATION_ELEMENTTYPE;
				addTypeReference(compoundName[compoundName.length-1]);
			}
			addFieldReference(TypeConstants.UPPER_FIELD);
		}
		if ((bits & TagBits.AnnotationForLocalVariable) != 0) {
			if (compoundName == null) {
				compoundName = TypeConstants.JAVA_LANG_ANNOTATION_ELEMENTTYPE;
				addTypeReference(compoundName[compoundName.length-1]);
			}
			addFieldReference(TypeConstants.UPPER_LOCAL_VARIABLE);
		}
		if ((bits & TagBits.AnnotationForMethod) != 0) {
			if (compoundName == null) {
				compoundName = TypeConstants.JAVA_LANG_ANNOTATION_ELEMENTTYPE;
				addTypeReference(compoundName[compoundName.length-1]);
			}
			addFieldReference(TypeConstants.UPPER_METHOD);
		}
		if ((bits & TagBits.AnnotationForPackage) != 0) {
			if (compoundName == null) {
				compoundName = TypeConstants.JAVA_LANG_ANNOTATION_ELEMENTTYPE;
				addTypeReference(compoundName[compoundName.length-1]);
			}
			addFieldReference(TypeConstants.UPPER_PACKAGE);
		}
		if ((bits & TagBits.AnnotationForParameter) != 0) {
			if (compoundName == null) {
				compoundName = TypeConstants.JAVA_LANG_ANNOTATION_ELEMENTTYPE;
				addTypeReference(compoundName[compoundName.length-1]);
			}
			addFieldReference(TypeConstants.UPPER_PARAMETER);
		}
		if ((bits & TagBits.AnnotationForType) != 0) {
			if (compoundName == null) {
				compoundName = TypeConstants.JAVA_LANG_ANNOTATION_ELEMENTTYPE;
				addTypeReference(compoundName[compoundName.length-1]);
			}
			addFieldReference(TypeConstants.TYPE);
		}
	}
	private void addBinaryRetentionAnnotation(long bits) {
		char[][] compoundName = TypeConstants.JAVA_LANG_ANNOTATION_RETENTIONPOLICY;
		addTypeReference(compoundName[compoundName.length-1]);
		if ((bits & TagBits.AnnotationRuntimeRetention) != 0) {
			addFieldReference(TypeConstants.UPPER_RUNTIME);
		}
		else if ((bits & TagBits.AnnotationClassRetention) != 0) {
			addFieldReference(TypeConstants.UPPER_CLASS);
		}
		else if ((bits & TagBits.AnnotationSourceRetention) != 0) {
			addFieldReference(TypeConstants.UPPER_SOURCE);
		}
	}
	private void addBinaryAnnotation(IBinaryAnnotation annotation) {
		addTypeReference(replace('/', '.', Signature.toCharArray(annotation.getTypeName())));
		IBinaryElementValuePair[] valuePairs = annotation.getElementValuePairs();
		if (valuePairs != null) {
			for (int j=0, vpLength=valuePairs.length; j<vpLength; j++) {
				IBinaryElementValuePair valuePair = valuePairs[j];
				addMethodReference(valuePair.getName(), 0);
				Object pairValue = valuePair.getValue();
				addPairValue(pairValue);
			}
		}
	}
	private void addPairValue(Object pairValue) {
		if (pairValue instanceof EnumConstantSignature) {
			EnumConstantSignature enumConstant = (EnumConstantSignature) pairValue;
			addTypeReference(replace('/', '.', Signature.toCharArray(enumConstant.getTypeName())));
			addNameReference(enumConstant.getEnumConstantName());
		} else if (pairValue instanceof ClassSignature) {
			ClassSignature classConstant = (ClassSignature) pairValue;
			addTypeReference(replace('/', '.', Signature.toCharArray(classConstant.getTypeName())));
		} else if (pairValue instanceof IBinaryAnnotation) {
			addBinaryAnnotation((IBinaryAnnotation) pairValue);
		} else if (pairValue instanceof Object[]) {
			Object[] objects = (Object[]) pairValue;
			for (int i=0,l=objects.length; i<l; i++) {
				addPairValue(objects[i]);
			}
		}
	}
	public void addTypeReference(char[] typeName) {
		int length = typeName.length;
		if (length > 2 && typeName[length - 2] == '$') {
			switch (typeName[length - 1]) {
				case '0' :
				case '1' :
				case '2' :
				case '3' :
				case '4' :
				case '5' :
				case '6' :
				case '7' :
				case '8' :
				case '9' :
					return; // skip local type names
			}
		}

	 	// consider that A$B is a member type: so replace '$' with '.'
	 	// (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=40116)
		typeName = CharOperation.replaceOnCopy(typeName, '$', '.'); // copy it so the original is not modified

		super.addTypeReference(typeName);
	}
	/**
	 * For example:
	 *   - int foo(String[]) is ([Ljava/lang/String;)I => java.lang.String[] in a char[][]
	 *   - void foo(int) is (I)V ==> int
	 */
	private void convertToArrayType(char[][] parameterTypes, int counter, int arrayDim) {
		int length = parameterTypes[counter].length;
		char[] arrayType = new char[length + arrayDim*2];
		System.arraycopy(parameterTypes[counter], 0, arrayType, 0, length);
		for (int i = 0; i < arrayDim; i++) {
			arrayType[length + (i * 2)] = '[';
			arrayType[length + (i * 2) + 1] = ']';
		}
		parameterTypes[counter] = arrayType;
	}
	/**
	 * For example:
	 *   - int foo(String[]) is ([Ljava/lang/String;)I => java.lang.String[] in a char[][]
	 *   - void foo(int) is (I)V ==> int
	 */
	private char[] convertToArrayType(char[] typeName, int arrayDim) {
		int length = typeName.length;
		char[] arrayType = new char[length + arrayDim*2];
		System.arraycopy(typeName, 0, arrayType, 0, length);
		for (int i = 0; i < arrayDim; i++) {
			arrayType[length + (i * 2)] = '[';
			arrayType[length + (i * 2) + 1] = ']';
		}
		return arrayType;
	}
	private char[] decodeFieldType(char[] signature) throws ClassFormatException {
		if (signature == null) return null;
		int arrayDim = 0;
		for (int i = 0, max = signature.length; i < max; i++) {
			switch(signature[i]) {
				case 'B':
					if (arrayDim > 0)
						return convertToArrayType(BYTE, arrayDim);
					return BYTE;
					
				case 'C':
					if (arrayDim > 0)
						return convertToArrayType(CHAR, arrayDim);
					return CHAR;
					
				case 'D':
					if (arrayDim > 0)
						return convertToArrayType(DOUBLE, arrayDim);
					return DOUBLE;
					
				case 'F':
					if (arrayDim > 0)
						return convertToArrayType(FLOAT, arrayDim);
					return FLOAT;
					
				case 'I':
					if (arrayDim > 0)
					return convertToArrayType(INT, arrayDim);
					return INT;
					
				case 'J':
					if (arrayDim > 0)
						return convertToArrayType(LONG, arrayDim);
					return LONG;
					
				case 'L':
					int indexOfSemiColon = CharOperation.indexOf(';', signature, i+1);
					if (indexOfSemiColon == -1) throw new ClassFormatException(ClassFormatException.ErrInvalidMethodSignature);
					if (arrayDim > 0) {
						return convertToArrayType(replace('/','.',CharOperation.subarray(signature, i + 1, indexOfSemiColon)), arrayDim);
					}
					return replace('/','.',CharOperation.subarray(signature, i + 1, indexOfSemiColon));
					
				case 'S':
					if (arrayDim > 0)
						return convertToArrayType(SHORT, arrayDim);
					return SHORT;
					
				case 'Z':
					if (arrayDim > 0)
						return convertToArrayType(BOOLEAN, arrayDim);
					return BOOLEAN;
					
				case 'V':
					return VOID;
					
				case '[':
					arrayDim++;
					break;
					
				default:
					throw new ClassFormatException(ClassFormatException.ErrInvalidMethodSignature);
			}
		}
		return null;
	}
	/**
	 * For example:
	 *   - int foo(String[]) is ([Ljava/lang/String;)I => java.lang.String[] in a char[][]
	 *   - void foo(int) is (I)V ==> int
	 */
	private char[][] decodeParameterTypes(char[] signature, boolean firstIsSynthetic) throws ClassFormatException {
		if (signature == null) return null;
		int indexOfClosingParen = CharOperation.lastIndexOf(')', signature);
		if (indexOfClosingParen == 1) {
			// there is no parameter
			return null;
		}
		if (indexOfClosingParen == -1) {
			throw new ClassFormatException(ClassFormatException.ErrInvalidMethodSignature);
		}
		char[][] parameterTypes = new char[3][];
		int parameterTypesCounter = 0;
		int arrayDim = 0;
		for (int i = 1; i < indexOfClosingParen; i++) {
			if (parameterTypesCounter == parameterTypes.length) {
				// resize
				System.arraycopy(parameterTypes, 0, (parameterTypes = new char[parameterTypesCounter * 2][]), 0, parameterTypesCounter);
			}
			switch(signature[i]) {
				case 'B':
					parameterTypes[parameterTypesCounter++] = BYTE;
					if (arrayDim > 0)
						convertToArrayType(parameterTypes, parameterTypesCounter-1, arrayDim);
					arrayDim = 0;
					break;
					
				case 'C':
					parameterTypes[parameterTypesCounter++] = CHAR;
					if (arrayDim > 0)
						convertToArrayType(parameterTypes, parameterTypesCounter-1, arrayDim);
					arrayDim = 0;
					break;

				case 'D':
					parameterTypes[parameterTypesCounter++] = DOUBLE;
					if (arrayDim > 0)
						convertToArrayType(parameterTypes, parameterTypesCounter-1, arrayDim);
					arrayDim = 0;
					break;

				case 'F':
					parameterTypes[parameterTypesCounter++] = FLOAT;
					if (arrayDim > 0)
						convertToArrayType(parameterTypes, parameterTypesCounter-1, arrayDim);
					arrayDim = 0;
					break;
					
				case 'I':
					parameterTypes[parameterTypesCounter++] = INT;
					if (arrayDim > 0)
						convertToArrayType(parameterTypes, parameterTypesCounter-1, arrayDim);
					arrayDim = 0;
					break;
					
				case 'J':
					parameterTypes[parameterTypesCounter++] = LONG;
					if (arrayDim > 0)
						convertToArrayType(parameterTypes, parameterTypesCounter-1, arrayDim);
					arrayDim = 0;
					break;

				case 'L':
					int indexOfSemiColon = CharOperation.indexOf(';', signature, i+1);
					if (indexOfSemiColon == -1) throw new ClassFormatException(ClassFormatException.ErrInvalidMethodSignature);
					if (firstIsSynthetic && parameterTypesCounter == 0) {
						// skip first synthetic parameter
						firstIsSynthetic = false;
					} else {
						parameterTypes[parameterTypesCounter++] = replace('/','.',CharOperation.subarray(signature, i + 1, indexOfSemiColon));
						if (arrayDim > 0)
							convertToArrayType(parameterTypes, parameterTypesCounter-1, arrayDim);
					}
					i = indexOfSemiColon;
					arrayDim = 0;
					break;

				case 'S':
					parameterTypes[parameterTypesCounter++] = SHORT;
					if (arrayDim > 0)
						convertToArrayType(parameterTypes, parameterTypesCounter-1, arrayDim);
					arrayDim = 0;
					break;

				case 'Z':
					parameterTypes[parameterTypesCounter++] = BOOLEAN;
					if (arrayDim > 0)
						convertToArrayType(parameterTypes, parameterTypesCounter-1, arrayDim);
					arrayDim = 0;
					break;

				case '[':
					arrayDim++;
					break;
					
				default:
					throw new ClassFormatException(ClassFormatException.ErrInvalidMethodSignature);
			}
		}
		if (parameterTypes.length != parameterTypesCounter) {
			System.arraycopy(parameterTypes, 0, parameterTypes = new char[parameterTypesCounter][], 0, parameterTypesCounter);
		}
		return parameterTypes;
	}
	private char[] decodeReturnType(char[] signature) throws ClassFormatException {
		if (signature == null) return null;
		int indexOfClosingParen = CharOperation.lastIndexOf(')', signature);
		if (indexOfClosingParen == -1) throw new ClassFormatException(ClassFormatException.ErrInvalidMethodSignature);
		int arrayDim = 0;
		for (int i = indexOfClosingParen + 1, max = signature.length; i < max; i++) {
			switch(signature[i]) {
				case 'B':
					if (arrayDim > 0)
						return convertToArrayType(BYTE, arrayDim);
					return BYTE;
					
				case 'C':
					if (arrayDim > 0)
						return convertToArrayType(CHAR, arrayDim);
					return CHAR;
					
				case 'D':
					if (arrayDim > 0)
						return convertToArrayType(DOUBLE, arrayDim);
					return DOUBLE;

				case 'F':
					if (arrayDim > 0)
						return convertToArrayType(FLOAT, arrayDim);
					return FLOAT;

				case 'I':
					if (arrayDim > 0)
						return convertToArrayType(INT, arrayDim);
					return INT;

				case 'J':
					if (arrayDim > 0)
						return convertToArrayType(LONG, arrayDim);
					return LONG;

				case 'L':
					int indexOfSemiColon = CharOperation.indexOf(';', signature, i+1);
					if (indexOfSemiColon == -1) throw new ClassFormatException(ClassFormatException.ErrInvalidMethodSignature);
					if (arrayDim > 0) {
						return convertToArrayType(replace('/','.',CharOperation.subarray(signature, i + 1, indexOfSemiColon)), arrayDim);
					}
					return replace('/','.',CharOperation.subarray(signature, i + 1, indexOfSemiColon));

				case 'S':
					if (arrayDim > 0)
						return convertToArrayType(SHORT, arrayDim);
					return SHORT;

				case 'Z':
					if (arrayDim > 0)
						return convertToArrayType(BOOLEAN, arrayDim);
					return BOOLEAN;

				case 'V':
					return VOID;

				case '[':
					arrayDim++;
					break;
					
				default:
					throw new ClassFormatException(ClassFormatException.ErrInvalidMethodSignature);
			}
		}
		return null;
	}
	private int extractArgCount(char[] signature, char[] className) throws ClassFormatException {
		int indexOfClosingParen = CharOperation.lastIndexOf(')', signature);
		if (indexOfClosingParen == 1) {
			// there is no parameter
			return 0;
		}
		if (indexOfClosingParen == -1) {
			throw new ClassFormatException(ClassFormatException.ErrInvalidMethodSignature);
		}
		int parameterTypesCounter = 0;
		for (int i = 1; i < indexOfClosingParen; i++) {
			switch(signature[i]) {
				case 'B':
				case 'C':
				case 'D':
				case 'F':
				case 'I':
				case 'J':
				case 'S':
				case 'Z':
					parameterTypesCounter++;
					break;
				case 'L':
					int indexOfSemiColon = CharOperation.indexOf(';', signature, i+1);
					if (indexOfSemiColon == -1) throw new ClassFormatException(ClassFormatException.ErrInvalidMethodSignature);
					// verify if first parameter is synthetic
					if (className != null && parameterTypesCounter == 0) {
						char[] classSignature = Signature.createCharArrayTypeSignature(className, true);
						int length = indexOfSemiColon-i+1;
						if (classSignature.length > (length+1)) {
							// synthetic means that parameter type has same signature than given class
							for (int j=i, k=0; j<indexOfSemiColon; j++, k++) {
								if (!(signature[j] == classSignature[k] || (signature[j] == '/' && classSignature[k] == '.' ))) {
									parameterTypesCounter++;
									break;
								}
							}
						} else {
							parameterTypesCounter++;
						}
						className = null; // do not verify following parameters
					} else {
						parameterTypesCounter++;
					}
					i = indexOfSemiColon;
					break;
				case '[':
					break;
				default:
					throw new ClassFormatException(ClassFormatException.ErrInvalidMethodSignature);
			}
		}
		return parameterTypesCounter;
	}
	private char[] extractClassName(int[] constantPoolOffsets, ClassFileReader reader, int index) {
		// the entry at i has to be a field ref or a method/interface method ref.
		int class_index = reader.u2At(constantPoolOffsets[index] + 1);
		int utf8Offset = constantPoolOffsets[reader.u2At(constantPoolOffsets[class_index] + 1)];
		return reader.utf8At(utf8Offset + 3, reader.u2At(utf8Offset + 1));
	}
	private char[] extractName(int[] constantPoolOffsets, ClassFileReader reader, int index) {
		int nameAndTypeIndex = reader.u2At(constantPoolOffsets[index] + 3);
		int utf8Offset = constantPoolOffsets[reader.u2At(constantPoolOffsets[nameAndTypeIndex] + 1)];
		return reader.utf8At(utf8Offset + 3, reader.u2At(utf8Offset + 1));
	}
	private char[] extractClassReference(int[] constantPoolOffsets, ClassFileReader reader, int index) {
		// the entry at i has to be a class ref.
		int utf8Offset = constantPoolOffsets[reader.u2At(constantPoolOffsets[index] + 1)];
		return reader.utf8At(utf8Offset + 3, reader.u2At(utf8Offset + 1));
	}
	/**
	 * Extract all type, method, field and interface method references from the constant pool
	 */
	private void extractReferenceFromConstantPool(byte[] contents, ClassFileReader reader) throws ClassFormatException {
		int[] constantPoolOffsets = reader.getConstantPoolOffsets();
		int constantPoolCount = constantPoolOffsets.length;
		for (int i = 1; i < constantPoolCount; i++) {
			int tag = reader.u1At(constantPoolOffsets[i]);
			/**
			 * u1 tag
			 * u2 class_index
			 * u2 name_and_type_index
			 */
			char[] name = null;
			char[] type = null;
			switch (tag) {
				case ClassFileConstants.FieldRefTag :
					// add reference to the class/interface and field name and type
					name = extractName(constantPoolOffsets, reader, i);
					addFieldReference(name);
					break;
				case ClassFileConstants.MethodRefTag :
					// add reference to the class and method name and type
				case ClassFileConstants.InterfaceMethodRefTag :
					// add reference to the interface and method name and type
					name = extractName(constantPoolOffsets, reader, i);
					type = extractType(constantPoolOffsets, reader, i);
					if (CharOperation.equals(INIT, name)) {
						// get class name and see if it's a local type or not
						char[] className = extractClassName(constantPoolOffsets, reader, i);
						boolean localType = false;
						if (className !=  null) {
							for (int c = 0, max = className.length; c < max; c++) {
								switch (className[c]) {
									case '/':
										className[c] = '.';
										break;
									case '$':
										localType = true;
										break;
								}
							}
						}
						// add a constructor reference, use class name to extract arg count if it's a local type to remove synthetic parameter
						addConstructorReference(className, extractArgCount(type, localType?className:null));
					} else {
						// add a method reference
						addMethodReference(name, extractArgCount(type, null));
					}
					break;
				case ClassFileConstants.ClassTag :
					// add a type reference
					name = extractClassReference(constantPoolOffsets, reader, i);
					if (name.length > 0 && name[0] == '[')
						break; // skip over array references
					name = replace('/', '.', name); // so that it looks like java.lang.String
					addTypeReference(name);
					
					// also add a simple reference on each segment of the qualification (see http://bugs.eclipse.org/bugs/show_bug.cgi?id=24741)
					char[][] qualification = CharOperation.splitOn('.', name);
					for (int j = 0, length = qualification.length; j < length; j++) {
						addNameReference(qualification[j]);
					}
					break;
			}
		}
	}
	private char[] extractType(int[] constantPoolOffsets, ClassFileReader reader, int index) {
		int constantPoolIndex = reader.u2At(constantPoolOffsets[index] + 3);
		int utf8Offset = constantPoolOffsets[reader.u2At(constantPoolOffsets[constantPoolIndex] + 3)];
		return reader.utf8At(utf8Offset + 3, reader.u2At(utf8Offset + 1));
	}
	public void indexDocument() {
		try {
			final byte[] contents = this.document.getByteContents();
			// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=107124
			// contents can potentially be null if a IOException occurs while retrieving the contents
			if (contents == null) return;
			final String path = this.document.getPath();
			ClassFileReader reader = new ClassFileReader(contents, path == null ? null : path.toCharArray());
	
			// first add type references
			char[] className = replace('/', '.', reader.getName()); // looks like java/lang/String
			// need to extract the package name and the simple name
			int packageNameIndex = CharOperation.lastIndexOf('.', className);
			char[] packageName = null;
			char[] name = null;
			if (packageNameIndex >= 0) {
				packageName = CharOperation.subarray(className, 0, packageNameIndex);
				name = CharOperation.subarray(className, packageNameIndex + 1, className.length);
			} else {
				packageName = CharOperation.NO_CHAR;
				name = className;
			}
			char[] enclosingTypeName = null;
			boolean isNestedType = reader.isNestedType();
			if (isNestedType) {
				if (reader.isAnonymous()) {
					name = CharOperation.NO_CHAR;
				} else {
					name = reader.getInnerSourceName();
				}
				if (reader.isLocal() || reader.isAnonymous()) {
					// set specific ['0'] value for local and anonymous to be able to filter them
					enclosingTypeName = ONE_ZERO;
				} else {
					char[] fullEnclosingName = reader.getEnclosingTypeName();
					int nameLength = fullEnclosingName.length - packageNameIndex - 1;
					if (nameLength <= 0) {
						// See PR 1GIR345: ITPJCORE:ALL - Indexer: NegativeArraySizeException
						return;
					}
					enclosingTypeName = new char[nameLength]; 
					System.arraycopy(fullEnclosingName, packageNameIndex + 1, enclosingTypeName, 0, nameLength);
				}
			}
			// type parameters
			char[][] typeParameterSignatures = null;
			char[] genericSignature = reader.getGenericSignature();
			if (genericSignature != null) {
				CharOperation.replace(genericSignature, '/', '.');
				typeParameterSignatures = Signature.getTypeParameters(genericSignature);
			}
			
			// eliminate invalid innerclasses (1G4KCF7)
			if (name == null) return;
			
			char[][] superinterfaces = replace('/', '.', reader.getInterfaceNames());
			char[][] enclosingTypeNames = enclosingTypeName == null ? null : new char[][] {enclosingTypeName};
			int modifiers = reader.getModifiers();
			switch (TypeDeclaration.kind(modifiers)) {
				case TypeDeclaration.CLASS_DECL :
					char[] superclass = replace('/', '.', reader.getSuperclassName());
					addClassDeclaration(modifiers, packageName, name, enclosingTypeNames, superclass, superinterfaces, typeParameterSignatures, false);
					break;
				case TypeDeclaration.INTERFACE_DECL :
					addInterfaceDeclaration(modifiers, packageName, name, enclosingTypeNames, superinterfaces, typeParameterSignatures, false);
					break;
				case TypeDeclaration.ENUM_DECL :
					superclass = replace('/', '.', reader.getSuperclassName());
					addEnumDeclaration(modifiers, packageName, name, enclosingTypeNames, superclass, superinterfaces, false);
					break;
				case TypeDeclaration.ANNOTATION_TYPE_DECL :
					addAnnotationTypeDeclaration(modifiers, packageName, name, enclosingTypeNames, false);
					break;
			}			

			// Look for references in class annotations
			IBinaryAnnotation[] annotations = reader.getAnnotations();
			if (annotations != null) {
				for (int a=0, length=annotations.length; a<length; a++) {
					IBinaryAnnotation annotation = annotations[a];
					addBinaryAnnotation(annotation);
				}
			}
			long tagBits = reader.getTagBits() & TagBits.AllStandardAnnotationsMask;
			if (tagBits != 0) {
				addBinaryStandardAnnotations(tagBits);
			}

			// first reference all methods declarations and field declarations
			MethodInfo[] methods = (MethodInfo[]) reader.getMethods();
			if (methods != null) {
				for (int i = 0, max = methods.length; i < max; i++) {
					MethodInfo method = methods[i];
					boolean isConstructor = method.isConstructor();
					char[] descriptor = method.getMethodDescriptor();
					char[][] parameterTypes = decodeParameterTypes(descriptor, isConstructor && isNestedType);
					char[] returnType = decodeReturnType(descriptor);
					char[][] exceptionTypes = replace('/', '.', method.getExceptionTypeNames());
					if (isConstructor) {
						addConstructorDeclaration(className, parameterTypes, exceptionTypes);
					} else {
						if (!method.isClinit()) {
							addMethodDeclaration(method.getSelector(), parameterTypes, returnType, exceptionTypes);
						}
					}
					// look for references in method annotations
					annotations = method.getAnnotations();
					if (annotations != null) {
						for (int a=0, length=annotations.length; a<length; a++) {
							IBinaryAnnotation annotation = annotations[a];
							addBinaryAnnotation(annotation);
						}
					}
				}
			}
			FieldInfo[] fields = (FieldInfo[]) reader.getFields();
			if (fields != null) {
				for (int i = 0, max = fields.length; i < max; i++) {
					FieldInfo field = fields[i];
					char[] fieldName = field.getName();
					char[] fieldType = decodeFieldType(replace('/', '.', field.getTypeName()));
					addFieldDeclaration(fieldType, fieldName);
					// look for references in field annotations
					annotations = field.getAnnotations();
					if (annotations != null) {
						for (int a=0, length=annotations.length; a<length; a++) {
							IBinaryAnnotation annotation = annotations[a];
							addBinaryAnnotation(annotation);
						}
					}
				}
			}
	
			// record all references found inside the .class file
			extractReferenceFromConstantPool(contents, reader);
		} catch (ClassFormatException e) {
			// ignore
		}
	}
	/*
	 * Modify the array by replacing all occurences of toBeReplaced with newChar
	 */
	private char[][] replace(char toBeReplaced, char newChar, char[][] array) {
		if (array == null) return null;
		for (int i = 0, max = array.length; i < max; i++) {
			replace(toBeReplaced, newChar, array[i]);
		}
		return array;
	}
	/*
	 * Modify the array by replacing all occurences of toBeReplaced with newChar
	 */
	private char[] replace(char toBeReplaced, char newChar, char[] array) {
		if (array == null) return null;
		for (int i = 0, max = array.length; i < max; i++) {
			if (array[i] == toBeReplaced) {
				array[i] = newChar;
			}
		}
		return array;
	}
}
