/*******************************************************************************
 * Copyright (c) 2000, 2018 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
 *     Stephan Herrmann - Contribution for
 *								Bug 458577 - IClassFile.getWorkingCopy() may lead to NPE in BecomeWorkingCopyOperation
 *******************************************************************************/
package org.eclipse.jdt.internal.core.util;

import java.io.*;
import java.net.URI;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import org.eclipse.core.filesystem.EFS;
import org.eclipse.core.filesystem.IFileStore;
import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.content.IContentType;
import org.eclipse.core.runtime.preferences.IScopeContext;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.jdt.core.*;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ArrayType;
import org.eclipse.jdt.core.dom.ParameterizedType;
import org.eclipse.jdt.core.dom.PrimitiveType;
import org.eclipse.jdt.core.dom.QualifiedType;
import org.eclipse.jdt.core.dom.SimpleType;
import org.eclipse.jdt.core.dom.Type;
import org.eclipse.jdt.core.dom.WildcardType;
import org.eclipse.jdt.core.util.IClassFileAttribute;
import org.eclipse.jdt.core.util.IClassFileReader;
import org.eclipse.jdt.core.util.ICodeAttribute;
import org.eclipse.jdt.core.util.IFieldInfo;
import org.eclipse.jdt.core.util.IMethodInfo;
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.AnnotationMethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Argument;
import org.eclipse.jdt.internal.compiler.ast.IntersectionCastTypeReference;
import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.jdt.internal.compiler.ast.UnionTypeReference;
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.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.IDependent;
import org.eclipse.jdt.internal.compiler.impl.Constant;
import org.eclipse.jdt.internal.compiler.lookup.Binding;
import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
import org.eclipse.jdt.internal.compiler.parser.ScannerHelper;
import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
import org.eclipse.jdt.internal.core.Annotation;
import org.eclipse.jdt.internal.core.ClassFile;
import org.eclipse.jdt.internal.core.JavaElement;
import org.eclipse.jdt.internal.core.JavaModelManager;
import org.eclipse.jdt.internal.core.Member;
import org.eclipse.jdt.internal.core.MemberValuePair;
import org.eclipse.jdt.internal.core.PackageFragment;
import org.eclipse.jdt.internal.core.PackageFragmentRoot;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.text.edits.MalformedTreeException;
import org.eclipse.text.edits.TextEdit;

/**
 * Provides convenient utility methods to other types in this package.
 */
@SuppressWarnings({ "rawtypes", "unchecked" })
public class Util {

	public interface Comparable {
		/**
		 * Returns 0 if this and c are equal, >0 if this is greater than c,
		 * or <0 if this is less than c.
		 */
		int compareTo(Comparable c);
	}

	public interface Comparer {
		/**
		 * Returns 0 if a and b are equal, >0 if a is greater than b,
		 * or <0 if a is less than b.
		 */
		int compare(Object a, Object b);
	}

	public static interface BindingsToNodesMap {
		public org.eclipse.jdt.internal.compiler.ast.ASTNode get(Binding binding);
	}

	private static final char ARGUMENTS_DELIMITER = '#';

	private static final String EMPTY_ARGUMENT = "   "; //$NON-NLS-1$

	private static char[][] JAVA_LIKE_EXTENSIONS;

	private static final char[] BOOLEAN = "boolean".toCharArray(); //$NON-NLS-1$
	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[] VOID = "void".toCharArray(); //$NON-NLS-1$
	private static final char[] INIT = "<init>".toCharArray(); //$NON-NLS-1$

	private static final String TASK_PRIORITIES_PROBLEM = "TASK_PRIORITIES_PB"; //$NON-NLS-1$
	private static List fgRepeatedMessages= new ArrayList(5);

	private Util() {
		// cannot be instantiated
	}

	/**
	 * Returns a new array adding the second array at the end of first array.
	 * It answers null if the first and second are null.
	 * If the first array is null or if it is empty, then a new array is created with second.
	 * If the second array is null, then the first array is returned.
	 * <br>
	 * <br>
	 * For example:
	 * <ol>
	 * <li><pre>
	 *    first = null
	 *    second = "a"
	 *    => result = {"a"}
	 * </pre>
	 * <li><pre>
	 *    first = {"a"}
	 *    second = null
	 *    => result = {"a"}
	 * </pre>
	 * </li>
	 * <li><pre>
	 *    first = {"a"}
	 *    second = {"b"}
	 *    => result = {"a", "b"}
	 * </pre>
	 * </li>
	 * </ol>
	 *
	 * @param first the first array to concatenate
	 * @param second the array to add at the end of the first array
	 * @return a new array adding the second array at the end of first array, or null if the two arrays are null.
	 */
	public static final String[] arrayConcat(String[] first, String second) {
		if (second == null)
			return first;
		if (first == null)
			return new String[] {second};

		int length = first.length;
		if (first.length == 0) {
			return new String[] {second};
		}

		String[] result = new String[length + 1];
		System.arraycopy(first, 0, result, 0, length);
		result[length] = second;
		return result;
	}

	/**
	 * Checks the type signature in String sig,
	 * starting at start and ending before end (end is not included).
	 * Returns the index of the character immediately after the signature if valid,
	 * or -1 if not valid.
	 */
	private static int checkTypeSignature(String sig, int start, int end, boolean allowVoid) {
		if (start >= end) return -1;
		int i = start;
		char c = sig.charAt(i++);
		int nestingDepth = 0;
		while (c == '[') {
			++nestingDepth;
			if (i >= end) return -1;
			c = sig.charAt(i++);
		}
		switch (c) {
			case 'B':
			case 'C':
			case 'D':
			case 'F':
			case 'I':
			case 'J':
			case 'S':
			case 'Z':
				break;
			case 'V':
				if (!allowVoid) return -1;
				// array of void is not allowed
				if (nestingDepth != 0) return -1;
				break;
			case 'L':
				int semicolon = sig.indexOf(';', i);
				// Must have at least one character between L and ;
				if (semicolon <= i || semicolon >= end) return -1;
				i = semicolon + 1;
				break;
			default:
				return -1;
		}
		return i;
	}

	/**
	 * Combines two hash codes to make a new one.
	 */
	public static int combineHashCodes(int hashCode1, int hashCode2) {
		return hashCode1 * 17 + hashCode2;
	}

	/**
	 * Compares two byte arrays.
	 * Returns <0 if a byte in a is less than the corresponding byte in b, or if a is shorter, or if a is null.
	 * Returns >0 if a byte in a is greater than the corresponding byte in b, or if a is longer, or if b is null.
	 * Returns 0 if they are equal or both null.
	 */
	public static int compare(byte[] a, byte[] b) {
		if (a == b)
			return 0;
		if (a == null)
			return -1;
		if (b == null)
			return 1;
		int len = Math.min(a.length, b.length);
		for (int i = 0; i < len; ++i) {
			int diff = a[i] - b[i];
			if (diff != 0)
				return diff;
		}
		if (a.length > len)
			return 1;
		if (b.length > len)
			return -1;
		return 0;
	}
	/**
	 * Compares two strings lexicographically.
	 * The comparison is based on the Unicode value of each character in
	 * the strings.
	 *
	 * @return  the value <code>0</code> if the str1 is equal to str2;
	 *          a value less than <code>0</code> if str1
	 *          is lexicographically less than str2;
	 *          and a value greater than <code>0</code> if str1 is
	 *          lexicographically greater than str2.
	 */
	public static int compare(char[] str1, char[] str2) {
		int len1= str1.length;
		int len2= str2.length;
		int n= Math.min(len1, len2);
		int i= 0;
		while (n-- != 0) {
			char c1= str1[i];
			char c2= str2[i++];
			if (c1 != c2) {
				return c1 - c2;
			}
		}
		return len1 - len2;
	}
	/**
	 * Concatenate a String[] compound name to a continuous char[].
	 */
	public static char[] concatCompoundNameToCharArray(String[] compoundName) {
		if (compoundName == null) return null;
		int length = compoundName.length;
		if (length == 0) return new char[0];
		int size = 0;
		for (int i=0; i<length; i++) {
			size += compoundName[i].length();
		}
		char[] compoundChars = new char[size+length-1];
		int pos = 0;
		for (int i=0; i<length; i++) {
			String name = compoundName[i];
			if (i > 0) compoundChars[pos++] = '.';
			int nameLength = name.length();
			name.getChars(0, nameLength, compoundChars, pos);
			pos += nameLength;
		}
		return compoundChars;
	}
	public static String concatenateName(String name1, String name2, char separator) {
		StringBuffer buf= new StringBuffer();
		if (name1 != null && name1.length() > 0) {
			buf.append(name1);
		}
		if (name2 != null && name2.length() > 0) {
			if (buf.length() > 0) {
				buf.append(separator);
			}
			buf.append(name2);
		}
		return buf.toString();
	}
	/**
	 * Returns the concatenation of the given array parts using the given separator between each part.
	 * <br>
	 * <br>
	 * For example:<br>
	 * <ol>
	 * <li><pre>
	 *    array = {"a", "b"}
	 *    separator = '.'
	 *    => result = "a.b"
	 * </pre>
	 * </li>
	 * <li><pre>
	 *    array = {}
	 *    separator = '.'
	 *    => result = ""
	 * </pre></li>
	 * </ol>
	 *
	 * @param array the given array
	 * @param separator the given separator
	 * @return the concatenation of the given array parts using the given separator between each part
	 */
	public static final String concatWith(String[] array, char separator) {
		StringBuffer buffer = new StringBuffer();
		for (int i = 0, length = array.length; i < length; i++) {
			buffer.append(array[i]);
			if (i < length - 1)
				buffer.append(separator);
		}
		return buffer.toString();
	}

	/**
	 * Returns the concatenation of the given array parts using the given separator between each
	 * part and appending the given name at the end.
	 * <br>
	 * <br>
	 * For example:<br>
	 * <ol>
	 * <li><pre>
	 *    name = "c"
	 *    array = { "a", "b" }
	 *    separator = '.'
	 *    => result = "a.b.c"
	 * </pre>
	 * </li>
	 * <li><pre>
	 *    name = null
	 *    array = { "a", "b" }
	 *    separator = '.'
	 *    => result = "a.b"
	 * </pre></li>
	 * <li><pre>
	 *    name = " c"
	 *    array = null
	 *    separator = '.'
	 *    => result = "c"
	 * </pre></li>
	 * </ol>
	 *
	 * @param array the given array
	 * @param name the given name
	 * @param separator the given separator
	 * @return the concatenation of the given array parts using the given separator between each
	 * part and appending the given name at the end
	 */
	public static final String concatWith(
		String[] array,
		String name,
		char separator) {

		if (array == null || array.length == 0) return name;
		if (name == null || name.length() == 0) return concatWith(array, separator);
		StringBuffer buffer = new StringBuffer();
		for (int i = 0, length = array.length; i < length; i++) {
			buffer.append(array[i]);
			buffer.append(separator);
		}
		buffer.append(name);
		return buffer.toString();

	}
	/**
	 * Converts a type signature from the IBinaryType representation to the DC representation.
	 */
	public static String convertTypeSignature(char[] sig, int start, int length) {
		return new String(sig, start, length).replace('/', '.');
	}

	/*
	 * Returns the default java extension (".java").
	 * To be used when the extension is not known.
	 */
	public static String defaultJavaExtension() {
		return SuffixConstants.SUFFIX_STRING_java;
	}

	/**
	 * Apply the given edit on the given string and return the updated string.
	 * Return the given string if anything wrong happen while applying the edit.
	 *
	 * @param original the given string
	 * @param edit the given edit
	 *
	 * @return the updated string
	 */
	public final static String editedString(String original, TextEdit edit) {
		if (edit == null) {
			return original;
		}
		SimpleDocument document = new SimpleDocument(original);
		try {
			edit.apply(document, TextEdit.NONE);
			return document.get();
		} catch (MalformedTreeException e) {
			e.printStackTrace();
		} catch (BadLocationException e) {
			e.printStackTrace();
		}
		return original;
	}

	/**
	 * Returns true iff str.toLowerCase().endsWith(end.toLowerCase())
	 * implementation is not creating extra strings.
	 */
	public final static boolean endsWithIgnoreCase(String str, String end) {

		int strLength = str == null ? 0 : str.length();
		int endLength = end == null ? 0 : end.length();

		// return false if the string is smaller than the end.
		if(endLength > strLength)
			return false;

		// return false if any character of the end are
		// not the same in lower case.
		for(int i = 1 ; i <= endLength; i++){
			if(ScannerHelper.toLowerCase(end.charAt(endLength - i)) != ScannerHelper.toLowerCase(str.charAt(strLength - i)))
				return false;
		}

		return true;
	}

	/**
	 * Compares two arrays using equals() on the elements.
	 * Neither can be null. Only the first len elements are compared.
	 * Return false if either array is shorter than len.
	 */
	public static boolean equalArrays(Object[] a, Object[] b, int len) {
		if (a == b)	return true;
		if (a.length < len || b.length < len) return false;
		for (int i = 0; i < len; ++i) {
			if (a[i] == null) {
				if (b[i] != null) return false;
			} else {
				if (!a[i].equals(b[i])) return false;
			}
		}
		return true;
	}

	/**
	 * Compares two arrays using equals() on the elements.
	 * Either or both arrays may be null.
	 * Returns true if both are null.
	 * Returns false if only one is null.
	 * If both are arrays, returns true iff they have the same length and
	 * all elements are equal.
	 */
	public static boolean equalArraysOrNull(int[] a, int[] b) {
		if (a == b)
			return true;
		if (a == null || b == null)
			return false;
		int len = a.length;
		if (len != b.length)
			return false;
		for (int i = 0; i < len; ++i) {
			if (a[i] != b[i])
				return false;
		}
		return true;
	}

	/**
	 * Compares two arrays using equals() on the elements.
	 * Either or both arrays may be null.
	 * Returns true if both are null.
	 * Returns false if only one is null.
	 * If both are arrays, returns true iff they have the same length and
	 * all elements compare true with equals.
	 */
	public static boolean equalArraysOrNull(Object[] a, Object[] b) {
		if (a == b)	return true;
		if (a == null || b == null) return false;

		int len = a.length;
		if (len != b.length) return false;
		// walk array from end to beginning as this optimizes package name cases
		// where the first part is always the same (e.g. org.eclipse.jdt)
		for (int i = len-1; i >= 0; i--) {
			if (a[i] == null) {
				if (b[i] != null) return false;
			} else {
				if (!a[i].equals(b[i])) return false;
			}
		}
		return true;
	}

