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

#include "CodeCompletionOrganizer.h"
#include "SwiftASTManager.h"
#include "SwiftLangSupport.h"
#include "SourceKit/Support/Logging.h"
#include "SourceKit/Support/UIdent.h"

#include "swift/AST/ASTPrinter.h"
#include "swift/Frontend/Frontend.h"
#include "swift/Frontend/PrintingDiagnosticConsumer.h"
#include "swift/IDE/CodeCompletionCache.h"

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

using namespace SourceKit;
using namespace swift;
using namespace ide;
using CodeCompletion::SwiftCompletionInfo;
using CodeCompletion::Completion;
using CodeCompletion::CodeCompletionView;
using CodeCompletion::CodeCompletionViewRef;
using CodeCompletion::NameToPopularityMap;

static_assert(swift::ide::CodeCompletionResult::MaxNumBytesToErase == 127,
              "custom array implementation for code completion results "
              "has this limit hardcoded");

namespace {
struct SwiftToSourceKitCompletionAdapter {
  static bool handleResult(SourceKit::CodeCompletionConsumer &consumer,
                           CodeCompletionResult *result) {
    llvm::SmallString<64> name;
    {
      llvm::raw_svector_ostream OSS(name);
      CodeCompletion::CompletionBuilder::getFilterName(
          result->getCompletionString(), OSS);
    }

    llvm::SmallString<64> description;
    {
      llvm::raw_svector_ostream OSS(description);
      // FIXME: The leading punctuation (e.g. "?." in an optional completion)
      // should really be part of a structured result description and clients
      // can
      // decide whether to display it or not. For now just include it in the
      // description only in the new code path.
      CodeCompletion::CompletionBuilder::getDescription(
          result, OSS, /*leadingPunctuation=*/false);
    }

    Completion extended(*result, name, description);
    return handleResult(consumer, &extended, /*leadingPunctuation=*/false,
                        /*legacyLiteralToKeyword=*/true);
  }

  static bool handleResult(SourceKit::CodeCompletionConsumer &consumer,
                           Completion *result, bool leadingPunctuation,
                           bool legacyLiteralToKeyword);

  static void getResultSourceText(const CodeCompletionString *CCStr,
                                  raw_ostream &OS);
  static void getResultTypeName(const CodeCompletionString *CCStr,
                                raw_ostream &OS);
  static void getResultAssociatedUSRs(ArrayRef<StringRef> AssocUSRs,
                                      raw_ostream &OS);
};

struct SwiftCodeCompletionConsumer
    : public ide::SimpleCachingCodeCompletionConsumer {
  using HandlerFunc = std::function<void(
      MutableArrayRef<CodeCompletionResult *>, SwiftCompletionInfo &)>;
  HandlerFunc handleResultsImpl;
  SwiftCompletionInfo swiftContext;

  SwiftCodeCompletionConsumer(HandlerFunc handleResultsImpl)
      : handleResultsImpl(handleResultsImpl) {}

  void setContext(swift::ASTContext *context,
                  swift::CompilerInvocation *invocation,
                  swift::ide::CodeCompletionContext *completionContext) {
    swiftContext.swiftASTContext = context;
    swiftContext.invocation = invocation;
    swiftContext.completionContext = completionContext;
  }
  void clearContext() { swiftContext = SwiftCompletionInfo(); }

  void handleResults(MutableArrayRef<CodeCompletionResult *> Results) override {
    assert(swiftContext.swiftASTContext);
    CodeCompletionContext::sortCompletionResults(Results);
    handleResultsImpl(Results, swiftContext);
  }
};
} // anonymous namespace

static bool swiftCodeCompleteImpl(SwiftLangSupport &Lang,
                                  llvm::MemoryBuffer *UnresolvedInputFile,
                                  unsigned Offset,
                                  SwiftCodeCompletionConsumer &SwiftConsumer,
                                  ArrayRef<const char *> Args,
                                  std::string &Error) {

  trace::TracedOperation TracedOp;
  if (trace::enabled()) {
    trace::SwiftInvocation SwiftArgs;
    trace::initTraceInfo(SwiftArgs,
                         UnresolvedInputFile->getBufferIdentifier(),
                         Args);
    SwiftArgs.addFile(UnresolvedInputFile->getBufferIdentifier(),
                      UnresolvedInputFile->getBuffer());

    TracedOp.start(trace::OperationKind::CodeCompletionInit, SwiftArgs,
                   { std::make_pair("Offset", std::to_string(Offset)),
                     std::make_pair("InputBufferSize",
                                    std::to_string(UnresolvedInputFile->getBufferSize()))});
  }
  
  // Resolve symlinks for the input file; we resolve them for the input files
  // in the arguments as well.
  // FIXME: We need the Swift equivalent of Clang's FileEntry.
  auto InputFile = llvm::MemoryBuffer::getMemBuffer(
      UnresolvedInputFile->getBuffer(),
      Lang.resolvePathSymlinks(UnresolvedInputFile->getBufferIdentifier()));

  CompilerInstance CI;
  // Display diagnostics to stderr.
  PrintingDiagnosticConsumer PrintDiags;
  CI.addDiagnosticConsumer(&PrintDiags);

  CompilerInvocation Invocation;
  bool Failed = Lang.getASTManager().initCompilerInvocation(
      Invocation, Args, CI.getDiags(), InputFile->getBufferIdentifier(), Error);
  if (Failed) {
    return false;
  }
  if (!Invocation.getFrontendOptions().InputsAndOutputs.hasInputs()) {
    Error = "no input filenames specified";
    return false;
  }

  auto origBuffSize = InputFile->getBufferSize();
  unsigned CodeCompletionOffset = Offset;
  if (CodeCompletionOffset > origBuffSize) {
    CodeCompletionOffset = origBuffSize;
  }

  const char *Position = InputFile->getBufferStart() + CodeCompletionOffset;
  std::unique_ptr<llvm::MemoryBuffer> NewBuffer =
      llvm::MemoryBuffer::getNewUninitMemBuffer(InputFile->getBufferSize() + 1,
                                              InputFile->getBufferIdentifier());
  char *NewBuf = const_cast<char*>(NewBuffer->getBufferStart());
  char *NewPos = std::copy(InputFile->getBufferStart(), Position, NewBuf);
  *NewPos = '\0';
  std::copy(Position, InputFile->getBufferEnd(), NewPos+1);

  Invocation.setCodeCompletionPoint(NewBuffer.get(), CodeCompletionOffset);

  auto swiftCache = Lang.getCodeCompletionCache(); // Pin the cache.
  ide::CodeCompletionContext CompletionContext(swiftCache->getCache());

  // Create a factory for code completion callbacks that will feed the
  // Consumer.
  std::unique_ptr<CodeCompletionCallbacksFactory> CompletionCallbacksFactory(
      ide::makeCodeCompletionCallbacksFactory(CompletionContext,
                                              SwiftConsumer));

  Invocation.setCodeCompletionFactory(CompletionCallbacksFactory.get());

  // FIXME: We need to be passing the buffers from the open documents.
  // It is not a huge problem in practice because Xcode auto-saves constantly.

  if (CI.setup(Invocation)) {
    // FIXME: error?
    return true;
  }

  TracedOp.finish();

  if (trace::enabled()) {
    trace::SwiftInvocation SwiftArgs;
    trace::initTraceInfo(SwiftArgs, InputFile->getBufferIdentifier(), Args);
    trace::initTraceFiles(SwiftArgs, CI);

    // Replace primary file with original content
    std::for_each(SwiftArgs.Files.begin(), SwiftArgs.Files.end(),
                  [&] (trace::StringPairs::value_type &Pair) {
                    if (Pair.first == InputFile->getBufferIdentifier()) {
                      Pair.second = InputFile->getBuffer();
                    }
                  });

    TracedOp.start(trace::OperationKind::CodeCompletion, SwiftArgs,
                   {std::make_pair("OriginalOffset", std::to_string(Offset)),
                    std::make_pair("Offset",
                      std::to_string(CodeCompletionOffset))});
  }

  CloseClangModuleFiles scopedCloseFiles(
      *CI.getASTContext().getClangModuleLoader());
  SwiftConsumer.setContext(&CI.getASTContext(), &Invocation,
                           &CompletionContext);
  CI.performSema();
  SwiftConsumer.clearContext();
  return true;
}

