//===--- SwiftEditor.cpp --------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://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/AST.h"
#include "swift/AST/ASTVisitor.h"
#include "swift/AST/ASTWalker.h"
#include "swift/AST/DiagnosticsClangImporter.h"
#include "swift/AST/DiagnosticsParse.h"
#include "swift/Basic/SourceManager.h"
#include "swift/Frontend/Frontend.h"
#include "swift/Frontend/PrintingDiagnosticConsumer.h"
#include "swift/IDE/CodeCompletion.h"
#include "swift/IDE/CommentConversion.h"
#include "swift/IDE/SyntaxModel.h"
#include "swift/IDE/SourceEntityWalker.h"
#include "swift/Subsystems.h"

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

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

void EditorDiagConsumer::handleDiagnostic(SourceManager &SM, SourceLoc Loc,
                                          DiagnosticKind Kind, StringRef Text,
                                          const DiagnosticInfo &Info) {
  if (Kind == DiagnosticKind::Error) {
    HadAnyError = true;
  }

  // Filter out lexer errors for placeholders.
  if (Info.ID == diag::lex_editor_placeholder.ID)
    return;

  if (Loc.isInvalid()) {
    if (Kind == DiagnosticKind::Error)
      HadInvalidLocError = true;
    clearLastDiag();
    return;
  }
  bool IsNote = (Kind == DiagnosticKind::Note);

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

  DiagnosticEntryInfo SKInfo;

  SKInfo.Description = Text;

  unsigned BufferID = SM.findBufferContainingLoc(Loc);

  if (!isInputBufferID(BufferID)) {
    if (Info.ID == diag::error_from_clang.ID ||
        Info.ID == diag::warning_from_clang.ID ||
        Info.ID == diag::note_from_clang.ID) {
      // Handle it as other diagnostics.
    } else {
      if (!IsNote) {
        LOG_WARN_FUNC("got swift diagnostic not pointing at input file, "
                      "buffer name: " << SM.getIdentifierForBuffer(BufferID));
        return;
      }

      // 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(BufferID);
      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;
    }
  }

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

  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() });
  }

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

  DiagnosticsTy &Diagnostics = BufferDiagnostics[BufferID];

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

  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 Column;
  unsigned Length:24;
  swift::ide::SyntaxNodeKind Kind:8;

  SwiftSyntaxToken(unsigned Column, unsigned Length,
                   swift::ide::SyntaxNodeKind Kind)
    :Column(Column), Length(Length), Kind(Kind) { }
};

class SwiftSyntaxMap {
  typedef std::vector<SwiftSyntaxToken> SwiftSyntaxLineMap;
  std::vector<SwiftSyntaxLineMap> Lines;

public:
  bool matchesFirstTokenOnLine(unsigned Line,
                               const SwiftSyntaxToken &Token) const {
    assert(Line > 0);
    if (Lines.size() < Line)
      return false;
    
    unsigned LineOffset = Line - 1;
    const SwiftSyntaxLineMap &LineMap = Lines[LineOffset];
    if (LineMap.empty())
      return false;
    
    const SwiftSyntaxToken &Tok = LineMap.front();
    if (Tok.Column == Token.Column && Tok.Length == Token.Length
        && Tok.Kind == Token.Kind) {
      return true;
    }
    
    return false;
  }

  void addTokenForLine(unsigned Line, const SwiftSyntaxToken &Token) {
    assert(Line > 0);
    if (Lines.size() < Line) {
      Lines.resize(Line);
    }
    unsigned LineOffset = Line - 1;
    SwiftSyntaxLineMap &LineMap = Lines[LineOffset];
    // FIXME: Assert this token is after the last one
    LineMap.push_back(Token);
  }

  void mergeTokenForLine(unsigned Line, const SwiftSyntaxToken &Token) {
    assert(Line > 0);
    if (Lines.size() < Line) {
      Lines.resize(Line);
    }
    unsigned LineOffset = Line - 1;
    SwiftSyntaxLineMap &LineMap = Lines[LineOffset];
    if (!LineMap.empty()) {
      auto &LastTok = LineMap.back();
      mergeSplitRanges(LastTok.Column, LastTok.Length,
                       Token.Column, Token.Length,
                       [&](unsigned BeforeOff, unsigned BeforeLen,
                           unsigned AfterOff, unsigned AfterLen) {
        auto LastKind = LastTok.Kind;
        LineMap.pop_back();
        if (BeforeLen)
          LineMap.emplace_back(BeforeOff, BeforeLen, LastKind);
        LineMap.push_back(Token);
        if (AfterLen)
          LineMap.emplace_back(AfterOff, AfterLen, LastKind);
      });
    }
    else {
      // Not overlapping, just add the new token to the end
      LineMap.push_back(Token);
    }
  }

  void clearLineRange(unsigned StartLine, unsigned Length) {
    assert(StartLine > 0);
    unsigned LineOffset = StartLine - 1;
    for (unsigned Line = LineOffset; Line < LineOffset + Length
                                    && Line < Lines.size(); ++Line) {
      Lines[Line].clear();
    }
  }

  void removeLineRange(unsigned StartLine, unsigned Length) {
    assert(StartLine > 0 && Length > 0);

    if (StartLine < Lines.size()) {
      unsigned EndLine = StartLine + Length - 1;
      // Delete all syntax map data from start line through end line
      Lines.erase(Lines.begin() + StartLine - 1,
                  EndLine >= Lines.size() ? Lines.end()
                                          : Lines.begin() + EndLine);
    }
  }

  void insertLineRange(unsigned StartLine, unsigned Length) {
    Lines.insert(StartLine <= Lines.size() ? Lines.begin() + StartLine - 1
                                           : Lines.end(),
                 Length, SwiftSyntaxLineMap());
  }

  void reset() {
    Lines.clear();
  }
};

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


class SwiftEditorLineRange {
  unsigned StartLine;
  unsigned Length;

public:
  SwiftEditorLineRange()
    :StartLine(0), Length(0) { }
  SwiftEditorLineRange(unsigned StartLine, unsigned Length)
    :StartLine(StartLine), Length(Length) { }
  SwiftEditorLineRange(const SwiftEditorLineRange &Other)
    :StartLine(Other.StartLine), Length(Other.Length) { }

  bool isValid() const {
    return Length != 0;
  }

  unsigned startLine() const {
    return StartLine;
  }
  
  unsigned endLine() const {
    return isValid() ? StartLine + Length - 1 : 0;
  }

  unsigned lineCount() const {
    return Length;
  }
  
  void setRange(unsigned NewStartLine, unsigned NewLength) {
    StartLine = NewStartLine;
    Length = NewLength;
  }

  void extendToIncludeLine(unsigned Line) {
    if (!isValid()) {
      StartLine = Line;
      Length = 1;
    }
    else if (Line >= StartLine + Length) {
      Length = Line - StartLine + 1;
    }
  }

};

typedef std::pair<unsigned, unsigned> SwiftEditorCharRange;

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;
  bool IsRef : 1;
  bool IsSystem : 1;

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

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

class SwiftDocumentSemanticInfo :
    public ThreadSafeRefCountedBase<SwiftDocumentSemanticInfo> {

  const std::string Filename;
  SwiftASTManager &ASTMgr;
  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, SwiftLangSupport &LangSupport)
    : Filename(Filename),
      ASTMgr(LangSupport.getASTManager()),
      NotificationCtr(LangSupport.getContext().getNotificationCenter()) {}

  SwiftInvocationRef getInvocation() const {
    return InvokRef;
  }

  uint64_t getASTGeneration() const;

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

  void readSemanticInfo(ImmutableTextSnapshotRef NewSnapshot,
                        std::vector<SwiftSemanticToken> &Tokens,
                        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)
      ASTMgr.removeCachedAST(InvokRef);
  }

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

  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;

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));
    SM.setHashbangBufferID(BufferID);
    DiagConsumer.setInputBufferIDs(BufferID);

    Parser.reset(
      new ParserUnit(SM, BufferID,
                     CompInv.getLangOptions(),
                     CompInv.getModuleName())
    );

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

  void initArgsAndPrimaryFile(trace::SwiftInvocation &Info) {
    Info.Args.PrimaryFile = PrimaryFile;
    Info.Args.Args = Args;
  }

  void parse() {
    auto &P = Parser->getParser();

    trace::TracedOperation TracedOp;
    if (trace::enabled()) {
      trace::SwiftInvocation Info;
      initArgsAndPrimaryFile(Info);
      auto Text = SM.getLLVMSourceMgr().getMemoryBuffer(BufferID)->getBuffer();
      Info.Files.push_back(std::make_pair(PrimaryFile, Text));
      TracedOp.start(trace::OperationKind::SimpleParse, Info);
    }
    
    bool Done = false;
    while (!Done) {
      P.parseTopLevel();
      Done = P.Tok.is(tok::eof);
    }
  }

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

  unsigned getBufferID() {
    return BufferID;
  }

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

  SourceManager &getSourceManager() {
    return SM;
  }

  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,
    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);
}

