//===--- DiagnosticVerifier.cpp - Diagnostic Verifier (-verify) -----------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
//  This file implements the DiagnosticVerifier class.
//
//===----------------------------------------------------------------------===//

#include "swift/Frontend/DiagnosticVerifier.h"
#include "swift/Basic/SourceManager.h"
#include "swift/Parse/Lexer.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"

using namespace swift;

namespace {
  struct ExpectedFixIt {
    const char *StartLoc, *EndLoc;   // The loc of the {{ and }}'s.
    unsigned StartCol;
    unsigned EndCol;
    std::string Text;
  };

  struct ExpectedDiagnosticInfo {
    // This specifies the full range of the "expected-foo {{}}" specifier.
    const char *ExpectedStart, *ExpectedEnd = nullptr;

    llvm::SourceMgr::DiagKind Classification;
    
    // This is true if a '*' constraint is present to say that the diagnostic
    // may appear (or not) an uncounted number of times.
    bool mayAppear = false;
      
    // This is true if a '{{none}}' is present to mark that there should be no
    // extra fixits.
    bool noExtraFixitsMayAppear = false;

    // This is the raw input buffer for the message text, the part in the
    // {{...}}
    StringRef MessageRange;
    
    // This is the message string with escapes expanded.
    std::string MessageStr;
    unsigned LineNo = ~0U;
    Optional<unsigned> ColumnNo;

    std::vector<ExpectedFixIt> Fixits;

    ExpectedDiagnosticInfo(const char *ExpectedStart,
                           llvm::SourceMgr::DiagKind Classification)
      : ExpectedStart(ExpectedStart), Classification(Classification) {
    }
    
  };
} // end anonymous namespace

static std::string getDiagKindString(llvm::SourceMgr::DiagKind Kind) {
  switch (Kind) {
  case llvm::SourceMgr::DK_Error: return "error";
  case llvm::SourceMgr::DK_Warning: return "warning";
  case llvm::SourceMgr::DK_Note: return "note";
  case llvm::SourceMgr::DK_Remark: return "remark";
  }

  llvm_unreachable("Unhandled DiagKind in switch.");
}



namespace {
  /// This class implements support for -verify mode in the compiler.  It
  /// buffers up diagnostics produced during compilation, then checks them
  /// against expected-error markers in the source file.
  class DiagnosticVerifier {
    SourceManager &SM;
    std::vector<llvm::SMDiagnostic> CapturedDiagnostics;
  public:
    explicit DiagnosticVerifier(SourceManager &SM) : SM(SM) {}

    void addDiagnostic(const llvm::SMDiagnostic &Diag) {
      CapturedDiagnostics.push_back(Diag);
    }

    /// verifyFile - After the file has been processed, check to see if we
    /// got all of the expected diagnostics and check to see if there were any
    /// unexpected ones.
    bool verifyFile(unsigned BufferID, bool autoApplyFixes);

    /// diagnostics for '<unknown>:0' should be considered as unexpected.
    bool verifyUnknown();

    /// If there are any -verify errors (e.g. differences between expectations
    /// and actual diagnostics produced), apply fixits to the original source
    /// file and drop it back in place.
    void autoApplyFixes(unsigned BufferID,
                        ArrayRef<llvm::SMDiagnostic> diagnostics);
    
  private:
    std::vector<llvm::SMDiagnostic>::iterator
    findDiagnostic(const ExpectedDiagnosticInfo &Expected,
                   StringRef BufferName);

  };
} // end anonymous namespace




/// If we find the specified diagnostic in the list, return it.
/// Otherwise return CapturedDiagnostics.end().
std::vector<llvm::SMDiagnostic>::iterator
DiagnosticVerifier::findDiagnostic(const ExpectedDiagnosticInfo &Expected,
                                   StringRef BufferName) {
  for (auto I = CapturedDiagnostics.begin(), E = CapturedDiagnostics.end();
       I != E; ++I) {
    // Verify the file and line of the diagnostic.
    if (I->getLineNo() != (int)Expected.LineNo ||
        I->getFilename() != BufferName)
      continue;

    // If a specific column was expected, verify it. Add one to the captured
    // index so expected column numbers correspond to printed output.
    if (Expected.ColumnNo.hasValue() &&
        I->getColumnNo() + 1 != (int)*Expected.ColumnNo)
      continue;

    // Verify the classification and string.
    if (I->getKind() != Expected.Classification ||
        I->getMessage().find(Expected.MessageStr) == StringRef::npos)
      continue;

    // Okay, we found a match, hurray!
    return I;
  }

  return CapturedDiagnostics.end();
}

