//===--- SwiftEditor.cpp --------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

#include "SwiftASTManager.h"
#include "SwiftEditorDiagConsumer.h"
#include "SwiftLangSupport.h"
#include "SourceKit/Core/Context.h"
#include "SourceKit/Core/NotificationCenter.h"
#include "SourceKit/Support/ImmutableTextBuffer.h"
#include "SourceKit/Support/Logging.h"
#include "SourceKit/Support/Tracing.h"
#include "SourceKit/Support/UIdent.h"

#include "swift/AST/ASTPrinter.h"
#include "swift/AST/ASTVisitor.h"
#include "swift/AST/ASTWalker.h"
#include "swift/AST/DiagnosticsClangImporter.h"
#include "swift/AST/DiagnosticsParse.h"
#include "swift/AST/DiagnosticsFrontend.h"
#include "swift/Basic/SourceManager.h"
#include "swift/Demangling/ManglingUtils.h"
#include "swift/Frontend/Frontend.h"
#include "swift/Frontend/PrintingDiagnosticConsumer.h"
#include "swift/IDE/CodeCompletion.h"
#include "swift/IDE/CommentConversion.h"
#include "swift/IDE/Formatting.h"
#include "swift/IDE/SourceEntityWalker.h"
#include "swift/IDE/SyntaxModel.h"
#include "swift/Subsystems.h"
#include "swift/Syntax/Serialization/SyntaxSerialization.h"
#include "swift/Syntax/SyntaxNodes.h"

#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Mutex.h"

using namespace SourceKit;
using namespace swift;
using namespace ide;

static std::vector<unsigned> getSortedBufferIDs(
    const llvm::DenseMap<unsigned, std::vector<DiagnosticEntryInfo>> &Map) {
  std::vector<unsigned> bufferIDs;
  bufferIDs.reserve(Map.size());
  for (auto I = Map.begin(), E = Map.end(); I != E; ++I) {
    bufferIDs.push_back(I->getFirst());
  }
  llvm::array_pod_sort(bufferIDs.begin(), bufferIDs.end());
  return bufferIDs;
}

void EditorDiagConsumer::getAllDiagnostics(
    SmallVectorImpl<DiagnosticEntryInfo> &Result) {

  Result.append(InvalidLocDiagnostics.begin(), InvalidLocDiagnostics.end());

  // Note: we cannot reuse InputBufIds because there may be diagnostics outside
  // the inputs.  Instead, sort the extant buffers.
  auto bufferIDs = getSortedBufferIDs(BufferDiagnostics);
  for (unsigned bufferID : bufferIDs) {
    const auto &diags = BufferDiagnostics[bufferID];
    Result.append(diags.begin(), diags.end());
  }
}

void EditorDiagConsumer::handleDiagnostic(
    SourceManager &SM, SourceLoc Loc, DiagnosticKind Kind,
    StringRef FormatString, ArrayRef<DiagnosticArgument> FormatArgs,
    const DiagnosticInfo &Info) {

  if (Kind == DiagnosticKind::Error) {
    HadAnyError = true;
  }

  // Filter out benign diagnostics for editing.
  if (Info.ID == diag::lex_editor_placeholder.ID ||
      Info.ID == diag::error_doing_code_completion.ID)
    return;

  bool IsNote = (Kind == DiagnosticKind::Note);

  if (IsNote && !haveLastDiag())
    // Is this possible?
    return;

  if (Kind == DiagnosticKind::Remark) {
    // FIXME: we may want to handle optimization remarks in sourcekitd.
    LOG_WARN_FUNC("unhandled optimization remark");
    return;
  }

  DiagnosticEntryInfo SKInfo;

  // Actually substitute the diagnostic arguments into the diagnostic text.
  llvm::SmallString<256> Text;
  {
    llvm::raw_svector_ostream Out(Text);
    DiagnosticEngine::formatDiagnosticText(Out, FormatString, FormatArgs);
  }
  SKInfo.Description = Text.str();

  Optional<unsigned> BufferIDOpt;
  if (Loc.isValid()) {
    BufferIDOpt =  SM.findBufferContainingLoc(Loc);
  }

  if (BufferIDOpt && !isInputBufferID(*BufferIDOpt)) {
    if (Info.ID == diag::error_from_clang.ID ||
        Info.ID == diag::warning_from_clang.ID ||
        Info.ID == diag::note_from_clang.ID ||
        !IsNote) {
      // Handle it as other diagnostics.
    } else {
      // FIXME: This is a note pointing to a synthesized declaration buffer for
      // a declaration coming from a module.
      // We should include the Decl* in the DiagnosticInfo and have a way for
      // Xcode to handle this "points-at-a-decl-from-module" location.
      //
      // For now instead of ignoring it, pick up the declaration name from the
      // buffer identifier and append it to the diagnostic message.
      auto &LastDiag = getLastDiag();
      SKInfo.Description += " (";
      SKInfo.Description += SM.getIdentifierForBuffer(*BufferIDOpt);
      SKInfo.Description += ")";
      SKInfo.Offset = LastDiag.Offset;
      SKInfo.Line = LastDiag.Line;
      SKInfo.Column = LastDiag.Column;
      SKInfo.Filename = LastDiag.Filename;
      LastDiag.Notes.push_back(std::move(SKInfo));
      return;
    }
  }

  if (BufferIDOpt.hasValue()) {
    unsigned BufferID = *BufferIDOpt;

    SKInfo.Offset = SM.getLocOffsetInBuffer(Loc, BufferID);
    std::tie(SKInfo.Line, SKInfo.Column) = SM.getLineAndColumn(Loc, BufferID);
    SKInfo.Filename = SM.getDisplayNameForLoc(Loc);

    for (auto R : Info.Ranges) {
      if (R.isInvalid() || SM.findBufferContainingLoc(R.getStart()) != BufferID)
        continue;
      unsigned Offset = SM.getLocOffsetInBuffer(R.getStart(), BufferID);
      unsigned Length = R.getByteLength();
      SKInfo.Ranges.push_back({Offset, Length});
    }

    for (auto F : Info.FixIts) {
      if (F.getRange().isInvalid() ||
          SM.findBufferContainingLoc(F.getRange().getStart()) != BufferID)
        continue;
      unsigned Offset =
          SM.getLocOffsetInBuffer(F.getRange().getStart(), BufferID);
      unsigned Length = F.getRange().getByteLength();
      SKInfo.Fixits.push_back({Offset, Length, F.getText()});
    }
  } else {
    SKInfo.Filename = "<unknown>";
  }

  if (IsNote) {
    getLastDiag().Notes.push_back(std::move(SKInfo));
    return;
  }

  switch (Kind) {
    case DiagnosticKind::Error:
      SKInfo.Severity = DiagnosticSeverityKind::Error;
      break;
    case DiagnosticKind::Warning:
      SKInfo.Severity = DiagnosticSeverityKind::Warning;
      break;
    case DiagnosticKind::Note:
    case DiagnosticKind::Remark:
      llvm_unreachable("already covered");
  }

  if (!BufferIDOpt) {
    InvalidLocDiagnostics.push_back(std::move(SKInfo));
    clearLastDiag();
    return;
  }

  unsigned BufferID = *BufferIDOpt;
  DiagnosticsTy &Diagnostics = BufferDiagnostics[BufferID];

  if (Diagnostics.empty() || Diagnostics.back().Offset <= SKInfo.Offset) {
    Diagnostics.push_back(std::move(SKInfo));
    LastDiagBufferID = BufferID;
    LastDiagIndex = Diagnostics.size() - 1;
    return;
  }

  // Keep the diagnostics array in source order.
  auto Pos = std::lower_bound(Diagnostics.begin(), Diagnostics.end(), SKInfo.Offset,
    [&](const DiagnosticEntryInfo &LHS, unsigned Offset) -> bool {
      return LHS.Offset < Offset;
    });
  LastDiagBufferID = BufferID;
  LastDiagIndex = Pos - Diagnostics.begin();
  Diagnostics.insert(Pos, std::move(SKInfo));
}

SwiftEditorDocumentRef
SwiftEditorDocumentFileMap::getByUnresolvedName(StringRef FilePath) {
  SwiftEditorDocumentRef EditorDoc;

  Queue.dispatchSync([&]{
    auto It = Docs.find(FilePath);
    if (It != Docs.end())
      EditorDoc = It->second.DocRef;
   });

  return EditorDoc;
}

SwiftEditorDocumentRef
SwiftEditorDocumentFileMap::findByPath(StringRef FilePath) {
  SwiftEditorDocumentRef EditorDoc;

  std::string ResolvedPath = SwiftLangSupport::resolvePathSymlinks(FilePath);
  Queue.dispatchSync([&]{
    for (auto &Entry : Docs) {
      if (Entry.getKey() == FilePath ||
          Entry.getValue().ResolvedPath == ResolvedPath) {
        EditorDoc = Entry.getValue().DocRef;
        break;
      }
    }
  });

  return EditorDoc;
}

bool SwiftEditorDocumentFileMap::getOrUpdate(
    StringRef FilePath, SwiftLangSupport &LangSupport,
    SwiftEditorDocumentRef &EditorDoc) {

  bool found = false;

  std::string ResolvedPath = SwiftLangSupport::resolvePathSymlinks(FilePath);
  Queue.dispatchBarrierSync([&]{
    DocInfo &Doc = Docs[FilePath];
    if (!Doc.DocRef) {
      Doc.DocRef = EditorDoc;
      Doc.ResolvedPath = ResolvedPath;
    } else {
      EditorDoc = Doc.DocRef;
      found = true;
    }
  });

  return found;
}

SwiftEditorDocumentRef SwiftEditorDocumentFileMap::remove(StringRef FilePath) {
  SwiftEditorDocumentRef Removed;
  Queue.dispatchBarrierSync([&]{
    auto I = Docs.find(FilePath);
    if (I != Docs.end()) {
      Removed = I->second.DocRef;
      Docs.erase(I);
    }
  });
  return Removed;
}

namespace {

/// Merges two overlapping ranges and splits the first range into two
/// ranges before and after the overlapping range.
void mergeSplitRanges(unsigned Off1, unsigned Len1, unsigned Off2, unsigned Len2,
                      std::function<void(unsigned BeforeOff, unsigned BeforeLen,
                                         unsigned AfterOff,
                                         unsigned AfterLen)> applier) {
  unsigned End1 = Off1 + Len1;
  unsigned End2 = Off2 + Len2;
  if (End1 > Off2) {
    // Overlapping. Split into before and after ranges.
    unsigned BeforeOff = Off1;
    unsigned BeforeLen = Off2 > Off1 ? Off2 - Off1 : 0;
    unsigned AfterOff = End2;
    unsigned AfterLen = End1 > End2 ? End1 - End2 : 0;
    applier(BeforeOff, BeforeLen, AfterOff, AfterLen);
  }
  else {
    // Not overlapping.
    applier(Off1, Len1, 0, 0);
  }
}

struct SwiftSyntaxToken {
  unsigned Offset;
  unsigned Length:24;
  SyntaxNodeKind Kind:8;

  static SwiftSyntaxToken createInvalid() {
    return {0, 0, SyntaxNodeKind::AttributeBuiltin};
  }

  SwiftSyntaxToken(unsigned Offset, unsigned Length, SyntaxNodeKind Kind)
    : Offset(Offset), Length(Length), Kind(Kind) {}

  unsigned endOffset() const { return Offset + Length; }

