kuhnel created this revision.
Herald added subscribers: usaxena95, kadircet, arphaman.
kuhnel requested review of this revision.
Herald added subscribers: cfe-commits, MaskRay, ilya-biryukov.
Herald added a project: clang.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D94293

Files:
  clang-tools-extra/clangd/ClangdServer.cpp
  clang-tools-extra/clangd/ClangdServer.h
  clang-tools-extra/clangd/index/Background.cpp
  clang-tools-extra/clangd/index/Background.h
  clang-tools-extra/clangd/tool/ClangdMain.cpp

Index: clang-tools-extra/clangd/tool/ClangdMain.cpp
===================================================================
--- clang-tools-extra/clangd/tool/ClangdMain.cpp
+++ clang-tools-extra/clangd/tool/ClangdMain.cpp
@@ -524,6 +524,15 @@
 std::function<void()> getMemoryCleanupFunction() { return nullptr; }
 #endif
 
+opt<bool> IndexSTL{
+    "index-stl",
+    cat(Features),
+    desc("Background index should always include the STL headers even if \n"
+         "not used at the moment. This will enable code completion and \n"
+         "include fixer."),
+    init(true),
+};
+
 #if CLANGD_ENABLE_REMOTE
 opt<std::string> RemoteIndexAddress{
     "remote-index-address",
@@ -897,6 +906,7 @@
 
   // Shall we allow to customize the file limit?
   Opts.Rename.AllowCrossFile = CrossFileRename;
+  Opts.IndexSTL = IndexSTL;
 
   if (CheckFile.getNumOccurrences()) {
     llvm::SmallString<256> Path;
Index: clang-tools-extra/clangd/index/Background.h
===================================================================
--- clang-tools-extra/clangd/index/Background.h
+++ clang-tools-extra/clangd/index/Background.h
@@ -141,6 +141,7 @@
     std::function<Context(PathRef)> ContextProvider = nullptr;
     // Whether to collect references to main-file-only symbols.
     bool CollectMainFileRefs = false;
+    bool IndexSTL = false;
   };
 
   /// Creates a new background index and starts its threads.
@@ -155,6 +156,8 @@
   // available sometime later.
   void enqueue(const std::vector<std::string> &ChangedFiles) {
     Queue.push(changedFilesTask(ChangedFiles));
+    // TODO(kuhnel): Only index if enqueueing C++ file.
+    indexSTLHeaders(ChangedFiles);
   }
 
   /// Boosts priority of indexing related to Path.
@@ -176,6 +179,8 @@
 
   void profile(MemoryTree &MT) const;
 
+  void indexSTLHeaders(const std::vector<std::string> &ChangedFiles);
+
 private:
   /// Represents the state of a single file when indexing was performed.
   struct ShardVersion {
@@ -220,6 +225,8 @@
   BackgroundQueue Queue;
   AsyncTaskRunner ThreadPool;
   GlobalCompilationDatabase::CommandChanged::Subscription CommandsChanged;
+  // Whether the STL header files need to be indexed
+  bool NeedToIndexSTLHeaders = true;
 };
 
 } // namespace clangd
Index: clang-tools-extra/clangd/index/Background.cpp
===================================================================
--- clang-tools-extra/clangd/index/Background.cpp
+++ clang-tools-extra/clangd/index/Background.cpp
@@ -49,6 +49,7 @@
 #include <chrono>
 #include <condition_variable>
 #include <cstddef>
+#include <fstream>
 #include <memory>
 #include <mutex>
 #include <numeric>