static unsigned getColumnNumber(StringRef buffer, llvm::SMLoc loc) {
  assert(loc.getPointer() >= buffer.data());
  assert((size_t)(loc.getPointer() - buffer.data()) <= buffer.size());

  StringRef UpToLoc = buffer.slice(0, loc.getPointer() - buffer.data());

  size_t ColumnNo = UpToLoc.size();
  size_t NewlinePos = UpToLoc.find_last_of("\r\n");
  if (NewlinePos != StringRef::npos)
    ColumnNo -= NewlinePos;

  return static_cast<unsigned>(ColumnNo);
}

/// Return true if the given \p ExpectedFixIt is in the fix-its emitted by
/// diagnostic \p D.
static bool checkForFixIt(const ExpectedFixIt &Expected,
                          const llvm::SMDiagnostic &D,
                          StringRef buffer) {
  for (auto &ActualFixIt : D.getFixIts()) {
    if (ActualFixIt.getText() != Expected.Text)
      continue;

    llvm::SMRange Range = ActualFixIt.getRange();
    if (getColumnNumber(buffer, Range.Start) != Expected.StartCol)
      continue;
    if (getColumnNumber(buffer, Range.End) != Expected.EndCol)
      continue;

    return true;
  }

  return false;
}

static std::string renderFixits(ArrayRef<llvm::SMFixIt> fixits,
                                StringRef InputFile) {
  std::string Result;
  llvm::raw_string_ostream OS(Result);
  interleave(fixits,
             [&](const llvm::SMFixIt &ActualFixIt) {
               llvm::SMRange Range = ActualFixIt.getRange();

               OS << "{{" << getColumnNumber(InputFile, Range.Start) << '-'
                  << getColumnNumber(InputFile, Range.End) << '=';

               for (auto C : ActualFixIt.getText()) {
                 if (C == '\n')
                   OS << "\\n";
                 else if (C == '}' || C == '\\')
                   OS << '\\' << C;
                 else
                   OS << C;
               }
               OS << "}}";
             },
             [&] { OS << ' '; });
  return OS.str();
}