void SwiftLangSupport::codeComplete(llvm::MemoryBuffer *UnresolvedInputFile,
                                    unsigned Offset,
                                    SourceKit::CodeCompletionConsumer &SKConsumer,
                                    ArrayRef<const char *> Args) {
  SwiftCodeCompletionConsumer SwiftConsumer([&](
      MutableArrayRef<CodeCompletionResult *> Results,
      SwiftCompletionInfo &info) {
    bool hasExpectedType = info.completionContext->HasExpectedTypeRelation;
    CodeCompletionContext::sortCompletionResults(Results);
    // FIXME: this adhoc filtering should be configurable like it is in the
    // codeCompleteOpen path.
    for (auto *Result : Results) {
      if (Result->getKind() == CodeCompletionResult::Literal) {
        switch (Result->getLiteralKind()) {
        case CodeCompletionLiteralKind::NilLiteral:
        case CodeCompletionLiteralKind::BooleanLiteral:
          break;
        case CodeCompletionLiteralKind::ImageLiteral:
        case CodeCompletionLiteralKind::ColorLiteral:
          if (hasExpectedType &&
              Result->getExpectedTypeRelation() <
                  CodeCompletionResult::Convertible)
            continue;
          break;
        default:
          continue;
        }
      }
      if (!SwiftToSourceKitCompletionAdapter::handleResult(SKConsumer, Result))
        break;
    }
  });

  std::string Error;
  if (!swiftCodeCompleteImpl(*this, UnresolvedInputFile, Offset, SwiftConsumer,
                             Args, Error)) {
    SKConsumer.failed(Error);
  }
}

static void getResultStructure(
    CodeCompletion::SwiftResult *result, bool leadingPunctuation,
    CodeCompletionInfo::DescriptionStructure &structure,
    std::vector<CodeCompletionInfo::ParameterStructure> &parameters) {
  auto *CCStr = result->getCompletionString();
  auto FirstTextChunk = CCStr->getFirstTextChunkIndex(leadingPunctuation);

  if (!FirstTextChunk.hasValue())
    return;

  bool isOperator = result->isOperator();

  auto chunks = CCStr->getChunks();
  using ChunkKind = CodeCompletionString::Chunk::ChunkKind;

  unsigned i = *FirstTextChunk;
  unsigned textSize = 0;

  // The result name.
  for (; i < chunks.size(); ++i) {
    auto C = chunks[i];
    if (C.is(ChunkKind::TypeAnnotation) ||
        C.is(ChunkKind::CallParameterClosureType) ||
        C.is(ChunkKind::Whitespace))
      continue;

    if (C.is(ChunkKind::LeftParen) || C.is(ChunkKind::LeftBracket) ||
        C.is(ChunkKind::BraceStmtWithCursor) ||
        C.is(ChunkKind::CallParameterBegin))
      break;

    if (C.is(ChunkKind::Equal))
      isOperator = true;

    if (C.hasText())
      textSize += C.getText().size();
  }

  structure.baseName.begin = 0;
  structure.baseName.end = textSize;

  // The parameters.
  for (; i < chunks.size(); ++i) {
    auto C = chunks[i];
    if (C.is(ChunkKind::TypeAnnotation) ||
        C.is(ChunkKind::CallParameterClosureType) ||
        C.is(ChunkKind::Whitespace))
      continue;

    if (C.is(ChunkKind::BraceStmtWithCursor))
      break;

    if (C.is(ChunkKind::ThrowsKeyword) ||
        C.is(ChunkKind::RethrowsKeyword)) {
      structure.throwsRange.begin = textSize;
      structure.throwsRange.end = textSize + C.getText().size();
    }

    if (C.is(ChunkKind::CallParameterBegin)) {
      CodeCompletionInfo::ParameterStructure param;

      ++i;
      bool inName = false;
      bool inAfterColon = false;
      for (; i < chunks.size(); ++i) {
        if (chunks[i].endsPreviousNestedGroup(C.getNestingLevel()))
          break;
        if (chunks[i].is(ChunkKind::CallParameterClosureType))
          continue;
        if (isOperator && chunks[i].is(ChunkKind::CallParameterType))
          continue;

        // Parameter name
        if (chunks[i].is(ChunkKind::CallParameterName) ||
            chunks[i].is(ChunkKind::CallParameterInternalName)) {
          param.name.begin = textSize;
          param.isLocalName =
              chunks[i].is(ChunkKind::CallParameterInternalName);
          inName = true;
        }

        // Parameter type
        if (chunks[i].is(ChunkKind::CallParameterType)) {
          unsigned start = textSize;
          unsigned prev = i - 1; // if i == 0, prev = ~0u.

          // Combine & for inout into the type name.
          if (prev != ~0u && chunks[prev].is(ChunkKind::Ampersand)) {
            start -= chunks[prev].getText().size();
            prev -= 1;
          }

          // Combine the whitespace after ':' into the type name.
          if (prev != ~0u && chunks[prev].is(ChunkKind::CallParameterColon))
            start -= 1;

          param.afterColon.begin = start;
          inAfterColon = true;
          if (inName) {
            param.name.end = start;
            inName = false;
          }
        }

        if (chunks[i].hasText())
          textSize += chunks[i].getText().size();
      }

      // If we had a name with no type following it, finish it now.
      if (inName)
        param.name.end = textSize;

      // Finish the type name.
      if (inAfterColon)
        param.afterColon.end = textSize;
      if (!param.range().empty())
        parameters.push_back(std::move(param));

      if (i < chunks.size() && chunks[i].hasText())
        textSize += chunks[i].getText().size();
    }

    if (C.hasText())
      textSize += C.getText().size();
  }

  if (!parameters.empty()) {
    structure.parameterRange.begin = parameters.front().range().begin;
    structure.parameterRange.end = parameters.back().range().end;
  }
}