  bool isInvalid() const { return Length == 0; }

  bool operator==(const SwiftSyntaxToken &Other) const {
    return Offset == Other.Offset && Length == Other.Length &&
      Kind == Other.Kind;
  }

  bool operator!=(const SwiftSyntaxToken &Other) const {
    return Offset != Other.Offset || Length != Other.Length ||
      Kind != Other.Kind;
  }
};

struct SwiftEditorCharRange {
  unsigned Offset;
  unsigned EndOffset;

  SwiftEditorCharRange(unsigned Offset, unsigned EndOffset) :
    Offset(Offset), EndOffset(EndOffset) {}

  SwiftEditorCharRange(SwiftSyntaxToken Token) :
    Offset(Token.Offset), EndOffset(Token.endOffset()) {}

  size_t length() const { return EndOffset - Offset; }
  bool isEmpty() const { return Offset == EndOffset; }
  bool intersects(const SwiftSyntaxToken &Token) const {
    return this->Offset < (Token.endOffset()) && this->EndOffset > Token.Offset;
  }
  void extendToInclude(const SwiftEditorCharRange &Range) {
    if (Range.Offset < Offset)
      Offset = Range.Offset;
    if (Range.EndOffset > EndOffset)
      EndOffset = Range.EndOffset;
  }
  void extendToInclude(unsigned OtherOffset) {
    extendToInclude({OtherOffset, OtherOffset});
  }
};

/// Finds and represents the first mismatching tokens in two syntax maps,
/// ignoring invalidated tokens.
template <class Iter>
struct TokenMismatch {
  /// The begin and end iterators of the previous syntax map
  Iter PrevTok, PrevEnd;
  /// The begin and end iterators of the current syntax map
  Iter CurrTok, CurrEnd;

  TokenMismatch(Iter CurrTok, Iter CurrEnd, Iter PrevTok, Iter PrevEnd) :
  PrevTok(PrevTok), PrevEnd(PrevEnd), CurrTok(CurrTok), CurrEnd(CurrEnd) {
    skipInvalid();
    while(advance());
  }

  /// Returns true if a mismatch was found
  bool foundMismatch() const {
    return CurrTok != CurrEnd || PrevTok != PrevEnd;
  }

  /// Returns the smallest start offset of the mismatched token ranges
  unsigned mismatchStart() const {
    assert(foundMismatch());
    if (CurrTok != CurrEnd) {
      if (PrevTok != PrevEnd)
        return std::min(CurrTok->Offset, PrevTok->Offset);
      return CurrTok->Offset;
    }
    return PrevTok->Offset;
  }

  /// Returns the largest end offset of the mismatched token ranges
  unsigned mismatchEnd() const {
    assert(foundMismatch());
    if (CurrTok != CurrEnd) {
      if (PrevTok != PrevEnd)
        return std::max(CurrTok->endOffset(), PrevTok->endOffset());
      return CurrTok->endOffset();
    }
    return PrevTok->endOffset();
  }

private:
  void skipInvalid() {
    while (PrevTok != PrevEnd && PrevTok->isInvalid())
      ++PrevTok;
  }

  bool advance() {
    if (CurrTok == CurrEnd || PrevTok == PrevEnd || *CurrTok != *PrevTok)
      return false;
    ++CurrTok;
    ++PrevTok;
    skipInvalid();
    return true;
  }
};

/// Represents a the syntax highlighted token ranges in a source file
struct SwiftSyntaxMap {
  std::vector<SwiftSyntaxToken> Tokens;

  explicit SwiftSyntaxMap(unsigned Capacity = 0) {
    if (Capacity)
      Tokens.reserve(Capacity);
  }

  void addToken(const SwiftSyntaxToken &Token) {
    assert(Tokens.empty() || Token.Offset >= Tokens.back().Offset);
    Tokens.push_back(Token);
  }

  /// Merge this nested token into the last token that was added
  void mergeToken(const SwiftSyntaxToken &Token) {
    if (Tokens.empty()) {
      Tokens.push_back(Token);
      return;
    }
    auto &LastTok = Tokens.back();
    assert(LastTok.Offset <= Token.Offset);
    mergeSplitRanges(LastTok.Offset, LastTok.Length, Token.Offset, Token.Length,
                     [&](unsigned BeforeOff, unsigned BeforeLen,
                         unsigned AfterOff, unsigned AfterLen) {
                       auto LastKind = LastTok.Kind;
                       Tokens.pop_back();
                       if (BeforeLen)
                         Tokens.emplace_back(BeforeOff, BeforeLen, LastKind);
                       Tokens.push_back(Token);
                       if (AfterLen)
                         Tokens.emplace_back(AfterOff, AfterLen, LastKind);
                     });
  }

  /// Adjusts the token offsets and lengths in this syntax map to account for
  /// replacing \p Len bytes at the given \p Offset with \p NewLen bytes. Tokens
  /// before the replacement stay the same, tokens after it are shifted, and
  /// tokens that intersect it are 'removed' (really just marked invalid).
  /// Clients are expected to match this behavior.
  ///
  /// Returns the union of the replaced range and the token ranges it
  /// intersected, or nothing if no tokens were intersected.
  llvm::Optional<SwiftEditorCharRange>
  adjustForReplacement(unsigned Offset, unsigned Len, unsigned NewLen) {
    unsigned ReplacedStart = Offset;
    unsigned ReplacedEnd = Offset + Len;
    bool TokenIntersected = false;
    SwiftEditorCharRange Affected = { /*Offset=*/ReplacedStart,
                                      /*EndOffset=*/ReplacedEnd};
    // Adjust the tokens
    auto Token = Tokens.begin();
    while (Token != Tokens.end() && Token->endOffset() <= ReplacedStart) {
      // Completely before the replaced range – no change needed
      ++Token;
    }

    while (Token != Tokens.end() && Token->Offset < ReplacedEnd) {
      // Intersecting the replaced range – extend Affected and invalidate
      TokenIntersected = true;
      Affected.extendToInclude(*Token);
      *Token = SwiftSyntaxToken::createInvalid();
      ++Token;
    }

    while (Token != Tokens.end()) {
      // Completely after the replaced range - shift to account for NewLen
      if (NewLen >= Len)
        Token->Offset += NewLen - Len;
      else
        Token->Offset -= Len - NewLen;
      ++Token;
    }

    // If the replaced range didn't intersect with any existing tokens, there's
    // no need to report an affected range
    if (!TokenIntersected)
      return None;

    // Update the end of the affected range to account for NewLen
    if (NewLen >= Len) {
      Affected.EndOffset += NewLen - Len;
    } else {
      Affected.EndOffset -= Len - NewLen;
    }

    return Affected;
  }

  /// Passes each token in this SwiftSyntaxMap to the given \p Consumer
  void forEach(EditorConsumer &Consumer) {
    for (auto &Token: Tokens) {
      auto Kind = SwiftLangSupport::getUIDForSyntaxNodeKind(Token.Kind);
      Consumer.handleSyntaxMap(Token.Offset, Token.Length, Kind);
    }
  }

  /// Finds the delta between the given SwiftSyntaxMap, \p Prev, and this one.
  /// It passes each token not in \p Prev to the given \p Consumer and, if
  /// needed, also expands or sets the given \p Affected range to cover all
  /// non-matching tokens in the two lists.
  ///
  /// Returns true if this SwiftSyntaxMap is different to \p Prev.
  bool forEachChanged(const SwiftSyntaxMap &Prev,
                      llvm::Optional<SwiftEditorCharRange> &Affected,
                      EditorConsumer &Consumer) const {
    typedef std::vector<SwiftSyntaxToken>::const_iterator ForwardIt;
    typedef std::vector<SwiftSyntaxToken>::const_reverse_iterator ReverseIt;

    // Find the first pair of tokens that don't match
    TokenMismatch<ForwardIt>
    Forward(Tokens.begin(), Tokens.end(), Prev.Tokens.begin(), Prev.Tokens.end());

    // Exit early if there was no mismatch
    if (!Forward.foundMismatch())
      return Affected && !Affected->isEmpty();

    // Find the last pair of tokens that don't match
    TokenMismatch<ReverseIt>
    Backward(Tokens.rbegin(), Tokens.rend(), Prev.Tokens.rbegin(), Prev.Tokens.rend());
    assert(Backward.foundMismatch());

    // Set or extend the affected range to include the  mismatched range
    SwiftEditorCharRange
    MismatchRange = {Forward.mismatchStart(),Backward.mismatchEnd()};
    if (!Affected) {
      Affected = MismatchRange;
    } else {
      Affected->extendToInclude(MismatchRange);
    }

    // Report all tokens in the affected range to the EditorConsumer
    auto From = Forward.CurrTok;
    auto To = Backward.CurrTok;
    while (From != Tokens.begin() && (From-1)->Offset >= Affected->Offset)
      --From;
    while (To != Tokens.rbegin() && (To-1)->endOffset() <= Affected->EndOffset)
      --To;
    for (; From < To.base(); ++From) {
      auto Kind = SwiftLangSupport::getUIDForSyntaxNodeKind(From->Kind);
      Consumer.handleSyntaxMap(From->Offset, From->Length, Kind);
    }

    return true;
  }
};

struct EditorConsumerSyntaxMapEntry {
  unsigned Offset;
  unsigned Length;
  UIdent Kind;
  EditorConsumerSyntaxMapEntry(unsigned Offset, unsigned Length, UIdent Kind)
    :Offset(Offset), Length(Length), Kind(Kind) { }
};

struct SwiftSemanticToken {
  unsigned ByteOffset;
  unsigned Length : 24;
  // The code-completion kinds are a good match for the semantic kinds we want.
  // FIXME: Maybe rename CodeCompletionDeclKind to a more general concept ?
  CodeCompletionDeclKind Kind : 6;
  unsigned IsRef : 1;
  unsigned IsSystem : 1;

  SwiftSemanticToken(CodeCompletionDeclKind Kind,
                     unsigned ByteOffset, unsigned Length,
                     bool IsRef, bool IsSystem)
    : ByteOffset(ByteOffset), Length(Length), Kind(Kind),
      IsRef(IsRef), IsSystem(IsSystem) { }

  bool getIsRef() const { return static_cast<bool>(IsRef); }

  bool getIsSystem() const { return static_cast<bool>(IsSystem); }

