[clang-tools-extra] r319655 - [clangd] Split CodeComplete into a separate file. NFC

Sam McCall via cfe-commits cfe-commits at lists.llvm.org
Mon Dec 4 05:49:59 PST 2017


Author: sammccall
Date: Mon Dec  4 05:49:59 2017
New Revision: 319655

URL: http://llvm.org/viewvc/llvm-project?rev=319655&view=rev
Log:
[clangd] Split CodeComplete into a separate file. NFC

Summary: Shared details of ClangdUnit and CodeComplete moved to a new Compiler file.

Reviewers: ilya-biryukov

Subscribers: klimek, mgorny, cfe-commits

Differential Revision: https://reviews.llvm.org/D40719

Added:
    clang-tools-extra/trunk/clangd/CodeComplete.cpp
    clang-tools-extra/trunk/clangd/CodeComplete.h
    clang-tools-extra/trunk/clangd/Compiler.cpp
    clang-tools-extra/trunk/clangd/Compiler.h
Modified:
    clang-tools-extra/trunk/clangd/CMakeLists.txt
    clang-tools-extra/trunk/clangd/ClangdServer.h
    clang-tools-extra/trunk/clangd/ClangdUnit.cpp
    clang-tools-extra/trunk/clangd/ClangdUnit.h

Modified: clang-tools-extra/trunk/clangd/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/CMakeLists.txt?rev=319655&r1=319654&r2=319655&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/CMakeLists.txt (original)
+++ clang-tools-extra/trunk/clangd/CMakeLists.txt Mon Dec  4 05:49:59 2017
@@ -7,6 +7,8 @@ add_clang_library(clangDaemon
   ClangdServer.cpp
   ClangdUnit.cpp
   ClangdUnitStore.cpp
+  CodeComplete.cpp
+  Compiler.cpp
   DraftStore.cpp
   FuzzyMatch.cpp
   GlobalCompilationDatabase.cpp

Modified: clang-tools-extra/trunk/clangd/ClangdServer.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdServer.h?rev=319655&r1=319654&r2=319655&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/ClangdServer.h (original)
+++ clang-tools-extra/trunk/clangd/ClangdServer.h Mon Dec  4 05:49:59 2017
@@ -20,6 +20,7 @@
 #include "llvm/ADT/StringRef.h"
 
 #include "ClangdUnit.h"
+#include "CodeComplete.h"
 #include "Function.h"
 #include "Protocol.h"
 

Modified: clang-tools-extra/trunk/clangd/ClangdUnit.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdUnit.cpp?rev=319655&r1=319654&r2=319655&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/ClangdUnit.cpp (original)
+++ clang-tools-extra/trunk/clangd/ClangdUnit.cpp Mon Dec  4 05:49:59 2017
@@ -9,6 +9,7 @@
 
 #include "ClangdUnit.h"
 
+#include "Compiler.h"
 #include "Logger.h"
 #include "Trace.h"
 #include "clang/Frontend/CompilerInstance.h"
@@ -20,7 +21,6 @@
 #include "clang/Lex/Lexer.h"
 #include "clang/Lex/MacroInfo.h"
 #include "clang/Lex/Preprocessor.h"
-#include "clang/Lex/PreprocessorOptions.h"
 #include "clang/Sema/Sema.h"
 #include "clang/Serialization/ASTWriter.h"
 #include "clang/Tooling/CompilationDatabase.h"
@@ -120,44 +120,6 @@ static int getSeverity(DiagnosticsEngine
   llvm_unreachable("Unknown diagnostic level!");
 }
 
-/// Get the optional chunk as a string. This function is possibly recursive.
-///
-/// The parameter info for each parameter is appended to the Parameters.
-std::string
-getOptionalParameters(const CodeCompletionString &CCS,
-                      std::vector<ParameterInformation> &Parameters) {
-  std::string Result;
-  for (const auto &Chunk : CCS) {
-    switch (Chunk.Kind) {
-    case CodeCompletionString::CK_Optional:
-      assert(Chunk.Optional &&
-             "Expected the optional code completion string to be non-null.");
-      Result += getOptionalParameters(*Chunk.Optional, Parameters);
-      break;
-    case CodeCompletionString::CK_VerticalSpace:
-      break;
-    case CodeCompletionString::CK_Placeholder:
-      // A string that acts as a placeholder for, e.g., a function call
-      // argument.
-      // Intentional fallthrough here.
-    case CodeCompletionString::CK_CurrentParameter: {
-      // A piece of text that describes the parameter that corresponds to
-      // the code-completion location within a function call, message send,
-      // macro invocation, etc.
-      Result += Chunk.Text;
-      ParameterInformation Info;
-      Info.label = Chunk.Text;
-      Parameters.push_back(std::move(Info));
-      break;
-    }
-    default:
-      Result += Chunk.Text;
-      break;
-    }
-  }
-  return Result;
-}
-
 llvm::Optional<DiagWithFixIts> toClangdDiag(const StoredDiagnostic &D) {
   auto Location = D.getLocation();
   if (!Location.isValid() || !Location.getManager().isInMainFile(Location))
@@ -193,722 +155,12 @@ private:
   std::vector<DiagWithFixIts> &Output;
 };
 
-class EmptyDiagsConsumer : public DiagnosticConsumer {
-public:
-  void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
-                        const clang::Diagnostic &Info) override {}
-};
-
-std::unique_ptr<CompilerInvocation>
-createCompilerInvocation(ArrayRef<const char *> ArgList,
-                         IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
-                         IntrusiveRefCntPtr<vfs::FileSystem> VFS) {
-  auto CI = createInvocationFromCommandLine(ArgList, std::move(Diags),
-                                            std::move(VFS));
-  // We rely on CompilerInstance to manage the resource (i.e. free them on
-  // EndSourceFile), but that won't happen if DisableFree is set to true.
-  // Since createInvocationFromCommandLine sets it to true, we have to override
-  // it.
-  CI->getFrontendOpts().DisableFree = false;
-  return CI;
-}
-
-/// Creates a CompilerInstance from \p CI, with main buffer overriden to \p
-/// Buffer and arguments to read the PCH from \p Preamble, if \p Preamble is not
-/// null. Note that vfs::FileSystem inside returned instance may differ from \p
-/// VFS if additional file remapping were set in command-line arguments.
-/// On some errors, returns null. When non-null value is returned, it's expected
-/// to be consumed by the FrontendAction as it will have a pointer to the \p
-/// Buffer that will only be deleted if BeginSourceFile is called.
-std::unique_ptr<CompilerInstance>
-prepareCompilerInstance(std::unique_ptr<clang::CompilerInvocation> CI,
-                        const PrecompiledPreamble *Preamble,
-                        std::unique_ptr<llvm::MemoryBuffer> Buffer,
-                        std::shared_ptr<PCHContainerOperations> PCHs,
-                        IntrusiveRefCntPtr<vfs::FileSystem> VFS,
-                        DiagnosticConsumer &DiagsClient) {
-  assert(VFS && "VFS is null");
-  assert(!CI->getPreprocessorOpts().RetainRemappedFileBuffers &&
-         "Setting RetainRemappedFileBuffers to true will cause a memory leak "
-         "of ContentsBuffer");
-
-  // NOTE: we use Buffer.get() when adding remapped files, so we have to make
-  // sure it will be released if no error is emitted.
-  if (Preamble) {
-    Preamble->AddImplicitPreamble(*CI, VFS, Buffer.get());
-  } else {
-    CI->getPreprocessorOpts().addRemappedFile(
-        CI->getFrontendOpts().Inputs[0].getFile(), Buffer.get());
-  }
-
-  auto Clang = llvm::make_unique<CompilerInstance>(PCHs);
-  Clang->setInvocation(std::move(CI));
-  Clang->createDiagnostics(&DiagsClient, false);
-
-  if (auto VFSWithRemapping = createVFSFromCompilerInvocation(
-          Clang->getInvocation(), Clang->getDiagnostics(), VFS))
-    VFS = VFSWithRemapping;
-  Clang->setVirtualFileSystem(VFS);
-
-  Clang->setTarget(TargetInfo::CreateTargetInfo(
-      Clang->getDiagnostics(), Clang->getInvocation().TargetOpts));
-  if (!Clang->hasTarget())
-    return nullptr;
-
-  // RemappedFileBuffers will handle the lifetime of the Buffer pointer,
-  // release it.
-  Buffer.release();
-  return Clang;
-}
-
 template <class T> bool futureIsReady(std::shared_future<T> const &Future) {
   return Future.wait_for(std::chrono::seconds(0)) == std::future_status::ready;
 }
 
 } // namespace
 