static UIdent KindLiteralArray("source.lang.swift.literal.array");
static UIdent KindLiteralBoolean("source.lang.swift.literal.boolean");
static UIdent KindLiteralColor("source.lang.swift.literal.color");
static UIdent KindLiteralImage("source.lang.swift.literal.image");
static UIdent KindLiteralDictionary("source.lang.swift.literal.dictionary");
static UIdent KindLiteralInteger("source.lang.swift.literal.integer");
static UIdent KindLiteralNil("source.lang.swift.literal.nil");
static UIdent KindLiteralString("source.lang.swift.literal.string");
static UIdent KindLiteralTuple("source.lang.swift.literal.tuple");

static UIdent
getUIDForCodeCompletionLiteralKind(CodeCompletionLiteralKind kind) {
  switch (kind) {
  case CodeCompletionLiteralKind::ArrayLiteral:
    return KindLiteralArray;
  case CodeCompletionLiteralKind::BooleanLiteral:
    return KindLiteralBoolean;
  case CodeCompletionLiteralKind::ColorLiteral:
    return KindLiteralColor;
  case CodeCompletionLiteralKind::ImageLiteral:
    return KindLiteralImage;
  case CodeCompletionLiteralKind::DictionaryLiteral:
    return KindLiteralDictionary;
  case CodeCompletionLiteralKind::IntegerLiteral:
    return KindLiteralInteger;
  case CodeCompletionLiteralKind::NilLiteral:
    return KindLiteralNil;
  case CodeCompletionLiteralKind::StringLiteral:
    return KindLiteralString;
  case CodeCompletionLiteralKind::Tuple:
    return KindLiteralTuple;
  }
}

static UIdent KeywordUID("source.lang.swift.keyword");
static UIdent KeywordLetUID("source.lang.swift.keyword.let");
static UIdent KeywordVarUID("source.lang.swift.keyword.var");
static UIdent KeywordIfUID("source.lang.swift.keyword.if");
static UIdent KeywordForUID("source.lang.swift.keyword.for");
static UIdent KeywordWhileUID("source.lang.swift.keyword.while");
static UIdent KeywordFuncUID("source.lang.swift.keyword.func");

bool SwiftToSourceKitCompletionAdapter::handleResult(
    SourceKit::CodeCompletionConsumer &Consumer, Completion *Result,
    bool leadingPunctuation, bool legacyLiteralToKeyword) {

  static UIdent KeywordUID("source.lang.swift.keyword");
  static UIdent PatternUID("source.lang.swift.pattern");

  CodeCompletionInfo Info;
  if (Result->hasCustomKind()) {
    Info.CustomKind = Result->getCustomKind();
  } else if (Result->getKind() == CodeCompletionResult::Keyword) {
    Info.Kind = KeywordUID;
  } else if (Result->getKind() == CodeCompletionResult::Pattern) {
    Info.Kind = PatternUID;
  } else if (Result->getKind() == CodeCompletionResult::BuiltinOperator) {
    Info.Kind = PatternUID; // FIXME: add a UID for operators
  } else if (Result->getKind() == CodeCompletionResult::Declaration) {
    Info.Kind = SwiftLangSupport::getUIDForCodeCompletionDeclKind(
        Result->getAssociatedDeclKind());
  } else if (Result->getKind() == CodeCompletionResult::Literal) {
    auto literalKind = Result->getLiteralKind();
    if (legacyLiteralToKeyword &&
        (literalKind == CodeCompletionLiteralKind::BooleanLiteral ||
         literalKind == CodeCompletionLiteralKind::NilLiteral)) {
      // Fallback to keywords as appropriate.
      Info.Kind = KeywordUID;
    } else {
      Info.Kind = getUIDForCodeCompletionLiteralKind(literalKind);
    }
  }

  if (Info.Kind.isInvalid() && !Info.CustomKind)
    return true;

  llvm::SmallString<512> SS;

  unsigned DescBegin = SS.size();
  {
    llvm::raw_svector_ostream ccOS(SS);
    CodeCompletion::CompletionBuilder::getDescription(
        Result, ccOS, leadingPunctuation);
  }
  unsigned DescEnd = SS.size();

  if (DescBegin == DescEnd) {
    LOG_FUNC_SECTION_WARN {
      llvm::SmallString<64> LogMessage;
      llvm::raw_svector_ostream LogMessageOs(LogMessage);

      LogMessageOs << "Code completion result with empty description "
                      "was ignored: \n";
      Result->print(LogMessageOs);

      *Log << LogMessage;
    }
    return true;
  }

  unsigned TextBegin = SS.size();
  {
    llvm::raw_svector_ostream ccOS(SS);
    getResultSourceText(Result->getCompletionString(), ccOS);
  }
  unsigned TextEnd = SS.size();

  unsigned TypeBegin = SS.size();
  {
    llvm::raw_svector_ostream ccOS(SS);
    getResultTypeName(Result->getCompletionString(), ccOS);
  }
  unsigned TypeEnd = SS.size();

  unsigned USRsBegin = SS.size();
  {
    llvm::raw_svector_ostream ccOS(SS);
    getResultAssociatedUSRs(Result->getAssociatedUSRs(), ccOS);
  }
  unsigned USRsEnd = SS.size();

  Info.Name = Result->getName();
  Info.Description = StringRef(SS.begin() + DescBegin, DescEnd - DescBegin);
  Info.SourceText = StringRef(SS.begin() + TextBegin, TextEnd - TextBegin);
  Info.TypeName = StringRef(SS.begin() + TypeBegin, TypeEnd - TypeBegin);
  Info.AssocUSRs = StringRef(SS.begin() + USRsBegin, USRsEnd - USRsBegin);

  static UIdent CCCtxNone("source.codecompletion.context.none");
  static UIdent CCCtxExpressionSpecific(
      "source.codecompletion.context.exprspecific");
  static UIdent CCCtxLocal("source.codecompletion.context.local");
  static UIdent CCCtxCurrentNominal("source.codecompletion.context.thisclass");
  static UIdent CCCtxSuper("source.codecompletion.context.superclass");
  static UIdent CCCtxOutsideNominal("source.codecompletion.context.otherclass");
  static UIdent CCCtxCurrentModule("source.codecompletion.context.thismodule");
  static UIdent CCCtxOtherModule("source.codecompletion.context.othermodule");

  switch (Result->getSemanticContext()) {
  case SemanticContextKind::None:
    Info.SemanticContext = CCCtxNone; break;
  case SemanticContextKind::ExpressionSpecific:
    Info.SemanticContext = CCCtxExpressionSpecific; break;
  case SemanticContextKind::Local:
    Info.SemanticContext = CCCtxLocal; break;
  case SemanticContextKind::CurrentNominal:
    Info.SemanticContext = CCCtxCurrentNominal; break;
  case SemanticContextKind::Super:
    Info.SemanticContext = CCCtxSuper; break;
  case SemanticContextKind::OutsideNominal:
    Info.SemanticContext = CCCtxOutsideNominal; break;
  case SemanticContextKind::CurrentModule:
    Info.SemanticContext = CCCtxCurrentModule; break;
  case SemanticContextKind::OtherModule:
    Info.SemanticContext = CCCtxOtherModule; break;
  }

  Info.ModuleName = Result->getModuleName();
  Info.DocBrief = Result->getBriefDocComment();
  Info.NotRecommended = Result->isNotRecommended();

  Info.NumBytesToErase = Result->getNumBytesToErase();

  // Extended result values.
  Info.ModuleImportDepth = Result->getModuleImportDepth();

  // Description structure.
  std::vector<CodeCompletionInfo::ParameterStructure> parameters;
  CodeCompletionInfo::DescriptionStructure structure;
  getResultStructure(Result, leadingPunctuation, structure, parameters);
  Info.descriptionStructure = structure;
  if (!parameters.empty())
    Info.parametersStructure = parameters;

  return Consumer.handleResult(Info);
}