  UIdent getUIdentForKind() const {
    return SwiftLangSupport::getUIDForCodeCompletionDeclKind(Kind, getIsRef());
  }
};
static_assert(sizeof(SwiftSemanticToken) == 8, "Too big");

class SwiftDocumentSemanticInfo :
    public ThreadSafeRefCountedBase<SwiftDocumentSemanticInfo> {

  const std::string Filename;
  std::weak_ptr<SwiftASTManager> ASTMgr;
  std::shared_ptr<NotificationCenter> NotificationCtr;
  ThreadSafeRefCntPtr<SwiftInvocation> InvokRef;
  std::string CompilerArgsError;

  uint64_t ASTGeneration = 0;
  ImmutableTextSnapshotRef TokSnapshot;
  std::vector<SwiftSemanticToken> SemaToks;

  ImmutableTextSnapshotRef DiagSnapshot;
  std::vector<DiagnosticEntryInfo> SemaDiags;

  mutable llvm::sys::Mutex Mtx;

public:
  SwiftDocumentSemanticInfo(StringRef Filename,
                            std::weak_ptr<SwiftASTManager> ASTMgr,
                            std::shared_ptr<NotificationCenter> NotificationCtr)
      : Filename(Filename), ASTMgr(ASTMgr), NotificationCtr(NotificationCtr) {}

  SwiftInvocationRef getInvocation() const {
    return InvokRef;
  }

  uint64_t getASTGeneration() const;

  void setCompilerArgs(ArrayRef<const char *> Args) {
    if (auto ASTMgr = this->ASTMgr.lock()) {
      InvokRef = ASTMgr->getInvocation(Args, Filename, CompilerArgsError);
    }
  }

  void readSemanticInfo(ImmutableTextSnapshotRef NewSnapshot,
                        std::vector<SwiftSemanticToken> &Tokens,
                        Optional<std::vector<DiagnosticEntryInfo>> &Diags,
                        ArrayRef<DiagnosticEntryInfo> ParserDiags);

  void processLatestSnapshotAsync(EditableTextBufferRef EditableBuffer);

  void updateSemanticInfo(std::vector<SwiftSemanticToken> Toks,
                          std::vector<DiagnosticEntryInfo> Diags,
                          ImmutableTextSnapshotRef Snapshot,
                          uint64_t ASTGeneration);
  void removeCachedAST() {
    if (InvokRef) {
      if (auto ASTMgr = this->ASTMgr.lock()) {
        ASTMgr->removeCachedAST(InvokRef);
      }
    }
  }

private:
  std::vector<SwiftSemanticToken> takeSemanticTokens(
      ImmutableTextSnapshotRef NewSnapshot);

  Optional<std::vector<DiagnosticEntryInfo>> getSemanticDiagnostics(
      ImmutableTextSnapshotRef NewSnapshot,
      ArrayRef<DiagnosticEntryInfo> ParserDiags);
};

class SwiftDocumentSyntaxInfo {
  SourceManager SM;
  EditorDiagConsumer DiagConsumer;
  std::unique_ptr<ParserUnit> Parser;
  unsigned BufferID;
  std::vector<std::string> Args;
  std::string PrimaryFile;
  /// Whether or not the AST stored in the source file is up-to-date or just an
  /// artifact of incremental syntax parsing
  bool HasUpToDateAST;

public:
  SwiftDocumentSyntaxInfo(const CompilerInvocation &CompInv,
                          ImmutableTextSnapshotRef Snapshot,
                          std::vector<std::string> &Args,
                          StringRef FilePath)
        : Args(Args), PrimaryFile(FilePath) {

    std::unique_ptr<llvm::MemoryBuffer> BufCopy =
      llvm::MemoryBuffer::getMemBufferCopy(
        Snapshot->getBuffer()->getText(), FilePath);

    BufferID = SM.addNewSourceBuffer(std::move(BufCopy));
    DiagConsumer.setInputBufferIDs(BufferID);

    Parser.reset(
                 new ParserUnit(SM, SourceFileKind::Main, BufferID,
                     CompInv.getLangOptions(),
                     CompInv.getModuleName(),
                     CompInv.getMainFileSyntaxParsingCache())
    );

    Parser->getDiagnosticEngine().addConsumer(DiagConsumer);

    // Collecting syntactic information shouldn't evaluate # conditions.
    Parser->getParser().State->PerformConditionEvaluation = false;

    // If there is a syntax parsing cache, incremental syntax parsing is
    // performed and thus the generated AST may not be up-to-date.
    HasUpToDateAST = CompInv.getMainFileSyntaxParsingCache() == nullptr;
  }

  void parse() {
    Parser->parse();
  }

  SourceFile &getSourceFile() {
    return Parser->getSourceFile();
  }

  unsigned getBufferID() {
    return BufferID;
  }

  const LangOptions &getLangOptions() {
    return Parser->getLangOptions();
  }

  SourceManager &getSourceManager() {
    return SM;
  }

  bool hasUpToDateAST() { return HasUpToDateAST; }

  ArrayRef<DiagnosticEntryInfo> getDiagnostics() {
    return DiagConsumer.getDiagnosticsForBuffer(BufferID);
  }
};

} // anonymous namespace

uint64_t SwiftDocumentSemanticInfo::getASTGeneration() const {
  llvm::sys::ScopedLock L(Mtx);
  return ASTGeneration;
}

void SwiftDocumentSemanticInfo::readSemanticInfo(
    ImmutableTextSnapshotRef NewSnapshot,
    std::vector<SwiftSemanticToken> &Tokens,
    Optional<std::vector<DiagnosticEntryInfo>> &Diags,
    ArrayRef<DiagnosticEntryInfo> ParserDiags) {

  llvm::sys::ScopedLock L(Mtx);

  Tokens = takeSemanticTokens(NewSnapshot);
  Diags = getSemanticDiagnostics(NewSnapshot, ParserDiags);
}

std::vector<SwiftSemanticToken>
SwiftDocumentSemanticInfo::takeSemanticTokens(
    ImmutableTextSnapshotRef NewSnapshot) {

  llvm::sys::ScopedLock L(Mtx);

  if (SemaToks.empty())
    return {};

  // Adjust the position of the tokens.
  TokSnapshot->foreachReplaceUntil(NewSnapshot,
    [&](ReplaceImmutableTextUpdateRef Upd) -> bool {
      if (SemaToks.empty())
        return false;

      auto ReplaceBegin = std::lower_bound(SemaToks.begin(), SemaToks.end(),
          Upd->getByteOffset(),
          [&](const SwiftSemanticToken &Tok, unsigned StartOffset) -> bool {
            return Tok.ByteOffset+Tok.Length < StartOffset;
          });

      std::vector<SwiftSemanticToken>::iterator ReplaceEnd;
      if (Upd->getLength() == 0) {
        ReplaceEnd = ReplaceBegin;
      } else {
        ReplaceEnd = std::upper_bound(ReplaceBegin, SemaToks.end(),
            Upd->getByteOffset() + Upd->getLength(),
            [&](unsigned EndOffset, const SwiftSemanticToken &Tok) -> bool {
              return EndOffset < Tok.ByteOffset;
            });
      }

      unsigned InsertLen = Upd->getText().size();
      int Delta = InsertLen - Upd->getLength();
      if (Delta != 0) {
        for (std::vector<SwiftSemanticToken>::iterator
               I = ReplaceEnd, E = SemaToks.end(); I != E; ++I)
          I->ByteOffset += Delta;
      }
      SemaToks.erase(ReplaceBegin, ReplaceEnd);
      return true;
    });

  return std::move(SemaToks);
}

Optional<std::vector<DiagnosticEntryInfo>>
SwiftDocumentSemanticInfo::getSemanticDiagnostics(
    ImmutableTextSnapshotRef NewSnapshot,
    ArrayRef<DiagnosticEntryInfo> ParserDiags) {

  std::vector<DiagnosticEntryInfo> curSemaDiags;
  {
    llvm::sys::ScopedLock L(Mtx);

    if (!DiagSnapshot || DiagSnapshot->getStamp() != NewSnapshot->getStamp()) {
      // The semantic diagnostics are out-of-date, ignore them.
      return llvm::None;
    }

    curSemaDiags = SemaDiags;
  }

  // Diagnostics from the AST and diagnostics from the parser are based on the
  // same source text snapshot. But diagnostics from the AST may have excluded
  // the parser diagnostics due to a fatal error, e.g. if the source has a
  // 'so such module' error, which will suppress other diagnostics.
  // We don't want to turn off the suppression to avoid a flood of diagnostics
  // when a module import fails, but we also don't want to lose the parser
  // diagnostics in such a case, so merge the parser diagnostics with the sema
  // ones.

  auto orderDiagnosticEntryInfos = [](const DiagnosticEntryInfo &LHS,
                                      const DiagnosticEntryInfo &RHS) -> bool {
    if (LHS.Filename != RHS.Filename)
      return LHS.Filename < RHS.Filename;
    if (LHS.Offset != RHS.Offset)
      return LHS.Offset < RHS.Offset;
    return LHS.Description < RHS.Description;
  };

  std::vector<DiagnosticEntryInfo> sortedParserDiags;
  sortedParserDiags.reserve(ParserDiags.size());
  sortedParserDiags.insert(sortedParserDiags.end(), ParserDiags.begin(),
                           ParserDiags.end());
  std::stable_sort(sortedParserDiags.begin(), sortedParserDiags.end(),
                   orderDiagnosticEntryInfos);

  std::vector<DiagnosticEntryInfo> finalDiags;
  finalDiags.reserve(sortedParserDiags.size()+curSemaDiags.size());

  // Add sema diagnostics unless it is an existing parser diagnostic.
  // Note that we want to merge and eliminate diagnostics from the 'sema' set
  // that also show up in the 'parser' set, but we don't want to remove
  // duplicate diagnostics from within the same set (e.g. duplicates existing in
  // the 'sema' set). We want to report the diagnostics as the compiler reported
  // them, even if there's some duplicate one. This is why we don't just do a
  // simple append/sort/keep-uniques step.
  for (const auto &curDE : curSemaDiags) {
    bool existsAsParserDiag = std::binary_search(sortedParserDiags.begin(),
                                                 sortedParserDiags.end(),
                                             curDE, orderDiagnosticEntryInfos);
    if (!existsAsParserDiag) {
      finalDiags.push_back(curDE);
    }
  }

  finalDiags.insert(finalDiags.end(),
                    sortedParserDiags.begin(), sortedParserDiags.end());
  std::stable_sort(finalDiags.begin(), finalDiags.end(),
                   orderDiagnosticEntryInfos);

  return finalDiags;
}

void SwiftDocumentSemanticInfo::updateSemanticInfo(
    std::vector<SwiftSemanticToken> Toks,
    std::vector<DiagnosticEntryInfo> Diags,
    ImmutableTextSnapshotRef Snapshot,
    uint64_t ASTGeneration) {

  {
    llvm::sys::ScopedLock L(Mtx);
    if (ASTGeneration > this->ASTGeneration) {
      SemaToks = std::move(Toks);
      SemaDiags = std::move(Diags);
      TokSnapshot = DiagSnapshot = std::move(Snapshot);
      this->ASTGeneration = ASTGeneration;
    }
  }

  LOG_INFO_FUNC(High, "posted document update notification for: " << Filename);
  NotificationCtr->postDocumentUpdateNotification(Filename);
}

namespace {

class SemanticAnnotator : public SourceEntityWalker {
  SourceManager &SM;
  unsigned BufferID;
public:

  std::vector<SwiftSemanticToken> SemaToks;

  SemanticAnnotator(SourceManager &SM, unsigned BufferID)
    : SM(SM), BufferID(BufferID) {}

  bool visitDeclReference(ValueDecl *D, CharSourceRange Range,
                          TypeDecl *CtorTyRef, ExtensionDecl *ExtTyRef, Type T,
                          ReferenceMetaData Data) override {
      if (isa<VarDecl>(D) && D->hasName() &&
          D->getFullName() == D->getASTContext().Id_self)
      return true;

    // Do not annotate references to unavailable decls.
    if (AvailableAttr::isUnavailable(D))
      return true;

    if (CtorTyRef)
      D = CtorTyRef;
    annotate(D, /*IsRef=*/true, Range);
    return true;
  }

  bool visitSubscriptReference(ValueDecl *D, CharSourceRange Range,
                               Optional<AccessKind> AccKind,
                               bool IsOpenBracket) override {
    // We should treat both open and close brackets equally
    return visitDeclReference(D, Range, nullptr, nullptr, Type(),
                      ReferenceMetaData(SemaReferenceKind::SubscriptRef, AccKind));
  }

