X-Git-Url: http://git.phpeclipse.com diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/util/Util.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/util/Util.java index ea8125b..0661b89 100644 --- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/util/Util.java +++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/util/Util.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2003 IBM Corporation and others. + * Copyright (c) 2000, 2004 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at @@ -11,9 +11,13 @@ package net.sourceforge.phpdt.internal.core.util; import java.io.BufferedInputStream; +import java.io.DataInput; +import java.io.EOFException; import java.io.IOException; import java.io.InputStream; +import java.io.OutputStream; import java.io.PrintStream; +import java.io.UTFDataFormatException; import java.util.Locale; import java.util.MissingResourceException; import java.util.ResourceBundle; @@ -22,84 +26,95 @@ import java.util.StringTokenizer; import net.sourceforge.phpdt.core.IJavaElement; import net.sourceforge.phpdt.core.IJavaModelStatusConstants; import net.sourceforge.phpdt.core.IPackageFragment; -import net.sourceforge.phpdt.core.JavaModelException; import net.sourceforge.phpdt.core.JavaCore; +import net.sourceforge.phpdt.core.JavaModelException; import net.sourceforge.phpdt.core.Signature; import net.sourceforge.phpdt.core.compiler.CharOperation; -import net.sourceforge.phpdt.internal.core.PackageFragmentRoot; -import net.sourceforge.phpdt.internal.corext.Assert; -import net.sourceforge.phpdt.internal.ui.util.PHPFileUtil; +import net.sourceforge.phpdt.internal.compiler.ast.TypeReference; +//incastrix +//import net.sourceforge.phpdt.internal.corext.Assert; +import org.eclipse.core.runtime.Assert; +//import net.sourceforge.phpdt.internal.core.PackageFragmentRoot; +import net.sourceforge.phpdt.internal.core.util.PHPFileUtil; import org.eclipse.core.resources.IFile; +//import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; +//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. */ public class Util { - private final static char[] DOUBLE_QUOTES = "''".toCharArray(); //$NON-NLS-1$ - private final static char[] SINGLE_QUOTE = "'".toCharArray(); //$NON-NLS-1$ - private static final String ARGUMENTS_DELIMITER = "#"; //$NON-NLS-1$ - private static final String EMPTY_ARGUMENT = " "; //$NON-NLS-1$ - 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. + * 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. + * 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 interface Displayable { - String displayString(Object o); - } - - public static final String[] fgEmptyStringArray = new String[0]; - /** - * Are we running JDK 1.1? - */ - private static boolean JDK1_1 = false; + private static final String ARGUMENTS_DELIMITER = "#"; //$NON-NLS-1$ /* Bundle containing messages */ protected static ResourceBundle bundle; - private final static String bundleName = "net.sourceforge.phpdt.internal.core.messages"; //$NON-NLS-1$ -// public final static char[] SUFFIX_class = ".class".toCharArray(); //$NON-NLS-1$ -// public final static char[] SUFFIX_CLASS = ".CLASS".toCharArray(); //$NON-NLS-1$ -// public final static char[] SUFFIX_java = ".java".toCharArray(); //$NON-NLS-1$ -// public final static char[] SUFFIX_JAVA = ".JAVA".toCharArray(); //$NON-NLS-1$ -// public final static char[] SUFFIX_jar = ".jar".toCharArray(); //$NON-NLS-1$ -// public final static char[] SUFFIX_JAR = ".JAR".toCharArray(); //$NON-NLS-1$ -// public final static char[] SUFFIX_zip = ".zip".toCharArray(); //$NON-NLS-1$ -// public final static char[] SUFFIX_ZIP = ".ZIP".toCharArray(); //$NON-NLS-1$ + private final static String bundleName = "net.sourceforge.phpdt.internal.core.util.messages"; //$NON-NLS-1$ + + private final static char[] DOUBLE_QUOTES = "''".toCharArray(); //$NON-NLS-1$ + + private static final String EMPTY_ARGUMENT = " "; //$NON-NLS-1$ + + public static final String[] fgEmptyStringArray = new String[0]; + + private final static char[] SINGLE_QUOTE = "'".toCharArray(); //$NON-NLS-1$ static { - String ver = System.getProperty("java.version"); //$NON-NLS-1$ - JDK1_1 = ((ver != null) && ver.startsWith("1.1")); //$NON-NLS-1$ relocalize(); - } - + } + + private Util() { + // cannot be instantiated + } + /** - * Lookup the message with the given ID in this catalog + * Lookup the message with the given ID in this catalog */ public static String bind(String id) { - return bind(id, (String[])null); + return bind(id, (String[]) null); + } + + /** + * Lookup the message with the given ID in this catalog and bind its + * substitution locations with the given string. + */ + public static String bind(String id, String binding) { + return bind(id, new String[] { binding }); } - + + /** + * Lookup the message with the given ID in this catalog and bind its + * substitution locations with the given strings. + */ + public static String bind(String id, String binding1, String binding2) { + return bind(id, new String[] { binding1, binding2 }); + } + /** * Lookup the message with the given ID in this catalog and bind its * substitution locations with the given string values. @@ -111,41 +126,69 @@ public class Util { try { message = bundle.getString(id); } catch (MissingResourceException e) { - // If we got an exception looking for the message, fail gracefully by just returning - // the id we were looking for. In most cases this is semi-informative so is not too bad. + // If we got an exception looking for the message, fail gracefully + // by just returning + // the id we were looking for. In most cases this is + // semi-informative so is not too bad. return "Missing message: " + id + " in: " + bundleName; //$NON-NLS-2$ //$NON-NLS-1$ } - // for compatibility with MessageFormat which eliminates double quotes in original message - char[] messageWithNoDoubleQuotes = - CharOperation.replace(message.toCharArray(), DOUBLE_QUOTES, SINGLE_QUOTE); - message = new String(messageWithNoDoubleQuotes); - + // for compatibility with MessageFormat which eliminates double quotes + // in original message + char[] messageWithNoDoubleQuotes = CharOperation.replace(message + .toCharArray(), DOUBLE_QUOTES, SINGLE_QUOTE); + if (bindings == null) - return message; - - int length = message.length(); - int start = -1; + return new String(messageWithNoDoubleQuotes); + + int length = messageWithNoDoubleQuotes.length; + int start = 0; int end = length; - StringBuffer output = new StringBuffer(80); + StringBuffer output = null; while (true) { - if ((end = message.indexOf('{', start)) > -1) { - output.append(message.substring(start + 1, end)); - if ((start = message.indexOf('}', end)) > -1) { + if ((end = CharOperation.indexOf('{', messageWithNoDoubleQuotes, + start)) > -1) { + if (output == null) + output = new StringBuffer(length + bindings.length * 20); + output.append(messageWithNoDoubleQuotes, start, end - start); + if ((start = CharOperation.indexOf('}', + messageWithNoDoubleQuotes, end + 1)) > -1) { int index = -1; + String argId = new String(messageWithNoDoubleQuotes, + end + 1, start - end - 1); try { - index = Integer.parseInt(message.substring(end + 1, start)); + index = Integer.parseInt(argId); output.append(bindings[index]); - } catch (NumberFormatException nfe) { - output.append(message.substring(end + 1, start + 1)); + } catch (NumberFormatException nfe) { // could be nested + // message ID + // {compiler.name} + boolean done = false; + if (!id.equals(argId)) { + String argMessage = null; + try { + argMessage = bundle.getString(argId); + output.append(argMessage); + done = true; + } catch (MissingResourceException e) { + // unable to bind argument, ignore (will leave + // argument in) + } + } + if (!done) + output.append(messageWithNoDoubleQuotes, end + 1, + start - end); } catch (ArrayIndexOutOfBoundsException e) { - output.append("{missing " + Integer.toString(index) + "}"); //$NON-NLS-2$ //$NON-NLS-1$ + output + .append("{missing " + Integer.toString(index) + "}"); //$NON-NLS-2$ //$NON-NLS-1$ } + start++; } else { - output.append(message.substring(end, length)); + output.append(messageWithNoDoubleQuotes, end, length); break; } } else { - output.append(message.substring(start + 1, length)); + if (output == null) + return new String(messageWithNoDoubleQuotes); + output.append(messageWithNoDoubleQuotes, start, length - start); break; } } @@ -153,76 +196,65 @@ public class Util { } /** - * Lookup the message with the given ID in this catalog and bind its - * substitution locations with the given string. - */ - public static String bind(String id, String binding) { - return bind(id, new String[] {binding}); - } - - /** - * Lookup the message with the given ID in this catalog and bind its - * substitution locations with the given strings. - */ - public static String bind(String id, String binding1, String binding2) { - return bind(id, new String[] {binding1, binding2}); - } - - /** - * 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. + * 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; + 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; + 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: + 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. + * 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) @@ -245,36 +277,39 @@ public class Util { } /** - * Compares two char arrays lexicographically. - * The comparison is based on the Unicode value of each character in - * the char arrays. - * @return the value 0 if a is equal to - * b; a value less than 0 if a - * is lexicographically less than b; and a - * value greater than 0 if a is - * lexicographically greater than b. - */ - public static int compare(char[] v1, char[] v2) { - int len1 = v1.length; - int len2 = v2.length; + * Compares two strings lexicographically. The comparison is based on the + * Unicode value of each character in the strings. + * + * @return the value 0 if the str1 is equal to str2; a value + * less than 0 if str1 is lexicographically less than + * str2; and a value greater than 0 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) { - if (v1[i] != v2[i]) { - return v1[i] - v2[i]; + char c1 = str1[i]; + char c2 = str2[i++]; + if (c1 != c2) { + return c1 - c2; } - ++i; } return len1 - len2; } /** * Concatenate two strings with a char in between. + * * @see #concat(String, String) */ public static String concat(String s1, char c, String s2) { - if (s1 == null) s1 = "null"; //$NON-NLS-1$ - if (s2 == null) s2 = "null"; //$NON-NLS-1$ + if (s1 == null) + s1 = "null"; //$NON-NLS-1$ + if (s2 == null) + s2 = "null"; //$NON-NLS-1$ int l1 = s1.length(); int l2 = s2.length(); char[] buf = new char[l1 + 1 + l2]; @@ -283,20 +318,19 @@ public class Util { s2.getChars(0, l2, buf, l1 + 1); return new String(buf); } - + /** - * Concatenate two strings. - * Much faster than using +, which: - * - creates a StringBuffer, - * - which is synchronized, - * - of default size, so the resulting char array is - * often larger than needed. - * This implementation creates an extra char array, since the - * String constructor copies its argument, but there's no way around this. + * Concatenate two strings. Much faster than using +, which: - creates a + * StringBuffer, - which is synchronized, - of default size, so the + * resulting char array is often larger than needed. This implementation + * creates an extra char array, since the String constructor copies its + * argument, but there's no way around this. */ public static String concat(String s1, String s2) { - if (s1 == null) s1 = "null"; //$NON-NLS-1$ - if (s2 == null) s2 = "null"; //$NON-NLS-1$ + if (s1 == null) + s1 = "null"; //$NON-NLS-1$ + if (s2 == null) + s2 = "null"; //$NON-NLS-1$ int l1 = s1.length(); int l2 = s2.length(); char[] buf = new char[l1 + l2]; @@ -307,12 +341,16 @@ public class Util { /** * Concatenate three strings. + * * @see #concat(String, String) */ public static String concat(String s1, String s2, String s3) { - if (s1 == null) s1 = "null"; //$NON-NLS-1$ - if (s2 == null) s2 = "null"; //$NON-NLS-1$ - if (s3 == null) s3 = "null"; //$NON-NLS-1$ + if (s1 == null) + s1 = "null"; //$NON-NLS-1$ + if (s2 == null) + s2 = "null"; //$NON-NLS-1$ + if (s3 == null) + s3 = "null"; //$NON-NLS-1$ int l1 = s1.length(); int l2 = s2.length(); int l3 = s3.length(); @@ -322,43 +360,70 @@ public class Util { s3.getChars(0, l3, buf, l1 + l2); return new String(buf); } - + /** - * Converts a type signature from the IBinaryType representation to the DC representation. + * Converts a type signature from the IBinaryType representation to the DC + * representation. */ public static String convertTypeSignature(char[] sig) { return new String(sig).replace('/', '.'); } /** + * 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) + 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(Character.toLowerCase(end.charAt(endLength - i)) != Character.toLowerCase(str.charAt(strLength - i))) + for (int i = 1; i <= endLength; i++) { + if (Character.toLowerCase(end.charAt(endLength - i)) != Character + .toLowerCase(str.charAt(strLength - 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 + * 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) { @@ -377,84 +442,90 @@ public class Util { } /** - * 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 + * 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; + if (a == b) + return true; + if (a == null || b == null) + return false; int len = a.length; - if (len != b.length) return false; + if (len != b.length) + return false; for (int i = 0; i < len; ++i) { if (a[i] == null) { - if (b[i] != null) return false; + if (b[i] != null) + return false; } else { - if (!a[i].equals(b[i])) return false; + 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. + * 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(String[] a, String[] b) { - if (a == b) return true; - if (a == null || b == null) return false; + 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 + 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; + 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. + * 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(Comparable[] a, Comparable[] b) { - if (a == b) return true; - if (a == null || b == null) return false; + 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 + 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; + 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. + * 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) { @@ -466,17 +537,18 @@ public class Util { } return a.equals(b); } - + /** - * Given a qualified name, extract the last component. - * If the input is not qualified, the same string is answered. + * 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); + if (i == -1) + return qualifiedName; + return qualifiedName.substring(i + 1); } - + /** * Extracts the parameter types from a method signature. */ @@ -497,17 +569,18 @@ public class Util { break; if (c == '[') { ++i; - } else - if (c == 'L') { - i = CharOperation.indexOf(';', sig, i + 1) + 1; - Assert.isTrue(i != 0); - result[count++] = convertTypeSignature(CharOperation.subarray(sig, start, i)); - start = i; - } else { - ++i; - result[count++] = convertTypeSignature(CharOperation.subarray(sig, start, i)); - start = i; - } + } else if (c == 'L') { + i = CharOperation.indexOf(';', sig, i + 1) + 1; + Assert.isTrue(i != 0); + result[count++] = convertTypeSignature(CharOperation.subarray( + sig, start, i)); + start = i; + } else { + ++i; + result[count++] = convertTypeSignature(CharOperation.subarray( + sig, start, i)); + start = i; + } } return result; } @@ -518,14 +591,33 @@ public class Util { public static String extractReturnType(String sig) { int i = sig.lastIndexOf(')'); Assert.isTrue(i != -1); - return sig.substring(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 +// // (net.sourceforge.phpdt.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 "\n" or "\r" or "\r\n", - * or null if none found + * + * @return "\n" or "\r" or "\r\n", + * or null if none found */ public static String findLineSeparator(char[] text) { // find the first line separator @@ -534,22 +626,135 @@ public class Util { char nextChar = text[0]; for (int i = 0; i < length; i++) { char currentChar = nextChar; - nextChar = i < length-1 ? text[i+1] : ' '; + 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$ + 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; } - - /** - * Returns the line separator used by the given buffer. - * Uses the given text if none found. - * - * @return "\n" or "\r" or "\r\n" + + // 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; + // } + /** + * Get the jdk level of this root. The value can be: + * + * 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) { + // byte[] bytes = Util.getResourceContentsAsByteArray(classFile); + // IPath location = classFile.getLocation(); + // reader = new ClassFileReader(bytes, location == null ? null : + // location.toString().toCharArray()); + // } + // } else { + // // root is a jar file or a zip file + // ZipFile jar = null; + // try { + // IPath path = null; + // if (targetLibrary instanceof IResource) { + // path = ((IResource)targetLibrary).getLocation(); + // } else if (targetLibrary instanceof File){ + // File f = (File) targetLibrary; + // if (!f.isDirectory()) { + // path = new Path(((File)targetLibrary).getPath()); + // } + // } + // if (path != null) { + // jar = JavaModelManager.getJavaModelManager().getZipFile(path); + // for (Enumeration e= jar.entries(); e.hasMoreElements();) { + // ZipEntry member= (ZipEntry) e.nextElement(); + // String entryName= member.getName(); + // if + // (net.sourceforge.phpdt.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(JavaModelException e) { + // // ignore + // } catch(ClassFormatException e) { + // // ignore + // } catch(IOException e) { + // // ignore + // } + // return 0; + // } + /** + * Returns the line separator used by the given buffer. Uses the given text + * if none found. + * + * @return "\n" or "\r" or "\r\n" */ private static String getLineSeparator(char[] text, char[] buffer) { // search in this buffer's contents first @@ -559,12 +764,12 @@ public class Util { lineSeparator = findLineSeparator(text); if (lineSeparator == null) { // default to system line separator - return System.getProperty("line.separator"); + return net.sourceforge.phpdt.internal.compiler.util.Util.LINE_SEPARATOR; } } return lineSeparator; } - + /** * Returns the number of parameter types in a method signature. */ @@ -581,373 +786,640 @@ public class Util { break; if (c == '[') { ++i; - } else - if (c == 'L') { - ++count; - i = CharOperation.indexOf(';', sig, i + 1) + 1; - Assert.isTrue(i != 0); - } else { - ++count; - ++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 { + args.append(arguments[j]); + } + } + + return args.toString(); + } + + /** + * 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; + try { + numberOfArg = Integer.parseInt(argumentsString.substring(0, index)); + } catch (NumberFormatException e) { + return null; + } + argumentsString = argumentsString.substring(index + 1, length); + + String[] args = new String[length]; + int count = 0; + + StringTokenizer tokenizer = new StringTokenizer(argumentsString, + ARGUMENTS_DELIMITER); + while (tokenizer.hasMoreTokens()) { + String argument = tokenizer.nextToken(); + if (argument.equals(EMPTY_ARGUMENT)) + argument = ""; //$NON-NLS-1$ + args[count++] = argument; + } + + if (count != numberOfArg) + return null; + + System.arraycopy(args, 0, args = new String[count], 0, count); + return args; + } + /** * Returns the given file's contents as a byte array. */ - public static byte[] getResourceContentsAsByteArray(IFile file) throws JavaModelException { - InputStream stream= null; + public static byte[] getResourceContentsAsByteArray(IFile file) + throws JavaModelException { + InputStream stream = null; try { stream = new BufferedInputStream(file.getContents(true)); } catch (CoreException e) { throw new JavaModelException(e); } try { - return net.sourceforge.phpdt.internal.compiler.util.Util.getInputStreamAsByteArray(stream, -1); + return net.sourceforge.phpdt.internal.compiler.util.Util + .getInputStreamAsByteArray(stream, -1); } catch (IOException e) { - throw new JavaModelException(e, IJavaModelStatusConstants.IO_EXCEPTION); + 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 { - String encoding = JavaCore.create(file.getProject()).getOption(JavaCore.CORE_ENCODING, true); + public static char[] getResourceContentsAsCharArray(IFile file) + throws JavaModelException { + // Get encoding from file + String encoding = null; + try { + encoding = file.getCharset(); + } catch (CoreException ce) { + // do not use any encoding + } return getResourceContentsAsCharArray(file, encoding); } - public static char[] getResourceContentsAsCharArray(IFile file, String encoding) throws JavaModelException { - InputStream stream= null; + public static char[] getResourceContentsAsCharArray(IFile file, + String encoding) throws JavaModelException { + // Get resource contents + InputStream stream = null; try { stream = new BufferedInputStream(file.getContents(true)); } catch (CoreException e) { - throw new JavaModelException(e, IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST); + throw new JavaModelException(e, + IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST); } try { - return net.sourceforge.phpdt.internal.compiler.util.Util.getInputStreamAsCharArray(stream, -1, encoding); + return net.sourceforge.phpdt.internal.compiler.util.Util + .getInputStreamAsCharArray(stream, -1, encoding); } catch (IOException e) { - throw new JavaModelException(e, IJavaModelStatusConstants.IO_EXCEPTION); + throw new JavaModelException(e, + IJavaModelStatusConstants.IO_EXCEPTION); } finally { try { stream.close(); } catch (IOException e) { + // ignore } } } - + /** * Returns a trimmed version the simples names returned by Signature. */ public static String[] getTrimmedSimpleNames(String name) { String[] result = Signature.getSimpleNames(name); - if (result == null) return null; + if (result == null) + return null; for (int i = 0, length = result.length; i < length; i++) { result[i] = result[i].trim(); } return result; } - - /** - * Returns true iff str.toLowerCase().endsWith(".class") - * implementation is not creating extra strings. + + /* + * Returns the index of the most specific argument paths which is strictly + * enclosing the path to check */ -// public final static boolean isClassFileName(String name) { -// int nameLength = name == null ? 0 : name.length(); -// int suffixLength = SUFFIX_CLASS.length; -// if (nameLength < suffixLength) return false; -// -// for (int i = 0, offset = nameLength - suffixLength; i < suffixLength; i++) { -// char c = name.charAt(offset + i); -// if (c != SUFFIX_class[i] && c != SUFFIX_CLASS[i]) return false; -// } -// return true; -// } - + 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 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 given java element is exluded from its root's classpath. + * 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(); - PackageFragmentRoot root = null; - IResource resource = null; + //PackageFragmentRoot root = null; + //IResource resource = null; switch (elementType) { -// case IJavaElement.PACKAGE_FRAGMENT: -// PackageFragmentRoot root = (PackageFragmentRoot)element.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT); -// IResource resource = element.getResource(); -// return resource != null && Util.isExcluded(resource, root.fullExclusionPatternChars()); - case IJavaElement.COMPILATION_UNIT: - root = (PackageFragmentRoot)element.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT); - resource = element.getResource(); -// if (resource != null && Util.isExcluded(resource, root.fullExclusionPatternChars())) -// return true; - return isExcluded(element.getParent()); - default: - IJavaElement cu = element.getAncestor(IJavaElement.COMPILATION_UNIT); - return cu != null && isExcluded(cu); + 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 = element.getResource(); + // 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 && 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 exclusion - * patterns. + * 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[][] exclusionPatterns) { - if (exclusionPatterns == null) return false; + public final static boolean isExcluded(IPath resourcePath, + char[][] inclusionPatterns, char[][] exclusionPatterns, + boolean isFolderPath) { + if (inclusionPatterns == null && exclusionPatterns == null) + return false; char[] path = resourcePath.toString().toCharArray(); - for (int i = 0, length = exclusionPatterns.length; i < length; i++) - if (CharOperation.pathMatch(exclusionPatterns[i], path, true, '/')) - return true; + + inclusionCheck: if (inclusionPatterns != null) { + for (int i = 0, length = inclusionPatterns.length; i < length; i++) { + char[] pattern = inclusionPatterns[i]; + char[] folderPattern = pattern; + if (isFolderPath) { + int lastSlash = CharOperation.lastIndexOf('/', pattern); + if (lastSlash != -1 && lastSlash != pattern.length - 1) { // trailing + // slash + // -> + // adds + // '**' + // for + // free + // (see + // http://ant.apache.org/manual/dirtasks.html) + int star = CharOperation.indexOf('*', pattern, + lastSlash); + if ((star == -1 || star >= pattern.length - 1 || pattern[star + 1] != '*')) { + folderPattern = CharOperation.subarray(pattern, 0, + lastSlash); + } + } + } + if (CharOperation.pathMatch(folderPattern, path, true, '/')) { + break inclusionCheck; + } + } + return true; // never included + } + if (isFolderPath) { + path = CharOperation.concat(path, new char[] { '*' }, '/'); + } + exclusionCheck: if (exclusionPatterns != null) { + for (int i = 0, length = exclusionPatterns.length; i < length; i++) { + if (CharOperation.pathMatch(exclusionPatterns[i], path, true, + '/')) { + return true; + } + } + } return false; - } - + } + + public final static boolean isExcluded(IResource resource, + char[][] exclusionPatterns) { + IPath path = resource.getFullPath(); + // ensure that folders are only excluded if all of their children are + // excluded + return isExcluded(path, null, exclusionPatterns, + resource.getType() == IResource.FOLDER); + } + /* * 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[][] exclusionPatterns) { + 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 - if (resource.getType() == IResource.FOLDER) - path = path.append("*"); //$NON-NLS-1$ - return isExcluded(path, exclusionPatterns); + // ensure that folders are only excluded if all of their children are + // excluded + return isExcluded(path, inclusionPatterns, exclusionPatterns, resource + .getType() == IResource.FOLDER); } /** - * Returns true iff str.toLowerCase().endsWith(".jar" or ".zip") - * implementation is not creating extra strings. - */ -// public final static boolean isArchiveFileName(String name) { -// int nameLength = name == null ? 0 : name.length(); -// int suffixLength = SUFFIX_JAR.length; -// if (nameLength < suffixLength) return false; -// -// int i, offset; -// for ( i = 0, offset = nameLength - suffixLength; i < suffixLength; i++) { -// char c = name.charAt(offset + i); -// if (c != SUFFIX_jar[i] && c != SUFFIX_JAR[i]) break; -// } -// if (i == suffixLength) return true; -// for ( i = 0, offset = nameLength - suffixLength; i < suffixLength; i++) { -// char c = name.charAt(offset + i); -// if (c != SUFFIX_zip[i] && c != SUFFIX_ZIP[i]) return false; -// } -// return true; -// } - - /** - * Validate the given compilation unit name. - * A compilation unit name must obey the following rules: + * Validate the given .class file name. A .class file name must obey the + * following rules: + * + *

