//===--- CodeCompletion.cpp - Code completion implementation --------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#include "swift/IDE/CodeCompletion.h"
#include "CodeCompletionResultBuilder.h"
#include "ExprContextAnalysis.h"
#include "swift/AST/ASTPrinter.h"
#include "swift/AST/ASTWalker.h"
#include "swift/AST/Comment.h"
#include "swift/AST/ImportCache.h"
#include "swift/AST/Initializer.h"
#include "swift/AST/GenericSignature.h"
#include "swift/AST/LazyResolver.h"
#include "swift/AST/NameLookup.h"
#include "swift/AST/ParameterList.h"
#include "swift/AST/ProtocolConformance.h"
#include "swift/AST/SourceFile.h"
#include "swift/AST/SubstitutionMap.h"
#include "swift/AST/USRGeneration.h"
#include "swift/Basic/Defer.h"
#include "swift/Basic/LLVM.h"
#include "swift/ClangImporter/ClangImporter.h"
#include "swift/ClangImporter/ClangModule.h"
#include "swift/IDE/CodeCompletionCache.h"
#include "swift/IDE/CodeCompletionResultPrinter.h"
#include "swift/IDE/Utils.h"
#include "swift/Parse/CodeCompletionCallbacks.h"
#include "swift/Sema/IDETypeChecking.h"
#include "swift/Sema/CodeCompletionTypeChecking.h"
#include "swift/Syntax/SyntaxKind.h"
#include "swift/Strings.h"
#include "swift/Subsystems.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
#include "clang/AST/Comment.h"
#include "clang/AST/CommentVisitor.h"
#include "clang/AST/Decl.h"
#include "clang/Basic/Module.h"
#include "clang/Index/USRGeneration.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/SaveAndRestore.h"
#include <algorithm>
#include <string>

using namespace swift;
using namespace ide;

using CommandWordsPairs = std::vector<std::pair<StringRef, StringRef>>;

enum CodeCompletionCommandKind {
  none,
  keyword,
  recommended,
  recommendedover,
  mutatingvariant,
  nonmutatingvariant,
};