  void annotate(const Decl *D, bool IsRef, CharSourceRange Range) {
    unsigned ByteOffset = SM.getLocOffsetInBuffer(Range.getStart(), BufferID);
    unsigned Length = Range.getByteLength();
    auto Kind = CodeCompletionResult::getCodeCompletionDeclKind(D);
    bool IsSystem = D->getModuleContext()->isSystemModule();
    SemaToks.emplace_back(Kind, ByteOffset, Length, IsRef, IsSystem);
  }
};

} // anonymous namespace

namespace {

class AnnotAndDiagASTConsumer : public SwiftASTConsumer {
  EditableTextBufferRef EditableBuffer;
  RefPtr<SwiftDocumentSemanticInfo> SemaInfoRef;

public:
  std::vector<SwiftSemanticToken> SemaToks;

  AnnotAndDiagASTConsumer(EditableTextBufferRef EditableBuffer,
                          RefPtr<SwiftDocumentSemanticInfo> SemaInfoRef)
    : EditableBuffer(std::move(EditableBuffer)),
      SemaInfoRef(std::move(SemaInfoRef)) { }

  void failed(StringRef Error) override {
    LOG_WARN_FUNC("sema annotations failed: " << Error);
  }

  void handlePrimaryAST(ASTUnitRef AstUnit) override {
    auto Generation = AstUnit->getGeneration();
    auto &CompIns = AstUnit->getCompilerInstance();
    auto &Consumer = AstUnit->getEditorDiagConsumer();
    assert(Generation);

    if (Generation < SemaInfoRef->getASTGeneration()) {
      // It may happen that this request was waiting in async queue for
      // too long so another thread has already updated this sema with
      // ast generation bigger than ASTGeneration
      return;
    }

    ImmutableTextSnapshotRef DocSnapshot;
    for (auto &Snap : AstUnit->getSnapshots()) {
      if (Snap->getEditableBuffer() == EditableBuffer) {
        DocSnapshot = Snap;
        break;
      }
    }

    if (!DocSnapshot) {
      LOG_WARN_FUNC("did not find document snapshot when handling the AST");
      return;
    }

    if (Generation == SemaInfoRef->getASTGeneration()) {
      // Save time if we already know we processed this AST version.
      if (DocSnapshot->getStamp() != EditableBuffer->getSnapshot()->getStamp()){
        // Handle edits that occurred after we processed the AST.
        SemaInfoRef->processLatestSnapshotAsync(EditableBuffer);
      }
      return;
    }

    if (!AstUnit->getPrimarySourceFile().getBufferID().hasValue()) {
      LOG_WARN_FUNC("Primary SourceFile is expected to have a BufferID");
      return;
    }
    unsigned BufferID = AstUnit->getPrimarySourceFile().getBufferID().getValue();

    SemanticAnnotator Annotator(CompIns.getSourceMgr(), BufferID);
    Annotator.walk(AstUnit->getPrimarySourceFile());
    SemaToks = std::move(Annotator.SemaToks);

    SemaInfoRef->
      updateSemanticInfo(std::move(SemaToks),
                     std::move(Consumer.getDiagnosticsForBuffer(BufferID)),
                         DocSnapshot,
                         Generation);

    if (DocSnapshot->getStamp() != EditableBuffer->getSnapshot()->getStamp()) {
      // Handle edits that occurred after we processed the AST.
      SemaInfoRef->processLatestSnapshotAsync(EditableBuffer);
    }
  }
};

} // anonymous namespace

void SwiftDocumentSemanticInfo::processLatestSnapshotAsync(
    EditableTextBufferRef EditableBuffer) {

  SwiftInvocationRef Invok = InvokRef;
  if (!Invok)
    return;

  RefPtr<SwiftDocumentSemanticInfo> SemaInfoRef = this;
  auto Consumer = std::make_shared<AnnotAndDiagASTConsumer>(EditableBuffer,
                                                            SemaInfoRef);

  // Semantic annotation queries for a particular document should cancel
  // previously queued queries for the same document. Each document has a
  // SwiftDocumentSemanticInfo pointer so use that for the token.
  const void *OncePerASTToken = SemaInfoRef.get();
  if (auto ASTMgr = this->ASTMgr.lock()) {
    ASTMgr->processASTAsync(Invok, std::move(Consumer), OncePerASTToken);
  }
}

struct SwiftEditorDocument::Implementation {
  std::weak_ptr<SwiftASTManager> ASTMgr;
  std::shared_ptr<NotificationCenter> NotificationCtr;

  const std::string FilePath;
  EditableTextBufferRef EditableBuffer;

  /// The list of syntax highlighted token offsets and ranges in the document
  SwiftSyntaxMap SyntaxMap;
  /// The minimal range of syntax highlighted tokens affected by the last edit
  llvm::Optional<SwiftEditorCharRange> AffectedRange;
  /// Whether the last operation was an edit rather than a document open
  bool Edited;
  /// The syntax tree of the document
  llvm::Optional<SourceFileSyntax> SyntaxTree;

  std::vector<DiagnosticEntryInfo> ParserDiagnostics;
  RefPtr<SwiftDocumentSemanticInfo> SemanticInfo;
  CodeFormatOptions FormatOptions;

  std::shared_ptr<SwiftDocumentSyntaxInfo> SyntaxInfo;

  std::shared_ptr<SwiftDocumentSyntaxInfo> getSyntaxInfo() {
    llvm::sys::ScopedLock L(AccessMtx);
    return SyntaxInfo;
  }

  llvm::sys::Mutex AccessMtx;

  Implementation(StringRef FilePath, SwiftLangSupport &LangSupport,
                 CodeFormatOptions options)
      : ASTMgr(LangSupport.getASTManager()),
        NotificationCtr(LangSupport.getNotificationCenter()),
        FilePath(FilePath), FormatOptions(options) {
    SemanticInfo =
        new SwiftDocumentSemanticInfo(FilePath, ASTMgr, NotificationCtr);
  }
};

namespace  {

static UIdent getAccessLevelUID(AccessLevel Access) {
  static UIdent AccessOpen("source.lang.swift.accessibility.open");
  static UIdent AccessPublic("source.lang.swift.accessibility.public");
  static UIdent AccessInternal("source.lang.swift.accessibility.internal");
  static UIdent AccessFilePrivate("source.lang.swift.accessibility.fileprivate");
  static UIdent AccessPrivate("source.lang.swift.accessibility.private");

  switch (Access) {
  case AccessLevel::Private:
    return AccessPrivate;
  case AccessLevel::FilePrivate:
    return AccessFilePrivate;
  case AccessLevel::Internal:
    return AccessInternal;
  case AccessLevel::Public:
    return AccessPublic;
  case AccessLevel::Open:
    return AccessOpen;
  }

  llvm_unreachable("Unhandled access level in switch.");
}

class SwiftDocumentStructureWalker: public ide::SyntaxModelWalker {
  SourceManager &SrcManager;
  EditorConsumer &Consumer;
  unsigned BufferID;

public:
  SwiftDocumentStructureWalker(SourceManager &SrcManager,
                               unsigned BufferID,
                               EditorConsumer &Consumer)
    : SrcManager(SrcManager), Consumer(Consumer), BufferID(BufferID) { }

  bool walkToSubStructurePre(SyntaxStructureNode Node) override {
    unsigned StartOffset = SrcManager.getLocOffsetInBuffer(Node.Range.getStart(),
                                                           BufferID);
    unsigned EndOffset = SrcManager.getLocOffsetInBuffer(Node.Range.getEnd(),
                                                         BufferID);
    unsigned NameStart;
    unsigned NameEnd;
    if (Node.NameRange.isValid()) {
      NameStart = SrcManager.getLocOffsetInBuffer(Node.NameRange.getStart(),
                                                  BufferID);
      NameEnd = SrcManager.getLocOffsetInBuffer(Node.NameRange.getEnd(),
                                                BufferID);
    }
    else {
      NameStart = NameEnd = 0;
    }

    unsigned BodyOffset;
    unsigned BodyEnd;
    if (Node.BodyRange.isValid()) {
      BodyOffset = SrcManager.getLocOffsetInBuffer(Node.BodyRange.getStart(),
                                                   BufferID);
      BodyEnd = SrcManager.getLocOffsetInBuffer(Node.BodyRange.getEnd(),
                                                BufferID);
    }
    else {
      BodyOffset = BodyEnd = 0;
    }

    unsigned DocOffset = 0;
    unsigned DocEnd = 0;
    if (Node.DocRange.isValid()) {
      DocOffset = SrcManager.getLocOffsetInBuffer(Node.DocRange.getStart(),
                                                  BufferID);
      DocEnd = SrcManager.getLocOffsetInBuffer(Node.DocRange.getEnd(),
                                               BufferID);
    }

    UIdent Kind = SwiftLangSupport::getUIDForSyntaxStructureKind(Node.Kind);
    UIdent AccessLevel;
    UIdent SetterAccessLevel;
    if (Node.Kind != SyntaxStructureKind::Parameter &&
        Node.Kind != SyntaxStructureKind::LocalVariable &&
        Node.Kind != SyntaxStructureKind::GenericTypeParam) {
      if (auto *VD = dyn_cast_or_null<ValueDecl>(Node.Dcl)) {
        AccessLevel = getAccessLevelUID(VD->getFormalAccess());
      } else if (auto *ED = dyn_cast_or_null<ExtensionDecl>(Node.Dcl)) {
        auto StrictAccess = ED->getDefaultAccessLevel();
        AccessLevel = getAccessLevelUID(StrictAccess);
      }
      if (auto *ASD = dyn_cast_or_null<AbstractStorageDecl>(Node.Dcl)) {
        if (ASD->isSettable(/*UseDC=*/nullptr)) {
          swift::AccessLevel SetAccess = ASD->getSetterFormalAccess();
          SetterAccessLevel = getAccessLevelUID(SetAccess);
        }
      }
    }

    SmallVector<StringRef, 4> InheritedNames;
    if (!Node.InheritedTypeRanges.empty()) {
      for (auto &TR : Node.InheritedTypeRanges) {
        InheritedNames.push_back(SrcManager.extractText(TR));
      }
    }

    StringRef TypeName;
    if (Node.TypeRange.isValid()) {
      TypeName = SrcManager.extractText(Node.TypeRange);
    }

    SmallString<64> DisplayNameBuf;
    StringRef DisplayName;
    if (auto ValueD = dyn_cast_or_null<ValueDecl>(Node.Dcl)) {
      llvm::raw_svector_ostream OS(DisplayNameBuf);
      if (!SwiftLangSupport::printDisplayName(ValueD, OS))
        DisplayName = OS.str();
    }
    else if (Node.NameRange.isValid()) {
      DisplayName = SrcManager.extractText(Node.NameRange);
    }

    SmallString<64> RuntimeNameBuf;
    StringRef RuntimeName = getObjCRuntimeName(Node.Dcl, RuntimeNameBuf);

    SmallString<64> SelectorNameBuf;
    StringRef SelectorName = getObjCSelectorName(Node.Dcl, SelectorNameBuf);

    std::vector<std::tuple<UIdent, unsigned, unsigned>> Attrs;

    for (auto Attr : Node.Attrs) {
      if (auto AttrUID = SwiftLangSupport::getUIDForDeclAttribute(Attr)) {
        unsigned AttrOffset = 0;
        unsigned AttrEnd = 0;
        auto AttrRange = Attr->getRangeWithAt();
        if (AttrRange.isValid()) {
          auto CharRange = Lexer::getCharSourceRangeFromSourceRange(SrcManager,
                                                                    AttrRange);
          AttrOffset = SrcManager.getLocOffsetInBuffer(CharRange.getStart(),
                                                       BufferID);
          AttrEnd = SrcManager.getLocOffsetInBuffer(CharRange.getEnd(),
                                                    BufferID);
        }

        auto AttrTuple = std::make_tuple(AttrUID.getValue(), AttrOffset,
                                         AttrEnd - AttrOffset);
        Attrs.push_back(AttrTuple);
      }
    }

    Consumer.beginDocumentSubStructure(StartOffset, EndOffset - StartOffset,
                                       Kind, AccessLevel, SetterAccessLevel,
                                       NameStart, NameEnd - NameStart,
                                       BodyOffset, BodyEnd - BodyOffset,
                                       DocOffset, DocEnd - DocOffset,
                                       DisplayName,
                                       TypeName, RuntimeName,
                                       SelectorName,
                                       InheritedNames, Attrs);

    for (const auto &Elem : Node.Elements) {
      if (Elem.Range.isInvalid())
        continue;

      UIdent Kind = SwiftLangSupport::getUIDForSyntaxStructureElementKind(Elem.Kind);
      unsigned Offset = SrcManager.getLocOffsetInBuffer(Elem.Range.getStart(),
                                                        BufferID);
      unsigned Length = Elem.Range.getByteLength();
      Consumer.handleDocumentSubStructureElement(Kind, Offset, Length);
    }

    return true;
  }