static CodeCompletionLiteralKind
getCodeCompletionLiteralKindForUID(UIdent uid) {
  if (uid == KindLiteralArray) {
    return CodeCompletionLiteralKind::ArrayLiteral;
  } else if (uid == KindLiteralBoolean) {
    return CodeCompletionLiteralKind::BooleanLiteral;
  } else if (uid == KindLiteralColor) {
    return CodeCompletionLiteralKind::ColorLiteral;
  } else if (uid == KindLiteralImage) {
    return CodeCompletionLiteralKind::ImageLiteral;
  } else if (uid == KindLiteralDictionary) {
    return CodeCompletionLiteralKind::DictionaryLiteral;
  } else if (uid == KindLiteralInteger) {
    return CodeCompletionLiteralKind::IntegerLiteral;
  } else if (uid == KindLiteralNil) {
    return CodeCompletionLiteralKind::NilLiteral;
  } else if (uid == KindLiteralString) {
    return CodeCompletionLiteralKind::StringLiteral;
  } else if (uid == KindLiteralTuple) {
    return CodeCompletionLiteralKind::Tuple;
  } else {
    llvm_unreachable("unexpected literal kind");
  }
}

static CodeCompletionKeywordKind
getCodeCompletionKeywordKindForUID(UIdent uid) {
#define SWIFT_KEYWORD(kw) \
  static UIdent Keyword##kw##UID("source.lang.swift.keyword." #kw); \
  if (uid == Keyword##kw##UID) { \
    return CodeCompletionKeywordKind::kw_##kw; \
  }
#include "swift/Syntax/TokenKinds.def"

  // FIXME: should warn about unexpected keyword kind.
  return CodeCompletionKeywordKind::None;
}

using ChunkKind = CodeCompletionString::Chunk::ChunkKind;

/// Provide the text for the call parameter, including constructing a typed
/// editor placeholder for it.
static void constructTextForCallParam(
    ArrayRef<CodeCompletionString::Chunk> ParamGroup, raw_ostream &OS) {
  assert(ParamGroup.front().is(ChunkKind::CallParameterBegin));

  for (; !ParamGroup.empty(); ParamGroup = ParamGroup.slice(1)) {
    auto &C = ParamGroup.front();
    if (C.is(ChunkKind::CallParameterInternalName) ||
        C.is(ChunkKind::CallParameterType)) {
      break;
    }
    if (!C.isAnnotation() && C.hasText()) {
      OS << C.getText();
    }
  }

  SmallString<32> DisplayString;
  SmallString<32> TypeString;
  SmallString<32> ExpansionTypeString;

  for (auto &C : ParamGroup) {
    if (C.isAnnotation() || !C.hasText())
      continue;
    if (C.is(ChunkKind::CallParameterClosureType)) {
      assert(ExpansionTypeString.empty());
      ExpansionTypeString = C.getText();
      continue;
    }
    if (C.is(ChunkKind::CallParameterType)) {
      assert(TypeString.empty());
      TypeString = C.getText();
    }
    DisplayString += C.getText();
  }

  StringRef Display = DisplayString.str();
  StringRef Type = TypeString.str();
  StringRef ExpansionType = ExpansionTypeString.str();
  if (ExpansionType.empty())
    ExpansionType = Type;

  OS << "<#T##" << Display;
  if (Display == Type && Display == ExpansionType) {
    // Short version, display and type are the same.
  } else {
    OS << "##" << Type;
    if (ExpansionType != Type)
      OS << "##" << ExpansionType;
  }
  OS << "#>";
}

void SwiftToSourceKitCompletionAdapter::getResultSourceText(
    const CodeCompletionString *CCStr, raw_ostream &OS) {
  auto Chunks = CCStr->getChunks();
  for (size_t i = 0; i < Chunks.size(); ++i) {
    auto &C = Chunks[i];
    if (C.is(ChunkKind::BraceStmtWithCursor)) {
      OS << " {\n" << getCodePlaceholder() << "\n}";
      continue;
    }
    if (C.is(ChunkKind::CallParameterBegin)) {
      size_t Start = i++;
      for (; i < Chunks.size(); ++i) {
        if (Chunks[i].endsPreviousNestedGroup(C.getNestingLevel()))
          break;
      }
      constructTextForCallParam(Chunks.slice(Start, i-Start), OS);
      --i;
      continue;
    }
    if (!C.isAnnotation() && C.hasText()) {
      OS << C.getText();
    }
  }
}

void SwiftToSourceKitCompletionAdapter::getResultTypeName(
    const CodeCompletionString *CCStr, raw_ostream &OS) {
  for (auto C : CCStr->getChunks()) {
    if (C.getKind() == CodeCompletionString::Chunk::ChunkKind::TypeAnnotation) {
      OS << C.getText();
    }
  }
}