CodeCompletionCommandKind getCommandKind(StringRef Command) {
#define CHECK_CASE(KIND)                                                      \
  if (Command == #KIND)                                                       \
    return CodeCompletionCommandKind::KIND;
  CHECK_CASE(keyword);
  CHECK_CASE(recommended);
  CHECK_CASE(recommendedover);
  CHECK_CASE(mutatingvariant);
  CHECK_CASE(nonmutatingvariant);
#undef CHECK_CASE
  return CodeCompletionCommandKind::none;
}

StringRef getCommandName(CodeCompletionCommandKind Kind) {
#define CHECK_CASE(KIND)                                                    \
  if (CodeCompletionCommandKind::KIND == Kind) {                            \
    static std::string Name(#KIND);                                         \
    return Name;                                                            \
  }
  CHECK_CASE(keyword)
  CHECK_CASE(recommended)
  CHECK_CASE(recommendedover)
  CHECK_CASE(mutatingvariant);
  CHECK_CASE(nonmutatingvariant);
#undef CHECK_CASE
  llvm_unreachable("Cannot handle this Kind.");
}

bool containsInterestedWords(StringRef Content, StringRef Splitter,
                             bool AllowWhitespace) {
  do {
    Content = Content.split(Splitter).second;
    Content = AllowWhitespace ? Content.trim() : Content;
#define CHECK_CASE(KIND)                                                       \
if (Content.startswith(#KIND))                                                 \
return true;
    CHECK_CASE(keyword)
    CHECK_CASE(recommended)
    CHECK_CASE(recommendedover)
    CHECK_CASE(mutatingvariant);
    CHECK_CASE(nonmutatingvariant);
#undef CHECK_CASE
  } while (!Content.empty());
  return false;
}

void splitTextByComma(StringRef Text, std::vector<StringRef>& Subs) {
  do {
    auto Pair = Text.split(',');
    auto Key = Pair.first.trim();
    if (!Key.empty())
      Subs.push_back(Key);
    Text = Pair.second;
  } while (!Text.empty());
}

namespace clang {
namespace comments {
class WordPairsArrangedViewer {
  ArrayRef<std::pair<StringRef, StringRef>> Content;
  std::vector<StringRef> ViewedText;
  std::vector<StringRef> Words;
  StringRef Key;

  bool isKeyViewed(StringRef K) {
    return std::find(ViewedText.begin(), ViewedText.end(), K) != ViewedText.end();
  }

public:
  WordPairsArrangedViewer(ArrayRef<std::pair<StringRef, StringRef>> Content):
    Content(Content) {}

  bool hasNext() {
    Words.clear();
    bool Found = false;
    for (auto P : Content) {
      if (!Found && !isKeyViewed(P.first)) {
        Key = P.first;
        Found = true;
      }
      if (Found && P.first == Key)
        Words.push_back(P.second);
    }
    return Found;
  }

  std::pair<StringRef, ArrayRef<StringRef>> next() {
    bool HasNext = hasNext();
    (void) HasNext;
    assert(HasNext && "Have no more data.");
    ViewedText.push_back(Key);
    return std::make_pair(Key, llvm::makeArrayRef(Words));
  }
};

class ClangCommentExtractor : public ConstCommentVisitor<ClangCommentExtractor> {
  CommandWordsPairs &Words;
  const CommandTraits &Traits;
  std::vector<const Comment *> Parents;

  void visitChildren(const Comment* C) {
    Parents.push_back(C);
    for (auto It = C->child_begin(); It != C->child_end(); ++ It)
      visit(*It);
    Parents.pop_back();
  }

public:
  ClangCommentExtractor(CommandWordsPairs &Words,
                        const CommandTraits &Traits) : Words(Words),
                                                       Traits(Traits) {}
#define CHILD_VISIT(NAME) \
  void visit##NAME(const NAME *C) {\
    visitChildren(C);\
  }
  CHILD_VISIT(FullComment)
  CHILD_VISIT(ParagraphComment)
#undef CHILD_VISIT

  void visitInlineCommandComment(const InlineCommandComment *C) {
    auto Command = C->getCommandName(Traits);
    auto CommandKind = getCommandKind(Command);
    if (CommandKind == CodeCompletionCommandKind::none)
      return;
    auto &Parent = Parents.back();
    for (auto CIT = std::find(Parent->child_begin(), Parent->child_end(), C) + 1;
         CIT != Parent->child_end(); ++CIT) {
      if (auto TC = dyn_cast<TextComment>(*CIT)) {
        auto Text = TC->getText();
        std::vector<StringRef> Subs;
        splitTextByComma(Text, Subs);
        auto Kind = getCommandName(CommandKind);
        for (auto S : Subs)
          Words.push_back(std::make_pair(Kind, S));
      } else
        break;
    }
  }
};

void getClangDocKeyword(ClangImporter &Importer, const Decl *D,
                        CommandWordsPairs &Words) {
  ClangCommentExtractor Extractor(Words, Importer.getClangASTContext().
    getCommentCommandTraits());
  if (auto RC = Importer.getClangASTContext().getRawCommentForAnyRedecl(D)) {
    auto RT = RC->getRawText(Importer.getClangASTContext().getSourceManager());
    if (containsInterestedWords(RT, "@", /*AllowWhitespace*/false)) {
      FullComment* Comment = Importer.getClangASTContext().
        getLocalCommentForDeclUncached(D);
      Extractor.visit(Comment);
    }
  }
}
} // end namespace comments
} // end namespace clang

namespace swift {
namespace markup {
class SwiftDocWordExtractor : public MarkupASTWalker {
  CommandWordsPairs &Pairs;
  CodeCompletionCommandKind Kind;
public:
  SwiftDocWordExtractor(CommandWordsPairs &Pairs) :
    Pairs(Pairs), Kind(CodeCompletionCommandKind::none) {}
  void visitKeywordField(const KeywordField *Field) override {
    Kind = CodeCompletionCommandKind::keyword;
  }
  void visitRecommendedField(const RecommendedField *Field) override {
    Kind = CodeCompletionCommandKind::recommended;
  }
  void visitRecommendedoverField(const RecommendedoverField *Field) override {
    Kind = CodeCompletionCommandKind::recommendedover;
  }
  void visitMutatingvariantField(const MutatingvariantField *Field) override {
    Kind = CodeCompletionCommandKind::mutatingvariant;
  }
  void visitNonmutatingvariantField(const NonmutatingvariantField *Field) override {
    Kind = CodeCompletionCommandKind::nonmutatingvariant;
  }
  void visitText(const Text *Text) override {
    if (Kind == CodeCompletionCommandKind::none)
      return;
    StringRef CommandName = getCommandName(Kind);
    std::vector<StringRef> Subs;
    splitTextByComma(Text->str(), Subs);
    for (auto S : Subs)
      Pairs.push_back(std::make_pair(CommandName, S));
  }
};

void getSwiftDocKeyword(const Decl* D, CommandWordsPairs &Words) {
  auto Interested = false;
  for (auto C : D->getRawComment().Comments) {
    if (containsInterestedWords(C.RawText, "-", /*AllowWhitespace*/true)) {
      Interested = true;
      break;
    }
  }
  if (!Interested)
    return;
  static swift::markup::MarkupContext MC;
  auto DC = getSingleDocComment(MC, D);
  if (!DC)
    return;
  SwiftDocWordExtractor Extractor(Words);
  for (auto Part : DC->getBodyNodes()) {
    switch (Part->getKind()) {
      case ASTNodeKind::KeywordField:
      case ASTNodeKind::RecommendedField:
      case ASTNodeKind::RecommendedoverField:
      case ASTNodeKind::MutatingvariantField:
      case ASTNodeKind::NonmutatingvariantField:
        Extractor.walk(Part);
        break;
      default:
        break;
    }
  }
}
} // end namespace markup
} // end namespace swift

using DeclFilter = std::function<bool(ValueDecl *, DeclVisibilityKind)>;
static bool DefaultFilter(ValueDecl* VD, DeclVisibilityKind Kind) {
  return true;
}
static bool KeyPathFilter(ValueDecl* decl, DeclVisibilityKind) {
  return isa<TypeDecl>(decl) ||
         (isa<VarDecl>(decl) && decl->getDeclContext()->isTypeContext());
}

static bool SwiftKeyPathFilter(ValueDecl* decl, DeclVisibilityKind) {
  switch(decl->getKind()){
  case DeclKind::Var:
  case DeclKind::Subscript:
    return true;
  default:
    return false;
  }
}

std::string swift::ide::removeCodeCompletionTokens(
    StringRef Input, StringRef TokenName, unsigned *CompletionOffset) {
  assert(TokenName.size() >= 1);

  *CompletionOffset = ~0U;

  std::string CleanFile;
  CleanFile.reserve(Input.size());
  const std::string Token = std::string("#^") + TokenName.str() + "^#";

  for (const char *Ptr = Input.begin(), *End = Input.end();
       Ptr != End; ++Ptr) {
    const char C = *Ptr;
    if (C == '#' && Ptr <= End - Token.size() &&
        StringRef(Ptr, Token.size()) == Token) {
      Ptr += Token.size() - 1;
      *CompletionOffset = CleanFile.size();
      CleanFile += '\0';
      continue;
    }
    if (C == '#' && Ptr <= End - 2 && Ptr[1] == '^') {
      do {
        ++Ptr;
      } while (Ptr < End && *Ptr != '#');
      if (Ptr == End)
        break;
      continue;
    }
    CleanFile += C;
  }
  return CleanFile;
}

llvm::StringRef swift::ide::copyString(llvm::BumpPtrAllocator &Allocator,
                                       llvm::StringRef Str) {
  char *Buffer = Allocator.Allocate<char>(Str.size());
  std::copy(Str.begin(), Str.end(), Buffer);
  return llvm::StringRef(Buffer, Str.size());
}

const char *swift::ide::copyCString(llvm::BumpPtrAllocator &Allocator,
                                    llvm::StringRef Str) {
  char *Buffer = Allocator.Allocate<char>(Str.size() + 1);
  std::copy(Str.begin(), Str.end(), Buffer);
  Buffer[Str.size()] = '\0';
  return Buffer;
}

CodeCompletionString::CodeCompletionString(ArrayRef<Chunk> Chunks) {
  std::uninitialized_copy(Chunks.begin(), Chunks.end(),
                          getTrailingObjects<Chunk>());
  NumChunks = Chunks.size();
}

CodeCompletionString *CodeCompletionString::create(llvm::BumpPtrAllocator &Allocator,
                                                   ArrayRef<Chunk> Chunks) {
  void *CCSMem = Allocator.Allocate(totalSizeToAlloc<Chunk>(Chunks.size()),
                                    alignof(CodeCompletionString));
  return new (CCSMem) CodeCompletionString(Chunks);
}

void CodeCompletionString::print(raw_ostream &OS) const {
  unsigned PrevNestingLevel = 0;
  auto chunks = getChunks();
  for (auto I = chunks.begin(), E = chunks.end(); I != E; ++I) {
    bool AnnotatedTextChunk = false;

    if (I->getNestingLevel() < PrevNestingLevel) {
      OS << "#}";
    }
    switch (I->getKind()) {
    using ChunkKind = Chunk::ChunkKind;
    case ChunkKind::AccessControlKeyword:
    case ChunkKind::DeclAttrKeyword:
    case ChunkKind::DeclAttrParamKeyword:
    case ChunkKind::OverrideKeyword:
    case ChunkKind::EffectsSpecifierKeyword:
    case ChunkKind::DeclIntroducer:
    case ChunkKind::Text:
    case ChunkKind::LeftParen:
    case ChunkKind::RightParen:
    case ChunkKind::LeftBracket:
    case ChunkKind::RightBracket:
    case ChunkKind::LeftAngle:
    case ChunkKind::RightAngle:
    case ChunkKind::Dot:
    case ChunkKind::Ellipsis:
    case ChunkKind::Comma:
    case ChunkKind::ExclamationMark:
    case ChunkKind::QuestionMark:
    case ChunkKind::Ampersand:
    case ChunkKind::Equal:
    case ChunkKind::Whitespace:
    case ChunkKind::Keyword:
    case ChunkKind::Attribute:
    case ChunkKind::BaseName:
    case ChunkKind::TypeIdSystem:
    case ChunkKind::TypeIdUser:
      AnnotatedTextChunk = I->isAnnotation();
      LLVM_FALLTHROUGH;
    case ChunkKind::CallParameterName:
    case ChunkKind::CallParameterInternalName:
    case ChunkKind::CallParameterColon:
    case ChunkKind::DeclAttrParamColon:
    case ChunkKind::CallParameterType:
    case ChunkKind::CallParameterClosureType:
    case ChunkKind::GenericParameterName:
      if (AnnotatedTextChunk)
        OS << "['";
      else if (I->getKind() == ChunkKind::CallParameterInternalName)
        OS << "(";
      else if (I->getKind() == ChunkKind::CallParameterClosureType)
        OS << "##";
      for (char Ch : I->getText()) {
        if (Ch == '\n')
          OS << "\\n";
        else
          OS << Ch;
      }
      if (AnnotatedTextChunk)
        OS << "']";
      else if (I->getKind() == ChunkKind::CallParameterInternalName)
        OS << ")";
      break;
    case ChunkKind::OptionalBegin:
    case ChunkKind::CallParameterBegin:
    case ChunkKind::CallParameterTypeBegin:
    case ChunkKind::GenericParameterBegin:
      OS << "{#";
      break;
    case ChunkKind::DynamicLookupMethodCallTail:
    case ChunkKind::OptionalMethodCallTail:
      OS << I->getText();
      break;
    case ChunkKind::TypeAnnotationBegin: {
      OS << "[#";
      ++I;
      auto level = I->getNestingLevel();
      for (; I != E && !I->endsPreviousNestedGroup(level); ++I)
        if (I->hasText())
          OS << I->getText();
      --I;
      OS << "#]";
      continue;
    }
    case ChunkKind::TypeAnnotation:
      OS << "[#";
      OS << I->getText();
      OS << "#]";
      break;
    case ChunkKind::CallParameterClosureExpr:
      OS << " {" << I->getText() << "|}";
      break;
    case ChunkKind::BraceStmtWithCursor:
      OS << " {|}";
      break;
    }
    PrevNestingLevel = I->getNestingLevel();
  }
  while (PrevNestingLevel > 0) {
    OS << "#}";
    --PrevNestingLevel;
  }
}

void CodeCompletionString::dump() const {
  print(llvm::errs());
}

CodeCompletionDeclKind
CodeCompletionResult::getCodeCompletionDeclKind(const Decl *D) {
  switch (D->getKind()) {
  case DeclKind::Import:
  case DeclKind::Extension:
  case DeclKind::PatternBinding:
  case DeclKind::EnumCase:
  case DeclKind::TopLevelCode:
  case DeclKind::IfConfig:
  case DeclKind::PoundDiagnostic:
  case DeclKind::MissingMember:
  case DeclKind::OpaqueType:
    llvm_unreachable("not expecting such a declaration result");
  case DeclKind::Module:
    return CodeCompletionDeclKind::Module;
  case DeclKind::TypeAlias:
    return CodeCompletionDeclKind::TypeAlias;
  case DeclKind::AssociatedType:
    return CodeCompletionDeclKind::AssociatedType;
  case DeclKind::GenericTypeParam:
    return CodeCompletionDeclKind::GenericTypeParam;
  case DeclKind::Enum:
    return CodeCompletionDeclKind::Enum;
  case DeclKind::Struct:
    return CodeCompletionDeclKind::Struct;
  case DeclKind::Class:
    return CodeCompletionDeclKind::Class;
  case DeclKind::Protocol:
    return CodeCompletionDeclKind::Protocol;
  case DeclKind::Var:
  case DeclKind::Param: {
    auto DC = D->getDeclContext();
    if (DC->isTypeContext()) {
      if (cast<VarDecl>(D)->isStatic())
        return CodeCompletionDeclKind::StaticVar;
      else
        return CodeCompletionDeclKind::InstanceVar;
    }
    if (DC->isLocalContext())
      return CodeCompletionDeclKind::LocalVar;
    return CodeCompletionDeclKind::GlobalVar;
  }
  case DeclKind::Constructor:
    return CodeCompletionDeclKind::Constructor;
  case DeclKind::Destructor:
    return CodeCompletionDeclKind::Destructor;
  case DeclKind::Accessor:
  case DeclKind::Func: {
    auto DC = D->getDeclContext();
    auto FD = cast<FuncDecl>(D);
    if (DC->isTypeContext()) {
      if (FD->isStatic())
        return CodeCompletionDeclKind::StaticMethod;
      return CodeCompletionDeclKind::InstanceMethod;
    }
    if (FD->isOperator()) {
      if (auto op = FD->getOperatorDecl()) {
        switch (op->getKind()) {
        case DeclKind::PrefixOperator:
          return CodeCompletionDeclKind::PrefixOperatorFunction;
        case DeclKind::PostfixOperator:
          return CodeCompletionDeclKind::PostfixOperatorFunction;
        case DeclKind::InfixOperator:
          return CodeCompletionDeclKind::InfixOperatorFunction;
        default:
          llvm_unreachable("unexpected operator kind");
        }
      } else {
        return CodeCompletionDeclKind::InfixOperatorFunction;
      }
    }
    return CodeCompletionDeclKind::FreeFunction;
  }
  case DeclKind::InfixOperator:
    return CodeCompletionDeclKind::InfixOperatorFunction;
  case DeclKind::PrefixOperator:
    return CodeCompletionDeclKind::PrefixOperatorFunction;
  case DeclKind::PostfixOperator:
    return CodeCompletionDeclKind::PostfixOperatorFunction;
  case DeclKind::PrecedenceGroup:
    return CodeCompletionDeclKind::PrecedenceGroup;
  case DeclKind::EnumElement:
    return CodeCompletionDeclKind::EnumElement;
  case DeclKind::Subscript:
    return CodeCompletionDeclKind::Subscript;
  }
  llvm_unreachable("invalid DeclKind");
}

bool CodeCompletionResult::getDeclIsSystem(const Decl *D) {
  return D->getModuleContext()->isSystemModule();
}

void CodeCompletionResult::printPrefix(raw_ostream &OS) const {
  llvm::SmallString<64> Prefix;
  switch (getKind()) {
  case ResultKind::Declaration:
    Prefix.append("Decl");
    switch (getAssociatedDeclKind()) {
    case CodeCompletionDeclKind::Class:
      Prefix.append("[Class]");
      break;
    case CodeCompletionDeclKind::Struct:
      Prefix.append("[Struct]");
      break;
    case CodeCompletionDeclKind::Enum:
      Prefix.append("[Enum]");
      break;
    case CodeCompletionDeclKind::EnumElement:
      Prefix.append("[EnumElement]");
      break;
    case CodeCompletionDeclKind::Protocol:
      Prefix.append("[Protocol]");
      break;
    case CodeCompletionDeclKind::TypeAlias:
      Prefix.append("[TypeAlias]");
      break;
    case CodeCompletionDeclKind::AssociatedType:
      Prefix.append("[AssociatedType]");
      break;
    case CodeCompletionDeclKind::GenericTypeParam:
      Prefix.append("[GenericTypeParam]");
      break;
    case CodeCompletionDeclKind::Constructor:
      Prefix.append("[Constructor]");
      break;
    case CodeCompletionDeclKind::Destructor:
      Prefix.append("[Destructor]");
      break;
    case CodeCompletionDeclKind::Subscript:
      Prefix.append("[Subscript]");
      break;
    case CodeCompletionDeclKind::StaticMethod:
      Prefix.append("[StaticMethod]");
      break;
    case CodeCompletionDeclKind::InstanceMethod:
      Prefix.append("[InstanceMethod]");
      break;
    case CodeCompletionDeclKind::PrefixOperatorFunction:
      Prefix.append("[PrefixOperatorFunction]");
      break;
    case CodeCompletionDeclKind::PostfixOperatorFunction:
      Prefix.append("[PostfixOperatorFunction]");
      break;
    case CodeCompletionDeclKind::InfixOperatorFunction:
      Prefix.append("[InfixOperatorFunction]");
      break;
    case CodeCompletionDeclKind::FreeFunction:
      Prefix.append("[FreeFunction]");
      break;
    case CodeCompletionDeclKind::StaticVar:
      Prefix.append("[StaticVar]");
      break;
    case CodeCompletionDeclKind::InstanceVar:
      Prefix.append("[InstanceVar]");
      break;
    case CodeCompletionDeclKind::LocalVar:
      Prefix.append("[LocalVar]");
      break;
    case CodeCompletionDeclKind::GlobalVar:
      Prefix.append("[GlobalVar]");
      break;
    case CodeCompletionDeclKind::Module:
      Prefix.append("[Module]");
      break;
    case CodeCompletionDeclKind::PrecedenceGroup:
      Prefix.append("[PrecedenceGroup]");
      break;
    }
    break;
  case ResultKind::Keyword:
    Prefix.append("Keyword");
    switch (getKeywordKind()) {
    case CodeCompletionKeywordKind::None:
      break;
#define KEYWORD(X) case CodeCompletionKeywordKind::kw_##X: \
      Prefix.append("[" #X "]"); \
      break;
#define POUND_KEYWORD(X) case CodeCompletionKeywordKind::pound_##X: \
      Prefix.append("[#" #X "]"); \
      break;
#include "swift/Syntax/TokenKinds.def"
    }
    break;
  case ResultKind::Pattern:
    Prefix.append("Pattern");
    break;
  case ResultKind::Literal:
    Prefix.append("Literal");
    switch (getLiteralKind()) {
    case CodeCompletionLiteralKind::ArrayLiteral:
      Prefix.append("[Array]");
      break;
    case CodeCompletionLiteralKind::BooleanLiteral:
      Prefix.append("[Boolean]");
      break;
    case CodeCompletionLiteralKind::ColorLiteral:
      Prefix.append("[_Color]");
      break;
    case CodeCompletionLiteralKind::ImageLiteral:
      Prefix.append("[_Image]");
      break;
    case CodeCompletionLiteralKind::DictionaryLiteral:
      Prefix.append("[Dictionary]");
      break;
    case CodeCompletionLiteralKind::IntegerLiteral:
      Prefix.append("[Integer]");
      break;
    case CodeCompletionLiteralKind::NilLiteral:
      Prefix.append("[Nil]");
      break;
    case CodeCompletionLiteralKind::StringLiteral:
      Prefix.append("[String]");
      break;
    case CodeCompletionLiteralKind::Tuple:
      Prefix.append("[Tuple]");
      break;
    }
    break;
  case ResultKind::BuiltinOperator:
    Prefix.append("BuiltinOperator");
    break;
  }
  Prefix.append("/");
  switch (getSemanticContext()) {
  case SemanticContextKind::None:
    Prefix.append("None");
    break;
  case SemanticContextKind::ExpressionSpecific:
    Prefix.append("ExprSpecific");
    break;
  case SemanticContextKind::Local:
    Prefix.append("Local");
    break;
  case SemanticContextKind::CurrentNominal:
    Prefix.append("CurrNominal");
    break;
  case SemanticContextKind::Super:
    Prefix.append("Super");
    break;
  case SemanticContextKind::OutsideNominal:
    Prefix.append("OutNominal");
    break;
  case SemanticContextKind::CurrentModule:
    Prefix.append("CurrModule");
    break;
  case SemanticContextKind::OtherModule:
    Prefix.append("OtherModule");
    if (!ModuleName.empty())
      Prefix.append((Twine("[") + ModuleName + "]").str());
    break;
  }
  if (NotRecommended)
    Prefix.append("/NotRecommended");
  if (IsSystem)
    Prefix.append("/IsSystem");
  if (NumBytesToErase != 0) {
    Prefix.append("/Erase[");
    Prefix.append(Twine(NumBytesToErase).str());
    Prefix.append("]");
  }
  switch (getExpectedTypeRelation()) {
    case ExpectedTypeRelation::Invalid:
      Prefix.append("/TypeRelation[Invalid]");
      break;
    case ExpectedTypeRelation::Identical:
      Prefix.append("/TypeRelation[Identical]");
      break;
    case ExpectedTypeRelation::Convertible:
      Prefix.append("/TypeRelation[Convertible]");
      break;
    case ExpectedTypeRelation::NotApplicable:
    case ExpectedTypeRelation::Unknown:
    case ExpectedTypeRelation::Unrelated:
      break;
  }

  for (clang::comments::WordPairsArrangedViewer Viewer(DocWords);
       Viewer.hasNext();) {
    auto Pair = Viewer.next();
    Prefix.append("/");
    Prefix.append(Pair.first);
    Prefix.append("[");
    StringRef Sep = ", ";
    for (auto KW : Pair.second) {
      Prefix.append(KW);
      Prefix.append(Sep);
    }
    for (unsigned I = 0, N = Sep.size(); I < N; ++I)
      Prefix.pop_back();
    Prefix.append("]");
  }

  Prefix.append(": ");
  while (Prefix.size() < 36) {
    Prefix.append(" ");
  }
  OS << Prefix;
}

void CodeCompletionResult::dump() const {
  printPrefix(llvm::errs());
  CompletionString->print(llvm::errs());
  llvm::errs() << "\n";
}

void CodeCompletionResultBuilder::withNestedGroup(
    CodeCompletionString::Chunk::ChunkKind Kind,
    llvm::function_ref<void()> body) {
  ++CurrentNestingLevel;
  addSimpleChunk(Kind);
  body();
  --CurrentNestingLevel;
}

void CodeCompletionResultBuilder::addChunkWithText(
    CodeCompletionString::Chunk::ChunkKind Kind, StringRef Text) {
  addChunkWithTextNoCopy(Kind, copyString(*Sink.Allocator, Text));
}

void CodeCompletionResultBuilder::setAssociatedDecl(const Decl *D) {
  assert(Kind == CodeCompletionResult::ResultKind::Declaration);
  AssociatedDecl = D;
  if (auto *ClangD = D->getClangDecl())
    CurrentModule = ClangD->getImportedOwningModule();
  // FIXME: macros
  // FIXME: imported header module

  if (!CurrentModule) {
    ModuleDecl *MD = D->getModuleContext();

    // If this is an underscored cross-import overlay, map it to the underlying
    // module that declares it instead.
    if (ModuleDecl *Declaring = MD->getDeclaringModuleIfCrossImportOverlay())
      MD = Declaring;

    CurrentModule = MD;
  }

  if (D->getAttrs().getDeprecated(D->getASTContext()))
    setNotRecommended(CodeCompletionResult::Deprecated);
}

namespace {
class AnnotatedTypePrinter : public ASTPrinter {
  using ChunkKind = CodeCompletionString::Chunk::ChunkKind;
  CodeCompletionResultBuilder &Builder;
  SmallString<16> Buffer;
  ChunkKind CurrChunkKind = ChunkKind::Text;
  ChunkKind NextChunkKind = ChunkKind::Text;

  Optional<ChunkKind> getChunkKindForPrintNameContext(PrintNameContext context) {
    switch (context) {
    case PrintNameContext::Keyword:
      return ChunkKind::Keyword;
    case PrintNameContext::Attribute:
      return ChunkKind::Attribute;
    default:
      return None;
    }
  }

  void flush() {
    if (Buffer.empty())
      return;
    Builder.addChunkWithText(CurrChunkKind, Buffer);
    Buffer.clear();
  }

public:
  AnnotatedTypePrinter(CodeCompletionResultBuilder &Builder) : Builder(Builder) {}

  ~AnnotatedTypePrinter() {
    // Flush the remainings.
    flush();
  }

  void printText(StringRef Text) override {
    if (CurrChunkKind != NextChunkKind) {
      // If the next desired kind is different from the current buffer, flush
      // the current buffer.
      flush();
      CurrChunkKind = NextChunkKind;
    }
    Buffer.append(Text);
  }

  void printTypeRef(
      Type T, const TypeDecl *TD, Identifier Name,
      PrintNameContext NameContext = PrintNameContext::Normal) override {

    NextChunkKind = TD->getModuleContext()->isSystemModule()
      ? ChunkKind::TypeIdSystem
      : ChunkKind::TypeIdUser;

    ASTPrinter::printTypeRef(T, TD, Name, NameContext);
    NextChunkKind = ChunkKind::Text;
  }

  void printNamePre(PrintNameContext context) override {
    if (auto Kind = getChunkKindForPrintNameContext(context))
      NextChunkKind = *Kind;
  }

  void printNamePost(PrintNameContext context) override {
    if (auto Kind = getChunkKindForPrintNameContext(context))
      NextChunkKind = ChunkKind::Text;
  }
};
} // namespcae

void CodeCompletionResultBuilder::addCallParameter(Identifier Name,
                                                   Identifier LocalName,
                                                   Type Ty,
                                                   Type ContextTy,
                                                   bool IsVarArg,
                                                   bool IsInOut,
                                                   bool IsIUO,
                                                   bool isAutoClosure,
                                                   bool useUnderscoreLabel,
                                                   bool isLabeledTrailingClosure) {
  ++CurrentNestingLevel;
  using ChunkKind = CodeCompletionString::Chunk::ChunkKind;

  addSimpleChunk(ChunkKind::CallParameterBegin);

  if (shouldAnnotateResults()) {
    if (!Name.empty() || !LocalName.empty()) {
      llvm::SmallString<16> EscapedKeyword;

      if (!Name.empty()) {
        addChunkWithText(
            CodeCompletionString::Chunk::ChunkKind::CallParameterName,
            escapeKeyword(Name.str(), false, EscapedKeyword));

        if (!LocalName.empty() && Name != LocalName) {
          addChunkWithTextNoCopy(ChunkKind::Text, " ");
          getLastChunk().setIsAnnotation();
          addChunkWithText(ChunkKind::CallParameterInternalName,
              escapeKeyword(LocalName.str(), false, EscapedKeyword));
          getLastChunk().setIsAnnotation();
        }
      } else {
        assert(!LocalName.empty());
        addChunkWithTextNoCopy(ChunkKind::CallParameterName, "_");
        getLastChunk().setIsAnnotation();
        addChunkWithTextNoCopy(ChunkKind::Text, " ");
        getLastChunk().setIsAnnotation();
        addChunkWithText(ChunkKind::CallParameterInternalName,
            escapeKeyword(LocalName.str(), false, EscapedKeyword));
      }
      addChunkWithTextNoCopy(ChunkKind::CallParameterColon, ": ");
    }
  } else {
    if (!Name.empty()) {
      llvm::SmallString<16> EscapedKeyword;
      addChunkWithText(
          CodeCompletionString::Chunk::ChunkKind::CallParameterName,
          escapeKeyword(Name.str(), false, EscapedKeyword));
      addChunkWithTextNoCopy(
          CodeCompletionString::Chunk::ChunkKind::CallParameterColon, ": ");
    } else if (useUnderscoreLabel) {
      addChunkWithTextNoCopy(
          CodeCompletionString::Chunk::ChunkKind::CallParameterName, "_");
      addChunkWithTextNoCopy(
          CodeCompletionString::Chunk::ChunkKind::CallParameterColon, ": ");
    } else if (!LocalName.empty()) {
      // Use local (non-API) parameter name if we have nothing else.
      llvm::SmallString<16> EscapedKeyword;
      addChunkWithText(
          CodeCompletionString::Chunk::ChunkKind::CallParameterInternalName,
            escapeKeyword(LocalName.str(), false, EscapedKeyword));
      addChunkWithTextNoCopy(
          CodeCompletionString::Chunk::ChunkKind::CallParameterColon, ": ");
    }
  }

  // 'inout' arguments are printed specially.
  if (IsInOut) {
    addChunkWithTextNoCopy(
        CodeCompletionString::Chunk::ChunkKind::Ampersand, "&");
    Ty = Ty->getInOutObjectType();
  }

  // If the parameter is of the type @autoclosure ()->output, then the
  // code completion should show the parameter of the output type
  // instead of the function type ()->output.
  if (isAutoClosure) {
    // 'Ty' may be ErrorType.
    if (auto funcTy = Ty->getAs<FunctionType>())
      Ty = funcTy->getResult();
  }

  PrintOptions PO;
  PO.SkipAttributes = true;
  PO.PrintOptionalAsImplicitlyUnwrapped = IsIUO;
  PO.OpaqueReturnTypePrinting =
      PrintOptions::OpaqueReturnTypePrintingMode::WithoutOpaqueKeyword;
  if (ContextTy)
    PO.setBaseType(ContextTy);
  if (shouldAnnotateResults()) {
    withNestedGroup(ChunkKind::CallParameterTypeBegin, [&]() {
      AnnotatedTypePrinter printer(*this);
      Ty->print(printer, PO);
    });
  } else {
    std::string TypeName = Ty->getString(PO);
    addChunkWithText(ChunkKind::CallParameterType, TypeName);
  }

  // Look through optional types and type aliases to find out if we have
  // function type.
  Ty = Ty->lookThroughAllOptionalTypes();
  if (auto AFT = Ty->getAs<AnyFunctionType>()) {
    // If this is a closure type, add ChunkKind::CallParameterClosureType or
    // ChunkKind::CallParameterClosureExpr for labeled trailing closures.
    PrintOptions PO;
    PO.PrintFunctionRepresentationAttrs =
      PrintOptions::FunctionRepresentationMode::None;
    PO.SkipAttributes = true;
    PO.OpaqueReturnTypePrinting =
        PrintOptions::OpaqueReturnTypePrintingMode::WithoutOpaqueKeyword;
    if (ContextTy)
      PO.setBaseType(ContextTy);

    if (isLabeledTrailingClosure) {
      // Expand the closure body.
      SmallString<32> buffer;
      llvm::raw_svector_ostream OS(buffer);

      bool firstParam = true;
      for (const auto &param : AFT->getParams()) {
        if (!firstParam)
          OS << ", ";
        firstParam = false;

        if (param.hasLabel()) {
          OS << param.getLabel();
        } else {
          OS << "<#";
          if (param.isInOut())
            OS << "inout ";
          OS << param.getPlainType()->getString(PO);
          if (param.isVariadic())
            OS << "...";
          OS << "#>";
        }
      }

      if (!firstParam)
        OS << " in";

      addChunkWithText(
         CodeCompletionString::Chunk::ChunkKind::CallParameterClosureExpr,
         OS.str());
    } else {
      // Add the closure type.
      addChunkWithText(
          CodeCompletionString::Chunk::ChunkKind::CallParameterClosureType,
          AFT->getString(PO));
    }
  }

  if (IsVarArg)
    addEllipsis();
  --CurrentNestingLevel;
}

void CodeCompletionResultBuilder::addTypeAnnotation(Type T, PrintOptions PO,
                                                    StringRef suffix) {
  T = T->getReferenceStorageReferent();

  // Replace '()' with 'Void'.
  if (T->isVoid())
    T = T->getASTContext().getVoidDecl()->getDeclaredInterfaceType();

  if (shouldAnnotateResults()) {
    withNestedGroup(CodeCompletionString::Chunk::ChunkKind::TypeAnnotationBegin,
                    [&]() {
                      AnnotatedTypePrinter printer(*this);
                      T->print(printer, PO);
                      if (!suffix.empty())
                        printer.printText(suffix);
                    });
  } else {
    auto str = T.getString(PO);
    if (!suffix.empty())
      str += suffix.str();
    addTypeAnnotation(str);
  }
}

StringRef CodeCompletionContext::copyString(StringRef Str) {
  return ::copyString(*CurrentResults.Allocator, Str);
}

bool shouldCopyAssociatedUSRForDecl(const ValueDecl *VD) {
  // Avoid trying to generate a USR for some declaration types.
  if (isa<AbstractTypeParamDecl>(VD) && !isa<AssociatedTypeDecl>(VD))
    return false;
  if (isa<ParamDecl>(VD))
    return false;
  if (isa<ModuleDecl>(VD))
    return false;
  if (VD->hasClangNode() && !VD->getClangDecl())
    return false;

  return true;
}

template <typename FnTy>
static void walkValueDeclAndOverriddenDecls(const Decl *D, const FnTy &Fn) {
  if (auto *VD = dyn_cast<ValueDecl>(D)) {
    Fn(VD);
    walkOverriddenDecls(VD, Fn);
  }
}

ArrayRef<StringRef> copyAssociatedUSRs(llvm::BumpPtrAllocator &Allocator,
                                       const Decl *D) {
  llvm::SmallVector<StringRef, 4> USRs;
  walkValueDeclAndOverriddenDecls(D, [&](llvm::PointerUnion<const ValueDecl*,
                                                  const clang::NamedDecl*> OD) {
    llvm::SmallString<128> SS;
    bool Ignored = true;
    if (auto *OVD = OD.dyn_cast<const ValueDecl*>()) {
      if (shouldCopyAssociatedUSRForDecl(OVD)) {
        llvm::raw_svector_ostream OS(SS);
        Ignored = printValueDeclUSR(OVD, OS);
      }
    } else if (auto *OND = OD.dyn_cast<const clang::NamedDecl*>()) {
      Ignored = clang::index::generateUSRForDecl(OND, SS);
    }

    if (!Ignored)
      USRs.push_back(copyString(Allocator, SS));
  });

  if (!USRs.empty())
    return copyArray(Allocator, ArrayRef<StringRef>(USRs));

  return ArrayRef<StringRef>();
}

static CodeCompletionResult::ExpectedTypeRelation
calculateTypeRelation(Type Ty, Type ExpectedTy, const DeclContext *DC) {
  if (Ty.isNull() || ExpectedTy.isNull() ||
      Ty->is<ErrorType>() ||
      ExpectedTy->is<ErrorType>())
    return CodeCompletionResult::ExpectedTypeRelation::Unrelated;

  // Equality/Conversion of GenericTypeParameterType won't account for
  // requirements – ignore them
  if (!Ty->hasTypeParameter() && !ExpectedTy->hasTypeParameter()) {
    if (Ty->isEqual(ExpectedTy))
      return CodeCompletionResult::ExpectedTypeRelation::Identical;
    bool isAny = false;
    isAny |= ExpectedTy->isAny();
    isAny |= ExpectedTy->is<ArchetypeType>() &&
             !ExpectedTy->castTo<ArchetypeType>()->hasRequirements();

    if (!isAny && isConvertibleTo(Ty, ExpectedTy, /*openArchetypes=*/true,
                                  *const_cast<DeclContext *>(DC)))
      return CodeCompletionResult::ExpectedTypeRelation::Convertible;
  }
  if (auto FT = Ty->getAs<AnyFunctionType>()) {
    if (FT->getResult()->isVoid())
      return CodeCompletionResult::ExpectedTypeRelation::Invalid;
  }
  return CodeCompletionResult::ExpectedTypeRelation::Unrelated;
}

static CodeCompletionResult::ExpectedTypeRelation
calculateMaxTypeRelation(Type Ty, const ExpectedTypeContext &typeContext,
                         const DeclContext *DC) {
  if (typeContext.empty())
    return CodeCompletionResult::ExpectedTypeRelation::Unknown;

  if (auto funcTy = Ty->getAs<AnyFunctionType>())
    Ty = funcTy->removeArgumentLabels(1);

  auto Result = CodeCompletionResult::ExpectedTypeRelation::Unrelated;
  for (auto expectedTy : typeContext.possibleTypes) {
    // Do not use Void type context for a single-expression body, since the
    // implicit return does not constrain the expression.
    //
    //     { ... -> ()  in x } // x can be anything
    //
    // This behaves differently from explicit return, and from non-Void:
    //
    //     { ... -> Int in x }        // x must be Int
    //     { ... -> ()  in return x } // x must be Void
    if (typeContext.isImplicitSingleExpressionReturn && expectedTy->isVoid())
      continue;

    Result = std::max(Result, calculateTypeRelation(Ty, expectedTy, DC));

    // Map invalid -> unrelated when in a single-expression body, since the
    // input may be incomplete.
    if (typeContext.isImplicitSingleExpressionReturn &&
        Result == CodeCompletionResult::ExpectedTypeRelation::Invalid)
      Result = CodeCompletionResult::ExpectedTypeRelation::Unrelated;
  }
  return Result;
}

CodeCompletionOperatorKind
CodeCompletionResult::getCodeCompletionOperatorKind(StringRef name) {
  using CCOK = CodeCompletionOperatorKind;
  using OpPair = std::pair<StringRef, CCOK>;

  // This list must be kept in alphabetical order.
  static OpPair ops[] = {
      std::make_pair("!", CCOK::Bang),
      std::make_pair("!=", CCOK::NotEq),
      std::make_pair("!==", CCOK::NotEqEq),
      std::make_pair("%", CCOK::Modulo),
      std::make_pair("%=", CCOK::ModuloEq),
      std::make_pair("&", CCOK::Amp),
      std::make_pair("&&", CCOK::AmpAmp),
      std::make_pair("&*", CCOK::AmpStar),
      std::make_pair("&+", CCOK::AmpPlus),
      std::make_pair("&-", CCOK::AmpMinus),
      std::make_pair("&=", CCOK::AmpEq),
      std::make_pair("(", CCOK::LParen),
      std::make_pair("*", CCOK::Star),
      std::make_pair("*=", CCOK::StarEq),
      std::make_pair("+", CCOK::Plus),
      std::make_pair("+=", CCOK::PlusEq),
      std::make_pair("-", CCOK::Minus),
      std::make_pair("-=", CCOK::MinusEq),
      std::make_pair(".", CCOK::Dot),
      std::make_pair("...", CCOK::DotDotDot),
      std::make_pair("..<", CCOK::DotDotLess),
      std::make_pair("/", CCOK::Slash),
      std::make_pair("/=", CCOK::SlashEq),
      std::make_pair("<", CCOK::Less),
      std::make_pair("<<", CCOK::LessLess),
      std::make_pair("<<=", CCOK::LessLessEq),
      std::make_pair("<=", CCOK::LessEq),
      std::make_pair("=", CCOK::Eq),
      std::make_pair("==", CCOK::EqEq),
      std::make_pair("===", CCOK::EqEqEq),
      std::make_pair(">", CCOK::Greater),
      std::make_pair(">=", CCOK::GreaterEq),
      std::make_pair(">>", CCOK::GreaterGreater),
      std::make_pair(">>=", CCOK::GreaterGreaterEq),
      std::make_pair("?.", CCOK::QuestionDot),
      std::make_pair("^", CCOK::Caret),
      std::make_pair("^=", CCOK::CaretEq),
      std::make_pair("|", CCOK::Pipe),
      std::make_pair("|=", CCOK::PipeEq),
      std::make_pair("||", CCOK::PipePipe),
      std::make_pair("~=", CCOK::TildeEq),
  };
  static auto opsSize = sizeof(ops) / sizeof(ops[0]);

  auto I = std::lower_bound(
      ops, &ops[opsSize], std::make_pair(name, CCOK::None),
      [](const OpPair &a, const OpPair &b) { return a.first < b.first; });

  if (I == &ops[opsSize] || I->first != name)
    return CCOK::Unknown;
  return I->second;
}

static StringRef getOperatorName(CodeCompletionString *str) {
  return str->getFirstTextChunk(/*includeLeadingPunctuation=*/true);
}

CodeCompletionOperatorKind
CodeCompletionResult::getCodeCompletionOperatorKind(CodeCompletionString *str) {
  return getCodeCompletionOperatorKind(getOperatorName(str));
}

CodeCompletionResult *CodeCompletionResultBuilder::takeResult() {
  auto *CCS = CodeCompletionString::create(*Sink.Allocator, Chunks);

  switch (Kind) {
  case CodeCompletionResult::ResultKind::Declaration: {
    StringRef BriefComment;
    auto MaybeClangNode = AssociatedDecl->getClangNode();
    if (MaybeClangNode) {
      if (auto *D = MaybeClangNode.getAsDecl()) {
        const auto &ClangContext = D->getASTContext();
        if (const clang::RawComment *RC =
                ClangContext.getRawCommentForAnyRedecl(D))
          BriefComment = RC->getBriefText(ClangContext);
      }
    } else {
      BriefComment = AssociatedDecl->getBriefComment();
    }

    StringRef ModuleName;
    if (CurrentModule) {
      if (Sink.LastModule.first == CurrentModule.getOpaqueValue()) {
        ModuleName = Sink.LastModule.second;
      } else {
        if (auto *C = CurrentModule.dyn_cast<const clang::Module *>()) {
          ModuleName = copyString(*Sink.Allocator, C->getFullModuleName());
        } else {
          ModuleName = copyString(
              *Sink.Allocator,
              CurrentModule.get<const swift::ModuleDecl *>()->getName().str());
        }
        Sink.LastModule.first = CurrentModule.getOpaqueValue();
        Sink.LastModule.second = ModuleName;
      }
    }

    return new (*Sink.Allocator) CodeCompletionResult(
        SemanticContext, NumBytesToErase, CCS, AssociatedDecl, ModuleName,
        /*NotRecommended=*/IsNotRecommended, NotRecReason,
        copyString(*Sink.Allocator, BriefComment),
        copyAssociatedUSRs(*Sink.Allocator, AssociatedDecl),
        copyArray(*Sink.Allocator, CommentWords), ExpectedTypeRelation);
  }

  case CodeCompletionResult::ResultKind::Keyword:
    return new (*Sink.Allocator)
        CodeCompletionResult(
          KeywordKind, SemanticContext, NumBytesToErase,
          CCS, ExpectedTypeRelation,
          copyString(*Sink.Allocator, BriefDocComment));

  case CodeCompletionResult::ResultKind::BuiltinOperator:
  case CodeCompletionResult::ResultKind::Pattern:
    return new (*Sink.Allocator) CodeCompletionResult(
        Kind, SemanticContext, NumBytesToErase, CCS, ExpectedTypeRelation,
        CodeCompletionOperatorKind::None,
        copyString(*Sink.Allocator, BriefDocComment));

  case CodeCompletionResult::ResultKind::Literal:
    assert(LiteralKind.hasValue());
    return new (*Sink.Allocator)
        CodeCompletionResult(*LiteralKind, SemanticContext, NumBytesToErase,
                             CCS, ExpectedTypeRelation);
  }

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

void CodeCompletionResultBuilder::finishResult() {
  if (!Cancelled)
    Sink.Results.push_back(takeResult());
}


MutableArrayRef<CodeCompletionResult *> CodeCompletionContext::takeResults() {
  // Copy pointers to the results.
  const size_t Count = CurrentResults.Results.size();
  CodeCompletionResult **Results =
      CurrentResults.Allocator->Allocate<CodeCompletionResult *>(Count);
  std::copy(CurrentResults.Results.begin(), CurrentResults.Results.end(),
            Results);
  CurrentResults.Results.clear();
  return MutableArrayRef<CodeCompletionResult *>(Results, Count);
}

Optional<unsigned> CodeCompletionString::getFirstTextChunkIndex(
    bool includeLeadingPunctuation) const {
  for (auto i : indices(getChunks())) {
    auto &C = getChunks()[i];
    switch (C.getKind()) {
    using ChunkKind = Chunk::ChunkKind;
    case ChunkKind::Text:
    case ChunkKind::CallParameterName:
    case ChunkKind::CallParameterInternalName:
    case ChunkKind::GenericParameterName:
    case ChunkKind::LeftParen:
    case ChunkKind::LeftBracket:
    case ChunkKind::Equal:
    case ChunkKind::DeclAttrParamKeyword:
    case ChunkKind::DeclAttrKeyword:
    case ChunkKind::Keyword:
    case ChunkKind::Attribute:
    case ChunkKind::BaseName:
    case ChunkKind::TypeIdSystem:
    case ChunkKind::TypeIdUser:
    case ChunkKind::CallParameterBegin:
      return i;
    case ChunkKind::Dot:
    case ChunkKind::ExclamationMark:
    case ChunkKind::QuestionMark:
      if (includeLeadingPunctuation)
        return i;
      continue;
    case ChunkKind::RightParen:
    case ChunkKind::RightBracket:
    case ChunkKind::LeftAngle:
    case ChunkKind::RightAngle:
    case ChunkKind::Ellipsis:
    case ChunkKind::Comma:
    case ChunkKind::Ampersand:
    case ChunkKind::Whitespace:
    case ChunkKind::AccessControlKeyword:
    case ChunkKind::OverrideKeyword:
    case ChunkKind::EffectsSpecifierKeyword:
    case ChunkKind::DeclIntroducer:
    case ChunkKind::CallParameterColon:
    case ChunkKind::CallParameterTypeBegin:
    case ChunkKind::DeclAttrParamColon:
    case ChunkKind::CallParameterType:
    case ChunkKind::CallParameterClosureType:
    case ChunkKind::CallParameterClosureExpr:
    case ChunkKind::OptionalBegin:
    case ChunkKind::GenericParameterBegin:
    case ChunkKind::DynamicLookupMethodCallTail:
    case ChunkKind::OptionalMethodCallTail:
    case ChunkKind::TypeAnnotation:
    case ChunkKind::TypeAnnotationBegin:
      continue;

    case ChunkKind::BraceStmtWithCursor:
      llvm_unreachable("should have already extracted the text");
    }
  }
  return None;
}

StringRef
CodeCompletionString::getFirstTextChunk(bool includeLeadingPunctuation) const {
  Optional<unsigned> Idx = getFirstTextChunkIndex(includeLeadingPunctuation);
  if (Idx.hasValue())
    return getChunks()[*Idx].getText();
  return StringRef();
}

void CodeCompletionString::getName(raw_ostream &OS) const {
  auto FirstTextChunk = getFirstTextChunkIndex();
  int TextSize = 0;
  if (FirstTextChunk.hasValue()) {
    auto chunks = getChunks().slice(*FirstTextChunk);

    for (auto i = chunks.begin(), e = chunks.end(); i != e; ++i) {
      using ChunkKind = Chunk::ChunkKind;

      bool shouldPrint = !i->isAnnotation();
      switch (i->getKind()) {
      case ChunkKind::TypeAnnotation:
      case ChunkKind::CallParameterClosureType:
      case ChunkKind::CallParameterClosureExpr:
      case ChunkKind::DeclAttrParamColon:
      case ChunkKind::OptionalMethodCallTail:
        continue;
      case ChunkKind::TypeAnnotationBegin: {
        auto level = i->getNestingLevel();
        do { ++i; } while (i != e && !i->endsPreviousNestedGroup(level));
        --i;
        continue;
      }
      case ChunkKind::EffectsSpecifierKeyword:
        shouldPrint = true; // Even when they're annotations.
        break;
      default:
        break;
      }

      if (i->hasText() && shouldPrint) {
        TextSize += i->getText().size();
        OS << i->getText();
      }
    }
  }
}

void CodeCompletionContext::sortCompletionResults(
    MutableArrayRef<CodeCompletionResult *> Results) {
  struct ResultAndName {
    CodeCompletionResult *result;
    std::string name;
  };

  // Caching the name of each field is important to avoid unnecessary calls to
  // CodeCompletionString::getName().
  std::vector<ResultAndName> nameCache(Results.size());
  for (unsigned i = 0, n = Results.size(); i < n; ++i) {
    auto *result = Results[i];
    nameCache[i].result = result;
    llvm::raw_string_ostream OS(nameCache[i].name);
    result->getCompletionString()->getName(OS);
    OS.flush();
  }

  // Sort nameCache, and then transform Results to return the pointers in order.
  std::sort(nameCache.begin(), nameCache.end(),
            [](const ResultAndName &LHS, const ResultAndName &RHS) {
    int Result = StringRef(LHS.name).compare_lower(RHS.name);
    // If the case insensitive comparison is equal, then secondary sort order
    // should be case sensitive.
    if (Result == 0)
      Result = LHS.name.compare(RHS.name);
    return Result < 0;
  });

  std::transform(nameCache.begin(), nameCache.end(), Results.begin(),
                 [](const ResultAndName &entry) { return entry.result; });
}

namespace {

class CodeCompletionCallbacksImpl : public CodeCompletionCallbacks {
  CodeCompletionContext &CompletionContext;
  CodeCompletionConsumer &Consumer;
  CodeCompletionExpr *CodeCompleteTokenExpr = nullptr;
  CompletionKind Kind = CompletionKind::None;
  Expr *ParsedExpr = nullptr;
  SourceLoc DotLoc;
  TypeLoc ParsedTypeLoc;
  DeclContext *CurDeclContext = nullptr;
  DeclAttrKind AttrKind;

  /// In situations when \c SyntaxKind hints or determines
  /// completions, i.e. a precedence group attribute, this
  /// can be set and used to control the code completion scenario.
  SyntaxKind SyntxKind;

  int AttrParamIndex;
  bool IsInSil = false;
  bool HasSpace = false;
  bool ShouldCompleteCallPatternAfterParen = true;
  bool PreferFunctionReferencesToCalls = false;
  bool AttTargetIsIndependent = false;
  bool IsAtStartOfLine = false;
  Optional<DeclKind> AttTargetDK;
  Optional<StmtKind> ParentStmtKind;

  SmallVector<StringRef, 3> ParsedKeywords;
  SourceLoc introducerLoc;

  std::vector<std::pair<std::string, bool>> SubModuleNameVisibilityPairs;

  void addSuperKeyword(CodeCompletionResultSink &Sink) {
    auto *DC = CurDeclContext->getInnermostTypeContext();
    if (!DC)
      return;
    auto *CD = DC->getSelfClassDecl();
    if (!CD)
      return;
    Type ST = CD->getSuperclass();
    if (ST.isNull() || ST->is<ErrorType>())
      return;

    CodeCompletionResultBuilder Builder(Sink,
                                        CodeCompletionResult::ResultKind::Keyword,
                                        SemanticContextKind::CurrentNominal,
                                        {});
    Builder.setKeywordKind(CodeCompletionKeywordKind::kw_super);
    Builder.addKeyword("super");
    Builder.addTypeAnnotation(ST, PrintOptions());
  }

  Optional<std::pair<Type, ConcreteDeclRef>> typeCheckParsedExpr() {
    assert(ParsedExpr && "should have an expression");

    // Figure out the kind of type-check we'll be performing.
    auto CheckKind = CompletionTypeCheckKind::Normal;
    if (Kind == CompletionKind::KeyPathExprObjC)
      CheckKind = CompletionTypeCheckKind::KeyPath;

    // If we've already successfully type-checked the expression for some
    // reason, just return the type.
    // FIXME: if it's ErrorType but we've already typechecked we shouldn't
    // typecheck again. rdar://21466394
    if (CheckKind == CompletionTypeCheckKind::Normal &&
        ParsedExpr->getType() && !ParsedExpr->getType()->is<ErrorType>()) {
      return getReferencedDecl(ParsedExpr);
    }

    ConcreteDeclRef ReferencedDecl = nullptr;
    Expr *ModifiedExpr = ParsedExpr;
    if (auto T = getTypeOfCompletionContextExpr(P.Context, CurDeclContext,
                                                CheckKind, ModifiedExpr,
                                                ReferencedDecl)) {
      // FIXME: even though we don't apply the solution, the type checker may
      // modify the original expression. We should understand what effect that
      // may have on code completion.
      ParsedExpr = ModifiedExpr;

      return std::make_pair(*T, ReferencedDecl);
    }
    return None;
  }

  /// \returns true on success, false on failure.
  bool typecheckParsedType() {
    assert(ParsedTypeLoc.getTypeRepr() && "should have a TypeRepr");
    if (ParsedTypeLoc.wasValidated() && !ParsedTypeLoc.isError()) {
      return true;
    }

    const auto ty = swift::performTypeResolution(
        ParsedTypeLoc.getTypeRepr(), P.Context,
        /*isSILMode=*/false,
        /*isSILType=*/false,
        CurDeclContext->getGenericEnvironmentOfContext(),
        /*GenericParams=*/nullptr,
        CurDeclContext,
        /*ProduceDiagnostics=*/false);
    ParsedTypeLoc.setType(ty);
    if (!ParsedTypeLoc.isError()) {
      return true;
    }

    // It doesn't type check as a type, so see if it's a qualifying module name.
    if (auto *ITR = dyn_cast<IdentTypeRepr>(ParsedTypeLoc.getTypeRepr())) {
      const auto &componentRange = ITR->getComponentRange();
      // If it has more than one component, it can't be a module name.
      if (std::distance(componentRange.begin(), componentRange.end()) != 1)
        return false;

      const auto &component = componentRange.front();
      ImportPath::Module::Builder builder(
          component->getNameRef().getBaseIdentifier(),
          component->getLoc());

      if (auto Module = Context.getLoadedModule(builder.get()))
        ParsedTypeLoc.setType(ModuleType::get(Module));
      return true;
    }
    return false;
  }

public:
  CodeCompletionCallbacksImpl(Parser &P,
                              CodeCompletionContext &CompletionContext,
                              CodeCompletionConsumer &Consumer)
      : CodeCompletionCallbacks(P), CompletionContext(CompletionContext),
        Consumer(Consumer) {
  }

  void setAttrTargetDeclKind(Optional<DeclKind> DK) override {
    if (DK == DeclKind::PatternBinding)
      DK = DeclKind::Var;
    else if (DK == DeclKind::Param)
      // For params, consider the attribute is always for the decl.
      AttTargetIsIndependent = false;

    if (!AttTargetIsIndependent)
      AttTargetDK = DK;
  }

  void completeDotExpr(CodeCompletionExpr *E, SourceLoc DotLoc) override;
  void completeStmtOrExpr(CodeCompletionExpr *E) override;
  void completePostfixExprBeginning(CodeCompletionExpr *E) override;
  void completeForEachSequenceBeginning(CodeCompletionExpr *E) override;
  void completePostfixExpr(Expr *E, bool hasSpace) override;
  void completePostfixExprParen(Expr *E, Expr *CodeCompletionE) override;
  void completeExprKeyPath(KeyPathExpr *KPE, SourceLoc DotLoc) override;

  void completeTypeDeclResultBeginning() override;
  void completeTypeSimpleBeginning() override;
  void completeTypeIdentifierWithDot(IdentTypeRepr *ITR) override;
  void completeTypeIdentifierWithoutDot(IdentTypeRepr *ITR) override;

  void completeCaseStmtKeyword() override;
  void completeCaseStmtBeginning(CodeCompletionExpr *E) override;
  void completeDeclAttrBeginning(bool Sil, bool isIndependent) override;
  void completeDeclAttrParam(DeclAttrKind DK, int Index) override;
  void completeEffectsSpecifier(bool hasAsync, bool hasThrows) override;
  void completeInPrecedenceGroup(SyntaxKind SK) override;
  void completeNominalMemberBeginning(
      SmallVectorImpl<StringRef> &Keywords, SourceLoc introducerLoc) override;
  void completeAccessorBeginning(CodeCompletionExpr *E) override;

  void completePoundAvailablePlatform() override;
  void completeImportDecl(ImportPath::Builder &Path) override;
  void completeUnresolvedMember(CodeCompletionExpr *E,
                                SourceLoc DotLoc) override;
  void completeCallArg(CodeCompletionExpr *E, bool isFirst) override;
  void completeLabeledTrailingClosure(CodeCompletionExpr *E,
                                      bool isAtStartOfLine) override;

  bool canPerformCompleteLabeledTrailingClosure() const override {
    return true;
  }

  void completeReturnStmt(CodeCompletionExpr *E) override;
  void completeYieldStmt(CodeCompletionExpr *E,
                         Optional<unsigned> yieldIndex) override;
  void completeAfterPoundExpr(CodeCompletionExpr *E,
                              Optional<StmtKind> ParentKind) override;
  void completeAfterPoundDirective() override;
  void completePlatformCondition() override;
  void completeGenericRequirement() override;
  void completeAfterIfStmt(bool hasElse) override;
  void completeStmtLabel(StmtKind ParentKind) override;

  void doneParsing() override;

private:
  void addKeywords(CodeCompletionResultSink &Sink, bool MaybeFuncBody);
  bool trySolverCompletion(bool MaybeFuncBody);
};
} // end anonymous namespace

namespace {
static bool isTopLevelSubcontext(const DeclContext *DC) {
  for (; DC && DC->isLocalContext(); DC = DC->getParent()) {
    switch (DC->getContextKind()) {
    case DeclContextKind::TopLevelCodeDecl:
      return true;
    case DeclContextKind::AbstractFunctionDecl:
    case DeclContextKind::SubscriptDecl:
    case DeclContextKind::EnumElementDecl:
      return false;
    default:
      continue;
    }
  }
  return false;
}

static KnownProtocolKind
protocolForLiteralKind(CodeCompletionLiteralKind kind) {
  switch (kind) {
  case CodeCompletionLiteralKind::ArrayLiteral:
    return KnownProtocolKind::ExpressibleByArrayLiteral;
  case CodeCompletionLiteralKind::BooleanLiteral:
    return KnownProtocolKind::ExpressibleByBooleanLiteral;
  case CodeCompletionLiteralKind::ColorLiteral:
    return KnownProtocolKind::ExpressibleByColorLiteral;
  case CodeCompletionLiteralKind::ImageLiteral:
    return KnownProtocolKind::ExpressibleByImageLiteral;
  case CodeCompletionLiteralKind::DictionaryLiteral:
    return KnownProtocolKind::ExpressibleByDictionaryLiteral;
  case CodeCompletionLiteralKind::IntegerLiteral:
    return KnownProtocolKind::ExpressibleByIntegerLiteral;
  case CodeCompletionLiteralKind::NilLiteral:
    return KnownProtocolKind::ExpressibleByNilLiteral;
  case CodeCompletionLiteralKind::StringLiteral:
    return KnownProtocolKind::ExpressibleByUnicodeScalarLiteral;
  case CodeCompletionLiteralKind::Tuple:
    llvm_unreachable("no such protocol kind");
  }

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

static Type
defaultTypeLiteralKind(CodeCompletionLiteralKind kind, ASTContext &Ctx) {
  switch (kind) {
  case CodeCompletionLiteralKind::BooleanLiteral:
    return Ctx.getBoolDecl()->getDeclaredInterfaceType();
  case CodeCompletionLiteralKind::IntegerLiteral:
    return Ctx.getIntDecl()->getDeclaredInterfaceType();
  case CodeCompletionLiteralKind::StringLiteral:
    return Ctx.getStringDecl()->getDeclaredInterfaceType();
  case CodeCompletionLiteralKind::ArrayLiteral:
    return Ctx.getArrayDecl()->getDeclaredType();
  case CodeCompletionLiteralKind::DictionaryLiteral:
    return Ctx.getDictionaryDecl()->getDeclaredType();
  case CodeCompletionLiteralKind::NilLiteral:
  case CodeCompletionLiteralKind::ColorLiteral:
  case CodeCompletionLiteralKind::ImageLiteral:
  case CodeCompletionLiteralKind::Tuple:
    return Type();
  }

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

/// Whether funcType has a single argument (not including defaulted arguments)
/// that is of type () -> ().
static bool hasTrivialTrailingClosure(const FuncDecl *FD,
                                      AnyFunctionType *funcType) {
  ParameterListInfo paramInfo(funcType->getParams(), FD,
                              /*skipCurriedSelf*/ FD->hasCurriedSelf());

  if (paramInfo.size() - paramInfo.numNonDefaultedParameters() == 1) {
    auto param = funcType->getParams().back();
    if (!param.isAutoClosure()) {
      if (auto Fn = param.getOldType()->getAs<AnyFunctionType>()) {
        return Fn->getParams().empty() && Fn->getResult()->isVoid();
      }
    }
  }

  return false;
}

/// Build completions by doing visible decl lookup from a context.
class CompletionLookup final : public swift::VisibleDeclConsumer {
  CodeCompletionResultSink &Sink;
  ASTContext &Ctx;
  const DeclContext *CurrDeclContext;
  ModuleDecl *CurrModule;
  ClangImporter *Importer;
  CodeCompletionContext *CompletionContext;

  enum class LookupKind {
    ValueExpr,
    ValueInDeclContext,
    EnumElement,
    Type,
    TypeInDeclContext,
    ImportFromModule,
    GenericRequirement,
  };

  LookupKind Kind;

  /// Type of the user-provided expression for LookupKind::ValueExpr
  /// completions.
  Type ExprType;

  /// Whether the expr is of statically inferred metatype.
  bool IsStaticMetatype = false;

  /// User-provided base type for LookupKind::Type completions.
  Type BaseType;

  /// Expected types of the code completion expression.
  ExpectedTypeContext expectedTypeContext;

  bool HaveDot = false;
  bool IsUnwrappedOptional = false;
  SourceLoc DotLoc;
  bool NeedLeadingDot = false;

  bool NeedOptionalUnwrap = false;
  unsigned NumBytesToEraseForOptionalUnwrap = 0;

  bool HaveLParen = false;
  bool IsSuperRefExpr = false;
  bool IsSelfRefExpr = false;
  bool IsKeyPathExpr = false;
  bool IsSwiftKeyPathExpr = false;
  bool IsAfterSwiftKeyPathRoot = false;
  bool IsDynamicLookup = false;
  bool PreferFunctionReferencesToCalls = false;
  bool HaveLeadingSpace = false;

  bool CheckForDuplicates = false;
  llvm::DenseSet<std::pair<const Decl *, Type>> PreviouslySeen;

  bool IncludeInstanceMembers = false;

  /// True if we are code completing inside a static method.
  bool InsideStaticMethod = false;

  /// Innermost method that the code completion point is in.
  const AbstractFunctionDecl *CurrentMethod = nullptr;

  Optional<SemanticContextKind> ForcedSemanticContext = None;
  bool IsUnresolvedMember = false;

public:
  bool FoundFunctionCalls = false;
  bool FoundFunctionsWithoutFirstKeyword = false;

private:
  void foundFunction(const AbstractFunctionDecl *AFD) {
    FoundFunctionCalls = true;
    const DeclName Name = AFD->getName();
    auto ArgNames = Name.getArgumentNames();
    if (ArgNames.empty())
      return;
    if (ArgNames[0].empty())
      FoundFunctionsWithoutFirstKeyword = true;
  }

  void foundFunction(const AnyFunctionType *AFT) {
    FoundFunctionCalls = true;
    auto Params = AFT->getParams();
    if (Params.empty())
      return;
    if (Params.size() == 1 && !Params[0].hasLabel()) {
      FoundFunctionsWithoutFirstKeyword = true;
      return;
    }
    if (!Params[0].hasLabel())
      FoundFunctionsWithoutFirstKeyword = true;
  }

  void setClangDeclKeywords(const ValueDecl *VD, CommandWordsPairs &Pairs,
                            CodeCompletionResultBuilder &Builder) {
    if (auto *CD = VD->getClangDecl()) {
      clang::comments::getClangDocKeyword(*Importer, CD, Pairs);
    } else {
      swift::markup::getSwiftDocKeyword(VD, Pairs);
    }
    Builder.addDeclDocCommentWords(llvm::makeArrayRef(Pairs));
  }

  /// Returns \c true if \p TAD is usable as a first type of a requirement in
  /// \c where clause for a context.
  /// \p selfTy must be a \c Self type of the context.
  static bool canBeUsedAsRequirementFirstType(Type selfTy, TypeAliasDecl *TAD) {
    auto T = TAD->getDeclaredInterfaceType();
    auto subMap = selfTy->getMemberSubstitutionMap(TAD->getParentModule(), TAD);
    T = T.subst(subMap)->getCanonicalType();

    ArchetypeType *archeTy = T->getAs<ArchetypeType>();
    if (!archeTy)
      return false;
    archeTy = archeTy->getRoot();

    // For protocol, the 'archeTy' should match with the 'baseTy' which is the
    // dynamic 'Self' type of the protocol. For nominal decls, 'archTy' should
    // be one of the generic params in 'selfTy'. Search 'archeTy' in 'baseTy'.
    return selfTy.findIf([&](Type T) { return archeTy->isEqual(T); });
  }

public:
  struct RequestedResultsTy {
    const ModuleDecl *TheModule;
    bool OnlyTypes;
    bool OnlyPrecedenceGroups;
    bool NeedLeadingDot;
    bool IncludeModuleQualifier;

    static RequestedResultsTy fromModule(const ModuleDecl *TheModule) {
      return { TheModule, false, false, false, true };
    }

    RequestedResultsTy onlyTypes() const {
      return { TheModule, true, false, NeedLeadingDot, IncludeModuleQualifier };
    }

    RequestedResultsTy onlyPrecedenceGroups() const {
      assert(!OnlyTypes && "onlyTypes() already includes precedence groups");
      return { TheModule, false, true, false, true };
    }

    RequestedResultsTy needLeadingDot(bool NeedDot) const {
      return {
          TheModule, OnlyTypes, OnlyPrecedenceGroups, NeedDot,
          IncludeModuleQualifier
      };
    }

    RequestedResultsTy withModuleQualifier(bool IncludeModule) const {
        return {
            TheModule, OnlyTypes, OnlyPrecedenceGroups, NeedLeadingDot,
            IncludeModule
        };
    }

    static RequestedResultsTy toplevelResults() {
      return { nullptr, false, false, false, true };
    }
  };

  std::vector<RequestedResultsTy> RequestedCachedResults;

public:
  CompletionLookup(CodeCompletionResultSink &Sink,
                   ASTContext &Ctx,
                   const DeclContext *CurrDeclContext,
                   CodeCompletionContext *CompletionContext = nullptr)
      : Sink(Sink), Ctx(Ctx), CurrDeclContext(CurrDeclContext),
        CurrModule(CurrDeclContext ? CurrDeclContext->getParentModule()
                                   : nullptr),
        Importer(static_cast<ClangImporter *>(CurrDeclContext->getASTContext().
          getClangModuleLoader())),
        CompletionContext(CompletionContext) {
    // Determine if we are doing code completion inside a static method.
    if (CurrDeclContext) {
      CurrentMethod = CurrDeclContext->getInnermostMethodContext();
      if (auto *FD = dyn_cast_or_null<FuncDecl>(CurrentMethod))
        InsideStaticMethod = FD->isStatic();
    }
  }

  void setHaveDot(SourceLoc DotLoc) {
    HaveDot = true;
    this->DotLoc = DotLoc;
  }

  void setIsUnwrappedOptional(bool value) {
    IsUnwrappedOptional = value;
  }

  void setIsStaticMetatype(bool value) {
    IsStaticMetatype = value;
  }

  void setExpectedTypes(ArrayRef<Type> Types,
                        bool isImplicitSingleExpressionReturn,
                        bool preferNonVoid = false) {
    expectedTypeContext.isImplicitSingleExpressionReturn =
        isImplicitSingleExpressionReturn;
    expectedTypeContext.preferNonVoid = preferNonVoid;
    expectedTypeContext.possibleTypes.clear();
    expectedTypeContext.possibleTypes.reserve(Types.size());
    for (auto T : Types)
      if (T)
        expectedTypeContext.possibleTypes.push_back(T);
  }

  void setIdealExpectedType(Type Ty) {
    expectedTypeContext.idealType = Ty;
  }

  CodeCompletionContext::TypeContextKind typeContextKind() const {
    if (expectedTypeContext.empty() && !expectedTypeContext.preferNonVoid) {
      return CodeCompletionContext::TypeContextKind::None;
    } else if (expectedTypeContext.isImplicitSingleExpressionReturn) {
      return CodeCompletionContext::TypeContextKind::SingleExpressionBody;
    } else {
      return CodeCompletionContext::TypeContextKind::Required;
    }
  }

  bool needDot() const {
    return NeedLeadingDot;
  }

  void setHaveLParen(bool Value) {
    HaveLParen = Value;
  }

  void setIsSuperRefExpr(bool Value = true) {
    IsSuperRefExpr = Value;
  }

  void setIsSelfRefExpr(bool value) { IsSelfRefExpr = value; }

  void setIsKeyPathExpr() {
    IsKeyPathExpr = true;
  }

  void shouldCheckForDuplicates(bool value = true) {
    CheckForDuplicates = value;
  }

  void setIsSwiftKeyPathExpr(bool onRoot) {
    IsSwiftKeyPathExpr = true;
    IsAfterSwiftKeyPathRoot = onRoot;
  }

  void setIsDynamicLookup() {
    IsDynamicLookup = true;
  }

  void setPreferFunctionReferencesToCalls() {
    PreferFunctionReferencesToCalls = true;
  }

  void setHaveLeadingSpace(bool value) { HaveLeadingSpace = value; }

  void includeInstanceMembers() {
    IncludeInstanceMembers = true;
  }

  void addSubModuleNames(std::vector<std::pair<std::string, bool>>
      &SubModuleNameVisibilityPairs) {
    for (auto &Pair : SubModuleNameVisibilityPairs) {
      CodeCompletionResultBuilder Builder(Sink,
                                          CodeCompletionResult::ResultKind::
                                          Declaration,
                                          SemanticContextKind::None,
                                          expectedTypeContext);
      auto MD = ModuleDecl::create(Ctx.getIdentifier(Pair.first), Ctx);
      Builder.setAssociatedDecl(MD);
      Builder.addBaseName(MD->getNameStr());
      Builder.addTypeAnnotation("Module");
      if (Pair.second)
        Builder.setNotRecommended(CodeCompletionResult::NotRecommendedReason::
                                    Redundant);
    }
  }

  void collectImportedModules(llvm::StringSet<> &ImportedModules) {
    SmallVector<ImportedModule, 16> Imported;
    SmallVector<ImportedModule, 16> FurtherImported;
    CurrDeclContext->getParentSourceFile()->getImportedModules(
        Imported,
        {ModuleDecl::ImportFilterKind::Exported,
         ModuleDecl::ImportFilterKind::Default,
         ModuleDecl::ImportFilterKind::ImplementationOnly});
    while (!Imported.empty()) {
      ModuleDecl *MD = Imported.back().importedModule;
      Imported.pop_back();
      if (!ImportedModules.insert(MD->getNameStr()).second)
        continue;
      FurtherImported.clear();
      MD->getImportedModules(FurtherImported,
                             ModuleDecl::ImportFilterKind::Exported);
      Imported.append(FurtherImported.begin(), FurtherImported.end());
    }
  }

  void addModuleName(
      ModuleDecl *MD,
      Optional<CodeCompletionResult::NotRecommendedReason> R = None) {

    // Don't add underscored cross-import overlay modules.
    if (MD->getDeclaringModuleIfCrossImportOverlay())
      return;

    CodeCompletionResultBuilder Builder(
        Sink,
        CodeCompletionResult::ResultKind::Declaration,
        SemanticContextKind::None,
        expectedTypeContext);
    Builder.setAssociatedDecl(MD);
    Builder.addBaseName(MD->getNameStr());
    Builder.addTypeAnnotation("Module");
    if (R)
      Builder.setNotRecommended(*R);
  }

  void addImportModuleNames() {
    SmallVector<Identifier, 0> ModuleNames;
    Ctx.getVisibleTopLevelModuleNames(ModuleNames);

    llvm::StringSet<> ImportedModules;
    collectImportedModules(ImportedModules);

    auto mainModuleName = CurrModule->getName();
    for (auto ModuleName : ModuleNames) {
      if (ModuleName.str().startswith("_") ||
          ModuleName == mainModuleName ||
          ModuleName == Ctx.SwiftShimsModuleName ||
          ModuleName.str() == SWIFT_ONONE_SUPPORT)
        continue;

      auto MD = ModuleDecl::create(ModuleName, Ctx);
      Optional<CodeCompletionResult::NotRecommendedReason> Reason = None;

      // Imported modules are not recommended.
      if (ImportedModules.count(MD->getNameStr()) != 0)
        Reason = CodeCompletionResult::NotRecommendedReason::Redundant;

      addModuleName(MD, Reason);
    }
  }

  SemanticContextKind getSemanticContext(const Decl *D,
                                         DeclVisibilityKind Reason,
                                         DynamicLookupInfo dynamicLookupInfo) {
    if (ForcedSemanticContext)
      return *ForcedSemanticContext;

    switch (Reason) {
    case DeclVisibilityKind::LocalVariable:
    case DeclVisibilityKind::FunctionParameter:
    case DeclVisibilityKind::GenericParameter:
      return SemanticContextKind::Local;

    case DeclVisibilityKind::MemberOfCurrentNominal:
      if (IsSuperRefExpr &&
          CurrentMethod && CurrentMethod->getOverriddenDecl() == D)
        return SemanticContextKind::ExpressionSpecific;
      return SemanticContextKind::CurrentNominal;

    case DeclVisibilityKind::MemberOfProtocolConformedToByCurrentNominal:
    case DeclVisibilityKind::MemberOfSuper:
      return SemanticContextKind::Super;

    case DeclVisibilityKind::MemberOfOutsideNominal:
      return SemanticContextKind::OutsideNominal;

    case DeclVisibilityKind::VisibleAtTopLevel:
      if (CurrDeclContext && D->getModuleContext() == CurrModule) {
        // Treat global variables from the same source file as local when
        // completing at top-level.
        if (isa<VarDecl>(D) && isTopLevelSubcontext(CurrDeclContext) &&
            D->getDeclContext()->getParentSourceFile() ==
                CurrDeclContext->getParentSourceFile()) {
          return SemanticContextKind::Local;
        } else {
          return SemanticContextKind::CurrentModule;
        }
      } else {
        return SemanticContextKind::OtherModule;
      }

    case DeclVisibilityKind::DynamicLookup:
      switch (dynamicLookupInfo.getKind()) {
      case DynamicLookupInfo::None:
        llvm_unreachable("invalid DynamicLookupInfo::Kind for dynamic lookup");

      case DynamicLookupInfo::AnyObject:
        // AnyObject results can come from different modules, including the
        // current module, but we always assign them the OtherModule semantic
        // context.  These declarations are uniqued by signature, so it is
        // totally random (determined by the hash function) which of the
        // equivalent declarations (across multiple modules) we will get.
        return SemanticContextKind::OtherModule;

      case DynamicLookupInfo::KeyPathDynamicMember:
        // Use the visibility of the underlying declaration.
        // FIXME: KeyPath<AnyObject, U> !?!?
        assert(dynamicLookupInfo.getKeyPathDynamicMember().originalVisibility !=
               DeclVisibilityKind::DynamicLookup);
        return getSemanticContext(
            D, dynamicLookupInfo.getKeyPathDynamicMember().originalVisibility,
            {});
      }

    case DeclVisibilityKind::MemberOfProtocolDerivedByCurrentNominal:
      llvm_unreachable("should not see this kind");
    }
    llvm_unreachable("unhandled kind");
  }

  bool isUnresolvedMemberIdealType(Type Ty) {
    assert(Ty);
    if (!IsUnresolvedMember)
      return false;
    Type idealTy = expectedTypeContext.idealType;
    if (!idealTy)
      return false;
    /// Consider optional object type is the ideal.
    /// For exmaple:
    ///   enum MyEnum { case foo, bar }
    ///   func foo(_: MyEnum?)
    ///   fooo(.<HERE>)
    /// Prefer '.foo' and '.bar' over '.some' and '.none'.
    idealTy = idealTy->lookThroughAllOptionalTypes();
    return idealTy->isEqual(Ty);
  }

  void addValueBaseName(CodeCompletionResultBuilder &Builder,
                        DeclBaseName Name) {
    auto NameStr = Name.userFacingName();
    bool shouldEscapeKeywords;
    if (Name.isSpecial()) {
      // Special names (i.e. 'init') are always displayed as its user facing
      // name.
      shouldEscapeKeywords = false;
    } else if (ExprType) {
      // After dot. User can write any keyword after '.' except for `init` and
      // `self`. E.g. 'func `init`()' must be called by 'expr.`init`()'.
      shouldEscapeKeywords = NameStr == "self" || NameStr == "init";
    } else {
      // As primary expresson. We have to escape almost every keywords except
      // for 'self' and 'Self'.
      shouldEscapeKeywords = NameStr != "self" && NameStr != "Self";
    }

    if (!shouldEscapeKeywords) {
      Builder.addBaseName(NameStr);
    } else {
      SmallString<16> buffer;
      Builder.addBaseName(Builder.escapeKeyword(NameStr, true, buffer));
    }
  }

  void addLeadingDot(CodeCompletionResultBuilder &Builder) {
    if (NeedOptionalUnwrap) {
      Builder.setNumBytesToErase(NumBytesToEraseForOptionalUnwrap);
      Builder.addQuestionMark();
      Builder.addLeadingDot();
      return;
    }
    if (needDot())
      Builder.addLeadingDot();
  }

  void addTypeAnnotation(CodeCompletionResultBuilder &Builder, Type T,
                         GenericSignature genericSig = GenericSignature()) {
    PrintOptions PO;
    PO.OpaqueReturnTypePrinting =
        PrintOptions::OpaqueReturnTypePrintingMode::WithoutOpaqueKeyword;
    if (auto typeContext = CurrDeclContext->getInnermostTypeContext())
      PO.setBaseType(typeContext->getDeclaredTypeInContext());
    Builder.addTypeAnnotation(eraseArchetypes(T, genericSig), PO);
    Builder.setExpectedTypeRelation(
        calculateMaxTypeRelation(T, expectedTypeContext, CurrDeclContext));
  }

  void addTypeAnnotationForImplicitlyUnwrappedOptional(
      CodeCompletionResultBuilder &Builder, Type T,
      GenericSignature genericSig = GenericSignature(),
      bool dynamicOrOptional = false) {

    std::string suffix;
    // FIXME: This retains previous behavior, but in reality the type of dynamic
    // lookups is IUO, not Optional as it is for the @optional attribute.
    if (dynamicOrOptional) {
      T = T->getOptionalObjectType();
      suffix = "?";
    }

    PrintOptions PO;
    PO.PrintOptionalAsImplicitlyUnwrapped = true;
    PO.OpaqueReturnTypePrinting =
        PrintOptions::OpaqueReturnTypePrintingMode::WithoutOpaqueKeyword;
    if (auto typeContext = CurrDeclContext->getInnermostTypeContext())
      PO.setBaseType(typeContext->getDeclaredTypeInContext());
    Builder.addTypeAnnotation(eraseArchetypes(T, genericSig), PO, suffix);
    Builder.setExpectedTypeRelation(
        calculateMaxTypeRelation(T, expectedTypeContext, CurrDeclContext));
  }

  /// For printing in code completion results, replace archetypes with
  /// protocol compositions.
  ///
  /// FIXME: Perhaps this should be an option in PrintOptions instead.
  Type eraseArchetypes(Type type, GenericSignature genericSig) {
    if (!genericSig)
      return type;

    auto buildProtocolComposition = [&](ArrayRef<ProtocolDecl *> protos) -> Type {
      SmallVector<Type, 2> types;
      for (auto proto : protos)
        types.push_back(proto->getDeclaredInterfaceType());
      return ProtocolCompositionType::get(Ctx, types,
                                          /*HasExplicitAnyObject=*/false);
    };

    if (auto *genericFuncType = type->getAs<GenericFunctionType>()) {
      SmallVector<AnyFunctionType::Param, 8> erasedParams;
      for (const auto &param : genericFuncType->getParams()) {
        auto erasedTy = eraseArchetypes(param.getPlainType(), genericSig);
        erasedParams.emplace_back(erasedTy, param.getLabel(),
                                  param.getParameterFlags());
      }
      return GenericFunctionType::get(genericSig,
          erasedParams,
          eraseArchetypes(genericFuncType->getResult(), genericSig),
          genericFuncType->getExtInfo());
    }

    return type.transform([&](Type t) -> Type {
      // FIXME: Code completion should only deal with one or the other,
      // and not both.
      if (auto *archetypeType = t->getAs<ArchetypeType>()) {
        // Don't erase opaque archetype.
        if (isa<OpaqueTypeArchetypeType>(archetypeType))
          return t;

        auto protos = archetypeType->getConformsTo();
        if (!protos.empty())
          return buildProtocolComposition(protos);
      }

      if (t->isTypeParameter()) {
        const auto protos = genericSig->getRequiredProtocols(t);
        if (!protos.empty())
          return buildProtocolComposition(protos);
      }

      return t;
    });
  }

  Type getTypeOfMember(const ValueDecl *VD,
                       DynamicLookupInfo dynamicLookupInfo) {
    switch (dynamicLookupInfo.getKind()) {
    case DynamicLookupInfo::None:
      return getTypeOfMember(VD, this->ExprType);
    case DynamicLookupInfo::AnyObject:
      return getTypeOfMember(VD, Type());
    case DynamicLookupInfo::KeyPathDynamicMember: {
      auto &keyPathInfo = dynamicLookupInfo.getKeyPathDynamicMember();

      // Map the result of VD to keypath member lookup results.
      // Given:
      //   struct Wrapper<T> {
      //     subscript<U>(dynamicMember: KeyPath<T, U>) -> Wrapped<U> { get }
      //   }
      //   struct Circle {
      //     var center: Point { get }
      //     var radius: Length { get }
      //   }
      //
      // Consider 'Wrapper<Circle>.center'.
      //   'VD' is 'Circle.center' decl.
      //   'keyPathInfo.subscript' is 'Wrapper<T>.subscript' decl.
      //   'keyPathInfo.baseType' is 'Wrapper<Circle>' type.

      // FIXME: Handle nested keypath member lookup.
      // i.e. cases where 'ExprType' != 'keyPathInfo.baseType'.

      auto *SD = keyPathInfo.subscript;
      const auto elementTy = SD->getElementInterfaceType();
      if (!elementTy->hasTypeParameter())
        return elementTy;

      // Map is:
      //   { τ_0_0(T) => Circle
      //     τ_1_0(U) => U }
      auto subs = keyPathInfo.baseType->getMemberSubstitutions(SD);

      // If the keyPath result type has type parameters, that might affect the
      // subscript result type.
      auto keyPathResultTy = getResultTypeOfKeypathDynamicMember(SD)->
        mapTypeOutOfContext();
      if (keyPathResultTy->hasTypeParameter()) {
        auto keyPathRootTy = getRootTypeOfKeypathDynamicMember(SD).
          subst(QueryTypeSubstitutionMap{subs},
                LookUpConformanceInModule(CurrModule));

        // The result type of the VD.
        // i.e. 'Circle.center' => 'Point'.
        auto innerResultTy = getTypeOfMember(VD, keyPathRootTy);

        if (auto paramTy = keyPathResultTy->getAs<GenericTypeParamType>()) {
          // Replace keyPath result type in the map with the inner result type.
          // i.e. Make the map as:
          //   { τ_0_0(T) => Circle
          //     τ_1_0(U) => Point }
          auto key =
              paramTy->getCanonicalType()->castTo<GenericTypeParamType>();
          subs[key] = innerResultTy;
        } else {
          // FIXME: Handle the case where the KeyPath result is generic.
          // e.g. 'subscript<U>(dynamicMember: KeyPath<T, Box<U>>) -> Bag<U>'
          // For now, just return the inner type.
          return innerResultTy;
        }
      }

      // Substitute the element type of the subscript using modified map.
      // i.e. 'Wrapped<U>' => 'Wrapped<Point>'.
      return elementTy.subst(QueryTypeSubstitutionMap{subs},
                             LookUpConformanceInModule(CurrModule));
    }
    }
    llvm_unreachable("Unhandled DynamicLookupInfo Kind in switch");
  }

  Type getTypeOfMember(const ValueDecl *VD, Type ExprType) {
    Type T = VD->getInterfaceType();
    assert(!T.isNull());

    if (ExprType) {
      Type ContextTy = VD->getDeclContext()->getDeclaredInterfaceType();
      if (ContextTy) {
        // Look through lvalue types and metatypes
        Type MaybeNominalType = ExprType->getRValueType();

        if (auto Metatype = MaybeNominalType->getAs<MetatypeType>())
          MaybeNominalType = Metatype->getInstanceType();

        if (auto SelfType = MaybeNominalType->getAs<DynamicSelfType>())
          MaybeNominalType = SelfType->getSelfType();

        // For optional protocol requirements and dynamic dispatch,
        // strip off optionality from the base type, but only if
        // we're not actually completing a member of Optional.
        if (!ContextTy->getOptionalObjectType() &&
            MaybeNominalType->getOptionalObjectType())
          MaybeNominalType = MaybeNominalType->getOptionalObjectType();

        // For dynamic lookup don't substitute in the base type.
        if (MaybeNominalType->isAnyObject())
          return T;

        // FIXME: Sometimes ExprType is the type of the member here,
        // and not the type of the base. That is inconsistent and
        // should be cleaned up.
        if (!MaybeNominalType->mayHaveMembers())
          return T;

        // We can't do anything if the base type has unbound generic parameters.
        if (MaybeNominalType->hasUnboundGenericType())
          return T;

        // For everything else, substitute in the base type.
        auto Subs = MaybeNominalType->getMemberSubstitutionMap(CurrModule, VD);

        // Pass in DesugarMemberTypes so that we see the actual
        // concrete type witnesses instead of type alias types.
        T = T.subst(Subs, SubstFlags::DesugarMemberTypes);
      }
    }

    return T;
  }

  Type getAssociatedTypeType(const AssociatedTypeDecl *ATD) {
    Type BaseTy = BaseType;
    if (!BaseTy)
      BaseTy = ExprType;
    if (!BaseTy && CurrDeclContext)
      BaseTy = CurrDeclContext->getInnermostTypeContext()
                   ->getDeclaredTypeInContext();
    if (BaseTy) {
      BaseTy = BaseTy->getInOutObjectType()->getMetatypeInstanceType();
      if (auto NTD = BaseTy->getAnyNominal()) {
        auto *Module = NTD->getParentModule();
        auto Conformance = Module->lookupConformance(
            BaseTy, ATD->getProtocol());
        if (Conformance.isConcrete()) {
          return Conformance.getConcrete()->getTypeWitness(
              const_cast<AssociatedTypeDecl *>(ATD));
        }
      }
    }
    return Type();
  }

  void addVarDeclRef(const VarDecl *VD, DeclVisibilityKind Reason,
                     DynamicLookupInfo dynamicLookupInfo) {
    if (!VD->hasName())
      return;

    const Identifier Name = VD->getName();
    assert(!Name.empty() && "name should not be empty");

    CommandWordsPairs Pairs;
    CodeCompletionResultBuilder Builder(
        Sink, CodeCompletionResult::ResultKind::Declaration,
        getSemanticContext(VD, Reason, dynamicLookupInfo), expectedTypeContext);
    Builder.setAssociatedDecl(VD);
    addLeadingDot(Builder);
    addValueBaseName(Builder, Name);
    setClangDeclKeywords(VD, Pairs, Builder);

    // "not recommended" in its own getter.
    if (Kind == LookupKind::ValueInDeclContext) {
      if (auto accessor = dyn_cast<AccessorDecl>(CurrDeclContext)) {
        if (accessor->getStorage() == VD && accessor->isGetter())
          Builder.setNotRecommended(CodeCompletionResult::NoReason);
      }
    }

    if (!VD->hasInterfaceType())
      return;

    // Add a type annotation.
    Type VarType = getTypeOfMember(VD, dynamicLookupInfo);
    if (auto *PD = dyn_cast<ParamDecl>(VD)) {
      if (Name != Ctx.Id_self && PD->isInOut()) {
        // It is useful to show inout for function parameters.
        // But for 'self' it is just noise.
        VarType = InOutType::get(VarType);
      }
    }
    auto DynamicOrOptional =
        IsDynamicLookup || VD->getAttrs().hasAttribute<OptionalAttr>();
    if (DynamicOrOptional) {
      // Values of properties that were found on a AnyObject have
      // Optional<T> type.  Same applies to optional members.
      VarType = OptionalType::get(VarType);
    }

    auto genericSig =
        VD->getInnermostDeclContext()->getGenericSignatureOfContext();
    if (VD->isImplicitlyUnwrappedOptional())
      addTypeAnnotationForImplicitlyUnwrappedOptional(
          Builder, VarType, genericSig, DynamicOrOptional);
    else
      addTypeAnnotation(Builder, VarType, genericSig);

    if (isUnresolvedMemberIdealType(VarType))
      Builder.setSemanticContext(SemanticContextKind::ExpressionSpecific);
  }

  static bool hasInterestingDefaultValues(const AbstractFunctionDecl *func) {
    if (!func) return false;

    for (auto param : *func->getParameters()) {
      switch (param->getDefaultArgumentKind()) {
      case DefaultArgumentKind::Normal:
      case DefaultArgumentKind::StoredProperty:
      case DefaultArgumentKind::Inherited: // FIXME: include this?
        return true;
      default:
        break;
      }
    }
    return false;
  }

  /// Build argument patterns for calling. Returns \c true if any content was
  /// added to \p Builder. If \p declParams is non-empty, the size must match
  /// with \p typeParams.
  bool addCallArgumentPatterns(CodeCompletionResultBuilder &Builder,
                               ArrayRef<AnyFunctionType::Param> typeParams,
                               ArrayRef<const ParamDecl *> declParams,
                               GenericSignature genericSig,
                               bool includeDefaultArgs = true) {
    assert(declParams.empty() || typeParams.size() == declParams.size());

    bool modifiedBuilder = false;

    // Determine whether we should skip this argument because it is defaulted.
    auto shouldSkipArg = [&](const ParamDecl *PD) -> bool {
      switch (PD->getDefaultArgumentKind()) {
      case DefaultArgumentKind::None:
        return false;

      case DefaultArgumentKind::Normal:
      case DefaultArgumentKind::StoredProperty:
      case DefaultArgumentKind::Inherited:
      case DefaultArgumentKind::NilLiteral:
      case DefaultArgumentKind::EmptyArray:
      case DefaultArgumentKind::EmptyDictionary:
        return !includeDefaultArgs;

#define MAGIC_IDENTIFIER(NAME, STRING, SYNTAX_KIND) \
      case DefaultArgumentKind::NAME:
#include "swift/AST/MagicIdentifierKinds.def"
        // Skip parameters that are defaulted to source location or other
        // caller context information.  Users typically don't want to specify
        // these parameters.
        return true;
      }

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

    bool NeedComma = false;
    // Iterate over each parameter.
    for (unsigned i = 0; i != typeParams.size(); ++i) {
      auto &typeParam = typeParams[i];

      Identifier argName;
      Identifier bodyName;
      bool isIUO = false;

      if (!declParams.empty()) {
        auto *PD = declParams[i];
        if (shouldSkipArg(PD))
          continue;
        argName = PD->getArgumentName();
        bodyName = PD->getParameterName();
        isIUO = PD->isImplicitlyUnwrappedOptional();
      } else {
        isIUO = false;
        argName = typeParam.getLabel();
      }

      bool isVariadic = typeParam.isVariadic();
      bool isInOut = typeParam.isInOut();
      bool isAutoclosure = typeParam.isAutoClosure();
      Type paramTy = typeParam.getPlainType();
      if (isVariadic)
        paramTy = ParamDecl::getVarargBaseTy(paramTy);

      if (NeedComma)
        Builder.addComma();
      Type contextTy;
      if (auto typeContext = CurrDeclContext->getInnermostTypeContext())
        contextTy = typeContext->getDeclaredTypeInContext();

      Builder.addCallParameter(argName, bodyName,
                               eraseArchetypes(paramTy, genericSig), contextTy,
                               isVariadic, isInOut, isIUO, isAutoclosure,
                               /*useUnderscoreLabel=*/false,
                               /*isLabeledTrailingClosure=*/false);

      modifiedBuilder = true;
      NeedComma = true;
    }
    return modifiedBuilder;
  }

  /// Build argument patterns for calling. Returns \c true if any content was
  /// added to \p Builder. If \p Params is non-nullptr, \F
  bool addCallArgumentPatterns(CodeCompletionResultBuilder &Builder,
                               const AnyFunctionType *AFT,
                               const ParameterList *Params,
                               GenericSignature genericSig,
                               bool includeDefaultArgs = true) {
    ArrayRef<const ParamDecl *> declParams;
    if (Params)
      declParams = Params->getArray();
    return addCallArgumentPatterns(Builder, AFT->getParams(), declParams,
                                   genericSig, includeDefaultArgs);
  }

  static void addEffectsSpecifiers(CodeCompletionResultBuilder &Builder,
                             const AnyFunctionType *AFT,
                             const AbstractFunctionDecl *AFD) {
    assert(AFT != nullptr);

    // 'async'.
    if ((AFD && AFD->hasAsync()) || AFT->isAsync())
      Builder.addAnnotatedAsync();

    // 'throws' or 'rethrows'.
    if (AFD && AFD->getAttrs().hasAttribute<RethrowsAttr>())
      Builder.addAnnotatedRethrows();
    else if (AFT->isThrowing())
      Builder.addAnnotatedThrows();
  }

  void addPoundAvailable(Optional<StmtKind> ParentKind) {
    if (ParentKind != StmtKind::If && ParentKind != StmtKind::Guard)
      return;
    CodeCompletionResultBuilder Builder(Sink, CodeCompletionResult::ResultKind::Keyword,
      SemanticContextKind::ExpressionSpecific, expectedTypeContext);
    Builder.addBaseName("available");
    Builder.addLeftParen();
    Builder.addSimpleTypedParameter("Platform", /*IsVarArg=*/true);
    Builder.addComma();
    Builder.addTextChunk("*");
    Builder.addRightParen();
  }

  void addPoundSelector(bool needPound) {
    // #selector is only available when the Objective-C runtime is.
    if (!Ctx.LangOpts.EnableObjCInterop) return;

    CodeCompletionResultBuilder Builder(
        Sink, CodeCompletionResult::ResultKind::Keyword,
        SemanticContextKind::None, {});
    if (needPound)
      Builder.addTextChunk("#selector");
    else
      Builder.addTextChunk("selector");
    Builder.addLeftParen();
    Builder.addSimpleTypedParameter("@objc method", /*IsVarArg=*/false);
    Builder.addRightParen();
    Builder.addTypeAnnotation("Selector");
    // This function is called only if the context type is 'Selector'.
    Builder.setExpectedTypeRelation(
        CodeCompletionResult::ExpectedTypeRelation::Identical);
  }

  void addPoundKeyPath(bool needPound) {
    // #keyPath is only available when the Objective-C runtime is.
    if (!Ctx.LangOpts.EnableObjCInterop) return;

    CodeCompletionResultBuilder Builder(
        Sink, CodeCompletionResult::ResultKind::Keyword,
        SemanticContextKind::None, {});
    if (needPound)
      Builder.addTextChunk("#keyPath");
    else
      Builder.addTextChunk("keyPath");
    Builder.addLeftParen();
    Builder.addSimpleTypedParameter("@objc property sequence",
                                    /*IsVarArg=*/false);
    Builder.addRightParen();
    Builder.addTypeAnnotation("String");
    // This function is called only if the context type is 'String'.
    Builder.setExpectedTypeRelation(
        CodeCompletionResult::ExpectedTypeRelation::Identical);
  }

  SemanticContextKind getSemanticContextKind(const ValueDecl *VD) {
    // FIXME: to get the corect semantic context we need to know how lookup
    // would have found the VD. For now, just infer a reasonable semantics.

    if (!VD)
      return SemanticContextKind::CurrentModule;

    DeclContext *calleeDC = VD->getDeclContext();
    
    if (calleeDC->isTypeContext())
      // FIXME: We should distinguish CurrentNominal and Super. We need to
      // propagate the base type to do that.
      return SemanticContextKind::CurrentNominal;

    if (calleeDC->isLocalContext())
      return SemanticContextKind::Local;
    if (calleeDC->getParentModule() == CurrModule)
      return SemanticContextKind::CurrentModule;

    return SemanticContextKind::OtherModule;
  }

  void addSubscriptCallPattern(
      const AnyFunctionType *AFT, const SubscriptDecl *SD,
      const Optional<SemanticContextKind> SemanticContext = None) {
    foundFunction(AFT);
    GenericSignature genericSig;
    if (SD)
      genericSig = SD->getGenericSignatureOfContext();

    CommandWordsPairs Pairs;
    CodeCompletionResultBuilder Builder(
        Sink,
        SD ? CodeCompletionResult::ResultKind::Declaration
           : CodeCompletionResult::ResultKind::Pattern,
        SemanticContext ? *SemanticContext : getSemanticContextKind(SD),
        expectedTypeContext);
    if (SD) {
      Builder.setAssociatedDecl(SD);
      setClangDeclKeywords(SD, Pairs, Builder);
    }
    if (!HaveLParen)
      Builder.addLeftBracket();
    else
      Builder.addAnnotatedLeftBracket();
    ArrayRef<const ParamDecl *> declParams;
    if (SD)
      declParams = SD->getIndices()->getArray();
    addCallArgumentPatterns(Builder, AFT->getParams(), declParams, genericSig);
    if (!HaveLParen)
      Builder.addRightBracket();
    else
      Builder.addAnnotatedRightBracket();
    if (SD && SD->isImplicitlyUnwrappedOptional())
      addTypeAnnotationForImplicitlyUnwrappedOptional(Builder,
                                                      AFT->getResult(),
                                                      genericSig);
    else
      addTypeAnnotation(Builder, AFT->getResult(), genericSig);
  }

  void addFunctionCallPattern(
      const AnyFunctionType *AFT, const AbstractFunctionDecl *AFD = nullptr,
      const Optional<SemanticContextKind> SemanticContext = None) {
    GenericSignature genericSig;
    if (AFD)
      genericSig = AFD->getGenericSignatureOfContext();

    // Add the pattern, possibly including any default arguments.
    auto addPattern = [&](ArrayRef<const ParamDecl *> declParams = {},
                          bool includeDefaultArgs = true) {
      CommandWordsPairs Pairs;
      CodeCompletionResultBuilder Builder(
          Sink,
          AFD ? CodeCompletionResult::ResultKind::Declaration
              : CodeCompletionResult::ResultKind::Pattern,
          SemanticContext ? *SemanticContext : getSemanticContextKind(AFD),
          expectedTypeContext);
      if (AFD) {
        Builder.setAssociatedDecl(AFD);
        setClangDeclKeywords(AFD, Pairs, Builder);
      }

      if (!HaveLParen)
        Builder.addLeftParen();
      else
        Builder.addAnnotatedLeftParen();

      addCallArgumentPatterns(Builder, AFT->getParams(), declParams,
                              genericSig, includeDefaultArgs);

      // The rparen matches the lparen here so that we insert both or neither.
      if (!HaveLParen)
        Builder.addRightParen();
      else
        Builder.addAnnotatedRightParen();

      addEffectsSpecifiers(Builder, AFT, AFD);

      if (AFD &&
          AFD->isImplicitlyUnwrappedOptional())
        addTypeAnnotationForImplicitlyUnwrappedOptional(Builder,
                                                        AFT->getResult(),
                                                        genericSig);
      else
        addTypeAnnotation(Builder, AFT->getResult(), genericSig);
    };

    if (!AFD || !AFD->getInterfaceType()->is<AnyFunctionType>()) {
      // Probably, calling closure type expression.
      foundFunction(AFT);
      addPattern();
      return;
    } else {
      // Calling function or method.
      foundFunction(AFD);

      // FIXME: Hack because we don't know we are calling instance
      // method or not. There's invariant that funcTy is derived from AFD.
      // Only if we are calling instance method on meta type, AFT is still
      // curried. So we should be able to detect that by comparing curried level
      // of AFT and the interface type of AFD.
      auto getCurriedLevel = [](const AnyFunctionType *funcTy) -> unsigned {
        unsigned level = 0;
        while ((funcTy = funcTy->getResult()->getAs<AnyFunctionType>()))
          ++level;
        return level;
      };
      bool isImplicitlyCurriedInstanceMethod =
          (AFD->hasImplicitSelfDecl() &&
           getCurriedLevel(AFT) ==
               getCurriedLevel(
                   AFD->getInterfaceType()->castTo<AnyFunctionType>()) &&
           // NOTE: shouldn't be necessary, but just in case curried level check
           // is insufficient.
           AFT->getParams().size() == 1 &&
           AFT->getParams()[0].getLabel().empty());

      if (isImplicitlyCurriedInstanceMethod) {
        addPattern({AFD->getImplicitSelfDecl()}, /*includeDefaultArgs=*/true);
      } else {
        if (hasInterestingDefaultValues(AFD))
          addPattern(AFD->getParameters()->getArray(),
                     /*includeDefaultArgs=*/false);
        addPattern(AFD->getParameters()->getArray(),
                   /*includeDefaultArgs=*/true);
      }
    }
  }

  bool isImplicitlyCurriedInstanceMethod(const AbstractFunctionDecl *FD) {
    if (FD->isStatic())
      return false;

    switch (Kind) {
    case LookupKind::ValueExpr:
      return ExprType->is<AnyMetatypeType>();
    case LookupKind::ValueInDeclContext:
      if (InsideStaticMethod)
        return FD->getDeclContext() == CurrentMethod->getDeclContext();
      if (auto Init = dyn_cast<Initializer>(CurrDeclContext)) {
        if (auto PatInit = dyn_cast<PatternBindingInitializer>(Init)) {
          if (PatInit->getInitializedLazyVar())
            return false;
        }
        return FD->getDeclContext() == Init->getInnermostTypeContext();
      }
      return false;
    case LookupKind::EnumElement:
    case LookupKind::Type:
    case LookupKind::TypeInDeclContext:
    case LookupKind::GenericRequirement:
      llvm_unreachable("cannot have a method call while doing a "
                       "type completion");
    case LookupKind::ImportFromModule:
      return false;
    }

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

  void addMethodCall(const FuncDecl *FD, DeclVisibilityKind Reason,
                     DynamicLookupInfo dynamicLookupInfo) {
    if (FD->getBaseIdentifier().empty())
      return;
    foundFunction(FD);

    const Identifier Name = FD->getBaseIdentifier();
    assert(!Name.empty() && "name should not be empty");

    Type FunctionType = getTypeOfMember(FD, dynamicLookupInfo);
    assert(FunctionType);

    auto AFT = FunctionType->getAs<AnyFunctionType>();

    bool IsImplicitlyCurriedInstanceMethod = false;
    if (FD->hasImplicitSelfDecl()) {
      IsImplicitlyCurriedInstanceMethod = isImplicitlyCurriedInstanceMethod(FD);

      // Strip off '(_ self: Self)' if needed.
      if (AFT && !IsImplicitlyCurriedInstanceMethod) {
        AFT = AFT->getResult()->getAs<AnyFunctionType>();

        // Check for duplicates with the adjusted type too.
        if (isDuplicate(FD, AFT))
          return;
      }
    }

    bool trivialTrailingClosure = false;
    if (AFT && !IsImplicitlyCurriedInstanceMethod)
      trivialTrailingClosure = hasTrivialTrailingClosure(FD, AFT);

    // Add the method, possibly including any default arguments.
    auto addMethodImpl = [&](bool includeDefaultArgs = true,
                             bool trivialTrailingClosure = false) {
      CommandWordsPairs Pairs;
      CodeCompletionResultBuilder Builder(
          Sink, CodeCompletionResult::ResultKind::Declaration,
          getSemanticContext(FD, Reason, dynamicLookupInfo),
          expectedTypeContext);
      setClangDeclKeywords(FD, Pairs, Builder);
      Builder.setAssociatedDecl(FD);
      addLeadingDot(Builder);
      addValueBaseName(Builder, Name);
      if (IsDynamicLookup)
        Builder.addDynamicLookupMethodCallTail();
      else if (FD->getAttrs().hasAttribute<OptionalAttr>())
        Builder.addOptionalMethodCallTail();

      if (!AFT) {
        addTypeAnnotation(Builder, FunctionType,
                          FD->getGenericSignatureOfContext());
        return;
      }
      if (IsImplicitlyCurriedInstanceMethod) {
        Builder.addLeftParen();
        addCallArgumentPatterns(Builder, AFT->getParams(),
                                {FD->getImplicitSelfDecl()},
                                FD->getGenericSignatureOfContext(),
                                includeDefaultArgs);
        Builder.addRightParen();
      } else if (trivialTrailingClosure) {
        Builder.addBraceStmtWithCursor(" { code }");
        addEffectsSpecifiers(Builder, AFT, FD);
      } else {
        Builder.addLeftParen();
        addCallArgumentPatterns(Builder, AFT, FD->getParameters(),
                                FD->getGenericSignatureOfContext(),
                                includeDefaultArgs);
        Builder.addRightParen();
        addEffectsSpecifiers(Builder, AFT, FD);
      }

      // Build type annotation.
      Type ResultType = AFT->getResult();
      // As we did with parameters in addParamPatternFromFunction,
      // for regular methods we'll print '!' after implicitly
      // unwrapped optional results.
      bool IsIUO =
          !IsImplicitlyCurriedInstanceMethod &&
          FD->isImplicitlyUnwrappedOptional();

      PrintOptions PO;
      PO.OpaqueReturnTypePrinting =
          PrintOptions::OpaqueReturnTypePrintingMode::WithoutOpaqueKeyword;
      PO.PrintOptionalAsImplicitlyUnwrapped = IsIUO;
      if (auto typeContext = CurrDeclContext->getInnermostTypeContext())
        PO.setBaseType(typeContext->getDeclaredTypeInContext());
      Type AnnotationTy =
          eraseArchetypes(ResultType, FD->getGenericSignatureOfContext());
      if (Builder.shouldAnnotateResults()) {
        Builder.withNestedGroup(
            CodeCompletionString::Chunk::ChunkKind::TypeAnnotationBegin, [&] {
              AnnotatedTypePrinter printer(Builder);
              if (IsImplicitlyCurriedInstanceMethod) {
                auto *FnType = AnnotationTy->castTo<AnyFunctionType>();
                AnyFunctionType::printParams(FnType->getParams(), printer,
                                             PrintOptions());
                AnnotationTy = FnType->getResult();
                printer.printText(" -> ");
              }

              // What's left is the result type.
              if (AnnotationTy->isVoid())
                AnnotationTy = Ctx.getVoidDecl()->getDeclaredInterfaceType();
              AnnotationTy.print(printer, PO);
            });
      } else {
        llvm::SmallString<32> TypeStr;
        llvm::raw_svector_ostream OS(TypeStr);
        if (IsImplicitlyCurriedInstanceMethod) {
          auto *FnType = AnnotationTy->castTo<AnyFunctionType>();
          AnyFunctionType::printParams(FnType->getParams(), OS);
          AnnotationTy = FnType->getResult();
          OS << " -> ";
        }

        // What's left is the result type.
        if (AnnotationTy->isVoid())
          AnnotationTy = Ctx.getVoidDecl()->getDeclaredInterfaceType();
        AnnotationTy.print(OS, PO);
        Builder.addTypeAnnotation(TypeStr);
      }

      Builder.setExpectedTypeRelation(calculateMaxTypeRelation(
          ResultType, expectedTypeContext, CurrDeclContext));

      if (isUnresolvedMemberIdealType(ResultType))
        Builder.setSemanticContext(SemanticContextKind::ExpressionSpecific);

      if (!IsImplicitlyCurriedInstanceMethod &&
          expectedTypeContext.requiresNonVoid() &&
          ResultType->isVoid()) {
        Builder.setExpectedTypeRelation(CodeCompletionResult::Invalid);
      }
    };

    if (!AFT || IsImplicitlyCurriedInstanceMethod) {
      addMethodImpl();
    } else {
      if (trivialTrailingClosure)
        addMethodImpl(/*includeDefaultArgs=*/false,
                      /*trivialTrailingClosure=*/true);
      if (hasInterestingDefaultValues(FD))
        addMethodImpl(/*includeDefaultArgs=*/false);
      addMethodImpl(/*includeDefaultArgs=*/true);
    }
  }

  void addConstructorCall(const ConstructorDecl *CD, DeclVisibilityKind Reason,
                          DynamicLookupInfo dynamicLookupInfo,
                          Optional<Type> BaseType, Optional<Type> Result,
                          bool IsOnType = true,
                          Identifier addName = Identifier()) {
    foundFunction(CD);
    Type MemberType = getTypeOfMember(CD, BaseType.getValueOr(ExprType));
    AnyFunctionType *ConstructorType = nullptr;
    if (auto MemberFuncType = MemberType->getAs<AnyFunctionType>())
      ConstructorType = MemberFuncType->getResult()
                                      ->castTo<AnyFunctionType>();

    bool needInit = false;
    if (!IsOnType) {
      assert(addName.empty());
      needInit = true;
    } else if (addName.empty() && HaveDot) {
      needInit = true;
    }

    // If we won't be able to provide a result, bail out.
    if (!ConstructorType && addName.empty() && !needInit)
      return;

    // Add the constructor, possibly including any default arguments.
    auto addConstructorImpl = [&](bool includeDefaultArgs = true) {
      CommandWordsPairs Pairs;
      CodeCompletionResultBuilder Builder(
          Sink, CodeCompletionResult::ResultKind::Declaration,
          getSemanticContext(CD, Reason, dynamicLookupInfo),
          expectedTypeContext);
      setClangDeclKeywords(CD, Pairs, Builder);
      Builder.setAssociatedDecl(CD);
      if (needInit) {
        assert(addName.empty());
        addLeadingDot(Builder);
        Builder.addBaseName("init");
      } else if (!addName.empty()) {
        Builder.addBaseName(addName.str());
      }

      if (!ConstructorType) {
        addTypeAnnotation(Builder, MemberType,
                          CD->getGenericSignatureOfContext());
        return;
      }

      if (!HaveLParen)
        Builder.addLeftParen();
      else
        Builder.addAnnotatedLeftParen();

      addCallArgumentPatterns(Builder, ConstructorType, CD->getParameters(),
                              CD->getGenericSignatureOfContext(),
                              includeDefaultArgs);

      // The rparen matches the lparen here so that we insert both or neither.
      if (!HaveLParen)
        Builder.addRightParen();
      else
        Builder.addAnnotatedRightParen();

      addEffectsSpecifiers(Builder, ConstructorType, CD);

      if (!Result.hasValue())
        Result = ConstructorType->getResult();
      if (CD->isImplicitlyUnwrappedOptional()) {
        addTypeAnnotationForImplicitlyUnwrappedOptional(
            Builder, *Result, CD->getGenericSignatureOfContext());
      } else {
        addTypeAnnotation(Builder, *Result, CD->getGenericSignatureOfContext());
      }
    };

    if (ConstructorType && hasInterestingDefaultValues(CD))
      addConstructorImpl(/*includeDefaultArgs*/ false);
    addConstructorImpl();
  }

  void addConstructorCallsForType(Type type, Identifier name,
                                  DeclVisibilityKind Reason,
                                  DynamicLookupInfo dynamicLookupInfo) {
    if (!Ctx.LangOpts.CodeCompleteInitsInPostfixExpr && !IsUnresolvedMember)
      return;

    assert(CurrDeclContext);

    auto results =
        swift::lookupSemanticMember(const_cast<DeclContext *>(CurrDeclContext),
                                    type, DeclBaseName::createConstructor());
    for (const auto &entry : results.allResults()) {
      auto *init = cast<ConstructorDecl>(entry.getValueDecl());
      if (init->shouldHideFromEditor())
        continue;
      if (IsUnresolvedMember && init->isFailable() &&
          !init->isImplicitlyUnwrappedOptional()) {
        continue;
      }
      addConstructorCall(cast<ConstructorDecl>(init), Reason,
                         dynamicLookupInfo, type, None,
                         /*IsOnType=*/true, name);
    }
  }

  void addSubscriptCall(const SubscriptDecl *SD, DeclVisibilityKind Reason,
                        DynamicLookupInfo dynamicLookupInfo) {
    // Don't add subscript call to unqualified completion.
    if (!ExprType)
      return;

    // Subscript after '.' is valid only after type part of Swift keypath
    // expression. (e.g. '\TyName.SubTy.[0])
    if (HaveDot && !IsAfterSwiftKeyPathRoot)
      return;

    auto subscriptType =
        getTypeOfMember(SD, dynamicLookupInfo)->getAs<AnyFunctionType>();
    if (!subscriptType)
      return;

    CommandWordsPairs Pairs;
    CodeCompletionResultBuilder Builder(
        Sink, CodeCompletionResult::ResultKind::Declaration,
        getSemanticContext(SD, Reason, dynamicLookupInfo), expectedTypeContext);
    Builder.setAssociatedDecl(SD);
    setClangDeclKeywords(SD, Pairs, Builder);

    // '\TyName#^TOKEN^#' requires leading dot.
    if (!HaveDot && IsAfterSwiftKeyPathRoot)
      Builder.addLeadingDot();

    if (NeedOptionalUnwrap) {
      Builder.setNumBytesToErase(NumBytesToEraseForOptionalUnwrap);
      Builder.addQuestionMark();
    }

    Builder.addLeftBracket();
    addCallArgumentPatterns(Builder, subscriptType, SD->getIndices(),
                            SD->getGenericSignatureOfContext(), true);
    Builder.addRightBracket();

    // Add a type annotation.
    Type resultTy = subscriptType->getResult();
    if (IsDynamicLookup) {
      // Values of properties that were found on a AnyObject have
      // Optional<T> type.
      resultTy = OptionalType::get(resultTy);
    }
    addTypeAnnotation(Builder, resultTy, SD->getGenericSignatureOfContext());
  }

  void addNominalTypeRef(const NominalTypeDecl *NTD, DeclVisibilityKind Reason,
                         DynamicLookupInfo dynamicLookupInfo) {
    if (IsUnresolvedMember)
      return;
    CommandWordsPairs Pairs;
    CodeCompletionResultBuilder Builder(
        Sink, CodeCompletionResult::ResultKind::Declaration,
        getSemanticContext(NTD, Reason, dynamicLookupInfo),
        expectedTypeContext);
    Builder.setAssociatedDecl(NTD);
    setClangDeclKeywords(NTD, Pairs, Builder);
    addLeadingDot(Builder);
    Builder.addBaseName(NTD->getName().str());

    addTypeAnnotation(Builder, NTD->getDeclaredType());

    // Override the type relation for NominalTypes. Use the better relation
    // for the metatypes and the instance type. For example,
    //
    //   func receiveInstance(_: Int) {}
    //   func receiveMetatype(_: Int.Type) {}
    //
    // We want to suggest 'Int' as 'Identical' for both arguments.
    Builder.setExpectedTypeRelation(std::max(
        calculateMaxTypeRelation(NTD->getDeclaredInterfaceType(),
                                 expectedTypeContext, CurrDeclContext),
        calculateMaxTypeRelation(NTD->getInterfaceType(), expectedTypeContext,
                                 CurrDeclContext)));
  }

  void addTypeAliasRef(const TypeAliasDecl *TAD, DeclVisibilityKind Reason,
                       DynamicLookupInfo dynamicLookupInfo) {
    if (IsUnresolvedMember)
      return;
    CommandWordsPairs Pairs;
    CodeCompletionResultBuilder Builder(
        Sink, CodeCompletionResult::ResultKind::Declaration,
        getSemanticContext(TAD, Reason, dynamicLookupInfo),
        expectedTypeContext);
    Builder.setAssociatedDecl(TAD);
    setClangDeclKeywords(TAD, Pairs, Builder);
    addLeadingDot(Builder);
    Builder.addBaseName(TAD->getName().str());
    if (auto underlyingType = TAD->getUnderlyingType()) {
      if (underlyingType->hasError()) {
        Type parentType;
        if (auto nominal = TAD->getDeclContext()->getSelfNominalTypeDecl()) {
          parentType = nominal->getDeclaredInterfaceType();
        }
        addTypeAnnotation(
                      Builder,
                      TypeAliasType::get(const_cast<TypeAliasDecl *>(TAD),
                                         parentType, SubstitutionMap(),
                                         underlyingType));

      } else {
        addTypeAnnotation(Builder, underlyingType);
      }
    }
  }

  void addGenericTypeParamRef(const GenericTypeParamDecl *GP,
                              DeclVisibilityKind Reason,
                              DynamicLookupInfo dynamicLookupInfo) {
    CommandWordsPairs Pairs;
    CodeCompletionResultBuilder Builder(
        Sink, CodeCompletionResult::ResultKind::Declaration,
        getSemanticContext(GP, Reason, dynamicLookupInfo), expectedTypeContext);
    setClangDeclKeywords(GP, Pairs, Builder);
    Builder.setAssociatedDecl(GP);
    addLeadingDot(Builder);
    Builder.addBaseName(GP->getName().str());
    addTypeAnnotation(Builder, GP->getDeclaredInterfaceType());
  }

  void addAssociatedTypeRef(const AssociatedTypeDecl *AT,
                            DeclVisibilityKind Reason,
                            DynamicLookupInfo dynamicLookupInfo) {
    CommandWordsPairs Pairs;
    CodeCompletionResultBuilder Builder(
        Sink, CodeCompletionResult::ResultKind::Declaration,
        getSemanticContext(AT, Reason, dynamicLookupInfo), expectedTypeContext);
    setClangDeclKeywords(AT, Pairs, Builder);
    Builder.setAssociatedDecl(AT);
    addLeadingDot(Builder);
    Builder.addBaseName(AT->getName().str());
    if (Type T = getAssociatedTypeType(AT))
      addTypeAnnotation(Builder, T);
  }

  void addPrecedenceGroupRef(PrecedenceGroupDecl *PGD) {
    auto semanticContext =
        getSemanticContext(PGD, DeclVisibilityKind::VisibleAtTopLevel, {});
    CodeCompletionResultBuilder builder(
      Sink, CodeCompletionResult::ResultKind::Declaration,
      semanticContext, {});

    builder.addBaseName(PGD->getName().str());
    builder.setAssociatedDecl(PGD);
  };

  void addEnumElementRef(const EnumElementDecl *EED, DeclVisibilityKind Reason,
                         DynamicLookupInfo dynamicLookupInfo,
                         bool HasTypeContext) {
    if (!EED->hasName() ||
        !EED->isAccessibleFrom(CurrDeclContext) ||
        EED->shouldHideFromEditor())
      return;

    CommandWordsPairs Pairs;
    CodeCompletionResultBuilder Builder(
        Sink, CodeCompletionResult::ResultKind::Declaration,
        HasTypeContext ? SemanticContextKind::ExpressionSpecific
                       : getSemanticContext(EED, Reason, dynamicLookupInfo),
        expectedTypeContext);
    Builder.setAssociatedDecl(EED);
    setClangDeclKeywords(EED, Pairs, Builder);
    addLeadingDot(Builder);
    addValueBaseName(Builder, EED->getBaseIdentifier());

    // Enum element is of function type; (Self.type) -> Self or
    // (Self.Type) -> (Args...) -> Self.
    Type EnumType = getTypeOfMember(EED, dynamicLookupInfo);
    if (EnumType->is<AnyFunctionType>())
      EnumType = EnumType->castTo<AnyFunctionType>()->getResult();

    if (EnumType->is<FunctionType>()) {
      Builder.addLeftParen();
      addCallArgumentPatterns(Builder, EnumType->castTo<FunctionType>(),
                              EED->getParameterList(),
                              EED->getGenericSignatureOfContext());
      Builder.addRightParen();

      // Extract result as the enum type.
      EnumType = EnumType->castTo<FunctionType>()->getResult();
    }

    addTypeAnnotation(Builder, EnumType, EED->getGenericSignatureOfContext());

    if (isUnresolvedMemberIdealType(EnumType))
      Builder.setSemanticContext(SemanticContextKind::ExpressionSpecific);
  }

  void addKeyword(StringRef Name, Type TypeAnnotation = Type(),
                  SemanticContextKind SK = SemanticContextKind::None,
                  CodeCompletionKeywordKind KeyKind
                    = CodeCompletionKeywordKind::None,
                  unsigned NumBytesToErase = 0) {
    CodeCompletionResultBuilder Builder(
        Sink, CodeCompletionResult::ResultKind::Keyword, SK,
        expectedTypeContext);
    addLeadingDot(Builder);
    Builder.addKeyword(Name);
    Builder.setKeywordKind(KeyKind);
    if (TypeAnnotation)
      addTypeAnnotation(Builder, TypeAnnotation);
    if (NumBytesToErase > 0)
      Builder.setNumBytesToErase(NumBytesToErase);
  }

  void addKeyword(StringRef Name, StringRef TypeAnnotation,
                  CodeCompletionKeywordKind KeyKind
                    = CodeCompletionKeywordKind::None) {
    CodeCompletionResultBuilder Builder(
        Sink,
        CodeCompletionResult::ResultKind::Keyword,
        SemanticContextKind::None, expectedTypeContext);
    addLeadingDot(Builder);
    Builder.addKeyword(Name);
    Builder.setKeywordKind(KeyKind);
    if (!TypeAnnotation.empty())
      Builder.addTypeAnnotation(TypeAnnotation);
  }

  void addDeclAttrParamKeyword(StringRef Name, StringRef Annotation,
                             bool NeedSpecify) {
    CodeCompletionResultBuilder Builder(
        Sink,
        CodeCompletionResult::ResultKind::Keyword,
        SemanticContextKind::None, expectedTypeContext);
    Builder.addDeclAttrParamKeyword(Name, Annotation, NeedSpecify);
  }

  void addDeclAttrKeyword(StringRef Name, StringRef Annotation) {
    CodeCompletionResultBuilder Builder(
        Sink,
        CodeCompletionResult::ResultKind::Keyword,
        SemanticContextKind::None, expectedTypeContext);
    Builder.addDeclAttrKeyword(Name, Annotation);
  }

  /// Add the compound function name for the given function.
  /// Returns \c true if the compound function name is actually used.
  bool addCompoundFunctionNameIfDesiable(AbstractFunctionDecl *AFD,
                                         DeclVisibilityKind Reason,
                                         DynamicLookupInfo dynamicLookupInfo) {
    auto funcTy =
        getTypeOfMember(AFD, dynamicLookupInfo)->getAs<AnyFunctionType>();
    bool dropCurryLevel = funcTy && AFD->getDeclContext()->isTypeContext() &&
        !isImplicitlyCurriedInstanceMethod(AFD);
    if (dropCurryLevel)
      funcTy = funcTy->getResult()->getAs<AnyFunctionType>();

    bool useFunctionReference = PreferFunctionReferencesToCalls;
    if (!useFunctionReference && funcTy) {
      auto maxRel = calculateMaxTypeRelation(funcTy, expectedTypeContext,
                                             CurrDeclContext);
      useFunctionReference =
          maxRel >= CodeCompletionResult::ExpectedTypeRelation::Convertible;
    }
    if (!useFunctionReference)
      return false;

    // Check for duplicates with the adjusted type too.
    if (dropCurryLevel && isDuplicate(AFD, funcTy))
      return true;

    CommandWordsPairs Pairs;
    CodeCompletionResultBuilder Builder(
        Sink, CodeCompletionResult::ResultKind::Declaration,
        getSemanticContext(AFD, Reason, dynamicLookupInfo),
        expectedTypeContext);
    setClangDeclKeywords(AFD, Pairs, Builder);
    Builder.setAssociatedDecl(AFD);

    // Base name
    addLeadingDot(Builder);
    addValueBaseName(Builder, AFD->getBaseName());

    // Add the argument labels.
    const auto ArgLabels = AFD->getName().getArgumentNames();
    if (!ArgLabels.empty()) {
      if (!HaveLParen)
        Builder.addLeftParen();
      else
        Builder.addAnnotatedLeftParen();

      for (auto ArgLabel : ArgLabels) {
        if (ArgLabel.empty())
          Builder.addTextChunk("_");
        else
          Builder.addTextChunk(ArgLabel.str());
        Builder.addTextChunk(":");
      }

      Builder.addRightParen();
    }

    if (funcTy)
      addTypeAnnotation(Builder, funcTy, AFD->getGenericSignatureOfContext());

    return true;
  }

private:

  /// Returns true if duplicate checking is enabled (via
  /// \c shouldCheckForDuplicates) and this decl + type combination has been
  /// checked previously. Returns false otherwise.
  bool isDuplicate(const ValueDecl *D, Type Ty) {
    if (!CheckForDuplicates)
      return false;
    return !PreviouslySeen.insert({D, Ty}).second;
  }

  /// Returns true if duplicate checking is enabled (via
  /// \c shouldCheckForDuplicates) and this decl has been checked previously
  /// with the type according to \c getTypeOfMember. Returns false otherwise.
  bool isDuplicate(const ValueDecl *D, DynamicLookupInfo dynamicLookupInfo) {
    if (!CheckForDuplicates)
      return false;
    Type Ty = getTypeOfMember(D, dynamicLookupInfo);
    return !PreviouslySeen.insert({D, Ty}).second;
  }

public:

  // Implement swift::VisibleDeclConsumer.
  void foundDecl(ValueDecl *D, DeclVisibilityKind Reason,
                 DynamicLookupInfo dynamicLookupInfo) override {
    assert(Reason !=
             DeclVisibilityKind::MemberOfProtocolDerivedByCurrentNominal &&
           "Including derived requirement in non-override lookup");

    if (D->shouldHideFromEditor())
      return;

    if (IsKeyPathExpr && !KeyPathFilter(D, Reason))
      return;

    if (IsSwiftKeyPathExpr && !SwiftKeyPathFilter(D, Reason))
      return;

    // If we've seen this decl+type before (possible when multiple lookups are
    // performed e.g. because of ambiguous base types), bail.
    if (isDuplicate(D, dynamicLookupInfo))
      return;
    
    // FIXME(InterfaceTypeRequest): Remove this.
    (void)D->getInterfaceType();
    switch (Kind) {
    case LookupKind::ValueExpr:
      if (auto *CD = dyn_cast<ConstructorDecl>(D)) {
        // Do we want compound function names here?
        if (addCompoundFunctionNameIfDesiable(CD, Reason, dynamicLookupInfo))
          return;

        if (auto MT = ExprType->getAs<AnyMetatypeType>()) {
          Type Ty = MT->getInstanceType();
          assert(Ty && "Cannot find instance type.");

          // If instance type is type alias, show users that the constructed
          // type is the typealias instead of the underlying type of the alias.
          Optional<Type> Result = None;
          if (!CD->getInterfaceType()->is<ErrorType>() &&
              isa<TypeAliasType>(Ty.getPointer()) &&
              Ty->getDesugaredType() ==
                CD->getResultInterfaceType().getPointer()) {
            Result = Ty;
          }
          // If the expression type is not a static metatype or an archetype, the base
          // is not a type. Direct call syntax is illegal on values, so we only add
          // initializer completions if we do not have a left parenthesis and either
          // the initializer is required, the base type's instance type is not a class,
          // or this is a 'self' or 'super' reference.
          if (IsStaticMetatype || IsUnresolvedMember || Ty->is<ArchetypeType>())
            addConstructorCall(CD, Reason, dynamicLookupInfo, None, Result,
                               /*isOnType*/ true);
          else if ((IsSelfRefExpr || IsSuperRefExpr || !Ty->is<ClassType>() ||
                    CD->isRequired()) && !HaveLParen)
            addConstructorCall(CD, Reason, dynamicLookupInfo, None, Result,
                               /*isOnType*/ false);
          return;
        }
        if (!HaveLParen) {
          auto CDC = dyn_cast<ConstructorDecl>(CurrDeclContext);
          if (!CDC)
            return;

          // For classes, we do not want 'init' completions for 'self' in
          // non-convenience initializers and for 'super' in convenience initializers.
          if (ExprType->is<ClassType>()) {
            if ((IsSelfRefExpr && !CDC->isConvenienceInit()) ||
                (IsSuperRefExpr && CDC->isConvenienceInit()))
              return;
          }
          if (IsSelfRefExpr || IsSuperRefExpr)
            addConstructorCall(CD, Reason, dynamicLookupInfo, None, None,
                               /*IsOnType=*/false);
        }
        return;
      }

      if (HaveLParen)
        return;

      LLVM_FALLTHROUGH;

    case LookupKind::ValueInDeclContext:
    case LookupKind::ImportFromModule:
      if (auto *VD = dyn_cast<VarDecl>(D)) {
        addVarDeclRef(VD, Reason, dynamicLookupInfo);
        return;
      }

      if (auto *FD = dyn_cast<FuncDecl>(D)) {
        // We cannot call operators with a postfix parenthesis syntax.
        if (FD->isBinaryOperator() || FD->isUnaryOperator())
          return;

        // We cannot call accessors.  We use VarDecls and SubscriptDecls to
        // produce completions that refer to getters and setters.
        if (isa<AccessorDecl>(FD))
          return;

        // Do we want compound function names here?
        if (addCompoundFunctionNameIfDesiable(FD, Reason, dynamicLookupInfo))
          return;

        addMethodCall(FD, Reason, dynamicLookupInfo);

        // SE-0253: Callable values of user-defined nominal types.
        if (FD->isCallAsFunctionMethod() && !HaveDot &&
            (!ExprType || !ExprType->is<AnyMetatypeType>())) {
          Type funcType = getTypeOfMember(FD, dynamicLookupInfo)
                              ->castTo<AnyFunctionType>()
                              ->getResult();

          // Check for duplicates with the adjusted type too.
          if (isDuplicate(FD, funcType))
            return;

          addFunctionCallPattern(
              funcType->castTo<AnyFunctionType>(), FD,
              getSemanticContext(FD, Reason, dynamicLookupInfo));
        }
        return;
      }

      if (auto *NTD = dyn_cast<NominalTypeDecl>(D)) {
        addNominalTypeRef(NTD, Reason, dynamicLookupInfo);
        addConstructorCallsForType(NTD->getDeclaredInterfaceType(),
                                   NTD->getName(), Reason, dynamicLookupInfo);
        return;
      }

      if (auto *TAD = dyn_cast<TypeAliasDecl>(D)) {
        addTypeAliasRef(TAD, Reason, dynamicLookupInfo);
        auto type = TAD->mapTypeIntoContext(TAD->getDeclaredInterfaceType());
        if (type->mayHaveMembers())
          addConstructorCallsForType(type, TAD->getName(), Reason,
                                     dynamicLookupInfo);
        return;
      }

      if (auto *GP = dyn_cast<GenericTypeParamDecl>(D)) {
        addGenericTypeParamRef(GP, Reason, dynamicLookupInfo);
        for (auto *protocol : GP->getConformingProtocols())
          addConstructorCallsForType(protocol->getDeclaredInterfaceType(),
                                     GP->getName(), Reason, dynamicLookupInfo);
        return;
      }

      if (auto *AT = dyn_cast<AssociatedTypeDecl>(D)) {
        addAssociatedTypeRef(AT, Reason, dynamicLookupInfo);
        return;
      }

      if (auto *EED = dyn_cast<EnumElementDecl>(D)) {
        addEnumElementRef(EED, Reason, dynamicLookupInfo,
                          /*HasTypeContext=*/false);
        return;
      }

      // Swift key path allows .[0]
      if (auto *SD = dyn_cast<SubscriptDecl>(D)) {
        addSubscriptCall(SD, Reason, dynamicLookupInfo);
        return;
      }
      return;

    case LookupKind::EnumElement:
      handleEnumElement(D, Reason, dynamicLookupInfo);
      return;

    case LookupKind::Type:
    case LookupKind::TypeInDeclContext:
      if (auto *NTD = dyn_cast<NominalTypeDecl>(D)) {
        addNominalTypeRef(NTD, Reason, dynamicLookupInfo);
        return;
      }

      if (auto *GP = dyn_cast<GenericTypeParamDecl>(D)) {
        addGenericTypeParamRef(GP, Reason, dynamicLookupInfo);
        return;
      }

      LLVM_FALLTHROUGH;
    case LookupKind::GenericRequirement:

      if (TypeAliasDecl *TAD = dyn_cast<TypeAliasDecl>(D)) {
        if (Kind == LookupKind::GenericRequirement &&
            !canBeUsedAsRequirementFirstType(BaseType, TAD))
          return;
        addTypeAliasRef(TAD, Reason, dynamicLookupInfo);
        return;
      }

      if (auto *AT = dyn_cast<AssociatedTypeDecl>(D)) {
        addAssociatedTypeRef(AT, Reason, dynamicLookupInfo);
        return;
      }

      return;
    }
  }

  bool handleEnumElement(ValueDecl *D, DeclVisibilityKind Reason,
                         DynamicLookupInfo dynamicLookupInfo) {
    if (auto *EED = dyn_cast<EnumElementDecl>(D)) {
      addEnumElementRef(EED, Reason, dynamicLookupInfo,
                        /*HasTypeContext=*/true);
      return true;
    } else if (auto *ED = dyn_cast<EnumDecl>(D)) {
      llvm::DenseSet<EnumElementDecl *> Elements;
      ED->getAllElements(Elements);
      for (auto *Ele : Elements) {
        addEnumElementRef(Ele, Reason, dynamicLookupInfo,
                          /*HasTypeContext=*/true);
      }
      return true;
    }
    return false;
  }

  bool tryTupleExprCompletions(Type ExprType) {
    auto *TT = ExprType->getAs<TupleType>();
    if (!TT)
      return false;

    unsigned Index = 0;
    for (auto TupleElt : TT->getElements()) {
      CodeCompletionResultBuilder Builder(
          Sink,
          CodeCompletionResult::ResultKind::Pattern,
          SemanticContextKind::CurrentNominal, expectedTypeContext);
      addLeadingDot(Builder);
      if (TupleElt.hasName()) {
        Builder.addBaseName(TupleElt.getName().str());
      } else {
        llvm::SmallString<4> IndexStr;
        {
          llvm::raw_svector_ostream OS(IndexStr);
          OS << Index;
        }
        Builder.addBaseName(IndexStr.str());
      }
      addTypeAnnotation(Builder, TupleElt.getType());
      ++Index;
    }
    return true;
  }

  bool tryFunctionCallCompletions(Type ExprType, const ValueDecl *VD, Optional<SemanticContextKind> SemanticContext = None) {
    ExprType = ExprType->getRValueType();
    if (auto AFT = ExprType->getAs<AnyFunctionType>()) {
      if (auto *AFD = dyn_cast_or_null<AbstractFunctionDecl>(VD)) {
        addFunctionCallPattern(AFT, AFD, SemanticContext);
      } else {
        addFunctionCallPattern(AFT);
      }
      return true;
    }
    return false;
  }

  bool tryModuleCompletions(Type ExprType, bool TypesOnly = false) {
    if (auto MT = ExprType->getAs<ModuleType>()) {
      ModuleDecl *M = MT->getModule();

      // Only lookup this module's symbols from the cache if it is not the
      // current module.
      if (M == CurrModule)
        return false;

      // If the module is shadowed by a separately imported overlay(s), look up
      // the symbols from the overlay(s) instead.
      SmallVector<ModuleDecl *, 1> ShadowingOrOriginal;
      if (auto *SF = CurrDeclContext->getParentSourceFile()) {
        SF->getSeparatelyImportedOverlays(M, ShadowingOrOriginal);
        if (ShadowingOrOriginal.empty())
          ShadowingOrOriginal.push_back(M);
      }
      for (ModuleDecl *M: ShadowingOrOriginal) {
        RequestedResultsTy Request = RequestedResultsTy::fromModule(M)
            .needLeadingDot(needDot())
            .withModuleQualifier(false);
        if (TypesOnly)
          Request = Request.onlyTypes();
        RequestedCachedResults.push_back(Request);
      }
      return true;
    }
    return false;
  }

  /// If the given ExprType is optional, this adds completions for the unwrapped
  /// type.
  ///
  /// \return true if the given type was Optional .
  bool tryUnwrappedCompletions(Type ExprType, bool isIUO) {
    // FIXME: consider types convertible to T?.

    ExprType = ExprType->getRValueType();
    // FIXME: We don't always pass down whether a type is from an
    // unforced IUO.
    if (isIUO) {
      if (Type Unwrapped = ExprType->getOptionalObjectType()) {
        lookupVisibleMemberDecls(*this, Unwrapped, CurrDeclContext,
                                 IncludeInstanceMembers,
                                 /*includeDerivedRequirements*/false,
                                 /*includeProtocolExtensionMembers*/true);
        return true;
      }
      assert(IsUnwrappedOptional && "IUOs should be optional if not bound/forced");
      return false;
    }

    if (Type Unwrapped = ExprType->getOptionalObjectType()) {
      llvm::SaveAndRestore<bool> ChangeNeedOptionalUnwrap(NeedOptionalUnwrap,
                                                          true);
      if (DotLoc.isValid()) {
        // Let's not erase the dot if the completion is after a swift key path
        // root because \A?.?.member is the correct way to access wrapped type
        // member from an optional key path root.
        auto loc = IsAfterSwiftKeyPathRoot ? DotLoc.getAdvancedLoc(1) : DotLoc;
        NumBytesToEraseForOptionalUnwrap = Ctx.SourceMgr.getByteDistance(
            loc, Ctx.SourceMgr.getCodeCompletionLoc());
      } else {
        NumBytesToEraseForOptionalUnwrap = 0;
      }
      if (NumBytesToEraseForOptionalUnwrap <=
          CodeCompletionResult::MaxNumBytesToErase) {
        if (!tryTupleExprCompletions(Unwrapped)) {
          lookupVisibleMemberDecls(*this, Unwrapped, CurrDeclContext,
                                   IncludeInstanceMembers,
                                   /*includeDerivedRequirements*/false,
                                   /*includeProtocolExtensionMembers*/true);
        }
      }
      return true;
    }
    return false;
  }

  void getPostfixKeywordCompletions(Type ExprType, Expr *ParsedExpr) {
    if (IsSuperRefExpr)
      return;

    if (!ExprType->getAs<ModuleType>()) {
      addKeyword(getTokenText(tok::kw_self), ExprType->getRValueType(),
                 SemanticContextKind::CurrentNominal,
                 CodeCompletionKeywordKind::kw_self);
    }

    if (isa<TypeExpr>(ParsedExpr)) {
      if (auto *T = ExprType->getAs<AnyMetatypeType>()) {
        auto instanceTy = T->getInstanceType();
        if (instanceTy->isAnyExistentialType()) {
          addKeyword("Protocol", MetatypeType::get(instanceTy),
                     SemanticContextKind::CurrentNominal);
          addKeyword("Type", ExistentialMetatypeType::get(instanceTy),
                     SemanticContextKind::CurrentNominal);
        } else {
          addKeyword("Type", MetatypeType::get(instanceTy),
                     SemanticContextKind::CurrentNominal);
        }
      }
    }
  }

  void getValueExprCompletions(Type ExprType, ValueDecl *VD = nullptr) {
    Kind = LookupKind::ValueExpr;
    NeedLeadingDot = !HaveDot;

    ExprType = ExprType->getRValueType();
    assert(!ExprType->hasTypeParameter());

    this->ExprType = ExprType;

    // Open existential types, so that lookupVisibleMemberDecls() can properly
    // substitute them.
    bool WasOptional = false;
    if (auto OptionalType = ExprType->getOptionalObjectType()) {
      ExprType = OptionalType;
      WasOptional = true;
    }

    if (!ExprType->getMetatypeInstanceType()->isAnyObject())
      if (ExprType->isAnyExistentialType())
        ExprType = OpenedArchetypeType::getAny(ExprType);

    if (WasOptional)
      ExprType = OptionalType::get(ExprType);

    // Handle special cases
    bool isIUO = VD && VD->isImplicitlyUnwrappedOptional();
    if (tryFunctionCallCompletions(ExprType, VD))
      return;
    if (tryModuleCompletions(ExprType))
      return;
    if (tryTupleExprCompletions(ExprType))
      return;
    // Don't check/return so we still add the members of Optional itself below
    tryUnwrappedCompletions(ExprType, isIUO);

    lookupVisibleMemberDecls(*this, ExprType, CurrDeclContext,
                             IncludeInstanceMembers,
                             /*includeDerivedRequirements*/false,
                             /*includeProtocolExtensionMembers*/true);
  }

  void collectOperators(SmallVectorImpl<OperatorDecl *> &results) {
    assert(CurrDeclContext);
    for (auto import : namelookup::getAllImports(CurrDeclContext))
      import.importedModule->getOperatorDecls(results);
  }

  void addPostfixBang(Type resultType) {
    CodeCompletionResultBuilder builder(
        Sink, CodeCompletionResult::ResultKind::BuiltinOperator,
        SemanticContextKind::None, {});
    // FIXME: we can't use the exclamation mark chunk kind, or it isn't
    // included in the completion name.
    builder.addTextChunk("!");
    assert(resultType);
    addTypeAnnotation(builder, resultType);
  }

  void addPostfixOperatorCompletion(OperatorDecl *op, Type resultType) {
    // FIXME: we should get the semantic context of the function, not the
    // operator decl.
    auto semanticContext =
        getSemanticContext(op, DeclVisibilityKind::VisibleAtTopLevel, {});
    CodeCompletionResultBuilder builder(
        Sink, CodeCompletionResult::ResultKind::Declaration, semanticContext,
        {});

    // FIXME: handle variable amounts of space.
    if (HaveLeadingSpace)
      builder.setNumBytesToErase(1);
    builder.setAssociatedDecl(op);
    builder.addBaseName(op->getName().str());
    assert(resultType);
    addTypeAnnotation(builder, resultType);
  }

  void tryPostfixOperator(Expr *expr, PostfixOperatorDecl *op) {
    ConcreteDeclRef referencedDecl;
    FunctionType *funcTy = getTypeOfCompletionOperator(
        const_cast<DeclContext *>(CurrDeclContext), expr, op->getName(),
        DeclRefKind::PostfixOperator, referencedDecl);
    if (!funcTy)
      return;

    // TODO: Use referencedDecl (FuncDecl) instead of 'op' (OperatorDecl).
    addPostfixOperatorCompletion(op, funcTy->getResult());
  }

  void addAssignmentOperator(Type RHSType, Type resultType) {
    CodeCompletionResultBuilder builder(
        Sink, CodeCompletionResult::ResultKind::BuiltinOperator,
        SemanticContextKind::None, {});

    if (HaveLeadingSpace)
      builder.addAnnotatedWhitespace(" ");
    else
      builder.addWhitespace(" ");
    builder.addEqual();
    builder.addWhitespace(" ");
    assert(RHSType && resultType);
    Type contextTy;
    if (auto typeContext = CurrDeclContext->getInnermostTypeContext())
      contextTy = typeContext->getDeclaredTypeInContext();
    builder.addCallParameter(Identifier(), RHSType, contextTy);
    addTypeAnnotation(builder, resultType);
  }

  void addInfixOperatorCompletion(OperatorDecl *op, Type resultType,
                                  Type RHSType) {
    // FIXME: we should get the semantic context of the function, not the
    // operator decl.
    auto semanticContext =
        getSemanticContext(op, DeclVisibilityKind::VisibleAtTopLevel, {});
    CodeCompletionResultBuilder builder(
        Sink, CodeCompletionResult::ResultKind::Declaration, semanticContext,
        {});
    builder.setAssociatedDecl(op);

    if (HaveLeadingSpace)
      builder.addAnnotatedWhitespace(" ");
    else
      builder.addWhitespace(" ");
    builder.addBaseName(op->getName().str());
    builder.addWhitespace(" ");
    if (RHSType) {
      Type contextTy;
      if (auto typeContext = CurrDeclContext->getInnermostTypeContext())
        contextTy = typeContext->getDeclaredTypeInContext();
      builder.addCallParameter(Identifier(), RHSType, contextTy);
    }
    if (resultType)
      addTypeAnnotation(builder, resultType);
  }

  void tryInfixOperatorCompletion(Expr *foldedExpr, InfixOperatorDecl *op) {
    ConcreteDeclRef referencedDecl;
    FunctionType *funcTy = getTypeOfCompletionOperator(
        const_cast<DeclContext *>(CurrDeclContext), foldedExpr, op->getName(),
        DeclRefKind::BinaryOperator, referencedDecl);
    if (!funcTy)
      return;

    Type lhsTy = funcTy->getParams()[0].getPlainType();
    Type rhsTy = funcTy->getParams()[1].getPlainType();
    Type resultTy = funcTy->getResult();

    // Don't complete optional operators on non-optional types.
    if (!lhsTy->getRValueType()->getOptionalObjectType()) {
      // 'T ?? T'
      if (op->getName().str() == "??")
        return;
      // 'T == nil'
      if (auto NT = rhsTy->getNominalOrBoundGenericNominal())
        if (NT->getName() ==
            CurrDeclContext->getASTContext().Id_OptionalNilComparisonType)
          return;
    }

    // If the right-hand side and result type are both type parameters, we're
    // not providing a useful completion.
    if (resultTy->isTypeParameter() && rhsTy->isTypeParameter())
      return;

    // TODO: Use referencedDecl (FuncDecl) instead of 'op' (OperatorDecl).
    addInfixOperatorCompletion(op, funcTy->getResult(),
                               funcTy->getParams()[1].getPlainType());
  }

  Expr *typeCheckLeadingSequence(Expr *LHS, ArrayRef<Expr *> leadingSequence) {
    if (leadingSequence.empty())
      return LHS;

    SourceRange sequenceRange(leadingSequence.front()->getStartLoc(),
                              LHS->getEndLoc());
    auto *expr = findParsedExpr(CurrDeclContext, sequenceRange);
    if (!expr)
      return LHS;

    if (expr->getType() && !expr->getType()->hasError())
      return expr;

    if (!typeCheckExpression(const_cast<DeclContext *>(CurrDeclContext), expr))
      return expr;
    return LHS;
  }

  void getOperatorCompletions(Expr *LHS, ArrayRef<Expr *> leadingSequence) {
    if (IsSuperRefExpr)
      return;

    Expr *foldedExpr = typeCheckLeadingSequence(LHS, leadingSequence);

    SmallVector<OperatorDecl *, 16> operators;
    collectOperators(operators);
    // FIXME: this always chooses the first operator with the given name.
    llvm::DenseSet<Identifier> seenPostfixOperators;
    llvm::DenseSet<Identifier> seenInfixOperators;

    for (auto op : operators) {
      switch (op->getKind()) {
      case DeclKind::PrefixOperator:
        // Don't insert prefix operators in postfix position.
        // FIXME: where should these get completed?
        break;
      case DeclKind::PostfixOperator:
        if (seenPostfixOperators.insert(op->getName()).second)
          tryPostfixOperator(LHS, cast<PostfixOperatorDecl>(op));
        break;
      case DeclKind::InfixOperator:
        if (seenInfixOperators.insert(op->getName()).second)
          tryInfixOperatorCompletion(foldedExpr, cast<InfixOperatorDecl>(op));
        break;
      default:
        llvm_unreachable("unexpected operator kind");
      }
    }

    if (leadingSequence.empty() && LHS->getType() &&
        LHS->getType()->hasLValueType()) {
      addAssignmentOperator(LHS->getType()->getRValueType(),
                            CurrDeclContext->getASTContext().TheEmptyTupleType);
    }

    // FIXME: unify this with the ?.member completions.
    if (auto T = LHS->getType())
      if (auto ValueT = T->getRValueType()->getOptionalObjectType())
        addPostfixBang(ValueT);
  }

  void addTypeRelationFromProtocol(CodeCompletionResultBuilder &builder,
                                   CodeCompletionLiteralKind kind) {
    // Check for matching ExpectedTypes.
    auto *P = Ctx.getProtocol(protocolForLiteralKind(kind));
    for (auto T : expectedTypeContext.possibleTypes) {
      if (!T)
        continue;

      auto typeRelation = CodeCompletionResult::Identical;
      // Convert through optional types unless we're looking for a protocol
      // that Optional itself conforms to.
      if (kind != CodeCompletionLiteralKind::NilLiteral) {
        if (auto optionalObjT = T->getOptionalObjectType()) {
          T = optionalObjT;
          typeRelation = CodeCompletionResult::Convertible;
        }
      }

      // Check for conformance to the literal protocol.
      if (auto *NTD = T->getAnyNominal()) {
        SmallVector<ProtocolConformance *, 2> conformances;
        if (NTD->lookupConformance(CurrModule, P, conformances)) {
          addTypeAnnotation(builder, T);
          builder.setExpectedTypeRelation(typeRelation);
          return;
        }
      }
    }

    // Fallback to showing the default type.
    if (auto defaultTy = defaultTypeLiteralKind(kind, Ctx)) {
      builder.addTypeAnnotation(defaultTy, PrintOptions());
      builder.setExpectedTypeRelation(
          expectedTypeContext.possibleTypes.empty()
              ? CodeCompletionResult::ExpectedTypeRelation::Unknown
              : CodeCompletionResult::ExpectedTypeRelation::Unrelated);
    }
  }

  /// Add '#file', '#line', et at.
  void addPoundLiteralCompletions(bool needPound) {
    auto addFromProto = [&](MagicIdentifierLiteralExpr::Kind magicKind,
                            Optional<CodeCompletionLiteralKind> literalKind) {
      CodeCompletionKeywordKind kwKind;
      switch (magicKind) {
      case MagicIdentifierLiteralExpr::FileIDSpelledAsFile:
        kwKind = CodeCompletionKeywordKind::pound_file;
        break;
      case MagicIdentifierLiteralExpr::FilePathSpelledAsFile:
        // Already handled by above case.
        return;
#define MAGIC_IDENTIFIER_TOKEN(NAME, TOKEN) \
      case MagicIdentifierLiteralExpr::NAME: \
        kwKind = CodeCompletionKeywordKind::TOKEN; \
        break;
#define MAGIC_IDENTIFIER_DEPRECATED_TOKEN(NAME, TOKEN)
#include "swift/AST/MagicIdentifierKinds.def"
      }

      StringRef name = MagicIdentifierLiteralExpr::getKindString(magicKind);
      if (!needPound)
        name = name.substr(1);

      if (!literalKind) {
        // Pointer type
        addKeyword(name, "UnsafeRawPointer", kwKind);
        return;
      }

      CodeCompletionResultBuilder builder(
          Sink, CodeCompletionResult::ResultKind::Keyword,
          SemanticContextKind::None, {});
      builder.setLiteralKind(literalKind.getValue());
      builder.setKeywordKind(kwKind);
      builder.addBaseName(name);
      addTypeRelationFromProtocol(builder, literalKind.getValue());
    };

#define MAGIC_STRING_IDENTIFIER(NAME, STRING, SYNTAX_KIND) \
    addFromProto(MagicIdentifierLiteralExpr::NAME, \
                 CodeCompletionLiteralKind::StringLiteral);
#define MAGIC_INT_IDENTIFIER(NAME, STRING, SYNTAX_KIND) \
    addFromProto(MagicIdentifierLiteralExpr::NAME, \
                 CodeCompletionLiteralKind::IntegerLiteral);
#define MAGIC_POINTER_IDENTIFIER(NAME, STRING, SYNTAX_KIND) \
    addFromProto(MagicIdentifierLiteralExpr::NAME, \
                 None);
#include "swift/AST/MagicIdentifierKinds.def"
  }

  void addValueLiteralCompletions() {
    auto &context = CurrDeclContext->getASTContext();

    auto addFromProto = [&](
        CodeCompletionLiteralKind kind,
        llvm::function_ref<void(CodeCompletionResultBuilder &)> consumer,
        bool isKeyword = false) {

      CodeCompletionResultBuilder builder(Sink, CodeCompletionResult::Literal,
                                          SemanticContextKind::None, {});
      builder.setLiteralKind(kind);

      consumer(builder);
      addTypeRelationFromProtocol(builder, kind);
    };

    // FIXME: the pedantically correct way is to resolve Swift.*LiteralType.

    using LK = CodeCompletionLiteralKind;
    using Builder = CodeCompletionResultBuilder;

    // Add literal completions that conform to specific protocols.
    addFromProto(LK::IntegerLiteral, [](Builder &builder) {
      builder.addTextChunk("0");
    });
    addFromProto(LK::BooleanLiteral, [](Builder &builder) {
      builder.addBaseName("true");
    }, /*isKeyword=*/true);
    addFromProto(LK::BooleanLiteral, [](Builder &builder) {
      builder.addBaseName("false");
    }, /*isKeyword=*/true);
    addFromProto(LK::NilLiteral, [](Builder &builder) {
      builder.addBaseName("nil");
    }, /*isKeyword=*/true);
    addFromProto(LK::StringLiteral, [&](Builder &builder) {
      builder.addTextChunk("\"");
      builder.addSimpleNamedParameter("abc");
      builder.addTextChunk("\"");
    });
    addFromProto(LK::ArrayLiteral, [&](Builder &builder) {
      builder.addLeftBracket();
      builder.addSimpleNamedParameter("values");
      builder.addRightBracket();
    });
    addFromProto(LK::DictionaryLiteral, [&](Builder &builder) {
      builder.addLeftBracket();
      builder.addSimpleNamedParameter("key");
      builder.addTextChunk(": ");
      builder.addSimpleNamedParameter("value");
      builder.addRightBracket();
    });

    auto floatType = context.getFloatDecl()->getDeclaredInterfaceType();
    addFromProto(LK::ColorLiteral, [&](Builder &builder) {
      builder.addBaseName("#colorLiteral");
      builder.addLeftParen();
      builder.addCallParameter(context.getIdentifier("red"), floatType);
      builder.addComma();
      builder.addCallParameter(context.getIdentifier("green"), floatType);
      builder.addComma();
      builder.addCallParameter(context.getIdentifier("blue"), floatType);
      builder.addComma();
      builder.addCallParameter(context.getIdentifier("alpha"), floatType);
      builder.addRightParen();
    });

    auto stringType = context.getStringDecl()->getDeclaredInterfaceType();
    addFromProto(LK::ImageLiteral, [&](Builder &builder) {
      builder.addBaseName("#imageLiteral");
      builder.addLeftParen();
      builder.addCallParameter(context.getIdentifier("resourceName"),
                               stringType);
      builder.addRightParen();
    });

    // Add tuple completion (item, item).
    {
      CodeCompletionResultBuilder builder(Sink, CodeCompletionResult::Literal,
                                          SemanticContextKind::None, {});
      builder.setLiteralKind(LK::Tuple);

      builder.addLeftParen();
      builder.addSimpleNamedParameter("values");
      builder.addRightParen();
      for (auto T : expectedTypeContext.possibleTypes) {
        if (T && T->is<TupleType>() && !T->isVoid()) {
          addTypeAnnotation(builder, T);
          builder.setExpectedTypeRelation(CodeCompletionResult::Identical);
          break;
        }
      }
    }
  }

  void addObjCPoundKeywordCompletions(bool needPound) {
    if (!Ctx.LangOpts.EnableObjCInterop)
      return;

    // If the expected type is ObjectiveC.Selector, add #selector. If
    // it's String, add #keyPath.
    bool addedSelector = false;
    bool addedKeyPath = false;

    for (auto T : expectedTypeContext.possibleTypes) {
      T = T->lookThroughAllOptionalTypes();
      if (auto structDecl = T->getStructOrBoundGenericStruct()) {
        if (!addedSelector && structDecl->getName() == Ctx.Id_Selector &&
            structDecl->getParentModule()->getName() == Ctx.Id_ObjectiveC) {
          addPoundSelector(needPound);
          if (addedKeyPath)
            break;
          addedSelector = true;
          continue;
        }
      }

      if (!addedKeyPath && T->getAnyNominal() == Ctx.getStringDecl()) {
        addPoundKeyPath(needPound);
        if (addedSelector)
          break;
        addedKeyPath = true;
        continue;
      }
    }
  }

  struct FilteredDeclConsumer : public swift::VisibleDeclConsumer {
    swift::VisibleDeclConsumer &Consumer;
    DeclFilter Filter;
    FilteredDeclConsumer(swift::VisibleDeclConsumer &Consumer,
                         DeclFilter Filter) : Consumer(Consumer), Filter(Filter) {}
    void foundDecl(ValueDecl *VD, DeclVisibilityKind Kind,
                   DynamicLookupInfo dynamicLookupInfo) override {
      if (Filter(VD, Kind))
        Consumer.foundDecl(VD, Kind, dynamicLookupInfo);
    }
  };

  void getValueCompletionsInDeclContext(SourceLoc Loc,
                                        DeclFilter Filter = DefaultFilter,
                                        bool LiteralCompletions = true,
                                        bool ModuleQualifier = true) {
    ExprType = Type();
    Kind = LookupKind::ValueInDeclContext;
    NeedLeadingDot = false;

    AccessFilteringDeclConsumer AccessFilteringConsumer(
        CurrDeclContext, *this);
    FilteredDeclConsumer FilteringConsumer(AccessFilteringConsumer, Filter);

    lookupVisibleDecls(FilteringConsumer, CurrDeclContext,
                       /*IncludeTopLevel=*/false, Loc);
    RequestedCachedResults.push_back(RequestedResultsTy::toplevelResults()
                                         .withModuleQualifier(ModuleQualifier));

    // Manually add any expected nominal types from imported modules so that
    // they get their expected type relation. Don't include protocols, since
    // they can't be initialized from the type name.
    // FIXME: this does not include types that conform to an expected protocol.
    // FIXME: this creates duplicate results.
    for (auto T : expectedTypeContext.possibleTypes) {
      if (auto NT = T->getAs<NominalType>()) {
        if (auto NTD = NT->getDecl()) {
          if (!isa<ProtocolDecl>(NTD) &&
              NTD->getModuleContext() != CurrModule) {
            addNominalTypeRef(NT->getDecl(),
                              DeclVisibilityKind::VisibleAtTopLevel, {});
          }
        }
      }
    }

    if (CompletionContext) {
      // FIXME: this is an awful simplification that says all and only enums can
      // use implicit member syntax (leading dot). Computing the accurate answer
      // using lookup (e.g. getUnresolvedMemberCompletions) is too expensive,
      // and for some clients this approximation is good enough.
      CompletionContext->MayUseImplicitMemberExpr =
          std::any_of(expectedTypeContext.possibleTypes.begin(),
                      expectedTypeContext.possibleTypes.end(),
          [](Type T) {
            if (auto *NTD = T->getAnyNominal())
              return isa<EnumDecl>(NTD);
            return false;
          });
    }

    if (LiteralCompletions) {
      addValueLiteralCompletions();
      addPoundLiteralCompletions(/*needPound=*/true);
    }

    addObjCPoundKeywordCompletions(/*needPound=*/true);
  }

  void getUnresolvedMemberCompletions(Type T) {
    if (!T->mayHaveMembers())
      return;

    if (auto objT = T->getOptionalObjectType()) {
      // Add 'nil' keyword with erasing '.' instruction.
      unsigned bytesToErase = 0;
      auto &SM = CurrDeclContext->getASTContext().SourceMgr;
      if (DotLoc.isValid())
        bytesToErase = SM.getByteDistance(DotLoc, SM.getCodeCompletionLoc());
      addKeyword("nil", T, SemanticContextKind::None,
                 CodeCompletionKeywordKind::kw_nil, bytesToErase);
    }

    // We can only say .foo where foo is a static member of the contextual
    // type and has the same type (or if the member is a function, then the
    // same result type) as the contextual type.
    FilteredDeclConsumer consumer(*this, [=](ValueDecl *VD,
                                             DeclVisibilityKind Reason) {
      if (T->getOptionalObjectType() &&
          VD->getModuleContext()->isStdlibModule()) {
        // In optional context, ignore '.init(<some>)', 'init(nilLiteral:)',
        if (isa<ConstructorDecl>(VD))
          return false;
      }
      return true;
    });

    auto baseType = MetatypeType::get(T);
    llvm::SaveAndRestore<LookupKind> SaveLook(Kind, LookupKind::ValueExpr);
    llvm::SaveAndRestore<Type> SaveType(ExprType, baseType);
    llvm::SaveAndRestore<bool> SaveUnresolved(IsUnresolvedMember, true);
    lookupVisibleMemberDecls(consumer, baseType, CurrDeclContext,
                             /*includeInstanceMembers=*/false,
                             /*includeDerivedRequirements*/false,
                             /*includeProtocolExtensionMembers*/true);
  }

  void getUnresolvedMemberCompletions(ArrayRef<Type> Types) {
    NeedLeadingDot = !HaveDot;

    SmallPtrSet<CanType, 4> seenTypes;
    for (auto T : Types) {
      if (!T || !seenTypes.insert(T->getCanonicalType()).second)
        continue;

      if (auto objT = T->getOptionalObjectType()) {
        // If this is optional type, perform completion for the object type.
        // i.e. 'let _: Enum??? = .enumMember' is legal.
        objT = objT->lookThroughAllOptionalTypes();
        if (seenTypes.insert(objT->getCanonicalType()).second)
          getUnresolvedMemberCompletions(objT);
      }
      getUnresolvedMemberCompletions(T);
    }
  }

  void addCallArgumentCompletionResults(
      ArrayRef<PossibleParamInfo> ParamInfos,
      bool isLabeledTrailingClosure = false) {
    Type ContextType;
    if (auto typeContext = CurrDeclContext->getInnermostTypeContext())
      ContextType = typeContext->getDeclaredTypeInContext();

    for (auto Info : ParamInfos) {
      const auto *Arg = Info.Param;
      if (!Arg)
        continue;
      CodeCompletionResultBuilder Builder(
          Sink, CodeCompletionResult::ResultKind::Pattern,
          SemanticContextKind::ExpressionSpecific, {});
      Builder.addCallParameter(Arg->getLabel(), Identifier(),
                               Arg->getPlainType(), ContextType,
                               Arg->isVariadic(), Arg->isInOut(),
                               /*isIUO=*/false, Arg->isAutoClosure(),
                               /*useUnderscoreLabel=*/true,
                               isLabeledTrailingClosure);
      auto Ty = Arg->getPlainType();
      if (Arg->isInOut()) {
        Ty = InOutType::get(Ty);
      } else if (Arg->isAutoClosure()) {
        // 'Ty' may be ErrorType.
        if (auto funcTy = Ty->getAs<FunctionType>())
          Ty = funcTy->getResult();
      }
      addTypeAnnotation(Builder, Ty);
      Builder.setExpectedTypeRelation(
          CodeCompletionResult::ExpectedTypeRelation::NotApplicable);
    }
  }

  void getTypeCompletions(Type BaseType) {
    if (tryModuleCompletions(BaseType, /*OnlyTypes=*/true))
      return;
    Kind = LookupKind::Type;
    this->BaseType = BaseType;
    NeedLeadingDot = !HaveDot;
    lookupVisibleMemberDecls(*this, MetatypeType::get(BaseType),
                             CurrDeclContext,
                             IncludeInstanceMembers,
                             /*includeDerivedRequirements*/false,
                             /*includeProtocolExtensionMembers*/false);
    if (BaseType->isAnyExistentialType()) {
      addKeyword("Protocol", MetatypeType::get(BaseType));
      addKeyword("Type", ExistentialMetatypeType::get(BaseType));
    } else if (!BaseType->is<ModuleType>()) {
      addKeyword("Type", MetatypeType::get(BaseType));
    }
  }

  void getGenericRequirementCompletions(DeclContext *DC) {
    auto genericSig = DC->getGenericSignatureOfContext();
    if (!genericSig)
      return;

    for (auto GPT : genericSig->getGenericParams()) {
      addGenericTypeParamRef(GPT->getDecl(),
                             DeclVisibilityKind::GenericParameter, {});
    }

    // For non-protocol nominal type decls, only suggest generic parameters.
    if (auto D = DC->getAsDecl())
      if (isa<NominalTypeDecl>(D) && !isa<ProtocolDecl>(D))
        return;

    auto typeContext = DC->getInnermostTypeContext();
    if (!typeContext)
      return;

    auto selfTy = typeContext->getSelfTypeInContext();
    Kind = LookupKind::GenericRequirement;
    this->BaseType = selfTy;
    NeedLeadingDot = false;
    lookupVisibleMemberDecls(*this, MetatypeType::get(selfTy),
                             CurrDeclContext, IncludeInstanceMembers,
                             /*includeDerivedRequirements*/false,
                             /*includeProtocolExtensionMembers*/true);
  }

  static bool canUseAttributeOnDecl(DeclAttrKind DAK, bool IsInSil,
                                    bool IsConcurrencyEnabled,
                                    Optional<DeclKind> DK) {
    if (DeclAttribute::isUserInaccessible(DAK))
      return false;
    if (DeclAttribute::isDeclModifier(DAK))
      return false;
    if (DeclAttribute::shouldBeRejectedByParser(DAK))
      return false;
    if (!IsInSil && DeclAttribute::isSilOnly(DAK))
      return false;
    if (!IsConcurrencyEnabled && DeclAttribute::isConcurrencyOnly(DAK))
      return false;
    if (!DK.hasValue())
      return true;
    return DeclAttribute::canAttributeAppearOnDeclKind(DAK, DK.getValue());
  }

  void getAttributeDeclCompletions(bool IsInSil, Optional<DeclKind> DK) {
    // FIXME: also include user-defined attribute keywords
    StringRef TargetName = "Declaration";
    if (DK.hasValue()) {
      switch (DK.getValue()) {
#define DECL(Id, ...)                                                         \
      case DeclKind::Id:                                                      \
        TargetName = #Id;                                                     \
        break;
#include "swift/AST/DeclNodes.def"
      }
    }
    bool IsConcurrencyEnabled = Ctx.LangOpts.EnableExperimentalConcurrency;
    std::string Description = TargetName.str() + " Attribute";
#define DECL_ATTR(KEYWORD, NAME, ...)                                         \
    if (canUseAttributeOnDecl(DAK_##NAME, IsInSil, IsConcurrencyEnabled, DK)) \
      addDeclAttrKeyword(#KEYWORD, Description);
#include "swift/AST/Attr.def"
  }

  void getAttributeDeclParamCompletions(DeclAttrKind AttrKind, int ParamIndex) {
    if (AttrKind == DAK_Available) {
      if (ParamIndex == 0) {
        addDeclAttrParamKeyword("*", "Platform", false);

#define AVAILABILITY_PLATFORM(X, PrettyName)                                  \
        addDeclAttrParamKeyword(swift::platformString(PlatformKind::X),       \
                                "Platform", false);
#include "swift/AST/PlatformKinds.def"

      } else {
        addDeclAttrParamKeyword("unavailable", "", false);
        addDeclAttrParamKeyword("message", "Specify message", true);
        addDeclAttrParamKeyword("renamed", "Specify replacing name", true);
        addDeclAttrParamKeyword("introduced", "Specify version number", true);
        addDeclAttrParamKeyword("deprecated", "Specify version number", true);
      }
    }
  }

  void collectPrecedenceGroups() {
    assert(CurrDeclContext);

    if (CurrModule) {
      for (auto FU: CurrModule->getFiles()) {
        // We are looking through the current module,
        // inspect only source files.
        if (FU->getKind() != FileUnitKind::Source)
          continue;

        llvm::SmallVector<PrecedenceGroupDecl*, 4> results;
        cast<SourceFile>(FU)->getPrecedenceGroups(results);

        for (auto PG: results)
            addPrecedenceGroupRef(PG);
      }
    }
    for (auto Import : namelookup::getAllImports(CurrDeclContext)) {
      auto Module = Import.importedModule;
      if (Module == CurrModule)
        continue;

      RequestedCachedResults.push_back(RequestedResultsTy::fromModule(Module)
                                           .onlyPrecedenceGroups()
                                           .withModuleQualifier(false));
    }
  }

  void getPrecedenceGroupCompletions(SyntaxKind SK) {
    switch (SK) {
    case SyntaxKind::PrecedenceGroupAssociativity:
      addKeyword(getAssociativitySpelling(Associativity::None));
      addKeyword(getAssociativitySpelling(Associativity::Left));
      addKeyword(getAssociativitySpelling(Associativity::Right));
      break;
    case SyntaxKind::PrecedenceGroupAssignment:
      addKeyword(getTokenText(tok::kw_false), Type(), SemanticContextKind::None,
                 CodeCompletionKeywordKind::kw_false);
      addKeyword(getTokenText(tok::kw_true), Type(), SemanticContextKind::None,
                 CodeCompletionKeywordKind::kw_true);
      break;
    case SyntaxKind::PrecedenceGroupAttributeList:
      addKeyword("associativity");
      addKeyword("higherThan");
      addKeyword("lowerThan");
      addKeyword("assignment");
      break;
    case SyntaxKind::PrecedenceGroupRelation:
      collectPrecedenceGroups();
      break;
    default:
        llvm_unreachable("not a precedencegroup SyntaxKind");
    }
  }

  void getPoundAvailablePlatformCompletions() {

    // The platform names should be identical to those in @available.
    getAttributeDeclParamCompletions(DAK_Available, 0);
  }

  void getSelfTypeCompletionInDeclContext(SourceLoc Loc, bool isForDeclResult) {
    const DeclContext *typeDC = CurrDeclContext->getInnermostTypeContext();
    if (!typeDC)
      return;

    // For protocols, there's a 'Self' generic parameter.
    if (typeDC->getSelfProtocolDecl())
      return;

    Type selfType =
        CurrDeclContext->mapTypeIntoContext(typeDC->getSelfInterfaceType());

    if (typeDC->getSelfClassDecl()) {
      // In classes, 'Self' can be used in result type of func, subscript and
      // computed property, or inside function bodies.
      bool canUseDynamicSelf = false;
      if (isForDeclResult) {
        canUseDynamicSelf = true;
      } else {
        const auto *checkDC = CurrDeclContext;
        if (isa<TypeAliasDecl>(checkDC))
          checkDC = checkDC->getParent();

        if (const auto *AFD = checkDC->getInnermostMethodContext()) {
          canUseDynamicSelf = Ctx.SourceMgr.rangeContainsTokenLoc(
              AFD->getBodySourceRange(), Loc);
        }
      }
      if (!canUseDynamicSelf)
        return;
      // 'Self' in class is a dynamic type.
      selfType = DynamicSelfType::get(selfType, Ctx);
    } else {
      // In enums and structs, 'Self' is just an alias for the nominal type,
      // and can be used anywhere.
    }

    CodeCompletionResultBuilder Builder(
        Sink, CodeCompletionResult::ResultKind::Keyword,
        SemanticContextKind::CurrentNominal, expectedTypeContext);
    Builder.addKeyword("Self");
    Builder.setKeywordKind(CodeCompletionKeywordKind::kw_Self);
    addTypeAnnotation(Builder, selfType);
  }

  void getTypeCompletionsInDeclContext(SourceLoc Loc,
                                       bool ModuleQualifier = true) {
    Kind = LookupKind::TypeInDeclContext;

    AccessFilteringDeclConsumer AccessFilteringConsumer(
        CurrDeclContext, *this);
    lookupVisibleDecls(AccessFilteringConsumer, CurrDeclContext,
                       /*IncludeTopLevel=*/false, Loc);

    RequestedCachedResults.push_back(
      RequestedResultsTy::toplevelResults()
        .onlyTypes()
        .withModuleQualifier(ModuleQualifier));
  }

  void getToplevelCompletions(bool OnlyTypes) {
    Kind = OnlyTypes ? LookupKind::TypeInDeclContext
                     : LookupKind::ValueInDeclContext;
    NeedLeadingDot = false;

    UsableFilteringDeclConsumer UsableFilteringConsumer(
        Ctx.SourceMgr, CurrDeclContext, Ctx.SourceMgr.getCodeCompletionLoc(),
        *this);
    AccessFilteringDeclConsumer AccessFilteringConsumer(
        CurrDeclContext, UsableFilteringConsumer);

    CurrModule->lookupVisibleDecls({}, AccessFilteringConsumer,
                                   NLKind::UnqualifiedLookup);
  }

  void lookupExternalModuleDecls(const ModuleDecl *TheModule,
                                 ArrayRef<std::string> AccessPath,
                                 bool ResultsHaveLeadingDot) {
    assert(CurrModule != TheModule &&
           "requested module should be external");

    Kind = LookupKind::ImportFromModule;
    NeedLeadingDot = ResultsHaveLeadingDot;

    ImportPath::Access::Builder builder;
    for (auto Piece : AccessPath) {
      builder.push_back(Ctx.getIdentifier(Piece));
    }

    AccessFilteringDeclConsumer FilteringConsumer(CurrDeclContext, *this);
    TheModule->lookupVisibleDecls(builder.get(), FilteringConsumer,
                                  NLKind::UnqualifiedLookup);

    llvm::SmallVector<PrecedenceGroupDecl*, 16> precedenceGroups;
    TheModule->getPrecedenceGroups(precedenceGroups);

    for (auto PGD: precedenceGroups)
      addPrecedenceGroupRef(PGD);
  }

  void getStmtLabelCompletions(SourceLoc Loc, bool isContinue) {
    class LabelFinder : public ASTWalker {
      SourceManager &SM;
      SourceLoc TargetLoc;
      bool IsContinue;

    public:
      SmallVector<Identifier, 2> Result;

      LabelFinder(SourceManager &SM, SourceLoc TargetLoc, bool IsContinue)
          : SM(SM), TargetLoc(TargetLoc), IsContinue(IsContinue) {}

      std::pair<bool, Stmt *> walkToStmtPre(Stmt *S) override {
        if (SM.isBeforeInBuffer(S->getEndLoc(), TargetLoc))
          return {false, S};

        if (LabeledStmt *LS = dyn_cast<LabeledStmt>(S)) {
          if (LS->getLabelInfo()) {
            if (!IsContinue || LS->isPossibleContinueTarget()) {
              auto label = LS->getLabelInfo().Name;
              if (!llvm::is_contained(Result, label))
                Result.push_back(label);
            }
          }
        }

        return {true, S};
      }

      Stmt *walkToStmtPost(Stmt *S) override { return nullptr; }

      std::pair<bool, Expr *> walkToExprPre(Expr *E) override {
        if (SM.isBeforeInBuffer(E->getEndLoc(), TargetLoc))
          return {false, E};
        return {true, E};
      }
    } Finder(CurrDeclContext->getASTContext().SourceMgr, Loc, isContinue);
    const_cast<DeclContext *>(CurrDeclContext)->walkContext(Finder);
    for (auto name : Finder.Result) {
      CodeCompletionResultBuilder Builder(
          Sink, CodeCompletionResult::ResultKind::Pattern,
          SemanticContextKind::Local, {});
      Builder.addTextChunk(name.str());
    }
  }
};

class CompletionOverrideLookup : public swift::VisibleDeclConsumer {
  CodeCompletionResultSink &Sink;
  ASTContext &Ctx;
  const DeclContext *CurrDeclContext;
  SmallVectorImpl<StringRef> &ParsedKeywords;
  SourceLoc introducerLoc;

  bool hasFuncIntroducer = false;
  bool hasVarIntroducer = false;
  bool hasTypealiasIntroducer = false;
  bool hasInitializerModifier = false;
  bool hasAccessModifier = false;
  bool hasOverride = false;
  bool hasOverridabilityModifier = false;
  bool hasStaticOrClass = false;

public:
  CompletionOverrideLookup(CodeCompletionResultSink &Sink, ASTContext &Ctx,
                           const DeclContext *CurrDeclContext,
                           SmallVectorImpl<StringRef> &ParsedKeywords,
                           SourceLoc introducerLoc)
      : Sink(Sink), Ctx(Ctx), CurrDeclContext(CurrDeclContext),
        ParsedKeywords(ParsedKeywords), introducerLoc(introducerLoc) {
    hasFuncIntroducer = isKeywordSpecified("func");
    hasVarIntroducer = isKeywordSpecified("var") ||
                       isKeywordSpecified("let");
    hasTypealiasIntroducer = isKeywordSpecified("typealias");
    hasInitializerModifier = isKeywordSpecified("required") ||
                             isKeywordSpecified("convenience");
    hasAccessModifier = isKeywordSpecified("private") ||
                        isKeywordSpecified("fileprivate") ||
                        isKeywordSpecified("internal") ||
                        isKeywordSpecified("public") ||
                        isKeywordSpecified("open");
    hasOverride = isKeywordSpecified("override");
    hasOverridabilityModifier = isKeywordSpecified("final") ||
                                isKeywordSpecified("open");
    hasStaticOrClass = isKeywordSpecified(getTokenText(tok::kw_class)) ||
                       isKeywordSpecified(getTokenText(tok::kw_static));
  }

  bool isKeywordSpecified(StringRef Word) {
    return std::find(ParsedKeywords.begin(), ParsedKeywords.end(), Word)
      != ParsedKeywords.end();
  }

  bool missingOverride(DeclVisibilityKind Reason) {
    return !hasOverride && Reason == DeclVisibilityKind::MemberOfSuper &&
           !CurrDeclContext->getSelfProtocolDecl();
  }

  void addAccessControl(const ValueDecl *VD,
                        CodeCompletionResultBuilder &Builder) {
    auto CurrentNominal = CurrDeclContext->getSelfNominalTypeDecl();
    assert(CurrentNominal);

    auto AccessOfContext = CurrentNominal->getFormalAccess();
    if (AccessOfContext < AccessLevel::Public)
      return;

    auto Access = VD->getFormalAccess();
    // Use the greater access between the protocol requirement and the witness.
    // In case of:
    //
    //   public protocol P { func foo() }
    //   public class B { func foo() {} }
    //   public class C: B, P {
    //     <complete>
    //   }
    //
    // 'VD' is 'B.foo()' which is implicitly 'internal'. But as the overriding
    // declaration, the user needs to write both 'public' and 'override':
    //
    //   public class C: B {
    //     public override func foo() {}
    //   }
    if (Access < AccessLevel::Public &&
        !isa<ProtocolDecl>(VD->getDeclContext())) {
      for (auto Conformance : CurrentNominal->getAllConformances()) {
        Conformance->getRootConformance()->forEachValueWitness(
            [&](ValueDecl *req, Witness witness) {
              if (witness.getDecl() == VD)
                Access = std::max(
                    Access, Conformance->getProtocol()->getFormalAccess());
            });
      }
    }

    Access = std::min(Access, AccessOfContext);
    // Only emit 'public', not needed otherwise.
    if (Access >= AccessLevel::Public)
      Builder.addAccessControlKeyword(Access);
  }

  /// Return type if the result type if \p VD should be represented as opaque
  /// result type.
  Type getOpaqueResultType(const ValueDecl *VD, DeclVisibilityKind Reason,
                           DynamicLookupInfo dynamicLookupInfo) {
    if (Reason !=
        DeclVisibilityKind::MemberOfProtocolConformedToByCurrentNominal)
      return nullptr;

    auto currTy = CurrDeclContext->getDeclaredTypeInContext();
    if (!currTy)
      return nullptr;

    Type ResultT;
    if (auto *FD = dyn_cast<FuncDecl>(VD)) {
      if (FD->getGenericParams()) {
        // Generic function cannot have opaque result type.
        return nullptr;
      }
      ResultT = FD->getResultInterfaceType();
    } else if (auto *SD = dyn_cast<SubscriptDecl>(VD)) {
      if (SD->getGenericParams()) {
        // Generic subscript cannot have opaque result type.
        return nullptr;
      }
      ResultT = SD->getElementInterfaceType();
    } else if (auto *VarD = dyn_cast<VarDecl>(VD)) {
      ResultT = VarD->getInterfaceType();
    } else {
      return nullptr;
    }

    if (!ResultT->is<DependentMemberType>() ||
        !ResultT->castTo<DependentMemberType>()->getAssocType())
      // The result is not a valid associatedtype.
      return nullptr;

    // Try substitution to see if the associated type is resolved to concrete
    // type.
    auto substMap = currTy->getMemberSubstitutionMap(
        CurrDeclContext->getParentModule(), VD);
    if (!ResultT.subst(substMap)->is<DependentMemberType>())
      // If resolved print it.
      return nullptr;

    auto genericSig = VD->getDeclContext()->getGenericSignatureOfContext();

    if (genericSig->isConcreteType(ResultT))
      // If it has same type requrement, we will emit the concrete type.
      return nullptr;

    // Collect requirements on the associatedtype.
    SmallVector<Type, 2> opaqueTypes;
    bool hasExplicitAnyObject = false;
    if (auto superTy = genericSig->getSuperclassBound(ResultT))
      opaqueTypes.push_back(superTy);
    for (const auto proto : genericSig->getRequiredProtocols(ResultT))
      opaqueTypes.push_back(proto->getDeclaredInterfaceType());
    if (auto layout = genericSig->getLayoutConstraint(ResultT))
      hasExplicitAnyObject = layout->isClass();

    if (!hasExplicitAnyObject) {
      if (opaqueTypes.empty())
        return nullptr;
      if (opaqueTypes.size() == 1)
        return opaqueTypes.front();
    }
    return ProtocolCompositionType::get(
        VD->getASTContext(), opaqueTypes, hasExplicitAnyObject);
  }

  void addValueOverride(const ValueDecl *VD, DeclVisibilityKind Reason,
                        DynamicLookupInfo dynamicLookupInfo,
                        CodeCompletionResultBuilder &Builder,
                        bool hasDeclIntroducer) {
    class DeclPrinter : public StreamPrinter {
      Type OpaqueBaseTy;

    public:
      using StreamPrinter::StreamPrinter;

      Optional<unsigned> NameOffset;

      DeclPrinter(raw_ostream &OS, Type OpaqueBaseTy)
          : StreamPrinter(OS), OpaqueBaseTy(OpaqueBaseTy) {}

      void printDeclLoc(const Decl *D) override {
        if (!NameOffset.hasValue())
          NameOffset = OS.tell();
      }

      // As for FuncDecl, SubscriptDecl, and VarDecl,
      void printDeclResultTypePre(ValueDecl *VD, TypeLoc &TL) override {
        if (!OpaqueBaseTy.isNull()) {
          OS << "some ";
          TL = TypeLoc::withoutLoc(OpaqueBaseTy);
        }
      }
    };

    llvm::SmallString<256> DeclStr;
    unsigned NameOffset = 0;
    {
      llvm::raw_svector_ostream OS(DeclStr);
      DeclPrinter Printer(
          OS, getOpaqueResultType(VD, Reason, dynamicLookupInfo));
      PrintOptions Options;
      if (auto transformType = CurrDeclContext->getDeclaredTypeInContext())
        Options.setBaseType(transformType);
      Options.SkipUnderscoredKeywords = true;
      Options.PrintImplicitAttrs = false;
      Options.ExclusiveAttrList.push_back(TAK_escaping);
      Options.ExclusiveAttrList.push_back(TAK_autoclosure);
      Options.PrintOverrideKeyword = false;
      Options.PrintPropertyAccessors = false;
      Options.PrintSubscriptAccessors = false;
      Options.PrintStaticKeyword = !hasStaticOrClass;
      VD->print(Printer, Options);
      NameOffset = Printer.NameOffset.getValue();
    }

    if (!hasDeclIntroducer && !hasAccessModifier)
      addAccessControl(VD, Builder);

    if (missingOverride(Reason)) {
      if (!hasDeclIntroducer)
        Builder.addOverrideKeyword();
      else {
        auto dist = Ctx.SourceMgr.getByteDistance(
            introducerLoc, Ctx.SourceMgr.getCodeCompletionLoc());
        if (dist <= CodeCompletionResult::MaxNumBytesToErase) {
          Builder.setNumBytesToErase(dist);
          Builder.addOverrideKeyword();
          Builder.addDeclIntroducer(DeclStr.str().substr(0, NameOffset));
        }
      }
    }

    if (!hasDeclIntroducer && NameOffset != 0)
      Builder.addDeclIntroducer(DeclStr.str().substr(0, NameOffset));

    Builder.addTextChunk(DeclStr.str().substr(NameOffset));
  }

  void addMethodOverride(const FuncDecl *FD, DeclVisibilityKind Reason,
                         DynamicLookupInfo dynamicLookupInfo) {
    CodeCompletionResultBuilder Builder(
        Sink, CodeCompletionResult::ResultKind::Declaration,
        SemanticContextKind::Super, {});
    Builder.setExpectedTypeRelation(
        CodeCompletionResult::ExpectedTypeRelation::NotApplicable);
    Builder.setAssociatedDecl(FD);
    addValueOverride(FD, Reason, dynamicLookupInfo, Builder, hasFuncIntroducer);
    Builder.addBraceStmtWithCursor();
  }

  void addVarOverride(const VarDecl *VD, DeclVisibilityKind Reason,
                      DynamicLookupInfo dynamicLookupInfo) {
    // Overrides cannot use 'let', but if the 'override' keyword is specified
    // then the intention is clear, so provide the results anyway.  The compiler
    // can then provide an error telling you to use 'var' instead.
    // If we don't need override then it's a protocol requirement, so show it.
    if (missingOverride(Reason) && hasVarIntroducer &&
        isKeywordSpecified("let"))
      return;

    CodeCompletionResultBuilder Builder(
        Sink, CodeCompletionResult::ResultKind::Declaration,
        SemanticContextKind::Super, {});
    Builder.setAssociatedDecl(VD);
    addValueOverride(VD, Reason, dynamicLookupInfo, Builder, hasVarIntroducer);
  }

  void addSubscriptOverride(const SubscriptDecl *SD, DeclVisibilityKind Reason,
                            DynamicLookupInfo dynamicLookupInfo) {
    CodeCompletionResultBuilder Builder(
        Sink, CodeCompletionResult::ResultKind::Declaration,
        SemanticContextKind::Super, {});
    Builder.setExpectedTypeRelation(
        CodeCompletionResult::ExpectedTypeRelation::NotApplicable);
    Builder.setAssociatedDecl(SD);
    addValueOverride(SD, Reason, dynamicLookupInfo, Builder, false);
    Builder.addBraceStmtWithCursor();
  }

  void addTypeAlias(const AssociatedTypeDecl *ATD, DeclVisibilityKind Reason,
                    DynamicLookupInfo dynamicLookupInfo) {
    CodeCompletionResultBuilder Builder(Sink,
      CodeCompletionResult::ResultKind::Declaration,
      SemanticContextKind::Super, {});
    Builder.setExpectedTypeRelation(
        CodeCompletionResult::ExpectedTypeRelation::NotApplicable);
    Builder.setAssociatedDecl(ATD);
    if (!hasTypealiasIntroducer && !hasAccessModifier)
      addAccessControl(ATD, Builder);
    if (!hasTypealiasIntroducer)
      Builder.addDeclIntroducer("typealias ");
    Builder.addTextChunk(ATD->getName().str());
    Builder.addTextChunk(" = ");
    Builder.addSimpleNamedParameter("Type");
  }

  void addConstructor(const ConstructorDecl *CD, DeclVisibilityKind Reason,
                      DynamicLookupInfo dynamicLookupInfo) {
    CodeCompletionResultBuilder Builder(
        Sink,
        CodeCompletionResult::ResultKind::Declaration,
        SemanticContextKind::Super, {});
    Builder.setExpectedTypeRelation(
        CodeCompletionResult::ExpectedTypeRelation::NotApplicable);
    Builder.setAssociatedDecl(CD);

    if (!hasAccessModifier)
      addAccessControl(CD, Builder);

    if (missingOverride(Reason) && CD->isDesignatedInit() && !CD->isRequired())
      Builder.addOverrideKeyword();

    // Emit 'required' if we're in class context, 'required' is not specified,
    // and 1) this is a protocol conformance and the class is not final, or 2)
    // this is subclass and the initializer is marked as required.
    bool needRequired = false;
    auto C = CurrDeclContext->getSelfClassDecl();
    if (C && !isKeywordSpecified("required")) {
      switch (Reason) {
      case DeclVisibilityKind::MemberOfProtocolConformedToByCurrentNominal:
      case DeclVisibilityKind::MemberOfProtocolDerivedByCurrentNominal:
        if (!C->isFinal())
          needRequired = true;
        break;
      case DeclVisibilityKind::MemberOfSuper:
        if (CD->isRequired())
          needRequired = true;
        break;
      default: break;
      }
    }

    llvm::SmallString<256> DeclStr;
    if (needRequired)
      DeclStr += "required ";
    {
      llvm::raw_svector_ostream OS(DeclStr);
      PrintOptions Options;
      if (auto transformType = CurrDeclContext->getDeclaredTypeInContext())
        Options.setBaseType(transformType);
      Options.PrintImplicitAttrs = false;
      Options.SkipAttributes = true;
      CD->print(OS, Options);
    }
    Builder.addTextChunk(DeclStr);
    Builder.addBraceStmtWithCursor();
  }

  // Implement swift::VisibleDeclConsumer.
  void foundDecl(ValueDecl *D, DeclVisibilityKind Reason,
                 DynamicLookupInfo dynamicLookupInfo) override {
    if (Reason == DeclVisibilityKind::MemberOfCurrentNominal)
      return;

    if (D->shouldHideFromEditor())
      return;

    if (D->isFinal())
      return;

    bool hasIntroducer = hasFuncIntroducer ||
                         hasVarIntroducer ||
                         hasTypealiasIntroducer;

    if (hasStaticOrClass && !D->isStatic())
      return;

    // As per the current convention, only instance members are
    // suggested if an introducer is not accompanied by a 'static' or
    // 'class' modifier.
    if (hasIntroducer && !hasStaticOrClass && D->isStatic())
      return;

    if (auto *FD = dyn_cast<FuncDecl>(D)) {
      // We cannot override operators as members.
      if (FD->isBinaryOperator() || FD->isUnaryOperator())
        return;

      // We cannot override individual accessors.
      if (isa<AccessorDecl>(FD))
        return;

      if (hasFuncIntroducer || (!hasIntroducer && !hasInitializerModifier))
        addMethodOverride(FD, Reason, dynamicLookupInfo);
      return;
    }

    if (auto *VD = dyn_cast<VarDecl>(D)) {
      if (hasVarIntroducer || (!hasIntroducer && !hasInitializerModifier))
        addVarOverride(VD, Reason, dynamicLookupInfo);
      return;
    }

    if (auto *SD = dyn_cast<SubscriptDecl>(D)) {
      if (!hasIntroducer && !hasInitializerModifier)
        addSubscriptOverride(SD, Reason, dynamicLookupInfo);
    }

    if (auto *CD = dyn_cast<ConstructorDecl>(D)) {
      if (!isa<ProtocolDecl>(CD->getDeclContext()))
        return;
      if (hasIntroducer || hasOverride || hasOverridabilityModifier ||
          hasStaticOrClass)
        return;
      if (CD->isRequired() || CD->isDesignatedInit())
        addConstructor(CD, Reason, dynamicLookupInfo);
      return;
    }
  }

  void addDesignatedInitializers(NominalTypeDecl *NTD) {
    if (hasFuncIntroducer || hasVarIntroducer || hasTypealiasIntroducer ||
        hasOverridabilityModifier || hasStaticOrClass)
      return;

    const auto *CD = dyn_cast<ClassDecl>(NTD);
    if (!CD)
      return;
    if (!CD->hasSuperclass())
      return;
    CD = CD->getSuperclassDecl();
    for (const auto *Member : CD->getMembers()) {
      const auto *Constructor = dyn_cast<ConstructorDecl>(Member);
      if (!Constructor)
        continue;
      if (Constructor->hasStubImplementation())
        continue;
      if (Constructor->isDesignatedInit())
        addConstructor(Constructor, DeclVisibilityKind::MemberOfSuper, {});
    }
  }

  void addAssociatedTypes(NominalTypeDecl *NTD) {
    if (!hasTypealiasIntroducer &&
        (hasFuncIntroducer || hasVarIntroducer || hasInitializerModifier ||
         hasOverride || hasOverridabilityModifier || hasStaticOrClass))
      return;

    for (auto Conformance : NTD->getAllConformances()) {
      auto Proto = Conformance->getProtocol();
      if (!Proto->isAccessibleFrom(CurrDeclContext))
        continue;
      for (auto *ATD : Proto->getAssociatedTypeMembers()) {
        // FIXME: Also exclude the type alias that has already been specified.
        if (!Conformance->hasTypeWitness(ATD) ||
            ATD->hasDefaultDefinitionType())
          continue;
        addTypeAlias(
            ATD,
            DeclVisibilityKind::MemberOfProtocolConformedToByCurrentNominal,
            {});
      }
    }
  }

  static StringRef getResultBuilderDocComment(
      ResultBuilderBuildFunction function) {
    switch (function) {
    case ResultBuilderBuildFunction::BuildArray:
      return "Enables support for..in loops in a result builder by "
        "combining the results of all iterations into a single result";

    case ResultBuilderBuildFunction::BuildBlock:
      return "Required by every result builder to build combined results "
          "from statement blocks";

    case ResultBuilderBuildFunction::BuildEitherFirst:
      return "With buildEither(second:), enables support for 'if-else' and "
          "'switch' statements by folding conditional results into a single "
          "result";

    case ResultBuilderBuildFunction::BuildEitherSecond:
      return "With buildEither(first:), enables support for 'if-else' and "
          "'switch' statements by folding conditional results into a single "
          "result";

    case ResultBuilderBuildFunction::BuildExpression:
      return "If declared, provides contextual type information for statement "
          "expressions to translate them into partial results";

    case ResultBuilderBuildFunction::BuildFinalResult:
      return "If declared, this will be called on the partial result from the "
          "outermost block statement to produce the final returned result";

    case ResultBuilderBuildFunction::BuildLimitedAvailability:
      return "If declared, this will be called on the partial result of "
        "an 'if #available' block to allow the result builder to erase "
        "type information";

    case ResultBuilderBuildFunction::BuildOptional:
      return "Enables support for `if` statements that do not have an `else`";
    }
  }

  void addResultBuilderBuildCompletion(
      NominalTypeDecl *builder, Type componentType,
      ResultBuilderBuildFunction function) {
    CodeCompletionResultBuilder Builder(
        Sink,
        CodeCompletionResult::ResultKind::Pattern,
        SemanticContextKind::CurrentNominal, {});
    Builder.setExpectedTypeRelation(
        CodeCompletionResult::ExpectedTypeRelation::NotApplicable);

    if (!hasFuncIntroducer) {
      if (!hasAccessModifier &&
          builder->getFormalAccess() >= AccessLevel::Public)
        Builder.addAccessControlKeyword(AccessLevel::Public);

      if (!hasStaticOrClass)
        Builder.addTextChunk("static ");

      Builder.addTextChunk("func ");
    }

    std::string declStringWithoutFunc;
    {
      llvm::raw_string_ostream out(declStringWithoutFunc);
      printResultBuilderBuildFunction(
          builder, componentType, function, None, out);
    }
    Builder.addTextChunk(declStringWithoutFunc);
    Builder.addBraceStmtWithCursor();
    Builder.setBriefDocComment(getResultBuilderDocComment(function));
  }

  /// Add completions for the various "build" functions in a result builder.
  void addResultBuilderBuildCompletions(NominalTypeDecl *builder) {
    Type componentType = inferResultBuilderComponentType(builder);

    addResultBuilderBuildCompletion(
        builder, componentType, ResultBuilderBuildFunction::BuildBlock);
    addResultBuilderBuildCompletion(
        builder, componentType, ResultBuilderBuildFunction::BuildExpression);
    addResultBuilderBuildCompletion(
        builder, componentType, ResultBuilderBuildFunction::BuildOptional);
    addResultBuilderBuildCompletion(
        builder, componentType, ResultBuilderBuildFunction::BuildEitherFirst);
    addResultBuilderBuildCompletion(
        builder, componentType, ResultBuilderBuildFunction::BuildEitherSecond);
    addResultBuilderBuildCompletion(
        builder, componentType, ResultBuilderBuildFunction::BuildArray);
    addResultBuilderBuildCompletion(
        builder, componentType,
        ResultBuilderBuildFunction::BuildLimitedAvailability);
    addResultBuilderBuildCompletion(
        builder, componentType, ResultBuilderBuildFunction::BuildFinalResult);
  }

  void getOverrideCompletions(SourceLoc Loc) {
    if (!CurrDeclContext->isTypeContext())
      return;
    if (isa<ProtocolDecl>(CurrDeclContext))
      return;

    Type CurrTy = CurrDeclContext->getSelfTypeInContext();
    auto *NTD = CurrDeclContext->getSelfNominalTypeDecl();
    if (CurrTy && !CurrTy->is<ErrorType>()) {
      // Look for overridable static members too.
      Type Meta = MetatypeType::get(CurrTy);
      lookupVisibleMemberDecls(*this, Meta, CurrDeclContext,
                               /*includeInstanceMembers=*/true,
                               /*includeDerivedRequirements*/true,
                               /*includeProtocolExtensionMembers*/false);
      addDesignatedInitializers(NTD);
      addAssociatedTypes(NTD);
    }

    if (NTD && NTD->getAttrs().hasAttribute<ResultBuilderAttr>()) {
      addResultBuilderBuildCompletions(NTD);
    }
  }
};
} // end anonymous namespace

static void addSelectorModifierKeywords(CodeCompletionResultSink &sink) {
  auto addKeyword = [&](StringRef Name, CodeCompletionKeywordKind Kind) {
    CodeCompletionResultBuilder Builder(
                                  sink,
                                  CodeCompletionResult::ResultKind::Keyword,
                                  SemanticContextKind::None, {});
    Builder.setKeywordKind(Kind);
    Builder.addTextChunk(Name);
    Builder.addCallParameterColon();
    Builder.addSimpleTypedParameter("@objc property", /*IsVarArg=*/false);
  };

  addKeyword("getter", CodeCompletionKeywordKind::None);
  addKeyword("setter", CodeCompletionKeywordKind::None);
}

void CodeCompletionCallbacksImpl::completeDotExpr(CodeCompletionExpr *E,
                                                  SourceLoc DotLoc) {
  assert(P.Tok.is(tok::code_complete));

  // Don't produce any results in an enum element.
  if (InEnumElementRawValue)
    return;

  Kind = CompletionKind::DotExpr;
  if (ParseExprSelectorContext != ObjCSelectorContext::None) {
    PreferFunctionReferencesToCalls = true;
    CompleteExprSelectorContext = ParseExprSelectorContext;
  }

  ParsedExpr = E->getBase();
  this->DotLoc = DotLoc;
  CurDeclContext = P.CurDeclContext;
  CodeCompleteTokenExpr = E;
}

void CodeCompletionCallbacksImpl::completeStmtOrExpr(CodeCompletionExpr *E) {
  assert(P.Tok.is(tok::code_complete));
  Kind = CompletionKind::StmtOrExpr;
  CurDeclContext = P.CurDeclContext;
  CodeCompleteTokenExpr = E;
}

void CodeCompletionCallbacksImpl::completePostfixExprBeginning(CodeCompletionExpr *E) {
  assert(P.Tok.is(tok::code_complete));

  // Don't produce any results in an enum element.
  if (InEnumElementRawValue)
    return;

  Kind = CompletionKind::PostfixExprBeginning;
  if (ParseExprSelectorContext != ObjCSelectorContext::None) {
    PreferFunctionReferencesToCalls = true;
    CompleteExprSelectorContext = ParseExprSelectorContext;
    if (CompleteExprSelectorContext == ObjCSelectorContext::MethodSelector) {
      addSelectorModifierKeywords(CompletionContext.getResultSink());
    }
  }


  CurDeclContext = P.CurDeclContext;
  CodeCompleteTokenExpr = E;
}

void CodeCompletionCallbacksImpl::completeForEachSequenceBeginning(
    CodeCompletionExpr *E) {
  assert(P.Tok.is(tok::code_complete));
  Kind = CompletionKind::ForEachSequence;
  CurDeclContext = P.CurDeclContext;
  CodeCompleteTokenExpr = E;
}

void CodeCompletionCallbacksImpl::completePostfixExpr(Expr *E, bool hasSpace) {
  assert(P.Tok.is(tok::code_complete));

  // Don't produce any results in an enum element.
  if (InEnumElementRawValue)
    return;

  HasSpace = hasSpace;
  Kind = CompletionKind::PostfixExpr;
  if (ParseExprSelectorContext != ObjCSelectorContext::None) {
    PreferFunctionReferencesToCalls = true;
    CompleteExprSelectorContext = ParseExprSelectorContext;
  }

  ParsedExpr = E;
  CurDeclContext = P.CurDeclContext;
}

void CodeCompletionCallbacksImpl::completePostfixExprParen(Expr *E,
                                                           Expr *CodeCompletionE) {
  assert(P.Tok.is(tok::code_complete));

  // Don't produce any results in an enum element.
  if (InEnumElementRawValue)
    return;

  Kind = CompletionKind::PostfixExprParen;
  ParsedExpr = E;
  CurDeclContext = P.CurDeclContext;
  CodeCompleteTokenExpr = static_cast<CodeCompletionExpr*>(CodeCompletionE);

  ShouldCompleteCallPatternAfterParen = true;
  if (Context.LangOpts.CodeCompleteCallPatternHeuristics) {
    // Lookahead one token to decide what kind of call completions to provide.
    // When it appears that there is already code for the call present, just
    // complete values and/or argument labels.  Otherwise give the entire call
    // pattern.
    Token next = P.peekToken();
    if (!next.isAtStartOfLine() && !next.is(tok::eof) && !next.is(tok::r_paren)) {
      ShouldCompleteCallPatternAfterParen = false;
    }
  }
}

void CodeCompletionCallbacksImpl::completeExprKeyPath(KeyPathExpr *KPE,
                                                      SourceLoc DotLoc) {
  Kind = (!KPE || KPE->isObjC()) ? CompletionKind::KeyPathExprObjC
                                 : CompletionKind::KeyPathExprSwift;
  ParsedExpr = KPE;
  this->DotLoc = DotLoc;
  CurDeclContext = P.CurDeclContext;
}

void CodeCompletionCallbacksImpl::completePoundAvailablePlatform() {
  Kind = CompletionKind::PoundAvailablePlatform;
  CurDeclContext = P.CurDeclContext;
}

void CodeCompletionCallbacksImpl::completeTypeDeclResultBeginning() {
  Kind = CompletionKind::TypeDeclResultBeginning;
  CurDeclContext = P.CurDeclContext;
}

void CodeCompletionCallbacksImpl::completeTypeSimpleBeginning() {
  Kind = CompletionKind::TypeSimpleBeginning;
  CurDeclContext = P.CurDeclContext;
}

void CodeCompletionCallbacksImpl::completeDeclAttrParam(DeclAttrKind DK,
                                                        int Index) {
  Kind = CompletionKind::AttributeDeclParen;
  AttrKind = DK;
  AttrParamIndex = Index;
  CurDeclContext = P.CurDeclContext;
}

void CodeCompletionCallbacksImpl::completeEffectsSpecifier(bool hasAsync,
                                                           bool hasThrows) {
  Kind = CompletionKind::EffectsSpecifier;
  CurDeclContext = P.CurDeclContext;
  ParsedKeywords.clear();
  if (hasAsync)
    ParsedKeywords.emplace_back("async");
  if (hasThrows)
    ParsedKeywords.emplace_back("throws");
}

void CodeCompletionCallbacksImpl::completeDeclAttrBeginning(
    bool Sil, bool isIndependent) {
  Kind = CompletionKind::AttributeBegin;
  IsInSil = Sil;
  CurDeclContext = P.CurDeclContext;
  AttTargetIsIndependent = isIndependent;
}

void CodeCompletionCallbacksImpl::completeInPrecedenceGroup(SyntaxKind SK) {
  assert(P.Tok.is(tok::code_complete));

  SyntxKind = SK;
  Kind = CompletionKind::PrecedenceGroup;
  CurDeclContext = P.CurDeclContext;
}

void CodeCompletionCallbacksImpl::completeTypeIdentifierWithDot(
    IdentTypeRepr *ITR) {
  if (!ITR) {
    completeTypeSimpleBeginning();
    return;
  }
  Kind = CompletionKind::TypeIdentifierWithDot;
  ParsedTypeLoc = TypeLoc(ITR);
  CurDeclContext = P.CurDeclContext;
}

void CodeCompletionCallbacksImpl::completeTypeIdentifierWithoutDot(
    IdentTypeRepr *ITR) {
  assert(ITR);
  Kind = CompletionKind::TypeIdentifierWithoutDot;
  ParsedTypeLoc = TypeLoc(ITR);
  CurDeclContext = P.CurDeclContext;
}

void CodeCompletionCallbacksImpl::completeCaseStmtKeyword() {
  Kind = CompletionKind::CaseStmtKeyword;
  CurDeclContext = P.CurDeclContext;
}

void CodeCompletionCallbacksImpl::completeCaseStmtBeginning(CodeCompletionExpr *E) {
  assert(!InEnumElementRawValue);

  Kind = CompletionKind::CaseStmtBeginning;
  CurDeclContext = P.CurDeclContext;
  CodeCompleteTokenExpr = E;
}

void CodeCompletionCallbacksImpl::completeImportDecl(
    ImportPath::Builder &Path) {
  Kind = CompletionKind::Import;
  CurDeclContext = P.CurDeclContext;
  DotLoc = Path.empty() ? SourceLoc() : Path.back().Loc;
  if (DotLoc.isInvalid())
    return;
  auto Importer = static_cast<ClangImporter *>(CurDeclContext->getASTContext().
                                               getClangModuleLoader());
  std::vector<std::string> SubNames;
  Importer->collectSubModuleNames(Path.get().getModulePath(false), SubNames);
  ASTContext &Ctx = CurDeclContext->getASTContext();
  Path.push_back(Identifier());
  for (StringRef Sub : SubNames) {
    Path.back().Item = Ctx.getIdentifier(Sub);
    SubModuleNameVisibilityPairs.push_back(
      std::make_pair(Sub.str(),
                     Ctx.getLoadedModule(Path.get().getModulePath(false))));
  }
  Path.pop_back();
}

void CodeCompletionCallbacksImpl::completeUnresolvedMember(CodeCompletionExpr *E,
    SourceLoc DotLoc) {
  Kind = CompletionKind::UnresolvedMember;
  CurDeclContext = P.CurDeclContext;
  CodeCompleteTokenExpr = E;
  this->DotLoc = DotLoc;
}

void CodeCompletionCallbacksImpl::completeCallArg(CodeCompletionExpr *E,
                                                  bool isFirst) {
  CurDeclContext = P.CurDeclContext;
  CodeCompleteTokenExpr = E;
  Kind = CompletionKind::CallArg;

  ShouldCompleteCallPatternAfterParen = false;
  if (isFirst) {
    ShouldCompleteCallPatternAfterParen = true;
    if (Context.LangOpts.CodeCompleteCallPatternHeuristics) {
      // Lookahead one token to decide what kind of call completions to provide.
      // When it appears that there is already code for the call present, just
      // complete values and/or argument labels.  Otherwise give the entire call
      // pattern.
      Token next = P.peekToken();
      if (!next.isAtStartOfLine() && !next.is(tok::eof) && !next.is(tok::r_paren)) {
        ShouldCompleteCallPatternAfterParen = false;
      }
    }
  }
}

void CodeCompletionCallbacksImpl::completeLabeledTrailingClosure(
    CodeCompletionExpr *E, bool isAtStartOfLine) {
  CurDeclContext = P.CurDeclContext;
  CodeCompleteTokenExpr = E;
  Kind = CompletionKind::LabeledTrailingClosure;
  IsAtStartOfLine = isAtStartOfLine;
}

void CodeCompletionCallbacksImpl::completeReturnStmt(CodeCompletionExpr *E) {
  CurDeclContext = P.CurDeclContext;
  CodeCompleteTokenExpr = E;
  Kind = CompletionKind::ReturnStmtExpr;
}

void CodeCompletionCallbacksImpl::completeYieldStmt(CodeCompletionExpr *E,
                                                    Optional<unsigned> index) {
  CurDeclContext = P.CurDeclContext;
  CodeCompleteTokenExpr = E;
  // TODO: use a different completion kind when completing without an index
  // in a multiple-value context.
  Kind = CompletionKind::YieldStmtExpr;
}

void CodeCompletionCallbacksImpl::completeAfterPoundExpr(
    CodeCompletionExpr *E, Optional<StmtKind> ParentKind) {
  CurDeclContext = P.CurDeclContext;
  CodeCompleteTokenExpr = E;
  Kind = CompletionKind::AfterPoundExpr;
  ParentStmtKind = ParentKind;
}

void CodeCompletionCallbacksImpl::completeAfterPoundDirective() {
  CurDeclContext = P.CurDeclContext;
  Kind = CompletionKind::AfterPoundDirective;
}

void CodeCompletionCallbacksImpl::completePlatformCondition() {
  CurDeclContext = P.CurDeclContext;
  Kind = CompletionKind::PlatformConditon;
}

void CodeCompletionCallbacksImpl::completeAfterIfStmt(bool hasElse) {
  CurDeclContext = P.CurDeclContext;
  if (hasElse) {
    Kind = CompletionKind::AfterIfStmtElse;
  } else {
    Kind = CompletionKind::StmtOrExpr;
  }
}

void CodeCompletionCallbacksImpl::completeGenericRequirement() {
  CurDeclContext = P.CurDeclContext;
  Kind = CompletionKind::GenericRequirement;
}

void CodeCompletionCallbacksImpl::completeNominalMemberBeginning(
    SmallVectorImpl<StringRef> &Keywords, SourceLoc introducerLoc) {
  assert(!InEnumElementRawValue);
  this->introducerLoc = introducerLoc;
  ParsedKeywords.clear();
  ParsedKeywords.append(Keywords.begin(), Keywords.end());
  Kind = CompletionKind::NominalMemberBeginning;
  CurDeclContext = P.CurDeclContext;
}

void CodeCompletionCallbacksImpl::completeAccessorBeginning(
    CodeCompletionExpr *E) {
  Kind = CompletionKind::AccessorBeginning;
  CurDeclContext = P.CurDeclContext;
  CodeCompleteTokenExpr = E;
}

void CodeCompletionCallbacksImpl::completeStmtLabel(StmtKind ParentKind) {
  CurDeclContext = P.CurDeclContext;
  Kind = CompletionKind::StmtLabel;
  ParentStmtKind = ParentKind;
}

static bool isDynamicLookup(Type T) {
  return T->getRValueType()->isAnyObject();
}

static bool isClangSubModule(ModuleDecl *TheModule) {
  if (auto ClangMod = TheModule->findUnderlyingClangModule())
    return ClangMod->isSubModule();
  return false;
}

static void
addKeyword(CodeCompletionResultSink &Sink, StringRef Name,
           CodeCompletionKeywordKind Kind, StringRef TypeAnnotation = "",
           CodeCompletionResult::ExpectedTypeRelation TypeRelation =
               CodeCompletionResult::ExpectedTypeRelation::NotApplicable) {
  CodeCompletionResultBuilder Builder(Sink,
                                      CodeCompletionResult::ResultKind::Keyword,
                                      SemanticContextKind::None, {});
  Builder.setKeywordKind(Kind);
  Builder.addKeyword(Name);
  if (!TypeAnnotation.empty())
    Builder.addTypeAnnotation(TypeAnnotation);
  Builder.setExpectedTypeRelation(TypeRelation);
}

static void addDeclKeywords(CodeCompletionResultSink &Sink,
                            bool IsConcurrencyEnabled) {
  auto AddDeclKeyword = [&](StringRef Name, CodeCompletionKeywordKind Kind,
                        Optional<DeclAttrKind> DAK) {
    if (Name == "let" || Name == "var") {
      // Treat keywords that could be the start of a pattern specially.
      return;
    }

    // FIXME: This should use canUseAttributeOnDecl.

    // Remove user inaccessible keywords.
    if (DAK.hasValue() && DeclAttribute::isUserInaccessible(*DAK)) return;

    // Remove keywords only available when concurrency is enabled.
    if (DAK.hasValue() && !IsConcurrencyEnabled &&
        DeclAttribute::isConcurrencyOnly(*DAK))
      return;

    addKeyword(Sink, Name, Kind);
  };

#define DECL_KEYWORD(kw) AddDeclKeyword(#kw, CodeCompletionKeywordKind::kw_##kw, None);
#include "swift/Syntax/TokenKinds.def"

  // Context-sensitive keywords.
  auto AddCSKeyword = [&](StringRef Name, DeclAttrKind Kind) {
    AddDeclKeyword(Name, CodeCompletionKeywordKind::None, Kind);
  };

#define CONTEXTUAL_CASE(KW, CLASS) AddCSKeyword(#KW, DAK_##CLASS);
#define CONTEXTUAL_DECL_ATTR(KW, CLASS, ...) CONTEXTUAL_CASE(KW, CLASS)
#define CONTEXTUAL_DECL_ATTR_ALIAS(KW, CLASS) CONTEXTUAL_CASE(KW, CLASS)
#define CONTEXTUAL_SIMPLE_DECL_ATTR(KW, CLASS, ...) CONTEXTUAL_CASE(KW, CLASS)
#include <swift/AST/Attr.def>
#undef CONTEXTUAL_CASE

}

static void addStmtKeywords(CodeCompletionResultSink &Sink, bool MaybeFuncBody) {
  auto AddStmtKeyword = [&](StringRef Name, CodeCompletionKeywordKind Kind) {
    if (!MaybeFuncBody && Kind == CodeCompletionKeywordKind::kw_return)
      return;
    addKeyword(Sink, Name, Kind);
  };
#define STMT_KEYWORD(kw) AddStmtKeyword(#kw, CodeCompletionKeywordKind::kw_##kw);
#include "swift/Syntax/TokenKinds.def"
}

static void addCaseStmtKeywords(CodeCompletionResultSink &Sink) {
  addKeyword(Sink, "case", CodeCompletionKeywordKind::kw_case);
  addKeyword(Sink, "default", CodeCompletionKeywordKind::kw_default);
}

static void addLetVarKeywords(CodeCompletionResultSink &Sink) {
  addKeyword(Sink, "let", CodeCompletionKeywordKind::kw_let);
  addKeyword(Sink, "var", CodeCompletionKeywordKind::kw_var);
}

static void addAccessorKeywords(CodeCompletionResultSink &Sink) {
  addKeyword(Sink, "get", CodeCompletionKeywordKind::None);
  addKeyword(Sink, "set", CodeCompletionKeywordKind::None);
}

static void addObserverKeywords(CodeCompletionResultSink &Sink) {
  addKeyword(Sink, "willSet", CodeCompletionKeywordKind::None);
  addKeyword(Sink, "didSet", CodeCompletionKeywordKind::None);
}

static void addExprKeywords(CodeCompletionResultSink &Sink,
                            bool IsConcurrencyEnabled) {
  // Expr keywords.
  addKeyword(Sink, "try", CodeCompletionKeywordKind::kw_try);
  addKeyword(Sink, "try!", CodeCompletionKeywordKind::kw_try);
  addKeyword(Sink, "try?", CodeCompletionKeywordKind::kw_try);
  if (IsConcurrencyEnabled) {
    addKeyword(Sink, "await", CodeCompletionKeywordKind::None);
  }
}

static void addOpaqueTypeKeyword(CodeCompletionResultSink &Sink) {
  addKeyword(Sink, "some", CodeCompletionKeywordKind::None, "some");
}

static void addAnyTypeKeyword(CodeCompletionResultSink &Sink, Type T) {
  CodeCompletionResultBuilder Builder(Sink,
                                      CodeCompletionResult::ResultKind::Keyword,
                                      SemanticContextKind::None, {});
  Builder.setKeywordKind(CodeCompletionKeywordKind::None);
  Builder.addKeyword("Any");
  Builder.addTypeAnnotation(T, PrintOptions());
}

void CodeCompletionCallbacksImpl::addKeywords(CodeCompletionResultSink &Sink,
                                              bool MaybeFuncBody) {
  switch (Kind) {
  case CompletionKind::None:
  case CompletionKind::DotExpr:
  case CompletionKind::AttributeDeclParen:
  case CompletionKind::AttributeBegin:
  case CompletionKind::PoundAvailablePlatform:
  case CompletionKind::Import:
  case CompletionKind::UnresolvedMember:
  case CompletionKind::CallArg:
  case CompletionKind::LabeledTrailingClosure:
  case CompletionKind::AfterPoundExpr:
  case CompletionKind::AfterPoundDirective:
  case CompletionKind::PlatformConditon:
  case CompletionKind::GenericRequirement:
  case CompletionKind::KeyPathExprObjC:
  case CompletionKind::KeyPathExprSwift:
  case CompletionKind::PrecedenceGroup:
  case CompletionKind::StmtLabel:
    break;

  case CompletionKind::EffectsSpecifier: {
    if (!llvm::is_contained(ParsedKeywords, "async") &&
        Context.LangOpts.EnableExperimentalConcurrency)
      addKeyword(Sink, "async", CodeCompletionKeywordKind::None);
    if (!llvm::is_contained(ParsedKeywords, "throws"))
      addKeyword(Sink, "throws", CodeCompletionKeywordKind::kw_throws);
    break;
  }

  case CompletionKind::AccessorBeginning: {
    // TODO: Omit already declared or mutally exclusive accessors.
    //       E.g. If 'get' is already declared, emit 'set' only.
    addAccessorKeywords(Sink);

    // Only 'var' for non-protocol context can have 'willSet' and 'didSet'.
    assert(ParsedDecl);
    VarDecl *var = dyn_cast<VarDecl>(ParsedDecl);
    if (auto accessor = dyn_cast<AccessorDecl>(ParsedDecl))
      var = dyn_cast<VarDecl>(accessor->getStorage());
    if (var && !var->getDeclContext()->getSelfProtocolDecl())
      addObserverKeywords(Sink);

    if (!isa<AccessorDecl>(ParsedDecl))
      break;

    MaybeFuncBody = true;
    LLVM_FALLTHROUGH;
  }
  case CompletionKind::StmtOrExpr:
    addDeclKeywords(Sink, Context.LangOpts.EnableExperimentalConcurrency);
    addStmtKeywords(Sink, MaybeFuncBody);
    LLVM_FALLTHROUGH;
  case CompletionKind::ReturnStmtExpr:
  case CompletionKind::YieldStmtExpr:
  case CompletionKind::PostfixExprBeginning:
  case CompletionKind::ForEachSequence:
    addSuperKeyword(Sink);
    addLetVarKeywords(Sink);
    addExprKeywords(Sink, Context.LangOpts.EnableExperimentalConcurrency);
    addAnyTypeKeyword(Sink, CurDeclContext->getASTContext().TheAnyType);
    break;

  case CompletionKind::CaseStmtKeyword:
    addCaseStmtKeywords(Sink);
    break;

  case CompletionKind::PostfixExpr:
  case CompletionKind::PostfixExprParen:
  case CompletionKind::CaseStmtBeginning:
  case CompletionKind::TypeIdentifierWithDot:
  case CompletionKind::TypeIdentifierWithoutDot:
    break;

  case CompletionKind::TypeDeclResultBeginning: {
    auto DC = CurDeclContext;
    if (ParsedDecl && ParsedDecl == CurDeclContext->getAsDecl())
      DC = ParsedDecl->getDeclContext();
    if (!isa<ProtocolDecl>(DC))
      if (DC->isTypeContext() || (ParsedDecl && isa<FuncDecl>(ParsedDecl)))
        addOpaqueTypeKeyword(Sink);

    LLVM_FALLTHROUGH;
  }
  case CompletionKind::TypeSimpleBeginning:
    addAnyTypeKeyword(Sink, CurDeclContext->getASTContext().TheAnyType);
    break;

  case CompletionKind::NominalMemberBeginning: {
    bool HasDeclIntroducer = llvm::find_if(ParsedKeywords,
                                           [this](const StringRef kw) {
      return llvm::StringSwitch<bool>(kw)
        .Case("associatedtype", true)
        .Case("class", !CurDeclContext || !isa<ClassDecl>(CurDeclContext))
        .Case("deinit", true)
        .Case("enum", true)
        .Case("extension", true)
        .Case("func", true)
        .Case("import", true)
        .Case("init", true)
        .Case("let", true)
        .Case("operator", true)
        .Case("precedencegroup", true)
        .Case("protocol", true)
        .Case("struct", true)
        .Case("subscript", true)
        .Case("typealias", true)
        .Case("var", true)
        .Default(false);
    }) != ParsedKeywords.end();
    if (!HasDeclIntroducer) {
      addDeclKeywords(Sink, Context.LangOpts.EnableExperimentalConcurrency);
      addLetVarKeywords(Sink);
    }
    break;
  }

  case CompletionKind::AfterIfStmtElse:
    addKeyword(Sink, "if", CodeCompletionKeywordKind::kw_if);
    break;
  }
}

static void addPoundDirectives(CodeCompletionResultSink &Sink) {
  auto addWithName =
      [&](StringRef name, CodeCompletionKeywordKind K,
          llvm::function_ref<void(CodeCompletionResultBuilder &)> consumer =
              nullptr) {
        CodeCompletionResultBuilder Builder(Sink, CodeCompletionResult::Keyword,
                                            SemanticContextKind::None, {});
        Builder.addBaseName(name);
        Builder.setKeywordKind(K);
        if (consumer)
          consumer(Builder);
      };

  addWithName("sourceLocation", CodeCompletionKeywordKind::pound_sourceLocation,
              [&] (CodeCompletionResultBuilder &Builder) {
    Builder.addLeftParen();
    Builder.addTextChunk("file");
    Builder.addCallParameterColon();
    Builder.addSimpleTypedParameter("String");
    Builder.addComma();
    Builder.addTextChunk("line");
    Builder.addCallParameterColon();
    Builder.addSimpleTypedParameter("Int");
    Builder.addRightParen();
  });
  addWithName("warning", CodeCompletionKeywordKind::pound_warning,
              [&] (CodeCompletionResultBuilder &Builder) {
    Builder.addLeftParen();
    Builder.addTextChunk("\"");
    Builder.addSimpleNamedParameter("message");
    Builder.addTextChunk("\"");
    Builder.addRightParen();
  });
  addWithName("error", CodeCompletionKeywordKind::pound_error,
              [&] (CodeCompletionResultBuilder &Builder) {
    Builder.addLeftParen();
    Builder.addTextChunk("\"");
    Builder.addSimpleNamedParameter("message");
    Builder.addTextChunk("\"");
    Builder.addRightParen();
  });

  addWithName("if ", CodeCompletionKeywordKind::pound_if,
              [&] (CodeCompletionResultBuilder &Builder) {
    Builder.addSimpleNamedParameter("condition");
  });

  // FIXME: These directives are only valid in conditional completion block.
  addWithName("elseif ", CodeCompletionKeywordKind::pound_elseif,
              [&] (CodeCompletionResultBuilder &Builder) {
    Builder.addSimpleNamedParameter("condition");
  });
  addWithName("else", CodeCompletionKeywordKind::pound_else);
  addWithName("endif", CodeCompletionKeywordKind::pound_endif);
}

/// Add platform conditions used in '#if' and '#elseif' directives.
static void addPlatformConditions(CodeCompletionResultSink &Sink) {
  auto addWithName =
      [&](StringRef Name,
          llvm::function_ref<void(CodeCompletionResultBuilder & Builder)>
              consumer) {
        CodeCompletionResultBuilder Builder(
            Sink, CodeCompletionResult::ResultKind::Pattern,
            SemanticContextKind::ExpressionSpecific, {});
        Builder.addBaseName(Name);
        Builder.addLeftParen();
        consumer(Builder);
        Builder.addRightParen();
      };
  addWithName("os", [](CodeCompletionResultBuilder &Builder) {
    Builder.addSimpleNamedParameter("name");
  });
  addWithName("arch", [](CodeCompletionResultBuilder &Builder) {
    Builder.addSimpleNamedParameter("name");
  });
  addWithName("canImport", [](CodeCompletionResultBuilder &Builder) {
    Builder.addSimpleNamedParameter("module");
  });
  addWithName("targetEnvironment", [](CodeCompletionResultBuilder &Builder) {
    Builder.addTextChunk("simulator");
  });
  addWithName("swift", [](CodeCompletionResultBuilder &Builder) {
    Builder.addTextChunk(">=");
    Builder.addSimpleNamedParameter("version");
  });
  addWithName("swift", [](CodeCompletionResultBuilder &Builder) {
    Builder.addTextChunk("<");
    Builder.addSimpleNamedParameter("version");
  });
  addWithName("compiler", [](CodeCompletionResultBuilder &Builder) {
    Builder.addTextChunk(">=");
    Builder.addSimpleNamedParameter("version");
  });
  addWithName("compiler", [](CodeCompletionResultBuilder &Builder) {
    Builder.addTextChunk("<");
    Builder.addSimpleNamedParameter("version");
  });

  addKeyword(Sink, "true", CodeCompletionKeywordKind::kw_true, "Bool");
  addKeyword(Sink, "false", CodeCompletionKeywordKind::kw_false, "Bool");
}

/// Add flags specified by '-D' to completion results.
static void addConditionalCompilationFlags(ASTContext &Ctx,
                                           CodeCompletionResultSink &Sink) {
  for (auto Flag : Ctx.LangOpts.getCustomConditionalCompilationFlags()) {
    // TODO: Should we filter out some flags?
    CodeCompletionResultBuilder Builder(
        Sink, CodeCompletionResult::ResultKind::Keyword,
        SemanticContextKind::ExpressionSpecific, {});
    Builder.addTextChunk(Flag);
  }
}

static void deliverCompletionResults(CodeCompletionContext &CompletionContext,
                                     CompletionLookup &Lookup,
                                     SourceFile &SF,
                                     CodeCompletionConsumer &Consumer) {
  llvm::SmallPtrSet<Identifier, 8> seenModuleNames;
  std::vector<RequestedCachedModule> RequestedModules;

  for (auto &Request: Lookup.RequestedCachedResults) {
    llvm::DenseSet<CodeCompletionCache::Key> ImportsSeen;
    auto handleImport = [&](ImportedModule Import) {
      ModuleDecl *TheModule = Import.importedModule;
      ImportPath::Access Path = Import.accessPath;
      if (TheModule->getFiles().empty())
        return;

      // Clang submodules are ignored and there's no lookup cost involved,
      // so just ignore them and don't put the empty results in the cache
      // because putting a lot of objects in the cache will push out
      // other lookups.
      if (isClangSubModule(TheModule))
        return;

      std::vector<std::string> AccessPath;
      for (auto Piece : Path) {
        AccessPath.push_back(std::string(Piece.Item));
      }

      StringRef ModuleFilename = TheModule->getModuleFilename();
      // ModuleFilename can be empty if something strange happened during
      // module loading, for example, the module file is corrupted.
      if (!ModuleFilename.empty()) {
        auto &Ctx = TheModule->getASTContext();
        CodeCompletionCache::Key K{
            ModuleFilename.str(),
            std::string(TheModule->getName()),
            AccessPath,
            Request.NeedLeadingDot,
            SF.hasTestableOrPrivateImport(
                AccessLevel::Internal, TheModule,
                SourceFile::ImportQueryKind::TestableOnly),
            SF.hasTestableOrPrivateImport(
                AccessLevel::Internal, TheModule,
                SourceFile::ImportQueryKind::PrivateOnly),
            Ctx.LangOpts.CodeCompleteInitsInPostfixExpr,
            CompletionContext.getAnnotateResult(),
        };

        using PairType = llvm::DenseSet<swift::ide::CodeCompletionCache::Key,
            llvm::DenseMapInfo<CodeCompletionCache::Key>>::iterator;
        std::pair<PairType, bool> Result = ImportsSeen.insert(K);
        if (!Result.second)
          return; // already handled.
        RequestedModules.push_back({std::move(K), TheModule,
          Request.OnlyTypes, Request.OnlyPrecedenceGroups});

        if (Request.IncludeModuleQualifier &&
            seenModuleNames.insert(TheModule->getName()).second)
          Lookup.addModuleName(TheModule);
      }
    };

    if (Request.TheModule) {
      // FIXME: actually check imports.
      for (auto Import : namelookup::getAllImports(Request.TheModule)) {
        handleImport(Import);
      }
    } else {
      // Add results from current module.
      Lookup.getToplevelCompletions(Request.OnlyTypes);

      // Add the qualifying module name
      auto curModule = SF.getParentModule();
      if (Request.IncludeModuleQualifier &&
          seenModuleNames.insert(curModule->getName()).second)
        Lookup.addModuleName(curModule);

      // Add results for all imported modules.
      SmallVector<ImportedModule, 4> Imports;
      SF.getImportedModules(
          Imports, {ModuleDecl::ImportFilterKind::Exported,
                    ModuleDecl::ImportFilterKind::Default,
                    ModuleDecl::ImportFilterKind::ImplementationOnly});

      for (auto Imported : Imports) {
        for (auto Import : namelookup::getAllImports(Imported.importedModule))
          handleImport(Import);
      }
    }
  }
  Lookup.RequestedCachedResults.clear();
  CompletionContext.typeContextKind = Lookup.typeContextKind();

  // Use the current SourceFile as the DeclContext so that we can use it to
  // perform qualified lookup, and to get the correct visibility for
  // @testable imports.
  DeclContext *DCForModules = &SF;
  Consumer.handleResultsAndModules(CompletionContext, RequestedModules,
                                   DCForModules);
}

void deliverUnresolvedMemberResults(
    ArrayRef<UnresolvedMemberTypeCheckCompletionCallback::Result> Results,
    DeclContext *DC, SourceLoc DotLoc,
    ide::CodeCompletionContext &CompletionCtx,
    CodeCompletionConsumer &Consumer) {
  ASTContext &Ctx = DC->getASTContext();
  CompletionLookup Lookup(CompletionCtx.getResultSink(), Ctx, DC,
                          &CompletionCtx);

  assert(DotLoc.isValid());
  Lookup.setHaveDot(DotLoc);
  Lookup.shouldCheckForDuplicates(Results.size() > 1);

  // Get the canonical versions of the top-level types
  SmallPtrSet<CanType, 4> originalTypes;
  for (auto &Result: Results)
    originalTypes.insert(Result.ExpectedTy->getCanonicalType());

  for (auto &Result: Results) {
    Lookup.setExpectedTypes({Result.ExpectedTy},
                            Result.IsImplicitSingleExpressionReturn,
                            /*expectsNonVoid*/true);
    Lookup.setIdealExpectedType(Result.ExpectedTy);

    // For optional types, also get members of the unwrapped type if it's not
    // already equivalent to one of the top-level types. Handling it via the top
    // level type and not here ensures we give the correct type relation
    // (identical, rather than convertible).
    if (Result.ExpectedTy->getOptionalObjectType()) {
      Type Unwrapped = Result.ExpectedTy->lookThroughAllOptionalTypes();
      if (originalTypes.insert(Unwrapped->getCanonicalType()).second)
        Lookup.getUnresolvedMemberCompletions(Unwrapped);
    }
    Lookup.getUnresolvedMemberCompletions(Result.ExpectedTy);
  }
  SourceFile *SF = DC->getParentSourceFile();
  deliverCompletionResults(CompletionCtx, Lookup, *SF, Consumer);
}

void deliverDotExprResults(
    ArrayRef<DotExprTypeCheckCompletionCallback::Result> Results,
    Expr *BaseExpr, DeclContext *DC, SourceLoc DotLoc, bool IsInSelector,
    ide::CodeCompletionContext &CompletionCtx,
    CodeCompletionConsumer &Consumer) {
  ASTContext &Ctx = DC->getASTContext();
  CompletionLookup Lookup(CompletionCtx.getResultSink(), Ctx, DC,
                          &CompletionCtx);

  if (DotLoc.isValid())
    Lookup.setHaveDot(DotLoc);

  Lookup.setIsSuperRefExpr(isa<SuperRefExpr>(BaseExpr));

  if (auto *DRE = dyn_cast<DeclRefExpr>(BaseExpr))
    Lookup.setIsSelfRefExpr(DRE->getDecl()->getName() == Ctx.Id_self);

  if (isa<BindOptionalExpr>(BaseExpr) || isa<ForceValueExpr>(BaseExpr))
    Lookup.setIsUnwrappedOptional(true);

  if (IsInSelector) {
    Lookup.includeInstanceMembers();
    Lookup.setPreferFunctionReferencesToCalls();
  }

  Lookup.shouldCheckForDuplicates(Results.size() > 1);
  for (auto &Result: Results) {
    Lookup.setIsStaticMetatype(Result.BaseIsStaticMetaType);
    Lookup.getPostfixKeywordCompletions(Result.BaseTy, BaseExpr);
    Lookup.setExpectedTypes(Result.ExpectedTypes,
                            Result.IsImplicitSingleExpressionReturn,
                            Result.ExpectsNonVoid);
    if (isDynamicLookup(Result.BaseTy))
      Lookup.setIsDynamicLookup();
    Lookup.getValueExprCompletions(Result.BaseTy, Result.BaseDecl);
  }

  SourceFile *SF = DC->getParentSourceFile();
  deliverCompletionResults(CompletionCtx, Lookup, *SF, Consumer);
}

bool CodeCompletionCallbacksImpl::trySolverCompletion(bool MaybeFuncBody) {
  assert(ParsedExpr || CurDeclContext);

  SourceLoc CompletionLoc = ParsedExpr
    ? ParsedExpr->getLoc()
    : CurDeclContext->getASTContext().SourceMgr.getCodeCompletionLoc();

  switch (Kind) {
  case CompletionKind::DotExpr: {
    assert(CodeCompleteTokenExpr);
    assert(CurDeclContext);

    DotExprTypeCheckCompletionCallback Lookup(CurDeclContext,
                                              CodeCompleteTokenExpr);
    llvm::SaveAndRestore<TypeCheckCompletionCallback*>
      CompletionCollector(Context.CompletionCallback, &Lookup);
    typeCheckContextAt(CurDeclContext, CompletionLoc);

    // This (hopefully) only happens in cases where the expression isn't
    // typechecked during normal compilation either (e.g. member completion in a
    // switch case where there control expression is invalid). Having normal
    // typechecking still resolve even these cases would be beneficial for
    // tooling in general though.
    if (!Lookup.gotCallback())
      Lookup.fallbackTypeCheck();

    addKeywords(CompletionContext.getResultSink(), MaybeFuncBody);

    Expr *CheckedBase = CodeCompleteTokenExpr->getBase();
    deliverDotExprResults(Lookup.getResults(), CheckedBase, CurDeclContext,
                          DotLoc, isInsideObjCSelector(), CompletionContext,
                          Consumer);
    return true;
  }
  case CompletionKind::UnresolvedMember: {
    assert(CodeCompleteTokenExpr);
    assert(CurDeclContext);

    UnresolvedMemberTypeCheckCompletionCallback Lookup(CodeCompleteTokenExpr);
    llvm::SaveAndRestore<TypeCheckCompletionCallback*>
      CompletionCollector(Context.CompletionCallback, &Lookup);
    typeCheckContextAt(CurDeclContext, CompletionLoc);

    if (!Lookup.gotCallback())
      Lookup.fallbackTypeCheck(CurDeclContext);

    addKeywords(CompletionContext.getResultSink(), MaybeFuncBody);
    deliverUnresolvedMemberResults(Lookup.getResults(), CurDeclContext, DotLoc,
                                   CompletionContext, Consumer);
    return true;
  }
  default:
    return false;
  }
}

// Undoes the single-expression closure/function body transformation on the
// given DeclContext and its parent contexts if they have a single expression
// body that contains the code completion location.
//
// FIXME: Remove this once all expression position completions are migrated
// to work via TypeCheckCompletionCallback.
static void undoSingleExpressionReturn(DeclContext *DC) {
  auto updateBody = [](BraceStmt *BS, ASTContext &Ctx) -> bool {
    ASTNode LastElem = BS->getLastElement();
    auto *RS = dyn_cast_or_null<ReturnStmt>(LastElem.dyn_cast<Stmt*>());

    if (!RS || !RS->isImplicit())
      return false;

    BS->setLastElement(RS->getResult());
    return true;
  };

  while (ClosureExpr *CE = dyn_cast_or_null<ClosureExpr>(DC)) {
    if (CE->hasSingleExpressionBody()) {
      if (updateBody(CE->getBody(), CE->getASTContext()))
        CE->setBody(CE->getBody(), false);
    }
    DC = DC->getParent();
  }
  if (FuncDecl *FD = dyn_cast_or_null<FuncDecl>(DC)) {
    if (FD->hasSingleExpressionBody()) {
      if (updateBody(FD->getBody(), FD->getASTContext()))
        FD->setHasSingleExpressionBody(false);
    }
  }
}

void CodeCompletionCallbacksImpl::doneParsing() {
  CompletionContext.CodeCompletionKind = Kind;

  if (Kind == CompletionKind::None) {
    return;
  }

  bool MaybeFuncBody = true;
  if (CurDeclContext) {
    auto *CD = CurDeclContext->getLocalContext();
    if (!CD || CD->getContextKind() == DeclContextKind::Initializer ||
        CD->getContextKind() == DeclContextKind::TopLevelCodeDecl)
      MaybeFuncBody = false;
  }

  if (auto *DC = dyn_cast_or_null<DeclContext>(ParsedDecl)) {
    if (DC->isChildContextOf(CurDeclContext))
      CurDeclContext = DC;
  }

  if (trySolverCompletion(MaybeFuncBody))
    return;

  undoSingleExpressionReturn(CurDeclContext);
  typeCheckContextAt(
      CurDeclContext,
      ParsedExpr
          ? ParsedExpr->getLoc()
          : CurDeclContext->getASTContext().SourceMgr.getCodeCompletionLoc());

  // Add keywords even if type checking fails completely.
  addKeywords(CompletionContext.getResultSink(), MaybeFuncBody);

  Optional<Type> ExprType;
  ConcreteDeclRef ReferencedDecl = nullptr;
  if (ParsedExpr) {
    if (auto *checkedExpr = findParsedExpr(CurDeclContext,
                                           ParsedExpr->getSourceRange())) {
      ParsedExpr = checkedExpr;
    }

    if (auto typechecked = typeCheckParsedExpr()) {
      ExprType = typechecked->first;
      ReferencedDecl = typechecked->second;
      ParsedExpr->setType(*ExprType);
    }

    if (!ExprType && Kind != CompletionKind::PostfixExprParen &&
        Kind != CompletionKind::CallArg &&
        Kind != CompletionKind::KeyPathExprObjC)
      return;
  }

  if (!ParsedTypeLoc.isNull() && !typecheckParsedType())
    return;

  CompletionLookup Lookup(CompletionContext.getResultSink(), P.Context,
                          CurDeclContext, &CompletionContext);
  if (ExprType) {
    Lookup.setIsStaticMetatype(ParsedExpr->isStaticallyDerivedMetatype());
  }
  if (auto *DRE = dyn_cast_or_null<DeclRefExpr>(ParsedExpr)) {
    Lookup.setIsSelfRefExpr(DRE->getDecl()->getName() == Context.Id_self);
  } else if (ParsedExpr && isa<SuperRefExpr>(ParsedExpr)) {
    Lookup.setIsSuperRefExpr();
  }

  if (isInsideObjCSelector())
    Lookup.includeInstanceMembers();
  if (PreferFunctionReferencesToCalls)
    Lookup.setPreferFunctionReferencesToCalls();

  auto DoPostfixExprBeginning = [&] (){
    SourceLoc Loc = P.Context.SourceMgr.getCodeCompletionLoc();
    Lookup.getValueCompletionsInDeclContext(Loc);
    Lookup.getSelfTypeCompletionInDeclContext(Loc, /*isForDeclResult=*/false);
  };

  switch (Kind) {
  case CompletionKind::None:
  case CompletionKind::DotExpr:
  case CompletionKind::UnresolvedMember:
    llvm_unreachable("should be already handled");
    return;

  case CompletionKind::KeyPathExprSwift: {
    auto KPE = dyn_cast<KeyPathExpr>(ParsedExpr);
    auto BGT = (*ExprType)->getAs<BoundGenericType>();
    if (!KPE || !BGT || BGT->getGenericArgs().size() != 2)
      break;
    assert(!KPE->isObjC());

    if (DotLoc.isValid())
      Lookup.setHaveDot(DotLoc);

    bool OnRoot = !KPE->getComponents().front().isValid();
    Lookup.setIsSwiftKeyPathExpr(OnRoot);

    Type baseType = BGT->getGenericArgs()[OnRoot ? 0 : 1];
    if (OnRoot && baseType->is<UnresolvedType>()) {
      // Infer the root type of the keypath from the context type.
      ExprContextInfo ContextInfo(CurDeclContext, ParsedExpr);
      for (auto T : ContextInfo.getPossibleTypes()) {
        if (auto unwrapped = T->getOptionalObjectType())
          T = unwrapped;

        // If the context type is any of the KeyPath types, use it.
        if (T->getAnyNominal() && T->getAnyNominal()->getKeyPathTypeKind() &&
            !T->hasUnresolvedType() && T->is<BoundGenericType>()) {
          baseType = T->castTo<BoundGenericType>()->getGenericArgs()[0];
          break;
        }

        // KeyPath can be used as a function that receives its root type.
        if (T->is<AnyFunctionType>()) {
          auto *fnType = T->castTo<AnyFunctionType>();
          if (fnType->getNumParams() == 1) {
            const AnyFunctionType::Param &param = fnType->getParams()[0];
            baseType = param.getParameterType();
            break;
          }
        }
      }
    }
    if (!OnRoot && KPE->getComponents().back().getKind() ==
                       KeyPathExpr::Component::Kind::OptionalWrap) {
      // KeyPath expr with '?' (e.g. '\Ty.[0].prop?.another').
      // Although expected type is optional, we should unwrap it because it's
      // unwrapped.
      baseType = baseType->getOptionalObjectType();
    }

    Lookup.getValueExprCompletions(baseType);
    break;
  }

  case CompletionKind::StmtOrExpr:
  case CompletionKind::ForEachSequence:
  case CompletionKind::PostfixExprBeginning: {
    ExprContextInfo ContextInfo(CurDeclContext, CodeCompleteTokenExpr);
    Lookup.setExpectedTypes(ContextInfo.getPossibleTypes(),
                            ContextInfo.isImplicitSingleExpressionReturn());
    DoPostfixExprBeginning();
    break;
  }

  case CompletionKind::PostfixExpr: {
    Lookup.setHaveLeadingSpace(HasSpace);
    if (isDynamicLookup(*ExprType))
      Lookup.setIsDynamicLookup();
    Lookup.getValueExprCompletions(*ExprType, ReferencedDecl.getDecl());
    Lookup.getOperatorCompletions(ParsedExpr, leadingSequenceExprs);
    Lookup.getPostfixKeywordCompletions(*ExprType, ParsedExpr);
    break;
  }

  case CompletionKind::PostfixExprParen: {
    Lookup.setHaveLParen(true);

    ExprContextInfo ContextInfo(CurDeclContext, CodeCompleteTokenExpr);

    if (ShouldCompleteCallPatternAfterParen) {
      ExprContextInfo ParentContextInfo(CurDeclContext, ParsedExpr);
      Lookup.setExpectedTypes(
          ParentContextInfo.getPossibleTypes(),
          ParentContextInfo.isImplicitSingleExpressionReturn());
      if (!ContextInfo.getPossibleCallees().empty()) {
        for (auto &typeAndDecl : ContextInfo.getPossibleCallees())
          Lookup.tryFunctionCallCompletions(typeAndDecl.Type, typeAndDecl.Decl,
                                            typeAndDecl.SemanticContext);
      } else if (ExprType && ((*ExprType)->is<AnyFunctionType>() ||
                              (*ExprType)->is<AnyMetatypeType>())) {
        Lookup.getValueExprCompletions(*ExprType, ReferencedDecl.getDecl());
      }
    } else {
      // Add argument labels, then fallthrough to get values.
      Lookup.addCallArgumentCompletionResults(ContextInfo.getPossibleParams());
    }

    if (!Lookup.FoundFunctionCalls ||
        (Lookup.FoundFunctionCalls &&
         Lookup.FoundFunctionsWithoutFirstKeyword)) {
      Lookup.setExpectedTypes(ContextInfo.getPossibleTypes(),
                              ContextInfo.isImplicitSingleExpressionReturn());
      Lookup.setHaveLParen(false);
      DoPostfixExprBeginning();
    }
    break;
  }

  case CompletionKind::KeyPathExprObjC: {
    if (DotLoc.isValid())
      Lookup.setHaveDot(DotLoc);
    Lookup.setIsKeyPathExpr();
    Lookup.includeInstanceMembers();

    if (ExprType) {
      if (isDynamicLookup(*ExprType))
        Lookup.setIsDynamicLookup();

      Lookup.getValueExprCompletions(*ExprType, ReferencedDecl.getDecl());
    } else {
      SourceLoc Loc = P.Context.SourceMgr.getCodeCompletionLoc();
      Lookup.getValueCompletionsInDeclContext(Loc, KeyPathFilter,
                                              /*LiteralCompletions=*/false);
    }
    break;
  }

  case CompletionKind::TypeDeclResultBeginning:
  case CompletionKind::TypeSimpleBeginning: {
    auto Loc = Context.SourceMgr.getCodeCompletionLoc();
    Lookup.getTypeCompletionsInDeclContext(Loc);
    Lookup.getSelfTypeCompletionInDeclContext(
        Loc, Kind == CompletionKind::TypeDeclResultBeginning);
    break;
  }

  case CompletionKind::TypeIdentifierWithDot: {
    Lookup.setHaveDot(SourceLoc());
    Lookup.getTypeCompletions(ParsedTypeLoc.getType());
    break;
  }

  case CompletionKind::TypeIdentifierWithoutDot: {
    Lookup.getTypeCompletions(ParsedTypeLoc.getType());
    break;
  }

  case CompletionKind::CaseStmtBeginning: {
    ExprContextInfo ContextInfo(CurDeclContext, CodeCompleteTokenExpr);
    Lookup.setExpectedTypes(ContextInfo.getPossibleTypes(),
                            ContextInfo.isImplicitSingleExpressionReturn());
    Lookup.setIdealExpectedType(CodeCompleteTokenExpr->getType());
    Lookup.getUnresolvedMemberCompletions(ContextInfo.getPossibleTypes());
    DoPostfixExprBeginning();
    break;
  }

  case CompletionKind::NominalMemberBeginning: {
    CompletionOverrideLookup OverrideLookup(CompletionContext.getResultSink(),
                                            P.Context, CurDeclContext,
                                            ParsedKeywords, introducerLoc);
    OverrideLookup.getOverrideCompletions(SourceLoc());
    break;
  }

  case CompletionKind::AccessorBeginning: {
    if (isa<AccessorDecl>(ParsedDecl)) {
      ExprContextInfo ContextInfo(CurDeclContext, CodeCompleteTokenExpr);
      Lookup.setExpectedTypes(ContextInfo.getPossibleTypes(),
                              ContextInfo.isImplicitSingleExpressionReturn());
      DoPostfixExprBeginning();
    }
    break;
  }

  case CompletionKind::AttributeBegin: {
    Lookup.getAttributeDeclCompletions(IsInSil, AttTargetDK);

    // TypeName at attribute position after '@'.
    // - VarDecl: Property Wrappers.
    // - ParamDecl/VarDecl/FuncDecl: Function Builders.
    if (!AttTargetDK || *AttTargetDK == DeclKind::Var ||
        *AttTargetDK == DeclKind::Param || *AttTargetDK == DeclKind::Func)
      Lookup.getTypeCompletionsInDeclContext(
          P.Context.SourceMgr.getCodeCompletionLoc());
    break;
  }
  case CompletionKind::AttributeDeclParen: {
    Lookup.getAttributeDeclParamCompletions(AttrKind, AttrParamIndex);
    break;
  }
  case CompletionKind::PoundAvailablePlatform: {
    Lookup.getPoundAvailablePlatformCompletions();
    break;
  }
  case CompletionKind::Import: {
    if (DotLoc.isValid())
      Lookup.addSubModuleNames(SubModuleNameVisibilityPairs);
    else
      Lookup.addImportModuleNames();
    break;
  }
  case CompletionKind::CallArg: {
    ExprContextInfo ContextInfo(CurDeclContext, CodeCompleteTokenExpr);

    bool shouldPerformGlobalCompletion = true;

    if (ShouldCompleteCallPatternAfterParen &&
        !ContextInfo.getPossibleCallees().empty()) {
      Lookup.setHaveLParen(true);
      for (auto &typeAndDecl : ContextInfo.getPossibleCallees()) {
        auto apply = ContextInfo.getAnalyzedExpr();
        if (apply && isa<SubscriptExpr>(apply)) {
          Lookup.addSubscriptCallPattern(
              typeAndDecl.Type,
              dyn_cast_or_null<SubscriptDecl>(typeAndDecl.Decl),
              typeAndDecl.SemanticContext);
        } else {
          Lookup.addFunctionCallPattern(
              typeAndDecl.Type,
              dyn_cast_or_null<AbstractFunctionDecl>(typeAndDecl.Decl),
              typeAndDecl.SemanticContext);
        }
      }
      Lookup.setHaveLParen(false);

      shouldPerformGlobalCompletion =
          !Lookup.FoundFunctionCalls ||
          (Lookup.FoundFunctionCalls &&
           Lookup.FoundFunctionsWithoutFirstKeyword);
    } else if (!ContextInfo.getPossibleParams().empty()) {
      auto params = ContextInfo.getPossibleParams();
      Lookup.addCallArgumentCompletionResults(params);

      shouldPerformGlobalCompletion = !ContextInfo.getPossibleTypes().empty();
      // Fallback to global completion if the position is out of number. It's
      // better than suggest nothing.
      shouldPerformGlobalCompletion |= llvm::all_of(
          params, [](const PossibleParamInfo &P) { return !P.Param; });
    }

    if (shouldPerformGlobalCompletion) {
      Lookup.setExpectedTypes(ContextInfo.getPossibleTypes(),
                              ContextInfo.isImplicitSingleExpressionReturn());
      DoPostfixExprBeginning();
    }
    break;
  }

  case CompletionKind::LabeledTrailingClosure: {
    ExprContextInfo ContextInfo(CurDeclContext, CodeCompleteTokenExpr);

    SmallVector<PossibleParamInfo, 2> params;
    // Only complete function type parameters
    llvm::copy_if(ContextInfo.getPossibleParams(), std::back_inserter(params),
                  [](const PossibleParamInfo &P) {
                    // nullptr indicates out of bounds.
                    if (!P.Param)
                      return true;
                    return P.Param->getPlainType()
                        ->lookThroughAllOptionalTypes()
                        ->is<AnyFunctionType>();
                  });

    bool allRequired = false;
    if (!params.empty()) {
      Lookup.addCallArgumentCompletionResults(
          params, /*isLabeledTrailingClosure=*/true);
      allRequired = llvm::all_of(
          params, [](const PossibleParamInfo &P) { return P.IsRequired; });
    }

    // If there're optional parameters, do global completion or member
    // completion depending on the completion is happening at the start of line.
    if (!allRequired) {
      if (IsAtStartOfLine) {
        //   foo() {}
        //   <HERE>

        auto &Sink = CompletionContext.getResultSink();
        if (isa<Initializer>(CurDeclContext))
          CurDeclContext = CurDeclContext->getParent();

        if (CurDeclContext->isTypeContext()) {
          // Override completion (CompletionKind::NominalMemberBeginning).
          addDeclKeywords(Sink, Context.LangOpts.EnableExperimentalConcurrency);
          addLetVarKeywords(Sink);
          SmallVector<StringRef, 0> ParsedKeywords;
          CompletionOverrideLookup OverrideLookup(Sink, Context, CurDeclContext,
                                                  ParsedKeywords, SourceLoc());
          OverrideLookup.getOverrideCompletions(SourceLoc());
        } else {
          // Global completion (CompletionKind::PostfixExprBeginning).
          addDeclKeywords(Sink, Context.LangOpts.EnableExperimentalConcurrency);
          addStmtKeywords(Sink, MaybeFuncBody);
          addSuperKeyword(Sink);
          addLetVarKeywords(Sink);
          addExprKeywords(Sink, Context.LangOpts.EnableExperimentalConcurrency);
          addAnyTypeKeyword(Sink, Context.TheAnyType);
          DoPostfixExprBeginning();
        }
      } else {
        //   foo() {} <HERE>
        // Member completion.
        Expr *analyzedExpr = ContextInfo.getAnalyzedExpr();
        if (!analyzedExpr)
          break;

        // Only if the completion token is the last token in the call.
        if (analyzedExpr->getEndLoc() != CodeCompleteTokenExpr->getLoc())
          break;

        Type resultTy = analyzedExpr->getType();
        // If the call expression doesn't have a type, fallback to:
        if (!resultTy || resultTy->is<ErrorType>()) {
          // 1) Try to type check removing CodeCompletionExpr from the call.
          Expr *removedExpr = analyzedExpr;
          removeCodeCompletionExpr(CurDeclContext->getASTContext(),
                                   removedExpr);
          ConcreteDeclRef referencedDecl;
          auto optT = getTypeOfCompletionContextExpr(
              CurDeclContext->getASTContext(), CurDeclContext,
              CompletionTypeCheckKind::Normal, removedExpr, referencedDecl);
          if (optT) {
            resultTy = *optT;
            analyzedExpr->setType(resultTy);
          }
        }
        if (!resultTy || resultTy->is<ErrorType>()) {
          // 2) Infer it from the possible callee info.
          if (!ContextInfo.getPossibleCallees().empty()) {
            auto calleeInfo = ContextInfo.getPossibleCallees()[0];
            resultTy = calleeInfo.Type->getResult();
            analyzedExpr->setType(resultTy);
          }
        }
        if (!resultTy || resultTy->is<ErrorType>()) {
          // 3) Give up providing postfix completions.
          break;
        }

        auto &SM = CurDeclContext->getASTContext().SourceMgr;
        auto leadingChar =
            SM.extractText({SM.getCodeCompletionLoc().getAdvancedLoc(-1), 1});
        Lookup.setHaveLeadingSpace(leadingChar.find_first_of(" \t\f\v") !=
                                   StringRef::npos);

        if (isDynamicLookup(resultTy))
          Lookup.setIsDynamicLookup();
        Lookup.getValueExprCompletions(resultTy, /*VD=*/nullptr);
        Lookup.getOperatorCompletions(analyzedExpr, leadingSequenceExprs);
        Lookup.getPostfixKeywordCompletions(resultTy, analyzedExpr);
      }
    }
    break;
  }

  case CompletionKind::ReturnStmtExpr : {
    SourceLoc Loc = P.Context.SourceMgr.getCodeCompletionLoc();
    SmallVector<Type, 2> possibleReturnTypes;
    collectPossibleReturnTypesFromContext(CurDeclContext, possibleReturnTypes);
    Lookup.setExpectedTypes(possibleReturnTypes,
                            /*isImplicitSingleExpressionReturn*/ false);
    Lookup.getValueCompletionsInDeclContext(Loc);
    break;
  }

  case CompletionKind::YieldStmtExpr: {
    SourceLoc Loc = P.Context.SourceMgr.getCodeCompletionLoc();
    if (auto FD = dyn_cast<AccessorDecl>(CurDeclContext)) {
      if (FD->isCoroutine()) {
        // TODO: handle multi-value yields.
        Lookup.setExpectedTypes(FD->getStorage()->getValueInterfaceType(),
                                /*isImplicitSingleExpressionReturn*/ false);
      }
    }
    Lookup.getValueCompletionsInDeclContext(Loc);
    break;
  }

  case CompletionKind::AfterPoundExpr: {
    ExprContextInfo ContextInfo(CurDeclContext, CodeCompleteTokenExpr);
    Lookup.setExpectedTypes(ContextInfo.getPossibleTypes(),
                            ContextInfo.isImplicitSingleExpressionReturn());

    Lookup.addPoundAvailable(ParentStmtKind);
    Lookup.addPoundLiteralCompletions(/*needPound=*/false);
    Lookup.addObjCPoundKeywordCompletions(/*needPound=*/false);
    break;
  }

  case CompletionKind::AfterPoundDirective: {
    addPoundDirectives(CompletionContext.getResultSink());
    // FIXME: Add pound expressions (e.g. '#selector()') if it's at statements
    // position.
    break;
  }

  case CompletionKind::PlatformConditon: {
    addPlatformConditions(CompletionContext.getResultSink());
    addConditionalCompilationFlags(CurDeclContext->getASTContext(),
                                   CompletionContext.getResultSink());
    break;
  }

  case CompletionKind::GenericRequirement:
    Lookup.getGenericRequirementCompletions(CurDeclContext);
    break;
  case CompletionKind::PrecedenceGroup:
    Lookup.getPrecedenceGroupCompletions(SyntxKind);
    break;
  case CompletionKind::StmtLabel: {
    SourceLoc Loc = P.Context.SourceMgr.getCodeCompletionLoc();
    Lookup.getStmtLabelCompletions(Loc, ParentStmtKind == StmtKind::Continue);
    break;
  }
  case CompletionKind::AfterIfStmtElse:
  case CompletionKind::CaseStmtKeyword:
  case CompletionKind::EffectsSpecifier:
    // Handled earlier by keyword completions.
    break;
  }

  deliverCompletionResults(CompletionContext, Lookup, P.SF, Consumer);
}

void PrintingCodeCompletionConsumer::handleResults(
    MutableArrayRef<CodeCompletionResult *> Results) {
  unsigned NumResults = 0;
  for (auto Result : Results) {
    if (!IncludeKeywords && Result->getKind() == CodeCompletionResult::Keyword)
      continue;
    ++NumResults;
  }
  if (NumResults == 0)
    return;

  OS << "Begin completions, " << NumResults << " items\n";
  for (auto Result : Results) {
    if (!IncludeKeywords && Result->getKind() == CodeCompletionResult::Keyword)
      continue;
    Result->printPrefix(OS);
    if (PrintAnnotatedDescription) {
      printCodeCompletionResultDescriptionAnnotated(*Result, OS, /*leadingPunctuation=*/false);
      OS << "; typename=";
      printCodeCompletionResultTypeNameAnnotated(*Result, OS);
    } else {
      Result->getCompletionString()->print(OS);
    }

    llvm::SmallString<64> Name;
    llvm::raw_svector_ostream NameOs(Name);
    Result->getCompletionString()->getName(NameOs);
    OS << "; name=" << Name;

    StringRef comment = Result->getBriefDocComment();
    if (IncludeComments && !comment.empty()) {
      OS << "; comment=" << comment;
    }

    OS << "\n";
  }
  OS << "End completions\n";
}

namespace {
class CodeCompletionCallbacksFactoryImpl
    : public CodeCompletionCallbacksFactory {
  CodeCompletionContext &CompletionContext;
  CodeCompletionConsumer &Consumer;

public:
  CodeCompletionCallbacksFactoryImpl(CodeCompletionContext &CompletionContext,
                                     CodeCompletionConsumer &Consumer)
      : CompletionContext(CompletionContext), Consumer(Consumer) {}

  CodeCompletionCallbacks *createCodeCompletionCallbacks(Parser &P) override {
    return new CodeCompletionCallbacksImpl(P, CompletionContext, Consumer);
  }
};
} // end anonymous namespace

CodeCompletionCallbacksFactory *
swift::ide::makeCodeCompletionCallbacksFactory(
    CodeCompletionContext &CompletionContext,
    CodeCompletionConsumer &Consumer) {
  return new CodeCompletionCallbacksFactoryImpl(CompletionContext, Consumer);
}

void swift::ide::lookupCodeCompletionResultsFromModule(
    CodeCompletionResultSink &targetSink, const ModuleDecl *module,
    ArrayRef<std::string> accessPath, bool needLeadingDot,
    const DeclContext *currDeclContext) {
  CompletionLookup Lookup(targetSink, module->getASTContext(), currDeclContext);
  Lookup.lookupExternalModuleDecls(module, accessPath, needLeadingDot);
}

void swift::ide::copyCodeCompletionResults(CodeCompletionResultSink &targetSink,
                                           CodeCompletionResultSink &sourceSink,
                                           bool onlyTypes,
                                           bool onlyPrecedenceGroups) {

  // We will be adding foreign results (from another sink) into TargetSink.
  // TargetSink should have an owning pointer to the allocator that keeps the
  // results alive.
  targetSink.ForeignAllocators.push_back(sourceSink.Allocator);

  if (onlyTypes) {
    std::copy_if(sourceSink.Results.begin(), sourceSink.Results.end(),
                 std::back_inserter(targetSink.Results),
                 [](CodeCompletionResult *R) -> bool {
      if (R->getKind() != CodeCompletionResult::Declaration)
        return false;
      switch(R->getAssociatedDeclKind()) {
      case CodeCompletionDeclKind::Module:
      case CodeCompletionDeclKind::Class:
      case CodeCompletionDeclKind::Struct:
      case CodeCompletionDeclKind::Enum:
      case CodeCompletionDeclKind::Protocol:
      case CodeCompletionDeclKind::TypeAlias:
      case CodeCompletionDeclKind::AssociatedType:
      case CodeCompletionDeclKind::GenericTypeParam:
        return true;
      case CodeCompletionDeclKind::PrecedenceGroup:
      case CodeCompletionDeclKind::EnumElement:
      case CodeCompletionDeclKind::Constructor:
      case CodeCompletionDeclKind::Destructor:
      case CodeCompletionDeclKind::Subscript:
      case CodeCompletionDeclKind::StaticMethod:
      case CodeCompletionDeclKind::InstanceMethod:
      case CodeCompletionDeclKind::PrefixOperatorFunction:
      case CodeCompletionDeclKind::PostfixOperatorFunction:
      case CodeCompletionDeclKind::InfixOperatorFunction:
      case CodeCompletionDeclKind::FreeFunction:
      case CodeCompletionDeclKind::StaticVar:
      case CodeCompletionDeclKind::InstanceVar:
      case CodeCompletionDeclKind::LocalVar:
      case CodeCompletionDeclKind::GlobalVar:
        return false;
      }

      llvm_unreachable("Unhandled CodeCompletionDeclKind in switch.");
    });
  } else if (onlyPrecedenceGroups) {
    std::copy_if(sourceSink.Results.begin(), sourceSink.Results.end(),
                 std::back_inserter(targetSink.Results),
                 [](CodeCompletionResult *R) -> bool {
      return R->getAssociatedDeclKind() ==
               CodeCompletionDeclKind::PrecedenceGroup;
    });
  } else {
    targetSink.Results.insert(targetSink.Results.end(),
                              sourceSink.Results.begin(),
                              sourceSink.Results.end());
  }
}

void SimpleCachingCodeCompletionConsumer::handleResultsAndModules(
    CodeCompletionContext &context,
    ArrayRef<RequestedCachedModule> requestedModules,
    DeclContext *DCForModules) {
  for (auto &R : requestedModules) {
    // FIXME(thread-safety): lock the whole AST context.  We might load a
    // module.
    llvm::Optional<CodeCompletionCache::ValueRefCntPtr> V =
        context.Cache.get(R.Key);
    if (!V.hasValue()) {
      // No cached results found. Fill the cache.
      V = context.Cache.createValue();
      (*V)->Sink.annotateResult = context.getAnnotateResult();
      lookupCodeCompletionResultsFromModule(
          (*V)->Sink, R.TheModule, R.Key.AccessPath,
          R.Key.ResultsHaveLeadingDot, DCForModules);
      context.Cache.set(R.Key, *V);
    }
    assert(V.hasValue());
    copyCodeCompletionResults(context.getResultSink(), (*V)->Sink,
                              R.OnlyTypes, R.OnlyPrecedenceGroups);
  }

  handleResults(context.takeResults());
}