	/**
	 * Compares two arrays using equals() on the elements.
	 * The arrays are first sorted.
	 * Either or both arrays may be null.
	 * Returns true if both are null.
	 * Returns false if only one is null.
	 * If both are arrays, returns true iff they have the same length and
	 * iff, after sorting both arrays, all elements compare true with equals.
	 * The original arrays are left untouched.
	 */
	public static boolean equalArraysOrNullSortFirst(Comparable[] a, Comparable[] b) {
		if (a == b)	return true;
		if (a == null || b == null) return false;
		int len = a.length;
		if (len != b.length) return false;
		if (len >= 2) {  // only need to sort if more than two items
			a = sortCopy(a);
			b = sortCopy(b);
		}
		for (int i = 0; i < len; ++i) {
			if (!a[i].equals(b[i])) return false;
		}
		return true;
	}

	/**
	 * Compares two String arrays using equals() on the elements.
	 * The arrays are first sorted.
	 * Either or both arrays may be null.
	 * Returns true if both are null.
	 * Returns false if only one is null.
	 * If both are arrays, returns true iff they have the same length and
	 * iff, after sorting both arrays, all elements compare true with equals.
	 * The original arrays are left untouched.
	 */
	public static boolean equalArraysOrNullSortFirst(String[] a, String[] b) {
		if (a == b)	return true;
		if (a == null || b == null) return false;
		int len = a.length;
		if (len != b.length) return false;
		if (len >= 2) {  // only need to sort if more than two items
			a = sortCopy(a);
			b = sortCopy(b);
		}
		for (int i = 0; i < len; ++i) {
			if (!a[i].equals(b[i])) return false;
		}
		return true;
	}

	/**
	 * Compares two objects using equals().
	 * Either or both array may be null.
	 * Returns true if both are null.
	 * Returns false if only one is null.
	 * Otherwise, return the result of comparing with equals().
	 */
	public static boolean equalOrNull(Object a, Object b) {
		if (a == b) {
			return true;
		}
		if (a == null || b == null) {
			return false;
		}
		return a.equals(b);
	}

	/*
	 * Returns whether the given file name equals to the given string ignoring the java like extension
	 * of the file name.
	 * Returns false if it is not a java like file name.
	 */
	public static boolean equalsIgnoreJavaLikeExtension(String fileName, String string) {
		int fileNameLength = fileName.length();
		int stringLength = string.length();
		if (fileNameLength < stringLength) return false;
		for (int i = 0; i < stringLength; i ++) {
			if (fileName.charAt(i) != string.charAt(i)) {
				return false;
			}
		}
		char[][] javaLikeExtensions = getJavaLikeExtensions();
		suffixes: for (int i = 0, length = javaLikeExtensions.length; i < length; i++) {
			char[] suffix = javaLikeExtensions[i];
			int extensionStart = stringLength+1;
			if (extensionStart + suffix.length != fileNameLength) continue;
			if (fileName.charAt(stringLength) != '.') continue;
			for (int j = extensionStart; j < fileNameLength; j++) {
				if (fileName.charAt(j) != suffix[j-extensionStart])
					continue suffixes;
			}
			return true;
		}
		return false;
	}

	/**
	 * Given a qualified name, extract the last component.
	 * If the input is not qualified, the same string is answered.
	 */
	public static String extractLastName(String qualifiedName) {
		int i = qualifiedName.lastIndexOf('.');
		if (i == -1) return qualifiedName;
		return qualifiedName.substring(i+1);
	}

	/**
	 * Extracts the parameter types from a method signature.
	 */
	public static String[] extractParameterTypes(char[] sig) {
		int count = getParameterCount(sig);
		String[] result = new String[count];
		if (count == 0)
			return result;
		int i = CharOperation.indexOf('(', sig) + 1;
		count = 0;
		int len = sig.length;
		int start = i;
		for (;;) {
			if (i == len)
				break;
			char c = sig[i];
			if (c == ')')
				break;
			if (c == '[') {
				++i;
			} else
				if (c == 'L') {
					i = CharOperation.indexOf(';', sig, i + 1) + 1;
					Assert.isTrue(i != 0);
					result[count++] = convertTypeSignature(sig, start, i - start);
					start = i;
				} else {
					++i;
					result[count++] = convertTypeSignature(sig, start, i - start);
					start = i;
				}
		}
		return result;
	}

	/**
	 * Extracts the return type from a method signature.
	 */
	public static String extractReturnType(String sig) {
		int i = sig.lastIndexOf(')');
		Assert.isTrue(i != -1);
		return sig.substring(i+1);
	}
	private static IFile findFirstClassFile(IFolder folder) {
		try {
			IResource[] members = folder.members();
			for (int i = 0, max = members.length; i < max; i++) {
				IResource member = members[i];
				if (member.getType() == IResource.FOLDER) {
					return findFirstClassFile((IFolder)member);
				} else if (org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(member.getName())) {
					return (IFile) member;
				}
			}
		} catch (CoreException e) {
			// ignore
		}
		return null;
	}

	/**
	 * Finds the first line separator used by the given text.
	 *
	 * @return </code>"\n"</code> or </code>"\r"</code> or  </code>"\r\n"</code>,
	 *			or <code>null</code> if none found
	 */
	public static String findLineSeparator(char[] text) {
		// find the first line separator
		int length = text.length;
		if (length > 0) {
			char nextChar = text[0];
			for (int i = 0; i < length; i++) {
				char currentChar = nextChar;
				nextChar = i < length-1 ? text[i+1] : ' ';
				switch (currentChar) {
					case '\n': return "\n"; //$NON-NLS-1$
					case '\r': return nextChar == '\n' ? "\r\n" : "\r"; //$NON-NLS-1$ //$NON-NLS-2$
				}
			}
		}
		// not found
		return null;
	}

	public static IClassFileAttribute getAttribute(IClassFileReader classFileReader, char[] attributeName) {
		IClassFileAttribute[] attributes = classFileReader.getAttributes();
		for (int i = 0, max = attributes.length; i < max; i++) {
			if (CharOperation.equals(attributes[i].getAttributeName(), attributeName)) {
				return attributes[i];
			}
		}
		return null;
	}

	public static IClassFileAttribute getAttribute(ICodeAttribute codeAttribute, char[] attributeName) {
		IClassFileAttribute[] attributes = codeAttribute.getAttributes();
		for (int i = 0, max = attributes.length; i < max; i++) {
			if (CharOperation.equals(attributes[i].getAttributeName(), attributeName)) {
				return attributes[i];
			}
		}
		return null;
	}

	public static IClassFileAttribute getAttribute(IFieldInfo fieldInfo, char[] attributeName) {
		IClassFileAttribute[] attributes = fieldInfo.getAttributes();
		for (int i = 0, max = attributes.length; i < max; i++) {
			if (CharOperation.equals(attributes[i].getAttributeName(), attributeName)) {
				return attributes[i];
			}
		}
		return null;
	}

	public static IClassFileAttribute getAttribute(IMethodInfo methodInfo, char[] attributeName) {
		IClassFileAttribute[] attributes = methodInfo.getAttributes();
		for (int i = 0, max = attributes.length; i < max; i++) {
			if (CharOperation.equals(attributes[i].getAttributeName(), attributeName)) {
				return attributes[i];
			}
		}
		return null;
	}

	private static IClassFile getClassFile(char[] fileName) {
		int jarSeparator = CharOperation.indexOf(IDependent.JAR_FILE_ENTRY_SEPARATOR, fileName);
		int pkgEnd = CharOperation.lastIndexOf('/', fileName); // pkgEnd is exclusive
		if (pkgEnd == -1)
			pkgEnd = CharOperation.lastIndexOf(File.separatorChar, fileName);
		if (jarSeparator != -1 && pkgEnd < jarSeparator) // if in a jar and no slash, it is a default package -> pkgEnd should be equal to jarSeparator
			pkgEnd = jarSeparator;
		if (pkgEnd == -1)
			return null;
		IPackageFragment pkg = getPackageFragment(fileName, pkgEnd, jarSeparator);
		if (pkg == null) return null;
		int start;
		return pkg.getClassFile(new String(fileName, start = pkgEnd + 1, fileName.length - start));
	}

	private static ICompilationUnit getCompilationUnit(char[] fileName, WorkingCopyOwner workingCopyOwner) {
		char[] slashSeparatedFileName = CharOperation.replaceOnCopy(fileName, File.separatorChar, '/');
		int pkgEnd = CharOperation.lastIndexOf('/', slashSeparatedFileName); // pkgEnd is exclusive
		if (pkgEnd == -1)
			return null;
		IPackageFragment pkg = getPackageFragment(slashSeparatedFileName, pkgEnd, -1/*no jar separator for .java files*/);
		if (pkg != null) {
			int start;
			ICompilationUnit cu = pkg.getCompilationUnit(new String(slashSeparatedFileName, start =  pkgEnd+1, slashSeparatedFileName.length - start));
			if (workingCopyOwner != null) {
				ICompilationUnit workingCopy = cu.findWorkingCopy(workingCopyOwner);
				if (workingCopy != null)
					return workingCopy;
			}
			return cu;
		}
		IWorkspaceRoot wsRoot = ResourcesPlugin.getWorkspace().getRoot();
		IFile file = wsRoot.getFile(new Path(String.valueOf(fileName)));
		if (file.exists()) {
			// this approach works if file exists but is not on the project's build path:
			return JavaCore.createCompilationUnitFrom(file);
		}
		return null;
	}

	/**
	 * Returns the registered Java like extensions.
	 */
	public static char[][] getJavaLikeExtensions() {
		if (JAVA_LIKE_EXTENSIONS == null) {
			IContentType javaContentType = Platform.getContentTypeManager().getContentType(JavaCore.JAVA_SOURCE_CONTENT_TYPE);
			HashSet fileExtensions = new HashSet();
			// content types derived from java content type should be included (https://bugs.eclipse.org/bugs/show_bug.cgi?id=121715)
			IContentType[] contentTypes = Platform.getContentTypeManager().getAllContentTypes();
			for (int i = 0, length = contentTypes.length; i < length; i++) {
				if (contentTypes[i].isKindOf(javaContentType)) { // note that javaContentType.isKindOf(javaContentType) == true
					String[] fileExtension = contentTypes[i].getFileSpecs(IContentType.FILE_EXTENSION_SPEC);
					for (int j = 0, length2 = fileExtension.length; j < length2; j++) {
						fileExtensions.add(fileExtension[j]);
					}
				}
			}
			int length = fileExtensions.size();
			// note that file extensions contains "java" as it is defined in JDT Core's plugin.xml
			char[][] extensions = new char[length][];
			extensions[0] = SuffixConstants.EXTENSION_java.toCharArray(); // ensure that "java" is first
			int index = 1;
			Iterator iterator = fileExtensions.iterator();
			while (iterator.hasNext()) {
				String fileExtension = (String) iterator.next();
				if (SuffixConstants.EXTENSION_java.equals(fileExtension))
					continue;
				extensions[index++] = fileExtension.toCharArray();
			}
			JAVA_LIKE_EXTENSIONS = extensions;
		}
		return JAVA_LIKE_EXTENSIONS;
	}
	/**
	 * Get the jdk level of this root.
	 * The value can be:
	 * <ul>
	 * <li>major<<16 + minor : see predefined constants on ClassFileConstants </li>
	 * <li><code>0</null> if the root is a source package fragment root or if a Java model exception occured</li>
	 * </ul>
	 * Returns the jdk level
	 */
	public static long getJdkLevel(Object targetLibrary) {
		try {
			ClassFileReader reader = null;
			if (targetLibrary instanceof IFolder) {
				IFile classFile = findFirstClassFile((IFolder) targetLibrary); // only internal classfolders are allowed
				if (classFile != null)
					reader = Util.newClassFileReader(classFile);
			} else {
				// root is a jar file or a zip file
				ZipFile jar = null;
				try {
					IPath path = null;
					if (targetLibrary instanceof IResource) {
						path = ((IResource)targetLibrary).getFullPath();
					} else if (targetLibrary instanceof File){
						File f = (File) targetLibrary;
						if (!f.isDirectory()) {
							path = new Path(((File)targetLibrary).getPath());
						}
					}
					if (path != null) {
						if (JavaModelManager.isJrt(path)) {
							return ClassFileConstants.JDK9;
						} else {
							jar = JavaModelManager.getJavaModelManager().getZipFile(path);
							for (Enumeration e= jar.entries(); e.hasMoreElements();) {
								ZipEntry member= (ZipEntry) e.nextElement();
								String entryName= member.getName();
								if (org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(entryName)) {
									reader = ClassFileReader.read(jar, entryName);
									break;
								}
							}
						}
					}
				} catch (CoreException e) {
					// ignore
				} finally {
					JavaModelManager.getJavaModelManager().closeZipFile(jar);
				}
			}
			if (reader != null) {
				return reader.getVersion();
			}
		} catch (CoreException e) {
			// ignore
		} catch(ClassFormatException e) {
			// ignore
		} catch(IOException e) {
			// ignore
		}
		return 0;
	}

	/**
	 * Returns the substring of the given file name, ending at the start of a
	 * Java like extension. The entire file name is returned if it doesn't end
	 * with a Java like extension.
	 */
	public static String getNameWithoutJavaLikeExtension(String fileName) {
		int index = indexOfJavaLikeExtension(fileName);
		if (index == -1)
			return fileName;
		return fileName.substring(0, index);
	}

	/**
	 * Returns the line separator found in the given text.
	 * If it is null, or not found return the line delimiter for the given project.
	 * If the project is null, returns the line separator for the workspace.
	 * If still null, return the system line separator.
	 */
	public static String getLineSeparator(String text, IJavaProject project) {
		String lineSeparator = null;

		// line delimiter in given text
		if (text != null && text.length() != 0) {
			lineSeparator = findLineSeparator(text.toCharArray());
			if (lineSeparator != null)
				return lineSeparator;
		}

		if (Platform.isRunning()) {
			// line delimiter in project preference
			IScopeContext[] scopeContext;
			if (project != null) {
				scopeContext= new IScopeContext[] { new ProjectScope(project.getProject()) };
				lineSeparator= Platform.getPreferencesService().getString(Platform.PI_RUNTIME, Platform.PREF_LINE_SEPARATOR, null, scopeContext);
				if (lineSeparator != null)
					return lineSeparator;
			}
	
			// line delimiter in workspace preference
			scopeContext= new IScopeContext[] { InstanceScope.INSTANCE };
			lineSeparator = Platform.getPreferencesService().getString(Platform.PI_RUNTIME, Platform.PREF_LINE_SEPARATOR, null, scopeContext);
			if (lineSeparator != null)
				return lineSeparator;
		}

		// system line delimiter
		return org.eclipse.jdt.internal.compiler.util.Util.LINE_SEPARATOR;
	}