@@ -103,7 +104,8 @@
       CommandsChanged(
           CDB.watch([&](const std::vector<std::string> &ChangedFiles) {
             enqueue(ChangedFiles);
-          })) {
+          })),
+      NeedToIndexSTLHeaders(Opts.IndexSTL) {
   assert(Opts.ThreadPoolSize > 0 && "Thread pool size can't be zero.");
   assert(this->IndexStorageFactory && "Storage factory can not be null!");
   for (unsigned I = 0; I < Opts.ThreadPoolSize; ++I) {
@@ -420,5 +422,56 @@
   // We don't want to mix memory used by index and symbols, so call base class.
   MT.child("index").addUsage(SwapIndex::estimateMemoryUsage());
 }
+
+void BackgroundIndex::indexSTLHeaders(
+    const std::vector<std::string> &ChangedFiles) {
+  // Only index if we need to.
+  if (!NeedToIndexSTLHeaders)
+    return;
+
+  vlog("Trying to find place for STL header include.");
+  std::string SourceRoot;
+  for (auto ChangedFile : ChangedFiles) {
+    if (CDB.getProjectInfo(ChangedFile)) {
+      SourceRoot = CDB.getProjectInfo(ChangedFile)->SourceRoot;
+      break;
+    }
+  }
+  // fallback if we can't find a Compilations Database
+  if (SourceRoot.empty()) {
+    if (ChangedFiles.empty()) {
+      vlog("Could not find place for STL header include.");
+      return;
+    }
+    SourceRoot = llvm::sys::path::parent_path(ChangedFiles[0]).str();
+  }
+  // TODO(kuhnel): is the a better place to store this file?
+  // TODO(kuhnel): do we need a file at all, can we just pass a string to the
+  //               indexer?
+  const Path STLHeaderPath = SourceRoot + "/.stl_header.h";
+  vlog("Indexing STL headers from {0}", STLHeaderPath);
+  std::ofstream STLIndexFile;
+  std::set<std::string> Headers;
+
+// gather all the known STL headers, without duplicates
+#define SYMBOL(Name, NameSpace, Header) Headers.insert(#Header);
+#include "StdSymbolMap.inc"
+#undef SYMBOL
+
+  // TODO(kuhnel): figure out if there are other ways to write to files in llvm.
+  STLIndexFile.open(STLHeaderPath);
+  STLIndexFile << "/* This is a temporary file created by clangd. It is "
+                  "used by the background index to automatically index the "
+                  "standard template library. */"
+               << std::endl
+               << std::endl;
+  for (auto Header : Headers) {
+    STLIndexFile << "#include " << Header << std::endl;
+  }
+  STLIndexFile.close();
+  Queue.push(changedFilesTask({STLHeaderPath}));
+  NeedToIndexSTLHeaders = false;
+};
+
 } // namespace clangd
 } // namespace clang
Index: clang-tools-extra/clangd/ClangdServer.h
===================================================================
--- clang-tools-extra/clangd/ClangdServer.h
+++ clang-tools-extra/clangd/ClangdServer.h
@@ -156,6 +156,10 @@
     /// Enable preview of FoldingRanges feature.
     bool FoldingRanges = false;
 
+    // Automatically parse the STL to enable code completion and include
+    // insertion
+    bool IndexSTL = false;
+
     explicit operator TUScheduler::Options() const;
   };
   // Sensible default options for use in tests.
Index: clang-tools-extra/clangd/ClangdServer.cpp
===================================================================
--- clang-tools-extra/clangd/ClangdServer.cpp
+++ clang-tools-extra/clangd/ClangdServer.cpp
@@ -30,6 +30,7 @@
 #include "support/Logger.h"
 #include "support/Markup.h"
 #include "support/MemoryTree.h"
+#include "support/Path.h"
 #include "support/ThreadsafeFS.h"
 #include "support/Trace.h"
 #include "clang/Format/Format.h"
@@ -53,9 +54,7 @@
 #include <algorithm>
 #include <chrono>
 #include <future>
-#include <memory>
 #include <mutex>
-#include <string>
 #include <type_traits>
 
 namespace clang {
@@ -179,6 +178,7 @@
   if (Opts.BackgroundIndex) {
     BackgroundIndex::Options BGOpts;
     BGOpts.ThreadPoolSize = std::max(Opts.AsyncThreadsCount, 1u);
+    BGOpts.IndexSTL = Opts.IndexSTL;
     BGOpts.OnProgress = [Callbacks](BackgroundQueue::Stats S) {
       if (Callbacks)
         Callbacks->onBackgroundIndexProgress(S);
@@ -219,6 +219,8 @@
   // If we loaded Foo.h, we want to make sure Foo.cpp is indexed.
   if (NewFile && BackgroundIdx)
     BackgroundIdx->boostRelated(File);
+  if (BackgroundIdx)
+    BackgroundIdx->indexSTLHeaders({File.str()});
 }
 
 void ClangdServer::removeDocument(PathRef File) { WorkScheduler.remove(File); }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to