/// After the file has been processed, check to see if we got all of
/// the expected diagnostics and check to see if there were any unexpected
/// ones.
bool DiagnosticVerifier::verifyFile(unsigned BufferID,
                                    bool shouldAutoApplyFixes) {
  using llvm::SMLoc;
  
  const SourceLoc BufferStartLoc = SM.getLocForBufferStart(BufferID);
  CharSourceRange EntireRange = SM.getRangeForBuffer(BufferID);
  StringRef InputFile = SM.extractText(EntireRange);
  StringRef BufferName = SM.getIdentifierForBuffer(BufferID);

  // Queue up all of the diagnostics, allowing us to sort them and emit them in
  // file order.
  std::vector<llvm::SMDiagnostic> Errors;

  unsigned PrevExpectedContinuationLine = 0;

  std::vector<ExpectedDiagnosticInfo> ExpectedDiagnostics;
  
  auto addError = [&](const char *Loc, std::string message,
                      ArrayRef<llvm::SMFixIt> FixIts = {}) {
    auto loc = SourceLoc(SMLoc::getFromPointer(Loc));
    auto diag = SM.GetMessage(loc, llvm::SourceMgr::DK_Error, message,
                              {}, FixIts);
    Errors.push_back(diag);
  };
  
  
  // Scan the memory buffer looking for expected-note/warning/error.
  for (size_t Match = InputFile.find("expected-");
       Match != StringRef::npos; Match = InputFile.find("expected-", Match+1)) {
    // Process this potential match.  If we fail to process it, just move on to
    // the next match.
    StringRef MatchStart = InputFile.substr(Match);
    const char *DiagnosticLoc = MatchStart.data();

    llvm::SourceMgr::DiagKind ExpectedClassification;
    if (MatchStart.startswith("expected-note")) {
      ExpectedClassification = llvm::SourceMgr::DK_Note;
      MatchStart = MatchStart.substr(strlen("expected-note"));
    } else if (MatchStart.startswith("expected-warning")) {
      ExpectedClassification = llvm::SourceMgr::DK_Warning;
      MatchStart = MatchStart.substr(strlen("expected-warning"));
    } else if (MatchStart.startswith("expected-error")) {
      ExpectedClassification = llvm::SourceMgr::DK_Error;
      MatchStart = MatchStart.substr(strlen("expected-error"));
    } else if (MatchStart.startswith("expected-remark")) {
      ExpectedClassification = llvm::SourceMgr::DK_Remark;
      MatchStart = MatchStart.substr(strlen("expected-remark"));
    } else
      continue;

    // Skip any whitespace before the {{.
    MatchStart = MatchStart.substr(MatchStart.find_first_not_of(" \t"));

    size_t TextStartIdx = MatchStart.find("{{");
    if (TextStartIdx == StringRef::npos) {
      addError(MatchStart.data(),
               "expected {{ in expected-warning/note/error line");
      continue;
    }

    ExpectedDiagnosticInfo Expected(DiagnosticLoc, ExpectedClassification);
    int LineOffset = 0;

    if (TextStartIdx > 0 && MatchStart[0] == '@') {
      if (MatchStart[1] != '+' && MatchStart[1] != '-' &&
          MatchStart[1] != ':') {
        addError(MatchStart.data(),
                 "expected '+'/'-' for line offset, or ':' for column");
        continue;
      }
      StringRef Offs;
      if (MatchStart[1] == '+')
        Offs = MatchStart.slice(2, TextStartIdx).rtrim();
      else
        Offs = MatchStart.slice(1, TextStartIdx).rtrim();

      size_t SpaceIndex = Offs.find(' ');
      if (SpaceIndex != StringRef::npos && SpaceIndex < TextStartIdx) {
        size_t Delta = Offs.size() - SpaceIndex;
        MatchStart = MatchStart.substr(TextStartIdx - Delta);
        TextStartIdx = Delta;
        Offs = Offs.slice(0, SpaceIndex);
      } else {
        MatchStart = MatchStart.substr(TextStartIdx);
        TextStartIdx = 0;
      }

      size_t ColonIndex = Offs.find(':');
      // Check whether a line offset was provided
      if (ColonIndex != 0) {
        StringRef LineOffs = Offs.slice(0, ColonIndex);
        if (LineOffs.getAsInteger(10, LineOffset)) {
          addError(MatchStart.data(), "expected line offset before '{{'");
          continue;
        }
      }

      // Check whether a column was provided
      if (ColonIndex != StringRef::npos) {
        Offs = Offs.slice(ColonIndex + 1, Offs.size());
        int Column = 0;
        if (Offs.getAsInteger(10, Column)) {
          addError(MatchStart.data(), "expected column before '{{'");
          continue;
        }
        Expected.ColumnNo = Column;
      }
    }

    unsigned Count = 1;
    if (TextStartIdx > 0) {
      StringRef CountStr = MatchStart.substr(0, TextStartIdx).trim();
      if (CountStr == "*") {
        Expected.mayAppear = true;
      } else {
        if (CountStr.getAsInteger(10, Count)) {
          addError(MatchStart.data(), "expected match count before '{{'");
          continue;
        }
        if (Count == 0) {
          addError(MatchStart.data(),
                   "expected positive match count before '{{'");
          continue;
        }
      }

      // Resync up to the '{{'.
      MatchStart = MatchStart.substr(TextStartIdx);
    }

    size_t End = MatchStart.find("}}");
    if (End == StringRef::npos) {
      addError(MatchStart.data(),
          "didn't find '}}' to match '{{' in expected-warning/note/error line");
      continue;
    }

    llvm::SmallString<256> Buf;
    Expected.MessageRange = MatchStart.slice(2, End);
    Expected.MessageStr =
      Lexer::getEncodedStringSegment(Expected.MessageRange, Buf);
    if (PrevExpectedContinuationLine)
      Expected.LineNo = PrevExpectedContinuationLine;
    else
      Expected.LineNo = SM.getLineAndColumn(
          BufferStartLoc.getAdvancedLoc(MatchStart.data() - InputFile.data()),
          BufferID).first;
    Expected.LineNo += LineOffset;

    // Check if the next expected diagnostic should be in the same line.
    StringRef AfterEnd = MatchStart.substr(End + strlen("}}"));
    AfterEnd = AfterEnd.substr(AfterEnd.find_first_not_of(" \t"));
    if (AfterEnd.startswith("\\"))
      PrevExpectedContinuationLine = Expected.LineNo;
    else
      PrevExpectedContinuationLine = 0;

    
    // Scan for fix-its: {{10-14=replacement text}}
    StringRef ExtraChecks = MatchStart.substr(End+2).ltrim(" \t");
    while (ExtraChecks.startswith("{{")) {
      // First make sure we have a closing "}}".
      size_t EndLoc = ExtraChecks.find("}}");
      if (EndLoc == StringRef::npos) {
        addError(ExtraChecks.data(),
                 "didn't find '}}' to match '{{' in fix-it verification");
        break;
      }
      
      // Allow for close braces to appear in the replacement text.
      while (EndLoc+2 < ExtraChecks.size() && ExtraChecks[EndLoc+2] == '}')
        ++EndLoc;
      
      StringRef FixItStr = ExtraChecks.slice(2, EndLoc);
      // Check for matching a later "}}" on a different line.
      if (FixItStr.find_first_of("\r\n") != StringRef::npos) {
        addError(ExtraChecks.data(), "didn't find '}}' to match '{{' in "
                 "fix-it verification");
        break;
      }
      
      // Prepare for the next round of checks.
      ExtraChecks = ExtraChecks.substr(EndLoc+2).ltrim();
      
      // Special case for specifying no fixits should appear.
      if (FixItStr == "none") {
        Expected.noExtraFixitsMayAppear = true;
        continue;
      }
        
      // Parse the pieces of the fix-it.
      size_t MinusLoc = FixItStr.find('-');
      if (MinusLoc == StringRef::npos) {
        addError(FixItStr.data(), "expected '-' in fix-it verification");
        continue;
      }
      StringRef StartColStr = FixItStr.slice(0, MinusLoc);
      StringRef AfterMinus = FixItStr.substr(MinusLoc+1);
      
      size_t EqualLoc = AfterMinus.find('=');
      if (EqualLoc == StringRef::npos) {
        addError(AfterMinus.data(),
                 "expected '=' after '-' in fix-it verification");
        continue;
      }
      StringRef EndColStr = AfterMinus.slice(0, EqualLoc);
      StringRef AfterEqual = AfterMinus.substr(EqualLoc+1);
      
      ExpectedFixIt FixIt;
      FixIt.StartLoc = StartColStr.data()-2;
      FixIt.EndLoc = FixItStr.data()+EndLoc;
      if (StartColStr.getAsInteger(10, FixIt.StartCol)) {
        addError(StartColStr.data(),
                 "invalid column number in fix-it verification");
        continue;
      }
      if (EndColStr.getAsInteger(10, FixIt.EndCol)) {
        addError(EndColStr.data(),
                 "invalid column number in fix-it verification");
        continue;
      }
      
      // Translate literal "\\n" into '\n', inefficiently.
      StringRef fixItText = AfterEqual.slice(0, EndLoc);
      for (const char *current = fixItText.begin(), *end = fixItText.end();
           current != end; /* in loop */) {
        if (*current == '\\' && current + 1 < end) {
          if (current[1] == 'n') {
            FixIt.Text += '\n';
            current += 2;
          } else {  // Handle \}, \\, etc.
            FixIt.Text += current[1];
            current += 2;
          }

        } else {
          FixIt.Text += *current++;
        }
      }
      
      Expected.Fixits.push_back(FixIt);
    }

    Expected.ExpectedEnd = ExtraChecks.data();
    
    // Don't include trailing whitespace in the expected-foo{{}} range.
    while (isspace(Expected.ExpectedEnd[-1]))
      --Expected.ExpectedEnd;

    // Add the diagnostic the expected number of times.
    for (; Count; --Count)
      ExpectedDiagnostics.push_back(Expected);
  }

  
  // Make sure all the expected diagnostics appeared.
  std::reverse(ExpectedDiagnostics.begin(), ExpectedDiagnostics.end());
  
  for (unsigned i = ExpectedDiagnostics.size(); i != 0; ) {
    --i;
    auto &expected = ExpectedDiagnostics[i];
    
    // Check to see if we had this expected diagnostic.
    auto FoundDiagnosticIter = findDiagnostic(expected, BufferName);
    if (FoundDiagnosticIter == CapturedDiagnostics.end()) {
      // Diagnostic didn't exist.  If this is a 'mayAppear' diagnostic, then
      // we're ok.  Otherwise, leave it in the list.
      if (expected.mayAppear)
        ExpectedDiagnostics.erase(ExpectedDiagnostics.begin()+i);
      continue;
    }
    
    auto &FoundDiagnostic = *FoundDiagnosticIter;

    const char *IncorrectFixit = nullptr;
    // Verify that any expected fix-its are present in the diagnostic.
    for (auto fixit : expected.Fixits) {
      // If we found it, we're ok.
      if (!checkForFixIt(fixit, FoundDiagnostic, InputFile))
        IncorrectFixit = fixit.StartLoc;
    }

    bool matchedAllFixIts =
      expected.Fixits.size() == FoundDiagnostic.getFixIts().size();
    
    // If we have any expected fixits that didn't get matched, then they are
    // wrong.  Replace the failed fixit with what actually happened.
    if (IncorrectFixit) {
      if (FoundDiagnostic.getFixIts().empty()) {
        addError(IncorrectFixit, "expected fix-it not seen");
      } else {
        // If we had an incorrect expected fixit, render it and produce a fixit
        // of our own.
        auto actual = renderFixits(FoundDiagnostic.getFixIts(), InputFile);
        auto replStartLoc = SMLoc::getFromPointer(expected.Fixits[0].StartLoc);
        auto replEndLoc = SMLoc::getFromPointer(expected.Fixits.back().EndLoc);
        
        llvm::SMFixIt fix(llvm::SMRange(replStartLoc, replEndLoc), actual);
        addError(IncorrectFixit,
                 "expected fix-it not seen; actual fix-its: " + actual, fix);
      }
    } else if (expected.noExtraFixitsMayAppear &&
               !matchedAllFixIts &&
               !expected.mayAppear) {
      // If there was no fixit specification, but some were produced, add a
      // fixit to add them in.
      auto actual = renderFixits(FoundDiagnostic.getFixIts(), InputFile);
      auto replStartLoc = SMLoc::getFromPointer(expected.ExpectedEnd - 8); // {{none}} length
      auto replEndLoc = SMLoc::getFromPointer(expected.ExpectedEnd - 1);

      llvm::SMFixIt fix(llvm::SMRange(replStartLoc, replEndLoc), actual);
      addError(replStartLoc.getPointer(), "expected no fix-its; actual fix-it seen: " + actual, fix);
    }
    
    // Actually remove the diagnostic from the list, so we don't match it
    // again. We do have to do this after checking fix-its, though, because
    // the diagnostic owns its fix-its.
    CapturedDiagnostics.erase(FoundDiagnosticIter);
    
    // We found the diagnostic, so remove it... unless we allow an arbitrary
    // number of diagnostics, in which case we want to reprocess this.
    if (expected.mayAppear)
      ++i;
    else
      ExpectedDiagnostics.erase(ExpectedDiagnostics.begin()+i);
  }
  
  // Check to see if we have any incorrect diagnostics.  If so, diagnose them as
  // such.
  for (unsigned i = ExpectedDiagnostics.size(); i != 0; ) {
    --i;
    auto &expected = ExpectedDiagnostics[i];

    // Check to see if any found diagnostics have the right line and
    // classification, but the wrong text.
    auto I = CapturedDiagnostics.begin();
    for (auto E = CapturedDiagnostics.end(); I != E; ++I) {
      // Verify the file and line of the diagnostic.
      if (I->getLineNo() != (int)expected.LineNo ||
          I->getFilename() != BufferName ||
          I->getKind() != expected.Classification)
        continue;
      
      // Otherwise, we found it, break out.
      break;
    }

    if (I == CapturedDiagnostics.end()) continue;

    if (I->getMessage().find(expected.MessageStr) == StringRef::npos) {
      auto StartLoc = SMLoc::getFromPointer(expected.MessageRange.begin());
      auto EndLoc = SMLoc::getFromPointer(expected.MessageRange.end());

      llvm::SMFixIt fixIt(llvm::SMRange{StartLoc, EndLoc}, I->getMessage());
      addError(expected.MessageRange.begin(), "incorrect message found", fixIt);
    } else if (I->getColumnNo() + 1 != (int)*expected.ColumnNo) {
      // The difference must be only in the column
      addError(expected.MessageRange.begin(),
               llvm::formatv("message found at column {0} but was expected to "
                             "appear at column {1}",
                             I->getColumnNo() + 1, *expected.ColumnNo));
    } else {
      llvm_unreachable("unhandled difference from expected diagnostic");
    }
    CapturedDiagnostics.erase(I);
    ExpectedDiagnostics.erase(ExpectedDiagnostics.begin()+i);
  }
  
  

  // Diagnose expected diagnostics that didn't appear.
  std::reverse(ExpectedDiagnostics.begin(), ExpectedDiagnostics.end());
  for (auto const &expected : ExpectedDiagnostics) {
    std::string message = "expected "+getDiagKindString(expected.Classification)
      + " not produced";

    // Get the range of the expected-foo{{}} diagnostic specifier.
    auto StartLoc = expected.ExpectedStart;
    auto EndLoc = expected.ExpectedEnd;

    // A very common case if for the specifier to be the last thing on the line.
    // In this case, eat any trailing whitespace.
    while (isspace(*EndLoc) && *EndLoc != '\n' && *EndLoc != '\r')
      ++EndLoc;

    // If we found the end of the line, we can do great things.  Otherwise,
    // avoid nuking whitespace that might be zapped through other means.
    if (*EndLoc != '\n' && *EndLoc != '\r') {
      EndLoc = expected.ExpectedEnd;
    } else {
      // If we hit the end of line, then zap whitespace leading up to it.
      auto FileStart = InputFile.data();
      while (StartLoc-1 != FileStart && isspace(StartLoc[-1]) &&
             StartLoc[-1] != '\n' && StartLoc[-1] != '\r')
        --StartLoc;

      // If we got to the end of the line, and the thing before this diagnostic
      // is a "//" then we can remove it too.
      if (StartLoc-2 >= FileStart && StartLoc[-1] == '/' && StartLoc[-2] == '/')
        StartLoc -= 2;

      // Perform another round of general whitespace nuking to cleanup
      // whitespace before the //.
      while (StartLoc-1 != FileStart && isspace(StartLoc[-1]) &&
             StartLoc[-1] != '\n' && StartLoc[-1] != '\r')
        --StartLoc;

      // If we found a \n, then we can nuke the entire line.
      if (StartLoc-1 != FileStart &&
          (StartLoc[-1] == '\n' || StartLoc[-1] == '\r'))
        --StartLoc;
    }

    // Remove the expected-foo{{}} as a fixit.
    llvm::SMFixIt fixIt(llvm::SMRange{
      SMLoc::getFromPointer(StartLoc),
      SMLoc::getFromPointer(EndLoc)
    }, "");
    addError(expected.ExpectedStart, message, fixIt);
  }
  
  // Verify that there are no diagnostics (in MemoryBuffer) left in the list.
  for (unsigned i = 0, e = CapturedDiagnostics.size(); i != e; ++i) {
    if (CapturedDiagnostics[i].getFilename() != BufferName)
      continue;

    std::string Message =
      "unexpected "+getDiagKindString(CapturedDiagnostics[i].getKind())+
      " produced: "+CapturedDiagnostics[i].getMessage().str();
    addError(CapturedDiagnostics[i].getLoc().getPointer(),
             Message);
  }

  // Sort the diagnostics by their address in the memory buffer as the primary
  // key.  This ensures that an "unexpected diagnostic" and
  // "expected diagnostic" in the same place are emitted next to each other.
  std::sort(Errors.begin(), Errors.end(),
            [&](const llvm::SMDiagnostic &lhs,
                const llvm::SMDiagnostic &rhs) -> bool {
              return lhs.getLoc().getPointer() < rhs.getLoc().getPointer();
            });

  // Emit all of the queue'd up errors.
  for (auto Err : Errors)
    SM.getLLVMSourceMgr().PrintMessage(llvm::errs(), Err);
  
  // If auto-apply fixits is on, rewrite the original source file.
  if (shouldAutoApplyFixes)
    autoApplyFixes(BufferID, Errors);
  
  return !Errors.empty();
}