+ * + * @param name + * the name of a .class file + * @return a status object with code IStatus.OK 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) { + // return JavaConventions.validateClassFileName(name).getSeverity() != + // IStatus.ERROR; + // } + /** + * Validate the given compilation unit name. A compilation unit name must + * obey the following rules: * *

- * @param name the name of a compilation unit - * @return a status object with code IStatus.OK if - * the given name is valid as a compilation unit name, otherwise a status - * object indicating what is wrong with the name + * + * @param name + * the name of a compilation unit + * @return a status object with code IStatus.OK 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) { return PHPFileUtil.isPHPFileName(name); -// return JavaConventions.validateCompilationUnitName(name).getSeverity() != IStatus.ERROR; + // return + // JavaConventions.validateCompilationUnitName(name).getSeverity() != + // IStatus.ERROR; } /** - * Validate the given .class file name. - * A .class file name must obey the following rules: - * - *

- * @param name the name of a .class file - * @return a status object with code IStatus.OK if - * the given name is valid as a .class file name, otherwise a status - * object indicating what is wrong with the name + * Returns true if the given folder name is valid for a package, false if it + * is not. */ -// public static boolean isValidClassFileName(String name) { -// return JavaConventions.validateClassFileName(name).getSeverity() != IStatus.ERROR; -// } + public static boolean isValidFolderNameForPackage(String folderName) { + // return JavaConventions.validateIdentifier(folderName).getSeverity() + // != IStatus.ERROR; + return true; + } /** - * Returns true if the given method signature is valid, - * false if it is not. + * 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; + if (len == 0) + return false; int i = 0; char c = sig.charAt(i++); - if (c != '(') return false; - if (i >= len) return false; + 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; + 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. + * 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 true if the given folder name is valid for a package, - * false if it is not. - */ - public static boolean isValidFolderNameForPackage(String folderName) { -// return JavaConventions.validateIdentifier(folderName).getSeverity() != IStatus.ERROR; - return true; - } /* * Add a log entry */ public static void log(Throwable e, String message) { Throwable nestedException; - if (e instanceof JavaModelException - && (nestedException = ((JavaModelException)e).getException()) != null) { + if (e instanceof JavaModelException + && (nestedException = ((JavaModelException) e).getException()) != null) { e = nestedException; } - IStatus status= new Status( - IStatus.ERROR, - JavaCore.getPlugin().getDescriptor().getUniqueIdentifier(), - IStatus.ERROR, - message, - e); + IStatus status = new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, + IStatus.ERROR, message, e); JavaCore.getPlugin().getLog().log(status); - } - + } + /** - * Normalizes the cariage returns in the given text. - * They are all changed to use the given buffer's line separator. + * 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; + 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] : ' '; + nextChar = i < length - 1 ? text[i + 1] : ' '; switch (currentChar) { - case '\n': - int lineLength = i-lineStart; - char[] line = new char[lineLength]; + 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); - 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; - } + if (nextChar == '\n') { + nextChar = ' '; + lineStart = i + 2; } else { // when line separator are mixed in the same file - // we need to prevent NegativeArraySizeException - lineStart = i+1; + // \r might not be followed by a \n. If not, we should + // increment + // lineStart by one and not by two. + lineStart = i + 1; } - break; + } 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; + int lastLineLength = length - lineStart; if (lastLineLength > 0) { lastLine = new char[lastLineLength]; System.arraycopy(text, lineStart, lastLine, 0, lastLineLength); result.append(lastLine); } return result.getContents(); - } else { - return text; } + return text; } /** - * Normalizes the cariage returns in the given text. - * They are all changed to use given buffer's line sepatator. + * Normalizes the cariage returns in the given text. They are all changed to + * use given buffer's line sepatator. */ public static String normalizeCRs(String text, String buffer) { - return new String(normalizeCRs(text.toCharArray(), buffer.toCharArray())); + return new String( + normalizeCRs(text.toCharArray(), buffer.toCharArray())); } /** - * Sort the objects in the given collection using the given sort order. + * Converts the given relative path into a package name. Returns null if the + * path is not a valid package name. + */ + public static String packageName(IPath pkgPath) { + 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)) { + // 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. */ - private static void quickSort(Object[] sortedCollection, int left, int right, int[] sortOrder) { + 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; - int mid = sortOrder[ (left + right) / 2]; + char[] mid = list[(left + right) / 2]; do { - while (sortOrder[left] < mid) { + while (compare(list[left], mid) < 0) { left++; } - while (mid < sortOrder[right]) { + while (compare(mid, list[right]) < 0) { right--; } if (left <= right) { - Object tmp = sortedCollection[left]; + 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) / 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; - int tmp2 = sortOrder[left]; - sortOrder[left] = sortOrder[right]; - sortOrder[right] = tmp2; left++; right--; } } while (left <= right); if (original_left < right) { - quickSort(sortedCollection, original_left, right, sortOrder); + quickSort(sortedCollection, original_left, right); } if (left < original_right) { - quickSort(sortedCollection, left, original_right, sortOrder); + 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) / 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) { + 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) / 2]; + Object mid = sortedCollection[(left + right) / 2]; do { while (comparer.compare(sortedCollection[left], mid) < 0) { left++; @@ -972,61 +1444,46 @@ public class Util { } /** - * Sort the strings in the given collection. + * Sort the objects in the given collection using the given sort order. */ - private static void quickSort(String[] sortedCollection, int left, int right) { + private static void quickSort(Object[] sortedCollection, int left, + int right, int[] sortOrder) { int original_left = left; int original_right = right; - String mid = sortedCollection[ (left + right) / 2]; + int mid = sortOrder[(left + right) / 2]; do { - while (sortedCollection[left].compareTo(mid) < 0) { + while (sortOrder[left] < mid) { left++; } - while (mid.compareTo(sortedCollection[right]) < 0) { + while (mid < sortOrder[right]) { right--; } if (left <= right) { - String tmp = sortedCollection[left]; + Object tmp = sortedCollection[left]; sortedCollection[left] = sortedCollection[right]; sortedCollection[right] = tmp; + int tmp2 = sortOrder[left]; + sortOrder[left] = sortOrder[right]; + sortOrder[right] = tmp2; left++; right--; } } while (left <= right); if (original_left < right) { - quickSort(sortedCollection, original_left, right); + quickSort(sortedCollection, original_left, right, sortOrder); } if (left < original_right) { - quickSort(sortedCollection, left, original_right); - } - } - - /** - * Converts the given relative path into a package name. - * Returns null if the path is not a valid package name. - */ - public static String packageName(IPath pkgPath) { - 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)) { - return null; - } - pkgName.append(segment); - if (j < pkgPath.segmentCount() - 1) { - pkgName.append("." ); //$NON-NLS-1$ - } + quickSort(sortedCollection, left, original_right, sortOrder); } - return pkgName.toString(); } /** - * Sort the comparable objects in the given collection. + * Sort the strings in the given collection. */ - private static void quickSort(Comparable[] sortedCollection, int left, int right) { + private static void quickSort(String[] sortedCollection, int left, int right) { int original_left = left; int original_right = right; - Comparable mid = sortedCollection[ (left + right) / 2]; + String mid = sortedCollection[(left + right) / 2]; do { while (sortedCollection[left].compareTo(mid) < 0) { left++; @@ -1035,7 +1492,7 @@ public class Util { right--; } if (left <= right) { - Comparable tmp = sortedCollection[left]; + String tmp = sortedCollection[left]; sortedCollection[left] = sortedCollection[right]; sortedCollection[right] = tmp; left++; @@ -1053,10 +1510,11 @@ public class Util { /** * Sort the strings in the given collection in reverse alphabetical order. */ - private static void quickSortReverse(String[] sortedCollection, int left, int right) { + private static void quickSortReverse(String[] sortedCollection, int left, + int right) { int original_left = left; int original_right = right; - String mid = sortedCollection[ (left + right) / 2]; + String mid = sortedCollection[(left + right) / 2]; do { while (sortedCollection[left].compareTo(mid) > 0) { left++; @@ -1081,16 +1539,119 @@ public class Util { } /** - * Sorts an array of objects in place, using the sort order given for each item. + * Reads in a string from the specified data input stream. The string has + * been encoded using a modified UTF-8 format. + *

+ * The first two bytes are read as if by readUnsignedShort. + * This value gives the number of following bytes that are in the encoded + * string, not the length of the resulting string. The following bytes are + * then interpreted as bytes encoding characters in the UTF-8 format and are + * converted into characters. + *

+ * This method blocks until all the bytes are read, the end of the stream is + * detected, or an exception is thrown. + * + * @param in + * a data input stream. + * @return a Unicode string. + * @exception EOFException + * if the input stream reaches the end before all the bytes. + * @exception IOException + * if an I/O error occurs. + * @exception UTFDataFormatException + * if the bytes do not represent a valid UTF-8 encoding of a + * Unicode string. + * @see java.io.DataInputStream#readUnsignedShort() + */ + public final static char[] readUTF(DataInput in) throws IOException { + int utflen = in.readUnsignedShort(); + char str[] = new char[utflen]; + int count = 0; + int strlen = 0; + while (count < utflen) { + int c = in.readUnsignedByte(); + int char2, char3; + switch (c >> 4) { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + // 0xxxxxxx + count++; + str[strlen++] = (char) c; + break; + case 12: + case 13: + // 110x xxxx 10xx xxxx + count += 2; + if (count > utflen) + throw new UTFDataFormatException(); + char2 = in.readUnsignedByte(); + if ((char2 & 0xC0) != 0x80) + throw new UTFDataFormatException(); + str[strlen++] = (char) (((c & 0x1F) << 6) | (char2 & 0x3F)); + break; + case 14: + // 1110 xxxx 10xx xxxx 10xx xxxx + count += 3; + if (count > utflen) + throw new UTFDataFormatException(); + char2 = in.readUnsignedByte(); + char3 = in.readUnsignedByte(); + if (((char2 & 0xC0) != 0x80) || ((char3 & 0xC0) != 0x80)) + throw new UTFDataFormatException(); + str[strlen++] = (char) (((c & 0x0F) << 12) + | ((char2 & 0x3F) << 6) | ((char3 & 0x3F) << 0)); + break; + default: + // 10xx xxxx, 1111 xxxx + throw new UTFDataFormatException(); + } + } + if (strlen < utflen) { + System.arraycopy(str, 0, str = new char[strlen], 0, strlen); + } + return str; + } + + /** + * Creates a NLS catalog for the given locale. */ - public static void sort(Object[] objects, int[] sortOrder) { + public static void relocalize() { + try { + bundle = ResourceBundle.getBundle(bundleName, Locale.getDefault()); + } catch (MissingResourceException e) { + System.out + .println("Missing resource : " + bundleName.replace('.', '/') + ".properties for locale " + Locale.getDefault()); //$NON-NLS-1$//$NON-NLS-2$ + throw e; + } + } + + 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, sortOrder); + 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. + * 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) @@ -1098,6 +1659,15 @@ public class Util { } /** + * Sorts an array of objects in place, using the sort order given for each + * item. + */ + public static void sort(Object[] objects, int[] sortOrder) { + if (objects.length > 1) + quickSort(objects, 0, objects.length - 1, sortOrder); + } + + /** * Sorts an array of strings in place using quicksort. */ public static void sort(String[] strings) { @@ -1106,16 +1676,20 @@ public class Util { } /** - * Sorts an array of Comparable objects in place. + * Sorts an array of Comparable objects, returning a new array with the + * sorted items. The original array is left untouched. */ - public static void sort(Comparable[] objects) { - if (objects.length > 1) - quickSort(objects, 0, objects.length - 1); + 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 Strings, returning a new array - * with the sorted items. The original array is left untouched. + * 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; @@ -1126,8 +1700,8 @@ public class Util { } /** - * Sorts an array of Strings, returning a new array - * with the sorted items. The original array is left untouched. + * 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; @@ -1138,20 +1712,8 @@ public class Util { } /** - * 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 strings in place using quicksort - * in reverse alphabetical order. + * Sorts an array of strings in place using quicksort in reverse + * alphabetical order. */ public static void sortReverseOrder(String[] strings) { if (strings.length > 1) @@ -1205,22 +1767,32 @@ public class Util { } /** + * Converts a char[] to String. + */ + public static String toString(char[] c) { + return new String(c); + } + + /** * 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('.'); + 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 '.'. + * 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); + 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]); @@ -1230,39 +1802,55 @@ public class Util { return sb.toString(); } - /** - * Converts a char[] to String. - */ - public static String toString(char[] c) { - return new String(c); - } - - /** - * Converts an array of Objects into String. - */ - public static String toString(Object[] objects) { - return toString(objects, - new Displayable(){ - public String displayString(Object o) { - if (o == null) return "null"; //$NON-NLS-1$ - return o.toString(); - } - }); - } - - /** - * Converts an array of Objects into String. - */ - public static String toString(Object[] objects, Displayable renderer) { - if (objects == null) return ""; //$NON-NLS-1$ - StringBuffer buffer = new StringBuffer(10); - for (int i = 0; i < objects.length; i++){ - if (i > 0) buffer.append(", "); //$NON-NLS-1$ - buffer.append(renderer.displayString(objects[i])); + /* + * 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 new String[0]; + // } + /* + * Returns the unresolved type signature of the given type reference, e.g. + * "QString;", "[int", "[[Qjava.util.Vector;" + */ + // public static String typeSignature(TypeReference type) { + // char[][] compoundName = type.getTypeName(); + // char[] typeName =CharOperation.concatWith(compoundName, '.'); + // String signature = Signature.createTypeSignature(typeName, false/*don't + // resolve*/); + // int dimensions = type.dimensions(); + // if (dimensions > 0) { + // signature = Signature.createArraySignature(signature, dimensions); + // } + // return signature; + // } + /* + * Returns the unresolved type signature of the given type reference, e.g. + * "QString;", "[int", "[[Qjava.util.Vector;" + */ + public static String typeSignature(TypeReference type) { + char[][] compoundName = type.getTypeName(); + char[] typeName = CharOperation.concatWith(compoundName, '.'); + String signature = Signature + .createTypeSignature(typeName, false/* don't resolve */); + int dimensions = type.dimensions(); + if (dimensions > 0) { + signature = Signature.createArraySignature(signature, dimensions); } - return buffer.toString(); + return signature; } - + /** * Asserts that the given method signature is valid. */ @@ -1276,90 +1864,76 @@ public class Util { 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; + printStream.print(log.substring(start, end == -1 ? log.length() + : end + 1)); + start = end + 1; } while (start != 0); printStream.println(); } + /** - * Creates a NLS catalog for the given locale. - */ - public static void relocalize() { - try { - bundle = ResourceBundle.getBundle(bundleName, Locale.getDefault()); - } catch(MissingResourceException e) { - System.out.println("Missing resource : " + bundleName.replace('.', '/') + ".properties for locale " + Locale.getDefault()); //$NON-NLS-1$//$NON-NLS-2$ - throw e; - } - } - - /** - * 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 { - args.append(arguments[j]); + * Writes a string to the given output stream using UTF-8 encoding in a + * machine-independent manner. + *

+ * First, two bytes are written to the output stream as if by the + * writeShort method giving the number of bytes to follow. + * This value is the number of bytes actually written out, not the length of + * the string. Following the length, each character of the string is output, + * in sequence, using the UTF-8 encoding for the character. + * + * @param str + * a string to be written. + * @return the number of bytes written to the stream. + * @exception IOException + * if an I/O error occurs. + * @since JDK1.0 + */ + public static int writeUTF(OutputStream out, char[] str) throws IOException { + int strlen = str.length; + int utflen = 0; + for (int i = 0; i < strlen; i++) { + int c = str[i]; + if ((c >= 0x0001) && (c <= 0x007F)) { + utflen++; + } else if (c > 0x07FF) { + utflen += 3; + } else { + utflen += 2; } } - - return args.toString(); - } - - /** - * 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; - try{ - numberOfArg = Integer.parseInt(argumentsString.substring(0 , index)); - } catch (NumberFormatException e) { - return null; - } - argumentsString = argumentsString.substring(index + 1, length); - - String[] args = new String[length]; - int count = 0; - - StringTokenizer tokenizer = new StringTokenizer(argumentsString, ARGUMENTS_DELIMITER); - while(tokenizer.hasMoreTokens()) { - String argument = tokenizer.nextToken(); - if(argument.equals(EMPTY_ARGUMENT)) - argument = ""; //$NON-NLS-1$ - args[count++] = argument; + if (utflen > 65535) + throw new UTFDataFormatException(); + out.write((utflen >>> 8) & 0xFF); + out.write((utflen >>> 0) & 0xFF); + if (strlen == utflen) { + for (int i = 0; i < strlen; i++) + out.write(str[i]); + } else { + for (int i = 0; i < strlen; i++) { + int c = str[i]; + if ((c >= 0x0001) && (c <= 0x007F)) { + out.write(c); + } else if (c > 0x07FF) { + out.write(0xE0 | ((c >> 12) & 0x0F)); + out.write(0x80 | ((c >> 6) & 0x3F)); + out.write(0x80 | ((c >> 0) & 0x3F)); + } else { + out.write(0xC0 | ((c >> 6) & 0x1F)); + out.write(0x80 | ((c >> 0) & 0x3F)); + } + } } - - if(count != numberOfArg) - return null; - - System.arraycopy(args, 0, args = new String[count], 0, count); - return args; + return utflen + 2; // the number of bytes written to the stream } - -} +} \ No newline at end of file