void SwiftToSourceKitCompletionAdapter::getResultAssociatedUSRs(
    ArrayRef<StringRef> AssocUSRs, raw_ostream &OS) {
  bool First = true;
  for (auto USR : AssocUSRs) {
    if (!First)
      OS << " ";
    First = false;
    OS << USR;
  }
}

//===----------------------------------------------------------------------===//
// CodeCompletion::SessionCache
//===----------------------------------------------------------------------===//
void CodeCompletion::SessionCache::setSortedCompletions(
    std::vector<Completion *> &&completions) {
  llvm::sys::ScopedLock L(mtx);
  sortedCompletions = std::move(completions);
}
ArrayRef<Completion *> CodeCompletion::SessionCache::getSortedCompletions() {
  llvm::sys::ScopedLock L(mtx);
  return sortedCompletions;
}
llvm::MemoryBuffer *CodeCompletion::SessionCache::getBuffer() {
  llvm::sys::ScopedLock L(mtx);
  return buffer.get();
}
ArrayRef<std::string> CodeCompletion::SessionCache::getCompilerArgs() {
  llvm::sys::ScopedLock L(mtx);
  return args;
}
CompletionKind CodeCompletion::SessionCache::getCompletionKind() {
  llvm::sys::ScopedLock L(mtx);
  return completionKind;
}
bool CodeCompletion::SessionCache::getCompletionHasExpectedTypes() {
  llvm::sys::ScopedLock L(mtx);
  return completionHasExpectedTypes;
}
bool CodeCompletion::SessionCache::getCompletionMayUseImplicitMemberExpr() {
  llvm::sys::ScopedLock L(mtx);
  return completionMayUseImplicitMemberExpr;
}
const CodeCompletion::FilterRules &
CodeCompletion::SessionCache::getFilterRules() {
  llvm::sys::ScopedLock L(mtx);
  return filterRules;
}

//===----------------------------------------------------------------------===//
// CodeCompletion::SessionCacheMap
//===----------------------------------------------------------------------===//

unsigned CodeCompletion::SessionCacheMap::getBufferID(StringRef name) const {
  auto pair = nameToBufferMap.insert(std::make_pair(name, nextBufferID));
  if (pair.second)
    ++nextBufferID;
  return pair.first->getValue();
}

CodeCompletion::SessionCacheRef
CodeCompletion::SessionCacheMap::get(StringRef name, unsigned offset) const {
  llvm::sys::ScopedLock L(mtx);
  auto key = std::make_pair(getBufferID(name), offset);
  auto I = sessions.find(key);
  if (I == sessions.end())
    return nullptr;
  return I->second;
}
bool CodeCompletion::SessionCacheMap::set(StringRef name, unsigned offset,
                                          CodeCompletion::SessionCacheRef s) {
  llvm::sys::ScopedLock L(mtx);
  auto key = std::make_pair(getBufferID(name), offset);
  return sessions.insert(std::make_pair(key, s)).second;
}
bool CodeCompletion::SessionCacheMap::remove(StringRef name, unsigned offset) {
  llvm::sys::ScopedLock L(mtx);
  auto key = std::make_pair(getBufferID(name), offset);
  return sessions.erase(key);
}

//===----------------------------------------------------------------------===//
// (New) Code completion interface
//===----------------------------------------------------------------------===//

namespace {
class SwiftGroupedCodeCompletionConsumer : public CodeCompletionView::Walker {
  GroupedCodeCompletionConsumer &consumer;

public:
  SwiftGroupedCodeCompletionConsumer(GroupedCodeCompletionConsumer &consumer)
      : consumer(consumer) {}
  bool handleResult(Completion *result) override {
    return SwiftToSourceKitCompletionAdapter::handleResult(
        consumer, result, /*leadingPunctuation=*/true,
        /*legacyLiteralToKeyword=*/false);
  }
  void startGroup(StringRef name) override {
    static UIdent GroupUID("source.lang.swift.codecomplete.group");
    consumer.startGroup(GroupUID, name);
  }
  void endGroup() override { consumer.endGroup(); }
};

} // end anonymous namespace

static void translateCodeCompletionOptions(OptionsDictionary &from,
                                           CodeCompletion::Options &to,
                                           StringRef &filterText,
                                           unsigned &resultOffset,
                                           unsigned &maxResults) {
  static UIdent KeySortByName("key.codecomplete.sort.byname");
  static UIdent KeyUseImportDepth("key.codecomplete.sort.useimportdepth");
  static UIdent KeyGroupOverloads("key.codecomplete.group.overloads");
  static UIdent KeyGroupStems("key.codecomplete.group.stems");
  static UIdent KeyFilterText("key.codecomplete.filtertext");
  static UIdent KeyRequestLimit("key.codecomplete.requestlimit");
  static UIdent KeyRequestStart("key.codecomplete.requeststart");
  static UIdent KeyHideUnderscores("key.codecomplete.hideunderscores");
  static UIdent KeyHideLowPriority("key.codecomplete.hidelowpriority");
  static UIdent KeyHideByName("key.codecomplete.hidebyname");
  static UIdent KeyIncludeExactMatch("key.codecomplete.includeexactmatch");
  static UIdent KeyAddInnerResults("key.codecomplete.addinnerresults");
  static UIdent KeyAddInnerOperators("key.codecomplete.addinneroperators");
  static UIdent KeyAddInitsToTopLevel("key.codecomplete.addinitstotoplevel");
  static UIdent KeyCallPatternHeuristics("key.codecomplete.callpatternheuristics");
  static UIdent KeyFuzzyMatching("key.codecomplete.fuzzymatching");
  static UIdent KeyTopNonLiteral("key.codecomplete.showtopnonliteralresults");
  static UIdent KeyContextWeight("key.codecomplete.sort.contextweight");
  static UIdent KeyFuzzyWeight("key.codecomplete.sort.fuzzyweight");
  static UIdent KeyPopularityBonus("key.codecomplete.sort.popularitybonus");
  from.valueForOption(KeySortByName, to.sortByName);
  from.valueForOption(KeyUseImportDepth, to.useImportDepth);
  from.valueForOption(KeyGroupOverloads, to.groupOverloads);
  from.valueForOption(KeyGroupStems, to.groupStems);
  from.valueForOption(KeyFilterText, filterText);
  from.valueForOption(KeyRequestLimit, maxResults);
  from.valueForOption(KeyRequestStart, resultOffset);
  unsigned howMuchHiding = 1;
  from.valueForOption(KeyHideUnderscores, howMuchHiding);
  to.hideUnderscores = howMuchHiding;
  to.reallyHideAllUnderscores = howMuchHiding > 1;
  from.valueForOption(KeyHideLowPriority, to.hideLowPriority);
  from.valueForOption(KeyIncludeExactMatch, to.includeExactMatch);
  from.valueForOption(KeyAddInnerResults, to.addInnerResults);
  from.valueForOption(KeyAddInnerOperators, to.addInnerOperators);
  from.valueForOption(KeyAddInitsToTopLevel, to.addInitsToTopLevel);
  from.valueForOption(KeyCallPatternHeuristics, to.callPatternHeuristics);
  from.valueForOption(KeyFuzzyMatching, to.fuzzyMatching);
  from.valueForOption(KeyContextWeight, to.semanticContextWeight);
  from.valueForOption(KeyFuzzyWeight, to.fuzzyMatchWeight);
  from.valueForOption(KeyPopularityBonus, to.popularityBonus);
  from.valueForOption(KeyHideByName, to.hideByNameStyle);
  from.valueForOption(KeyTopNonLiteral, to.showTopNonLiteralResults);
}