  StringRef getObjCRuntimeName(const Decl *D, SmallString<64> &Buf) {
    if (!D || D->isInvalid())
      return StringRef();
    if (!isa<ClassDecl>(D) && !isa<ProtocolDecl>(D))
      return StringRef();
    auto *VD = cast<ValueDecl>(D);
    if (!VD->hasName())
      return StringRef();
    auto ident = VD->getBaseName().getIdentifier().str();
    if (ident.empty() || Mangle::isDigit(ident.front()))
      return StringRef();

    // We don't support getting the runtime name for nested classes.
    // This would require typechecking or at least name lookup, if the nested
    // class is in an extension.
    if (!D->getDeclContext()->isModuleScopeContext())
      return StringRef();

    if (auto ClassD = dyn_cast<ClassDecl>(D)) {
      // We don't vend the runtime name for generic classes for now.
      if (ClassD->getGenericParams())
        return StringRef();
      return ClassD->getObjCRuntimeName(Buf);
    }
    return cast<ProtocolDecl>(D)->getObjCRuntimeName(Buf);
  }

  StringRef getObjCSelectorName(const Decl *D, SmallString<64> &Buf) {
    if (auto FuncD = dyn_cast_or_null<AbstractFunctionDecl>(D)) {
      // We only vend the selector name for @IBAction methods.
      if (FuncD->getAttrs().hasAttribute<IBActionAttr>())
        return FuncD->getObjCSelector().getString(Buf);
    }
    return StringRef();
  }

  bool walkToSubStructurePost(SyntaxStructureNode Node) override {
    Consumer.endDocumentSubStructure();
    return true;
  }

  bool walkToNodePre(SyntaxNode Node) override {
    if (Node.Kind != SyntaxNodeKind::CommentMarker)
      return false;

    unsigned StartOffset = SrcManager.getLocOffsetInBuffer(Node.Range.getStart(),
                                                           BufferID);
    unsigned EndOffset = SrcManager.getLocOffsetInBuffer(Node.Range.getEnd(),
                                                         BufferID);
    UIdent Kind = SwiftLangSupport::getUIDForSyntaxNodeKind(Node.Kind);
    Consumer.beginDocumentSubStructure(StartOffset, EndOffset - StartOffset,
                                       Kind, UIdent(), UIdent(), 0, 0,
                                       0, 0, 0, 0,
                                       StringRef(),
                                       StringRef(), StringRef(),
                                       StringRef(),
                                       {}, {});
    return true;
  }

  bool walkToNodePost(SyntaxNode Node) override {
    if (Node.Kind != SyntaxNodeKind::CommentMarker)
      return true;

    Consumer.endDocumentSubStructure();
    return true;
  }
};

/// Walks the syntax model to populate a given SwiftSyntaxMap with the token
/// ranges to highlight and pass document structure information to the given
/// EditorConsumer.
class SwiftEditorSyntaxWalker: public ide::SyntaxModelWalker {
  /// The syntax map to populate
  SwiftSyntaxMap &SyntaxMap;
  SourceManager &SrcManager;
  unsigned BufferID;
  SwiftDocumentStructureWalker DocStructureWalker;
  /// The current token nesting level (e.g. for a field in a doc comment)
  unsigned NestingLevel = 0;
public:
  SwiftEditorSyntaxWalker(SwiftSyntaxMap &SyntaxMap,
                          SourceManager &SrcManager, EditorConsumer &Consumer,
                          unsigned BufferID)
    : SyntaxMap(SyntaxMap), SrcManager(SrcManager), BufferID(BufferID),
      DocStructureWalker(SrcManager, BufferID, Consumer) { }

  bool walkToNodePre(SyntaxNode Node) override {
    if (Node.Kind == SyntaxNodeKind::CommentMarker)
      return DocStructureWalker.walkToNodePre(Node);
    ++NestingLevel;

    auto End = SrcManager.getLocOffsetInBuffer(Node.Range.getEnd(), BufferID),
      Start = SrcManager.getLocOffsetInBuffer(Node.Range.getStart(), BufferID);

    if (NestingLevel > 1) {
      // We're nested inside the previously reported token - merge
      SyntaxMap.mergeToken({Start, End - Start, Node.Kind});
    } else {
      // We're a top-level token, add it after the previous one
      SyntaxMap.addToken({Start, End - Start, Node.Kind});
    }

    return true;
  }

  bool walkToNodePost(SyntaxNode Node) override {
    if (Node.Kind == SyntaxNodeKind::CommentMarker)
      return DocStructureWalker.walkToNodePost(Node);
    --NestingLevel;

    return true;
  }

  bool walkToSubStructurePre(SyntaxStructureNode Node) override {
    return DocStructureWalker.walkToSubStructurePre(Node);
  }

  bool walkToSubStructurePost(SyntaxStructureNode Node) override {
    return DocStructureWalker.walkToSubStructurePost(Node);
  }

};

class PlaceholderExpansionScanner {

public:
  struct Param {
    CharSourceRange NameRange;
    CharSourceRange TypeRange;
    Param(CharSourceRange NameRange, CharSourceRange TypeRange)
      :NameRange(NameRange), TypeRange(TypeRange) { }
  };

private:

  struct ClosureInfo {
    std::vector<Param> Params;
    CharSourceRange ReturnTypeRange;
  };

  SourceManager &SM;
  ClosureInfo TargetClosureInfo;
  EditorPlaceholderExpr *PHE = nullptr;

  class PlaceholderFinder: public ASTWalker {
    SourceLoc PlaceholderLoc;
    EditorPlaceholderExpr *&Found;

  public:
    PlaceholderFinder(SourceLoc PlaceholderLoc,
                      EditorPlaceholderExpr *&Found)
    : PlaceholderLoc(PlaceholderLoc), Found(Found) {
    }

    std::pair<bool, Expr *> walkToExprPre(Expr *E) override {
      if (isa<EditorPlaceholderExpr>(E) && E->getStartLoc() == PlaceholderLoc) {
        Found = cast<EditorPlaceholderExpr>(E);
        return { false, nullptr };
      }
      return { true, E };
    }
  };

  class ClosureTypeWalker: public ASTWalker {
    SourceManager &SM;
    ClosureInfo &Info;
  public:
    bool FoundFunctionTypeRepr = false;
    explicit ClosureTypeWalker(SourceManager &SM, ClosureInfo &Info) : SM(SM),
      Info(Info) { }

    bool walkToTypeReprPre(TypeRepr *T) override {
      if (auto *FTR = dyn_cast<FunctionTypeRepr>(T)) {
        FoundFunctionTypeRepr = true;
        for (auto &ArgElt : FTR->getArgsTypeRepr()->getElements()) {
          CharSourceRange NR;
          CharSourceRange TR;
          auto name = ArgElt.Name;
          if (!name.empty()) {
            NR = CharSourceRange(ArgElt.NameLoc,
                                 name.getLength());
          }
          SourceLoc SRE = Lexer::getLocForEndOfToken(SM,
                                                  ArgElt.Type->getEndLoc());
          TR = CharSourceRange(SM, ArgElt.Type->getStartLoc(), SRE);
          Info.Params.emplace_back(NR, TR);
        }
        if (auto *RTR = FTR->getResultTypeRepr()) {
          SourceLoc SRE = Lexer::getLocForEndOfToken(SM, RTR->getEndLoc());
          Info.ReturnTypeRange = CharSourceRange(SM, RTR->getStartLoc(), SRE);
        }
      }
      return !FoundFunctionTypeRepr;
    }

    bool walkToTypeReprPost(TypeRepr *T) override {
      // If we just visited the FunctionTypeRepr, end traversal.
      return !FoundFunctionTypeRepr;
    }

  };

  bool containClosure(Expr *E) {
    if (E->getStartLoc().isInvalid())
      return false;
    EditorPlaceholderExpr *Found = nullptr;
    ClosureInfo Info;
    ClosureTypeWalker ClosureWalker(SM, Info);
    PlaceholderFinder Finder(E->getStartLoc(), Found);
    E->walk(Finder);
    if (Found) {
      if (auto TR = Found->getTypeLoc().getTypeRepr()) {
        TR->walk(ClosureWalker);
        return ClosureWalker.FoundFunctionTypeRepr;
      }
    }
    E->walk(ClosureWalker);
    return ClosureWalker.FoundFunctionTypeRepr;
  }

  bool scanClosureType(SourceFile &SF, SourceLoc PlaceholderLoc) {
    TargetClosureInfo.Params.clear();
    TargetClosureInfo.ReturnTypeRange = CharSourceRange();
    PlaceholderFinder Finder(PlaceholderLoc, PHE);
    SF.walk(Finder);
    if (!PHE || !PHE->getTypeForExpansion())
      return false;
    ClosureTypeWalker PW(SM, TargetClosureInfo);
    PHE->getTypeForExpansion()->walk(PW);
    return PW.FoundFunctionTypeRepr;
  }

