/**
  * Assert that the number of errors that have been gathered matches the number of errors that are
  * given and that they have the expected error codes. The order in which the errors were gathered
  * is ignored.
  *
  * @param errorCodes the errors that should have been gathered
  * @throws AssertionFailedError with
  */
 private void fail(AnalysisError[] expectedErrors) {
   PrintStringWriter writer = new PrintStringWriter();
   writer.print("Expected ");
   writer.print(expectedErrors.length);
   writer.print(" errors:");
   for (AnalysisError error : expectedErrors) {
     Source source = error.getSource();
     File file = source == null ? null : source.getFile();
     LineInfo lineInfo = lineInfoMap.get(source);
     writer.println();
     if (lineInfo == null) {
       int offset = error.getOffset();
       writer.printf(
           "  %s %s (%d..%d)",
           file == null ? "" : file.getName(),
           error.getErrorCode(),
           offset,
           offset + error.getLength());
     } else {
       LineInfo.Location location = lineInfo.getLocation(error.getOffset());
       writer.printf(
           "  %s %s (%d, %d/%d)",
           source == null ? "" : source.getFile().getName(),
           error.getErrorCode(),
           location.getLineNumber(),
           location.getColumnNumber(),
           error.getLength());
     }
   }
   writer.println();
   writer.print("found ");
   writer.print(errors.size());
   writer.print(" errors:");
   for (AnalysisError error : errors) {
     Source source = error.getSource();
     File file = source == null ? null : source.getFile();
     LineInfo lineInfo = lineInfoMap.get(source);
     writer.println();
     if (lineInfo == null) {
       int offset = error.getOffset();
       writer.printf(
           "  %s %s (%d..%d): %s",
           file == null ? "" : file.getName(),
           error.getErrorCode(),
           offset,
           offset + error.getLength(),
           error.getMessage());
     } else {
       LineInfo.Location location = lineInfo.getLocation(error.getOffset());
       writer.printf(
           "  %s %s (%d, %d/%d): %s",
           source == null ? "" : source.getFile().getName(),
           error.getErrorCode(),
           location.getLineNumber(),
           location.getColumnNumber(),
           error.getLength(),
           error.getMessage());
     }
   }
   Assert.fail(writer.toString());
 }
 /**
  * Return {@code true} if the two errors are equivalent.
  *
  * @param firstError the first error being compared
  * @param secondError the second error being compared
  * @return {@code true} if the two errors are equivalent
  */
 private boolean equals(AnalysisError firstError, AnalysisError secondError) {
   return firstError.getErrorCode() == secondError.getErrorCode()
       && firstError.getOffset() == secondError.getOffset()
       && firstError.getLength() == secondError.getLength()
       && equals(firstError.getSource(), secondError.getSource());
 }