bool DiagnosticVerifier::verifyUnknown() {
  bool HadError = false;
  for (unsigned i = 0, e = CapturedDiagnostics.size(); i != e; ++i) {
    if (CapturedDiagnostics[i].getFilename() != "<unknown>")
      continue;

    HadError = true;
    std::string Message =
      "unexpected "+getDiagKindString(CapturedDiagnostics[i].getKind())+
      " produced: "+CapturedDiagnostics[i].getMessage().str();

    auto diag = SM.GetMessage({}, llvm::SourceMgr::DK_Error, Message,
                              {}, {});
    SM.getLLVMSourceMgr().PrintMessage(llvm::errs(), diag);
  }
  return HadError;
}

/// If there are any -verify errors (e.g. differences between expectations
/// and actual diagnostics produced), apply fixits to the original source
/// file and drop it back in place.
void DiagnosticVerifier::autoApplyFixes(unsigned BufferID,
                                        ArrayRef<llvm::SMDiagnostic> diags) {
  // Walk the list of diagnostics, pulling out any fixits into an array of just
  // them.
  SmallVector<llvm::SMFixIt, 4> FixIts;
  for (auto &diag : diags)
    FixIts.append(diag.getFixIts().begin(), diag.getFixIts().end());

  // If we have no fixits to apply, avoid touching the file.
  if (FixIts.empty())
    return;
  
  // Sort the fixits by their start location.
  std::sort(FixIts.begin(), FixIts.end(),
            [&](const llvm::SMFixIt &lhs, const llvm::SMFixIt &rhs) -> bool {
              return lhs.getRange().Start.getPointer()
                   < rhs.getRange().Start.getPointer();
            });
  // Coalesce identical fix-its. This happens most often with "expected-error 2"
  // syntax.
  FixIts.erase(std::unique(FixIts.begin(), FixIts.end(),
                           [](const llvm::SMFixIt &lhs,
                              const llvm::SMFixIt &rhs) -> bool {
                 return lhs.getRange().Start == rhs.getRange().Start &&
                        lhs.getRange().End == rhs.getRange().End &&
                        lhs.getText() == rhs.getText();
               }), FixIts.end());
  // Filter out overlapping fix-its. This allows the compiler to apply changes
  // to the easy parts of the file, and leave in the tricky cases for the
  // developer to handle manually.
  FixIts.erase(swift::removeAdjacentIf(FixIts.begin(), FixIts.end(),
                                       [](const llvm::SMFixIt &lhs,
                                          const llvm::SMFixIt &rhs) {
    return lhs.getRange().End.getPointer() > rhs.getRange().Start.getPointer();
  }), FixIts.end());

  // Get the contents of the original source file.
  auto memBuffer = SM.getLLVMSourceMgr().getMemoryBuffer(BufferID);
  auto bufferRange = memBuffer->getBuffer();

  // Apply the fixes, building up a new buffer as an std::string.
  const char *LastPos = bufferRange.begin();
  std::string Result;
  
  for (auto &fix : FixIts) {
    // We cannot handle overlapping fixits, so assert that they don't happen.
    assert(LastPos <= fix.getRange().Start.getPointer() &&
           "Cannot handle overlapping fixits");
    
    // Keep anything from the last spot we've checked to the start of the fixit.
    Result.append(LastPos, fix.getRange().Start.getPointer());
    
    // Replace the content covered by the fixit with the replacement text.
    Result.append(fix.getText().begin(), fix.getText().end());
    
    // Next character to consider is at the end of the fixit.
    LastPos = fix.getRange().End.getPointer();
  }
  
  // Retain the end of the file.
  Result.append(LastPos, bufferRange.end());

  std::error_code error;
  llvm::raw_fd_ostream outs(memBuffer->getBufferIdentifier(), error,
                            llvm::sys::fs::OpenFlags::F_None);
  if (!error)
    outs << Result;
}