-namespace {
-
-CompletionItemKind getKindOfDecl(CXCursorKind CursorKind) {
-  switch (CursorKind) {
-  case CXCursor_MacroInstantiation:
-  case CXCursor_MacroDefinition:
-    return CompletionItemKind::Text;
-  case CXCursor_CXXMethod:
-    return CompletionItemKind::Method;
-  case CXCursor_FunctionDecl:
-  case CXCursor_FunctionTemplate:
-    return CompletionItemKind::Function;
-  case CXCursor_Constructor:
-  case CXCursor_Destructor:
-    return CompletionItemKind::Constructor;
-  case CXCursor_FieldDecl:
-    return CompletionItemKind::Field;
-  case CXCursor_VarDecl:
-  case CXCursor_ParmDecl:
-    return CompletionItemKind::Variable;
-  case CXCursor_ClassDecl:
-  case CXCursor_StructDecl:
-  case CXCursor_UnionDecl:
-  case CXCursor_ClassTemplate:
-  case CXCursor_ClassTemplatePartialSpecialization:
-    return CompletionItemKind::Class;
-  case CXCursor_Namespace:
-  case CXCursor_NamespaceAlias:
-  case CXCursor_NamespaceRef:
-    return CompletionItemKind::Module;
-  case CXCursor_EnumConstantDecl:
-    return CompletionItemKind::Value;
-  case CXCursor_EnumDecl:
-    return CompletionItemKind::Enum;
-  case CXCursor_TypeAliasDecl:
-  case CXCursor_TypeAliasTemplateDecl:
-  case CXCursor_TypedefDecl:
-  case CXCursor_MemberRef:
-  case CXCursor_TypeRef:
-    return CompletionItemKind::Reference;
-  default:
-    return CompletionItemKind::Missing;
-  }
-}
-
-CompletionItemKind getKind(CodeCompletionResult::ResultKind ResKind,
-                           CXCursorKind CursorKind) {
-  switch (ResKind) {
-  case CodeCompletionResult::RK_Declaration:
-    return getKindOfDecl(CursorKind);
-  case CodeCompletionResult::RK_Keyword:
-    return CompletionItemKind::Keyword;
-  case CodeCompletionResult::RK_Macro:
-    return CompletionItemKind::Text; // unfortunately, there's no 'Macro'
-                                     // completion items in LSP.
-  case CodeCompletionResult::RK_Pattern:
-    return CompletionItemKind::Snippet;
-  }
-  llvm_unreachable("Unhandled CodeCompletionResult::ResultKind.");
-}
-
-std::string escapeSnippet(const llvm::StringRef Text) {
-  std::string Result;
-  Result.reserve(Text.size()); // Assume '$', '}' and '\\' are rare.
-  for (const auto Character : Text) {
-    if (Character == '$' || Character == '}' || Character == '\\')
-      Result.push_back('\\');
-    Result.push_back(Character);
-  }
-  return Result;
-}
-
-std::string getDocumentation(const CodeCompletionString &CCS) {
-  // Things like __attribute__((nonnull(1,3))) and [[noreturn]]. Present this
-  // information in the documentation field.
-  std::string Result;
-  const unsigned AnnotationCount = CCS.getAnnotationCount();
-  if (AnnotationCount > 0) {
-    Result += "Annotation";
-    if (AnnotationCount == 1) {
-      Result += ": ";
-    } else /* AnnotationCount > 1 */ {
-      Result += "s: ";
-    }
-    for (unsigned I = 0; I < AnnotationCount; ++I) {
-      Result += CCS.getAnnotation(I);
-      Result.push_back(I == AnnotationCount - 1 ? '\n' : ' ');
-    }
-  }
-  // Add brief documentation (if there is any).
-  if (CCS.getBriefComment() != nullptr) {
-    if (!Result.empty()) {
-      // This means we previously added annotations. Add an extra newline
-      // character to make the annotations stand out.
-      Result.push_back('\n');
-    }
-    Result += CCS.getBriefComment();
-  }
-  return Result;
-}
-
-/// A scored code completion result.
-/// It may be promoted to a CompletionItem if it's among the top-ranked results.
-struct CompletionCandidate {
-  CompletionCandidate(CodeCompletionResult &Result)
-      : Result(&Result), Score(score(Result)) {}
-
-  CodeCompletionResult *Result;
-  float Score; // 0 to 1, higher is better.
-
-  // Comparison reflects rank: better candidates are smaller.
-  bool operator<(const CompletionCandidate &C) const {
-    if (Score != C.Score)
-      return Score > C.Score;
-    return *Result < *C.Result;
-  }
-
-  // Returns a string that sorts in the same order as operator<, for LSP.
-  // Conceptually, this is [-Score, Name]. We convert -Score to an integer, and
-  // hex-encode it for readability. Example: [0.5, "foo"] -> "41000000foo"
-  std::string sortText() const {
-    std::string S, NameStorage;
-    llvm::raw_string_ostream OS(S);
-    write_hex(OS, encodeFloat(-Score), llvm::HexPrintStyle::Lower,
-              /*Width=*/2 * sizeof(Score));
-    OS << Result->getOrderedName(NameStorage);
-    return OS.str();
-  }
-
-private:
-  static float score(const CodeCompletionResult &Result) {
-    // Priority 80 is a really bad score.
-    float Score = 1 - std::min<float>(80, Result.Priority) / 80;
-
-    switch (static_cast<CXAvailabilityKind>(Result.Availability)) {
-    case CXAvailability_Available:
-      // No penalty.
-      break;
-    case CXAvailability_Deprecated:
-      Score *= 0.1f;
-      break;
-    case CXAvailability_NotAccessible:
-    case CXAvailability_NotAvailable:
-      Score = 0;
-      break;
-    }
-    return Score;
-  }
-
-  // Produces an integer that sorts in the same order as F.
-  // That is: a < b <==> encodeFloat(a) < encodeFloat(b).
-  static uint32_t encodeFloat(float F) {
-    static_assert(std::numeric_limits<float>::is_iec559, "");
-    static_assert(sizeof(float) == sizeof(uint32_t), "");
-    constexpr uint32_t TopBit = ~(~uint32_t{0} >> 1);
-
-    // Get the bits of the float. Endianness is the same as for integers.
-    uint32_t U;
-    memcpy(&U, &F, sizeof(float));
-    // IEEE 754 floats compare like sign-magnitude integers.
-    if (U & TopBit)    // Negative float.
-      return 0 - U;    // Map onto the low half of integers, order reversed.
-    return U + TopBit; // Positive floats map onto the high half of integers.
-  }
-};
-
-class CompletionItemsCollector : public CodeCompleteConsumer {
-public:
-  CompletionItemsCollector(const clangd::CodeCompleteOptions &CodeCompleteOpts,
-                           CompletionList &Items)
-      : CodeCompleteConsumer(CodeCompleteOpts.getClangCompleteOpts(),
-                             /*OutputIsBinary=*/false),
-        ClangdOpts(CodeCompleteOpts), Items(Items),
-        Allocator(std::make_shared<clang::GlobalCodeCompletionAllocator>()),
-        CCTUInfo(Allocator) {}
-
-  void ProcessCodeCompleteResults(Sema &S, CodeCompletionContext Context,
-                                  CodeCompletionResult *Results,
-                                  unsigned NumResults) override final {
-    StringRef Filter = S.getPreprocessor().getCodeCompletionFilter();
-    std::priority_queue<CompletionCandidate> Candidates;
-    for (unsigned I = 0; I < NumResults; ++I) {
-      auto &Result = Results[I];
-      if (!ClangdOpts.IncludeIneligibleResults &&
-          (Result.Availability == CXAvailability_NotAvailable ||
-           Result.Availability == CXAvailability_NotAccessible))
-        continue;
-      if (!Filter.empty() && !fuzzyMatch(S, Context, Filter, Result))
-        continue;
-      Candidates.emplace(Result);
-      if (ClangdOpts.Limit && Candidates.size() > ClangdOpts.Limit) {
-        Candidates.pop();
-        Items.isIncomplete = true;
-      }
-    }
-    while (!Candidates.empty()) {
-      auto &Candidate = Candidates.top();
-      const auto *CCS = Candidate.Result->CreateCodeCompletionString(
-          S, Context, *Allocator, CCTUInfo,
-          CodeCompleteOpts.IncludeBriefComments);
-      assert(CCS && "Expected the CodeCompletionString to be non-null");
-      Items.items.push_back(ProcessCodeCompleteResult(Candidate, *CCS));
-      Candidates.pop();
-    }
-    std::reverse(Items.items.begin(), Items.items.end());
-  }
-
-  GlobalCodeCompletionAllocator &getAllocator() override { return *Allocator; }
-
-  CodeCompletionTUInfo &getCodeCompletionTUInfo() override { return CCTUInfo; }
-
-private:
-  bool fuzzyMatch(Sema &S, const CodeCompletionContext &CCCtx, StringRef Filter,
-                  CodeCompletionResult Result) {
-    switch (Result.Kind) {
-    case CodeCompletionResult::RK_Declaration:
-      if (auto *ID = Result.Declaration->getIdentifier())
-        return fuzzyMatch(Filter, ID->getName());
-      break;
-    case CodeCompletionResult::RK_Keyword:
-      return fuzzyMatch(Filter, Result.Keyword);
-    case CodeCompletionResult::RK_Macro:
-      return fuzzyMatch(Filter, Result.Macro->getName());
-    case CodeCompletionResult::RK_Pattern:
-      return fuzzyMatch(Filter, Result.Pattern->getTypedText());
-    }
-    auto *CCS = Result.CreateCodeCompletionString(
-        S, CCCtx, *Allocator, CCTUInfo, /*IncludeBriefComments=*/false);
-    return fuzzyMatch(Filter, CCS->getTypedText());
-  }
-
-  // Checks whether Target matches the Filter.
-  // Currently just requires a case-insensitive subsequence match.
-  // FIXME: make stricter and word-based: 'unique_ptr' should not match 'que'.
-  // FIXME: return a score to be incorporated into ranking.
-  static bool fuzzyMatch(StringRef Filter, StringRef Target) {
-    size_t TPos = 0;
-    for (char C : Filter) {
-      TPos = Target.find_lower(C, TPos);
-      if (TPos == StringRef::npos)
-        return false;
-    }
-    return true;
-  }
-
-  CompletionItem
-  ProcessCodeCompleteResult(const CompletionCandidate &Candidate,
-                            const CodeCompletionString &CCS) const {
-
-    // Adjust this to InsertTextFormat::Snippet iff we encounter a
-    // CK_Placeholder chunk in SnippetCompletionItemsCollector.
-    CompletionItem Item;
-    Item.insertTextFormat = InsertTextFormat::PlainText;
-
-    Item.documentation = getDocumentation(CCS);
-    Item.sortText = Candidate.sortText();
-
-    // Fill in the label, detail, insertText and filterText fields of the
-    // CompletionItem.
-    ProcessChunks(CCS, Item);
-
-    // Fill in the kind field of the CompletionItem.
-    Item.kind = getKind(Candidate.Result->Kind, Candidate.Result->CursorKind);
-
-    return Item;
-  }
-
-  virtual void ProcessChunks(const CodeCompletionString &CCS,
-                             CompletionItem &Item) const = 0;
-
-  clangd::CodeCompleteOptions ClangdOpts;
-  CompletionList &Items;
-  std::shared_ptr<clang::GlobalCodeCompletionAllocator> Allocator;
-  CodeCompletionTUInfo CCTUInfo;
-
-}; // CompletionItemsCollector
-
-bool isInformativeQualifierChunk(CodeCompletionString::Chunk const &Chunk) {
-  return Chunk.Kind == CodeCompletionString::CK_Informative &&
-         StringRef(Chunk.Text).endswith("::");
-}
-
-class PlainTextCompletionItemsCollector final
-    : public CompletionItemsCollector {
-
-public:
-  PlainTextCompletionItemsCollector(
-      const clangd::CodeCompleteOptions &CodeCompleteOpts,
-      CompletionList &Items)
-      : CompletionItemsCollector(CodeCompleteOpts, Items) {}
-
-private:
-  void ProcessChunks(const CodeCompletionString &CCS,
-                     CompletionItem &Item) const override {
-    for (const auto &Chunk : CCS) {
-      // Informative qualifier chunks only clutter completion results, skip
-      // them.
-      if (isInformativeQualifierChunk(Chunk))
-        continue;
-
-      switch (Chunk.Kind) {
-      case CodeCompletionString::CK_TypedText:
-        // There's always exactly one CK_TypedText chunk.
-        Item.insertText = Item.filterText = Chunk.Text;
-        Item.label += Chunk.Text;
-        break;
-      case CodeCompletionString::CK_ResultType:
-        assert(Item.detail.empty() && "Unexpected extraneous CK_ResultType");
-        Item.detail = Chunk.Text;
-        break;
-      case CodeCompletionString::CK_Optional:
-        break;
-      default:
-        Item.label += Chunk.Text;
-        break;
-      }
-    }
-  }
-}; // PlainTextCompletionItemsCollector
-
-class SnippetCompletionItemsCollector final : public CompletionItemsCollector {
-
-public:
-  SnippetCompletionItemsCollector(
-      const clangd::CodeCompleteOptions &CodeCompleteOpts,
-      CompletionList &Items)
-      : CompletionItemsCollector(CodeCompleteOpts, Items) {}
-
-private:
-  void ProcessChunks(const CodeCompletionString &CCS,
-                     CompletionItem &Item) const override {
-    unsigned ArgCount = 0;
-    for (const auto &Chunk : CCS) {
-      // Informative qualifier chunks only clutter completion results, skip
-      // them.
-      if (isInformativeQualifierChunk(Chunk))
-        continue;
-
-      switch (Chunk.Kind) {
-      case CodeCompletionString::CK_TypedText:
-        // The piece of text that the user is expected to type to match
-        // the code-completion string, typically a keyword or the name of
-        // a declarator or macro.
-        Item.filterText = Chunk.Text;
-        LLVM_FALLTHROUGH;
-      case CodeCompletionString::CK_Text:
-        // A piece of text that should be placed in the buffer,
-        // e.g., parentheses or a comma in a function call.
-        Item.label += Chunk.Text;
-        Item.insertText += Chunk.Text;
-        break;
-      case CodeCompletionString::CK_Optional:
-        // A code completion string that is entirely optional.
-        // For example, an optional code completion string that
-        // describes the default arguments in a function call.
-
-        // FIXME: Maybe add an option to allow presenting the optional chunks?
-        break;
-      case CodeCompletionString::CK_Placeholder:
-        // A string that acts as a placeholder for, e.g., a function call
-        // argument.
-        ++ArgCount;
-        Item.insertText += "${" + std::to_string(ArgCount) + ':' +
-                           escapeSnippet(Chunk.Text) + '}';
-        Item.label += Chunk.Text;
-        Item.insertTextFormat = InsertTextFormat::Snippet;
-        break;
-      case CodeCompletionString::CK_Informative:
-        // A piece of text that describes something about the result
-        // but should not be inserted into the buffer.
-        // For example, the word "const" for a const method, or the name of
-        // the base class for methods that are part of the base class.
-        Item.label += Chunk.Text;
-        // Don't put the informative chunks in the insertText.
-        break;
-      case CodeCompletionString::CK_ResultType:
-        // A piece of text that describes the type of an entity or,
-        // for functions and methods, the return type.
-        assert(Item.detail.empty() && "Unexpected extraneous CK_ResultType");
-        Item.detail = Chunk.Text;
-        break;
-      case CodeCompletionString::CK_CurrentParameter:
-        // A piece of text that describes the parameter that corresponds to
-        // the code-completion location within a function call, message send,
-        // macro invocation, etc.
-        //
-        // This should never be present while collecting completion items,
-        // only while collecting overload candidates.
-        llvm_unreachable("Unexpected CK_CurrentParameter while collecting "
-                         "CompletionItems");
-        break;
-      case CodeCompletionString::CK_LeftParen:
-        // A left parenthesis ('(').
-      case CodeCompletionString::CK_RightParen:
-        // A right parenthesis (')').
-      case CodeCompletionString::CK_LeftBracket:
-        // A left bracket ('[').
-      case CodeCompletionString::CK_RightBracket:
-        // A right bracket (']').
-      case CodeCompletionString::CK_LeftBrace:
-        // A left brace ('{').
-      case CodeCompletionString::CK_RightBrace:
-        // A right brace ('}').
-      case CodeCompletionString::CK_LeftAngle:
-        // A left angle bracket ('<').
-      case CodeCompletionString::CK_RightAngle:
-        // A right angle bracket ('>').
-      case CodeCompletionString::CK_Comma:
-        // A comma separator (',').
-      case CodeCompletionString::CK_Colon:
-        // A colon (':').
-      case CodeCompletionString::CK_SemiColon:
-        // A semicolon (';').
-      case CodeCompletionString::CK_Equal:
-        // An '=' sign.
-      case CodeCompletionString::CK_HorizontalSpace:
-        // Horizontal whitespace (' ').
-        Item.insertText += Chunk.Text;
-        Item.label += Chunk.Text;
-        break;
-      case CodeCompletionString::CK_VerticalSpace:
-        // Vertical whitespace ('\n' or '\r\n', depending on the
-        // platform).
-        Item.insertText += Chunk.Text;
-        // Don't even add a space to the label.
-        break;
-      }
-    }
-  }
-}; // SnippetCompletionItemsCollector
-
-class SignatureHelpCollector final : public CodeCompleteConsumer {
-
-public:
-  SignatureHelpCollector(const clang::CodeCompleteOptions &CodeCompleteOpts,
-                         SignatureHelp &SigHelp)
-      : CodeCompleteConsumer(CodeCompleteOpts, /*OutputIsBinary=*/false),
-        SigHelp(SigHelp),
-        Allocator(std::make_shared<clang::GlobalCodeCompletionAllocator>()),
-        CCTUInfo(Allocator) {}
-
-  void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
-                                 OverloadCandidate *Candidates,
-                                 unsigned NumCandidates) override {
-    SigHelp.signatures.reserve(NumCandidates);
-    // FIXME(rwols): How can we determine the "active overload candidate"?
-    // Right now the overloaded candidates seem to be provided in a "best fit"
-    // order, so I'm not too worried about this.
-    SigHelp.activeSignature = 0;
-    assert(CurrentArg <= (unsigned)std::numeric_limits<int>::max() &&
-           "too many arguments");
-    SigHelp.activeParameter = static_cast<int>(CurrentArg);
-    for (unsigned I = 0; I < NumCandidates; ++I) {
-      const auto &Candidate = Candidates[I];
-      const auto *CCS = Candidate.CreateSignatureString(
-          CurrentArg, S, *Allocator, CCTUInfo, true);
-      assert(CCS && "Expected the CodeCompletionString to be non-null");
-      SigHelp.signatures.push_back(ProcessOverloadCandidate(Candidate, *CCS));
-    }
-  }
-
-  GlobalCodeCompletionAllocator &getAllocator() override { return *Allocator; }
-
-  CodeCompletionTUInfo &getCodeCompletionTUInfo() override { return CCTUInfo; }
-
-private:
-  SignatureInformation
-  ProcessOverloadCandidate(const OverloadCandidate &Candidate,
-                           const CodeCompletionString &CCS) const {
-    SignatureInformation Result;
-    const char *ReturnType = nullptr;
-
-    Result.documentation = getDocumentation(CCS);
-
-    for (const auto &Chunk : CCS) {
-      switch (Chunk.Kind) {
-      case CodeCompletionString::CK_ResultType:
-        // A piece of text that describes the type of an entity or,
-        // for functions and methods, the return type.
-        assert(!ReturnType && "Unexpected CK_ResultType");
-        ReturnType = Chunk.Text;
-        break;
-      case CodeCompletionString::CK_Placeholder:
-        // A string that acts as a placeholder for, e.g., a function call
-        // argument.
-        // Intentional fallthrough here.
-      case CodeCompletionString::CK_CurrentParameter: {
-        // A piece of text that describes the parameter that corresponds to
-        // the code-completion location within a function call, message send,
-        // macro invocation, etc.
-        Result.label += Chunk.Text;
-        ParameterInformation Info;
-        Info.label = Chunk.Text;
-        Result.parameters.push_back(std::move(Info));
-        break;
-      }
-      case CodeCompletionString::CK_Optional: {
-        // The rest of the parameters are defaulted/optional.
-        assert(Chunk.Optional &&
-               "Expected the optional code completion string to be non-null.");
-        Result.label +=
-            getOptionalParameters(*Chunk.Optional, Result.parameters);
-        break;
-      }
-      case CodeCompletionString::CK_VerticalSpace:
-        break;
-      default:
-        Result.label += Chunk.Text;
-        break;
-      }
-    }
-    if (ReturnType) {
-      Result.label += " -> ";
-      Result.label += ReturnType;
-    }
-    return Result;
-  }
-
-  SignatureHelp &SigHelp;
-  std::shared_ptr<clang::GlobalCodeCompletionAllocator> Allocator;
-  CodeCompletionTUInfo CCTUInfo;
-
-}; // SignatureHelpCollector
-
-bool invokeCodeComplete(std::unique_ptr<CodeCompleteConsumer> Consumer,
-                        const clang::CodeCompleteOptions &Options,
-                        PathRef FileName,
-                        const tooling::CompileCommand &Command,
-                        PrecompiledPreamble const *Preamble, StringRef Contents,
-                        Position Pos, IntrusiveRefCntPtr<vfs::FileSystem> VFS,
-                        std::shared_ptr<PCHContainerOperations> PCHs,
-                        clangd::Logger &Logger) {
-  std::vector<const char *> ArgStrs;
-  for (const auto &S : Command.CommandLine)
-    ArgStrs.push_back(S.c_str());
-
-  VFS->setCurrentWorkingDirectory(Command.Directory);
-
-  std::unique_ptr<CompilerInvocation> CI;
-  EmptyDiagsConsumer DummyDiagsConsumer;
-  {
-    IntrusiveRefCntPtr<DiagnosticsEngine> CommandLineDiagsEngine =
-        CompilerInstance::createDiagnostics(new DiagnosticOptions,
-                                            &DummyDiagsConsumer, false);
-    CI = createCompilerInvocation(ArgStrs, CommandLineDiagsEngine, VFS);
-  }
-  assert(CI && "Couldn't create CompilerInvocation");
-
-  std::unique_ptr<llvm::MemoryBuffer> ContentsBuffer =
-      llvm::MemoryBuffer::getMemBufferCopy(Contents, FileName);
-
-  // Attempt to reuse the PCH from precompiled preamble, if it was built.
-  if (Preamble) {
-    auto Bounds =
-        ComputePreambleBounds(*CI->getLangOpts(), ContentsBuffer.get(), 0);
-    if (!Preamble->CanReuse(*CI, ContentsBuffer.get(), Bounds, VFS.get()))
-      Preamble = nullptr;
-  }
-
-  auto Clang = prepareCompilerInstance(
-      std::move(CI), Preamble, std::move(ContentsBuffer), std::move(PCHs),
-      std::move(VFS), DummyDiagsConsumer);
-  auto &DiagOpts = Clang->getDiagnosticOpts();
-  DiagOpts.IgnoreWarnings = true;
-
-  auto &FrontendOpts = Clang->getFrontendOpts();
-  FrontendOpts.SkipFunctionBodies = true;
-  FrontendOpts.CodeCompleteOpts = Options;
-  FrontendOpts.CodeCompletionAt.FileName = FileName;
-  FrontendOpts.CodeCompletionAt.Line = Pos.line + 1;
-  FrontendOpts.CodeCompletionAt.Column = Pos.character + 1;
-
-  Clang->setCodeCompletionConsumer(Consumer.release());
-
-  SyntaxOnlyAction Action;
-  if (!Action.BeginSourceFile(*Clang, Clang->getFrontendOpts().Inputs[0])) {
-    Logger.log("BeginSourceFile() failed when running codeComplete for " +
-               FileName);
-    return false;
-  }
-  if (!Action.Execute()) {
-    Logger.log("Execute() failed when running codeComplete for " + FileName);
-    return false;
-  }
-
-  Action.EndSourceFile();
-
-  return true;
-}
-
-} // namespace
-
-clang::CodeCompleteOptions
-clangd::CodeCompleteOptions::getClangCompleteOpts() const {
-  clang::CodeCompleteOptions Result;
-  Result.IncludeCodePatterns = EnableSnippets && IncludeCodePatterns;
-  Result.IncludeMacros = IncludeMacros;
-  Result.IncludeGlobals = IncludeGlobals;
-  Result.IncludeBriefComments = IncludeBriefComments;
-
-  return Result;
-}
-
-CompletionList
-clangd::codeComplete(PathRef FileName, const tooling::CompileCommand &Command,
-                     PrecompiledPreamble const *Preamble, StringRef Contents,
-                     Position Pos, IntrusiveRefCntPtr<vfs::FileSystem> VFS,
-                     std::shared_ptr<PCHContainerOperations> PCHs,
-                     clangd::CodeCompleteOptions Opts, clangd::Logger &Logger) {
-  CompletionList Results;
-  std::unique_ptr<CodeCompleteConsumer> Consumer;
-  if (Opts.EnableSnippets) {
-    Consumer =
-        llvm::make_unique<SnippetCompletionItemsCollector>(Opts, Results);
-  } else {
-    Consumer =
-        llvm::make_unique<PlainTextCompletionItemsCollector>(Opts, Results);
-  }
-  invokeCodeComplete(std::move(Consumer), Opts.getClangCompleteOpts(), FileName,
-                     Command, Preamble, Contents, Pos, std::move(VFS),
-                     std::move(PCHs), Logger);
-  return Results;
-}
-
-SignatureHelp
-clangd::signatureHelp(PathRef FileName, const tooling::CompileCommand &Command,
-                      PrecompiledPreamble const *Preamble, StringRef Contents,
-                      Position Pos, IntrusiveRefCntPtr<vfs::FileSystem> VFS,
-                      std::shared_ptr<PCHContainerOperations> PCHs,
-                      clangd::Logger &Logger) {
-  SignatureHelp Result;
-  clang::CodeCompleteOptions Options;
-  Options.IncludeGlobals = false;
-  Options.IncludeMacros = false;
-  Options.IncludeCodePatterns = false;
-  Options.IncludeBriefComments = true;
-  invokeCodeComplete(llvm::make_unique<SignatureHelpCollector>(Options, Result),
-                     Options, FileName, Command, Preamble, Contents, Pos,
-                     std::move(VFS), std::move(PCHs), Logger);
-  return Result;
-}
-
 void clangd::dumpAST(ParsedAST &AST, llvm::raw_ostream &OS) {
   AST.getASTContext().getTranslationUnitDecl()->dump(OS, true);
 }