  /// Finds the enclosing CallExpr, and indicates whether it should be further
  /// considered a candidate for application of trailing closure.
  /// For example, if the CallExpr is enclosed in another expression or statement
  /// such as "outer(inner(<#closure#>))", or "if inner(<#closure#>)", then trailing
  /// closure should not be applied to the inner call.
  std::pair<Expr*, bool> enclosingCallExprArg(SourceFile &SF, SourceLoc SL) {

    class CallExprFinder : public SourceEntityWalker {
    public:
      const SourceManager &SM;
      SourceLoc TargetLoc;
      std::pair<Expr *, Expr*> EnclosingCallAndArg;
      Expr *OuterExpr;
      Stmt *OuterStmt;
      explicit CallExprFinder(const SourceManager &SM)
        :SM(SM) { }

      bool checkCallExpr(Expr *E) {
        Expr* Arg = nullptr;
        if (auto *CE = dyn_cast<CallExpr>(E)) {
          // Call expression can have argument.
          Arg = CE->getArg();
        } else if (auto UME = dyn_cast<UnresolvedMemberExpr>(E)) {
          // Unresolved member can have argument too.
          Arg = UME->getArgument();
        }
        if (!Arg)
          return false;
        if (EnclosingCallAndArg.first)
          OuterExpr = EnclosingCallAndArg.first;
        EnclosingCallAndArg = {E, Arg};
        return true;
      }

      bool walkToExprPre(Expr *E) override {
        auto SR = E->getSourceRange();
        if (SR.isValid() && SM.rangeContainsTokenLoc(SR, TargetLoc)) {
          if (!checkCallExpr(E) && !EnclosingCallAndArg.first)
            OuterExpr = E;
        }
        return true;
      }

      bool walkToExprPost(Expr *E) override {
        if (E->getStartLoc() == TargetLoc)
          return false; // found what we needed to find, stop walking.
        return true;
      }

      bool walkToStmtPre(Stmt *S) override {
        auto SR = S->getSourceRange();
        if (SR.isValid() && SM.rangeContainsTokenLoc(SR, TargetLoc)) {
          if (!EnclosingCallAndArg.first) {
            if (isa<BraceStmt>(S))
              // In case OuterStmt is already set, we should clear it to nullptr.
              OuterStmt = nullptr;
            else
              OuterStmt = S;
          }
        }
        return true;
      }

      Expr *findEnclosingCallArg(SourceFile &SF, SourceLoc SL) {
        EnclosingCallAndArg = {nullptr, nullptr};
        OuterExpr = nullptr;
        OuterStmt = nullptr;
        TargetLoc = SL;
        walk(SF);
        return EnclosingCallAndArg.second;
      }
    };

    CallExprFinder CEFinder(SM);
    auto *CE = CEFinder.findEnclosingCallArg(SF, SL);

    if (!CE)
      return std::make_pair(CE, false);
    if (CEFinder.OuterExpr)
      return std::make_pair(CE, false);
    if (CEFinder.OuterStmt)
      return std::make_pair(CE, false);

    return std::make_pair(CE, true);
  }

  bool shouldUseTrailingClosureInTuple(TupleExpr *TE,
                                       SourceLoc PlaceHolderStartLoc) {
    if (!TE->getElements().empty()) {
      for (unsigned I = 0, N = TE->getNumElements(); I < N; ++ I) {
        bool IsLast = I == N - 1;
        Expr *E = TE->getElement(I);
        if (IsLast) {
          return E->getStartLoc() == PlaceHolderStartLoc;
        } else if (containClosure(E)) {
          return false;
        }
      }
    }
    return false;
  }

public:
  explicit PlaceholderExpansionScanner(SourceManager &SM) : SM(SM) { }

  /// Retrieves the parameter list, return type and context info for
  /// a typed completion placeholder in a function call.
  /// For example: foo.bar(aaa, <#T##(Int, Int) -> Bool#>).
  bool scan(SourceFile &SF, unsigned BufID, unsigned Offset,
             unsigned Length, std::function<void(Expr *Args,
                                                 bool UseTrailingClosure,
                                                 ArrayRef<Param>,
                                                 CharSourceRange)> Callback,
            std::function<bool(EditorPlaceholderExpr*)> NonClosureCallback) {

    SourceLoc PlaceholderStartLoc = SM.getLocForOffset(BufID, Offset);

    // See if the placeholder is encapsulated with an EditorPlaceholderExpr
    // and retrieve parameter and return type ranges.
    if (!scanClosureType(SF, PlaceholderStartLoc)) {
      return NonClosureCallback(PHE);
    }

    // Now we need to see if we can suggest trailing closure expansion,
    // and if the call parens can be removed in that case.
    // We'll first find the enclosing CallExpr, and then do further analysis.
    bool UseTrailingClosure = false;
    auto ECE = enclosingCallExprArg(SF, PlaceholderStartLoc);
    Expr *Args = ECE.first;
    if (Args && ECE.second) {
      if (isa<ParenExpr>(Args)) {
        UseTrailingClosure = true;
      } else if (auto *TE = dyn_cast<TupleExpr>(Args)) {
        UseTrailingClosure = shouldUseTrailingClosureInTuple(TE,
                                                          PlaceholderStartLoc);
      }
    }

    Callback(Args, UseTrailingClosure, TargetClosureInfo.Params,
             TargetClosureInfo.ReturnTypeRange);
    return true;
  }

};

} // anonymous namespace

SwiftEditorDocument::SwiftEditorDocument(StringRef FilePath,
    SwiftLangSupport &LangSupport, CodeFormatOptions Options)
  :Impl(*new Implementation(FilePath, LangSupport, Options)) { }

SwiftEditorDocument::~SwiftEditorDocument()
{
  delete &Impl;
}

ImmutableTextSnapshotRef SwiftEditorDocument::initializeText(
    llvm::MemoryBuffer *Buf, ArrayRef<const char *> Args,
    bool ProvideSemanticInfo) {

  llvm::sys::ScopedLock L(Impl.AccessMtx);

  Impl.Edited = false;
  Impl.EditableBuffer =
      new EditableTextBuffer(Impl.FilePath, Buf->getBuffer());

  // Reset the syntax map data and affected range
  Impl.SyntaxMap.Tokens.clear();
  Impl.AffectedRange = {0, static_cast<unsigned>(Buf->getBufferSize())};

  // Try to create a compiler invocation object if needing semantic info
  // or it's syntactic-only but with passed-in compiler arguments.
  if (ProvideSemanticInfo || !Args.empty()) {
    Impl.SemanticInfo = new SwiftDocumentSemanticInfo(Impl.FilePath, Impl.ASTMgr,
                                                      Impl.NotificationCtr);
    Impl.SemanticInfo->setCompilerArgs(Args);
  }
  return Impl.EditableBuffer->getSnapshot();
}

static void updateSemaInfo(RefPtr<SwiftDocumentSemanticInfo> SemanticInfo,
                           EditableTextBufferRef EditableBuffer) {
  if (SemanticInfo) {
    SemanticInfo->processLatestSnapshotAsync(EditableBuffer);
  }
}

ImmutableTextSnapshotRef SwiftEditorDocument::replaceText(
    unsigned Offset, unsigned Length, llvm::MemoryBuffer *Buf,
    bool ProvideSemanticInfo, std::string &error) {

  ImmutableTextSnapshotRef Snapshot;
  EditableTextBufferRef EditableBuffer;
  RefPtr<SwiftDocumentSemanticInfo> SemanticInfo;
  {
    llvm::sys::ScopedLock L(Impl.AccessMtx);

    EditableBuffer = Impl.EditableBuffer;
    SemanticInfo = Impl.SemanticInfo;

    // Validate offset and length.
    if ((Offset + Length) > EditableBuffer->getSize()) {
      error = "'offset' + 'length' is out of range";
      return nullptr;
    }

    Impl.Edited = true;
    llvm::StringRef Str = Buf->getBuffer();

    // Update the buffer itself
    Snapshot = EditableBuffer->replace(Offset, Length, Str);

    // Update the old syntax map offsets to account for the replaced range.
    // Also set the initial AffectedRange to cover any tokens that
    // the replaced range intersected. This allows for clients that split
    // multi-line tokens at line boundaries, and ensure all parts of these tokens
    // will be cleared.
    Impl.AffectedRange =
        Impl.SyntaxMap.adjustForReplacement(Offset, Length, Str.size());

    // We need to release `AccessMtx` before calling into the ASTManager, since
    // it may call back to the editor for document state.
  }

  if (ProvideSemanticInfo) {
    // If this is not a no-op, update semantic info.
    if (Length != 0 || Buf->getBufferSize() != 0) {
      ::updateSemaInfo(SemanticInfo, EditableBuffer);

      // FIXME: we should also update any "interesting" ASTs that depend on this
      // document here, e.g. any ASTs for files visible in an editor. However,
      // because our API conflates this with any file with unsaved changes we do
      // not update all open documents, since there could be too many of them.
    }
  }

  return Snapshot;
}

void SwiftEditorDocument::updateSemaInfo() {
  Impl.AccessMtx.lock();
  auto EditableBuffer = Impl.EditableBuffer;
  auto SemanticInfo = Impl.SemanticInfo;
  // We need to release `AccessMtx` before calling into the ASTManager, since it
  // may call back to the editor for document state.
  Impl.AccessMtx.unlock();

  ::updateSemaInfo(SemanticInfo, EditableBuffer);
}

void SwiftEditorDocument::parse(ImmutableTextSnapshotRef Snapshot,
                                SwiftLangSupport &Lang, bool BuildSyntaxTree,
                                SyntaxParsingCache *SyntaxCache) {
  llvm::sys::ScopedLock L(Impl.AccessMtx);

  assert(Impl.SemanticInfo && "Impl.SemanticInfo must be set");

  std::vector<std::string> Args;
  std::string PrimaryFile; // Ignored, Impl.FilePath will be used

  CompilerInvocation CompInv;
  if (Impl.SemanticInfo->getInvocation()) {
    Impl.SemanticInfo->getInvocation()->applyTo(CompInv);
    Impl.SemanticInfo->getInvocation()->raw(Args, PrimaryFile);
  } else {
    // Use stdin as a .swift input to satisfy the driver. Note that we don't
    // use Impl.FilePath here because it may be invalid filename for driver
    // like "" or "-foobar".
    SmallVector<const char *, 1> Args;
    Args.push_back("-");
    std::string Error;
    // Ignore possible error(s)
    Lang.getASTManager()->
      initCompilerInvocation(CompInv, Args, StringRef(), Error);
  }
  CompInv.getLangOptions().BuildSyntaxTree = BuildSyntaxTree;
  CompInv.setMainFileSyntaxParsingCache(SyntaxCache);
  // When reuse parts of the syntax tree from a SyntaxParsingCache, not
  // all tokens are visited and thus token collection is invalid
  CompInv.getLangOptions().CollectParsedToken = (SyntaxCache == nullptr);
  // Access to Impl.SyntaxInfo is guarded by Impl.AccessMtx
  Impl.SyntaxInfo.reset(
    new SwiftDocumentSyntaxInfo(CompInv, Snapshot, Args, Impl.FilePath));

  Impl.SyntaxInfo->parse();
}