static bool
adjustDiagnosticRanges(SmallVectorImpl<std::pair<unsigned, unsigned>> &Ranges,
                       unsigned ByteOffset, unsigned RemoveLen, int Delta) {
  for (auto &Range : Ranges) {
    unsigned RangeBegin = Range.first;
    unsigned RangeEnd = Range.first +  Range.second;
    unsigned RemoveEnd = ByteOffset + RemoveLen;
    // If it intersects with the remove range, ignore the whole diagnostic.
    if (!(RangeEnd < ByteOffset || RangeBegin > RemoveEnd))
      return true; // Ignore.
    if (RangeBegin > RemoveEnd)
      Range.first += Delta;
  }
  return false;
}

static bool
adjustDiagnosticFixits(SmallVectorImpl<DiagnosticEntryInfo::Fixit> &Fixits,
                       unsigned ByteOffset, unsigned RemoveLen, int Delta) {
  for (auto &Fixit : Fixits) {
    unsigned FixitBegin = Fixit.Offset;
    unsigned FixitEnd = Fixit.Offset +  Fixit.Length;
    unsigned RemoveEnd = ByteOffset + RemoveLen;
    // If it intersects with the remove range, ignore the whole diagnostic.
    if (!(FixitEnd < ByteOffset || FixitBegin > RemoveEnd))
      return true; // Ignore.
    if (FixitBegin > FixitEnd)
      Fixit.Offset += Delta;
  }
  return false;
}

static bool
adjustDiagnosticBase(DiagnosticEntryInfoBase &Diag,
                     unsigned ByteOffset, unsigned RemoveLen, int Delta) {
  if (Diag.Offset >= ByteOffset && Diag.Offset < ByteOffset+RemoveLen)
    return true; // Ignore.
  bool Ignore = adjustDiagnosticRanges(Diag.Ranges, ByteOffset, RemoveLen, Delta);
  if (Ignore)
    return true;
  Ignore = adjustDiagnosticFixits(Diag.Fixits, ByteOffset, RemoveLen, Delta);
  if (Ignore)
    return true;
  if (Diag.Offset > ByteOffset)
    Diag.Offset += Delta;
  return false;
}

static bool
adjustDiagnostic(DiagnosticEntryInfo &Diag, StringRef Filename,
                 unsigned ByteOffset, unsigned RemoveLen, int Delta) {
  for (auto &Note : Diag.Notes) {
    if (Filename != Note.Filename)
      continue;
    bool Ignore = adjustDiagnosticBase(Note, ByteOffset, RemoveLen, Delta);
    if (Ignore)
      return true;
  }
  return adjustDiagnosticBase(Diag, ByteOffset, RemoveLen, Delta);
}

static std::vector<DiagnosticEntryInfo>
adjustDiagnostics(std::vector<DiagnosticEntryInfo> Diags, StringRef Filename,
                  unsigned ByteOffset, unsigned RemoveLen, int Delta) {
  std::vector<DiagnosticEntryInfo> NewDiags;
  NewDiags.reserve(Diags.size());

  for (auto &Diag : Diags) {
    bool Ignore = adjustDiagnostic(Diag, Filename, ByteOffset, RemoveLen, Delta);
    if (!Ignore) {
      NewDiags.push_back(std::move(Diag));
    }
  }

  return NewDiags;
}

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

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

  if (SemaDiags.empty())
    return SemaDiags;

  assert(DiagSnapshot && "If we have diagnostics, we must have snapshot!");

  if (!DiagSnapshot->precedesOrSame(NewSnapshot)) {
    // It may happen that other thread has already updated the diagnostics to
    // the version *after* NewSnapshot. This can happen in at least two cases:
    //   (a) two or more editor.open or editor.replacetext queries are being
    //       processed concurrently (not valid, but possible call pattern)
    //   (b) while editor.replacetext processing is running, a concurrent
    //       thread executes getBuffer()/getBufferForSnapshot() on the same
    //       Snapshot/EditableBuffer (thus creating a new ImmutableTextBuffer)
    //       and updates DiagSnapshot/SemaDiags
    assert(NewSnapshot->precedesOrSame(DiagSnapshot));

    // Since we cannot "adjust back" diagnostics, we just return an empty set.
    // FIXME: add handling of the case#b above
    return {};
  }

  SmallVector<unsigned, 16> ParserDiagLines;
  for (auto Diag : ParserDiags)
    ParserDiagLines.push_back(Diag.Line);
  std::sort(ParserDiagLines.begin(), ParserDiagLines.end());

  auto hasParserDiagAtLine = [&](unsigned Line) {
    return std::binary_search(ParserDiagLines.begin(), ParserDiagLines.end(),
                              Line);
  };

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

      unsigned ByteOffset = Upd->getByteOffset();
      unsigned RemoveLen = Upd->getLength();
      unsigned InsertLen = Upd->getText().size();
      int Delta = InsertLen - RemoveLen;
      SemaDiags = adjustDiagnostics(std::move(SemaDiags), Filename,
                                    ByteOffset, RemoveLen, Delta);
      return true;
    });

  if (!SemaDiags.empty()) {
    auto ImmBuf = NewSnapshot->getBuffer();
    for (auto &Diag : SemaDiags) {
      std::tie(Diag.Line, Diag.Column) = ImmBuf->getLineAndColumn(Diag.Offset);
    }

    // If there is a parser diagnostic in a line, ignore diagnostics in the same
    // line that we got from the semantic pass.
    // Note that the semantic pass also includes parser diagnostics so this
    // avoids duplicates.
    SemaDiags.erase(std::remove_if(SemaDiags.begin(), SemaDiags.end(),
                                   [&](const DiagnosticEntryInfo &Diag) -> bool {
                                     return hasParserDiagAtLine(Diag.Line);
                                   }),
                    SemaDiags.end());
  }

  DiagSnapshot = NewSnapshot;
  return SemaDiags;
}

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, Type T) override {
    if (isa<VarDecl>(D) && D->hasName() && D->getName().str() == "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,
                               bool IsOpenBracket) override {
    // We should treat both open and close brackets equally
    return visitDeclReference(D, Range, nullptr, Type());
  }

  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();

    trace::TracedOperation TracedOp;
    if (trace::enabled()) {
      trace::SwiftInvocation SwiftArgs;
      SemaInfoRef->getInvocation()->raw(SwiftArgs.Args.Args,
                                        SwiftArgs.Args.PrimaryFile);
      trace::initTraceFiles(SwiftArgs, CompIns);
      TracedOp.start(trace::OperationKind::AnnotAndDiag, SwiftArgs);
    }

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

    TracedOp.finish();

    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();
  ASTMgr.processASTAsync(Invok, std::move(Consumer), OncePerASTToken);
}


struct SwiftEditorDocument::CodeFormatOptions {
  bool UseTabs = false;
  unsigned IndentWidth = 4;
  unsigned TabWidth = 4;
};

struct SwiftEditorDocument::Implementation {
  SwiftLangSupport &LangSupport;
  const std::string FilePath;
  EditableTextBufferRef EditableBuffer;

  SwiftSyntaxMap SyntaxMap;
  SwiftEditorLineRange EditedLineRange;
  SwiftEditorCharRange AffectedRange;

  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)
    : LangSupport(LangSupport), FilePath(FilePath) {
    SemanticInfo = new SwiftDocumentSemanticInfo(FilePath, LangSupport);
  }

  void buildSwiftInv(trace::SwiftInvocation &Inv);
};

void SwiftEditorDocument::Implementation::buildSwiftInv(
                                                  trace::SwiftInvocation &Inv) {
  if (SemanticInfo->getInvocation()) {
    std::string PrimaryFile; // Ignored, FilePath will be used
    SemanticInfo->getInvocation()->raw(Inv.Args.Args, PrimaryFile);
  }
  Inv.Args.PrimaryFile = FilePath;
  auto &SM = SyntaxInfo->getSourceManager();
  auto ID = SyntaxInfo->getBufferID();
  auto Text = SM.getLLVMSourceMgr().getMemoryBuffer(ID)->getBuffer();
  Inv.Files.push_back(std::make_pair(FilePath, Text));
}