@@ -946,7 +198,7 @@ ParsedAST::Build(std::unique_ptr<clang::
 
   // UnitDiagsConsumer is local, we can not store it in CompilerInstance that
   // has a longer lifetime.
-  Clang->getDiagnostics().setClient(new EmptyDiagsConsumer);
+  Clang->getDiagnostics().setClient(new IgnoreDiagnostics);
 
   std::vector<const Decl *> ParsedDecls = Action->takeTopLevelDecls();
   return ParsedAST(std::move(Preamble), std::move(Clang), std::move(Action),
@@ -1302,11 +554,14 @@ CppFile::deferRebuild(StringRef NewConte
     {
       // FIXME(ibiryukov): store diagnostics from CommandLine when we start
       // reporting them.
-      EmptyDiagsConsumer CommandLineDiagsConsumer;
+      IgnoreDiagnostics IgnoreDiagnostics;
       IntrusiveRefCntPtr<DiagnosticsEngine> CommandLineDiagsEngine =
           CompilerInstance::createDiagnostics(new DiagnosticOptions,
-                                              &CommandLineDiagsConsumer, false);
-      CI = createCompilerInvocation(ArgStrs, CommandLineDiagsEngine, VFS);
+                                              &IgnoreDiagnostics, false);
+      CI =
+          createInvocationFromCommandLine(ArgStrs, CommandLineDiagsEngine, VFS);
+      // createInvocationFromCommandLine sets DisableFree.
+      CI->getFrontendOpts().DisableFree = false;
     }
     assert(CI && "Couldn't create CompilerInvocation");
 

Modified: clang-tools-extra/trunk/clangd/ClangdUnit.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdUnit.h?rev=319655&r1=319654&r2=319655&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/ClangdUnit.h (original)
+++ clang-tools-extra/trunk/clangd/ClangdUnit.h Mon Dec  4 05:49:59 2017
@@ -256,56 +256,6 @@ private:
   clangd::Logger &Logger;
 };
 
-struct CodeCompleteOptions {
-  /// Returns options that can be passed to clang's completion engine.
-  clang::CodeCompleteOptions getClangCompleteOpts() const;
-
-  /// When true, completion items will contain expandable code snippets in
-  /// completion (e.g.  `return ${1:expression}` or `foo(${1:int a}, ${2:int
-  /// b})).
-  bool EnableSnippets = false;
-
-  /// Add code patterns to completion results.
-  /// If EnableSnippets is false, this options is ignored and code patterns will
-  /// always be omitted.
-  bool IncludeCodePatterns = true;
-
-  /// Add macros to code completion results.
-  bool IncludeMacros = true;
-
-  /// Add globals to code completion results.
-  bool IncludeGlobals = true;
-
-  /// Add brief comments to completion items, if available.
-  /// FIXME(ibiryukov): it looks like turning this option on significantly slows
-  /// down completion, investigate if it can be made faster.
-  bool IncludeBriefComments = true;
-
-  /// Include results that are not legal completions in the current context.
-  /// For example, private members are usually inaccessible.
-  bool IncludeIneligibleResults = false;
-
-  /// Limit the number of results returned (0 means no limit).
-  /// If more results are available, we set CompletionList.isIncomplete.
-  size_t Limit = 0;
-};
-
-/// Get code completions at a specified \p Pos in \p FileName.
-CompletionList
-codeComplete(PathRef FileName, const tooling::CompileCommand &Command,
-             PrecompiledPreamble const *Preamble, StringRef Contents,
-             Position Pos, IntrusiveRefCntPtr<vfs::FileSystem> VFS,
-             std::shared_ptr<PCHContainerOperations> PCHs,
-             clangd::CodeCompleteOptions Opts, clangd::Logger &Logger);
-
-/// Get signature help at a specified \p Pos in \p FileName.
-SignatureHelp signatureHelp(PathRef FileName,
-                            const tooling::CompileCommand &Command,
-                            PrecompiledPreamble const *Preamble,
-                            StringRef Contents, Position Pos,
-                            IntrusiveRefCntPtr<vfs::FileSystem> VFS,
-                            std::shared_ptr<PCHContainerOperations> PCHs,
-                            clangd::Logger &Logger);
 
 /// Get the beginning SourceLocation at a specified \p Pos.
 SourceLocation getBeginningOfIdentifier(ParsedAST &Unit, const Position &Pos,

Added: clang-tools-extra/trunk/clangd/CodeComplete.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/CodeComplete.cpp?rev=319655&view=auto
==============================================================================
--- clang-tools-extra/trunk/clangd/CodeComplete.cpp (added)
+++ clang-tools-extra/trunk/clangd/CodeComplete.cpp Mon Dec  4 05:49:59 2017
@@ -0,0 +1,706 @@
+//===--- CodeComplete.cpp ---------------------------------------*- C++-*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+//
+// AST-based completions are provided using the completion hooks in Sema.
+//
+// Signature help works in a similar way as code completion, but it is simpler
+// as there are typically fewer candidates.
+//
+//===---------------------------------------------------------------------===//
+
+#include "CodeComplete.h"
+#include "Compiler.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FrontendActions.h"
+#include "clang/Sema/CodeCompleteConsumer.h"
+#include "clang/Sema/Sema.h"
+#include <queue>
+
+namespace clang {
+namespace clangd {
+namespace {
+
+CompletionItemKind getKindOfDecl(CXCursorKind CursorKind) {
+  switch (CursorKind) {
+  case CXCursor_MacroInstantiation:
+  case CXCursor_MacroDefinition:
+    return CompletionItemKind::Text;
+  case CXCursor_CXXMethod:
+    return CompletionItemKind::Method;
+  case CXCursor_FunctionDecl:
+  case CXCursor_FunctionTemplate:
+    return CompletionItemKind::Function;
+  case CXCursor_Constructor:
+  case CXCursor_Destructor:
+    return CompletionItemKind::Constructor;
+  case CXCursor_FieldDecl:
+    return CompletionItemKind::Field;
+  case CXCursor_VarDecl:
+  case CXCursor_ParmDecl:
+    return CompletionItemKind::Variable;
+  case CXCursor_ClassDecl:
+  case CXCursor_StructDecl:
+  case CXCursor_UnionDecl:
+  case CXCursor_ClassTemplate:
+  case CXCursor_ClassTemplatePartialSpecialization:
+    return CompletionItemKind::Class;
+  case CXCursor_Namespace:
+  case CXCursor_NamespaceAlias:
+  case CXCursor_NamespaceRef:
+    return CompletionItemKind::Module;
+  case CXCursor_EnumConstantDecl:
+    return CompletionItemKind::Value;
+  case CXCursor_EnumDecl:
+    return CompletionItemKind::Enum;
+  case CXCursor_TypeAliasDecl:
+  case CXCursor_TypeAliasTemplateDecl:
+  case CXCursor_TypedefDecl:
+  case CXCursor_MemberRef:
+  case CXCursor_TypeRef:
+    return CompletionItemKind::Reference;
+  default:
+    return CompletionItemKind::Missing;
+  }
+}
+
+CompletionItemKind getKind(CodeCompletionResult::ResultKind ResKind,
+                           CXCursorKind CursorKind) {
+  switch (ResKind) {
+  case CodeCompletionResult::RK_Declaration:
+    return getKindOfDecl(CursorKind);
+  case CodeCompletionResult::RK_Keyword:
+    return CompletionItemKind::Keyword;
+  case CodeCompletionResult::RK_Macro:
+    return CompletionItemKind::Text; // unfortunately, there's no 'Macro'
+                                     // completion items in LSP.
+  case CodeCompletionResult::RK_Pattern:
+    return CompletionItemKind::Snippet;
+  }
+  llvm_unreachable("Unhandled CodeCompletionResult::ResultKind.");
+}
+
+std::string escapeSnippet(const llvm::StringRef Text) {
+  std::string Result;
+  Result.reserve(Text.size()); // Assume '$', '}' and '\\' are rare.
+  for (const auto Character : Text) {
+    if (Character == '$' || Character == '}' || Character == '\\')
+      Result.push_back('\\');
+    Result.push_back(Character);
+  }
+  return Result;
+}
+
+std::string getDocumentation(const CodeCompletionString &CCS) {
+  // Things like __attribute__((nonnull(1,3))) and [[noreturn]]. Present this
+  // information in the documentation field.
+  std::string Result;
+  const unsigned AnnotationCount = CCS.getAnnotationCount();
+  if (AnnotationCount > 0) {
+    Result += "Annotation";
+    if (AnnotationCount == 1) {
+      Result += ": ";
+    } else /* AnnotationCount > 1 */ {
+      Result += "s: ";
+    }
+    for (unsigned I = 0; I < AnnotationCount; ++I) {
+      Result += CCS.getAnnotation(I);
+      Result.push_back(I == AnnotationCount - 1 ? '\n' : ' ');
+    }
+  }
+  // Add brief documentation (if there is any).
+  if (CCS.getBriefComment() != nullptr) {
+    if (!Result.empty()) {
+      // This means we previously added annotations. Add an extra newline
+      // character to make the annotations stand out.
+      Result.push_back('\n');
+    }
+    Result += CCS.getBriefComment();
+  }
+  return Result;
+}
+
+/// Get the optional chunk as a string. This function is possibly recursive.
+///
+/// The parameter info for each parameter is appended to the Parameters.
+std::string
+getOptionalParameters(const CodeCompletionString &CCS,
+                      std::vector<ParameterInformation> &Parameters) {
+  std::string Result;
+  for (const auto &Chunk : CCS) {
+    switch (Chunk.Kind) {
+    case CodeCompletionString::CK_Optional:
+      assert(Chunk.Optional &&
+             "Expected the optional code completion string to be non-null.");
+      Result += getOptionalParameters(*Chunk.Optional, Parameters);
+      break;
+    case CodeCompletionString::CK_VerticalSpace:
+      break;
+    case CodeCompletionString::CK_Placeholder:
+      // A string that acts as a placeholder for, e.g., a function call
+      // argument.
+      // Intentional fallthrough here.
+    case CodeCompletionString::CK_CurrentParameter: {
+      // A piece of text that describes the parameter that corresponds to
+      // the code-completion location within a function call, message send,
+      // macro invocation, etc.
+      Result += Chunk.Text;
+      ParameterInformation Info;
+      Info.label = Chunk.Text;
+      Parameters.push_back(std::move(Info));
+      break;
+    }
+    default:
+      Result += Chunk.Text;
+      break;
+    }
+  }
+  return Result;
+}
+
+
+/// A scored code completion result.
+/// It may be promoted to a CompletionItem if it's among the top-ranked results.
+struct CompletionCandidate {
+  CompletionCandidate(CodeCompletionResult &Result)
+      : Result(&Result), Score(score(Result)) {}
+
+  CodeCompletionResult *Result;
+  float Score; // 0 to 1, higher is better.
+
+  // Comparison reflects rank: better candidates are smaller.
+  bool operator<(const CompletionCandidate &C) const {
+    if (Score != C.Score)
+      return Score > C.Score;
+    return *Result < *C.Result;
+  }
+
+  // Returns a string that sorts in the same order as operator<, for LSP.
+  // Conceptually, this is [-Score, Name]. We convert -Score to an integer, and
+  // hex-encode it for readability. Example: [0.5, "foo"] -> "41000000foo"
+  std::string sortText() const {
+    std::string S, NameStorage;
+    llvm::raw_string_ostream OS(S);
+    write_hex(OS, encodeFloat(-Score), llvm::HexPrintStyle::Lower,
+              /*Width=*/2 * sizeof(Score));
+    OS << Result->getOrderedName(NameStorage);
+    return OS.str();
+  }
+
+private:
+  static float score(const CodeCompletionResult &Result) {
+    // Priority 80 is a really bad score.
+    float Score = 1 - std::min<float>(80, Result.Priority) / 80;
+
+    switch (static_cast<CXAvailabilityKind>(Result.Availability)) {
+    case CXAvailability_Available:
+      // No penalty.
+      break;
+    case CXAvailability_Deprecated:
+      Score *= 0.1f;
+      break;
+    case CXAvailability_NotAccessible:
+    case CXAvailability_NotAvailable:
+      Score = 0;
+      break;
+    }
+    return Score;
+  }
+
+  // Produces an integer that sorts in the same order as F.
+  // That is: a < b <==> encodeFloat(a) < encodeFloat(b).
+  static uint32_t encodeFloat(float F) {
+    static_assert(std::numeric_limits<float>::is_iec559, "");
+    static_assert(sizeof(float) == sizeof(uint32_t), "");
+    constexpr uint32_t TopBit = ~(~uint32_t{0} >> 1);
+
+    // Get the bits of the float. Endianness is the same as for integers.
+    uint32_t U;
+    memcpy(&U, &F, sizeof(float));
+    // IEEE 754 floats compare like sign-magnitude integers.
+    if (U & TopBit)    // Negative float.
+      return 0 - U;    // Map onto the low half of integers, order reversed.
+    return U + TopBit; // Positive floats map onto the high half of integers.
+  }
+};
+
+class CompletionItemsCollector : public CodeCompleteConsumer {
+public:
+  CompletionItemsCollector(const CodeCompleteOptions &CodeCompleteOpts,
+                           CompletionList &Items)
+      : CodeCompleteConsumer(CodeCompleteOpts.getClangCompleteOpts(),
+                             /*OutputIsBinary=*/false),
+        ClangdOpts(CodeCompleteOpts), Items(Items),
+        Allocator(std::make_shared<clang::GlobalCodeCompletionAllocator>()),
+        CCTUInfo(Allocator) {}
+
+  void ProcessCodeCompleteResults(Sema &S, CodeCompletionContext Context,
+                                  CodeCompletionResult *Results,
+                                  unsigned NumResults) override final {
+    StringRef Filter = S.getPreprocessor().getCodeCompletionFilter();
+    std::priority_queue<CompletionCandidate> Candidates;
+    for (unsigned I = 0; I < NumResults; ++I) {
+      auto &Result = Results[I];
+      if (!ClangdOpts.IncludeIneligibleResults &&
+          (Result.Availability == CXAvailability_NotAvailable ||
+           Result.Availability == CXAvailability_NotAccessible))
+        continue;
+      if (!Filter.empty() && !fuzzyMatch(S, Context, Filter, Result))
+        continue;
+      Candidates.emplace(Result);
+      if (ClangdOpts.Limit && Candidates.size() > ClangdOpts.Limit) {
+        Candidates.pop();
+        Items.isIncomplete = true;
+      }
+    }
+    while (!Candidates.empty()) {
+      auto &Candidate = Candidates.top();
+      const auto *CCS = Candidate.Result->CreateCodeCompletionString(
+          S, Context, *Allocator, CCTUInfo,
+          CodeCompleteOpts.IncludeBriefComments);
+      assert(CCS && "Expected the CodeCompletionString to be non-null");
+      Items.items.push_back(ProcessCodeCompleteResult(Candidate, *CCS));
+      Candidates.pop();
+    }
+    std::reverse(Items.items.begin(), Items.items.end());
+  }
+
+  GlobalCodeCompletionAllocator &getAllocator() override { return *Allocator; }
+
+  CodeCompletionTUInfo &getCodeCompletionTUInfo() override { return CCTUInfo; }
+
+private:
+  bool fuzzyMatch(Sema &S, const CodeCompletionContext &CCCtx, StringRef Filter,
+                  CodeCompletionResult Result) {
+    switch (Result.Kind) {
+    case CodeCompletionResult::RK_Declaration:
+      if (auto *ID = Result.Declaration->getIdentifier())
+        return fuzzyMatch(Filter, ID->getName());
+      break;
+    case CodeCompletionResult::RK_Keyword:
+      return fuzzyMatch(Filter, Result.Keyword);
+    case CodeCompletionResult::RK_Macro:
+      return fuzzyMatch(Filter, Result.Macro->getName());
+    case CodeCompletionResult::RK_Pattern:
+      return fuzzyMatch(Filter, Result.Pattern->getTypedText());
+    }
+    auto *CCS = Result.CreateCodeCompletionString(
+        S, CCCtx, *Allocator, CCTUInfo, /*IncludeBriefComments=*/false);
+    return fuzzyMatch(Filter, CCS->getTypedText());
+  }
+
+  // Checks whether Target matches the Filter.
+  // Currently just requires a case-insensitive subsequence match.
+  // FIXME: make stricter and word-based: 'unique_ptr' should not match 'que'.
+  // FIXME: return a score to be incorporated into ranking.
+  static bool fuzzyMatch(StringRef Filter, StringRef Target) {
+    size_t TPos = 0;
+    for (char C : Filter) {
+      TPos = Target.find_lower(C, TPos);
+      if (TPos == StringRef::npos)
+        return false;
+    }
+    return true;
+  }
+
+  CompletionItem
+  ProcessCodeCompleteResult(const CompletionCandidate &Candidate,
+                            const CodeCompletionString &CCS) const {
+
+    // Adjust this to InsertTextFormat::Snippet iff we encounter a
+    // CK_Placeholder chunk in SnippetCompletionItemsCollector.
+    CompletionItem Item;
+    Item.insertTextFormat = InsertTextFormat::PlainText;
+
+    Item.documentation = getDocumentation(CCS);
+    Item.sortText = Candidate.sortText();
+
+    // Fill in the label, detail, insertText and filterText fields of the
+    // CompletionItem.
+    ProcessChunks(CCS, Item);
+
+    // Fill in the kind field of the CompletionItem.
+    Item.kind = getKind(Candidate.Result->Kind, Candidate.Result->CursorKind);
+
+    return Item;
+  }
+
+  virtual void ProcessChunks(const CodeCompletionString &CCS,
+                             CompletionItem &Item) const = 0;
+
+  CodeCompleteOptions ClangdOpts;
+  CompletionList &Items;
+  std::shared_ptr<clang::GlobalCodeCompletionAllocator> Allocator;
+  CodeCompletionTUInfo CCTUInfo;
+
+}; // CompletionItemsCollector
+
+bool isInformativeQualifierChunk(CodeCompletionString::Chunk const &Chunk) {
+  return Chunk.Kind == CodeCompletionString::CK_Informative &&
+         StringRef(Chunk.Text).endswith("::");
+}
+
+class PlainTextCompletionItemsCollector final
+    : public CompletionItemsCollector {
+
+public:
+  PlainTextCompletionItemsCollector(
+      const CodeCompleteOptions &CodeCompleteOpts,
+      CompletionList &Items)
+      : CompletionItemsCollector(CodeCompleteOpts, Items) {}
+
+private:
+  void ProcessChunks(const CodeCompletionString &CCS,
+                     CompletionItem &Item) const override {
+    for (const auto &Chunk : CCS) {
+      // Informative qualifier chunks only clutter completion results, skip
+      // them.
+      if (isInformativeQualifierChunk(Chunk))
+        continue;
+
+      switch (Chunk.Kind) {
+      case CodeCompletionString::CK_TypedText:
+        // There's always exactly one CK_TypedText chunk.
+        Item.insertText = Item.filterText = Chunk.Text;
+        Item.label += Chunk.Text;
+        break;
+      case CodeCompletionString::CK_ResultType:
+        assert(Item.detail.empty() && "Unexpected extraneous CK_ResultType");
+        Item.detail = Chunk.Text;
+        break;
+      case CodeCompletionString::CK_Optional:
+        break;
+      default:
+        Item.label += Chunk.Text;
+        break;
+      }
+    }
+  }
+}; // PlainTextCompletionItemsCollector
+
+class SnippetCompletionItemsCollector final : public CompletionItemsCollector {
+
+public:
+  SnippetCompletionItemsCollector(
+      const CodeCompleteOptions &CodeCompleteOpts,
+      CompletionList &Items)
+      : CompletionItemsCollector(CodeCompleteOpts, Items) {}
+
+private:
+  void ProcessChunks(const CodeCompletionString &CCS,
+                     CompletionItem &Item) const override {
+    unsigned ArgCount = 0;
+    for (const auto &Chunk : CCS) {
+      // Informative qualifier chunks only clutter completion results, skip
+      // them.
+      if (isInformativeQualifierChunk(Chunk))
+        continue;
+
+      switch (Chunk.Kind) {
+      case CodeCompletionString::CK_TypedText:
+        // The piece of text that the user is expected to type to match
+        // the code-completion string, typically a keyword or the name of
+        // a declarator or macro.
+        Item.filterText = Chunk.Text;
+        LLVM_FALLTHROUGH;
+      case CodeCompletionString::CK_Text:
+        // A piece of text that should be placed in the buffer,
+        // e.g., parentheses or a comma in a function call.
+        Item.label += Chunk.Text;
+        Item.insertText += Chunk.Text;
+        break;
+      case CodeCompletionString::CK_Optional:
+        // A code completion string that is entirely optional.
+        // For example, an optional code completion string that
+        // describes the default arguments in a function call.
+
+        // FIXME: Maybe add an option to allow presenting the optional chunks?
+        break;
+      case CodeCompletionString::CK_Placeholder:
+        // A string that acts as a placeholder for, e.g., a function call
+        // argument.
+        ++ArgCount;
+        Item.insertText += "${" + std::to_string(ArgCount) + ':' +
+                           escapeSnippet(Chunk.Text) + '}';
+        Item.label += Chunk.Text;
+        Item.insertTextFormat = InsertTextFormat::Snippet;
+        break;
+      case CodeCompletionString::CK_Informative:
+        // A piece of text that describes something about the result
+        // but should not be inserted into the buffer.
+        // For example, the word "const" for a const method, or the name of
+        // the base class for methods that are part of the base class.
+        Item.label += Chunk.Text;
+        // Don't put the informative chunks in the insertText.
+        break;
+      case CodeCompletionString::CK_ResultType:
+        // A piece of text that describes the type of an entity or,
+        // for functions and methods, the return type.
+        assert(Item.detail.empty() && "Unexpected extraneous CK_ResultType");
+        Item.detail = Chunk.Text;
+        break;
+      case CodeCompletionString::CK_CurrentParameter:
+        // A piece of text that describes the parameter that corresponds to
+        // the code-completion location within a function call, message send,
+        // macro invocation, etc.
+        //
+        // This should never be present while collecting completion items,
+        // only while collecting overload candidates.
+        llvm_unreachable("Unexpected CK_CurrentParameter while collecting "
+                         "CompletionItems");
+        break;
+      case CodeCompletionString::CK_LeftParen:
+        // A left parenthesis ('(').
+      case CodeCompletionString::CK_RightParen:
+        // A right parenthesis (')').
+      case CodeCompletionString::CK_LeftBracket:
+        // A left bracket ('[').
+      case CodeCompletionString::CK_RightBracket:
+        // A right bracket (']').
+      case CodeCompletionString::CK_LeftBrace:
+        // A left brace ('{').
+      case CodeCompletionString::CK_RightBrace:
+        // A right brace ('}').
+      case CodeCompletionString::CK_LeftAngle:
+        // A left angle bracket ('<').
+      case CodeCompletionString::CK_RightAngle:
+        // A right angle bracket ('>').
+      case CodeCompletionString::CK_Comma:
+        // A comma separator (',').
+      case CodeCompletionString::CK_Colon:
+        // A colon (':').
+      case CodeCompletionString::CK_SemiColon:
+        // A semicolon (';').
+      case CodeCompletionString::CK_Equal:
+        // An '=' sign.
+      case CodeCompletionString::CK_HorizontalSpace:
+        // Horizontal whitespace (' ').
+        Item.insertText += Chunk.Text;
+        Item.label += Chunk.Text;
+        break;
+      case CodeCompletionString::CK_VerticalSpace:
+        // Vertical whitespace ('\n' or '\r\n', depending on the
+        // platform).
+        Item.insertText += Chunk.Text;
+        // Don't even add a space to the label.
+        break;
+      }
+    }
+  }
+}; // SnippetCompletionItemsCollector
+
+class SignatureHelpCollector final : public CodeCompleteConsumer {
+
+public:
+  SignatureHelpCollector(const clang::CodeCompleteOptions &CodeCompleteOpts,
+                         SignatureHelp &SigHelp)
+      : CodeCompleteConsumer(CodeCompleteOpts, /*OutputIsBinary=*/false),
+        SigHelp(SigHelp),
+        Allocator(std::make_shared<clang::GlobalCodeCompletionAllocator>()),
+        CCTUInfo(Allocator) {}
+
+  void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
+                                 OverloadCandidate *Candidates,
+                                 unsigned NumCandidates) override {
+    SigHelp.signatures.reserve(NumCandidates);
+    // FIXME(rwols): How can we determine the "active overload candidate"?
+    // Right now the overloaded candidates seem to be provided in a "best fit"
+    // order, so I'm not too worried about this.
+    SigHelp.activeSignature = 0;
+    assert(CurrentArg <= (unsigned)std::numeric_limits<int>::max() &&
+           "too many arguments");
+    SigHelp.activeParameter = static_cast<int>(CurrentArg);
+    for (unsigned I = 0; I < NumCandidates; ++I) {
+      const auto &Candidate = Candidates[I];
+      const auto *CCS = Candidate.CreateSignatureString(
+          CurrentArg, S, *Allocator, CCTUInfo, true);
+      assert(CCS && "Expected the CodeCompletionString to be non-null");
+      SigHelp.signatures.push_back(ProcessOverloadCandidate(Candidate, *CCS));
+    }
+  }
+
+  GlobalCodeCompletionAllocator &getAllocator() override { return *Allocator; }
+
+  CodeCompletionTUInfo &getCodeCompletionTUInfo() override { return CCTUInfo; }
+
+private:
+  SignatureInformation
+  ProcessOverloadCandidate(const OverloadCandidate &Candidate,
+                           const CodeCompletionString &CCS) const {
+    SignatureInformation Result;
+    const char *ReturnType = nullptr;
+
+    Result.documentation = getDocumentation(CCS);
+
+    for (const auto &Chunk : CCS) {
+      switch (Chunk.Kind) {
+      case CodeCompletionString::CK_ResultType:
+        // A piece of text that describes the type of an entity or,
+        // for functions and methods, the return type.
+        assert(!ReturnType && "Unexpected CK_ResultType");
+        ReturnType = Chunk.Text;
+        break;
+      case CodeCompletionString::CK_Placeholder:
+        // A string that acts as a placeholder for, e.g., a function call
+        // argument.
+        // Intentional fallthrough here.
+      case CodeCompletionString::CK_CurrentParameter: {
+        // A piece of text that describes the parameter that corresponds to
+        // the code-completion location within a function call, message send,
+        // macro invocation, etc.
+        Result.label += Chunk.Text;
+        ParameterInformation Info;
+        Info.label = Chunk.Text;
+        Result.parameters.push_back(std::move(Info));
+        break;
+      }
+      case CodeCompletionString::CK_Optional: {
+        // The rest of the parameters are defaulted/optional.
+        assert(Chunk.Optional &&
+               "Expected the optional code completion string to be non-null.");
+        Result.label +=
+            getOptionalParameters(*Chunk.Optional, Result.parameters);
+        break;
+      }
+      case CodeCompletionString::CK_VerticalSpace:
+        break;
+      default:
+        Result.label += Chunk.Text;
+        break;
+      }
+    }
+    if (ReturnType) {
+      Result.label += " -> ";
+      Result.label += ReturnType;
+    }
+    return Result;
+  }
+
+  SignatureHelp &SigHelp;
+  std::shared_ptr<clang::GlobalCodeCompletionAllocator> Allocator;
+  CodeCompletionTUInfo CCTUInfo;
+
+}; // SignatureHelpCollector
+
+bool invokeCodeComplete(std::unique_ptr<CodeCompleteConsumer> Consumer,
+                        const clang::CodeCompleteOptions &Options,
+                        PathRef FileName,
+                        const tooling::CompileCommand &Command,
+                        PrecompiledPreamble const *Preamble, StringRef Contents,
+                        Position Pos, IntrusiveRefCntPtr<vfs::FileSystem> VFS,
+                        std::shared_ptr<PCHContainerOperations> PCHs,
+                        Logger &Logger) {
+  std::vector<const char *> ArgStrs;
+  for (const auto &S : Command.CommandLine)
+    ArgStrs.push_back(S.c_str());
+
+  VFS->setCurrentWorkingDirectory(Command.Directory);
+
+  IgnoreDiagnostics DummyDiagsConsumer;
+  auto CI = createInvocationFromCommandLine(
+      ArgStrs,
+      CompilerInstance::createDiagnostics(new DiagnosticOptions,
+                                          &DummyDiagsConsumer, false),
+      VFS);
+  assert(CI && "Couldn't create CompilerInvocation");
+
+  std::unique_ptr<llvm::MemoryBuffer> ContentsBuffer =
+      llvm::MemoryBuffer::getMemBufferCopy(Contents, FileName);
+
+  // Attempt to reuse the PCH from precompiled preamble, if it was built.
+  if (Preamble) {
+    auto Bounds =
+        ComputePreambleBounds(*CI->getLangOpts(), ContentsBuffer.get(), 0);
+    if (!Preamble->CanReuse(*CI, ContentsBuffer.get(), Bounds, VFS.get()))
+      Preamble = nullptr;
+  }
+
+  auto Clang = prepareCompilerInstance(
+      std::move(CI), Preamble, std::move(ContentsBuffer), std::move(PCHs),
+      std::move(VFS), DummyDiagsConsumer);
+  auto &DiagOpts = Clang->getDiagnosticOpts();
+  DiagOpts.IgnoreWarnings = true;
+
+  auto &FrontendOpts = Clang->getFrontendOpts();
+  FrontendOpts.SkipFunctionBodies = true;
+  FrontendOpts.CodeCompleteOpts = Options;
+  FrontendOpts.CodeCompletionAt.FileName = FileName;
+  FrontendOpts.CodeCompletionAt.Line = Pos.line + 1;
+  FrontendOpts.CodeCompletionAt.Column = Pos.character + 1;
+
+  Clang->setCodeCompletionConsumer(Consumer.release());
+
+  SyntaxOnlyAction Action;
+  if (!Action.BeginSourceFile(*Clang, Clang->getFrontendOpts().Inputs[0])) {
+    Logger.log("BeginSourceFile() failed when running codeComplete for " +
+               FileName);
+    return false;
+  }
+  if (!Action.Execute()) {
+    Logger.log("Execute() failed when running codeComplete for " + FileName);
+    return false;
+  }
+
+  Action.EndSourceFile();
+
+  return true;
+}
+
+} // namespace
+
+clang::CodeCompleteOptions CodeCompleteOptions::getClangCompleteOpts() const {
+  clang::CodeCompleteOptions Result;
+  Result.IncludeCodePatterns = EnableSnippets && IncludeCodePatterns;
+  Result.IncludeMacros = IncludeMacros;
+  Result.IncludeGlobals = IncludeGlobals;
+  Result.IncludeBriefComments = IncludeBriefComments;
+
+  return Result;
+}
+
+CompletionList codeComplete(PathRef FileName,
+                            const tooling::CompileCommand &Command,
+                            PrecompiledPreamble const *Preamble,
+                            StringRef Contents, Position Pos,
+                            IntrusiveRefCntPtr<vfs::FileSystem> VFS,
+                            std::shared_ptr<PCHContainerOperations> PCHs,
+                            CodeCompleteOptions Opts, Logger &Logger) {
+  CompletionList Results;
+  std::unique_ptr<CodeCompleteConsumer> Consumer;
+  if (Opts.EnableSnippets) {
+    Consumer =
+        llvm::make_unique<SnippetCompletionItemsCollector>(Opts, Results);
+  } else {
+    Consumer =
+        llvm::make_unique<PlainTextCompletionItemsCollector>(Opts, Results);
+  }
+  invokeCodeComplete(std::move(Consumer), Opts.getClangCompleteOpts(), FileName,
+                     Command, Preamble, Contents, Pos, std::move(VFS),
+                     std::move(PCHs), Logger);
+  return Results;
+}
+
+SignatureHelp
+signatureHelp(PathRef FileName, const tooling::CompileCommand &Command,
+              PrecompiledPreamble const *Preamble, StringRef Contents,
+              Position Pos, IntrusiveRefCntPtr<vfs::FileSystem> VFS,
+              std::shared_ptr<PCHContainerOperations> PCHs, Logger &Logger) {
+  SignatureHelp Result;
+  clang::CodeCompleteOptions Options;
+  Options.IncludeGlobals = false;
+  Options.IncludeMacros = false;
+  Options.IncludeCodePatterns = false;
+  Options.IncludeBriefComments = true;
+  invokeCodeComplete(llvm::make_unique<SignatureHelpCollector>(Options, Result),
+                     Options, FileName, Command, Preamble, Contents, Pos,
+                     std::move(VFS), std::move(PCHs), Logger);
+  return Result;
+}
+
+} // namespace clangd
+} // namespace clang

Added: clang-tools-extra/trunk/clangd/CodeComplete.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/CodeComplete.h?rev=319655&view=auto
==============================================================================
--- clang-tools-extra/trunk/clangd/CodeComplete.h (added)
+++ clang-tools-extra/trunk/clangd/CodeComplete.h Mon Dec  4 05:49:59 2017
@@ -0,0 +1,82 @@
+//===--- CodeComplete.h -----------------------------------------*- C++-*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+//
+// Code completion provides suggestions for what the user might type next.
+// After "std::string S; S." we might suggest members of std::string.
+// Signature help describes the parameters of a function as you type them.
+//
+//===---------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_CODECOMPLETE_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_CODECOMPLETE_H
+
+#include "Logger.h"
+#include "Path.h"
+#include "Protocol.h"
+#include "clang/Frontend/PrecompiledPreamble.h"
+#include "clang/Sema/CodeCompleteOptions.h"
+#include "clang/Tooling/CompilationDatabase.h"
+
+namespace clang {
+class PCHContainerOperations;
+namespace clangd {
+
+struct CodeCompleteOptions {
+  /// Returns options that can be passed to clang's completion engine.
+  clang::CodeCompleteOptions getClangCompleteOpts() const;
+
+  /// When true, completion items will contain expandable code snippets in
+  /// completion (e.g.  `return ${1:expression}` or `foo(${1:int a}, ${2:int
+  /// b})).
+  bool EnableSnippets = false;
+
+  /// Add code patterns to completion results.
+  /// If EnableSnippets is false, this options is ignored and code patterns will
+  /// always be omitted.
+  bool IncludeCodePatterns = true;
+
+  /// Add macros to code completion results.
+  bool IncludeMacros = true;
+
+  /// Add globals to code completion results.
+  bool IncludeGlobals = true;
+
+  /// Add brief comments to completion items, if available.
+  /// FIXME(ibiryukov): it looks like turning this option on significantly slows
+  /// down completion, investigate if it can be made faster.
+  bool IncludeBriefComments = true;
+
+  /// Include results that are not legal completions in the current context.
+  /// For example, private members are usually inaccessible.
+  bool IncludeIneligibleResults = false;
+
+  /// Limit the number of results returned (0 means no limit).
+  /// If more results are available, we set CompletionList.isIncomplete.
+  size_t Limit = 0;
+};
+
+/// Get code completions at a specified \p Pos in \p FileName.
+CompletionList codeComplete(PathRef FileName,
+                            const tooling::CompileCommand &Command,
+                            PrecompiledPreamble const *Preamble,
+                            StringRef Contents, Position Pos,
+                            IntrusiveRefCntPtr<vfs::FileSystem> VFS,
+                            std::shared_ptr<PCHContainerOperations> PCHs,
+                            CodeCompleteOptions Opts, Logger &Logger);
+
+/// Get signature help at a specified \p Pos in \p FileName.
+SignatureHelp
+signatureHelp(PathRef FileName, const tooling::CompileCommand &Command,
+              PrecompiledPreamble const *Preamble, StringRef Contents,
+              Position Pos, IntrusiveRefCntPtr<vfs::FileSystem> VFS,
+              std::shared_ptr<PCHContainerOperations> PCHs, Logger &Logger);
+
+} // namespace clangd
+} // namespace clang
+
+#endif

Added: clang-tools-extra/trunk/clangd/Compiler.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/Compiler.cpp?rev=319655&view=auto
==============================================================================
--- clang-tools-extra/trunk/clangd/Compiler.cpp (added)
+++ clang-tools-extra/trunk/clangd/Compiler.cpp Mon Dec  4 05:49:59 2017
@@ -0,0 +1,65 @@
+//===--- Compiler.cpp -------------------------------------------*- C++-*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+#include "Compiler.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Lex/PreprocessorOptions.h"
+
+namespace clang {
+namespace clangd {
+
+/// Creates a CompilerInstance from \p CI, with main buffer overriden to \p
+/// Buffer and arguments to read the PCH from \p Preamble, if \p Preamble is not
+/// null. Note that vfs::FileSystem inside returned instance may differ from \p
+/// VFS if additional file remapping were set in command-line arguments.
+/// On some errors, returns null. When non-null value is returned, it's expected
+/// to be consumed by the FrontendAction as it will have a pointer to the \p
+/// Buffer that will only be deleted if BeginSourceFile is called.
+std::unique_ptr<CompilerInstance>
+prepareCompilerInstance(std::unique_ptr<clang::CompilerInvocation> CI,
+                        const PrecompiledPreamble *Preamble,
+                        std::unique_ptr<llvm::MemoryBuffer> Buffer,
+                        std::shared_ptr<PCHContainerOperations> PCHs,
+                        IntrusiveRefCntPtr<vfs::FileSystem> VFS,
+                        DiagnosticConsumer &DiagsClient) {
+  assert(VFS && "VFS is null");
+  assert(!CI->getPreprocessorOpts().RetainRemappedFileBuffers &&
+         "Setting RetainRemappedFileBuffers to true will cause a memory leak "
+         "of ContentsBuffer");
+
+  // NOTE: we use Buffer.get() when adding remapped files, so we have to make
+  // sure it will be released if no error is emitted.
+  if (Preamble) {
+    Preamble->AddImplicitPreamble(*CI, VFS, Buffer.get());
+  } else {
+    CI->getPreprocessorOpts().addRemappedFile(
+        CI->getFrontendOpts().Inputs[0].getFile(), Buffer.get());
+  }
+
+  auto Clang = llvm::make_unique<CompilerInstance>(PCHs);
+  Clang->setInvocation(std::move(CI));
+  Clang->createDiagnostics(&DiagsClient, false);
+
+  if (auto VFSWithRemapping = createVFSFromCompilerInvocation(
+          Clang->getInvocation(), Clang->getDiagnostics(), VFS))
+    VFS = VFSWithRemapping;
+  Clang->setVirtualFileSystem(VFS);
+
+  Clang->setTarget(TargetInfo::CreateTargetInfo(
+      Clang->getDiagnostics(), Clang->getInvocation().TargetOpts));
+  if (!Clang->hasTarget())
+    return nullptr;
+
+  // RemappedFileBuffers will handle the lifetime of the Buffer pointer,
+  // release it.
+  Buffer.release();
+  return Clang;
+}
+
+} // namespace clangd
+} // namespace clang

Added: clang-tools-extra/trunk/clangd/Compiler.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/Compiler.h?rev=319655&view=auto
==============================================================================
--- clang-tools-extra/trunk/clangd/Compiler.h (added)
+++ clang-tools-extra/trunk/clangd/Compiler.h Mon Dec  4 05:49:59 2017
@@ -0,0 +1,46 @@
+//===--- Compiler.h ---------------------------------------------*- C++-*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+//
+// Shared utilities for invoking the clang compiler.
+// ClangdUnit takes care of much of this, but some features like CodeComplete
+// run their own compile actions that share logic.
+//
+//===---------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_COMPILER_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_COMPILER_H
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/CompilerInvocation.h"
+#include "clang/Frontend/PrecompiledPreamble.h"
+
+namespace clang {
+namespace clangd {
+
+class IgnoreDiagnostics : public DiagnosticConsumer {
+public:
+  void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
+                        const clang::Diagnostic &Info) override {}
+};
+
+/// Creates a CompilerInstance with the main file contens overridden.
+/// The preamble will be reused unless it is null.
+/// Note that the vfs::FileSystem inside returned instance may differ if
+/// additional file remappings occur in command-line arguments.
+/// On some errors, returns null. When non-null value is returned, it's expected
+/// to be consumed by the FrontendAction as it will have a pointer to the
+/// MainFile buffer that will only be deleted if BeginSourceFile is called.
+std::unique_ptr<CompilerInstance> prepareCompilerInstance(
+    std::unique_ptr<clang::CompilerInvocation>, const PrecompiledPreamble *,
+    std::unique_ptr<llvm::MemoryBuffer> MainFile,
+    std::shared_ptr<PCHContainerOperations>,
+    IntrusiveRefCntPtr<vfs::FileSystem>, DiagnosticConsumer &);
+
+} // namespace clangd
+} // namespace clang
+
+#endif




More information about the cfe-commits mailing list