//===----------------------------------------------------------------------===//
// Main entrypoints
//===----------------------------------------------------------------------===//

/// Every time a diagnostic is generated in -verify mode, this function is
/// called with the diagnostic.  We just buffer them up until the end of the
/// file.
static void VerifyModeDiagnosticHook(const llvm::SMDiagnostic &Diag,
                                     void *Context) {
  ((DiagnosticVerifier*)Context)->addDiagnostic(Diag);
}


void swift::enableDiagnosticVerifier(SourceManager &SM) {
  SM.getLLVMSourceMgr().setDiagHandler(VerifyModeDiagnosticHook,
                                       new DiagnosticVerifier(SM));
}

bool swift::verifyDiagnostics(SourceManager &SM, ArrayRef<unsigned> BufferIDs,
                              bool autoApplyFixes, bool ignoreUnknown) {
  auto *Verifier = (DiagnosticVerifier*)SM.getLLVMSourceMgr().getDiagContext();
  SM.getLLVMSourceMgr().setDiagHandler(nullptr, nullptr);
  
  bool HadError = false;

  for (auto &BufferID : BufferIDs)
    HadError |= Verifier->verifyFile(BufferID, autoApplyFixes);
  if (!ignoreUnknown)
    HadError |= Verifier->verifyUnknown();

  delete Verifier;

  return HadError;
}