	/**
	 * Returns the line separator used by the given buffer.
	 * Uses the given text if none found.
	 *
	 * @return </code>"\n"</code> or </code>"\r"</code> or  </code>"\r\n"</code>
	 */
	private static String getLineSeparator(char[] text, char[] buffer) {
		// search in this buffer's contents first
		String lineSeparator = findLineSeparator(buffer);
		if (lineSeparator == null) {
			// search in the given text
			lineSeparator = findLineSeparator(text);
			if (lineSeparator == null) {
				// default to system line separator
				return getLineSeparator((String) null, (IJavaProject) null);
			}
		}
		return lineSeparator;
	}

	public static IPackageFragment getPackageFragment(char[] fileName, int pkgEnd, int jarSeparator) {
		if (jarSeparator != -1) {
			String jarMemento = new String(fileName, 0, jarSeparator);
			PackageFragmentRoot root = (PackageFragmentRoot) JavaCore.create(jarMemento);
			if (pkgEnd == jarSeparator)
				return root.getPackageFragment(CharOperation.NO_STRINGS);
			char[] pkgName = CharOperation.subarray(fileName, jarSeparator+1, pkgEnd);
			char[][] compoundName = CharOperation.splitOn('/', pkgName);
			return root.getPackageFragment(CharOperation.toStrings(compoundName));
		} else {
			Path path = new Path(new String(fileName, 0, pkgEnd));
			IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
			IContainer folder = path.segmentCount() == 1 ? workspaceRoot.getProject(path.lastSegment()) : (IContainer) workspaceRoot.getFolder(path);
			IJavaElement element = JavaCore.create(folder);
			if (element == null) return null;
			switch (element.getElementType()) {
				case IJavaElement.PACKAGE_FRAGMENT:
					return (IPackageFragment) element;
				case IJavaElement.PACKAGE_FRAGMENT_ROOT:
					return ((PackageFragmentRoot) element).getPackageFragment(CharOperation.NO_STRINGS);
				case IJavaElement.JAVA_PROJECT:
					PackageFragmentRoot root = (PackageFragmentRoot) ((IJavaProject) element).getPackageFragmentRoot(folder);
					if (root == null) return null;
					return root.getPackageFragment(CharOperation.NO_STRINGS);
			}
			return null;
		}
	}

	/**
	 * Returns the number of parameter types in a method signature.
	 */
	public static int getParameterCount(char[] sig) {
		int i = CharOperation.indexOf('(', sig) + 1;
		Assert.isTrue(i != 0);
		int count = 0;
		int len = sig.length;
		for (;;) {
			if (i == len)
				break;
			char c = sig[i];
			if (c == ')')
				break;
			if (c == '[') {
				++i;
			} else
				if (c == 'L') {
					++count;
					i = CharOperation.indexOf(';', sig, i + 1) + 1;
					Assert.isTrue(i != 0);
				} else {
					++count;
					++i;
				}
		}
		return count;
	}

	/**
	 * Put all the arguments in one String.
	 */
	public static String getProblemArgumentsForMarker(String[] arguments){
		StringBuffer args = new StringBuffer(10);

		args.append(arguments.length);
		args.append(':');


		for (int j = 0; j < arguments.length; j++) {
			if(j != 0)
				args.append(ARGUMENTS_DELIMITER);

			if(arguments[j].length() == 0) {
				args.append(EMPTY_ARGUMENT);
			} else {
				encodeArgument(arguments[j], args);
			}
		}

		return args.toString();
	}

	/**
	 * Encode the argument by doubling the '#' if present into the argument value.
	 * 
	 * <p>This stores the encoded argument into the given buffer.</p>
	 *
	 * @param argument the given argument
	 * @param buffer the buffer in which the encoded argument is stored
	 */
	private static void encodeArgument(String argument, StringBuffer buffer) {
		for (int i = 0, max = argument.length(); i < max; i++) {
			char charAt = argument.charAt(i);
			switch(charAt) {
				case ARGUMENTS_DELIMITER :
					buffer.append(ARGUMENTS_DELIMITER).append(ARGUMENTS_DELIMITER);
					break;
				default:
					buffer.append(charAt);
			}
		}
	}

	/**
	 * Separate all the arguments of a String made by getProblemArgumentsForMarker
	 */
	public static String[] getProblemArgumentsFromMarker(String argumentsString){
		if (argumentsString == null) {
			return null;
		}
		int index = argumentsString.indexOf(':');
		if(index == -1)
			return null;

		int length = argumentsString.length();
		int numberOfArg = 0;
		try{
			numberOfArg = Integer.parseInt(argumentsString.substring(0 , index));
		} catch (NumberFormatException e) {
			return null;
		}
		argumentsString = argumentsString.substring(index + 1, length);

		return decodeArgumentString(numberOfArg, argumentsString);
	}

	private static String[] decodeArgumentString(int length, String argumentsString) {
		// decode the argumentString knowing that '#' is doubled if part of the argument value
		if (length == 0) {
			if (argumentsString.length() != 0) {
				return null;
			}
			return CharOperation.NO_STRINGS;
		}
		String[] result = new String[length];
		int count = 0;
		StringBuffer buffer = new StringBuffer();
		for (int i = 0, max = argumentsString.length(); i < max; i++) {
			char current = argumentsString.charAt(i);
			switch(current) {
				case ARGUMENTS_DELIMITER :
					/* check the next character. If this is also ARGUMENTS_DELIMITER then only put one into the
					 * decoded argument and proceed with the next character
					 */
					if ((i + 1) == max) {
						return null;
					}
					char next = argumentsString.charAt(i + 1);
					if (next == ARGUMENTS_DELIMITER) {
						buffer.append(ARGUMENTS_DELIMITER);
						i++; // proceed with the next character
					} else {
						// this means the current argument is over
						String currentArgumentContents = String.valueOf(buffer);
						if (EMPTY_ARGUMENT.equals(currentArgumentContents)) {
							currentArgumentContents = org.eclipse.jdt.internal.compiler.util.Util.EMPTY_STRING;
						}
						result[count++] = currentArgumentContents;
						if (count > length) {
							// too many elements - ill-formed
							return null;
						}
						buffer.delete(0, buffer.length());
					}
					break;
				default :
					buffer.append(current);
			}
		}
		// process last argument
		String currentArgumentContents = String.valueOf(buffer);
		if (EMPTY_ARGUMENT.equals(currentArgumentContents)) {
			currentArgumentContents = org.eclipse.jdt.internal.compiler.util.Util.EMPTY_STRING;
		}
		result[count++] = currentArgumentContents;
		if (count > length) {
			// too many elements - ill-formed
			return null;
		}
		buffer.delete(0, buffer.length());
		return result;
	}

	/**
	 * Returns the given file's contents as a byte array.
	 */
	public static byte[] getResourceContentsAsByteArray(IFile file) throws JavaModelException {
		InputStream stream= null;
		try {
			stream = file.getContents(true);
		} catch (CoreException e) {
			throw new JavaModelException(e);
		}
		try {
			return org.eclipse.jdt.internal.compiler.util.Util.getInputStreamAsByteArray(stream, -1);
		} catch (IOException e) {
			throw new JavaModelException(e, IJavaModelStatusConstants.IO_EXCEPTION);
		} finally {
			try {
				stream.close();
			} catch (IOException e) {
				// ignore
			}
		}
	}

	/**
	 * Returns the given file's contents as a character array.
	 */
	public static char[] getResourceContentsAsCharArray(IFile file) throws JavaModelException {
		// Get encoding from file
		String encoding;
		try {
			encoding = file.getCharset();
		} catch(CoreException ce) {
			// do not use any encoding
			encoding = null;
		}
		return getResourceContentsAsCharArray(file, encoding);
	}

	public static char[] getResourceContentsAsCharArray(IFile file, String encoding) throws JavaModelException {
		// Get file length
		// workaround https://bugs.eclipse.org/bugs/show_bug.cgi?id=130736 by using java.io.File if possible
		IPath location = file.getLocation();
		long length;
		if (location == null) {
			// non local file
			try {
				URI locationURI = file.getLocationURI();
				if (locationURI == null)
					throw new CoreException(new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, Messages.bind(Messages.file_notFound, file.getFullPath().toString())));
				length = EFS.getStore(locationURI).fetchInfo().getLength();
			} catch (CoreException e) {
				throw new JavaModelException(e, IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST);
			}
		} else {
			// local file
			length = location.toFile().length();
		}

