[clangd] collect symbol #include & insert #include in global code completion.

Summary:
o Collect suitable #include paths for index symbols. This also does smart mapping
for STL symbols and IWYU pragma (code borrowed from include-fixer).
o For global code completion, add a command for inserting new #include in each code
completion item.

Reviewers: sammccall

Reviewed By: sammccall

Subscribers: klimek, mgorny, ilya-biryukov, jkorous-apple, hintonda, cfe-commits

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

llvm-svn: 325343
diff --git a/clang-tools-extra/clangd/index/SymbolCollector.cpp b/clang-tools-extra/clangd/index/SymbolCollector.cpp
index 0e2186d..2a32565 100644
--- a/clang-tools-extra/clangd/index/SymbolCollector.cpp
+++ b/clang-tools-extra/clangd/index/SymbolCollector.cpp
@@ -11,6 +11,7 @@
 #include "../CodeCompletionStrings.h"
 #include "../Logger.h"
 #include "../URI.h"
+#include "CanonicalIncludes.h"
 #include "clang/AST/DeclCXX.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
 #include "clang/Basic/SourceManager.h"
@@ -127,6 +128,51 @@
   return false;
 }
 
+// We only collect #include paths for symbols that are suitable for global code
+// completion, except for namespaces since #include path for a namespace is hard
+// to define.
+bool shouldCollectIncludePath(index::SymbolKind Kind) {
+  using SK = index::SymbolKind;
+  switch (Kind) {
+  case SK::Macro:
+  case SK::Enum:
+  case SK::Struct:
+  case SK::Class:
+  case SK::Union:
+  case SK::TypeAlias:
+  case SK::Using:
+  case SK::Function:
+  case SK::Variable:
+  case SK::EnumConstant:
+    return true;
+  default:
+    return false;
+  }
+}
+
+/// Gets a canonical include (<header>  or "header") for header of \p Loc.
+/// Returns None if the header has no canonical include.
+/// FIXME: we should handle .inc files whose symbols are expected be exported by
+/// their containing headers.
+llvm::Optional<std::string>
+getIncludeHeader(const SourceManager &SM, SourceLocation Loc,
+                 const SymbolCollector::Options &Opts) {
+  llvm::StringRef FilePath = SM.getFilename(Loc);
+  if (FilePath.empty())
+    return llvm::None;
+  if (Opts.Includes) {
+    llvm::StringRef Mapped = Opts.Includes->mapHeader(FilePath);
+    if (Mapped != FilePath)
+      return (Mapped.startswith("<") || Mapped.startswith("\""))
+                 ? Mapped.str()
+                 : ("\"" + Mapped + "\"").str();
+  }
+  // If the header path is the same as the file path of the declaration, we skip
+  // storing the #include path; users can use the URI in declaration location to
+  // calculate the #include path.
+  return llvm::None;
+}
+
 // Return the symbol location of the given declaration `D`.
 //
 // For symbols defined inside macros:
@@ -252,6 +298,14 @@
   std::string Documentation = getDocumentation(*CCS);
   std::string CompletionDetail = getDetail(*CCS);
 
+  std::string Include;
+  if (Opts.CollectIncludePath && shouldCollectIncludePath(S.SymInfo.Kind)) {
+    // Use the expansion location to get the #include header since this is
+    // where the symbol is exposed.
+    if (auto Header =
+            getIncludeHeader(SM, SM.getExpansionLoc(ND.getLocation()), Opts))
+      Include = std::move(*Header);
+  }
   S.CompletionFilterText = FilterText;
   S.CompletionLabel = Label;
   S.CompletionPlainInsertText = PlainInsertText;
@@ -259,6 +313,7 @@
   Symbol::Details Detail;
   Detail.Documentation = Documentation;
   Detail.CompletionDetail = CompletionDetail;
+  Detail.IncludeHeader = Include;
   S.Detail = &Detail;
 
   Symbols.insert(S);