namespace  {

static UIdent getAccessibilityUID(Accessibility Access) {
  static UIdent AccessPublic("source.lang.swift.accessibility.public");
  static UIdent AccessInternal("source.lang.swift.accessibility.internal");
  static UIdent AccessPrivate("source.lang.swift.accessibility.private");

  switch (Access) {
  case Accessibility::Private:
    return AccessPrivate;
  case Accessibility::Internal:
    return AccessInternal;
  case Accessibility::Public:
    return AccessPublic;
  }
}

static Accessibility inferDefaultAccessibility(const ExtensionDecl *ED) {
  if (ED->hasDefaultAccessibility())
    return ED->getDefaultAccessibility();

  if (auto *AA = ED->getAttrs().getAttribute<AccessibilityAttr>())
    return AA->getAccess();

  // Assume "internal", which is the most common thing anyway.
  return Accessibility::Internal;
}

/// If typechecking was performed we use the computed accessibility, otherwise
/// we fallback to inferring accessibility syntactically. This may not be as
/// accurate but it's only until we have typechecked the AST.
static Accessibility inferAccessibility(const ValueDecl *D) {
  assert(D);
  if (D->hasAccessibility())
    return D->getFormalAccess();

  // Check if the decl has an explicit accessibility attribute.
  if (auto *AA = D->getAttrs().getAttribute<AccessibilityAttr>())
    return AA->getAccess();

  DeclContext *DC = D->getDeclContext();
  switch (DC->getContextKind()) {
  case DeclContextKind::SerializedLocal:
  case DeclContextKind::AbstractClosureExpr:
  case DeclContextKind::Initializer:
  case DeclContextKind::TopLevelCodeDecl:
  case DeclContextKind::AbstractFunctionDecl:
    return Accessibility::Private;
  case DeclContextKind::Module:
  case DeclContextKind::FileUnit:
    return Accessibility::Internal;
  case DeclContextKind::NominalTypeDecl: {
    auto Nominal = cast<NominalTypeDecl>(DC);
    Accessibility Access = inferAccessibility(Nominal);
    if (!isa<ProtocolDecl>(Nominal))
      Access = std::min(Access, Accessibility::Internal);
    return Access;
  }
  case DeclContextKind::ExtensionDecl:
    return inferDefaultAccessibility(cast<ExtensionDecl>(DC));
  }
}

static Optional<Accessibility>
inferSetterAccessibility(const AbstractStorageDecl *D) {
  if (auto *VD = dyn_cast<VarDecl>(D)) {
    if (VD->isLet())
      return None;
  }
  if (D->getGetter() && !D->getSetter())
    return None;

  // FIXME: Have the parser detect as read-only the syntactic form of generated
  // interfaces, which is "var foo : Int { get }"

  if (auto *AA = D->getAttrs().getAttribute<SetterAccessibilityAttr>())
    return AA->getAccess();
  else
    return inferAccessibility(D);
}

std::vector<UIdent> UIDsFromDeclAttributes(const DeclAttributes &Attrs) {
  std::vector<UIdent> AttrUIDs;

#define ATTR(X) \
  if (Attrs.has(AK_##X)) { \
    static UIdent Attr_##X("source.decl.attribute."#X); \
    AttrUIDs.push_back(Attr_##X); \
  }
#include "swift/AST/Attr.def"

  for (auto Attr : Attrs) {
    // Check special-case names first.
    switch (Attr->getKind()) {
    case DAK_IBAction: {
      static UIdent Attr_IBAction("source.decl.attribute.ibaction");
      AttrUIDs.push_back(Attr_IBAction);
      continue;
    }
    case DAK_IBOutlet: {
      static UIdent Attr_IBOutlet("source.decl.attribute.iboutlet");
      AttrUIDs.push_back(Attr_IBOutlet);
      continue;
    }
    case DAK_IBDesignable: {
      static UIdent Attr_IBDesignable("source.decl.attribute.ibdesignable");
      AttrUIDs.push_back(Attr_IBDesignable);
      continue;
    }
    case DAK_IBInspectable: {
      static UIdent Attr_IBInspectable("source.decl.attribute.ibinspectable");
      AttrUIDs.push_back(Attr_IBInspectable);
      continue;
    }
    case DAK_ObjC: {
      static UIdent Attr_Objc("source.decl.attribute.objc");
      static UIdent Attr_ObjcNamed("source.decl.attribute.objc.name");
      if (cast<ObjCAttr>(Attr)->hasName()) {
        AttrUIDs.push_back(Attr_ObjcNamed);
      } else {
        AttrUIDs.push_back(Attr_Objc);
      }
      continue;
    }

    // We handle accessibility explicitely.
    case DAK_Accessibility:
    case DAK_SetterAccessibility:
      continue;
    default:
      break;
    }

    switch (Attr->getKind()) {
    case DAK_Count:
      break;
#define DECL_ATTR(X, CLASS, ...)\
    case DAK_##CLASS: {\
      static UIdent Attr_##X("source.decl.attribute."#X); \
      AttrUIDs.push_back(Attr_##X); \
      break;\
    }
#include "swift/AST/Attr.def"
    }
  }

  return AttrUIDs;
}

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;
    }

    UIdent Kind = SwiftLangSupport::getUIDForSyntaxStructureKind(Node.Kind);
    UIdent AccessLevel;
    UIdent SetterAccessLevel;
    if (Node.Kind != SyntaxStructureKind::Parameter) {
      if (auto *VD = dyn_cast_or_null<ValueDecl>(Node.Dcl)) {
        AccessLevel = getAccessibilityUID(inferAccessibility(VD));
      }
      if (auto *ASD = dyn_cast_or_null<AbstractStorageDecl>(Node.Dcl)) {
        Optional<Accessibility> SetAccess = inferSetterAccessibility(ASD);
        if (SetAccess.hasValue()) {
          SetterAccessLevel = getAccessibilityUID(SetAccess.getValue());
        }
      }
    }

    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<UIdent> Attrs = UIDsFromDeclAttributes(Node.Attrs);

    Consumer.beginDocumentSubStructure(StartOffset, EndOffset - StartOffset,
                                       Kind, AccessLevel, SetterAccessLevel,
                                       NameStart, NameEnd - NameStart,
                                       BodyOffset, BodyEnd - BodyOffset,
                                       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)
      return StringRef();
    if (!isa<ClassDecl>(D) && !isa<ProtocolDecl>(D))
      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,
                                       StringRef(),
                                       StringRef(), StringRef(),
                                       StringRef(),
                                       {}, {});
    return true;
  }

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

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

class SwiftEditorSyntaxWalker: public ide::SyntaxModelWalker {
  SwiftSyntaxMap &SyntaxMap;
  SwiftEditorLineRange EditedLineRange;
  SwiftEditorCharRange &AffectedRange;
  SourceManager &SrcManager;
  EditorConsumer &Consumer;
  unsigned BufferID;
  SwiftDocumentStructureWalker DocStructureWalker;
  std::vector<EditorConsumerSyntaxMapEntry> ConsumerSyntaxMap;
  unsigned NestingLevel = 0;
public:
  SwiftEditorSyntaxWalker(SwiftSyntaxMap &SyntaxMap,
                          SwiftEditorLineRange EditedLineRange,
                          SwiftEditorCharRange &AffectedRange,
                          SourceManager &SrcManager, EditorConsumer &Consumer,
                          unsigned BufferID)
    : SyntaxMap(SyntaxMap), EditedLineRange(EditedLineRange),
      AffectedRange(AffectedRange), SrcManager(SrcManager), Consumer(Consumer),
      BufferID(BufferID),
      DocStructureWalker(SrcManager, BufferID, Consumer) { }

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

    ++NestingLevel;
    SourceLoc StartLoc = Node.Range.getStart();
    auto StartLineAndColumn = SrcManager.getLineAndColumn(StartLoc);
    auto EndLineAndColumn = SrcManager.getLineAndColumn(Node.Range.getEnd());
    unsigned StartLine = StartLineAndColumn.first;
    unsigned EndLine = EndLineAndColumn.second > 1 ? EndLineAndColumn.first
                                                   : EndLineAndColumn.first - 1;
    unsigned Offset = SrcManager.getByteDistance(
                           SrcManager.getLocForBufferStart(BufferID), StartLoc);
    // Note that the length can span multiple lines.
    unsigned Length = Node.Range.getByteLength();

    SwiftSyntaxToken Token(StartLineAndColumn.second, Length,
                           Node.Kind);
    if (EditedLineRange.isValid()) {
      if (StartLine < EditedLineRange.startLine()) {
        if (EndLine < EditedLineRange.startLine()) {
          // We're entirely before the edited range, no update needed.
          return true;
        }

        // This token starts before the edited range, but doesn't end before it,
        // we need to adjust edited line range and clear the affected syntax map
        // line range.
        unsigned AdjLineCount = EditedLineRange.startLine() - StartLine;
        EditedLineRange.setRange(StartLine, AdjLineCount
                                            + EditedLineRange.lineCount());
        SyntaxMap.clearLineRange(StartLine, AdjLineCount);

        // Also adjust the affected char range accordingly.
        unsigned AdjCharCount = AffectedRange.first - Offset;
        AffectedRange.first -= AdjCharCount;
        AffectedRange.second += AdjCharCount;
      }
      else if (Offset > AffectedRange.first + AffectedRange.second) {
        // We're passed the affected range and already synced up, just return.
        return true;
      }
      else if (StartLine > EditedLineRange.endLine()) {
        // We're after the edited line range, let's test if we're synced up.
        if (SyntaxMap.matchesFirstTokenOnLine(StartLine, Token)) {
          // We're synced up, mark the affected range and return.
          AffectedRange.second =
                 Offset - (StartLineAndColumn.second - 1) - AffectedRange.first;
          return true;
        }

        // We're not synced up, continue replacing syntax map data on this line.
        SyntaxMap.clearLineRange(StartLine, 1);
        EditedLineRange.extendToIncludeLine(StartLine);
      }

      if (EndLine > StartLine) {
        // The token spans multiple lines, make sure to replace syntax map data
        // for affected lines.
        EditedLineRange.extendToIncludeLine(EndLine);

        unsigned LineCount = EndLine - StartLine + 1;
        SyntaxMap.clearLineRange(StartLine, LineCount);
      }

    }