		// Get resource contents
		InputStream stream= null;
		try {
			stream = file.getContents(true);
		} catch (CoreException e) {
			throw new JavaModelException(e, IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST);
		}
		try {
			return org.eclipse.jdt.internal.compiler.util.Util.getInputStreamAsCharArray(stream, (int) length, encoding);
		} catch (IOException e) {
			throw new JavaModelException(e, IJavaModelStatusConstants.IO_EXCEPTION);
		} finally {
			try {
				stream.close();
			} catch (IOException e) {
				// ignore
			}
		}
	}

	/*
	 * Returns the signature of the given type.
	 */
	public static String getSignature(Type type) {
		StringBuffer buffer = new StringBuffer();
		getFullyQualifiedName(type, buffer);
		return Signature.createTypeSignature(buffer.toString(), false/*not resolved in source*/);
	}

	/*
	 * Returns the source attachment property for this package fragment root's path
	 */
	public static String getSourceAttachmentProperty(IPath path) throws JavaModelException {
		Map rootPathToAttachments = JavaModelManager.getJavaModelManager().rootPathToAttachments;
		String property = (String) rootPathToAttachments.get(path);
		if (property == null) {
			try {
				property = ResourcesPlugin.getWorkspace().getRoot().getPersistentProperty(getSourceAttachmentPropertyName(path));
				if (property == null) {
					rootPathToAttachments.put(path, PackageFragmentRoot.NO_SOURCE_ATTACHMENT);
					return null;
				}
				rootPathToAttachments.put(path, property);
				return property;
			} catch (CoreException e)  {
				throw new JavaModelException(e);
			}
		} else if (property.equals(PackageFragmentRoot.NO_SOURCE_ATTACHMENT)) {
			return null;
		} else
			return property;
	}

	private static QualifiedName getSourceAttachmentPropertyName(IPath path) {
		return new QualifiedName(JavaCore.PLUGIN_ID, "sourceattachment: " + path.toOSString()); //$NON-NLS-1$
	}

	public static void setSourceAttachmentProperty(IPath path, String property) {
		if (property == null) {
			JavaModelManager.getJavaModelManager().rootPathToAttachments.put(path, PackageFragmentRoot.NO_SOURCE_ATTACHMENT);
		} else {
			JavaModelManager.getJavaModelManager().rootPathToAttachments.put(path, property);
		}
		try {
			ResourcesPlugin.getWorkspace().getRoot().setPersistentProperty(getSourceAttachmentPropertyName(path), property);
		} catch (CoreException e) {
			e.printStackTrace();
		}
	}

	/*
	 * Returns the declaring type signature of the element represented by the given binding key.
	 * Returns the signature of the element if it is a type.
	 *
	 * @return the declaring type signature
	 */
	public static String getDeclaringTypeSignature(String key) {
		KeyToSignature keyToSignature = new KeyToSignature(key, KeyToSignature.DECLARING_TYPE);
		keyToSignature.parse();
		return keyToSignature.signature.toString();
	}

	/*
	 * Appends to the given buffer the fully qualified name (as it appears in the source) of the given type
	 */
	private static void getFullyQualifiedName(Type type, StringBuffer buffer) {
		switch (type.getNodeType()) {
			case ASTNode.ARRAY_TYPE:
				ArrayType arrayType = (ArrayType) type;
				getFullyQualifiedName(arrayType.getElementType(), buffer);
				for (int i = 0, length = arrayType.getDimensions(); i < length; i++) {
					buffer.append('[');
					buffer.append(']');
				}
				break;
			case ASTNode.PARAMETERIZED_TYPE:
				ParameterizedType parameterizedType = (ParameterizedType) type;
				getFullyQualifiedName(parameterizedType.getType(), buffer);
				buffer.append('<');
				Iterator iterator = parameterizedType.typeArguments().iterator();
				boolean isFirst = true;
				while (iterator.hasNext()) {
					if (!isFirst)
						buffer.append(',');
					else
						isFirst = false;
					Type typeArgument = (Type) iterator.next();
					getFullyQualifiedName(typeArgument, buffer);
				}
				buffer.append('>');
				break;
			case ASTNode.PRIMITIVE_TYPE:
				buffer.append(((PrimitiveType) type).getPrimitiveTypeCode().toString());
				break;
			case ASTNode.QUALIFIED_TYPE:
				buffer.append(((QualifiedType) type).getName().getFullyQualifiedName());
				break;
			case ASTNode.SIMPLE_TYPE:
				buffer.append(((SimpleType) type).getName().getFullyQualifiedName());
				break;
			case ASTNode.WILDCARD_TYPE:
				buffer.append('?');
				WildcardType wildcardType = (WildcardType) type;
				Type bound = wildcardType.getBound();
				if (bound == null) return;
				if (wildcardType.isUpperBound()) {
					buffer.append(" extends "); //$NON-NLS-1$
				} else {
					buffer.append(" super "); //$NON-NLS-1$
				}
				getFullyQualifiedName(bound, buffer);
				break;
		}
	}

	/**
	 * Returns a trimmed version the simples names returned by Signature.
	 */
	public static String[] getTrimmedSimpleNames(String name) {
		String[] result = Signature.getSimpleNames(name);
		for (int i = 0, length = result.length; i < length; i++) {
			result[i] = result[i].trim();
		}
		return result;
	}

	/**
	 * Return the java element corresponding to the given compiler binding.
	 */
	public static JavaElement getUnresolvedJavaElement(FieldBinding binding, WorkingCopyOwner workingCopyOwner, BindingsToNodesMap bindingsToNodes) {
		if (binding.declaringClass == null) return null; // array length
		JavaElement unresolvedJavaElement = getUnresolvedJavaElement(binding.declaringClass, workingCopyOwner, bindingsToNodes);
		if (unresolvedJavaElement == null || unresolvedJavaElement.getElementType() != IJavaElement.TYPE) {
			return null;
		}
		return (JavaElement) ((IType) unresolvedJavaElement).getField(String.valueOf(binding.name));
	}

	/**
	 * Returns the IInitializer that contains the given local variable in the given type
	 */
	public static JavaElement getUnresolvedJavaElement(int localSourceStart, int localSourceEnd, JavaElement type) {
		try {
			if (!(type instanceof IType))
				return null;
			IInitializer[] initializers = ((IType) type).getInitializers();
			for (int i = 0; i < initializers.length; i++) {
				IInitializer initializer = initializers[i];
				ISourceRange sourceRange = initializer.getSourceRange();
				if (sourceRange != null) {
					int initializerStart = sourceRange.getOffset();
					int initializerEnd = initializerStart + sourceRange.getLength();
					if (initializerStart <= localSourceStart && localSourceEnd <= initializerEnd) {
						return (JavaElement) initializer;
					}
				}
			}
			return null;
		} catch (JavaModelException e) {
			return null;
		}
	}

	/**
	 * Return the java element corresponding to the given compiler binding.
	 */
	public static JavaElement getUnresolvedJavaElement(MethodBinding methodBinding, WorkingCopyOwner workingCopyOwner, BindingsToNodesMap bindingsToNodes) {
		JavaElement unresolvedJavaElement = getUnresolvedJavaElement(methodBinding.declaringClass, workingCopyOwner, bindingsToNodes);
		if (unresolvedJavaElement == null || unresolvedJavaElement.getElementType() != IJavaElement.TYPE) {
			return null;
		}
		IType declaringType = (IType) unresolvedJavaElement;

		org.eclipse.jdt.internal.compiler.ast.ASTNode node = bindingsToNodes == null ? null : bindingsToNodes.get(methodBinding);
		if (node != null && !declaringType.isBinary()) {
			if (node instanceof AnnotationMethodDeclaration) {
				// node is an AnnotationMethodDeclaration
				AnnotationMethodDeclaration typeMemberDeclaration = (AnnotationMethodDeclaration) node;
				return (JavaElement) declaringType.getMethod(String.valueOf(typeMemberDeclaration.selector), CharOperation.NO_STRINGS); // annotation type members don't have parameters
			} else {
				// node is an MethodDeclaration
				MethodDeclaration methodDeclaration = (MethodDeclaration) node;

				Argument[] arguments = methodDeclaration.arguments;
				String[] parameterSignatures;
				if (arguments != null) {
					parameterSignatures = new String[arguments.length];
					for (int i = 0; i < arguments.length; i++) {
						Argument argument = arguments[i];
						TypeReference typeReference = argument.type;
						int arrayDim = typeReference.dimensions();

						String typeSig =
							Signature.createTypeSignature(
									CharOperation.concatWith(
											typeReference.getTypeName(), '.'), false);
						if (arrayDim > 0) {
							typeSig = Signature.createArraySignature(typeSig, arrayDim);
						}
						parameterSignatures[i] = typeSig;

					}
				} else {
					parameterSignatures = CharOperation.NO_STRINGS;
				}
				return (JavaElement) declaringType.getMethod(String.valueOf(methodDeclaration.selector), parameterSignatures);
			}
		} else {
			// case of method not in the created AST, or a binary method
			org.eclipse.jdt.internal.compiler.lookup.MethodBinding original = methodBinding.original();
			String selector = original.isConstructor() ? declaringType.getElementName() : new String(original.selector);
			boolean isBinary = declaringType.isBinary();
			ReferenceBinding enclosingType = original.declaringClass.enclosingType();
			// Static inner types' constructors don't get receivers (https://bugs.eclipse.org/bugs/show_bug.cgi?id=388137)
			boolean isInnerBinaryTypeConstructor = isBinary && original.isConstructor() && !original.declaringClass.isStatic() && enclosingType != null;
			TypeBinding[] parameters = original.parameters;
			int length = parameters == null ? 0 : parameters.length;
			int declaringIndex = isInnerBinaryTypeConstructor ? 1 : 0;
			String[] parameterSignatures = new String[declaringIndex + length];
			if (isInnerBinaryTypeConstructor)
				parameterSignatures[0] = new String(enclosingType.genericTypeSignature()).replace('/', '.');
			for (int i = 0;  i < length; i++) {
				char[] signature = parameters[i].genericTypeSignature();
				if (isBinary) {
					signature = CharOperation.replaceOnCopy(signature, '/', '.');
				} else {
					signature = toUnresolvedTypeSignature(signature);
				}
				parameterSignatures[declaringIndex + i] = new String(signature);
			}
			IMethod result = declaringType.getMethod(selector, parameterSignatures);
			if (isBinary)
				return (JavaElement) result;
			if (result.exists()) // if perfect match (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=249567 )
				return (JavaElement) result;
			IMethod[] methods = null;
			try {
				methods = declaringType.getMethods();
			} catch (JavaModelException e) {
				// declaring type doesn't exist
				return null;
			}
			IMethod[] candidates = Member.findMethods(result, methods);
			if (candidates == null || candidates.length == 0)
				return null;
			return (JavaElement) candidates[0];
		}
	}

	/**
	 * Return the java element corresponding to the given compiler binding.
	 */
	public static JavaElement getUnresolvedJavaElement(TypeBinding typeBinding, WorkingCopyOwner workingCopyOwner, BindingsToNodesMap bindingsToNodes) {
		if (typeBinding == null)
			return null;
		switch (typeBinding.kind()) {
			case Binding.ARRAY_TYPE :
				typeBinding = ((org.eclipse.jdt.internal.compiler.lookup.ArrayBinding) typeBinding).leafComponentType();
				return getUnresolvedJavaElement(typeBinding, workingCopyOwner, bindingsToNodes);
			case Binding.BASE_TYPE :
			case Binding.WILDCARD_TYPE :
			case Binding.INTERSECTION_TYPE:
				return null;
			default :
				if (typeBinding.isCapture())
					return null;
		}
		ReferenceBinding referenceBinding;
		if (typeBinding.isParameterizedType() || typeBinding.isRawType())
			referenceBinding = (ReferenceBinding) typeBinding.erasure();
		else
			referenceBinding = (ReferenceBinding) typeBinding;
		char[] fileName = referenceBinding.getFileName();
		if (referenceBinding.isLocalType() || referenceBinding.isAnonymousType()) {
			// local or anonymous type
			if (org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(fileName)) {
				int jarSeparator = CharOperation.indexOf(IDependent.JAR_FILE_ENTRY_SEPARATOR, fileName);
				int pkgEnd = CharOperation.lastIndexOf('/', fileName); // pkgEnd is exclusive
				if (pkgEnd == -1)
					pkgEnd = CharOperation.lastIndexOf(File.separatorChar, fileName);
				if (jarSeparator != -1 && pkgEnd < jarSeparator) // if in a jar and no slash, it is a default package -> pkgEnd should be equal to jarSeparator
					pkgEnd = jarSeparator;
				if (pkgEnd == -1)
					return null;
				IPackageFragment pkg = getPackageFragment(fileName, pkgEnd, jarSeparator);
				char[] constantPoolName = referenceBinding.constantPoolName();
				if (constantPoolName == null) {
					ClassFile classFile = (ClassFile) getClassFile(fileName);
					return classFile == null ? null : (JavaElement) classFile.getType();
				}
				pkgEnd = CharOperation.lastIndexOf('/', constantPoolName);
				char[] classFileName = CharOperation.subarray(constantPoolName, pkgEnd+1, constantPoolName.length);
				ClassFile classFile = (ClassFile) pkg.getClassFile(new String(classFileName) + SuffixConstants.SUFFIX_STRING_class);
				return (JavaElement) classFile.getType();
			}
			ICompilationUnit cu = getCompilationUnit(fileName, workingCopyOwner);
			if (cu == null) return null;
			// must use getElementAt(...) as there is no back pointer to the defining method (scope is null after resolution has ended)
			try {
				int sourceStart = ((org.eclipse.jdt.internal.compiler.lookup.LocalTypeBinding) referenceBinding).sourceStart;
				return (JavaElement) cu.getElementAt(sourceStart);
			} catch (JavaModelException e) {
				// does not exist
				return null;
			}
		} else if (referenceBinding.isTypeVariable()) {
			// type parameter
			final String typeVariableName = new String(referenceBinding.sourceName());
			org.eclipse.jdt.internal.compiler.lookup.Binding declaringElement = ((org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding) referenceBinding).declaringElement;
			if (declaringElement instanceof MethodBinding) {
				IMethod declaringMethod = (IMethod) getUnresolvedJavaElement((MethodBinding) declaringElement, workingCopyOwner, bindingsToNodes);
				return (JavaElement) declaringMethod.getTypeParameter(typeVariableName);
			} else {
				IType declaringType = (IType) getUnresolvedJavaElement((TypeBinding) declaringElement, workingCopyOwner, bindingsToNodes);
				if (declaringType == null)
					return null;
				return (JavaElement) declaringType.getTypeParameter(typeVariableName);
			}
		} else {
			if (fileName == null) return null; // case of a WilCardBinding that doesn't have a corresponding Java element
			// member or top level type
			TypeBinding declaringTypeBinding = typeBinding.enclosingType();
			if (declaringTypeBinding == null) {
				// top level type
				if (org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(fileName)) {
					ClassFile classFile = (ClassFile) getClassFile(fileName);
					if (classFile == null) return null;
					return (JavaElement) classFile.getType();
				}
				ICompilationUnit cu = getCompilationUnit(fileName, workingCopyOwner);
				if (cu == null) return null;
				return (JavaElement) cu.getType(new String(referenceBinding.sourceName()));
			} else {
				// member type
				IType declaringType = (IType) getUnresolvedJavaElement(declaringTypeBinding, workingCopyOwner, bindingsToNodes);
				if (declaringType == null) return null;
				return (JavaElement) declaringType.getType(new String(referenceBinding.sourceName()));
			}
		}
	}

	/*
	 * Returns the index of the most specific argument paths which is strictly enclosing the path to check
	 */
	public static int indexOfEnclosingPath(IPath checkedPath, IPath[] paths, int pathCount) {

	    int bestMatch = -1, bestLength = -1;
		for (int i = 0; i < pathCount; i++){
			if (paths[i].equals(checkedPath)) continue;
			if (paths[i].isPrefixOf(checkedPath)) {
			    int currentLength = paths[i].segmentCount();
			    if (currentLength > bestLength) {
			        bestLength = currentLength;
			        bestMatch = i;
			    }
			}
		}
		return bestMatch;
	}

	/*
	 * Returns the index of the Java like extension of the given file name
	 * or -1 if it doesn't end with a known Java like extension.
	 * Note this is the index of the '.' even if it is not considered part of the extension.
	 */
	public static int indexOfJavaLikeExtension(String fileName) {
		int fileNameLength = fileName.length();
		char[][] javaLikeExtensions = getJavaLikeExtensions();
		extensions: for (int i = 0, length = javaLikeExtensions.length; i < length; i++) {
			char[] extension = javaLikeExtensions[i];
			int extensionLength = extension.length;
			int extensionStart = fileNameLength - extensionLength;
			int dotIndex = extensionStart - 1;
			if (dotIndex < 0) continue;
			if (fileName.charAt(dotIndex) != '.') continue;
			for (int j = 0; j < extensionLength; j++) {
				if (fileName.charAt(extensionStart + j) != extension[j])
					continue extensions;
			}
			return dotIndex;
		}
		return -1;
	}

	/*
	 * Returns the index of the first argument paths which is equal to the path to check
	 */
	public static int indexOfMatchingPath(IPath checkedPath, IPath[] paths, int pathCount) {

		for (int i = 0; i < pathCount; i++){
			if (paths[i].equals(checkedPath)) return i;
		}
		return -1;
	}

	/*
	 * Returns the index of the first argument paths which is strictly nested inside the path to check
	 */
	public static int indexOfNestedPath(IPath checkedPath, IPath[] paths, int pathCount) {

		for (int i = 0; i < pathCount; i++){
			if (checkedPath.equals(paths[i])) continue;
			if (checkedPath.isPrefixOf(paths[i])) return i;
		}
		return -1;
	}
	/**
	 * Returns whether the local file system supports accessing and modifying
	 * the given attribute.
	 */
	protected static boolean isAttributeSupported(int attribute) {
		return (EFS.getLocalFileSystem().attributes() & attribute) != 0;
	}

	/**
	 * Returns whether the given resource is read-only or not.
	 * @param resource
	 * @return <code>true</code> if the resource is read-only, <code>false</code> if it is not or
	 * 	if the file system does not support the read-only attribute.
	 */
	public static boolean isReadOnly(IResource resource) {
		if (isReadOnlySupported()) {
			ResourceAttributes resourceAttributes = resource.getResourceAttributes();
			if (resourceAttributes == null) return false; // not supported on this platform for this resource
			return resourceAttributes.isReadOnly();
		}
		return false;
	}

	/**
	 * Returns whether the local file system supports accessing and modifying
	 * the read only flag.
	 */
	public static boolean isReadOnlySupported() {
		return isAttributeSupported(EFS.ATTRIBUTE_READ_ONLY);
	}

	/*
	 * Returns whether the given java element is exluded from its root's classpath.
	 * It doesn't check whether the root itself is on the classpath or not
	 */
	public static final boolean isExcluded(IJavaElement element) {
		int elementType = element.getElementType();
		switch (elementType) {
			case IJavaElement.JAVA_MODEL:
			case IJavaElement.JAVA_PROJECT:
			case IJavaElement.PACKAGE_FRAGMENT_ROOT:
				return false;

			case IJavaElement.PACKAGE_FRAGMENT:
				PackageFragmentRoot root = (PackageFragmentRoot) element.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
				IResource resource = ((PackageFragment) element).resource();
				return resource != null && isExcluded(resource, root.fullInclusionPatternChars(), root.fullExclusionPatternChars());

			case IJavaElement.COMPILATION_UNIT:
				root = (PackageFragmentRoot) element.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
				resource = element.getResource();
				if (resource == null)
					return false;
				if (isExcluded(resource, root.fullInclusionPatternChars(), root.fullExclusionPatternChars()))
					return true;
				return isExcluded(element.getParent());

			default:
				IJavaElement cu = element.getAncestor(IJavaElement.COMPILATION_UNIT);
				return cu != null && isExcluded(cu);
		}
	}
	/*
	 * Returns whether the given resource path matches one of the inclusion/exclusion
	 * patterns.
	 * NOTE: should not be asked directly using pkg root pathes
	 * @see IClasspathEntry#getInclusionPatterns
	 * @see IClasspathEntry#getExclusionPatterns
	 */
	public final static boolean isExcluded(IPath resourcePath, char[][] inclusionPatterns, char[][] exclusionPatterns, boolean isFolderPath) {
		if (inclusionPatterns == null && exclusionPatterns == null) return false;
		return org.eclipse.jdt.internal.compiler.util.Util.isExcluded(resourcePath.toString().toCharArray(), inclusionPatterns, exclusionPatterns, isFolderPath);
	}

	/*
	 * Returns whether the given resource matches one of the exclusion patterns.
	 * NOTE: should not be asked directly using pkg root pathes
	 * @see IClasspathEntry#getExclusionPatterns
	 */
	public final static boolean isExcluded(IResource resource, char[][] inclusionPatterns, char[][] exclusionPatterns) {
		IPath path = resource.getFullPath();
		// ensure that folders are only excluded if all of their children are excluded
		int resourceType = resource.getType();
		return isExcluded(path, inclusionPatterns, exclusionPatterns, resourceType == IResource.FOLDER || resourceType == IResource.PROJECT);
	}


	/**
	 * Validate the given .class file name.
	 * A .class file name must obey the following rules:
	 * <ul>
	 * <li> it must not be null
	 * <li> it must include the <code>".class"</code> suffix
	 * <li> its prefix must be a valid identifier
	 * </ul>
	 * </p>
	 * @param name the name of a .class file
	 * @param sourceLevel the source level
	 * @param complianceLevel the compliance level
	 * @return a status object with code <code>IStatus.OK</code> if
	 *		the given name is valid as a .class file name, otherwise a status
	 *		object indicating what is wrong with the name
	 */
	public static boolean isValidClassFileName(String name, String sourceLevel, String complianceLevel) {
		return JavaConventions.validateClassFileName(name, sourceLevel, complianceLevel).getSeverity() != IStatus.ERROR;
	}


	/**
	 * Validate the given compilation unit name.
	 * A compilation unit name must obey the following rules:
	 * <ul>
	 * <li> it must not be null
	 * <li> it must include the <code>".java"</code> suffix
	 * <li> its prefix must be a valid identifier
	 * </ul>
	 * </p>
	 * @param name the name of a compilation unit
	 * @param sourceLevel the source level
	 * @param complianceLevel the compliance level
	 * @return a status object with code <code>IStatus.OK</code> if
	 *		the given name is valid as a compilation unit name, otherwise a status
	 *		object indicating what is wrong with the name
	 */
	public static boolean isValidCompilationUnitName(String name, String sourceLevel, String complianceLevel) {
		return JavaConventions.validateCompilationUnitName(name, sourceLevel, complianceLevel).getSeverity() != IStatus.ERROR;
	}

	/**
	 * Returns true if the given folder name is valid for a package,
	 * false if it is not.
	 * @param folderName the name of the folder
	 * @param sourceLevel the source level
	 * @param complianceLevel the compliance level
	 */
	public static boolean isValidFolderNameForPackage(String folderName, String sourceLevel, String complianceLevel) {
		return JavaConventions.validateIdentifier(folderName, sourceLevel, complianceLevel).getSeverity() != IStatus.ERROR;
	}

	/**
	 * Returns true if the given method signature is valid,
	 * false if it is not.
	 */
	public static boolean isValidMethodSignature(String sig) {
		int len = sig.length();
		if (len == 0) return false;
		int i = 0;
		char c = sig.charAt(i++);
		if (c != '(') return false;
		if (i >= len) return false;
		while (sig.charAt(i) != ')') {
			// Void is not allowed as a parameter type.
			i = checkTypeSignature(sig, i, len, false);
			if (i == -1) return false;
			if (i >= len) return false;
		}
		++i;
		i = checkTypeSignature(sig, i, len, true);
		return i == len;
	}

	/**
	 * Returns true if the given type signature is valid,
	 * false if it is not.
	 */
	public static boolean isValidTypeSignature(String sig, boolean allowVoid) {
		int len = sig.length();
		return checkTypeSignature(sig, 0, len, allowVoid) == len;
	}

	/*
	 * Returns the simple name of a local type from the given binary type name.
	 * The last '$' is at lastDollar. The last character of the type name is at end-1.
	 */
	public static String localTypeName(String binaryTypeName, int lastDollar, int end) {
		if (lastDollar > 0 && binaryTypeName.charAt(lastDollar-1) == '$')
			// local name starts with a dollar sign
			// (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=103466)
			return binaryTypeName;
		int nameStart = lastDollar+1;
		while (nameStart < end && Character.isDigit(binaryTypeName.charAt(nameStart)))
			nameStart++;
		return binaryTypeName.substring(nameStart, end);
	}

	/*
	 * Add a log entry
	 */
	public static void log(Throwable e, String message) {
		Throwable nestedException;
		if (e instanceof JavaModelException
				&& (nestedException = ((JavaModelException)e).getException()) != null) {
			e = nestedException;
		}
		log(new Status(
				IStatus.ERROR,
				JavaCore.PLUGIN_ID,
				IStatus.ERROR,
				message,
				e));
	}

	/**
	 * Log a message that is potentially repeated in the same session.
	 * The first time this method is called with a given exception, the
	 * exception stack trace is written to the log.
	 * <p>Only intended for use in debug statements.</p>
	 *
	 * @param key the given key
	 * @param e the given exception
	 * @throws IllegalArgumentException if the given key is null
	 */
	public static void logRepeatedMessage(String key, Exception e) {
		if (key == null) {
			throw new IllegalArgumentException("key cannot be null"); //$NON-NLS-1$
		}
		if (fgRepeatedMessages.contains(key)) {
			return;
		}
		fgRepeatedMessages.add(key);
		log(e);
	}

	public static void logRepeatedMessage(String key, int statusErrorID, String message) {
		if (key == null) {
			throw new IllegalArgumentException("key cannot be null"); //$NON-NLS-1$
		}
		if (fgRepeatedMessages.contains(key)) {
			return;
		}
		fgRepeatedMessages.add(key);
		log(statusErrorID, message);
	}

	/*
	 * Add a log entry
	 */
	public static void log(int statusErrorID, String message) {
		log(new Status(
				statusErrorID,
				JavaCore.PLUGIN_ID,
				message));
	}

	/*
	 * Add a log entry
	 */
	public static void log(IStatus status) {
		Plugin plugin = JavaCore.getPlugin();
		if (plugin == null) {
			System.err.println(status.toString());
		} else {
			plugin.getLog().log(status);
		}
	}

	public static void log(Throwable e) {
		log(new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, Messages.internal_error, e));
	}

	public static ClassFileReader newClassFileReader(IResource resource) throws CoreException, ClassFormatException, IOException {
		InputStream in = null;
		try {
			in = ((IFile) resource).getContents(true);
			return ClassFileReader.read(in, resource.getFullPath().toString());
		} finally {
			if (in != null)
				in.close();
		}
	}

	/**
	 * Normalizes the cariage returns in the given text.
	 * They are all changed  to use the given buffer's line separator.
	 */
	public static char[] normalizeCRs(char[] text, char[] buffer) {
		CharArrayBuffer result = new CharArrayBuffer();
		int lineStart = 0;
		int length = text.length;
		if (length == 0) return text;
		String lineSeparator = getLineSeparator(text, buffer);
		char nextChar = text[0];
		for (int i = 0; i < length; i++) {
			char currentChar = nextChar;
			nextChar = i < length-1 ? text[i+1] : ' ';
			switch (currentChar) {
				case '\n':
					int lineLength = i-lineStart;
					char[] line = new char[lineLength];
					System.arraycopy(text, lineStart, line, 0, lineLength);
					result.append(line);
					result.append(lineSeparator);
					lineStart = i+1;
					break;
				case '\r':
					lineLength = i-lineStart;
					if (lineLength >= 0) {
						line = new char[lineLength];
						System.arraycopy(text, lineStart, line, 0, lineLength);
						result.append(line);
						result.append(lineSeparator);
						if (nextChar == '\n') {
							nextChar = ' ';
							lineStart = i+2;
						} else {
							// when line separator are mixed in the same file
							// \r might not be followed by a \n. If not, we should increment
							// lineStart by one and not by two.
							lineStart = i+1;
						}
					} else {
						// when line separator are mixed in the same file
						// we need to prevent NegativeArraySizeException
						lineStart = i+1;
					}
					break;
			}
		}
		char[] lastLine;
		if (lineStart > 0) {
			int lastLineLength = length-lineStart;
			if (lastLineLength > 0) {
				lastLine = new char[lastLineLength];
				System.arraycopy(text, lineStart, lastLine, 0, lastLineLength);
				result.append(lastLine);
			}
			return result.getContents();
		}
		return text;
	}

	/**
	 * Normalizes the carriage returns in the given text.
	 * They are all changed to use given buffer's line separator.
	 */
	public static String normalizeCRs(String text, String buffer) {
		return new String(normalizeCRs(text.toCharArray(), buffer.toCharArray()));
	}

	/**
	 * Converts the given relative path into a package name.
	 * Returns null if the path is not a valid package name.
	 * @param pkgPath the package path
	 * @param sourceLevel the source level
	 * @param complianceLevel the compliance level
	 */
	public static String packageName(IPath pkgPath, String sourceLevel, String complianceLevel) {
		StringBuffer pkgName = new StringBuffer(IPackageFragment.DEFAULT_PACKAGE_NAME);
		for (int j = 0, max = pkgPath.segmentCount(); j < max; j++) {
			String segment = pkgPath.segment(j);
			if (!isValidFolderNameForPackage(segment, sourceLevel, complianceLevel)) {
				return null;
			}
			pkgName.append(segment);
			if (j < pkgPath.segmentCount() - 1) {
				pkgName.append("." ); //$NON-NLS-1$
			}
		}
		return pkgName.toString();
	}

	/**
	 * Returns the length of the common prefix between s1 and s2.
	 */
	public static int prefixLength(char[] s1, char[] s2) {
		int len= 0;
		int max= Math.min(s1.length, s2.length);
		for (int i= 0; i < max && s1[i] == s2[i]; ++i)
			++len;
		return len;
	}
	/**
	 * Returns the length of the common prefix between s1 and s2.
	 */
	public static int prefixLength(String s1, String s2) {
		int len= 0;
		int max= Math.min(s1.length(), s2.length());
		for (int i= 0; i < max && s1.charAt(i) == s2.charAt(i); ++i)
			++len;
		return len;
	}
	private static void quickSort(char[][] list, int left, int right) {
		int original_left= left;
		int original_right= right;
		char[] mid= list[left + (right - left) / 2];
		do {
			while (compare(list[left], mid) < 0) {
				left++;
			}
			while (compare(mid, list[right]) < 0) {
				right--;
			}
			if (left <= right) {
				char[] tmp= list[left];
				list[left]= list[right];
				list[right]= tmp;
				left++;
				right--;
			}
		} while (left <= right);
		if (original_left < right) {
			quickSort(list, original_left, right);
		}
		if (left < original_right) {
			quickSort(list, left, original_right);
		}
	}

	/**
	 * Sort the comparable objects in the given collection.
	 */
	private static void quickSort(Comparable[] sortedCollection, int left, int right) {
		int original_left = left;
		int original_right = right;
		Comparable mid = sortedCollection[ left + (right - left) / 2];
		do {
			while (sortedCollection[left].compareTo(mid) < 0) {
				left++;
			}
			while (mid.compareTo(sortedCollection[right]) < 0) {
				right--;
			}
			if (left <= right) {
				Comparable tmp = sortedCollection[left];
				sortedCollection[left] = sortedCollection[right];
				sortedCollection[right] = tmp;
				left++;
				right--;
			}
		} while (left <= right);
		if (original_left < right) {
			quickSort(sortedCollection, original_left, right);
		}
		if (left < original_right) {
			quickSort(sortedCollection, left, original_right);
		}
	}
	private static void quickSort(int[] list, int left, int right) {
		int original_left= left;
		int original_right= right;
		int mid= list[left + (right - left) / 2];
		do {
			while (list[left] < mid) {
				left++;
			}
			while (mid < list[right]) {
				right--;
			}
			if (left <= right) {
				int tmp= list[left];
				list[left]= list[right];
				list[right]= tmp;
				left++;
				right--;
			}
		} while (left <= right);
		if (original_left < right) {
			quickSort(list, original_left, right);
		}
		if (left < original_right) {
			quickSort(list, left, original_right);
		}
	}

	/**
	 * Sort the objects in the given collection using the given comparer.
	 */
	private static void quickSort(Object[] sortedCollection, int left, int right, Comparer comparer) {
		int original_left = left;
		int original_right = right;
		Object mid = sortedCollection[ left + (right - left) / 2];
		do {
			while (comparer.compare(sortedCollection[left], mid) < 0) {
				left++;
			}
			while (comparer.compare(mid, sortedCollection[right]) < 0) {
				right--;
			}
			if (left <= right) {
				Object tmp = sortedCollection[left];
				sortedCollection[left] = sortedCollection[right];
				sortedCollection[right] = tmp;
				left++;
				right--;
			}
		} while (left <= right);
		if (original_left < right) {
			quickSort(sortedCollection, original_left, right, comparer);
		}
		if (left < original_right) {
			quickSort(sortedCollection, left, original_right, comparer);
		}
	}

	/**
	 * Sort the strings in the given collection.
	 */
	private static void quickSort(String[] sortedCollection, int left, int right) {
		int original_left = left;
		int original_right = right;
		String mid = sortedCollection[ left + (right - left) / 2];
		do {
			while (sortedCollection[left].compareTo(mid) < 0) {
				left++;
			}
			while (mid.compareTo(sortedCollection[right]) < 0) {
				right--;
			}
			if (left <= right) {
				String tmp = sortedCollection[left];
				sortedCollection[left] = sortedCollection[right];
				sortedCollection[right] = tmp;
				left++;
				right--;
			}
		} while (left <= right);
		if (original_left < right) {
			quickSort(sortedCollection, original_left, right);
		}
		if (left < original_right) {
			quickSort(sortedCollection, left, original_right);
		}
	}

	/**
	 * Returns the toString() of the given full path minus the first given number of segments.
	 * The returned string is always a relative path (it has no leading slash)
	 */
	public static String relativePath(IPath fullPath, int skipSegmentCount) {
		boolean hasTrailingSeparator = fullPath.hasTrailingSeparator();
		String[] segments = fullPath.segments();

		// compute length
		int length = 0;
		int max = segments.length;
		if (max > skipSegmentCount) {
			for (int i1 = skipSegmentCount; i1 < max; i1++) {
				length += segments[i1].length();
			}
			//add the separator lengths
			length += max - skipSegmentCount - 1;
		}
		if (hasTrailingSeparator)
			length++;

		char[] result = new char[length];
		int offset = 0;
		int len = segments.length - 1;
		if (len >= skipSegmentCount) {
			//append all but the last segment, with separators
			for (int i = skipSegmentCount; i < len; i++) {
				int size = segments[i].length();
				segments[i].getChars(0, size, result, offset);
				offset += size;
				result[offset++] = '/';
			}
			//append the last segment
			int size = segments[len].length();
			segments[len].getChars(0, size, result, offset);
			offset += size;
		}
		if (hasTrailingSeparator)
			result[offset++] = '/';
		return new String(result);
	}

	/*
	 * Resets the list of Java-like extensions after a change in content-type.
	 */
	public static void resetJavaLikeExtensions() {
		JAVA_LIKE_EXTENSIONS = null;
	}

	/**
	 * Scans the given string for a type signature starting at the given index
	 * and returns the index of the last character.
	 * <pre>
	 * TypeSignature:
	 *  |  BaseTypeSignature
	 *  |  ArrayTypeSignature
	 *  |  ClassTypeSignature
	 *  |  TypeVariableSignature
	 * </pre>
	 *
	 * @param string the signature string
	 * @param start the 0-based character index of the first character
	 * @return the 0-based character index of the last character
	 * @exception IllegalArgumentException if this is not a type signature
	 */
	public static int scanTypeSignature(char[] string, int start) {
		// this method is used in jdt.debug
		return org.eclipse.jdt.internal.compiler.util.Util.scanTypeSignature(string, start);
	}
	/**
	 * Return a new array which is the split of the given string using the given divider. The given end
	 * is exclusive and the given start is inclusive.
	 * <br>
	 * <br>
	 * For example:
	 * <ol>
	 * <li><pre>
	 *    divider = 'b'
	 *    string = "abbaba"
	 *    start = 2
	 *    end = 5
	 *    result => { "", "a", "" }
	 * </pre>
	 * </li>
	 * </ol>
	 *
	 * @param divider the given divider
	 * @param string the given string
	 * @param start the given starting index
	 * @param end the given ending index
	 * @return a new array which is the split of the given string using the given divider
	 * @throws ArrayIndexOutOfBoundsException if start is lower than 0 or end is greater than the array length
	 */
	public static final String[] splitOn(
		char divider,
		String string,
		int start,
		int end) {
		int length = string == null ? 0 : string.length();
		if (length == 0 || start > end)
			return CharOperation.NO_STRINGS;

		int wordCount = 1;
		for (int i = start; i < end; i++)
			if (string.charAt(i) == divider)
				wordCount++;
		String[] split = new String[wordCount];
		int last = start, currentWord = 0;
		for (int i = start; i < end; i++) {
			if (string.charAt(i) == divider) {
				split[currentWord++] = string.substring(last, i);
				last = i + 1;
			}
		}
		split[currentWord] = string.substring(last, end);
		return split;
	}
	/**
	 * Sets or unsets the given resource as read-only in the file system.
	 * It's a no-op if the file system does not support the read-only attribute.
	 *
	 * @param resource The resource to set as read-only
	 * @param readOnly <code>true</code> to set it to read-only,
	 *		<code>false</code> to unset
	 */
	public static void setReadOnly(IResource resource, boolean readOnly) {
		if (isReadOnlySupported()) {
			ResourceAttributes resourceAttributes = resource.getResourceAttributes();
			if (resourceAttributes == null) return; // not supported on this platform for this resource
			resourceAttributes.setReadOnly(readOnly);
			try {
				resource.setResourceAttributes(resourceAttributes);
			} catch (CoreException e) {
				// ignore
			}
		}
	}
	public static void sort(char[][] list) {
		if (list.length > 1)
			quickSort(list, 0, list.length - 1);
	}

	/**
	 * Sorts an array of Comparable objects in place.
	 */
	public static void sort(Comparable[] objects) {
		if (objects.length > 1)
			quickSort(objects, 0, objects.length - 1);
	}
	public static void sort(int[] list) {
		if (list.length > 1)
			quickSort(list, 0, list.length - 1);
	}

	/**
	 * Sorts an array of objects in place.
	 * The given comparer compares pairs of items.
	 */
	public static void sort(Object[] objects, Comparer comparer) {
		if (objects.length > 1)
			quickSort(objects, 0, objects.length - 1, comparer);
	}

	/**
	 * Sorts an array of strings in place using quicksort.
	 */
	public static void sort(String[] strings) {
		if (strings.length > 1)
			quickSort(strings, 0, strings.length - 1);
	}

	/**
	 * Sorts an array of Comparable objects, returning a new array
	 * with the sorted items.  The original array is left untouched.
	 */
	public static Comparable[] sortCopy(Comparable[] objects) {
		int len = objects.length;
		Comparable[] copy = new Comparable[len];
		System.arraycopy(objects, 0, copy, 0, len);
		sort(copy);
		return copy;
	}

	/**
	 * Sorts an array of Java elements based on their toStringWithAncestors(),
	 * returning a new array with the sorted items.
	 * The original array is left untouched.
	 */
	public static IJavaElement[] sortCopy(IJavaElement[] elements) {
		int len = elements.length;
		IJavaElement[] copy = new IJavaElement[len];
		System.arraycopy(elements, 0, copy, 0, len);
		sort(copy, new Comparer() {
			@Override
			public int compare(Object a, Object b) {
				return ((JavaElement) a).toStringWithAncestors().compareTo(((JavaElement) b).toStringWithAncestors());
			}
		});
		return copy;
	}

	/**
	 * Sorts an array of Strings, returning a new array
	 * with the sorted items.  The original array is left untouched.
	 */
	public static Object[] sortCopy(Object[] objects, Comparer comparer) {
		int len = objects.length;
		Object[] copy = new Object[len];
		System.arraycopy(objects, 0, copy, 0, len);
		sort(copy, comparer);
		return copy;
	}

	/**
	 * Sorts an array of Strings, returning a new array
	 * with the sorted items.  The original array is left untouched.
	 */
	public static String[] sortCopy(String[] objects) {
		int len = objects.length;
		String[] copy = new String[len];
		System.arraycopy(objects, 0, copy, 0, len);
		sort(copy);
		return copy;
	}

	/*
	 * Returns whether the given compound name starts with the given prefix.
	 * Returns true if the n first elements of the prefix are equals and the last element of the
	 * prefix is a prefix of the corresponding element in the compound name.
	 */
	public static boolean startsWithIgnoreCase(String[] compoundName, String[] prefix, boolean partialMatch) {
		int prefixLength = prefix.length;
		int nameLength = compoundName.length;
		if (prefixLength > nameLength) return false;
		for (int i = 0; i < prefixLength - 1; i++) {
			if (!compoundName[i].equalsIgnoreCase(prefix[i]))
				return false;
		}
		return (partialMatch || prefixLength == nameLength) && compoundName[prefixLength-1].toLowerCase().startsWith(prefix[prefixLength-1].toLowerCase());
	}

	/**
	 * Converts a String[] to char[][].
	 */
	public static char[][] toCharArrays(String[] a) {
		int len = a.length;
		if (len == 0) return CharOperation.NO_CHAR_CHAR;
		char[][] result = new char[len][];
		for (int i = 0; i < len; ++i) {
			result[i] = a[i].toCharArray();
		}
		return result;
	}

	/**
	 * Converts a String to char[][], where segments are separate by '.'.
	 */
	public static char[][] toCompoundChars(String s) {
		int len = s.length();
		if (len == 0) {
			return CharOperation.NO_CHAR_CHAR;
		}
		int segCount = 1;
		for (int off = s.indexOf('.'); off != -1; off = s.indexOf('.', off + 1)) {
			++segCount;
		}
		char[][] segs = new char[segCount][];
		int start = 0;
		for (int i = 0; i < segCount; ++i) {
			int dot = s.indexOf('.', start);
			int end = (dot == -1 ? s.length() : dot);
			segs[i] = new char[end - start];
			s.getChars(start, end, segs[i], 0);
			start = end + 1;
		}
		return segs;
	}

	/*
	 * Converts the given URI to a local file. Use the existing file if the uri is on the local file system.
	 * Otherwise fetch it.
	 * Returns null if unable to fetch it.
	 */
	public static File toLocalFile(URI uri, IProgressMonitor monitor) throws CoreException {
		IFileStore fileStore = EFS.getStore(uri);
		File localFile = fileStore.toLocalFile(EFS.NONE, monitor);
		if (localFile ==null)
			// non local file system
			localFile= fileStore.toLocalFile(EFS.CACHE, monitor);
		return localFile;
	}
	/**
	 * Converts a char[][] to String, where segments are separated by '.'.
	 */
	public static String toString(char[][] c) {
		StringBuffer sb = new StringBuffer();
		for (int i = 0, max = c.length; i < max; ++i) {
			if (i != 0) sb.append('.');
			sb.append(c[i]);
		}
		return sb.toString();
	}

	/**
	 * Converts a char[][] and a char[] to String, where segments are separated by '.'.
	 */
	public static String toString(char[][] c, char[] d) {
		if (c == null) return new String(d);
		StringBuffer sb = new StringBuffer();
		for (int i = 0, max = c.length; i < max; ++i) {
			sb.append(c[i]);
			sb.append('.');
		}
		sb.append(d);
		return sb.toString();
	}

	/*
	 * Converts a char[][] to String[].
	 */
	public static String[] toStrings(char[][] a) {
		int len = a.length;
		String[] result = new String[len];
		for (int i = 0; i < len; ++i) {
			result[i] = new String(a[i]);
		}
		return result;
	}
	private static char[] toUnresolvedTypeSignature(char[] signature) {
		int length = signature.length;
		if (length <= 1)
			return signature;
		StringBuffer buffer = new StringBuffer(length);
		toUnresolvedTypeSignature(signature, 0, length, buffer);
		int bufferLength = buffer.length();
		char[] result = new char[bufferLength];
		buffer.getChars(0, bufferLength, result, 0);
		return result;
	}

	private static int toUnresolvedTypeSignature(char[] signature, int start, int length, StringBuffer buffer) {
		if (signature[start] == Signature.C_RESOLVED)
			buffer.append(Signature.C_UNRESOLVED);
		else
			buffer.append(signature[start]);
		for (int i = start+1; i < length; i++) {
			char c = signature[i];
			switch (c) {
			case '/':
			case Signature.C_DOLLAR:
				buffer.append(Signature.C_DOT);
				break;
			case Signature.C_GENERIC_START:
				buffer.append(Signature.C_GENERIC_START);
				i = toUnresolvedTypeSignature(signature, i+1, length, buffer);
				break;
			case Signature.C_GENERIC_END:
				buffer.append(Signature.C_GENERIC_END);
				return i;
			default:
				buffer.append(c);
				break;
			}
		}
		return length;
	}
	private static void appendArrayTypeSignature(char[] string, int start, StringBuffer buffer, boolean compact) {
		int length = string.length;
		// need a minimum 2 char
		if (start >= length - 1) {
			throw raiseIllegalSignatureException(string, start);
		}
		char c = string[start];
		if (c != Signature.C_ARRAY) {
			throw raiseUnexpectedCharacterException(string, start, c);
		}

		int index = start;
		c = string[++index];
		while(c == Signature.C_ARRAY) {
			// need a minimum 2 char
			if (index >= length - 1) {
				throw raiseIllegalSignatureException(string, start);
			}
			c = string[++index];
		}

		appendTypeSignature(string, index, buffer, compact);

		for(int i = 0, dims = index - start; i < dims; i++) {
			buffer.append('[').append(']');
		}
	}
	private static void appendClassTypeSignature(char[] string, int start, StringBuffer buffer, boolean compact) {
		char c = string[start];
		if (c != Signature.C_RESOLVED) {
			return;
		}
		int p = start + 1;
		int checkpoint = buffer.length();
		while (true) {
			c = string[p];
			switch(c) {
				case Signature.C_SEMICOLON :
					// all done
					return;
				case Signature.C_DOT :
				case '/' :
					// erase package prefix
					if (compact) {
						buffer.setLength(checkpoint);
					} else {
						buffer.append('.');
					}
					break;
				 case Signature.C_DOLLAR :
					/**
					 * Convert '$' in resolved type signatures into '.'.
					 * NOTE: This assumes that the type signature is an inner type
					 * signature. This is true in most cases, but someone can define a
					 * non-inner type name containing a '$'.
					 */
					buffer.append('.');
				 	break;
				 default :
					buffer.append(c);
			}
			p++;
		}
	}
	static void appendTypeSignature(char[] string, int start, StringBuffer buffer, boolean compact) {
		char c = string[start];
		switch (c) {
			case Signature.C_ARRAY :
				appendArrayTypeSignature(string, start, buffer, compact);
				break;
			case Signature.C_RESOLVED :
				appendClassTypeSignature(string, start, buffer, compact);
				break;
			case Signature.C_TYPE_VARIABLE :
				int e = org.eclipse.jdt.internal.compiler.util.Util.scanTypeVariableSignature(string, start);
				buffer.append(string, start + 1, e - start - 1);
				break;
			case Signature.C_BOOLEAN :
				buffer.append(BOOLEAN);
				break;
			case Signature.C_BYTE :
				buffer.append(BYTE);
				break;
			case Signature.C_CHAR :
				buffer.append(CHAR);
				break;
			case Signature.C_DOUBLE :
				buffer.append(DOUBLE);
				break;
			case Signature.C_FLOAT :
				buffer.append(FLOAT);
				break;
			case Signature.C_INT :
				buffer.append(INT);
				break;
			case Signature.C_LONG :
				buffer.append(LONG);
				break;
			case Signature.C_SHORT :
				buffer.append(SHORT);
				break;
			case Signature.C_VOID :
				buffer.append(VOID);
				break;
		}
	}
	public static String toString(char[] declaringClass, char[] methodName, char[] methodSignature, boolean includeReturnType, boolean compact) {
		final boolean isConstructor = CharOperation.equals(methodName, INIT);
		int firstParen = CharOperation.indexOf(Signature.C_PARAM_START, methodSignature);
		if (firstParen == -1) {
			return ""; //$NON-NLS-1$
		}

		StringBuffer buffer = new StringBuffer(methodSignature.length + 10);

		// decode declaring class name
		// it can be either an array signature or a type signature
		if (declaringClass != null && declaringClass.length > 0) {
			char[] declaringClassSignature = null;
			if (declaringClass[0] == Signature.C_ARRAY) {
				CharOperation.replace(declaringClass, '/', '.');
				declaringClassSignature = Signature.toCharArray(declaringClass);
			} else {
				CharOperation.replace(declaringClass, '/', '.');
				declaringClassSignature = declaringClass;
			}
			int lastIndexOfSlash = CharOperation.lastIndexOf('.', declaringClassSignature);
			if (compact && lastIndexOfSlash != -1) {
				buffer.append(declaringClassSignature, lastIndexOfSlash + 1, declaringClassSignature.length - lastIndexOfSlash - 1);
			} else {
				buffer.append(declaringClassSignature);
			}
			if (!isConstructor) {
				buffer.append('.');
			}
		}

		// selector
		if (!isConstructor && methodName != null) {
			buffer.append(methodName);
		}

		// parameters
		buffer.append('(');
		char[][] pts = Signature.getParameterTypes(methodSignature);
		for (int i = 0, max = pts.length; i < max; i++) {
			appendTypeSignature(pts[i], 0 , buffer, compact);
			if (i != pts.length - 1) {
				buffer.append(',');
				buffer.append(' ');
			}
		}
		buffer.append(')');

		if (!isConstructor) {
			buffer.append(" : "); //$NON-NLS-1$
			// return type
			if (includeReturnType) {
				char[] rts = Signature.getReturnType(methodSignature);
				appendTypeSignature(rts, 0 , buffer, compact);
			}
		}
		return String.valueOf(buffer);
	}
	/*
	 * Returns the unresolved type parameter signatures of the given method
	 * e.g. {"QString;", "[int", "[[Qjava.util.Vector;"}
	 */
	public static String[] typeParameterSignatures(AbstractMethodDeclaration method) {
		Argument[] args = method.arguments;
		if (args != null) {
			int length = args.length;
			String[] signatures = new String[length];
			for (int i = 0; i < args.length; i++) {
				Argument arg = args[i];
				signatures[i] = typeSignature(arg.type);
			}
			return signatures;
		}
		return CharOperation.NO_STRINGS;
	}

	/*
	 * Returns the unresolved type signature of the given type reference,
	 * e.g. "QString;", "[int", "[[Qjava.util.Vector;"
	 */
	public static String typeSignature(TypeReference type) {
		String signature = null;
		if ((type.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.IsUnionType) != 0) {
			// special treatment for union type reference
			UnionTypeReference unionTypeReference = (UnionTypeReference) type;
			TypeReference[] typeReferences = unionTypeReference.typeReferences;
			String[] typeSignatures = typeSignatures(typeReferences);
			signature = Signature.createIntersectionTypeSignature(typeSignatures);
		} else if (type instanceof IntersectionCastTypeReference) {
			IntersectionCastTypeReference intersection = (IntersectionCastTypeReference) type;
			TypeReference[] typeReferences = intersection.typeReferences;
			String[] typeSignatures = typeSignatures(typeReferences);
			signature = Signature.createUnionTypeSignature(typeSignatures);
		} else {
			char[][] compoundName = type.getParameterizedTypeName();
			char[] typeName =CharOperation.concatWith(compoundName, '.');
			signature = Signature.createTypeSignature(typeName, false/*don't resolve*/);
		}
		return signature;
	}
	
	private static String[] typeSignatures(TypeReference[] types) {
		int length = types.length;
		String[] typeSignatures = new String[length];
		for(int i = 0; i < length; i++) {
			char[][] compoundName = types[i].getParameterizedTypeName();
			char[] typeName = CharOperation.concatWith(compoundName, '.');
			typeSignatures[i] = Signature.createTypeSignature(typeName, false/*don't resolve*/);
		}
		return typeSignatures;
	}
	/**
	 * Asserts that the given method signature is valid.
	 */
	public static void validateMethodSignature(String sig) {
		Assert.isTrue(isValidMethodSignature(sig));
	}

	/**
	 * Asserts that the given type signature is valid.
	 */
	public static void validateTypeSignature(String sig, boolean allowVoid) {
		Assert.isTrue(isValidTypeSignature(sig, allowVoid));
	}
	public static void verbose(String log) {
		verbose(log, System.out);
	}
	public static synchronized void verbose(String log, PrintStream printStream) {
		int start = 0;
		do {
			int end = log.indexOf('\n', start);
			printStream.print(Thread.currentThread());
			printStream.print(" "); //$NON-NLS-1$
			printStream.print(log.substring(start, end == -1 ? log.length() : end+1));
			start = end+1;
		} while (start != 0);
		printStream.println();
	}

	/**
	 * Returns true if the given name ends with one of the known java like extension.
	 * (implementation is not creating extra strings)
	 */
	public final static boolean isJavaLikeFileName(String name) {
		if (name == null) return false;
		return indexOfJavaLikeExtension(name) != -1;
	}

	/**
	 * Returns true if the given name ends with one of the known java like extension.
	 * (implementation is not creating extra strings)
	 */
	public final static boolean isJavaLikeFileName(char[] fileName) {
		if (fileName == null) return false;
		int fileNameLength = fileName.length;
		char[][] javaLikeExtensions = getJavaLikeExtensions();
		extensions: for (int i = 0, length = javaLikeExtensions.length; i < length; i++) {
			char[] extension = javaLikeExtensions[i];
			int extensionLength = extension.length;
			int extensionStart = fileNameLength - extensionLength;
			if (extensionStart-1 < 0) continue;
			if (fileName[extensionStart-1] != '.') continue;
			for (int j = 0; j < extensionLength; j++) {
				if (fileName[extensionStart + j] != extension[j])
					continue extensions;
			}
			return true;
		}
		return false;
	}

	/**
	 * Get all type arguments from an array of signatures.
	 *
	 * Example:
	 * 	For following type X<Y<Z>,V<W>,U>.A<B> signatures is:
	 * 	[
	 * 		['L','X','<','L','Y','<','L','Z',';'>',';','L','V','<','L','W',';'>',';','L','U',';',>',';'],
	 * 		['L','A','<','L','B',';','>',';']
	 * 	]
	 * 	@see #splitTypeLevelsSignature(String)
	 * 	Then, this method returns:
	 * 	[
	 * 		[
	 * 			['L','Y','<','L','Z',';'>',';'],
	 * 			['L','V','<','L','W',';'>',';'],
	 * 			['L','U',';']
	 * 		],
	 * 		[
	 * 			['L','B',';']
	 * 		]
	 * 	]
	 *
	 * @param typeSignatures Array of signatures (one per each type levels)
	 * @throws IllegalArgumentException If one of provided signature is malformed
	 * @return char[][][] Array of type arguments for each signature
	 */
	public final static char[][][] getAllTypeArguments(char[][] typeSignatures) {
		if (typeSignatures == null) return null;
		int length = typeSignatures.length;
		char[][][] typeArguments = new char[length][][];
		for (int i=0; i<length; i++){
			typeArguments[i] = Signature.getTypeArguments(typeSignatures[i]);
		}
		return typeArguments;
	}
	public static IAnnotation getAnnotation(JavaElement parent, IBinaryAnnotation binaryAnnotation, String memberValuePairName) {
		char[] typeName = org.eclipse.jdt.core.Signature.toCharArray(CharOperation.replaceOnCopy(binaryAnnotation.getTypeName(), '/', '.'));
		return new Annotation(parent, new String(typeName), memberValuePairName);
	}
	
	public static Object getAnnotationMemberValue(JavaElement parent, MemberValuePair memberValuePair, Object binaryValue) {
		if (binaryValue instanceof Constant) {
			return getAnnotationMemberValue(memberValuePair, (Constant) binaryValue);
		} else if (binaryValue instanceof IBinaryAnnotation) {
			memberValuePair.valueKind = IMemberValuePair.K_ANNOTATION;
			return getAnnotation(parent, (IBinaryAnnotation) binaryValue, memberValuePair.getMemberName());
		} else if (binaryValue instanceof ClassSignature) {
			memberValuePair.valueKind = IMemberValuePair.K_CLASS;
			char[] className = Signature.toCharArray(CharOperation.replaceOnCopy(((ClassSignature) binaryValue).getTypeName(), '/', '.'));
			return new String(className);
		} else if (binaryValue instanceof EnumConstantSignature) {
			memberValuePair.valueKind = IMemberValuePair.K_QUALIFIED_NAME;
			EnumConstantSignature enumConstant = (EnumConstantSignature) binaryValue;
			char[] enumName = Signature.toCharArray(CharOperation.replaceOnCopy(enumConstant.getTypeName(), '/', '.'));
			char[] qualifiedName = CharOperation.concat(enumName, enumConstant.getEnumConstantName(), '.');
			return new String(qualifiedName);
		} else if (binaryValue instanceof Object[]) {
			memberValuePair.valueKind = -1; // modified below by the first call to getMemberValue(...)
			Object[] binaryValues = (Object[]) binaryValue;
			int length = binaryValues.length;
			Object[] values = new Object[length];
			for (int i = 0; i < length; i++) {
				int previousValueKind = memberValuePair.valueKind;
				Object value = getAnnotationMemberValue(parent, memberValuePair, binaryValues[i]);
				if (previousValueKind != -1 && memberValuePair.valueKind != previousValueKind) {
					// values are heterogeneous, value kind is thus unknown
					memberValuePair.valueKind = IMemberValuePair.K_UNKNOWN;
				}
				if (value instanceof Annotation) {
					Annotation annotation = (Annotation) value;
					for (int j = 0; j < i; j++) {
						if (annotation.equals(values[j])) {
							annotation.occurrenceCount++;
						}
					}
				}
				values[i] = value;
			}
			if (memberValuePair.valueKind == -1)
				memberValuePair.valueKind = IMemberValuePair.K_UNKNOWN;
			return values;
		} else {
			memberValuePair.valueKind = IMemberValuePair.K_UNKNOWN;
			return null;
		}
	}

	/*
	 * Creates a member value from the given constant, and sets the valueKind on the given memberValuePair
	 */
	public static Object getAnnotationMemberValue(MemberValuePair memberValuePair, Constant constant) {
		if (constant == null) {
			memberValuePair.valueKind = IMemberValuePair.K_UNKNOWN;
			return null;
		}
		switch (constant.typeID()) {
			case TypeIds.T_int :
				memberValuePair.valueKind = IMemberValuePair.K_INT;
				return Integer.valueOf(constant.intValue());
			case TypeIds.T_byte :
				memberValuePair.valueKind = IMemberValuePair.K_BYTE;
				return Byte.valueOf(constant.byteValue());
			case TypeIds.T_short :
				memberValuePair.valueKind = IMemberValuePair.K_SHORT;
				return Short.valueOf(constant.shortValue());
			case TypeIds.T_char :
				memberValuePair.valueKind = IMemberValuePair.K_CHAR;
				return Character.valueOf(constant.charValue());
			case TypeIds.T_float :
				memberValuePair.valueKind = IMemberValuePair.K_FLOAT;
				return new Float(constant.floatValue());
			case TypeIds.T_double :
				memberValuePair.valueKind = IMemberValuePair.K_DOUBLE;
				return new Double(constant.doubleValue());
			case TypeIds.T_boolean :
				memberValuePair.valueKind = IMemberValuePair.K_BOOLEAN;
				return Boolean.valueOf(constant.booleanValue());
			case TypeIds.T_long :
				memberValuePair.valueKind = IMemberValuePair.K_LONG;
				return Long.valueOf(constant.longValue());
			case TypeIds.T_JavaLangString :
				memberValuePair.valueKind = IMemberValuePair.K_STRING;
				return constant.stringValue();
			default:
				memberValuePair.valueKind = IMemberValuePair.K_UNKNOWN;
				return null;
		}
	}
	
	/*
	 * Creates a member value from the given constant in case of negative numerals,
	 * and sets the valueKind on the given memberValuePair
	 */
	public static Object getNegativeAnnotationMemberValue(MemberValuePair memberValuePair, Constant constant) {
		if (constant == null) {
			memberValuePair.valueKind = IMemberValuePair.K_UNKNOWN;
			return null;
		}
		switch (constant.typeID()) {
			case TypeIds.T_int :
				memberValuePair.valueKind = IMemberValuePair.K_INT;
				return Integer.valueOf(constant.intValue() * -1);
			case TypeIds.T_float :
				memberValuePair.valueKind = IMemberValuePair.K_FLOAT;
				return new Float(constant.floatValue() * -1.0f);
			case TypeIds.T_double :
				memberValuePair.valueKind = IMemberValuePair.K_DOUBLE;
				return new Double(constant.doubleValue() * -1.0);
			case TypeIds.T_long :
				memberValuePair.valueKind = IMemberValuePair.K_LONG;
				return Long.valueOf(constant.longValue() * -1L);
			default:
				memberValuePair.valueKind = IMemberValuePair.K_UNKNOWN;
				return null;
		}
	}
	/**
	 * Split signatures of all levels  from a type unique key.
	 *
	 * Example:
	 * 	For following type X<Y<Z>,V<W>,U>.A<B>, unique key is:
	 * 	"LX<LY<LZ;>;LV<LW;>;LU;>.LA<LB;>;"
	 *
	 * 	The return splitted signatures array is:
	 * 	[
	 * 		['L','X','<','L','Y','<','L','Z',';'>',';','L','V','<','L','W',';'>',';','L','U','>',';'],
	 * 		['L','A','<','L','B',';','>',';']
	 *
	 * @param typeSignature ParameterizedSourceType type signature
	 * @return char[][] Array of signatures for each level of given unique key
	 */
	public final static char[][] splitTypeLevelsSignature(String typeSignature) {
		// In case of IJavaElement signature, replace '$' by '.'
		char[] source = Signature.removeCapture(typeSignature.toCharArray());
		CharOperation.replace(source, '$', '.');

		// Init counters and arrays
		char[][] signatures = new char[10][];
		int signaturesCount = 0;
//		int[] lengthes = new int [10];
		int paramOpening = 0;

		// Scan each signature character
		for (int idx=0, ln = source.length; idx < ln; idx++) {
			switch (source[idx]) {
				case '>':
					paramOpening--;
					if (paramOpening == 0)  {
						if (signaturesCount == signatures.length) {
							System.arraycopy(signatures, 0, signatures = new char[signaturesCount+10][], 0, signaturesCount);
						}
					}
					break;
				case '<':
					paramOpening++;
					break;
				case '.':
					if (paramOpening == 0)  {
						if (signaturesCount == signatures.length) {
							System.arraycopy(signatures, 0, signatures = new char[signaturesCount+10][], 0, signaturesCount);
						}
						signatures[signaturesCount] = new char[idx+1];
						System.arraycopy(source, 0, signatures[signaturesCount], 0, idx);
						signatures[signaturesCount][idx] = Signature.C_SEMICOLON;
						signaturesCount++;
					}
					break;
				case '/':
					source[idx] = '.';
					break;
			}
		}

		// Resize signatures array
		char[][] typeSignatures = new char[signaturesCount+1][];
		typeSignatures[0] = source;
		for (int i=1, j=signaturesCount-1; i<=signaturesCount; i++, j--){
			typeSignatures[i] = signatures[j];
		}
		return typeSignatures;
	}

	/*
	 * Can throw IllegalArgumentException or ArrayIndexOutOfBoundsException
	 */
	public static String toAnchor(int startingIndex, char[] methodSignature, String methodName, boolean isVarArgs) {
		try {
			return new String(toAnchor(startingIndex, methodSignature, methodName.toCharArray(), isVarArgs));
		} catch(IllegalArgumentException e) {
			return null;
		}
	}
	public static char[] toAnchor(int startingIndex, char[] methodSignature, char[] methodName, boolean isVargArgs) {
		int firstParen = CharOperation.indexOf(Signature.C_PARAM_START, methodSignature);
		if (firstParen == -1) {
			throw new IllegalArgumentException(new String(methodSignature));
		}

		StringBuffer buffer = new StringBuffer(methodSignature.length + 10);

		// selector
		if (methodName != null) {
			buffer.append(methodName);
		}

		// parameters
		buffer.append('(');
		char[][] pts = Signature.getParameterTypes(methodSignature);
		for (int i = startingIndex, max = pts.length; i < max; i++) {
			if (i == max - 1) {
				appendTypeSignatureForAnchor(pts[i], 0 , buffer, isVargArgs);
			} else {
				appendTypeSignatureForAnchor(pts[i], 0 , buffer, false);
			}
			if (i != pts.length - 1) {
				buffer.append(',');
				buffer.append(' ');
			}
		}
		buffer.append(')');
		char[] result = new char[buffer.length()];
		buffer.getChars(0, buffer.length(), result, 0);
		return result;
	}

	private static int appendTypeSignatureForAnchor(char[] string, int start, StringBuffer buffer, boolean isVarArgs) {
		// need a minimum 1 char
		if (start >= string.length) {
			throw raiseIllegalSignatureException(string, start);
		}
		char c = string[start];
		if (isVarArgs) {
			switch (c) {
				case Signature.C_ARRAY :
					return appendArrayTypeSignatureForAnchor(string, start, buffer, true);
				case Signature.C_RESOLVED :
				case Signature.C_TYPE_VARIABLE :
				case Signature.C_BOOLEAN :
				case Signature.C_BYTE :
				case Signature.C_CHAR :
				case Signature.C_DOUBLE :
				case Signature.C_FLOAT :
				case Signature.C_INT :
				case Signature.C_LONG :
				case Signature.C_SHORT :
				case Signature.C_VOID :
				case Signature.C_STAR:
				case Signature.C_EXTENDS:
				case Signature.C_SUPER:
				case Signature.C_CAPTURE:
				default:
					// a var args is an array type
					throw raiseUnexpectedCharacterException(string, start, c);
			}
		} else {
			switch (c) {
				case Signature.C_ARRAY :
					return appendArrayTypeSignatureForAnchor(string, start, buffer, false);
				case Signature.C_RESOLVED :
					return appendClassTypeSignatureForAnchor(string, start, buffer);
				case Signature.C_TYPE_VARIABLE :
					int e = org.eclipse.jdt.internal.compiler.util.Util.scanTypeVariableSignature(string, start);
					buffer.append(string, start + 1, e - start - 1);
					return e;
				case Signature.C_BOOLEAN :
					buffer.append(BOOLEAN);
					return start;
				case Signature.C_BYTE :
					buffer.append(BYTE);
					return start;
				case Signature.C_CHAR :
					buffer.append(CHAR);
					return start;
				case Signature.C_DOUBLE :
					buffer.append(DOUBLE);
					return start;
				case Signature.C_FLOAT :
					buffer.append(FLOAT);
					return start;
				case Signature.C_INT :
					buffer.append(INT);
					return start;
				case Signature.C_LONG :
					buffer.append(LONG);
					return start;
				case Signature.C_SHORT :
					buffer.append(SHORT);
					return start;
				case Signature.C_VOID :
					buffer.append(VOID);
					return start;
				case Signature.C_CAPTURE :
					return appendCaptureTypeSignatureForAnchor(string, start, buffer);
				case Signature.C_STAR:
				case Signature.C_EXTENDS:
				case Signature.C_SUPER:
					return appendTypeArgumentSignatureForAnchor(string, start, buffer);
				default :
					throw raiseIllegalSignatureException(string, start);
			}
		}
	}

	private static int appendTypeArgumentSignatureForAnchor(char[] string, int start, StringBuffer buffer) {
		// need a minimum 1 char
		if (start >= string.length) {
			throw raiseIllegalSignatureException(string, start);
		}
		char c = string[start];
		switch(c) {
			case Signature.C_STAR :
				return start;
			case Signature.C_EXTENDS :
				return appendTypeSignatureForAnchor(string, start + 1, buffer, false);
			case Signature.C_SUPER :
				return appendTypeSignatureForAnchor(string, start + 1, buffer, false);
			default :
				return appendTypeSignatureForAnchor(string, start, buffer, false);
		}
	}
	private static int appendCaptureTypeSignatureForAnchor(char[] string, int start, StringBuffer buffer) {
		// need a minimum 2 char
		if (start >= string.length - 1) {
			throw raiseIllegalSignatureException(string, start);
		}
		char c = string[start];
		if (c != Signature.C_CAPTURE) {
			throw raiseUnexpectedCharacterException(string, start, c);
		}
		return appendTypeArgumentSignatureForAnchor(string, start + 1, buffer);
	}
	private static int appendArrayTypeSignatureForAnchor(char[] string, int start, StringBuffer buffer, boolean isVarArgs) {
		int length = string.length;
		// need a minimum 2 char
		if (start >= length - 1) {
			throw raiseIllegalSignatureException(string, start);
		}
		char c = string[start];
		if (c != Signature.C_ARRAY) {
			throw raiseUnexpectedCharacterException(string, start, c);
		}

		int index = start;
		c = string[++index];
		while(c == Signature.C_ARRAY) {
			// need a minimum 2 char
			if (index >= length - 1) {
				throw raiseIllegalSignatureException(string, start);
			}
			c = string[++index];
		}

		int e = appendTypeSignatureForAnchor(string, index, buffer, false);

		for(int i = 1, dims = index - start; i < dims; i++) {
			buffer.append('[').append(']');
		}

		if (isVarArgs) {
			buffer.append('.').append('.').append('.');
		} else {
			buffer.append('[').append(']');
		}
		return e;
	}
	private static int appendClassTypeSignatureForAnchor(char[] string, int start, StringBuffer buffer) {
		// need a minimum 3 chars "Lx;"
		if (start >= string.length - 2) {
			throw raiseIllegalSignatureException(string, start);
		}
		// must start in "L" or "Q"
		char c = string[start];
		if (c != Signature.C_RESOLVED && c != Signature.C_UNRESOLVED) {
			throw raiseUnexpectedCharacterException(string, start, c);
		}
		int p = start + 1;
		while (true) {
			if (p >= string.length) {
				throw raiseIllegalSignatureException(string, start);
			}
			c = string[p];
			switch(c) {
				case Signature.C_SEMICOLON :
					// all done
					return p;
				case Signature.C_GENERIC_START :
					int e = scanGenericEnd(string, p + 1);
					// once we hit type arguments there are no more package prefixes
					p = e;
					break;
				case Signature.C_DOT :
					buffer.append('.');
					break;
				 case '/' :
					buffer.append('/');
					break;
				 case Signature.C_DOLLAR :
					// once we hit "$" there are no more package prefixes
					/**
					 * Convert '$' in resolved type signatures into '.'.
					 * NOTE: This assumes that the type signature is an inner type
					 * signature. This is true in most cases, but someone can define a
					 * non-inner type name containing a '$'.
					 */
					buffer.append('.');
				 	break;
				 default :
					buffer.append(c);
			}
			p++;
		}
	}

	private static IllegalArgumentException raiseIllegalSignatureException(char[] string, int start) {
		throw new IllegalArgumentException("\"" + new String(string) + "\" starting at " + start); //$NON-NLS-1$ //$NON-NLS-2$
	}

	private static IllegalArgumentException raiseUnexpectedCharacterException(char[] string, int start, char unexpected) {
		throw new IllegalArgumentException("Unexpected '" + unexpected + "' in \"" + new String(string) + "\" starting at " + start); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
	}

	private static int scanGenericEnd(char[] string, int start) {
		if (string[start] == Signature.C_GENERIC_END) {
			return start;
		}
		int length = string.length;
		int balance = 1;
		start++;
		while (start <= length) {
			switch(string[start]) {
				case Signature.C_GENERIC_END :
					balance--;
					if (balance == 0) {
						return start;
					}
					break;
				case Signature.C_GENERIC_START :
					balance++;
					break;
			}
			start++;
		}
		return start;
	}

	/*
	 * This method adjusts the task tags and task priorities so that they have the same size
	 */
	public static void fixTaskTags(Map defaultOptionsMap) {
		Object taskTagsValue = defaultOptionsMap.get(JavaCore.COMPILER_TASK_TAGS);
		char[][] taskTags = null;
		if (taskTagsValue instanceof String) {
			taskTags = CharOperation.splitAndTrimOn(',', ((String) taskTagsValue).toCharArray());
		}
		Object taskPrioritiesValue = defaultOptionsMap.get(JavaCore.COMPILER_TASK_PRIORITIES);
		char[][] taskPriorities = null;
		if (taskPrioritiesValue instanceof String) {
			taskPriorities = CharOperation.splitAndTrimOn(',', ((String) taskPrioritiesValue).toCharArray());
		}
		if (taskPriorities == null) {
			if (taskTags != null) {
				Util.logRepeatedMessage(TASK_PRIORITIES_PROBLEM, IStatus.ERROR, "Inconsistent values for taskTags (not null) and task priorities (null)"); //$NON-NLS-1$
				defaultOptionsMap.remove(JavaCore.COMPILER_TASK_TAGS);
			}
			return;
		} else if (taskTags == null) {
			Util.logRepeatedMessage(TASK_PRIORITIES_PROBLEM, IStatus.ERROR, "Inconsistent values for taskTags (null) and task priorities (not null)"); //$NON-NLS-1$
			defaultOptionsMap.remove(JavaCore.COMPILER_TASK_PRIORITIES);
			return;
		}
		int taskTagsLength = taskTags.length;
		int taskPrioritiesLength = taskPriorities.length;
		if (taskTagsLength != taskPrioritiesLength) {
			Util.logRepeatedMessage(TASK_PRIORITIES_PROBLEM, IStatus.ERROR, "Inconsistent values for taskTags and task priorities : length is different"); //$NON-NLS-1$
			if (taskTagsLength > taskPrioritiesLength) {
				System.arraycopy(taskTags, 0, (taskTags = new char[taskPrioritiesLength][]), 0, taskPrioritiesLength);
				defaultOptionsMap.put(JavaCore.COMPILER_TASK_TAGS, new String(CharOperation.concatWith(taskTags,',')));
			} else {
				System.arraycopy(taskPriorities, 0, (taskPriorities = new char[taskTagsLength][]), 0, taskTagsLength);
				defaultOptionsMap.put(JavaCore.COMPILER_TASK_PRIORITIES, new String(CharOperation.concatWith(taskPriorities,',')));
			}
		}
	}
	/**
	 * Finds the IMethod element corresponding to the given selector, 
	 * without creating a new dummy instance of a binary method. 
	 * @param type the type in which the method is declared
	 * @param selector the method name
	 * @param paramTypeSignatures the type signatures of the method arguments
	 * @param isConstructor whether we're looking for a constructor
	 * @return an IMethod if found, otherwise null
	 * @throws JavaModelException
	 */
	public static IMethod findMethod(IType type, char[] selector, String[] paramTypeSignatures, boolean isConstructor) throws JavaModelException {
		IMethod method = null;
		int startingIndex = 0;
		String[] args;
		IType enclosingType = type.getDeclaringType();
		// If the method is a constructor of a non-static inner type, add the enclosing type as an 
		// additional parameter to the constructor
		if (enclosingType != null
				&& isConstructor
				&& !Flags.isStatic(type.getFlags())) {
			args = new String[paramTypeSignatures.length+1];
			startingIndex = 1;
			args[0] = Signature.createTypeSignature(enclosingType.getFullyQualifiedName(), true);
		} else {
			args = new String[paramTypeSignatures.length];
		}
		int length = args.length;
		for(int i = startingIndex;	i< length ; i++){
			args[i] = new String(paramTypeSignatures[i-startingIndex]);
		}
		method = type.getMethod(new String(selector), args);
		
		IMethod[] methods = type.findMethods(method);
		if (methods != null && methods.length > 0) {
			method = methods[0];
		}
		return method;
	}
}