/// Canonicalize a name that is in the format of a reference to a function into
/// the name format used internally for filtering.
///
/// Returns true if the name is invalid.
static bool canonicalizeFilterName(const char *origName,
                                   SmallVectorImpl<char> &Result) {
  assert(origName);
  const char *p = origName;
  char curr = '\0';
  char prev;

  // FIXME: disallow unnamed parameters without underscores `foo(::)`.
  while (true) {
    prev = curr;
    curr = *p++;
    switch (curr) {
    case '\0':
      return false; // Done.
    case '_':
      // Remove the _ underscore for an unnamed parameter.
      if (prev == ':' || prev == '(') {
        char next = *p;
        if (next == ':' || next == ')')
          continue;
      }
      LLVM_FALLTHROUGH;
    default:
      Result.push_back(curr);
      continue;
    }
  }
  llvm_unreachable("exit is on null byte");
}

static void translateFilterRules(ArrayRef<FilterRule> rawFilterRules,
                                 CodeCompletion::FilterRules &filterRules) {
  for (auto &rule : rawFilterRules) {
    switch (rule.kind) {
    case FilterRule::Everything:
      filterRules.hideAll = rule.hide;
      break;
    case FilterRule::Identifier:
      for (auto name : rule.names) {
        SmallString<128> canonName;
        // Note: name is null-terminated.
        if (canonicalizeFilterName(name.data(), canonName))
          continue;
        filterRules.hideByFilterName[canonName] = rule.hide;
      }
      break;
    case FilterRule::Description:
      for (auto name : rule.names) {
        filterRules.hideByDescription[name] = rule.hide;
      }
      break;
    case FilterRule::Module:
      for (auto name : rule.names) {
        filterRules.hideModule[name] = rule.hide;
      }
      break;
    case FilterRule::Keyword:
      if (rule.uids.empty())
        filterRules.hideAllKeywords = rule.hide;
      for (auto uid : rule.uids) {
        auto kind = getCodeCompletionKeywordKindForUID(uid);
        filterRules.hideKeyword[kind] = rule.hide;
      }
      break;
    case FilterRule::Literal:
      if (rule.uids.empty())
        filterRules.hideAllValueLiterals = rule.hide;
      for (auto uid : rule.uids) {
        auto kind = getCodeCompletionLiteralKindForUID(uid);
        filterRules.hideValueLiteral[kind] = rule.hide;
      }
      break;
    case FilterRule::CustomCompletion:
      if (rule.uids.empty())
        filterRules.hideCustomCompletions = rule.hide;
      // FIXME: hide individual custom completions
      break;
    }
  }
}

static bool checkInnerResult(CodeCompletionResult *result, bool &hasDot,
                             bool &hasQDot, bool &hasInit) {
  auto chunks = result->getCompletionString()->getChunks();
  if (!chunks.empty() &&
      chunks[0].is(CodeCompletionString::Chunk::ChunkKind::Dot)) {
    hasDot = true;
    return true;
  } else if (chunks.size() >= 2 &&
             chunks[0].is(
                 CodeCompletionString::Chunk::ChunkKind::QuestionMark) &&
             chunks[1].is(CodeCompletionString::Chunk::ChunkKind::Dot)) {
    hasQDot = true;
    return true;
  } else if (result->getKind() ==
                 CodeCompletion::SwiftResult::ResultKind::Declaration &&
             result->getAssociatedDeclKind() ==
                 CodeCompletionDeclKind::Constructor) {
    hasInit = true;
    return true;
  } else {
    return false;
  }
}

template <typename Result>
static std::vector<Result *>
filterInnerResults(ArrayRef<Result *> results, bool includeInner,
                   bool includeInnerOperators,
                   bool &hasDot, bool &hasQDot, bool &hasInit,
                   const CodeCompletion::FilterRules &rules) {
  std::vector<Result *> topResults;
  for (auto *result : results) {
    if (!includeInnerOperators && result->isOperator())
      continue;

    llvm::SmallString<64> filterName;
    {
      llvm::raw_svector_ostream OSS(filterName);
      CodeCompletion::CompletionBuilder::getFilterName(
          result->getCompletionString(), OSS);
    }
    llvm::SmallString<64> description;
    {
      llvm::raw_svector_ostream OSS(description);
      CodeCompletion::CompletionBuilder::getDescription(
          result, OSS, /*leadingPunctuation=*/false);
    }
    if (rules.hideCompletion(result, filterName, description))
      continue;

    bool inner = checkInnerResult(result, hasDot, hasQDot, hasInit);

    if (!inner ||
        (includeInner &&
         result->getSemanticContext() <= SemanticContextKind::CurrentNominal))
      topResults.push_back(result);
  }
  return topResults;
}