    // Add the syntax map token.
    if (NestingLevel > 1)
      SyntaxMap.mergeTokenForLine(StartLine, Token);
    else
      SyntaxMap.addTokenForLine(StartLine, Token);

    // Add consumer entry.
    unsigned ByteOffset = SrcManager.getLocOffsetInBuffer(Node.Range.getStart(),
                                                          BufferID);
    UIdent Kind = SwiftLangSupport::getUIDForSyntaxNodeKind(Node.Kind);
    if (NestingLevel > 1) {
      assert(!ConsumerSyntaxMap.empty());
      auto &Last = ConsumerSyntaxMap.back();
      mergeSplitRanges(Last.Offset, Last.Length, ByteOffset, Length,
                       [&](unsigned BeforeOff, unsigned BeforeLen,
                           unsigned AfterOff, unsigned AfterLen) {
        auto LastKind = Last.Kind;
        ConsumerSyntaxMap.pop_back();
        if (BeforeLen)
          ConsumerSyntaxMap.emplace_back(BeforeOff, BeforeLen, LastKind);
        ConsumerSyntaxMap.emplace_back(ByteOffset, Length, Kind);
        if (AfterLen)
          ConsumerSyntaxMap.emplace_back(AfterOff, AfterLen, LastKind);
      });
    }
    else
      ConsumerSyntaxMap.emplace_back(ByteOffset, Length, Kind);

    return true;
  }

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

    if (--NestingLevel == 0) {
      // We've unwound to the top level, so inform the consumer and drain
      // the consumer syntax map queue.
      for (auto &Entry: ConsumerSyntaxMap)
        Consumer.handleSyntaxMap(Entry.Offset, Entry.Length, Entry.Kind);
      ConsumerSyntaxMap.clear();
    }

    return true;
  }

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

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

};

typedef llvm::SmallString<64> StringBuilder;

static SourceLoc getVarDeclInitEnd(VarDecl *VD) {
  return VD->getBracesRange().isValid() ? VD->getBracesRange().End :
           VD->getParentInitializer() &&
           VD->getParentInitializer()->getEndLoc().isValid() ?
             VD->getParentInitializer()->getEndLoc() :
             SourceLoc();
}

class FormatContext
{
  SourceManager &SM;
  std::vector<swift::ASTWalker::ParentTy>& Stack;
  std::vector<swift::ASTWalker::ParentTy>::reverse_iterator Cursor;
  swift::ASTWalker::ParentTy Start;
  swift::ASTWalker::ParentTy End;
  bool InDocCommentBlock;
  bool InCommentLine;
  SourceLoc SiblingLoc;

public:
  FormatContext(SourceManager &SM,
                std::vector<swift::ASTWalker::ParentTy>& Stack,
                swift::ASTWalker::ParentTy Start = swift::ASTWalker::ParentTy(),
                swift::ASTWalker::ParentTy End = swift::ASTWalker::ParentTy(),
                bool InDocCommentBlock = false,
                bool InCommentLine = false,
                SourceLoc SiblingLoc = SourceLoc())
    :SM(SM), Stack(Stack), Cursor(Stack.rbegin()), Start(Start), End(End),
     InDocCommentBlock(InDocCommentBlock), InCommentLine(InCommentLine),
     SiblingLoc(SiblingLoc) { }

  FormatContext parent() {
    assert(Cursor != Stack.rend());
    FormatContext Parent(*this);
    ++Parent.Cursor;
    return Parent;
  }

  bool IsInDocCommentBlock() {
    return InDocCommentBlock;
  }

  bool IsInCommentLine() {
    return InCommentLine;
  }

  void padToSiblingColumn(StringBuilder &Builder) {
    assert(SiblingLoc.isValid() && "No sibling to align with.");
    CharSourceRange Range(SM, Lexer::getLocForStartOfLine(SM, SiblingLoc),
                          SiblingLoc);
    for (auto C : Range.str()) {
      Builder.append(1, C == '\t' ? C : ' ');
    }
  }

  bool HasSibling() {
    return SiblingLoc.isValid();
  }

  std::pair<unsigned, unsigned> lineAndColumn() {
    if (Cursor == Stack.rend())
      return std::make_pair(0, 0);

    if (Stmt *S = Cursor->getAsStmt()) {
      SourceLoc SL = S->getStartLoc();
      return SM.getLineAndColumn(SL);
    }
    if (Decl *D = Cursor->getAsDecl()) {
      SourceLoc SL = D->getStartLoc();

      // FIXME: put the attributes into forward source order so we don't need
      // to iterate through them.
      for (auto *Attr : D->getAttrs()) {
        SourceLoc AttrLoc = Attr->getRangeWithAt().Start;
        if (AttrLoc.isValid() && SM.isBeforeInBuffer(AttrLoc, SL))
            SL = AttrLoc;
      }

      return SM.getLineAndColumn(SL);
    }
    if (Expr *E = Cursor->getAsExpr()) {
      SourceLoc SL = E->getStartLoc();
      return SM.getLineAndColumn(SL);
    }

    return std::make_pair(0, 0);
  }

  template <class T>
  bool isStmtContext() {
    if (Cursor == Stack.rend())
      return false;
    Stmt *ContextStmt = Cursor->getAsStmt();
    return ContextStmt && isa<T>(ContextStmt);
  }

  bool isBraceContext() {
    return isStmtContext<BraceStmt>();
  }

  bool isImplicitBraceContext() {
    // If we're directly at the top, it's implicit.
    if (Cursor == Stack.rend())
      return true;

    if (!isBraceContext())
      return false;
    auto Parent = parent();
    // If the parent is directly at the top, it's implicit.
    if (Parent.Cursor == Stack.rend())
      return true;

    // If we're within a case body, it's implicit.
    // For example:
    // case ...:
    //     case body is implicitly wrapped in a brace statement
    if (Parent.isCaseContext())
      return true;

    return false;
  }

  bool isCaseContext() {
    return isStmtContext<CaseStmt>();
  }

  bool isSwitchContext() {
    return isStmtContext<SwitchStmt>();
  }

  std::pair<unsigned, unsigned> indentLineAndColumn() {
    if (Cursor == Stack.rend())
      return std::make_pair(0, 0);

    // Get the line and indent position for this context.
    auto LineAndColumn = lineAndColumn();
    auto SavedCursor = Cursor;

    // Walk up the context stack to find the topmost applicable context.
    while (++Cursor != Stack.rend()) {
      auto ParentLineAndColumn = lineAndColumn();

      if (ParentLineAndColumn.second == 0)
        break;

      if (ParentLineAndColumn.first != LineAndColumn.first) {
        // The start line is not the same, see if this is at the 'else' clause.
        if (IfStmt *If = dyn_cast_or_null<IfStmt>(Cursor->getAsStmt())) {
          SourceLoc ElseLoc = If->getElseLoc();
          // If we're at 'else', take the indent of 'if' and continue.
          if (ElseLoc.isValid() &&
              LineAndColumn.first == SM.getLineAndColumn(ElseLoc).first) {
            LineAndColumn = ParentLineAndColumn;
            continue;
          }
          // If we are at conditions, take the indent of 'if' and continue.
          for (auto Cond : If->getCond()) {
            if (LineAndColumn.first == SM.getLineNumber(Cond.getEndLoc())) {
              LineAndColumn = ParentLineAndColumn;
              continue;
            }
          }
        }

        // No extra indentation level for getters without explicit names.
        // e.g.
        // public var someValue: Int {
        //   return 0; <- No indentation added because of the getter.
        // }
        if (auto VD = dyn_cast_or_null<VarDecl>(Cursor->getAsDecl())) {
          if (auto Getter = VD->getGetter()) {
            if (Getter->getAccessorKeywordLoc().isInvalid()) {
              LineAndColumn = ParentLineAndColumn;
              continue;
            }
          }
        }

        // Align with Func start instead of with param decls.
        if (auto *FD = dyn_cast_or_null<AbstractFunctionDecl>(Cursor->getAsDecl())) {
          if (LineAndColumn.first <= SM.getLineNumber(FD->getSignatureSourceRange().End)) {
            LineAndColumn = ParentLineAndColumn;
            continue;
          }
        }

        // Break out if the line is no longer the same.
        break;
      }

      LineAndColumn.second = ParentLineAndColumn.second;
    }

    Cursor = SavedCursor;
    return LineAndColumn;
  }

