@SuppressWarnings(
      "null") /* eclipse bug; it falsely thinks stuffAc will always be null or some such hogwash. */
  private static void compareMessages(
      String name,
      LombokImmutableList<CompilerMessageMatcher> expected,
      LinkedHashSet<CompilerMessage> actual) {
    Iterator<CompilerMessageMatcher> expectedIterator = expected.iterator();
    Iterator<CompilerMessage> actualIterator = actual.iterator();

    CompilerMessage stuffAc = null;
    while (true) {
      boolean exHasNext = expectedIterator.hasNext();
      boolean acHasNext = stuffAc != null || actualIterator.hasNext();
      if (!exHasNext && !acHasNext) break;
      if (exHasNext && acHasNext) {
        CompilerMessageMatcher cmm = expectedIterator.next();
        CompilerMessage cm = stuffAc == null ? actualIterator.next() : stuffAc;
        if (cmm.matches(cm)) continue;
        if (cmm.isOptional()) stuffAc = cm;
        fail(String.format("[%s] Expected message '%s' but got message '%s'", name, cmm, cm));
        throw new AssertionError("fail should have aborted already.");
      }

      while (expectedIterator.hasNext()) {
        CompilerMessageMatcher next = expectedIterator.next();
        if (next.isOptional()) continue;
        fail(
            String.format("[%s] Expected message '%s' but ran out of actual messages", name, next));
      }
      if (acHasNext)
        fail(String.format("[%s] Unexpected message: %s", name, actualIterator.next()));
      break;
    }
  }
 private static void dumpToFile(File file, Collection<CompilerMessage> content)
     throws IOException {
   FileOutputStream fos = new FileOutputStream(file);
   try {
     for (CompilerMessage message : content) {
       fos.write(
           CompilerMessageMatcher.asCompilerMessageMatcher(message).toString().getBytes("UTF-8"));
       fos.write('\n');
     }
   } finally {
     fos.close();
   }
 }