void SwiftEditorDocument::readSyntaxInfo(EditorConsumer &Consumer) {
  llvm::sys::ScopedLock L(Impl.AccessMtx);

  Impl.ParserDiagnostics = Impl.SyntaxInfo->getDiagnostics();

  SwiftSyntaxMap NewMap = SwiftSyntaxMap(Impl.SyntaxMap.Tokens.size() + 16);

  if (Consumer.syntaxTreeEnabled()) {
    auto SyntaxTree = Impl.SyntaxInfo->getSourceFile().getSyntaxRoot();
    Impl.SyntaxTree.emplace(SyntaxTree);
    if (Consumer.syntaxMapEnabled()) {
      Consumer.handleRequestError(
          "Retrieving both a syntax map and a syntax tree at the same time is "
          "not supported. Use the SyntaxClassifier in swiftSyntax to generate "
          "the syntax map on the Swift side.");
    }
    if (Consumer.documentStructureEnabled()) {
      Consumer.handleRequestError(
          "Retrieving both the document structure and a syntax tree at the "
          "same time is not supported. Use the syntax tree to compute the "
          "document structure.");
    }
  } else {
    ide::SyntaxModelContext ModelContext(Impl.SyntaxInfo->getSourceFile());

    SwiftEditorSyntaxWalker SyntaxWalker(
        NewMap, Impl.SyntaxInfo->getSourceManager(), Consumer,
        Impl.SyntaxInfo->getBufferID());
    ModelContext.walk(SyntaxWalker);

    bool SawChanges = true;
    if (Impl.Edited) {
      // We're ansering an edit request. Report all highlighted token ranges not
      // in the previous syntax map to the Consumer and extend the AffectedRange
      // to contain all added/removed token ranges.
      SawChanges =
          NewMap.forEachChanged(Impl.SyntaxMap, Impl.AffectedRange, Consumer);
    } else {
      // The is an open/initialise. Report all highlighted token ranges to the
      // Consumer.
      NewMap.forEach(Consumer);
    }
    Impl.SyntaxMap = std::move(NewMap);

    // Recording an affected length of 0 still results in the client updating
    // its copy of the syntax map (by clearning all tokens on the line of the
    // affected offset). We need to not record it at all to signal a no-op.
    if (SawChanges)
      Consumer.recordAffectedRange(Impl.AffectedRange->Offset,
                                   Impl.AffectedRange->length());
  }
}

void SwiftEditorDocument::readSemanticInfo(ImmutableTextSnapshotRef Snapshot,
                                           EditorConsumer& Consumer) {
  std::vector<SwiftSemanticToken> SemaToks;
  Optional<std::vector<DiagnosticEntryInfo>> SemaDiags;
  Impl.SemanticInfo->readSemanticInfo(Snapshot, SemaToks, SemaDiags,
                                      Impl.ParserDiagnostics);

  for (auto SemaTok : SemaToks) {
    unsigned Offset = SemaTok.ByteOffset;
    unsigned Length = SemaTok.Length;
    UIdent Kind = SemaTok.getUIdentForKind();
    bool IsSystem = SemaTok.getIsSystem();
    if (Kind.isValid())
      Consumer.handleSemanticAnnotation(Offset, Length, Kind, IsSystem);
  }

  static UIdent SemaDiagStage("source.diagnostic.stage.swift.sema");
  static UIdent ParseDiagStage("source.diagnostic.stage.swift.parse");

  // If there's no value returned for diagnostics it means they are out-of-date
  // (based on a different snapshot).
  if (SemaDiags.hasValue()) {
    Consumer.setDiagnosticStage(SemaDiagStage);
    for (auto &Diag : SemaDiags.getValue())
      Consumer.handleDiagnostic(Diag, SemaDiagStage);
  } else {
    Consumer.setDiagnosticStage(ParseDiagStage);
    for (auto &Diag : Impl.ParserDiagnostics)
      Consumer.handleDiagnostic(Diag, ParseDiagStage);
  }
}

void SwiftEditorDocument::removeCachedAST() {
  Impl.SemanticInfo->removeCachedAST();
}

void SwiftEditorDocument::applyFormatOptions(OptionsDictionary &FmtOptions) {
  static UIdent KeyUseTabs("key.editor.format.usetabs");
  static UIdent KeyIndentWidth("key.editor.format.indentwidth");
  static UIdent KeyTabWidth("key.editor.format.tabwidth");

  FmtOptions.valueForOption(KeyUseTabs, Impl.FormatOptions.UseTabs);
  FmtOptions.valueForOption(KeyIndentWidth, Impl.FormatOptions.IndentWidth);
  FmtOptions.valueForOption(KeyTabWidth, Impl.FormatOptions.TabWidth);
}

const CodeFormatOptions &SwiftEditorDocument::getFormatOptions() {
  return Impl.FormatOptions;
}

const llvm::Optional<swift::SourceFileSyntax> &
SwiftEditorDocument::getSyntaxTree() const {
  return Impl.SyntaxTree;
}

std::string SwiftEditorDocument::getFilePath() const { return Impl.FilePath; }

bool SwiftEditorDocument::hasUpToDateAST() const {
  return Impl.SyntaxInfo->hasUpToDateAST();
}

void SwiftEditorDocument::formatText(unsigned Line, unsigned Length,
                                     EditorConsumer &Consumer) {
  auto SyntaxInfo = Impl.getSyntaxInfo();
  SourceFile &SF = SyntaxInfo->getSourceFile();
  SourceManager &SM = SyntaxInfo->getSourceManager();

  LineRange inputRange = LineRange(Line, Length);
  CodeFormatOptions Options = getFormatOptions();
  auto indented = reformat(inputRange, Options, SM, SF);

  LineRange LineRange = indented.first;
  StringRef ModifiedText = indented.second;
  Consumer.recordFormattedText(ModifiedText);
  Consumer.recordAffectedLineRange(LineRange.startLine(), LineRange.lineCount());
}

bool isReturningVoid(SourceManager &SM, CharSourceRange Range) {
  if (Range.isInvalid())
    return false;
  StringRef Text = SM.extractText(Range);
  return "()" == Text || "Void" == Text;
}

void SwiftEditorDocument::expandPlaceholder(unsigned Offset, unsigned Length,
                                            EditorConsumer &Consumer) {
  auto SyntaxInfo = Impl.getSyntaxInfo();
  SourceManager &SM = SyntaxInfo->getSourceManager();
  unsigned BufID = SyntaxInfo->getBufferID();

  const unsigned PlaceholderStartLen = 2;
  const unsigned PlaceholderEndLen = 2;

  if (Length < (PlaceholderStartLen + PlaceholderEndLen)) {
    Consumer.handleRequestError("Invalid Length parameter");
    return;
  }

  PlaceholderExpansionScanner Scanner(SM);
  SourceFile &SF = SyntaxInfo->getSourceFile();

  Scanner.scan(SF, BufID, Offset, Length,
          [&](Expr *Args,
              bool UseTrailingClosure,
              ArrayRef<PlaceholderExpansionScanner::Param> ClosureParams,
              CharSourceRange ClosureReturnTypeRange) {

      unsigned EffectiveOffset = Offset;
      unsigned EffectiveLength = Length;
      llvm::SmallString<128> ExpansionStr;
      {
        llvm::raw_svector_ostream OS(ExpansionStr);
        if (UseTrailingClosure) {
          assert(Args);

          if (isa<ParenExpr>(Args)) {
            // There appears to be no other parameters in this call, so we'll
            // expand replacement for trailing closure and cover call parens.
            // For example:
            // foo.bar(<#closure#>) turns into foo.bar <#closure#>.
            EffectiveOffset = SM.getLocOffsetInBuffer(Args->getStartLoc(), BufID);
            OS << " ";
          } else {
            auto *TupleE = cast<TupleExpr>(Args);
            auto Elems = TupleE->getElements();
            assert(!Elems.empty());
            if (Elems.size() == 1) {
              EffectiveOffset = SM.getLocOffsetInBuffer(Args->getStartLoc(), BufID);
              OS << " ";
            } else {
              // Expand replacement range for trailing closure.
              // For example:
              // foo.bar(a, <#closure#>) turns into foo.bar(a) <#closure#>.

              // If the preceding token in the call is the leading parameter
              // separator, we'll expand replacement to cover that.
              assert(Elems.size() > 1);
              SourceLoc BeforeLoc = Lexer::getLocForEndOfToken(SM,
                                              Elems[Elems.size()-2]->getEndLoc());
              EffectiveOffset = SM.getLocOffsetInBuffer(BeforeLoc, BufID);
              OS << ") ";
            }
          }

          unsigned End = SM.getLocOffsetInBuffer(Args->getEndLoc(), BufID);
          EffectiveLength = (End + 1) - EffectiveOffset;
        }

        OS << "{ ";

        bool ReturningVoid = isReturningVoid(SM, ClosureReturnTypeRange);

        bool HasSignature = !ClosureParams.empty() ||
                            (ClosureReturnTypeRange.isValid() && !ReturningVoid);
        bool FirstParam = true;
        if (HasSignature)
          OS << "(";
        for (auto &Param: ClosureParams) {
          if (!FirstParam)
            OS << ", ";
          FirstParam = false;
          if (Param.NameRange.isValid()) {
            // If we have a parameter name, just output the name as is and skip
            // the type. For example:
            // <#(arg1: Int, arg2: Int)#> turns into (arg1, arg2).
            OS << SM.extractText(Param.NameRange);
          }
          else {
            // If we only have the parameter type, output the type as a
            // placeholder. For example:
            // <#(Int, Int)#> turns into (<#Int#>, <#Int#>).
            OS << "<#";
            OS << SM.extractText(Param.TypeRange);
            OS << "#>";
          }
        }
        if (HasSignature)
          OS << ") ";
        if (ClosureReturnTypeRange.isValid()) {
          auto ReturnTypeText = SM.extractText(ClosureReturnTypeRange);

          // We need return type if it is not Void.
          if (!ReturningVoid) {
            OS << "-> ";
            OS << ReturnTypeText << " ";
          }
        }
        if (HasSignature)
          OS << "in";
        OS << "\n" << getCodePlaceholder() << "\n";
        OS << "}";
      }
      Consumer.handleSourceText(ExpansionStr);
      Consumer.recordAffectedRange(EffectiveOffset, EffectiveLength);
    }, [&](EditorPlaceholderExpr *PHE) {
      if (!PHE)
        return false;
      if (auto Ty = PHE->getTypeForExpansion()) {
        std::string S;
        llvm::raw_string_ostream OS(S);
        Ty->print(OS);
        Consumer.handleSourceText(OS.str());
        Consumer.recordAffectedRange(Offset, Length);
        return true;
      }
      return false;
    });
}

ImmutableTextSnapshotRef SwiftEditorDocument::getLatestSnapshot() const {
  llvm::sys::ScopedLock L(Impl.AccessMtx);
  return Impl.EditableBuffer->getSnapshot();
}

void SwiftEditorDocument::reportDocumentStructure(SourceFile &SrcFile,
                                                  EditorConsumer &Consumer) {
  ide::SyntaxModelContext ModelContext(SrcFile);
  SwiftDocumentStructureWalker Walker(SrcFile.getASTContext().SourceMgr,
                                      *SrcFile.getBufferID(),
                                      Consumer);
  ModelContext.walk(Walker);
}

//===----------------------------------------------------------------------===//
// EditorOpen
//===----------------------------------------------------------------------===//

void SwiftLangSupport::editorOpen(StringRef Name, llvm::MemoryBuffer *Buf,
                                  EditorConsumer &Consumer,
                                  ArrayRef<const char *> Args) {

  ImmutableTextSnapshotRef Snapshot = nullptr;
  auto EditorDoc = EditorDocuments->getByUnresolvedName(Name);
  if (!EditorDoc) {
    EditorDoc = new SwiftEditorDocument(Name, *this);
    Snapshot = EditorDoc->initializeText(Buf, Args, Consumer.needsSemanticInfo());
    EditorDoc->parse(Snapshot, *this, Consumer.syntaxTreeEnabled());
    if (EditorDocuments->getOrUpdate(Name, *this, EditorDoc)) {
      // Document already exists, re-initialize it. This should only happen
      // if we get OPEN request while the previous document is not closed.
      LOG_WARN_FUNC("Document already exists in editorOpen(..): " << Name);
      Snapshot = nullptr;
    }
    auto numOpen = ++Stats->numOpenDocs;
    Stats->maxOpenDocs.updateMax(numOpen);
  }

  if (!Snapshot) {
    Snapshot = EditorDoc->initializeText(Buf, Args, Consumer.needsSemanticInfo());
    EditorDoc->parse(Snapshot, *this, Consumer.syntaxTreeEnabled());
  }

  if (Consumer.needsSemanticInfo()) {
    EditorDoc->updateSemaInfo();
  }

  EditorDoc->readSyntaxInfo(Consumer);
  EditorDoc->readSemanticInfo(Snapshot, Consumer);

  if (Consumer.syntaxTreeEnabled()) {
    assert(EditorDoc->getSyntaxTree().hasValue());
    std::unordered_set<unsigned> ReusedNodeIds;
    Consumer.handleSyntaxTree(EditorDoc->getSyntaxTree().getValue(), 
                              ReusedNodeIds);
  }
}