  bool shouldAddIndentForLine(unsigned Line) {
    if (Cursor == Stack.rend())
      return false;

    // Handle switch / case, indent unless at a case label.
    if (CaseStmt *Case = dyn_cast_or_null<CaseStmt>(Cursor->getAsStmt())) {
      auto LabelItems = Case->getCaseLabelItems();
      SourceLoc Loc;
      if (!LabelItems.empty())
        Loc = LabelItems.back().getPattern()->getLoc();
      if (Loc.isValid())
        return Line > SM.getLineAndColumn(Loc).first;
      return true;
    }
    if (isSwitchContext()) {
      // If we're at the start of a case label, don't add indent.
      // For example:
      // switch ... {
      // case xyz: <-- No indent here, should be at same level as switch.
      Stmt *AtStmtStart = Start.getAsStmt();
      if (AtStmtStart && isa<CaseStmt>(AtStmtStart))
        return false;

      // If we're at the open brace of the switch, don't add an indent.
      // For example:
      // switch ...
      // { <-- No indent here, open brace should be at same level as switch.
      auto *S = cast<SwitchStmt>(Cursor->getAsStmt());
      if (SM.getLineAndColumn(S->getLBraceLoc()).first == Line)
        return false;
      if(IsInCommentLine()) {
        for (auto Case : S->getCases()) {
          // switch ...
          // {
          // // case comment <-- No indent here.
          // case 0:
          if (SM.getLineAndColumn(Case->swift::Stmt::getStartLoc()).first == Line + 1)
            return false;
        }
      }
    }

    // If we're within an implicit brace context, don't add indent.
    if (isImplicitBraceContext())
      return false;

    // If we're at the open brace of a no-name getter, don't add an indent.
    // For example:
    //  public var someValue: Int
    //  { <- We add no indentation here.
    //    return 0
    //  }
    if (auto FD = dyn_cast_or_null<FuncDecl>(Start.getAsDecl())) {
      if(FD->isGetter() && FD->getAccessorKeywordLoc().isInvalid()) {
        if(SM.getLineNumber(FD->getBody()->getLBraceLoc()) == Line)
          return false;
      }
    }

    // If we're at the beginning of a brace on a separate line in the context
    // of anything other than BraceStmt, don't add an indent.
    // For example:
    // func foo()
    // { <-- No indent here, open brace should be at same level as func.
    Stmt *AtStmtStart = Start.getAsStmt();
    if (AtStmtStart && isa<BraceStmt>(AtStmtStart) && !isBraceContext())
      return false;

    // If we're at the end of a brace on a separate line in the context
    // of anything other than BraceStmt, don't add an indent.
    // For example:
    if (Stmt *AtStmtEnd = End.getAsStmt()) {
      if (!isBraceContext()) {
        // func foo() {
        // } <-- No indent here, close brace should be at same level as func.
        if (isa<BraceStmt>(AtStmtEnd))
          return false;
        // do {
        // }
        // catch {
        // } <-- No indent here, close brace should be at same level as do.
        // catch {
        // }
        if (isa<CatchStmt>(AtStmtEnd))
          return false;
      }
    }

    // If we're at the open brace of a NominalTypeDecl or ExtensionDecl,
    // don't add an indent.
    // For example:
    // class Foo
    // { <-- No indent here, open brace should be at same level as class.
    auto *NTD = dyn_cast_or_null<NominalTypeDecl>(Cursor->getAsDecl());
    if (NTD && SM.getLineAndColumn(NTD->getBraces().Start).first == Line)
      return false;
    auto *ETD = dyn_cast_or_null<ExtensionDecl>(Cursor->getAsDecl());
    if (ETD && SM.getLineAndColumn(ETD->getBraces().Start).first == Line)
      return false;

    // If we are at the start of a trailing closure, do not add indentation.
    // For example:
    // foo(1)
    // { <-- No indent here.
    auto *TE = dyn_cast_or_null<TupleExpr>(Cursor->getAsExpr());
    if (TE && TE->hasTrailingClosure() &&
        SM.getLineNumber(TE->getElements().back()->getStartLoc()) == Line) {
      return false;
    }

    // If we're in an IfStmt and at the 'else', don't add an indent.
    IfStmt *If = dyn_cast_or_null<IfStmt>(Cursor->getAsStmt());
    if (If && If->getElseLoc().isValid() &&
        SM.getLineAndColumn(If->getElseLoc()).first == Line)
      return false;

    // If we're in an DoCatchStmt and at a 'catch', don't add an indent.
    if (auto *DoCatchS = dyn_cast_or_null<DoCatchStmt>(Cursor->getAsStmt())) {
      for (CatchStmt *CatchS : DoCatchS->getCatches()) {
        SourceLoc Loc = CatchS->getCatchLoc();
        if (Loc.isValid() && SM.getLineAndColumn(Loc).first == Line)
          return false;
      }
    }

    // If we're at the end of a closure, paren or tuple expr, and the context
    // is a paren/tuple expr ending with that sub expression, and it ends on the
    // same line, don't add an indent.
    // For example:
    // foo(x, {
    // }) <-- No indent here, the paren expr for the call ends on the same line.
    Expr *AtExprEnd = End.getAsExpr();
    if (AtExprEnd && (isa<ClosureExpr>(AtExprEnd) ||
                      isa<ParenExpr>(AtExprEnd) ||
                      isa<TupleExpr>(AtExprEnd))) {

      if (auto *Paren = dyn_cast_or_null<ParenExpr>(Cursor->getAsExpr())) {
        auto *SubExpr = Paren->getSubExpr();
        if (SubExpr && SubExpr == AtExprEnd &&
            SM.getLineAndColumn(Paren->getEndLoc()).first == Line)
          return false;
      }
      else if (auto *Tuple = dyn_cast_or_null<TupleExpr>(Cursor->getAsExpr())) {
        auto SubExprs = Tuple->getElements();
        if (!SubExprs.empty() && SubExprs.back() == AtExprEnd &&
            SM.getLineAndColumn(Tuple->getEndLoc()).first == Line) {
          return false;
        }
      } else if (auto *VD = dyn_cast_or_null<VarDecl>(Cursor->getAsDecl())) {
        SourceLoc Loc = getVarDeclInitEnd(VD);
        if (Loc.isValid() && SM.getLineNumber(Loc) == Line) {
          return false;
        }
      }
    }

    // Indent another level from the outer context by default.
    return true;
  }
};

class FormatWalker: public ide::SourceEntityWalker {
  typedef std::vector<Token>::iterator TokenIt;
  class SiblingCollector {
    SourceLoc FoundSibling;
    SourceManager &SM;
    std::vector<Token> &Tokens;
    SourceLoc &TargetLoc;
    TokenIt TI;

    bool isImmediateAfterSeparator(SourceLoc End, tok Seperator) {
      auto BeforeE = [&]() {
        return TI != Tokens.end() &&
               !SM.isBeforeInBuffer(End, TI->getLoc());
      };
      if (!BeforeE())
        return false;
      for (; BeforeE(); TI ++);
      if (TI == Tokens.end() || TI->getKind() != Seperator)
        return false;
      auto SeparatorLoc = TI->getLoc();
      TI ++;
      if (TI == Tokens.end())
        return false;
      auto NextLoc = TI->getLoc();
      return SM.isBeforeInBuffer(SeparatorLoc, TargetLoc) &&
            !SM.isBeforeInBuffer(NextLoc, TargetLoc);
    }