static void transformAndForwardResults(
    GroupedCodeCompletionConsumer &consumer, SwiftLangSupport &lang,
    CodeCompletion::SessionCacheRef session,
    const NameToPopularityMap *nameToPopularity,
    CodeCompletion::Options options, unsigned offset, StringRef filterText,
    unsigned resultOffset, unsigned maxResults) {

  CodeCompletion::CompletionSink innerSink;
  Completion *exactMatch = nullptr;
  auto buildInnerResult = [&](ArrayRef<CodeCompletionString::Chunk> chunks) {
    auto *completionString =
        CodeCompletionString::create(innerSink.allocator, chunks);
    CodeCompletion::SwiftResult paren(
        CodeCompletion::SwiftResult::ResultKind::BuiltinOperator,
        SemanticContextKind::ExpressionSpecific,
        exactMatch ? exactMatch->getNumBytesToErase() : 0, completionString);

    SwiftCompletionInfo info;
    std::vector<Completion *> extended =
        extendCompletions(&paren, innerSink, info, nameToPopularity, options,
                          exactMatch, SemanticContextKind::ExpressionSpecific);
    assert(extended.size() == 1);
    return extended.front();
  };
  auto buildParen = [&]() {
    return buildInnerResult(CodeCompletionString::Chunk::createWithText(
        CodeCompletionString::Chunk::ChunkKind::LeftParen, 0, "("));
  };
  auto buildDot = [&]() {
    return buildInnerResult(CodeCompletionString::Chunk::createWithText(
        CodeCompletionString::Chunk::ChunkKind::Dot, 0, "."));
  };
  auto buildQDot = [&]() {
    CodeCompletionString::Chunk chunks[2] = {
        CodeCompletionString::Chunk::createWithText(
            CodeCompletionString::Chunk::ChunkKind::QuestionMark, 0, "?"),
        CodeCompletionString::Chunk::createWithText(
            CodeCompletionString::Chunk::ChunkKind::Dot, 0, ".")};
    return buildInnerResult(chunks);
  };

  CodeCompletion::CodeCompletionOrganizer organizer(
      options, session->getCompletionKind(),
      session->getCompletionHasExpectedTypes());

  auto &rules = session->getFilterRules();

  bool hasEarlyInnerResults =
      session->getCompletionKind() == CompletionKind::PostfixExpr;

  if (!hasEarlyInnerResults) {
    organizer.addCompletionsWithFilter(session->getSortedCompletions(),
                                       filterText, rules, exactMatch);
    // Add leading dot?
    if (options.addInnerOperators && !rules.hideFilterName(".") &&
        session->getCompletionMayUseImplicitMemberExpr()) {
      organizer.addCompletionsWithFilter(
          buildDot(), filterText, CodeCompletion::FilterRules(), exactMatch);
    }
  }

  if (hasEarlyInnerResults &&
      (options.addInnerResults || options.addInnerOperators)) {
    bool hasInit = false;
    bool hasDot = false;
    bool hasQDot = false;
    auto completions = session->getSortedCompletions();
    auto innerResults =
        filterInnerResults(completions, options.addInnerResults,
                           options.addInnerOperators, hasDot, hasQDot, hasInit,
                           rules);
    if (options.addInnerOperators) {
      if (hasInit && !rules.hideFilterName("("))
        innerResults.insert(innerResults.begin(), buildParen());
      if (hasDot && !rules.hideFilterName("."))
        innerResults.insert(innerResults.begin(), buildDot());
      if (hasQDot && !rules.hideFilterName("?."))
        innerResults.insert(innerResults.begin(), buildQDot());
    }

    organizer.addCompletionsWithFilter(innerResults, filterText,
                                       CodeCompletion::FilterRules(), exactMatch);
  }

  organizer.groupAndSort(options);

  if ((options.addInnerResults || options.addInnerOperators) &&
      exactMatch && exactMatch->getKind() == Completion::Declaration) {
    std::vector<Completion *> innerResults;
    bool hasDot = false;
    bool hasQDot = false;
    bool hasInit = false;
    SwiftCodeCompletionConsumer swiftConsumer([&](
        MutableArrayRef<CodeCompletionResult *> results,
        SwiftCompletionInfo &info) {
      auto *context = info.completionContext;
      if (!context || context->CodeCompletionKind != CompletionKind::PostfixExpr)
        return;
      auto topResults = filterInnerResults(results, options.addInnerResults,
                                           options.addInnerOperators, hasDot,
                                           hasQDot, hasInit, rules);
      // FIXME: Overriding the default to context "None" is a hack so that they
      // won't overwhelm other results that also match the filter text.
      innerResults = extendCompletions(
          topResults, innerSink, info, nameToPopularity, options, exactMatch,
          SemanticContextKind::None, SemanticContextKind::None);
    });

    auto *inputBuf = session->getBuffer();
    std::string str = inputBuf->getBuffer().slice(0, offset);
    {
      llvm::raw_string_ostream OSS(str);
      SwiftToSourceKitCompletionAdapter::getResultSourceText(
          exactMatch->getCompletionString(), OSS);
    }

    auto buffer =
        llvm::MemoryBuffer::getMemBuffer(str, inputBuf->getBufferIdentifier());
    auto args = session->getCompilerArgs();
    std::vector<const char *> cargs;
    for (auto &arg : args)
      cargs.push_back(arg.c_str());
    std::string error;
    if (!swiftCodeCompleteImpl(lang, buffer.get(), str.size(), swiftConsumer,
                               cargs, error)) {
      consumer.failed(error);
      return;
    }

    if (options.addInnerOperators) {
      if (hasInit && !rules.hideFilterName("("))
        innerResults.insert(innerResults.begin(), buildParen());
      if (hasDot && !rules.hideFilterName("."))
        innerResults.insert(innerResults.begin(), buildDot());
      if (hasQDot && !rules.hideFilterName("?."))
        innerResults.insert(innerResults.begin(), buildQDot());
    }

    // Add the inner results (and don't filter them).
    exactMatch = nullptr; // No longer needed.
    organizer.addCompletionsWithFilter(innerResults, filterText,
                                       CodeCompletion::FilterRules(), exactMatch);

    CodeCompletion::Options noGroupOpts = options;
    noGroupOpts.groupStems = false;
    noGroupOpts.groupOverloads = false;
    organizer.groupAndSort(noGroupOpts);
  }

  // Build the final results view.
  auto view = organizer.takeResultsView();
  CodeCompletion::LimitedResultView limitedResults(*view, resultOffset,
                                                   maxResults);

  // Forward results to the SourceKit consumer.
  SwiftGroupedCodeCompletionConsumer groupedConsumer(consumer);
  limitedResults.walk(groupedConsumer);
  consumer.setNextRequestStart(limitedResults.getNextOffset());
}