//===----------------------------------------------------------------------===//
// EditorClose
//===----------------------------------------------------------------------===//

void SwiftLangSupport::editorClose(StringRef Name, bool RemoveCache) {
  auto Removed = EditorDocuments->remove(Name);
  if (Removed) {
    --Stats->numOpenDocs;
  } else {
    IFaceGenContexts.remove(Name);
  }

  if (Removed && RemoveCache)
    Removed->removeCachedAST();
  // FIXME: Report error if Name did not apply to anything ?
}


//===----------------------------------------------------------------------===//
// EditorReplaceText
//===----------------------------------------------------------------------===//

void verifyIncrementalParse(SwiftEditorDocumentRef EditorDoc,
                            unsigned EditOffset, unsigned EditLength,
                            StringRef PreEditText, StringRef ReplaceText) {
  swift::json::Output::UserInfoMap JsonUserInfo;
  JsonUserInfo[swift::json::DontSerializeNodeIdsUserInfoKey] =
      reinterpret_cast<void *>(true);

  // Dump the incremental syntax tree
  std::string IncrTreeString;
  llvm::raw_string_ostream IncrTreeStream(IncrTreeString);
  swift::json::Output IncrTreeOutput(IncrTreeStream, JsonUserInfo);
  IncrTreeOutput << *EditorDoc->getSyntaxTree()->getRaw();

  // Reparse the file from scratch
  CompilerInvocation Invocation;
  Invocation.getLangOptions().BuildSyntaxTree = true;
  std::vector<std::string> Args;
  SwiftDocumentSyntaxInfo ScratchSyntaxInfo(Invocation,
                                            EditorDoc->getLatestSnapshot(),
                                            Args, EditorDoc->getFilePath());
  ScratchSyntaxInfo.parse();

  // Dump the from-scratch syntax tree
  std::string FromScratchTreeString;
  llvm::raw_string_ostream ScratchTreeStream(FromScratchTreeString);
  swift::json::Output ScratchTreeOutput(ScratchTreeStream, JsonUserInfo);
  auto SyntaxRoot = ScratchSyntaxInfo.getSourceFile().getSyntaxRoot();
  ScratchTreeOutput << *SyntaxRoot.getRaw();

  // If the serialized format of the two trees doesn't match incremental parsing
  // we have found an error.
  if (IncrTreeStream.str().compare(ScratchTreeStream.str())) {
    LOG_SECTION("Incremental Parsing", Warning) {
      Log->getOS() << "Incremental parsing different to from scratch parsing\n";
      Log->getOS() << "Edit was " << EditOffset << "-"
                   << (EditOffset + EditLength) << "='" << ReplaceText << "'"
                   << " pre-edit-text: '" << PreEditText << "'\n";

      SmallString<32> DirectoryName;
      if (llvm::sys::fs::createUniqueDirectory(
              "SourceKit-IncrementalParsing-Inconsistency", DirectoryName)) {
        Log->getOS() << "Failed to create log directory\n";
      }

      std::error_code ErrorCode;

      // Write the incremental syntax tree
      auto IncrTreeFilename = DirectoryName + "/incrementalTree.json";
      llvm::raw_fd_ostream IncrementalFilestream(
          IncrTreeFilename.str(), ErrorCode,
          llvm::sys::fs::FA_Read | llvm::sys::fs::FA_Write);
      IncrementalFilestream << IncrTreeStream.str();
      if (ErrorCode) {
        Log->getOS() << "Failed to write incremental syntax tree to "
                     << IncrTreeFilename << "(error code " << ErrorCode.value()
                     << ": " << ErrorCode.message() << ")\n";
      } else {
        Log->getOS() << "Incremental syntax tree written to "
                     << IncrTreeFilename << '\n';
      }

      // Write from-scratch syntax tree
      auto ScratchTreeFilename = DirectoryName + "/fromScratchTree.json";
      llvm::raw_fd_ostream ScratchTreeFilestream(
          ScratchTreeFilename.str(), ErrorCode,
          llvm::sys::fs::FA_Read | llvm::sys::fs::FA_Write);
      ScratchTreeFilestream << ScratchTreeStream.str();
      if (ErrorCode) {
        Log->getOS() << "Failed to write from-scratch syntax tree to "
                     << ScratchTreeFilename << "(error code "
                     << ErrorCode.value() << ": " << ErrorCode.message()
                     << ")\n";
      } else {
        Log->getOS() << "From-scratch syntax tree written to "
                     << ScratchTreeFilename << '\n';
      }

      // Write source file
      auto SourceFilename = DirectoryName + "/postEditSource.swift";
      llvm::raw_fd_ostream SourceFilestream(SourceFilename.str(), ErrorCode,
                              llvm::sys::fs::FA_Read | llvm::sys::fs::FA_Write);
      auto FileBuffer = EditorDoc->getLatestSnapshot()->getBuffer();
      SourceFilestream << FileBuffer->getText();
    }
  }
}

void SwiftLangSupport::editorReplaceText(StringRef Name,
                                         llvm::MemoryBuffer *Buf,
                                         unsigned Offset, unsigned Length,
                                         EditorConsumer &Consumer) {
  bool LogReuseRegions = ::getenv("SOURCEKIT_LOG_INCREMENTAL_REUSE_REGIONS");
  bool ValidateSyntaxTree = ::getenv("SOURCEKIT_INCREMENTAL_PARSE_VALIDATION");

  auto EditorDoc = EditorDocuments->getByUnresolvedName(Name);
  if (!EditorDoc) {
    Consumer.handleRequestError("No associated Editor Document");
    return;
  }

  ImmutableTextSnapshotRef Snapshot;
  if (Length != 0 || Buf->getBufferSize() != 0) {
    std::string PreEditText;
    if (ValidateSyntaxTree) {
      auto CurBuffer = EditorDoc->getLatestSnapshot()->getBuffer();
      auto BufferStart = CurBuffer->getInternalBuffer()->getBufferStart();
      StringRef PreEditTextRef(BufferStart + Offset, Length);
      PreEditText = PreEditTextRef.str();
    }
    std::string error;
    Snapshot = EditorDoc->replaceText(Offset, Length, Buf,
                                      Consumer.needsSemanticInfo(), error);
    if (!Snapshot) {
      assert(error.size());
      Consumer.handleRequestError(error.c_str());
      return;
    }

    llvm::Optional<SyntaxParsingCache> SyntaxCache = llvm::None;
    if (EditorDoc->getSyntaxTree().hasValue()) {
      SyntaxCache.emplace(EditorDoc->getSyntaxTree().getValue());
      SyntaxCache->addEdit(Offset, Offset + Length, Buf->getBufferSize());
    }

    SyntaxParsingCache *SyntaxCachePtr = nullptr;
    if (SyntaxCache.hasValue()) {
      SyntaxCachePtr = SyntaxCache.getPointer();
    }
    EditorDoc->parse(Snapshot, *this, Consumer.syntaxTreeEnabled(),
                     SyntaxCachePtr);
    EditorDoc->readSyntaxInfo(Consumer);

    // Log reuse information
    if (SyntaxCache.hasValue() && LogReuseRegions) {
      auto &SyntaxTree = EditorDoc->getSyntaxTree();
      auto ReuseRegions = SyntaxCache->getReusedRegions(*SyntaxTree);
      LOG_SECTION("SyntaxCache", InfoHighPrio) {
        Log->getOS() << "Reused ";

        bool FirstIteration = true;
        for (auto ReuseRegion : ReuseRegions) {
          if (!FirstIteration) {
            Log->getOS() << ", ";
          } else {
            FirstIteration = false;
          }

          Log->getOS() << ReuseRegion.Start << " - " << ReuseRegion.End;
        }
      }
    }

    if (Consumer.syntaxTreeEnabled()) {
      std::unordered_set<unsigned> ReusedNodeIds;
      if (SyntaxCache.hasValue()) {
        auto &ReusedVector = SyntaxCache->getReusedNodeIds();
        ReusedNodeIds = std::unordered_set<unsigned>(ReusedVector.begin(),
                                                     ReusedVector.end());
      }
      Consumer.handleSyntaxTree(EditorDoc->getSyntaxTree().getValue(),
                                ReusedNodeIds);
    }

    if (ValidateSyntaxTree) {
      verifyIncrementalParse(EditorDoc, Offset, Length, PreEditText,
                             Buf->getBuffer());
    }
  } else {
    Snapshot = EditorDoc->getLatestSnapshot();
  }

  EditorDoc->readSemanticInfo(Snapshot, Consumer);
}


//===----------------------------------------------------------------------===//
// EditorFormatText
//===----------------------------------------------------------------------===//
void SwiftLangSupport::editorApplyFormatOptions(StringRef Name,
                                                OptionsDictionary &FmtOptions) {
  auto EditorDoc = EditorDocuments->getByUnresolvedName(Name);
  if (EditorDoc)
    EditorDoc->applyFormatOptions(FmtOptions);
}

void SwiftLangSupport::editorFormatText(StringRef Name, unsigned Line,
                                        unsigned Length,
                                        EditorConsumer &Consumer) {
  auto EditorDoc = EditorDocuments->getByUnresolvedName(Name);
  if (!EditorDoc) {
    Consumer.handleRequestError("No associated Editor Document");
    return;
  }

  if (!EditorDoc->hasUpToDateAST()) {
    // An up-to-date AST is needed for formatting. If it does not exist, fall
    // back to a full reparse of the file
    EditorDoc->parse(EditorDoc->getLatestSnapshot(), *this,
                     /*BuildSyntaxTree=*/true);
  }

  EditorDoc->formatText(Line, Length, Consumer);
}

void SwiftLangSupport::editorExtractTextFromComment(StringRef Source,
                                                    EditorConsumer &Consumer) {
  Consumer.handleSourceText(extractPlainTextFromComment(Source));
}

void SwiftLangSupport::editorConvertMarkupToXML(StringRef Source,
                                                EditorConsumer &Consumer) {
  std::string Result;
  llvm::raw_string_ostream OS(Result);
  if (convertMarkupToXML(Source, OS)) {
    Consumer.handleRequestError("Conversion failed.");
    return;
  }
  Consumer.handleSourceText(Result);
}

//===----------------------------------------------------------------------===//
// EditorExpandPlaceholder
//===----------------------------------------------------------------------===//
void SwiftLangSupport::editorExpandPlaceholder(StringRef Name, unsigned Offset,
                                               unsigned Length,
                                               EditorConsumer &Consumer) {
  auto EditorDoc = EditorDocuments->getByUnresolvedName(Name);
  if (!EditorDoc) {
    Consumer.handleRequestError("No associated Editor Document");
    return;
  }

  EditorDoc->expandPlaceholder(Offset, Length, Consumer);
}