  public:
    SiblingCollector(SourceManager &SM, std::vector<Token> &Tokens,
                     SourceLoc &TargetLoc) : SM(SM), Tokens(Tokens),
                      TargetLoc(TargetLoc), TI(Tokens.begin()) {}
    void collect(ASTNode Node) {
      if (FoundSibling.isValid())
        return;
      SourceLoc PrevLoc;
      auto FindAlignLoc = [&](SourceLoc Loc) {
        if (PrevLoc.isValid() &&
            SM.getLineNumber(PrevLoc) == SM.getLineNumber(Loc))
          return PrevLoc;
        return PrevLoc = Loc;
      };

      auto addPair = [&](SourceLoc EndLoc, SourceLoc AlignLoc, tok Separator) {
        if (isImmediateAfterSeparator(EndLoc, Separator))
          FoundSibling = AlignLoc;
      };

      if (auto AE = dyn_cast_or_null<ApplyExpr>(Node.dyn_cast<Expr *>())) {
        collect(AE->getArg());
        return;
      }

      if (auto PE = dyn_cast_or_null<ParenExpr>(Node.dyn_cast<Expr *>())) {
        if (auto Sub = PE->getSubExpr()) {
          addPair(Sub->getEndLoc(), FindAlignLoc(Sub->getStartLoc()),
                  tok::comma);
        }
      }

      // Tuple elements are siblings.
      if (auto TE = dyn_cast_or_null<TupleExpr>(Node.dyn_cast<Expr *>())) {
        // Trailing closures are not considered siblings to other args.
        unsigned EndAdjust = TE->hasTrailingClosure() ? 1 : 0;
        for (unsigned I = 0, N = TE->getNumElements() - EndAdjust; I < N; I ++) {
          addPair(TE->getElement(I)->getEndLoc(),
                  FindAlignLoc(TE->getElement(I)->getStartLoc()), tok::comma);
        }
      }

      if (auto AFD = dyn_cast_or_null<AbstractFunctionDecl>(Node.dyn_cast<Decl*>())) {

        // Generic type params are siblings to align.
        if (auto GPL = AFD->getGenericParams()) {
          const auto Params = GPL->getParams();
          for (unsigned I = 0, N = Params.size(); I < N; I ++) {
            addPair(Params[I]->getEndLoc(), FindAlignLoc(Params[I]->getStartLoc()),
                    tok::comma);
          }
        }

        // Function parameters are siblings.
        for (auto P : AFD->getBodyParamPatterns()) {
          if (auto TU = dyn_cast<TuplePattern>(P)) {
            for (unsigned I = 0, N = TU->getNumElements(); I < N; I ++) {
              addPair(TU->getElement(I).getPattern()->getEndLoc(),
                      FindAlignLoc(TU->getElement(I).getLabelLoc()), tok::comma);
            }
          }
        }
      }

      // Array/Dictionary elements are siblings to align with each other.
      if (auto AE = dyn_cast_or_null<CollectionExpr>(Node.dyn_cast<Expr *>())) {
        for (unsigned I = 0, N = AE->getNumElements(); I < N;  I ++) {
          addPair(AE->getElement(I)->getEndLoc(),
                  FindAlignLoc(AE->getElement(I)->getStartLoc()), tok::comma);
        }
      }
    };

    SourceLoc findSibling() {
      return FoundSibling;
    }
  };

  SourceFile &SF;
  SourceManager &SM;
  SourceLoc TargetLocation;
  std::vector<swift::ASTWalker::ParentTy> Stack;
  swift::ASTWalker::ParentTy AtStart;
  swift::ASTWalker::ParentTy AtEnd;
  bool InDocCommentBlock = false;
  bool InCommentLine = false;
  std::vector<Token> Tokens;
  LangOptions Options;
  TokenIt CurrentTokIt;
  unsigned TargetLine;
  SiblingCollector SCollector;

  /// Sometimes, target is a part of "parent", for instance, "#else" is a part
  /// of an ifconfigstmt, so that ifconfigstmt is not really the parent of "#else".
  bool isTargetPartOf(swift::ASTWalker::ParentTy Parent) {
    if(auto Conf = dyn_cast_or_null<IfConfigStmt>(Parent.getAsStmt())) {
      for (auto Clause : Conf->getClauses()) {
        if (Clause.Loc == TargetLocation)
          return true;
      }
    } else if (auto Call = dyn_cast_or_null<CallExpr>(Parent.getAsExpr())) {
      if(auto Clo = dyn_cast<ClosureExpr>(Call->getFn())) {
        if (Clo->getBody()->getLBraceLoc() == TargetLocation ||
            Clo->getBody()->getRBraceLoc() == TargetLocation) {
          return true;
        }
      }
    }
    return false;
  }

  template <class T>
  bool HandlePre(T* Node, SourceLoc Start, SourceLoc End) {
    scanForComments(Start);
    SCollector.collect(Node);

    if (SM.isBeforeInBuffer(TargetLocation, Start))
      return false; // Target is before start of Node, skip it.
    if (SM.isBeforeInBuffer(End, TargetLocation))
      return false; // Target is after end of Node, skip it.
    if (TargetLocation == Start) {
      // Target is right at the start of Node, mark it.
      AtStart = Node;
      return false;
    }
    if (TargetLocation == End) {
      // Target is right at the end of Node, mark it.
      AtEnd = Node;
      return false;
    }

    // Target is within Node and Node is really the parent of Target, take it.
    if (!isTargetPartOf(Node))
      Stack.push_back(Node);
    return true;
  }

  void scanForComments(SourceLoc Loc) {
    if (InDocCommentBlock || InCommentLine)
      return;
    for (auto InValid = Loc.isInvalid(); CurrentTokIt != Tokens.end() &&
         (InValid || SM.isBeforeInBuffer(CurrentTokIt->getLoc(), Loc));
         CurrentTokIt ++) {
      if (CurrentTokIt->getKind() == tok::comment) {
        auto StartLine = SM.getLineNumber(CurrentTokIt->getRange().getStart());
        auto EndLine = SM.getLineNumber(CurrentTokIt->getRange().getEnd());
        auto TokenStr = CurrentTokIt->getRange().str();
        InDocCommentBlock |= TargetLine > StartLine && TargetLine <= EndLine &&
                             TokenStr.startswith("/*");
        InCommentLine |= StartLine == TargetLine && TokenStr.startswith("//");
      }
    }
  }

  template <typename T>
  bool HandlePost(T* Node) {
    if (SM.isBeforeInBuffer(TargetLocation, Node->getStartLoc()))
      return false; // Target is before start of Node, terminate walking.

    return true;
  }

public:
  explicit FormatWalker(SourceFile &SF, SourceManager &SM)
    :SF(SF), SM(SM),
     Tokens(tokenize(Options, SM, SF.getBufferID().getValue())),
     CurrentTokIt(Tokens.begin()),
     SCollector(SM, Tokens, TargetLocation) {}

  FormatContext walkToLocation(SourceLoc Loc) {
    Stack.clear();
    TargetLocation = Loc;
    TargetLine = SM.getLineNumber(TargetLocation);
    AtStart = AtEnd = swift::ASTWalker::ParentTy();
    walk(SF);
    scanForComments(SourceLoc());
    return FormatContext(SM, Stack, AtStart, AtEnd, InDocCommentBlock,
                         InCommentLine, SCollector.findSibling());
  }

  bool walkToDeclPre(Decl *D, CharSourceRange Range) override {
    SourceLoc Start = D->getStartLoc();
    SourceLoc End = D->getEndLoc();

    if (auto *VD = dyn_cast<VarDecl>(D)) {
      // We'll treat properties with accessors as spanning the braces as well.
      // This will ensure we can do indentation inside the braces.
      auto Loc = getVarDeclInitEnd(VD);
      End = Loc.isValid() ? Loc : End;
    }

    return HandlePre(D, Start, End);
  }

  bool walkToDeclPost(Decl *D) override {
    return HandlePost(D);
  }

  bool walkToStmtPre(Stmt *S) override {
    return HandlePre(S, S->getStartLoc(), S->getEndLoc());
  }

  bool walkToStmtPost(Stmt *S) override {
    return HandlePost(S);
  }

  bool walkToExprPre(Expr *E) override {
    return HandlePre(E, E->getStartLoc(), E->getEndLoc());
  }

  bool walkToExprPost(Expr *E) override {
    return HandlePost(E);
  }

  bool shouldWalkInactiveConfigRegion() override {
    return true;
  }
};

class CodeFormatter {
  SwiftEditorDocument &Doc;
  EditorConsumer &Consumer;
public:
  CodeFormatter(SwiftEditorDocument &Doc, EditorConsumer& Consumer)
    :Doc(Doc), Consumer(Consumer) { }

  SwiftEditorLineRange indent(unsigned LineIndex, FormatContext &FC) {
    auto &FmtOptions = Doc.getFormatOptions();

    // If having sibling locs to align with, respect siblings.
    if (FC.HasSibling()) {
      StringRef Line = Doc.getTrimmedTextForLine(LineIndex);
      StringBuilder Builder;
      FC.padToSiblingColumn(Builder);
      Builder.append(Line);
      Consumer.recordFormattedText(Builder.str().str());
      return SwiftEditorLineRange(LineIndex, 1);
    }

    // Take the current indent position of the outer context, then add another
    // indent level if expected.
    auto LineAndColumn = FC.indentLineAndColumn();
    size_t ExpandedIndent = Doc.getExpandedIndentForLine(LineAndColumn.first);
    auto AddIndentFunc = [&] () {
      auto Width = FmtOptions.UseTabs ? FmtOptions.TabWidth
                                      : FmtOptions.IndentWidth;
      // Increment indent.
      ExpandedIndent += Width;
      // Normalize indent to align on proper column indent width.
      ExpandedIndent -= ExpandedIndent % Width;
    };

    if (LineAndColumn.second > 0 && FC.shouldAddIndentForLine(LineIndex))
      AddIndentFunc();
    if (FC.IsInDocCommentBlock()) {

      // Inside doc comment block, the indent is one space, e.g.
      // /**
      //  * <---Indent to align with the first star.
      //  */
      ExpandedIndent += 1;
    }

    // Reformat the specified line with the calculated indent.
    StringRef Line = Doc.getTrimmedTextForLine(LineIndex);
    std::string IndentedLine;
    if (FmtOptions.UseTabs)
      IndentedLine.assign(ExpandedIndent / FmtOptions.TabWidth, '\t');
    else
      IndentedLine.assign(ExpandedIndent, ' ');
    IndentedLine.append(Line);

    Consumer.recordFormattedText(IndentedLine);

    // Return affected line range, which can later be more than one line.
    return SwiftEditorLineRange(LineIndex, 1);
  }

};

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