void SwiftLangSupport::codeCompleteOpen(
    StringRef name, llvm::MemoryBuffer *inputBuf, unsigned offset,
    OptionsDictionary *options, ArrayRef<FilterRule> rawFilterRules,
    GroupedCodeCompletionConsumer &consumer, ArrayRef<const char *> args) {
  StringRef filterText;
  unsigned resultOffset = 0;
  unsigned maxResults = 0;
  CodeCompletion::Options CCOpts;
  if (options)
    translateCodeCompletionOptions(*options, CCOpts, filterText, resultOffset,
                                   maxResults);

  CodeCompletion::FilterRules filterRules;
  translateFilterRules(rawFilterRules, filterRules);

  // Set up the code completion consumer to pass results to organizer.
  CodeCompletion::CompletionSink sink;
  std::vector<Completion *> completions;

  NameToPopularityMap *nameToPopularity = nullptr;
  // This reference must outlive the uses of nameToPopularity.
  auto popularAPIRef = PopularAPI;
  if (popularAPIRef) {
    nameToPopularity = &popularAPIRef->nameToFactor;
  }

  CompletionKind completionKind = CompletionKind::None;
  bool hasExpectedTypes = false;
  bool mayUseImplicitMemberExpr = false;

  SwiftCodeCompletionConsumer swiftConsumer(
      [&](MutableArrayRef<CodeCompletionResult *> results,
          SwiftCompletionInfo &info) {
        auto &completionCtx = *info.completionContext;
        completionKind = completionCtx.CodeCompletionKind;
        hasExpectedTypes = completionCtx.HasExpectedTypeRelation;
        mayUseImplicitMemberExpr = completionCtx.MayUseImplicitMemberExpr;
        completions =
            extendCompletions(results, sink, info, nameToPopularity, CCOpts);
      });

  // Add any codecomplete.open specific flags.
  std::vector<const char *> extendedArgs(args.begin(), args.end());
  if (CCOpts.addInitsToTopLevel) {
    extendedArgs.push_back("-Xfrontend");
    extendedArgs.push_back("-code-complete-inits-in-postfix-expr");
  }
  if (CCOpts.callPatternHeuristics) {
    extendedArgs.push_back("-Xfrontend");
    extendedArgs.push_back("-code-complete-call-pattern-heuristics");
  }

  // Invoke completion.
  std::string error;
  if (!swiftCodeCompleteImpl(*this, inputBuf, offset, swiftConsumer,
                             extendedArgs, error)) {
    consumer.failed(error);
    return;
  }

  // Add any relevant custom completions.
  if (auto custom = CustomCompletions)
    addCustomCompletions(sink, completions, custom->customCompletions,
                         completionKind);

  // Pre-sort the completions.
  CodeCompletion::CodeCompletionOrganizer::preSortCompletions(completions);

  // Store in the session.
  using CodeCompletion::SessionCache;
  using CodeCompletion::SessionCacheRef;
  auto bufferCopy = llvm::MemoryBuffer::getMemBufferCopy(
      inputBuf->getBuffer(), inputBuf->getBufferIdentifier());
  std::vector<std::string> argsCopy(extendedArgs.begin(), extendedArgs.end());
  SessionCacheRef session{new SessionCache(
      std::move(sink), std::move(bufferCopy), std::move(argsCopy),
      completionKind, hasExpectedTypes, mayUseImplicitMemberExpr,
      std::move(filterRules))};
  session->setSortedCompletions(std::move(completions));

  if (!CCSessions.set(name, offset, session)) {
    std::string err;
    llvm::raw_string_ostream OS(err);
    OS << "codecomplete.open: code completion session for '" << name << "', "
       << offset << " already exists";
    consumer.failed(OS.str());
  }

  transformAndForwardResults(consumer, *this, session, nameToPopularity, CCOpts,
                             offset, filterText, resultOffset, maxResults);
}

void SwiftLangSupport::codeCompleteClose(
    StringRef name, unsigned offset, GroupedCodeCompletionConsumer &consumer) {
  if (!CCSessions.remove(name, offset)) {
    std::string err;
    llvm::raw_string_ostream OS(err);
    OS << "codecomplete.close: no code completion session for '" << name
       << "', " << offset;
    consumer.failed(OS.str());
  }
}

void SwiftLangSupport::codeCompleteUpdate(
    StringRef name, unsigned offset, OptionsDictionary *options,
    GroupedCodeCompletionConsumer &consumer) {
  auto session = CCSessions.get(name, offset);
  if (!session) {
    std::string err;
    llvm::raw_string_ostream OS(err);
    OS << "codecomplete.update: no code completion session for '" << name
       << "', " << offset;
    consumer.failed(OS.str());
    return;
  }

  StringRef filterText;
  unsigned resultOffset = 0;
  unsigned maxResults = 0;

  // FIXME: consider whether CCOpts has changed since the 'open'.
  CodeCompletion::Options CCOpts;
  if (options)
    translateCodeCompletionOptions(*options, CCOpts, filterText, resultOffset,
                                   maxResults);

  NameToPopularityMap *nameToPopularity = nullptr;
  // This reference must outlive the uses of nameToPopularity.
  auto popularAPIRef = PopularAPI;
  if (popularAPIRef) {
    nameToPopularity = &popularAPIRef->nameToFactor;
  }

  transformAndForwardResults(consumer, *this, session, nameToPopularity, CCOpts,
                             offset, filterText, resultOffset, maxResults);
}

swift::ide::CodeCompletionCache &SwiftCompletionCache::getCache() {
  return *inMemory;
}
SwiftCompletionCache::~SwiftCompletionCache() {}

void SwiftLangSupport::codeCompleteCacheOnDisk(StringRef path) {
  ThreadSafeRefCntPtr<SwiftCompletionCache> newCache(new SwiftCompletionCache);
  newCache->onDisk = llvm::make_unique<ide::OnDiskCodeCompletionCache>(path);
  newCache->inMemory =
      llvm::make_unique<ide::CodeCompletionCache>(newCache->onDisk.get());

  CCCache = newCache; // replace the old cache.
}

void SwiftLangSupport::codeCompleteSetPopularAPI(
    ArrayRef<const char *> popularAPI, ArrayRef<const char *> unpopularAPI) {
  using Factor = CodeCompletion::PopularityFactor;
  ThreadSafeRefCntPtr<SwiftPopularAPI> newPopularAPI(new SwiftPopularAPI);
  auto &nameToFactor = newPopularAPI->nameToFactor;
  for (unsigned i = 0, n = popularAPI.size(); i < n; ++i) {
    SmallString<64> name;
    if (canonicalizeFilterName(popularAPI[i], name))
      continue;
    nameToFactor[name] = Factor(double(n - i) / n);
  }
  for (unsigned i = 0, n = unpopularAPI.size(); i < n; ++i) {
    SmallString<64> name;
    if (canonicalizeFilterName(unpopularAPI[i], name))
      continue;
    nameToFactor[name] = Factor(-double(n - i) / n);
  }

  PopularAPI = newPopularAPI; // replace the old popular API.
}

void SwiftLangSupport::codeCompleteSetCustom(
    ArrayRef<CustomCompletionInfo> completions) {
  ThreadSafeRefCntPtr<SwiftCustomCompletions> newCustomCompletions(
      new SwiftCustomCompletions);
  newCustomCompletions->customCompletions.assign(completions.begin(),
                                                 completions.end());
  CustomCompletions = newCustomCompletions; // Replace the existing completions.
}
