}
- public static class Comparators {
+ public static class Comparators {
+ /**
+ * Compare based solely on null-inequality:
+ * -1 if one is not null and two is null,
+ * 1 if one is null and two is not null,
+ * 0 otherwise.
+ */
+ static int compareNull(Object one, Object two) {
+ return (null == one
+ ? (null == two ? 0 : 1)
+ : (null == two ? -1 : 0));
+ }
+
+ /**
+ * Soft comparison of String returns 0 if either is empty
+ * or a substring of the other, and the case-insensitive
+ * ordering otherwise.
+ * @param lhs_s
+ * @param rhs_s
+ * @return
+ */
+ static int compareStringsSoftly(String lhs_s, String rhs_s) {
+ if (LangUtil.isEmpty(lhs_s)
+ || LangUtil.isEmpty(rhs_s)) {
+ return 0;
+ }
+ if ((-1 != lhs_s.indexOf(rhs_s))
+ || (-1 != rhs_s.indexOf(lhs_s))) {
+ return 0;
+ }
+ return String.CASE_INSENSITIVE_ORDER.compare(lhs_s, rhs_s);
+ }
+
/**
- * This is a weak ordering
- * so use only for sorts, not to maintain maps.
- * It returns 0 if one file path is a suffix of the other
+ * This returns 0 if one file path is a suffix of the other
* or a case-insensitive string comparison otherwise.
+ * WARNING: it returns 0 if either file is
+ * ISourceLocation.NO_FILE to permit tests to
+ * not specify file paths.
+ *
+ * Use only for sorts, not to maintain maps.
*/
public static final Comparator WEAK_File = new Comparator() {
public int compare(Object o1, Object o2) {
+ if ((o1 == o2)
+ || (o1 == ISourceLocation.NO_FILE)
+ || (o2 == ISourceLocation.NO_FILE) ) {
+ return 0;
+ }
+ int result = compareNull(o1, o2);
+ if (0 != result) {
+ return result;
+ }
File one = (File) o1;
File two = (File) o2;
- if (null == one) {
- return (null == two ? 0 : 1);
- } else if (null == two) {
- return -1;
- } else if (one == two) {
+ String s1 = one.getPath();
+ String s2 = two.getPath();
+ // check if normalize needed
+ if (s1.endsWith(s2) || s2.endsWith(s1)) {
return 0;
- } else {
- String s1 = FileUtil.weakNormalize(one.getPath());
- String s2 = FileUtil.weakNormalize(two.getPath());
- if (s1.endsWith(s2) || s2.endsWith(s1)) {
- return 0;
- } else {
- return String.CASE_INSENSITIVE_ORDER.compare(s1, s2);
- }
}
- }};
+ s1 = FileUtil.weakNormalize(s1);
+ s2 = FileUtil.weakNormalize(s2);
+ if (s1.endsWith(s2) || s2.endsWith(s1)) {
+ return 0;
+ }
+ return String.CASE_INSENSITIVE_ORDER.compare(s1, s2);
+
+ }
+ };
/**
- * Ordering ignores filename,
- * so use only for sorts, not to maintain maps
+ * Ordering only uses line number.
+ * Use only for sorts, not to maintain maps.
*/
public static final Comparator WEAK_ISourceLocation = new Comparator() {
public int compare(Object o1, Object o2) {
+ if (o1 == o2) {
+ return 0;
+ }
+ int result = compareNull(o1, o2);
+ if (0 != result) {
+ return result;
+ }
ISourceLocation one = (ISourceLocation) o1;
ISourceLocation two = (ISourceLocation) o2;
- if (null == one) {
- return (null == two ? 0 : 1);
- } else if (null == two) {
- return -1;
- } else if (one == two) {
+ int i1 = one.getLine();
+ int i2 = two.getLine();
+ return i1 - i2;
+ }
+ };
+
+ /**
+ * Like WEAK_ISourceLocation, except it also
+ * uses WEAK_FILE on the sourceFile.
+ * Use only for sorts, not to maintain maps.
+ */
+ public static final Comparator MEDIUM_ISourceLocation = new Comparator() {
+ public int compare(Object o1, Object o2) {
+ int result = WEAK_ISourceLocation.compare(o1, o2);
+ if (0 != result) {
+ return result;
+ }
+ ISourceLocation one = (ISourceLocation) o1;
+ ISourceLocation two = (ISourceLocation) o2;
+ result = compareNull(one, two);
+ if (0 != result) { // one but not other is null
+ return result;
+ }
+ if (null == one) { // both null
return 0;
- } else { // XXX start with File to make strong
- int i1 = one.getLine();
- int i2 = two.getLine();
- return i1 - i2;
-// // defer subcomparisons until messages complete
-// if (i1 != i2) {
-// return i1 - i2;
-// } else {
-// i1 = one.getColumn();
-// i2 = two.getColumn();
-// if (i1 != i2) {
-// return i1 - i2;
-// } else {
-// i1 = one.getEndLine();
-// i2 = two.getEndLine();
-// return i1 - i2;
-// }
-// }
}
- }};
-
+ // neither null
+ return WEAK_File.compare(one.getSourceFile(), two.getSourceFile());
+ }
+ };
+
/**
- * Ordering ignores filename and message
+ * Ordering uses kind and weak source location,
+ * and ignores message
* so use only for sorts, not to maintain maps
*/
public static final Comparator WEAK_IMessage = new Comparator() {
public int compare(Object o1, Object o2) {
+ if (o1 == o2) {
+ return 0;
+ }
+ int result = compareNull(o1, o2);
+ if (0 != result) {
+ return result;
+ }
IMessage one = (IMessage) o1;
IMessage two = (IMessage) o2;
- if (null == one) {
- return (null == two ? 0 : 1);
- } else if (null == two) {
- return -1;
- } else if (one == two) {
- return 0;
- } else {
- IMessage.Kind kind1 = one.getKind();
- IMessage.Kind kind2= two.getKind();
- if (kind1 != kind2) {
- return IMessage.Kind.COMPARATOR.compare(kind1, kind2);
- } else {
- ISourceLocation sl1 = one.getISourceLocation();
- ISourceLocation sl2 = two.getISourceLocation();
- return WEAK_ISourceLocation.compare(sl1, sl2);
- }
+ IMessage.Kind kind1 = one.getKind();
+ IMessage.Kind kind2= two.getKind();
+ result = IMessage.Kind.COMPARATOR.compare(kind1, kind2);
+ if (0 != result) {
+ return result;
}
- }};
-
- }
+ ISourceLocation sl1 = one.getISourceLocation();
+ ISourceLocation sl2 = two.getISourceLocation();
+ return WEAK_ISourceLocation.compare(sl1, sl2);
+ }
+ };
+ /**
+ * Ordering uses line and weak filename and message
+ * (message matches if either is a substring of the other,
+ * or if either is empty, i.e., none specified).
+ * so use only for sorts, not to maintain maps
+ */
+ public static final Comparator MEDIUM_IMessage = new Comparator() {
+ public int compare(Object o1, Object o2) {
+ int result = WEAK_IMessage.compare(o1, o2);
+ if (0 != result) {
+ return result;
+ }
+ IMessage rhs_m= (IMessage) o1;
+ IMessage lhs_m = (IMessage) o2;
+ ISourceLocation rhs_sl = rhs_m.getISourceLocation();
+ ISourceLocation lhs_sl = lhs_m.getISourceLocation();
+ result = MEDIUM_ISourceLocation.compare(lhs_sl, rhs_sl);
+ if (0 != result) {
+ return result;
+ }
+ String lhs_s =lhs_m.getMessage();
+ String rhs_s = rhs_m.getMessage();
+ return compareStringsSoftly(lhs_s, rhs_s);
+ }
+ };
+}
public static SourceLocation makeSourceLocation(String input) { // XXX only for testing, not production
return makeSourceLocation(input, (File) null);
}