private:
  SourceManager &SM;
  std::vector<Param> Params;
  CharSourceRange ReturnTypeRange;
  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 };
    }
  };

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

    class ClosureTypeWalker: public ASTWalker {
    public:
      PlaceholderExpansionScanner &S;
      bool FoundFunctionTypeRepr = false;
      explicit ClosureTypeWalker(PlaceholderExpansionScanner &S)
        :S(S) { }

      bool walkToTypeReprPre(TypeRepr *T) override {
        if (auto *FTR = dyn_cast<FunctionTypeRepr>(T)) {
          FoundFunctionTypeRepr = true;
          if (auto *TTR = dyn_cast_or_null<TupleTypeRepr>(FTR->getArgsTypeRepr())) {
            for (auto *ArgTR : TTR->getElements()) {
              CharSourceRange NR;
              CharSourceRange TR;
              auto *NTR = dyn_cast<NamedTypeRepr>(ArgTR);
              if (NTR && NTR->hasName()) {
                NR = CharSourceRange(NTR->getNameLoc(),
                                     NTR->getName().getLength());
                ArgTR = NTR->getTypeRepr();
              }
              SourceLoc SRE = Lexer::getLocForEndOfToken(S.SM,
                                                         ArgTR->getEndLoc());
              TR = CharSourceRange(S.SM, ArgTR->getStartLoc(), SRE);
              S.Params.emplace_back(NR, TR);
            }
          } else if (FTR->getArgsTypeRepr()) {
            CharSourceRange TR;
            TR = CharSourceRange(S.SM, FTR->getArgsTypeRepr()->getStartLoc(),
                                 Lexer::getLocForEndOfToken(S.SM,
                                   FTR->getArgsTypeRepr()->getEndLoc()));
            S.Params.emplace_back(CharSourceRange(), TR);
          }
          if (auto *RTR = FTR->getResultTypeRepr()) {
            SourceLoc SRE = Lexer::getLocForEndOfToken(S.SM, RTR->getEndLoc());
            S.ReturnTypeRange = CharSourceRange(S.SM, RTR->getStartLoc(), SRE);
          }
        }
        return !FoundFunctionTypeRepr;
      }

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

    } PW(*this);

    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<CallExpr *, bool> enclosingCallExpr(SourceFile &SF, SourceLoc SL) {

    class CallExprFinder: public ide::SourceEntityWalker {
    public:
      const SourceManager &SM;
      SourceLoc TargetLoc;
      CallExpr *EnclosingCall;
      Expr *OuterExpr;
      Stmt *OuterStmt;
      explicit CallExprFinder(const SourceManager &SM)
        :SM(SM) { }

      bool walkToExprPre(Expr *E) override {
        auto SR = E->getSourceRange();
        if (SR.isValid() && SM.rangeContainsTokenLoc(SR, TargetLoc)) {
          if (auto *CE = dyn_cast<CallExpr>(E)) {
            if (EnclosingCall)
              OuterExpr = EnclosingCall;
            EnclosingCall = CE;
          }
          else if (!EnclosingCall)
            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(!EnclosingCall && !isa<BraceStmt>(S))
            OuterStmt = S;
        }
        return true;
      }

      CallExpr *findEnclosingCall(SourceFile &SF, SourceLoc SL) {
        EnclosingCall = nullptr;
        OuterExpr = nullptr;
        OuterStmt = nullptr;
        TargetLoc = SL;
        walk(SF);
        return EnclosingCall;
      }
    };

    CallExprFinder CEFinder(SM);
    auto *CE = CEFinder.findEnclosingCall(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);
  }

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;
    std::pair<CallExpr*, bool> ECE = enclosingCallExpr(SF, PlaceholderStartLoc);
    Expr *Args = ECE.first ? ECE.first->getArg() : nullptr;
    if (Args && ECE.second) {
      if (isa<ParenExpr>(Args)) {
        UseTrailingClosure = true;
      } else if (auto *TE = dyn_cast<TupleExpr>(Args)) {
        if (!TE->getElements().empty())
          UseTrailingClosure =
            TE->getElements().back()->getStartLoc() == PlaceholderStartLoc;
      }
    }

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

};


} // anonymous namespace

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

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

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

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

  Impl.EditableBuffer =
      new EditableTextBuffer(Impl.FilePath, Buf->getBuffer());
  Impl.SyntaxMap.reset();
  Impl.EditedLineRange.setRange(0,0);
  Impl.AffectedRange = std::make_pair(0, Buf->getBufferSize());
  Impl.SemanticInfo =
      new SwiftDocumentSemanticInfo(Impl.FilePath, Impl.LangSupport);
  Impl.SemanticInfo->setCompilerArgs(Args);
  return Impl.EditableBuffer->getSnapshot();
}

ImmutableTextSnapshotRef SwiftEditorDocument::replaceText(
    unsigned int Offset, unsigned int Length, llvm::MemoryBuffer *Buf,
    bool ProvideSemanticInfo) {

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

  llvm::StringRef Str = Buf->getBuffer();
  ImmutableTextSnapshotRef Snapshot =
      Impl.EditableBuffer->replace(Offset, Length, Str);

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

      if (auto Invok = Impl.SemanticInfo->getInvocation()) {
        // Update semantic info for open editor documents of the same module.
        // FIXME: Detect edits that don't affect other files, e.g. whitespace,
        // comments, inside a function body, etc.
        CompilerInvocation CI;
        Invok->applyTo(CI);
        auto &EditorDocs = Impl.LangSupport.getEditorDocuments();
        for (auto &Input : CI.getInputFilenames()) {
          if (auto EditorDoc = EditorDocs.findByPath(Input)) {
            if (EditorDoc.get() != this)
              EditorDoc->updateSemaInfo();
          }
        }
      }
    }
  }

  SourceManager &SrcManager = Impl.SyntaxInfo->getSourceManager();
  unsigned BufID = Impl.SyntaxInfo->getBufferID();
  SourceLoc StartLoc = SrcManager.getLocForBufferStart(BufID).getAdvancedLoc(
                                                                        Offset);
  unsigned StartLine = SrcManager.getLineAndColumn(StartLoc).first;
  unsigned EndLine = SrcManager.getLineAndColumn(
                                         StartLoc.getAdvancedLoc(Length)).first;

  // Delete all syntax map data from start line through end line.
  unsigned OldLineCount = EndLine - StartLine + 1;
  Impl.SyntaxMap.removeLineRange(StartLine, OldLineCount);

  // Insert empty syntax map data for replaced lines.
  unsigned NewLineCount = Str.count('\n') + 1;
  Impl.SyntaxMap.insertLineRange(StartLine, NewLineCount);

  // Update the edited line range.
  Impl.EditedLineRange.setRange(StartLine, NewLineCount);

  ImmutableTextBufferRef ImmBuf = Snapshot->getBuffer();

  // The affected range starts from the previous newline.
  if (Offset > 0) {
    auto AffectedRangeOffset = ImmBuf->getText().rfind('\n', Offset);
    Impl.AffectedRange.first =
      AffectedRangeOffset != StringRef::npos ? AffectedRangeOffset + 1 : 0;
  }
  else
    Impl.AffectedRange.first = 0;

  Impl.AffectedRange.second = ImmBuf->getText().size() - Impl.AffectedRange.first;

  return Snapshot;
}

void SwiftEditorDocument::updateSemaInfo() {
  if (auto SemaInfo = Impl.SemanticInfo) {
    Impl.SemanticInfo->processLatestSnapshotAsync(Impl.EditableBuffer);
  }
}

void SwiftEditorDocument::parse(ImmutableTextSnapshotRef Snapshot,
                                SwiftLangSupport &Lang) {
  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 {
    ArrayRef<const char *> Args;
    std::string Error;
    // Ignore possible error(s)
    Lang.getASTManager().
      initCompilerInvocation(CompInv, Args, StringRef(), Error);
  }

  // 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);

  trace::TracedOperation TracedOp;
  if (trace::enabled()) {
    trace::SwiftInvocation Info;
    Impl.buildSwiftInv(Info);
    TracedOp.start(trace::OperationKind::ReadSyntaxInfo, Info);
  }

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

  ide::SyntaxModelContext ModelContext(Impl.SyntaxInfo->getSourceFile());

  SwiftEditorSyntaxWalker SyntaxWalker(Impl.SyntaxMap,
                                       Impl.EditedLineRange,
                                       Impl.AffectedRange,
                                       Impl.SyntaxInfo->getSourceManager(),
                                       Consumer,
                                       Impl.SyntaxInfo->getBufferID());

  ModelContext.walk(SyntaxWalker);

  Consumer.recordAffectedRange(Impl.AffectedRange.first,
                               Impl.AffectedRange.second);
}

void SwiftEditorDocument::readSemanticInfo(ImmutableTextSnapshotRef Snapshot,
                                           EditorConsumer& Consumer) {
  trace::TracedOperation TracedOp;
  if (trace::enabled()) {
    trace::SwiftInvocation Info;
    Impl.buildSwiftInv(Info);
    TracedOp.start(trace::OperationKind::ReadSemanticInfo, Info);
  }

  std::vector<SwiftSemanticToken> SemaToks;
  std::vector<DiagnosticEntryInfo> SemaDiags;

  // FIXME: Parser diagnostics should be filtered out of the semantic ones,
  // Then just merge the semantic ones with the current parse ones.
  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.IsSystem;
    if (Kind.isValid())
      if (!Consumer.handleSemanticAnnotation(Offset, Length, Kind, IsSystem))
        break;
  }

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

  if (!SemaDiags.empty() || !SemaToks.empty()) {
    Consumer.setDiagnosticStage(SemaDiagStage);
  } else {
    Consumer.setDiagnosticStage(ParseDiagStage);
  }

  for (auto &Diag : Impl.ParserDiagnostics)
    Consumer.handleDiagnostic(Diag, ParseDiagStage);
  for (auto &Diag : SemaDiags)
    Consumer.handleDiagnostic(Diag, SemaDiagStage);
}

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
SwiftEditorDocument::CodeFormatOptions &SwiftEditorDocument::getFormatOptions() {
  return Impl.FormatOptions;
}

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

  trace::TracedOperation TracedOp;
  if (trace::enabled()) {
    trace::SwiftInvocation SwiftArgs;
    // Compiler arguments do not matter
    auto Buf = SM.getLLVMSourceMgr().getMemoryBuffer(BufID);
    SwiftArgs.Args.PrimaryFile = Buf->getBufferIdentifier();
    SwiftArgs.addFile(SwiftArgs.Args.PrimaryFile, Buf->getBuffer());
    trace::StringPairs OpArgs = {
      std::make_pair("Line", std::to_string(Line)),
      std::make_pair("Length", std::to_string(Length)),
      std::make_pair("IndentWidth",
                     std::to_string(Impl.FormatOptions.IndentWidth)),
      std::make_pair("TabWidth",
                     std::to_string(Impl.FormatOptions.TabWidth)),
      std::make_pair("UseTabs",
                     std::to_string(Impl.FormatOptions.UseTabs))};
    TracedOp.start(trace::OperationKind::FormatText, SwiftArgs, OpArgs);
  }

  FormatWalker walker(SF, SM);
  size_t Offset = getTrimmedLineOffset(Line);
  SourceLoc Loc = SM.getLocForBufferStart(BufID).getAdvancedLoc(Offset);
  FormatContext FC = walker.walkToLocation(Loc);
  CodeFormatter CF(*this, Consumer);
  SwiftEditorLineRange LineRange = CF.indent(Line, FC);

  Consumer.recordAffectedLineRange(LineRange.startLine(), LineRange.lineCount());
}

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;
  }

  trace::TracedOperation TracedOp;
  if (trace::enabled()) {
    trace::SwiftInvocation SwiftArgs;
    SyntaxInfo->initArgsAndPrimaryFile(SwiftArgs);
    auto Buf = SM.getLLVMSourceMgr().getMemoryBuffer(BufID);
    SwiftArgs.addFile(Buf->getBufferIdentifier(), Buf->getBuffer());
    trace::StringPairs OpArgs = {
      std::make_pair("Offset", std::to_string(Offset)),
      std::make_pair("Length", std::to_string(Length))};
    TracedOp.start(trace::OperationKind::ExpandPlaceholder, SwiftArgs, OpArgs);
  }

  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 preceeding 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 = ClosureReturnTypeRange.isValid() &&
                             "Void" == SM.extractText(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<#code#>\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;
    });
}

size_t SwiftEditorDocument::getLineOffset(unsigned LineIndex) {
  StringRef Text = Impl.EditableBuffer->getBuffer()->getText();
  // FIXME: We should have a cached line map in EditableTextBuffer, for now
  // we just do the slow naive thing here.
  size_t LineOffset = 0;
  unsigned CurrentLine = 0;
  while (LineOffset < Text.size() && ++CurrentLine < LineIndex) {
    LineOffset = Text.find_first_of("\r\n", LineOffset);
    if (LineOffset != std::string::npos) {
      ++LineOffset;
      if (LineOffset < Text.size() &&
          Text[LineOffset - 1] == '\r' && Text[LineOffset] == '\n')
        ++LineOffset;
    }

  }
  if (LineOffset == std::string::npos)
    LineOffset = 0;
  return LineOffset;
}

size_t SwiftEditorDocument::getTrimmedLineOffset(unsigned LineIndex) {
  size_t LineOffset = getLineOffset(LineIndex);

  // Skip leading whitespace.
  StringRef Text = Impl.EditableBuffer->getBuffer()->getText();
  size_t FirstNonWSOnLine = Text.find_first_not_of(" \t\v\f", LineOffset);
  if (FirstNonWSOnLine != std::string::npos)
    LineOffset = FirstNonWSOnLine;
  
  return LineOffset;
}

size_t SwiftEditorDocument::getExpandedIndentForLine(unsigned LineIndex) {
  size_t LineOffset = getLineOffset(LineIndex);

  // Tab-expand all leading whitespace
  StringRef Text = Impl.EditableBuffer->getBuffer()->getText();
  size_t FirstNonWSOnLine = Text.find_first_not_of(" \t\v\f", LineOffset);
  size_t Indent = 0;
  while (LineOffset < Text.size() && LineOffset < FirstNonWSOnLine) {
    if (Text[LineOffset++] == '\t')
      Indent += Impl.FormatOptions.TabWidth;
    else
      Indent += 1;
  }
  return Indent;
}

StringRef SwiftEditorDocument::getTrimmedTextForLine(unsigned LineIndex) {
  StringRef Text = Impl.EditableBuffer->getBuffer()->getText();
  size_t LineOffset = getTrimmedLineOffset(LineIndex);
  size_t LineEnd = Text.find_first_of("\r\n", LineOffset);
  return Text.slice(LineOffset, LineEnd);
}

ImmutableTextSnapshotRef SwiftEditorDocument::getLatestSnapshot() const {
  return Impl.EditableBuffer->getSnapshot();
}

void SwiftEditorDocument::reportDocumentStructure(swift::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,
                                  bool EnableSyntaxMap,
                                  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);
    EditorDoc->parse(Snapshot, *this);
    if (EditorDocuments.getOrUpdate(Name, *this, EditorDoc)) {
      // Document already exists, re-initialize it. This should only happen
      // if we get OPEN request while the prevous document is not closed.
      LOG_WARN_FUNC("Document already exists in editorOpen(..): " << Name);
      Snapshot = nullptr;
    }
  }

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

  if (Consumer.needsSemanticInfo()) {
    EditorDoc->updateSemaInfo();
  }
  
  EditorDoc->readSyntaxInfo(Consumer);
  EditorDoc->readSemanticInfo(Snapshot, Consumer);
}


//============================================================================//
// EditorClose
//============================================================================//

void SwiftLangSupport::editorClose(StringRef Name, bool RemoveCache) {
  auto Removed = EditorDocuments.remove(Name);
  if (!Removed)
    IFaceGenContexts.remove(Name);
  if (Removed && RemoveCache)
    Removed->removeCachedAST();
  // FIXME: Report error if Name did not apply to anything ?
}


//============================================================================//
// EditorReplaceText
//============================================================================//

void SwiftLangSupport::editorReplaceText(StringRef Name, llvm::MemoryBuffer *Buf,
                                         unsigned Offset, unsigned Length,
                                         EditorConsumer &Consumer) {
  auto EditorDoc = EditorDocuments.getByUnresolvedName(Name);
  if (!EditorDoc) {
    Consumer.handleRequestError("No associated Editor Document");
    return;
  }

  ImmutableTextSnapshotRef Snapshot;
  if (Length != 0 || Buf->getBufferSize() != 0) {
    Snapshot = EditorDoc->replaceText(Offset, Length, Buf,
                                      Consumer.needsSemanticInfo());
    assert(Snapshot);
    EditorDoc->parse(Snapshot, *this);
    EditorDoc->readSyntaxInfo(Consumer);
  } 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;
  }
  
  EditorDoc->formatText(Line, Length, Consumer);
}

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

//============================================================================//
// 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);
}
